EffectUtils.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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 hasEntityData(Entity ent, String key)
  77. {
  78. EntityData data = entityData.get(ent.getEntityId());
  79. if(data == null)
  80. {
  81. return null;
  82. }
  83. return data.data;
  84. }
  85. // -----------------------------------------------------------------------------------
  86. // Entity-Level
  87. // -----------------------------------------------------------------------------------
  88. /** Returns the level of a players effect
  89. *
  90. * @param p a player
  91. * @param eff an effect
  92. * @return the level of the effect, 0 on non existance for the player
  93. */
  94. public static int getEffectLevel(EntityPlayer p, Effect eff)
  95. {
  96. JobAPI job = KajetansMod.jobs;
  97. return eff.getSkills().stream().mapToInt(s -> job.getSkillLevel(p, s)).max().orElse(0);
  98. }
  99. @SuppressWarnings(value = "unchecked")
  100. public static Class<? extends ActiveEffectBase> getEffectClass(String s)
  101. {
  102. Class<? extends ActiveEffectBase> c;
  103. try
  104. {
  105. c = (Class<? extends ActiveEffectBase>) Class.forName("me.km.effects.active." + s);
  106. }
  107. catch(ClassNotFoundException | ClassCastException ex)
  108. {
  109. return null;
  110. }
  111. return c;
  112. }
  113. // -----------------------------------------------------------------------------------
  114. // Entity-Collections
  115. // -----------------------------------------------------------------------------------
  116. public static Collection<EntityPlayer> getPlayersOfGuild(EntityPlayer p, World w, Vec3d v, double radius)
  117. {
  118. Collection<EntityPlayer> col = Utils.getNearbyPlayers(w, v, radius);
  119. if(col.isEmpty())
  120. {
  121. return col;
  122. }
  123. int id = KajetansMod.playerbank.getGuildId(p);
  124. col.removeIf(pl -> KajetansMod.playerbank.getGuildId(pl) != id);
  125. return col;
  126. }
  127. public static Collection<EntityPlayer> getPlayersOfGuild(EntityPlayer p, double radius)
  128. {
  129. return getPlayersOfGuild(p, p.world, p.getPositionVector(), radius);
  130. }
  131. public static Collection<EntityLivingBase> getEntsOfNotGuild(EntityPlayer p, World w, Vec3d v, double radius)
  132. {
  133. boolean animals = KajetansMod.plots.getDataBank(ProtectionBank.class).canBuild(w, new BlockPos(v), p);
  134. boolean pvp = !KajetansMod.worldManager.getWorldPreferences(w).pvpProtection;
  135. boolean ppvp = KajetansMod.playerbank.getDataBank().getTag(p, "pvp") >= 1;
  136. int id = KajetansMod.playerbank.getGuildId(p);
  137. return Utils.getNearbyEntities(w, v, radius, EntityLivingBase.class).stream()
  138. .filter(ent -> animals || !(ent instanceof EntityAnimal))
  139. .filter(ent -> pvp || !(ent instanceof EntityPlayer) || (ppvp &&
  140. KajetansMod.playerbank.getDataBank().getTag((EntityPlayer) ent, "pvp") >= 1))
  141. .filter(ent -> !(ent instanceof EntityPlayer) ||
  142. (id != KajetansMod.playerbank.getGuildId((EntityPlayer) ent)))
  143. .filter(ent -> !(ent.equals(p)))
  144. .collect(Collectors.toList());
  145. }
  146. public static Collection<EntityLivingBase> getEntsOfNotGuild(EntityPlayer p, double radius)
  147. {
  148. return getEntsOfNotGuild(p, p.world, p.getPositionVector(), radius);
  149. }
  150. // -----------------------------------------------------------------------------------
  151. // Target Selector
  152. // -----------------------------------------------------------------------------------
  153. public static BlockPos getPlayerTarget(EntityPlayer p, int range)
  154. {
  155. return Utils.getPlayerTarget(p, range + 7).up();
  156. }
  157. // -----------------------------------------------------------------------------------
  158. // Particles
  159. // -----------------------------------------------------------------------------------
  160. 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)
  161. {
  162. SPacketParticles packet = new SPacketParticles(particle, false, x, y, z, offX, offY, offZ, speed, count, data);
  163. Utils.getNearbyPlayers(w, x, y, z, 512).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet));
  164. }
  165. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, float offX, float offY, float offZ, int count)
  166. {
  167. spawnParticle(w, particle, x, y, z, offX, offY, offZ, 1, count, new int[0]);
  168. }
  169. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, int count)
  170. {
  171. spawnParticle(w, particle, x, y, z, 0, 0, 0, count);
  172. }
  173. public static void spawnParticle(WorldServer w, EnumParticleTypes particle, Vec3d v, int count)
  174. {
  175. spawnParticle(w, particle, (float) v.xCoord, (float) v.yCoord, (float) v.zCoord, 0, 0, 0, count);
  176. }
  177. public static void playSpell(EntityPlayerMP p, int level)
  178. {
  179. 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]);
  180. }
  181. public static <T> void playEffectCircleWithData(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter, int... data)
  182. {
  183. double x = v.xCoord;
  184. float y = (float) v.yCoord;
  185. double z = v.yCoord;
  186. double angle = 2 * Math.PI / counter;
  187. for(int i = 0; i < counter; i++)
  188. {
  189. spawnParticle(w, particle, (float) (x + Math.cos(i * angle) * radius), y, (float) (z + Math.sin(i * angle) * radius), 0, 0, 0, 1, 1, data);
  190. }
  191. }
  192. public static <T> void playEffectCircle(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter)
  193. {
  194. playEffectCircleWithData(w, v, particle, radius, counter, new int[0]);
  195. }
  196. // -----------------------------------------------------------------------------------
  197. // Sounds
  198. // -----------------------------------------------------------------------------------
  199. public static void playSound(WorldServer w, SoundEvent se, SoundCategory sc, double x, double y, double z)
  200. {
  201. SPacketSoundEffect packet = new SPacketSoundEffect(se, sc, x, y, z, 1, 1);
  202. Utils.getNearbyPlayers(w, x, y, z, 128).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet));
  203. }
  204. public static void playSound(EntityPlayerMP p, SoundEvent se, SoundCategory sc)
  205. {
  206. playSound(p.getServerWorld(), se, sc, p.posX, p.posY, p.posZ);
  207. }
  208. public static void playSound(EntityPlayerMP p, SoundEvent se)
  209. {
  210. playSound(p.getServerWorld(), se, SoundCategory.PLAYERS, p.posX, p.posY, p.posZ);
  211. }
  212. // -----------------------------------------------------------------------------------
  213. // Potions
  214. // -----------------------------------------------------------------------------------
  215. public static void addPotionTo(EntityLivingBase ent, Potion potion, int duration, int amplifier)
  216. {
  217. if(ent.isPotionActive(potion))
  218. {
  219. ent.removePotionEffect(potion);
  220. }
  221. ent.addPotionEffect(new PotionEffect(potion, duration, amplifier));
  222. }
  223. public static void spawnPotionCloud(Vec3d v, EntityPlayerMP p, Potion potion, int pduration, int amplifier, int duration, float radius)
  224. {
  225. EntityAreaEffectCloud cloud = new EntityAreaEffectCloud(p.getServerWorld(), v.xCoord, v.yCoord, v.zCoord);
  226. cloud.setDuration(duration);
  227. cloud.setRadius(radius);
  228. cloud.setOwner(p);
  229. cloud.setWaitTime(5);
  230. cloud.setPotion(new PotionType(new PotionEffect(potion, pduration, amplifier)));
  231. p.getServerWorld().spawnEntity(cloud);
  232. }
  233. public static void spawnPotionCloud(EntityPlayerMP p, Potion potion, int level)
  234. {
  235. BlockPos pos = getPlayerTarget(p, level);
  236. spawnPotionCloud(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), p, potion, 20 * level, (level / 4), 40 * level, 0.5f + level / 4f);
  237. playSpell(p, level);
  238. playSound(p, SoundEvents.ENTITY_FIREWORK_BLAST, SoundCategory.PLAYERS);
  239. }
  240. // -----------------------------------------------------------------------------------
  241. // Projectiles
  242. // -----------------------------------------------------------------------------------
  243. public static <T> T launchProjectile(EntityPlayer p, Class<? extends T> projectile, double scale, Object data)
  244. {
  245. World w = p.world;
  246. Entity launch = null;
  247. if(EntityItemProjectile.class == projectile)
  248. {
  249. if(data == null)
  250. {
  251. throw new NullPointerException("Data musn't be null for EntityItemProjectile");
  252. }
  253. ItemStack stack = (ItemStack) data;
  254. if(stack.isEmpty())
  255. {
  256. throw new IllegalArgumentException("Empty ItemStack not allowed here");
  257. }
  258. launch = new EntityItemProjectile(p, stack.copy());
  259. ((EntityItemProjectile) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  260. }
  261. else if(EntitySnowball.class == projectile)
  262. {
  263. launch = new EntitySnowball(w, p);
  264. ((EntitySnowball) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  265. }
  266. else if(EntityEgg.class == projectile)
  267. {
  268. launch = new EntityEgg(w, p);
  269. ((EntityEgg) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  270. }
  271. else if(EntityEnderPearl.class == projectile)
  272. {
  273. launch = new EntityEnderPearl(w, p);
  274. ((EntityEnderPearl) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f);
  275. }
  276. else if(EntityPotion.class == projectile)
  277. {
  278. launch = new EntityPotion(w, p, (ItemStack) data);
  279. ((EntityPotion) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.5f, 1.0f);
  280. }
  281. else if(EntityExpBottle.class == projectile)
  282. {
  283. launch = new EntityExpBottle(w, p);
  284. ((EntityExpBottle) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.7f, 1.0f);
  285. }
  286. else if(EntityArrow.class.isAssignableFrom(projectile))
  287. {
  288. if(EntityTippedArrow.class == projectile)
  289. {
  290. launch = new EntityTippedArrow(w, p);
  291. ((EntityTippedArrow) launch).setPotionEffect((ItemStack) data);
  292. }
  293. else if(EntitySpectralArrow.class == projectile)
  294. {
  295. launch = new EntitySpectralArrow(w, p);
  296. }
  297. else
  298. {
  299. launch = new EntityTippedArrow(w, p);
  300. }
  301. ((EntityArrow) launch).setAim(p, p.rotationPitch, p.rotationYaw, 0.0F, 3.0F, 1.0F);
  302. }
  303. else if(EntityFireball.class.isAssignableFrom(projectile))
  304. {
  305. Vec3d v = p.getLookVec().scale(10);
  306. if (EntitySmallFireball.class == projectile)
  307. {
  308. launch = new EntitySmallFireball(w, p, v.xCoord, v.yCoord, v.zCoord);
  309. }
  310. else if (EntityWitherSkull.class == projectile)
  311. {
  312. launch = new EntityWitherSkull(w, p, v.xCoord, v.yCoord, v.zCoord);
  313. }
  314. else if (EntityDragonFireball.class == projectile)
  315. {
  316. launch = new EntityDragonFireball(w, p, v.xCoord, v.yCoord, v.zCoord);
  317. }
  318. else
  319. {
  320. launch = new EntityLargeFireball(w, p, v.xCoord, v.yCoord, v.zCoord);
  321. }
  322. }
  323. Utils.scaleVelocity(launch, scale);
  324. w.spawnEntity(launch);
  325. return (T) launch;
  326. }
  327. public static EntityTippedArrow launchTippedArrow(EntityPlayer p, double scale, Potion potion, int duration, int amplifier)
  328. {
  329. ItemStack stack = new ItemStack(Items.TIPPED_ARROW);
  330. PotionUtils.addPotionToItemStack(stack, new PotionType(new PotionEffect(potion, duration, amplifier)));
  331. EntityTippedArrow arrow = launchProjectile(p, EntityTippedArrow.class, scale, stack);
  332. return arrow;
  333. }
  334. }