Change particle effects to use records

This commit is contained in:
Sollace 2023-10-18 18:29:49 +01:00
parent a9923c71f4
commit 15071ccd72
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
22 changed files with 233 additions and 204 deletions

View file

@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment; import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.SphereParticleEffect; import com.minelittlepony.unicopia.particle.SphereParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
@ -95,7 +96,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
} }
if (!source.isClient() && source.asWorld().random.nextInt(300) == 0) { if (!source.isClient() && source.asWorld().random.nextInt(300) == 0) {
ParticleUtils.spawnParticle(source.asWorld(), UParticles.LIGHTNING_BOLT, getOrigin(source), Vec3d.ZERO); ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
} }
return super.tick(source, situation); return super.tick(source, situation);

View file

@ -4,7 +4,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.*; import com.minelittlepony.unicopia.ability.magic.spell.*;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
@ -39,7 +39,7 @@ public class DispellEvilSpell extends AbstractSpell implements ProjectileDelegat
l.takeKnockback(1, d, e); l.takeKnockback(1, d, e);
} }
source.addParticle(UParticles.LIGHTNING_BOLT, entity.getPos(), Vec3d.ZERO); source.addParticle(LightningBoltParticleEffect.DEFAULT, entity.getPos(), Vec3d.ZERO);
}); });
source.subtractEnergyCost(1000); source.subtractEnergyCost(1000);

View file

@ -65,7 +65,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme
ParticleEffect effect = teleportationTarget.getTarget() ParticleEffect effect = teleportationTarget.getTarget()
.map(target -> { .map(target -> {
getType(); getType();
return new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target.pos(), 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK); return (ParticleEffect)new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target.pos(), 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK);
}) })
.orElse(ParticleTypes.ELECTRIC_SPARK); .orElse(ParticleTypes.ELECTRIC_SPARK);

View file

@ -1,9 +1,8 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
@ -79,6 +78,6 @@ public class ZapBlock extends Block {
}); });
} }
world.emitGameEvent(GameEvent.LIGHTNING_STRIKE, pos, GameEvent.Emitter.of(state)); world.emitGameEvent(GameEvent.LIGHTNING_STRIKE, pos, GameEvent.Emitter.of(state));
ParticleUtils.spawnParticle(world, UParticles.LIGHTNING_BOLT, Vec3d.ofCenter(pos), Vec3d.ZERO); ParticleUtils.spawnParticle(world, LightningBoltParticleEffect.DEFAULT, Vec3d.ofCenter(pos), Vec3d.ZERO);
} }
} }

View file

@ -15,12 +15,10 @@ public class DiskParticle extends SphereParticle {
private final Quaternionf rotation = new Quaternionf(0, 0, 0, 1); private final Quaternionf rotation = new Quaternionf(0, 0, 0, 1);
public DiskParticle(SphereParticleEffect effect, ClientWorld w, double x, double y, double z, double rX, double rY, double rZ) { public DiskParticle(SphereParticleEffect effect, ClientWorld w, double x, double y, double z, double rX, double rY, double rZ) {
super(effect, w, x, y, z, 0, 0, 0); super(effect.withOffset(new Vec3d(0, 0.25, 0)), w, x, y, z, 0, 0, 0);
rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees((float)effect.getOffset().y)); rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees((float)effect.offset().y));
rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - (float)effect.getOffset().x)); rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - (float)effect.offset().x));
effect.setOffset(new Vec3d(0, 0.25, 0));
} }
@Override @Override

View file

