From 6ffff327182acc3d8a04390b8ef9f3133acbbb3e Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 2 Feb 2021 12:52:50 +0200 Subject: [PATCH] Added a health drain particle for changelings, fixed changeling feed having too wide of a radius, and fixed particles not spawning on the clients --- .../ability/ChangelingFeedAbility.java | 5 +- .../unicopia/client/URenderers.java | 6 +- .../particle/ChangelingMagicParticle.java | 5 +- .../client/particle/HealthDrainParticle.java | 48 ++++++++++ .../client/particle/MagicParticle.java | 7 +- .../client/particle/RaindropsParticle.java | 3 +- .../particle/FollowingParticleEffect.java | 96 +++++++++++++++++++ .../unicopia/particle/ParticleUtils.java | 13 ++- .../unicopia/particle/UParticles.java | 2 + .../unicopia/util/VecHelper.java | 14 --- .../unicopia/particles/health_drain.json | 5 + 11 files changed, 180 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/particle/HealthDrainParticle.java create mode 100644 src/main/java/com/minelittlepony/unicopia/particle/FollowingParticleEffect.java create mode 100644 src/main/resources/assets/unicopia/particles/health_drain.json diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingFeedAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingFeedAbility.java index bc604e34..2bdbbdbe 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingFeedAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingFeedAbility.java @@ -8,6 +8,7 @@ import javax.annotation.Nullable; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.particle.FollowingParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.util.MagicalDamageSource; @@ -79,7 +80,7 @@ public class ChangelingFeedAbility implements Ability { } protected List getTargets(Pony player) { - List list = VecHelper.findInReach(player.getMaster(), 3, this::canDrain); + List list = VecHelper.findInRange(player.getMaster(), player.getWorld(), player.getOriginVector(), 3, this::canDrain); RayTraceHelper.findEntity(player.getMaster(), 17, 1, looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked)) @@ -122,6 +123,7 @@ public class ChangelingFeedAbility implements Ability { } public float drainFrom(PlayerEntity changeling, LivingEntity living) { + DamageSource d = MagicalDamageSource.create("feed", changeling); float damage = living.getHealth()/2; @@ -131,6 +133,7 @@ public class ChangelingFeedAbility implements Ability { } ParticleUtils.spawnParticles(UParticles.CHANGELING_MAGIC, living, 7); + ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, changeling, 0.2F), living, 1); if (changeling.hasStatusEffect(StatusEffects.NAUSEA)) { StatusEffectInstance effect = changeling.getStatusEffect(StatusEffects.NAUSEA); diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index e9542939..9e4f0e61 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.client; import com.minelittlepony.unicopia.UEntities; import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle; import com.minelittlepony.unicopia.client.particle.DiskParticle; +import com.minelittlepony.unicopia.client.particle.HealthDrainParticle; import com.minelittlepony.unicopia.client.particle.MagicParticle; import com.minelittlepony.unicopia.client.particle.RainboomParticle; import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle; @@ -24,6 +25,7 @@ public interface URenderers { ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new)); + ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::new)); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.SPHERE, SphereParticle::new); @@ -33,10 +35,10 @@ public interface URenderers { } static PendingParticleFactory createFactory(ParticleSupplier supplier) { - return provider -> (effect, world, x, y, z, dx, dy, dz) -> supplier.get(provider, world, x, y, z, dx, dy, dz); + return provider -> (effect, world, x, y, z, dx, dy, dz) -> supplier.get(effect, provider, world, x, y, z, dx, dy, dz); } interface ParticleSupplier { - Particle get(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz); + Particle get(T effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz); } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/ChangelingMagicParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/ChangelingMagicParticle.java index 3327800a..c0c5d2f6 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/ChangelingMagicParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/ChangelingMagicParticle.java @@ -2,13 +2,14 @@ package com.minelittlepony.unicopia.client.particle; import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.ParticleEffect; public class ChangelingMagicParticle extends MagicParticle { private final SpriteProvider provider; - public ChangelingMagicParticle(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) { - super(provider, world, x, y, z, dx, dy, dz, 1, 1, 1); + public ChangelingMagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) { + super(effect, provider, world, x, y, z, dx, dy, dz, 1, 1, 1); this.provider = provider; float intensity = random.nextFloat() * 0.6F + 0.4F; diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/HealthDrainParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/HealthDrainParticle.java new file mode 100644 index 00000000..2a107cc6 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/HealthDrainParticle.java @@ -0,0 +1,48 @@ +package com.minelittlepony.unicopia.client.particle; + +import com.minelittlepony.unicopia.particle.FollowingParticleEffect; + +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.particle.SpriteBillboardParticle; +import net.minecraft.client.particle.SpriteProvider; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.Vec3d; + +public class HealthDrainParticle extends SpriteBillboardParticle { + + private final FollowingParticleEffect effect; + + public HealthDrainParticle(FollowingParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + setSprite(provider); + setMaxAge(3); + scale(0.125F); + this.effect = effect; + this.collidesWithWorld = false; + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT; + } + + @Override + public void tick() { + super.tick(); + + Vec3d target = effect.getTarget(world); + Vec3d pos = new Vec3d(x, y, z); + + if (this.scale * 1.5F < 0.5F) { + scale(1.5F); + } + + double distance = pos.distanceTo(target); + if (distance > 1) { + age = 0; + } + + Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, effect.getSpeed())); + move(motion.x, motion.y, motion.z); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/MagicParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/MagicParticle.java index fa97eb73..16ec7b38 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/MagicParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/MagicParticle.java @@ -4,13 +4,14 @@ import net.minecraft.client.particle.ParticleTextureSheet; import net.minecraft.client.particle.SpriteBillboardParticle; import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.ParticleEffect; public class MagicParticle extends SpriteBillboardParticle { private double startX; private double startY; private double startZ; - MagicParticle(SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ, float r, float g, float b) { + MagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ, float r, float g, float b) { super(w, x, y, z); setSprite(provider); @@ -28,8 +29,8 @@ public class MagicParticle extends SpriteBillboardParticle { colorBlue = b; } - public MagicParticle(SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ) { - this(provider, w, x, y, z, vX, vY, vZ, 1, 1, 1); + public MagicParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld w, double x, double y, double z, double vX, double vY, double vZ) { + this(effect, provider, w, x, y, z, vX, vY, vZ, 1, 1, 1); colorAlpha = 0.7F; colorGreen *= 0.3F; diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RaindropsParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RaindropsParticle.java index 37572dd8..4b978551 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RaindropsParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RaindropsParticle.java @@ -3,10 +3,11 @@ package com.minelittlepony.unicopia.client.particle; import net.minecraft.client.particle.RainSplashParticle; import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.ParticleEffect; public class RaindropsParticle extends RainSplashParticle { - public RaindropsParticle(SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) { + public RaindropsParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double dx, double dy, double dz) { super(world, x, y, z); velocityY = -0.1; maxAge += 19; diff --git a/src/main/java/com/minelittlepony/unicopia/particle/FollowingParticleEffect.java b/src/main/java/com/minelittlepony/unicopia/particle/FollowingParticleEffect.java new file mode 100644 index 00000000..3a4afc68 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/particle/FollowingParticleEffect.java @@ -0,0 +1,96 @@ +package com.minelittlepony.unicopia.particle; + +import java.util.Locale; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleType; +import net.minecraft.entity.Entity; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +public class FollowingParticleEffect implements ParticleEffect { + public static final ParticleEffect.Factory FACTORY = new ParticleEffect.Factory() { + @Override + public FollowingParticleEffect read(ParticleType type, StringReader reader) throws CommandSyntaxException { + reader.expect(' '); + double x = reader.readDouble(); + reader.expect(' '); + double y = reader.readDouble(); + reader.expect(' '); + double z = reader.readDouble(); + reader.expect(' '); + float speed = reader.readFloat(); + return new FollowingParticleEffect(type, -1, new Vec3d(x, y, z), speed); + } + + @Override + public FollowingParticleEffect read(ParticleType particleType, PacketByteBuf buf) { + return new FollowingParticleEffect(particleType, buf.readInt(), new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat()); + } + }; + + private final ParticleType type; + + private Vec3d fixedTarget; + + private int movingTarget; + + private final float followSpeed; + + public FollowingParticleEffect(ParticleType type, Vec3d target, float followSpeed) { + this.type = type; + this.fixedTarget = target; + this.movingTarget = -1; + this.followSpeed = followSpeed; + } + + public FollowingParticleEffect(ParticleType type, Entity target, float followSpeed) { + this(type, target.getEntityId(), target.getCameraPosVec(1), followSpeed); + } + + private FollowingParticleEffect(ParticleType type, int movingTarget, Vec3d fixedTarget, float followSpeed) { + this.type = type; + this.movingTarget = movingTarget; + this.fixedTarget = fixedTarget; + this.followSpeed = followSpeed; + } + + public Vec3d getTarget(World world) { + if (movingTarget > -1) { + Entity e = world.getEntityById(movingTarget); + if (e != null) { + fixedTarget = e.getCameraPosVec(1); + } else { + movingTarget = -1; + } + } + return fixedTarget; + } + + public float getSpeed() { + return followSpeed; + } + + @Override + public ParticleType getType() { + return type; + } + + @Override + public void write(PacketByteBuf buf) { + buf.writeInt(movingTarget); + buf.writeDouble(fixedTarget.x); + buf.writeDouble(fixedTarget.y); + buf.writeDouble(fixedTarget.z); + } + + @Override + public String asString() { + return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f", Registry.PARTICLE_TYPE.getId(getType()), fixedTarget.x, fixedTarget.y, fixedTarget.z, followSpeed); + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java b/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java index 16cfcfc5..a31f9cf9 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/ParticleUtils.java @@ -5,6 +5,8 @@ import com.minelittlepony.unicopia.util.shape.Sphere; import net.minecraft.entity.Entity; import net.minecraft.particle.ParticleEffect; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.World; /** * Utility for spawning particles. @@ -18,11 +20,20 @@ public final class ParticleUtils { Shape shape = new Sphere(false, Math.abs((float)halfDist + entity.getWidth())); shape.randomPoints(count, entity.world.random).forEach(point -> { - entity.world.addParticle(particleId, + spawnParticle(entity.world, particleId, entity.getX() + point.x, middle + point.y, entity.getZ() + point.z, 0, 0, 0); }); } + + public static void spawnParticle(World world, ParticleEffect effect, double x, double y, double z, double vX, double vY, double vZ) { + if (world instanceof ServerWorld) { + ((ServerWorld)world).spawnParticles(effect, x, y, z, 1, vX, vY, vZ, 0); + } else { + world.addParticle(effect, x, y, z, vX, vY, vZ); + } + + } } diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index a990b5c7..3f65546d 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -19,6 +19,8 @@ public interface UParticles { ParticleType SPHERE = register("sphere", FabricParticleTypes.complex(true, SphereParticleEffect.FACTORY)); ParticleType DISK = register("disk", FabricParticleTypes.complex(true, DiskParticleEffect.FACTORY)); + ParticleType HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY)); + static > T register(String name, T type) { return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type); } diff --git a/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java b/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java index 9c592c65..ba1a8b8c 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/VecHelper.java @@ -5,7 +5,6 @@ import java.util.function.Predicate; import javax.annotation.Nullable; import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; @@ -23,17 +22,4 @@ public interface VecHelper { static List findInRange(@Nullable Entity origin, World w, Vec3d pos, double radius, @Nullable Predicate predicate) { return w.getOtherEntities(origin, Box.method_29968(pos).expand(radius), predicate == null ? inRange(pos, radius) : inRange(pos, radius).and(predicate)); } - - - /** - * Gets all entities within a given range from the player. - */ - static List findInReach(PlayerEntity player, double reach, @Nullable Predicate predicate) { - Vec3d look = player.getCameraPosVec(1).multiply(reach); - - return player.world.getOtherEntities(player, player - .getBoundingBox() - .expand(look.x, look.y, look.z) - .expand(1, 1, 1), predicate); - } } diff --git a/src/main/resources/assets/unicopia/particles/health_drain.json b/src/main/resources/assets/unicopia/particles/health_drain.json new file mode 100644 index 00000000..1d45f426 --- /dev/null +++ b/src/main/resources/assets/unicopia/particles/health_drain.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "minecraft:heart" + ] +}