package me.km.effects; import java.util.Collection; import java.util.HashMap; import java.util.stream.Collectors; import me.km.KajetansMod; import me.km.api.Module; import me.km.api.Utils; import me.km.entities.EntityItemProjectile; import me.km.jobsystem.JobAPI; import me.km.plots.ProtectionBank; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityAreaEffectCloud; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityEnderPearl; import net.minecraft.entity.item.EntityExpBottle; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.projectile.*; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.network.play.server.SPacketParticles; import net.minecraft.network.play.server.SPacketSoundEffect; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.potion.PotionType; import net.minecraft.potion.PotionUtils; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraft.world.WorldServer; public class EffectUtils extends Module { private final HashMap entityData; public EffectUtils(String mname, String prefix, TextFormatting color) { super(mname, prefix, color); entityData = new HashMap<>(); } // ----------------------------------------------------------------------------------- // Entity-Data // ----------------------------------------------------------------------------------- private class EntityData { private final String s; private final Object data; public EntityData(String s, Object data) { this.s = s; this.data = data; } } public void addEntityData(Entity ent, String key, Object data) { entityData.put(ent.getEntityId(), new EntityData(key, data)); removeInvalidData(ent); } public void addEntityData(Entity ent, String key) { addEntityData(ent, key, true); } private void removeInvalidData(Entity ent) { if(ent.isDead) { entityData.remove(ent.getEntityId()); return; } KajetansMod.scheduler.scheduleTask(() -> removeInvalidData(ent), 100); } public Object getEntityData(Entity ent, String key) { EntityData data = entityData.get(ent.getEntityId()); if(data == null) { return null; } if(data.s.equals(key)) { return data.data; } return null; } // ----------------------------------------------------------------------------------- // Entity-Level // ----------------------------------------------------------------------------------- /** Returns the level of a players effect * * @param p a player * @param eff an effect * @return the level of the effect, 0 on non existance for the player */ public static int getEffectLevel(EntityPlayer p, Effect eff) { JobAPI job = KajetansMod.jobs; return eff.getSkills().stream().mapToInt(s -> job.getSkillLevel(p, s)).max().orElse(0); } @SuppressWarnings(value = "unchecked") public static Class getEffectClass(String s) { Class c; try { c = (Class) Class.forName("me.km.effects.active." + s); } catch(ClassNotFoundException | ClassCastException ex) { return null; } return c; } // ----------------------------------------------------------------------------------- // Entity-Collections // ----------------------------------------------------------------------------------- public static Collection getPlayersOfGuild(EntityPlayer p, World w, Vec3d v, double radius) { Collection col = Utils.getNearbyPlayers(w, v, radius); if(col.isEmpty()) { return col; } int id = KajetansMod.playerbank.getGuildId(p); col.removeIf(pl -> KajetansMod.playerbank.getGuildId(pl) != id); return col; } public static Collection getPlayersOfGuild(EntityPlayer p, double radius) { return getPlayersOfGuild(p, p.world, p.getPositionVector(), radius); } public static Collection getEntsOfNotGuild(EntityPlayer p, World w, Vec3d v, double radius) { boolean animals = KajetansMod.plots.getDataBank(ProtectionBank.class).canBuild(w, new BlockPos(v), p); boolean pvp = !KajetansMod.worldManager.getWorldPreferences(w).pvpProtection; boolean ppvp = KajetansMod.playerbank.getDataBank().getTag(p, "pvp") >= 1; int id = KajetansMod.playerbank.getGuildId(p); return Utils.getNearbyEntities(w, v, radius, EntityLivingBase.class).stream() .filter(ent -> animals || !(ent instanceof EntityAnimal)) .filter(ent -> pvp || !(ent instanceof EntityPlayer) || (ppvp && KajetansMod.playerbank.getDataBank().getTag((EntityPlayer) ent, "pvp") >= 1)) .filter(ent -> !(ent instanceof EntityPlayer) || (id != KajetansMod.playerbank.getGuildId((EntityPlayer) ent))) .filter(ent -> !(ent.equals(p))) .collect(Collectors.toList()); } public static Collection getEntsOfNotGuild(EntityPlayer p, double radius) { return getEntsOfNotGuild(p, p.world, p.getPositionVector(), radius); } // ----------------------------------------------------------------------------------- // Target Selector // ----------------------------------------------------------------------------------- public static BlockPos getPlayerTarget(EntityPlayer p, int range) { return Utils.getPlayerTarget(p, range + 7).up(); } // ----------------------------------------------------------------------------------- // Particles // ----------------------------------------------------------------------------------- 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) { SPacketParticles packet = new SPacketParticles(particle, false, x, y, z, offX, offY, offZ, speed, count, data); Utils.getNearbyPlayers(w, x, y, z, 512).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet)); } public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, float offX, float offY, float offZ, int count) { spawnParticle(w, particle, x, y, z, offX, offY, offZ, 1, count, new int[0]); } public static void spawnParticle(WorldServer w, EnumParticleTypes particle, float x, float y, float z, int count) { spawnParticle(w, particle, x, y, z, 0, 0, 0, count); } public static void spawnParticle(WorldServer w, EnumParticleTypes particle, Vec3d v, int count) { spawnParticle(w, particle, (float) v.x, (float) v.y, (float) v.z, 0, 0, 0, count); } public static void playSpell(EntityPlayerMP p, int level) { 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]); } public static void playEffectCircleWithData(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter, int... data) { double x = v.x; float y = (float) v.y; double z = v.z; double angle = 2 * Math.PI / counter; for(int i = 0; i < counter; i++) { spawnParticle(w, particle, (float) (x + Math.cos(i * angle) * radius), y, (float) (z + Math.sin(i * angle) * radius), 0, 0, 0, 1, 1, data); } } public static void playEffectCircle(WorldServer w, Vec3d v, EnumParticleTypes particle, double radius, int counter) { playEffectCircleWithData(w, v, particle, radius, counter, new int[0]); } // ----------------------------------------------------------------------------------- // Sounds // ----------------------------------------------------------------------------------- public static void playSound(WorldServer w, SoundEvent se, SoundCategory sc, double x, double y, double z) { SPacketSoundEffect packet = new SPacketSoundEffect(se, sc, x, y, z, 1, 1); Utils.getNearbyPlayers(w, x, y, z, 128).forEach(p -> ((EntityPlayerMP) p).connection.sendPacket(packet)); } public static void playSound(EntityPlayerMP p, SoundEvent se, SoundCategory sc) { playSound(p.getServerWorld(), se, sc, p.posX, p.posY, p.posZ); } public static void playSound(EntityPlayerMP p, SoundEvent se) { playSound(p.getServerWorld(), se, SoundCategory.PLAYERS, p.posX, p.posY, p.posZ); } // ----------------------------------------------------------------------------------- // Potions // ----------------------------------------------------------------------------------- public static void addPotionTo(EntityLivingBase ent, Potion potion, int duration, int amplifier) { if(ent.isPotionActive(potion)) { ent.removePotionEffect(potion); } ent.addPotionEffect(new PotionEffect(potion, duration, amplifier)); } public static void spawnPotionCloud(Vec3d v, EntityPlayerMP p, Potion potion, int pduration, int amplifier, int duration, float radius) { EntityAreaEffectCloud cloud = new EntityAreaEffectCloud(p.getServerWorld(), v.x, v.y, v.z); cloud.setDuration(duration); cloud.setRadius(radius); cloud.setOwner(p); cloud.setWaitTime(5); cloud.setPotion(new PotionType(new PotionEffect(potion, pduration, amplifier))); p.getServerWorld().spawnEntity(cloud); } public static void spawnPotionCloud(EntityPlayerMP p, Potion potion, int level) { BlockPos pos = getPlayerTarget(p, level); spawnPotionCloud(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), p, potion, 20 * level, (level / 4), 40 * level, 0.5f + level / 4f); playSpell(p, level); playSound(p, SoundEvents.ENTITY_FIREWORK_BLAST, SoundCategory.PLAYERS); } // ----------------------------------------------------------------------------------- // Projectiles // ----------------------------------------------------------------------------------- public static T launchProjectile(EntityPlayer p, Class projectile, double scale, Object data) { World w = p.world; Entity launch = null; if(EntityItemProjectile.class == projectile) { if(data == null) { throw new NullPointerException("Data musn't be null for EntityItemProjectile"); } ItemStack stack = (ItemStack) data; if(stack.isEmpty()) { throw new IllegalArgumentException("Empty ItemStack not allowed here"); } launch = new EntityItemProjectile(p, stack.copy()); ((EntityItemProjectile) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f); } else if(EntitySnowball.class == projectile) { launch = new EntitySnowball(w, p); ((EntitySnowball) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f); } else if(EntityEgg.class == projectile) { launch = new EntityEgg(w, p); ((EntityEgg) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f); } else if(EntityEnderPearl.class == projectile) { launch = new EntityEnderPearl(w, p); ((EntityEnderPearl) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, 0.0f, 1.5f, 1.0f); } else if(EntityPotion.class == projectile) { launch = new EntityPotion(w, p, (ItemStack) data); ((EntityPotion) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.5f, 1.0f); } else if(EntityExpBottle.class == projectile) { launch = new EntityExpBottle(w, p); ((EntityExpBottle) launch).setHeadingFromThrower(p, p.rotationPitch, p.rotationYaw, -20.0f, 0.7f, 1.0f); } else if(EntityArrow.class.isAssignableFrom(projectile)) { if(EntityTippedArrow.class == projectile) { launch = new EntityTippedArrow(w, p); ((EntityTippedArrow) launch).setPotionEffect((ItemStack) data); } else if(EntitySpectralArrow.class == projectile) { launch = new EntitySpectralArrow(w, p); } else { launch = new EntityTippedArrow(w, p); } ((EntityArrow) launch).setAim(p, p.rotationPitch, p.rotationYaw, 0.0F, 3.0F, 1.0F); } else if(EntityFireball.class.isAssignableFrom(projectile)) { Vec3d v = p.getLookVec().scale(10); if (EntitySmallFireball.class == projectile) { launch = new EntitySmallFireball(w, p, v.x, v.y, v.z); } else if (EntityWitherSkull.class == projectile) { launch = new EntityWitherSkull(w, p, v.x, v.y, v.z); } else if (EntityDragonFireball.class == projectile) { launch = new EntityDragonFireball(w, p, v.x, v.y, v.z); } else { launch = new EntityLargeFireball(w, p, v.x, v.y, v.z); } } Utils.scaleVelocity(launch, scale); w.spawnEntity(launch); return (T) launch; } public static EntityTippedArrow launchTippedArrow(EntityPlayer p, double scale, Potion potion, int duration, int amplifier) { ItemStack stack = new ItemStack(Items.TIPPED_ARROW); PotionUtils.addPotionToItemStack(stack, new PotionType(new PotionEffect(potion, duration, amplifier))); EntityTippedArrow arrow = launchProjectile(p, EntityTippedArrow.class, scale, stack); return arrow; } }