@ -24,7 +24,7 @@ public class FollowingParticle extends NoRenderParticle {
scale(0.125F); scale(0.125F);
this.parameters = parameters; this.parameters = parameters;
this.collidesWithWorld = false; this.collidesWithWorld = false;
this.particle = parameters.getChildEffect().map(child -> MinecraftClient.getInstance().particleManager.addParticle(child, x, y, z, velocityX, velocityY, velocityZ)).orElse(null); this.particle = parameters.childEffect().map(child -> MinecraftClient.getInstance().particleManager.addParticle(child, x, y, z, velocityX, velocityY, velocityZ)).orElse(null);
} }
@Override @Override
@ -50,7 +50,7 @@ public class FollowingParticle extends NoRenderParticle {
super.tick(); super.tick();
Vec3d target = parameters.getTarget(world); Vec3d target = parameters.target().getPosition(world);
Vec3d pos = new Vec3d(x, y, z); Vec3d pos = new Vec3d(x, y, z);
if (scale * 1.5F < 0.5F) { if (scale * 1.5F < 0.5F) {
@ -62,12 +62,12 @@ public class FollowingParticle extends NoRenderParticle {
age = 0; age = 0;
} }
Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, parameters.getSpeed())); Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, parameters.followSpeed()));
move(motion.x, motion.y, motion.z); move(motion.x, motion.y, motion.z);
} }
@Override @Override
public String toString() { public String toString() {
return super.toString() + ", Speed " + parameters.getSpeed() + ", Target (" + parameters.getTargetDescriptor() + ") Sub-Particle (" + particle + ")"; return super.toString() + ", Speed " + parameters.followSpeed() + ", Target (" + parameters.target() + ") Sub-Particle (" + particle + ")";
} }
} }

View file

@ -14,7 +14,7 @@ public class HealthDrainParticle extends SpriteBillboardParticle {
private final FollowingParticleEffect effect; private final FollowingParticleEffect effect;
public static Particle create(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()) { if (effect.childEffect().isPresent()) {
return new FollowingParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ); return new FollowingParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ);
} }
return new HealthDrainParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ); return new HealthDrainParticle(effect, provider, world, x, y, z, velocityX, velocityY, velocityZ);
@ -38,7 +38,7 @@ public class HealthDrainParticle extends SpriteBillboardParticle {
public void tick() { public void tick() {
super.tick(); super.tick();
Vec3d target = effect.getTarget(world); Vec3d target = effect.target().getPosition(world);
Vec3d pos = new Vec3d(x, y, z); Vec3d pos = new Vec3d(x, y, z);
if (this.scale * 1.5F < 0.5F) { if (this.scale * 1.5F < 0.5F) {
@ -50,7 +50,7 @@ public class HealthDrainParticle extends SpriteBillboardParticle {
age = 0; age = 0;
} }
Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, effect.getSpeed())); Vec3d motion = target.subtract(pos).normalize().multiply(Math.min(distance, effect.followSpeed()));
move(motion.x, motion.y, motion.z); move(motion.x, motion.y, motion.z);
} }
} }

View file

@ -6,6 +6,7 @@ import java.util.List;
import org.joml.Vector3f; import org.joml.Vector3f;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@ -14,7 +15,6 @@ import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -23,8 +23,11 @@ public class LightningBoltParticle extends AbstractGeometryBasedParticle {
private final List<List<Vector3f>> branches = new ArrayList<>(); private final List<List<Vector3f>> branches = new ArrayList<>();
public LightningBoltParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { private final LightningBoltParticleEffect effect;
public LightningBoltParticle(LightningBoltParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
super(world, x, y, z, velocityX, velocityY, velocityZ); super(world, x, y, z, velocityX, velocityY, velocityZ);
this.effect = effect;
} }
@Override @Override
@ -34,7 +37,7 @@ public class LightningBoltParticle extends AbstractGeometryBasedParticle {
return; return;
} }
if (age % 5 == 0) { if (age % effect.changeFrequency() == 0) {
branches.clear(); branches.clear();
} }
if (branches.isEmpty()) { if (branches.isEmpty()) {
@ -44,7 +47,9 @@ public class LightningBoltParticle extends AbstractGeometryBasedParticle {
branches.add(generateBranch()); branches.add(generateBranch());
} }
world.playSound(x, y, z, USounds.Vanilla.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, 10000, 8, true); if (!effect.silent()) {
world.playSound(x, y, z, USounds.Vanilla.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, 10000, 8, true);
}
} }
world.setLightningTicksLeft(2); world.setLightningTicksLeft(2);

View file

@ -20,11 +20,11 @@ public abstract class OrientedBillboardParticle extends AbstractBillboardParticl
public OrientedBillboardParticle(OrientedBillboardParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { public OrientedBillboardParticle(OrientedBillboardParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
super(world, x, y, z, velocityX, velocityY, velocityZ); super(world, x, y, z, velocityX, velocityY, velocityZ);
fixed = effect.isAngleFixed(); fixed = effect.fixed();
if (fixed) { if (fixed) {
// Was hamiltonianProduct (CHECK THIS!!) // Was hamiltonianProduct (CHECK THIS!!)
rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.getPitch())); rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.pitch()));
rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.getYaw())); rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.yaw()));
} }
} }

