Added general particle effects that follow a point of entity

This commit is contained in:
Sollace 2021-12-26 10:49:04 +02:00
parent 7ad82f0bb2
commit 56af8f80ba
5 changed files with 146 additions and 5 deletions

View file

@ -51,7 +51,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.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new);
ParticleFactoryRegistry.getInstance().register(UParticles.MAGIC_RUNES, RunesParticle::new);

View file

@ -0,0 +1,76 @@
package com.minelittlepony.unicopia.client.particle;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.particle.NoRenderParticle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.Vec3d;
public class FollowingParticle extends NoRenderParticle {
private final FollowingParticleEffect parameters;
private final Particle particle;
private float scale;
public FollowingParticle(FollowingParticleEffect parameters, SpriteProvider provider, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
super(world, x, y, z, velocityX, velocityY, velocityZ);
this.scale = 0.1f * (this.random.nextFloat() * 0.5f + 0.5f) * 2.0f;
setMaxAge(3);
scale(0.125F);
this.parameters = parameters;
this.collidesWithWorld = false;
this.particle = parameters.getChildEffect().map(child -> MinecraftClient.getInstance().particleManager.addParticle(child, x, y, z, velocityX, velocityY, velocityZ)).orElse(null);
}
@Override
public Particle scale(float scale) {
this.scale *= scale;
super.scale(scale);
if (particle != null) {
particle.scale(scale);
}
return this;
}
@Override
public void move(double dx, double dy, double dz) {
super.move(dx, dy, dz);
if (particle != null) {
particle.setPos(x, y, z);
}
}
@Override
public void tick() {
if (this.particle == null || !this.particle.isAlive()) {
markDead();
}
super.tick();
Vec3d target = parameters.getTarget(world);
Vec3d pos = new Vec3d(x, y, z);
if (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, parameters.getSpeed()));
move(motion.x, motion.y, motion.z);
}
@Override
public String toString() {
return super.toString() + ", Speed " + parameters.getSpeed() + ", Target (" + parameters.getTargetDescriptor() + ") Sub-Particle (" + particle + ")";
}
}

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.client.particle;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.particle.SpriteBillboardParticle;
import net.minecraft.client.particle.SpriteProvider;
@ -12,7 +13,14 @@ 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) {
public static Particle create(FollowingParticleEffect effect, SpriteProvider provider, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
if (effect.getChildEffect().isPresent()) {
return new FollowingParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ);
}
return new HealthDrainParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ);
}
protected 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);

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.particle;
import java.util.Locale;
import java.util.Optional;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -25,12 +26,23 @@ public class FollowingParticleEffect implements ParticleEffect {
private final float followSpeed;
private Optional<ParticleEffect> childEffect = Optional.empty();
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, StringReader reader) throws CommandSyntaxException {
this(type, -1, ParticleFactoryHelper.readVector(reader), ParticleFactoryHelper.readFloat(reader));
if (reader.canRead()) {
reader.expect(' ');
childEffect = ParticleFactoryHelper.read(reader);
}
}
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> particleType, PacketByteBuf buf) {
this(particleType, buf.readInt(), new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, PacketByteBuf buf) {
this(type, buf.readInt(), new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
if (buf.readBoolean()) {
childEffect = ParticleFactoryHelper.read(Registry.PARTICLE_TYPE.get(buf.readInt()), buf);
}
}
public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Vec3d target, float followSpeed) {
@ -51,6 +63,22 @@ public class FollowingParticleEffect implements ParticleEffect {
this.followSpeed = followSpeed;
}
public ParticleEffect withChild(ParticleEffect child) {
childEffect = Optional.of(child);
return this;
}
public Optional<ParticleEffect> getChildEffect() {
return childEffect;
}
public String getTargetDescriptor() {
if (movingTarget > -1) {
return "Moving(" + movingTarget + ")";
}
return fixedTarget.toString();
}
public Vec3d getTarget(World world) {
if (movingTarget > -1) {
Entity e = world.getEntityById(movingTarget);
@ -79,10 +107,26 @@ public class FollowingParticleEffect implements ParticleEffect {
buf.writeDouble(fixedTarget.y);
buf.writeDouble(fixedTarget.z);
buf.writeFloat(followSpeed);
getChildEffect().ifPresentOrElse(child -> {
buf.writeBoolean(true);
buf.writeInt(Registry.PARTICLE_TYPE.getRawId(child.getType()));
child.write(buf);
}, () -> buf.writeBoolean(false));
}
@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);
return getChildEffect().map(child -> {
return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f %s",
Registry.PARTICLE_TYPE.getId(getType()),
fixedTarget.x, fixedTarget.y, fixedTarget.z,
followSpeed, child.asString());
}).orElseGet(() -> {
return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f",
Registry.PARTICLE_TYPE.getId(getType()),
fixedTarget.x, fixedTarget.y, fixedTarget.z,
followSpeed);
});
}
}

View file

@ -1,8 +1,11 @@
package com.minelittlepony.unicopia.particle;
import java.util.Optional;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.argument.ParticleEffectArgumentType;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleType;
@ -10,6 +13,16 @@ import net.minecraft.util.math.Vec3d;
public interface ParticleFactoryHelper {
@SuppressWarnings("unchecked")
static <T extends ParticleEffect> Optional<T> read(StringReader reader) throws CommandSyntaxException {
return Optional.ofNullable((T)ParticleEffectArgumentType.readParameters(reader));
}
@SuppressWarnings("deprecation")
static <T extends ParticleEffect> Optional<ParticleEffect> read(ParticleType<T> type, PacketByteBuf buf) {
return Optional.ofNullable(type.getParametersFactory().read(type, buf));
}
static Vec3d readVector(StringReader reader) throws CommandSyntaxException {
return new Vec3d(readDouble(reader), readDouble(reader), readDouble(reader));
}