EffectUtils.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. package me.km.effects;
  2. import java.util.Collection;
  3. import java.util.HashMap;
  4. import java.util.stream.Collectors;
  5. import me.km.KajetansMod;
  6. import me.km.api.Module;
  7. import me.km.api.Utils;
  8. import me.km.entities.EntityItemProjectile;
  9. import me.km.jobsystem.JobAPI;
  10. import me.km.plots.ProtectionBank;
  11. import net.minecraft.entity.Entity;
  12. import net.minecraft.entity.EntityAreaEffectCloud;
  13. import net.minecraft.entity.EntityLivingBase;
  14. import net.minecraft.entity.item.EntityEnderPearl;
  15. import net.minecraft.entity.item.EntityExpBottle;
  16. import net.minecraft.entity.passive.EntityAnimal;
  17. import net.minecraft.entity.player.EntityPlayer;
  18. import net.minecraft.entity.player.EntityPlayerMP;
  19. import net.minecraft.entity.projectile.*;
  20. import net.minecraft.init.Items;
  21. import net.minecraft.init.SoundEvents;
  22. import net.minecraft.item.ItemStack;
  23. import net.minecraft.network.play.server.SPacketParticles;
  24. import net.minecraft.network.play.server.SPacketSoundEffect;
  25. import net.minecraft.potion.Potion;
  26. import net.minecraft.potion.PotionEffect;
  27. import net.minecraft.potion.PotionType;
  28. import net.minecraft.potion.PotionUtils;
  29. import net.minecraft.util.EnumParticleTypes;
  30. import net.minecraft.util.SoundCategory;
  31. import net.minecraft.util.SoundEvent;
  32. import net.minecraft.util.math.BlockPos;
  33. import net.minecraft.util.math.Vec3d;
  34. import net.minecraft.util.text.TextFormatting;
  35. import net.minecraft.world.World;
  36. import net.minecraft.world.WorldServer;
  37. public class EffectUtils extends Module
  38. {
  39. private final HashMap<Integer, EntityData> entityData;
  40. public EffectUtils(String mname, String prefix, TextFormatting color)
  41. {
  42. super(mname, prefix, color);
  43. entityData = new HashMap<>();
  44. }
  45. // -----------------------------------------------------------------------------------
  46. // Entity-Data
  47. // -----------------------------------------------------------------------------------
  48. private class EntityData
  49. {
  50. private final String s;
  51. private final Object data;
  52. public EntityData(String s, Object data)
  53. {
  54. this.s = s;
  55. this.data = data;
  56. }
  57. }
  58. public void addEntityData(Entity ent, String key, Object data)
  59. {
  60. entityData.put(ent.getEntityId(), new EntityData(key, data));
  61. removeInvalidData(ent);
  62. }
  63. public void addEntityData(Entity ent, String key)
  64. {
  65. addEntityData(ent, key, true);
  66. }
  67. private void removeInvalidData(Entity ent)
  68. {
  69. if(ent.isDead)
  70. {
  71. entityData.remove(ent.getEntityId());
  72. return;
  73. }
  74. KajetansMod.scheduler.scheduleTask(() -> removeInvalidData(ent), 100);
  75. }
  76. public Object getEntityData(Entity ent, String key)
  77. {
  78. EntityData data = entityData.get(ent.getEntityId());
  79. if(data == null)
  80. {
  81. return null;
  82. }
  83. if(data.s.equals(key))
  84. {
  85. return data.data;
  86. }
  87. return null;
  88. }
  89. // -----------------------------------------------------------------------------------
  90. // Entity-Level
  91. // -----------------------------------------------------------------------------------
  92. /** Returns the level of a players effect
  93. *
  94. * @param p a player
  95. * @param eff an effect
  96. * @return the level of the effect, 0 on non existance for the player
  97. */
  98. public static int getEffectLevel(EntityPlayer p, Effect eff)
  99. {
  100. JobAPI job = KajetansMod.jobs;
  101. return eff.getSkills().stream().mapToInt(s -> job.getSkillLevel(p, s)).max().orElse(0);
  102. }
  103. @SuppressWarnings(value = "unchecked")
  104. public static Class<? extends ActiveEffectBase> getEffectClass(String s)
  105. {
  106. Class<? extends ActiveEffectBase> c;
  107. try
  108. {
  109. c = (Class<? extends ActiveEffectBase>) Class.forName("me.km.effects.active." + s);
  110. }
  111. catch(ClassNotFoundException | ClassCastException ex)
  112. {
  113. return null;
  114. }
  115. return c;
  116. }
  117. // -----------------------------------------------------------------------------------
  118. // Entity-Collections
  119. // -----------------------------------------------------------------------------------
  120. public static Collection<EntityPlayer> getPlayersOfGuild(EntityPlayer p, World w, Vec3d v, double radius)
  121. {
  122. Collection<EntityPlayer> col = Utils.getNearbyPlayers(w, v, radius);
  123. if(col.isEmpty())
  124. {
  125. return col;
  126. }
  127. int id = KajetansMod.playerbank.getGuildId(p);
  128. col.removeIf(pl -> KajetansMod.playerbank.getGuildId(pl) != id);
  129. return col;
  130. }
  131. public static Collection<EntityPlayer> getPlayersOfGuild(EntityPlayer p, double radius)
  132. {
  133. return getPlayersOfGuild(p, p.world, p.getPositionVector(), radius);
  134. }
  135. public static Collection<EntityLivingBase> getEntsOfNotGuild(EntityPlayer p, World w, Vec3d v, double radius)
  136. {
  137. boolean animals = KajetansMod.plots.getDataBank(ProtectionBank.class).canBuild(w, new BlockPos(v), p);
  138. boolean pvp = !KajetansMod.worldManager.getWorldPreferences(w).pvpProtection;
  139. boolean ppvp = KajetansMod.playerbank.getDataBank().getTag(p, "pvp") >= 1;
  140. int id = KajetansMod.playerbank.getGuildId(p);
  141. return Utils.getNearbyEntities(w, v, radius, EntityLivingBase.class).stream()
  142. .filter(ent -> animals || !(ent instanceof EntityAnimal))
  143. .filter(ent -> pvp || !(ent instanceof EntityPlayer) || (ppvp &&
  144. KajetansMod.playerbank.getDataBank().getTag((EntityPlayer) ent, "pvp") >= 1))
  145. .filter(ent -> !(ent instanceof EntityPlayer) ||
  146. (id != KajetansMod.playerbank.getGuildId((EntityPlayer) ent)))
  147. .filter(ent -> !(ent.equals(p)))
  148. .collect(Collectors.toList());
  149. }
  150. public static Collection<EntityLivingBase> getEntsOfNotGuild(EntityPlayer p, double radius)
  151. {
  152. return getEntsOfNotGuild(p, p.world, p.getPositionVector(), radius);
  153. }
  154. // -----------------------------------------------------------------------------------
  155. // Target Selector
  156. // -----------------------------------------------------------------------------------
  157. public static BlockPos getPlayerTarget(EntityPlayer p, int range)
  158. {
  159. return Utils.getPlayerTarget(p, range + 7).up();
  160. }
  161. // -----------------------------------------------------------------------------------
  162. // Particles
  163. // -----------------------------------------------------------------------------------
  164. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, float offX, float offY, float offZ, float speed, int count, int... data)
  165. {
  166. SPacketParticles packet = new SPacketParticles(particle, false, x, y, z, offX, offY, offZ, speed, count, data);
  167. Utils.getNearbyPlayers(w, x, y, z, 512).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet));
  168. }
  169. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, float offX, float offY, float offZ, int count)
  170. {
  171. spawnParticle(w, particle, x, y, z, offX, offY, offZ, 1, count, new int[0]);
  172. }
  173. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, int count)
  174. {
  175. spawnParticle(w, particle, x, y, z, 0, 0, 0, count);
  176. }
  177. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, Vec3d v, int count)
  178. {
  179. spawnParticle(w, particle, (float) v.x, (float) v.y, (float) v.z, 0, 0, 0, count);
  180. }
  181. public static void playSpell(EntityPlayerMP p, int level)
  182. {
  183. spawnParticle(p.getServerWorld(), EnumParticleTypes.SPELL, (float) p.posX, (float) p.posY + 1, (float) p.posZ, 0.5f, 0.5f, 0.5f, 1, 10 + level, new int[0]);
  184. }
  185. public static <T> void playEffectCircleWithData(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter, int... data)
  186. {
  187. double x = v.x;
  188. float y = (float) v.y;
  189. double z = v.z;
  190. double angle = 2 * Math.PI / counter;
  191. for(int i = 0; i < counter; i++)
  192. {
  193. spawnParticle(w, particle, (float) (x + Math.cos(i * angle) * radius), y, (float) (z + Math.sin(i * angle) * radius), 0, 0, 0, 1, 1, data);
  194. }
  195. }
  196. public static <T> void playEffectCircle(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter)
  197. {
  198. playEffectCircleWithData(w, v, particle, radius, counter, new int[0]);
  199. }
  200. // -----------------------------------------------------------------------------------
  201. // Sounds
  202. // -----------------------------------------------------------------------------------
  203. public static void playSound(WorldServer w, SoundEvent se, SoundCategory sc, double x, double y, double z)
  204. {
  205. SPacketSoundEffect packet = new SPacketSoundEffect(se, sc, x, y, z, 1, 1);
  206. Utils.getNearbyPlayers(w, x, y, z, 128).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet));
  207. }
  208. public static void playSound(EntityPlayerMP p, SoundEvent se, SoundCategory sc)
  209. {
  210. playSound(p.getServerWorld(), se, sc, p.posX, p.posY, p.posZ);
  211. }
  212. public static void playSound(EntityPlayerMP p, SoundEvent se)
  213. {
  214. playSound(p.getServerWorld(), se, SoundCategory.PLAYERS, p.posX, p.posY, p.posZ);
  215. }
  216. // -----------------------------------------------------------------------------------
  217. // Potions
  218. // -----------------------------------------------------------------------------------
  219. public static void addPotionTo(EntityLivingBase ent, Potion potion, int duration, int amplifier)
  220. {
  221. if(ent.isPotionActive(potion))
  222. {
  223. ent.removePotionEffect(potion);
  224. }
  225. ent.addPotionEffect(new PotionEffect(potion, duration, amplifier));
  226. }
  227. public static void spawnPotionCloud(Vec3d v, EntityPlayerMP p, Potion potion, int pduration, int amplifier, int duration, float radius)
  228. {
  229. EntityAreaEffectCloud cloud = new EntityAreaEffectCloud(p.getServerWorld(), v.x, v.y, v.z);
  230. cloud.setDuration(duration);
  231. cloud.setRadius(radius);
  232. cloud.setOwner(p);
  233. cloud.setWaitTime(5);
  234. cloud.setPotion(new PotionType(new PotionEffect(potion, pduration, amplifier)));
  235. p.getServerWorld().spawnEntity(cloud);
  236. }
  237. public static void spawnPotionCloud(EntityPlayerMP p, Potion potion, int level)
  238. {
  239. BlockPos pos = getPlayerTarget(p, level);
  240. spawnPotionCloud(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), p, potion, 20 * level, (level / 4), 40 * level, 0.5f + level / 4f);
  241. playSpell(p, level);
  242. playSound(p, SoundEvents.ENTITY_FIREWORK_BLAST, SoundCategory.PLAYERS);
  243. }
  244. // -----------------------------------------------------------------------------------
  245. // Projectiles
  246. // -----------------------------------------------------------------------------------
  247. public static <T> T launchProjectile(EntityPlayer p, Class<? extends T> projectile, double scale, Object data)
  248. {
  249. World w = p.world;
  250. Entity launch = null;
  251. if(EntityItemProjectile.class == projectile)
  252. {
  253. if(data == null)
  254. {
  255. throw new NullPointerException("Data musn't be null for EntityItemProjectile");
  256. }
  257. ItemStack stack = (ItemStack) data;
  258. if(stack.isEmpty())
  259. {
  260. throw new IllegalArgumentException("Empty ItemStack not allowed here");
  261. }
  262. launch = new EntityItemProjectile(p, stack.copy());
  263. ((EntityItemProjectile) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  264. }
  265. else if(EntitySnowball.class == projectile)
  266. {
  267. launch = new EntitySnowball(w, p);
  268. ((EntitySnowball) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  269. }
  270. else if(EntityEgg.class == projectile)
  271. {
  272. launch = new EntityEgg(w, p);
  273. ((EntityEgg) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  274. }
  275. else if(EntityEnderPearl.class == projectile)
  276. {
  277. launch = new EntityEnderPearl(w, p);
  278. ((EntityEnderPearl) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  279. }
  280. else if(EntityPotion.class == projectile)
  281. {
  282. launch = new EntityPotion(w, p, (ItemStack) data);
  283. ((EntityPotion) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.5f, 1.0f);
  284. }
  285. else if(EntityExpBottle.class == projectile)
  286. {
  287. launch = new EntityExpBottle(w, p);
  288. ((EntityExpBottle) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.7f, 1.0f);
  289. }
  290. else if(EntityArrow.class.isAssignableFrom(projectile))
  291. {
  292. if(EntityTippedArrow.class == projectile)
  293. {
  294. launch = new EntityTippedArrow(w, p);
  295. ((EntityTippedArrow) launch).setPotionEffect((ItemStack) data);
  296. }
  297. else if(EntitySpectralArrow.class == projectile)
  298. {
  299. launch = new EntitySpectralArrow(w, p);
  300. }
  301. else
  302. {
  303. launch = new EntityTippedArrow(w, p);
  304. }
  305. ((EntityArrow) launch).setAim(p, p.rotationPitch, p.rotationYaw, 0.0F, 3.0F, 1.0F);
  306. }
  307. else if(EntityFireball.class.isAssignableFrom(projectile))
  308. {
  309. Vec3d v = p.getLookVec().scale(10);
  310. if (EntitySmallFireball.class == projectile)
  311. {
  312. launch = new EntitySmallFireball(w, p, v.x, v.y, v.z);
  313. }
  314. else if (EntityWitherSkull.class == projectile)
  315. {
  316. launch = new EntityWitherSkull(w, p, v.x, v.y, v.z);
  317. }
  318. else if (EntityDragonFireball.class == projectile)
  319. {
  320. launch = new EntityDragonFireball(w, p, v.x, v.y, v.z);
  321. }
  322. else
  323. {
  324. launch = new EntityLargeFireball(w, p, v.x, v.y, v.z);
  325. }
  326. }
  327. Utils.scaleVelocity(launch, scale);
  328. w.spawnEntity(launch);
  329. return (T) launch;
  330. }
  331. public static EntityTippedArrow launchTippedArrow(EntityPlayer p, double scale, Potion potion, int duration, int amplifier)
  332. {
  333. ItemStack stack = new ItemStack(Items.TIPPED_ARROW);
  334. PotionUtils.addPotionToItemStack(stack, new PotionType(new PotionEffect(potion, duration, amplifier)));
  335. EntityTippedArrow arrow = launchProjectile(p, EntityTippedArrow.class, scale, stack);
  336. return arrow;
  337. }
  338. public static void jumpTo(EntityLivingBase ent, EntityLivingBase ent2)
  339. {
  340. Vec3d v1 = ent2.getPositionVector();
  341. Vec3d v2 = ent.getPositionVector();
  342. Utils.setVelocity(ent, (v1.x - v2.x) * 0.2, (v1.y - v2.y) * 0.2 + 0.9, (v1.z - v2.z) * 0.2);
  343. KajetansMod.scheduler.scheduleTask(() ->
  344. {
  345. Vec3d v3 = ent2.getPositionVector();
  346. Vec3d v4 = ent.getPositionVector();
  347. Utils.setVelocity(ent, (v3.x - v4.x) * 0.2, (v3.y - v4.y) * 0.2, (v3.z - v4.z) * 0.2);
  348. }, 12);
  349. }
  350. }