View file

@ -51,11 +51,11 @@ public class SphereParticle extends Particle implements Attachment {
public SphereParticle(SphereParticleEffect parameters, ClientWorld w, double x, double y, double z) { public SphereParticle(SphereParticleEffect parameters, ClientWorld w, double x, double y, double z) {
super(w, x, y, z); super(w, x, y, z);
this.parameters = parameters; this.parameters = parameters;
this.radius = parameters.getRadius(); this.radius = parameters.radius();
this.red = parameters.getColor().x / 255F; this.red = parameters.color().x / 255F;
this.green = parameters.getColor().y / 255F; this.green = parameters.color().y / 255F;
this.blue = parameters.getColor().z / 255F; this.blue = parameters.color().z / 255F;
this.alpha = parameters.getAlpha(); this.alpha = parameters.alpha();
setMaxAge(10); setMaxAge(10);
} }
@ -109,7 +109,7 @@ public class SphereParticle extends Particle implements Attachment {
if (link.isPresent()) { if (link.isPresent()) {
link.flatMap(Link::get).map(EntityConvertable::asEntity).ifPresentOrElse(e -> { link.flatMap(Link::get).map(EntityConvertable::asEntity).ifPresentOrElse(e -> {
if (!bound) { if (!bound) {
Vec3d offset = parameters.getOffset(); Vec3d offset = parameters.offset();
setPos(e.getX() + offset.getX(), e.getY() + offset.getY(), e.getZ() + offset.getZ()); setPos(e.getX() + offset.getX(), e.getY() + offset.getY(), e.getZ() + offset.getZ());
prevPosX = e.lastRenderX + offset.getX(); prevPosX = e.lastRenderX + offset.getX();

View file

@ -10,10 +10,9 @@ import com.minelittlepony.unicopia.WeaklyOwned;
import com.minelittlepony.unicopia.entity.DynamicLightSource; import com.minelittlepony.unicopia.entity.DynamicLightSource;
import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.EntityReference;
import com.minelittlepony.unicopia.entity.MagicImmune; import com.minelittlepony.unicopia.entity.MagicImmune;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
@ -212,7 +211,7 @@ public class FairyEntity extends PathAwareEntity implements DynamicLightSource,
attacker.onStruckByLightning(serverWorld, lightning); attacker.onStruckByLightning(serverWorld, lightning);
} }
emitGameEvent(GameEvent.LIGHTNING_STRIKE); emitGameEvent(GameEvent.LIGHTNING_STRIKE);
ParticleUtils.spawnParticle(getWorld(), UParticles.LIGHTNING_BOLT, getPos(), Vec3d.ZERO); ParticleUtils.spawnParticle(getWorld(), LightningBoltParticleEffect.DEFAULT, getPos(), Vec3d.ZERO);
return false; return false;
} }

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.IItemEntity; import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl; import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
@ -128,7 +129,7 @@ public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallba
} }
if (lightning) { if (lightning) {
ParticleUtils.spawnParticle(projectile.getWorld(), UParticles.LIGHTNING_BOLT, projectile.getPos(), Vec3d.ZERO); ParticleUtils.spawnParticle(projectile.getWorld(), LightningBoltParticleEffect.DEFAULT, projectile.getPos(), Vec3d.ZERO);
} }
if (rain || thunder) { if (rain || thunder) {

View file

@ -10,8 +10,8 @@ import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.group.MultiItem; import com.minelittlepony.unicopia.item.group.MultiItem;
import com.minelittlepony.unicopia.item.toxin.*; import com.minelittlepony.unicopia.item.toxin.*;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.util.TraceHelper; import com.minelittlepony.unicopia.util.TraceHelper;
import com.minelittlepony.unicopia.util.RegistryUtils; import com.minelittlepony.unicopia.util.RegistryUtils;
@ -67,7 +67,7 @@ public class ZapAppleItem extends Item implements ChameleonItem, ToxicHolder, Mu
} }
player.emitGameEvent(GameEvent.LIGHTNING_STRIKE); player.emitGameEvent(GameEvent.LIGHTNING_STRIKE);
ParticleUtils.spawnParticle(w, UParticles.LIGHTNING_BOLT, player.getPos(), Vec3d.ZERO); ParticleUtils.spawnParticle(w, LightningBoltParticleEffect.DEFAULT, player.getPos(), Vec3d.ZERO);
return stack; return stack;
} }

View file

@ -12,87 +12,44 @@ import net.minecraft.entity.Entity;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.world.World;
public class FollowingParticleEffect implements ParticleEffect { public record FollowingParticleEffect (
ParticleType<FollowingParticleEffect> type,
WeakTarget target,
float followSpeed,
Optional<ParticleEffect> childEffect
) implements ParticleEffect {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static final Factory<FollowingParticleEffect> FACTORY = ParticleFactoryHelper.of(FollowingParticleEffect::new, FollowingParticleEffect::new); public static final Factory<FollowingParticleEffect> FACTORY = ParticleFactoryHelper.of(FollowingParticleEffect::new, FollowingParticleEffect::new);
private final ParticleType<FollowingParticleEffect> type;
private Vec3d fixedTarget;
private int movingTarget;
private final float followSpeed;
private Optional<ParticleEffect> childEffect = Optional.empty();
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, StringReader reader) throws CommandSyntaxException { protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, StringReader reader) throws CommandSyntaxException {
this(type, -1, ParticleFactoryHelper.readVector(reader), ParticleFactoryHelper.readFloat(reader)); this(type,
new WeakTarget(reader),
if (reader.canRead()) { ParticleFactoryHelper.readFloat(reader),
reader.expect(' '); ParticleFactoryHelper.readOptional(reader, r -> {
childEffect = ParticleFactoryHelper.read(reader); r.expect(' ');
} return ParticleFactoryHelper.read(r);
}));
} }
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, PacketByteBuf buf) { protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, PacketByteBuf buf) {
this(type, buf.readInt(), new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat()); this(type,
new WeakTarget(buf),
if (buf.readBoolean()) { buf.readFloat(),
childEffect = ParticleFactoryHelper.read(Registries.PARTICLE_TYPE.get(buf.readInt()), buf); buf.readOptional(b -> ParticleFactoryHelper.readEffect(b))
} );
} }
public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Vec3d target, float followSpeed) { public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Vec3d target, float followSpeed) {
this.type = type; this(type, new WeakTarget(target, (Entity)null), followSpeed, Optional.empty());
this.fixedTarget = target;
this.movingTarget = -1;
this.followSpeed = followSpeed;
} }
public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Entity target, float followSpeed) { public FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, Entity target, float followSpeed) {
this(type, target.getId(), target.getCameraPosVec(1), followSpeed); this(type, new WeakTarget(target.getCameraPosVec(1), target), followSpeed, Optional.empty());
} }
private FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, int movingTarget, Vec3d fixedTarget, float followSpeed) { public FollowingParticleEffect withChild(ParticleEffect child) {
this.type = type; return new FollowingParticleEffect(type, target, followSpeed, Optional.of(child));
this.movingTarget = movingTarget;
this.fixedTarget = fixedTarget;
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);
if (e != null) {
fixedTarget = e.getCameraPosVec(1);
} else {
movingTarget = -1;
}
}
return fixedTarget;
}
public float getSpeed() {
return followSpeed;
} }
@Override @Override
@ -102,29 +59,30 @@ public class FollowingParticleEffect implements ParticleEffect {
@Override @Override
public void write(PacketByteBuf buf) { public void write(PacketByteBuf buf) {
buf.writeInt(movingTarget); target.write(buf);
buf.writeDouble(fixedTarget.x);
buf.writeDouble(fixedTarget.y);
buf.writeDouble(fixedTarget.z);
buf.writeFloat(followSpeed); buf.writeFloat(followSpeed);
getChildEffect().ifPresentOrElse(child -> { buf.writeOptional(childEffect(), (b, child) -> {
buf.writeBoolean(true); b.writeBoolean(true);
buf.writeInt(Registries.PARTICLE_TYPE.getRawId(child.getType())); b.writeInt(Registries.PARTICLE_TYPE.getRawId(child.getType()));
child.write(buf); child.write(buf);
}, () -> buf.writeBoolean(false)); });
} }
@Override @Override
public String asString() { public String asString() {
return getChildEffect().map(child -> { return childEffect().map(child -> {
return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f %s", return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f %s",
Registries.PARTICLE_TYPE.getId(getType()), Registries.PARTICLE_TYPE.getId(getType()),
fixedTarget.x, fixedTarget.y, fixedTarget.z, target.fixedPosition.x,
target.fixedPosition.y,
target.fixedPosition.z,
followSpeed, child.asString()); followSpeed, child.asString());
}).orElseGet(() -> { }).orElseGet(() -> {
return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f", return String.format(Locale.ROOT, "%s %.2f %.2f %.2f %.2f",
Registries.PARTICLE_TYPE.getId(getType()), Registries.PARTICLE_TYPE.getId(getType()),
fixedTarget.x, fixedTarget.y, fixedTarget.z, target.fixedPosition.x,
target.fixedPosition.y,
target.fixedPosition.z,
followSpeed); followSpeed);
}); });

View file

@ -0,0 +1,44 @@
package com.minelittlepony.unicopia.particle;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleType;
public record LightningBoltParticleEffect (
boolean silent,
int changeFrequency,
int maxBranchLength
) implements ParticleEffect {
public static final LightningBoltParticleEffect DEFAULT = new LightningBoltParticleEffect(false, 10, 6);
@SuppressWarnings("deprecation")
public static final ParticleEffect.Factory<LightningBoltParticleEffect> FACTORY = ParticleFactoryHelper.of(LightningBoltParticleEffect::new, LightningBoltParticleEffect::new);
protected LightningBoltParticleEffect(ParticleType<LightningBoltParticleEffect> particleType, StringReader reader) throws CommandSyntaxException {
this(ParticleFactoryHelper.readBoolean(reader), ParticleFactoryHelper.readInt(reader), ParticleFactoryHelper.readInt(reader));
}
protected LightningBoltParticleEffect(ParticleType<LightningBoltParticleEffect> particleType, PacketByteBuf buf) {
this(buf.readBoolean(), buf.readInt(), buf.readInt());
}
@Override
public ParticleType<?> getType() {
return UParticles.LIGHTNING_BOLT;
}
@Override
public void write(PacketByteBuf buffer) {
buffer.writeBoolean(silent);
buffer.writeInt(changeFrequency);
buffer.writeInt(maxBranchLength);
}
@Override
public String asString() {
return String.format("%s %s %s", silent, changeFrequency, maxBranchLength);
}
}

View file

@ -15,14 +15,14 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
public class MagicParticleEffect implements ParticleEffect { public record MagicParticleEffect (
boolean tinted,
Vector3f color
) implements ParticleEffect {
public static final MagicParticleEffect UNICORN = new MagicParticleEffect(false, new Vector3f()); public static final MagicParticleEffect UNICORN = new MagicParticleEffect(false, new Vector3f());
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static final ParticleEffect.Factory<MagicParticleEffect> FACTORY = ParticleFactoryHelper.of(MagicParticleEffect::new, MagicParticleEffect::new); public static final ParticleEffect.Factory<MagicParticleEffect> FACTORY = ParticleFactoryHelper.of(MagicParticleEffect::new, MagicParticleEffect::new);
private final boolean tinted;
private final Vector3f color;
protected MagicParticleEffect(ParticleType<MagicParticleEffect> particleType, StringReader reader) throws CommandSyntaxException { protected MagicParticleEffect(ParticleType<MagicParticleEffect> particleType, StringReader reader) throws CommandSyntaxException {
this(ParticleFactoryHelper.readBoolean(reader), AbstractDustParticleEffect.readColor(reader)); this(ParticleFactoryHelper.readBoolean(reader), AbstractDustParticleEffect.readColor(reader));
} }
@ -39,17 +39,8 @@ public class MagicParticleEffect implements ParticleEffect {
this(true, color); this(true, color);
} }
protected MagicParticleEffect(boolean tint, Vector3f color) {
tinted = tint;
this.color = color;
}
public boolean hasTint() {
return tinted;
}
public Vector3f getColor(Random random) { public Vector3f getColor(Random random) {
if (hasTint()) { if (tinted()) {
return color; return color;
} }

View file

@ -11,16 +11,15 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
public class OrientedBillboardParticleEffect implements ParticleEffect { public record OrientedBillboardParticleEffect (
ParticleType<OrientedBillboardParticleEffect> type,
boolean fixed,
float yaw,
float pitch
) implements ParticleEffect {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static final ParticleEffect.Factory<OrientedBillboardParticleEffect> FACTORY = ParticleFactoryHelper.of(OrientedBillboardParticleEffect::new, OrientedBillboardParticleEffect::new); public static final ParticleEffect.Factory<OrientedBillboardParticleEffect> FACTORY = ParticleFactoryHelper.of(OrientedBillboardParticleEffect::new, OrientedBillboardParticleEffect::new);
private final boolean fixed;
private final float yaw;
private final float pitch;
private final ParticleType<OrientedBillboardParticleEffect> type;
protected OrientedBillboardParticleEffect(ParticleType<OrientedBillboardParticleEffect> type, StringReader reader) throws CommandSyntaxException { protected OrientedBillboardParticleEffect(ParticleType<OrientedBillboardParticleEffect> type, StringReader reader) throws CommandSyntaxException {
this(type, ParticleFactoryHelper.readBoolean(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readFloat(reader)); this(type, ParticleFactoryHelper.readBoolean(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readFloat(reader));
} }
@ -37,25 +36,6 @@ public class OrientedBillboardParticleEffect implements ParticleEffect {
this(type, true, yaw, pitch); this(type, true, yaw, pitch);
} }
private OrientedBillboardParticleEffect(ParticleType<OrientedBillboardParticleEffect> type, boolean fixed, float yaw, float pitch) {
this.fixed = fixed;
this.yaw = yaw;
this.pitch = pitch;
this.type = type;
}
public boolean isAngleFixed() {
return fixed;
}
public float getYaw() {
return yaw;
}
public float getPitch() {
return pitch;
}
@Override @Override
public ParticleType<?> getType() { public ParticleType<?> getType() {
return type; return type;

View file

@ -1,7 +1,6 @@
package com.minelittlepony.unicopia.particle; package com.minelittlepony.unicopia.particle;
import java.util.Optional; import java.util.Optional;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -15,33 +14,58 @@ import net.minecraft.util.math.Vec3d;
public interface ParticleFactoryHelper { public interface ParticleFactoryHelper {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <T extends ParticleEffect> Optional<T> read(StringReader reader) throws CommandSyntaxException { static <T extends ParticleEffect> T read(StringReader reader) throws CommandSyntaxException {
return Optional.ofNullable((T)ParticleEffectArgumentType.readParameters(reader, Registries.PARTICLE_TYPE.getReadOnlyWrapper())); return (T)ParticleEffectArgumentType.readParameters(reader, Registries.PARTICLE_TYPE.getReadOnlyWrapper());
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
static <T extends ParticleEffect> Optional<ParticleEffect> read(ParticleType<T> type, PacketByteBuf buf) { static <T extends ParticleEffect> ParticleEffect readEffect(PacketByteBuf buf) {
return Optional.ofNullable(type.getParametersFactory().read(type, buf)); @SuppressWarnings("unchecked")
ParticleType<T> type = (ParticleType<T>)Registries.PARTICLE_TYPE.get(buf.readInt());
return type.getParametersFactory().read(type, buf);
} }
static Vec3d readVector(StringReader reader) throws CommandSyntaxException { static Vec3d readVector(StringReader reader) throws CommandSyntaxException {
return new Vec3d(readDouble(reader), readDouble(reader), readDouble(reader)); return new Vec3d(readDouble(reader), readDouble(reader), readDouble(reader));
} }
static Vec3d readVector(PacketByteBuf buffer) {
return new Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble());
}
static void writeVector(PacketByteBuf buffer, Vec3d vector) {
buffer.writeDouble(vector.x);
buffer.writeDouble(vector.y);
buffer.writeDouble(vector.z);
}
static boolean readBoolean(StringReader reader) throws CommandSyntaxException { static boolean readBoolean(StringReader reader) throws CommandSyntaxException {
reader.expect(' '); reader.expect(' ');
return reader.readBoolean(); return reader.readBoolean();
} }
static <T> Optional<T> readOptional(StringReader reader, ReaderFunc<T> readFunc) throws CommandSyntaxException {
if (reader.canRead()) {
return Optional.ofNullable(readFunc.read(reader));
}
return Optional.empty();
}
static double readDouble(StringReader reader) throws CommandSyntaxException { static double readDouble(StringReader reader) throws CommandSyntaxException {
reader.expect(' '); reader.expect(' ');
return reader.readDouble(); return reader.readDouble();
} }
static float readFloat(StringReader reader) throws CommandSyntaxException { static float readFloat(StringReader reader) throws CommandSyntaxException {
reader.expect(' '); reader.expect(' ');
return reader.readFloat(); return reader.readFloat();
} }
static int readInt(StringReader reader) throws CommandSyntaxException {
reader.expect(' ');
return reader.readInt();
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
static <T extends ParticleEffect> ParticleEffect.Factory<T> of(CommandReader<T> commandReader, PacketReader<T> packetReader) { static <T extends ParticleEffect> ParticleEffect.Factory<T> of(CommandReader<T> commandReader, PacketReader<T> packetReader) {
return new ParticleEffect.Factory<>() { return new ParticleEffect.Factory<>() {
@ -56,6 +80,10 @@ public interface ParticleFactoryHelper {
}; };
} }
interface ReaderFunc<T> {
T read(StringReader reader) throws CommandSyntaxException;
}
interface CommandReader<T extends ParticleEffect> { interface CommandReader<T extends ParticleEffect> {
T read(ParticleType<T> type, StringReader reader) throws CommandSyntaxException; T read(ParticleType<T> type, StringReader reader) throws CommandSyntaxException;
} }

View file

@ -15,26 +15,24 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
public class SphereParticleEffect implements ParticleEffect { public record SphereParticleEffect (
ParticleType<? extends SphereParticleEffect> type,
Vector3f color,
float alpha,
float radius,
Vec3d offset
) implements ParticleEffect {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static final Factory<SphereParticleEffect> FACTORY = ParticleFactoryHelper.of(SphereParticleEffect::new, SphereParticleEffect::new); public static final Factory<SphereParticleEffect> FACTORY = ParticleFactoryHelper.of(SphereParticleEffect::new, SphereParticleEffect::new);
private static final Vec3d DEFAULT_OFFSET = new Vec3d(0, 0.5, 0); private static final Vec3d DEFAULT_OFFSET = new Vec3d(0, 0.5, 0);
private final Vector3f color;
private final float alpha;
private final float radius;
private Vec3d offset = Vec3d.ZERO;
private final ParticleType<? extends SphereParticleEffect> type;
protected SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, StringReader reader) throws CommandSyntaxException { protected SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, StringReader reader) throws CommandSyntaxException {
this(type, AbstractDustParticleEffect.readColor(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readVector(reader)); this(type, AbstractDustParticleEffect.readColor(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readFloat(reader), ParticleFactoryHelper.readVector(reader));
} }
protected SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, PacketByteBuf buf) { protected SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, PacketByteBuf buf) {
this(type, AbstractDustParticleEffect.readColor(buf), buf.readFloat(), buf.readFloat()); this(type, buf.readVector3f(), buf.readFloat(), buf.readFloat(), ParticleFactoryHelper.readVector(buf));
} }
public SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, int tint, float alpha, float rad) { public SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, int tint, float alpha, float rad) {
@ -49,32 +47,8 @@ public class SphereParticleEffect implements ParticleEffect {
this(type, new Vector3f(Color.r(tint) * 255, Color.g(tint) * 255, Color.b(tint) * 255), alpha, rad, offset); this(type, new Vector3f(Color.r(tint) * 255, Color.g(tint) * 255, Color.b(tint) * 255), alpha, rad, offset);
} }
public SphereParticleEffect(ParticleType<? extends SphereParticleEffect> type, Vector3f color, float alpha, float rad, Vec3d offset) { public SphereParticleEffect withOffset(Vec3d offset) {
this.type = type; return new SphereParticleEffect(type, color, alpha, radius, offset);
this.color = color;
this.offset = offset;
this.alpha = alpha;
this.radius = rad;
}
public Vec3d getOffset() {
return offset;
}
public void setOffset(Vec3d offset) {
this.offset = offset;
}
public Vector3f getColor() {
return color;
}
public float getAlpha() {
return alpha;
}
public float getRadius() {
return radius;
} }
@Override @Override
@ -84,14 +58,10 @@ public class SphereParticleEffect implements ParticleEffect {
@Override @Override
public void write(PacketByteBuf buf) { public void write(PacketByteBuf buf) {
buf.writeFloat(color.x); buf.writeVector3f(color);
buf.writeFloat(color.y);
buf.writeFloat(color.z);
buf.writeFloat(alpha); buf.writeFloat(alpha);
buf.writeFloat(radius); buf.writeFloat(radius);
buf.writeDouble(offset.getX()); ParticleFactoryHelper.writeVector(buf, offset);
buf.writeDouble(offset.getY());
buf.writeDouble(offset.getZ());
} }
@Override @Override

View file

@ -28,7 +28,7 @@ public interface UParticles {
DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple()); DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple());
DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true)); DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true));
DefaultParticleType LIGHTNING_BOLT = register("lightning_bolt", FabricParticleTypes.simple(true)); ParticleType<LightningBoltParticleEffect> LIGHTNING_BOLT = register("lightning_bolt", FabricParticleTypes.complex(true, LightningBoltParticleEffect.FACTORY));
DefaultParticleType SHOCKWAVE = register("shockwave", FabricParticleTypes.simple(true)); DefaultParticleType SHOCKWAVE = register("shockwave", FabricParticleTypes.simple(true));
static <T extends ParticleType<?>> T register(String name, T type) { static <T extends ParticleType<?>> T register(String name, T type) {

View file

@ -0,0 +1,55 @@
package com.minelittlepony.unicopia.particle;
import org.jetbrains.annotations.Nullable;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class WeakTarget {
Vec3d fixedPosition;
private int targetId;
public WeakTarget(Vec3d fixedPosition, @Nullable Entity entity) {
this.fixedPosition = fixedPosition;
targetId = entity == null ? -1 : entity.getId();
}
public WeakTarget(PacketByteBuf buf) {
fixedPosition = ParticleFactoryHelper.readVector(buf);
targetId = buf.readInt();
}
public WeakTarget(StringReader reader) throws CommandSyntaxException {
this(ParticleFactoryHelper.readVector(reader), null);
}
public Vec3d getPosition(World world) {
if (targetId > -1) {
Entity e = world.getEntityById(targetId);
if (e != null) {
fixedPosition = e.getCameraPosVec(1);
} else {
targetId = -1;
}
}
return fixedPosition;
}
@Override
public String toString() {
if (targetId > -1) {
return "Moving(" + targetId + ")";
}
return "Fixed(" + fixedPosition + ")";
}
public void write(PacketByteBuf buf) {
ParticleFactoryHelper.writeVector(buf, fixedPosition);
buf.writeInt(targetId);
}
}

View file

@ -7,8 +7,8 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.block.ZapAppleLeavesBlock; import com.minelittlepony.unicopia.block.ZapAppleLeavesBlock;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.util.Tickable; import com.minelittlepony.unicopia.util.Tickable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -97,7 +97,7 @@ public class ZapAppleStageStore extends PersistentState implements Tickable {
public void triggerLightningStrike(BlockPos pos) { public void triggerLightningStrike(BlockPos pos) {
world.emitGameEvent(GameEvent.LIGHTNING_STRIKE, pos, GameEvent.Emitter.of(world.getBlockState(pos))); world.emitGameEvent(GameEvent.LIGHTNING_STRIKE, pos, GameEvent.Emitter.of(world.getBlockState(pos)));
ParticleUtils.spawnParticle(world, UParticles.LIGHTNING_BOLT, Vec3d.ofCenter(pos), Vec3d.ZERO); ParticleUtils.spawnParticle(world, LightningBoltParticleEffect.DEFAULT, Vec3d.ofCenter(pos), Vec3d.ZERO);
if (nextLightningEvent <= 0) { if (nextLightningEvent <= 0) {
StreamSupport.stream(BlockPos.iterateRandomly(world.random, 20, pos, 10).spliterator(), false) StreamSupport.stream(BlockPos.iterateRandomly(world.random, 20, pos, 10).spliterator(), false)