mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Add spiral particle (wip)
This commit is contained in:
parent
1545210efa
commit
03f4b4004e
8 changed files with 180 additions and 15 deletions
|
@ -22,6 +22,7 @@ import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle;
|
|||
import com.minelittlepony.unicopia.client.particle.RaindropsParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.ShockwaveParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.SphereParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.SpiralParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.WindParticle;
|
||||
import com.minelittlepony.unicopia.client.render.*;
|
||||
import com.minelittlepony.unicopia.client.render.entity.*;
|
||||
|
@ -80,6 +81,7 @@ public interface URenderers {
|
|||
ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.FOOTPRINT, createFactory(FootprintParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.SPIRAL, createFactory(SpiralParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_TRAIL, RainbowTrailParticle::new);
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.WIND, WindParticle::new);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package com.minelittlepony.unicopia.client.particle;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.particle.SpiralParticleEffect;
|
||||
|
||||
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.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class SpiralParticle extends NoRenderParticle {
|
||||
|
||||
private final SpiralParticleEffect parameters;
|
||||
|
||||
@Nullable
|
||||
private final Particle particle;
|
||||
|
||||
private float scale;
|
||||
|
||||
public SpiralParticle(SpiralParticleEffect 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 * (random.nextFloat() * 0.5f + 0.5f) * 2.0f;
|
||||
setMaxAge(3);
|
||||
scale(0.125F);
|
||||
this.parameters = parameters;
|
||||
this.collidesWithWorld = false;
|
||||
this.particle = MinecraftClient.getInstance().particleManager.addParticle(parameters.effect(), x, y, z, velocityX, velocityY, velocityZ);
|
||||
this.particle.setMaxAge(1000);
|
||||
this.gravityStrength = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Particle scale(float scale) {
|
||||
this.scale *= scale;
|
||||
super.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 (particle == null || !particle.isAlive()) {
|
||||
markDead();
|
||||
}
|
||||
|
||||
super.tick();
|
||||
|
||||
Vec3d target = parameters.centerPoint().getPosition(world);
|
||||
Vec3d pos = new Vec3d(x, y, z);
|
||||
|
||||
if (scale * 1.5F < 0.5F) {
|
||||
scale(1.5F);
|
||||
}
|
||||
|
||||
double distance = pos.distanceTo(target);
|
||||
if (distance > 0) {
|
||||
age = 0;
|
||||
}
|
||||
|
||||
Vec3d radial = target.subtract(pos).normalize();
|
||||
Vec3d tangent = radial.rotateY(MathHelper.HALF_PI).multiply(parameters.angularVelocity() * 0.9F);
|
||||
Vec3d motion = radial.multiply(parameters.angularVelocity() * 0.1F).add(tangent);
|
||||
move(motion.x, motion.y, motion.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ", Angular Velocity " + parameters.angularVelocity() + ", Target (" + parameters.centerPoint() + ") Sub-Particle (" + particle + ")";
|
||||
}
|
||||
}
|
|
@ -26,10 +26,7 @@ public record FollowingParticleEffect (
|
|||
this(type,
|
||||
new WeakTarget(reader),
|
||||
ParticleFactoryHelper.readFloat(reader),
|
||||
ParticleFactoryHelper.readOptional(reader, r -> {
|
||||
r.expect(' ');
|
||||
return ParticleFactoryHelper.read(r);
|
||||
}));
|
||||
ParticleFactoryHelper.readOptional(reader, r -> ParticleFactoryHelper.read(r)));
|
||||
}
|
||||
|
||||
protected FollowingParticleEffect(ParticleType<FollowingParticleEffect> type, PacketByteBuf buf) {
|
||||
|
|
|
@ -14,17 +14,11 @@ import net.minecraft.registry.Registries;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public interface ParticleFactoryHelper {
|
||||
@SuppressWarnings("deprecation")
|
||||
PacketCodec<ParticleEffect> PARTICLE_EFFECT_CODEC = new PacketCodec<>(
|
||||
buf -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ParticleType<ParticleEffect> type = (ParticleType<ParticleEffect>)Registries.PARTICLE_TYPE.get(buf.readInt());
|
||||
return type.getParametersFactory().read(type, buf);
|
||||
},
|
||||
(buf, effect) -> {
|
||||
buf.writeInt(Registries.PARTICLE_TYPE.getRawId(effect.getType()));
|
||||
effect.write(buf);
|
||||
}
|
||||
@SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
|
||||
PacketCodec<ParticleEffect> PARTICLE_EFFECT_CODEC = PacketCodec.ofRegistry(Registries.PARTICLE_TYPE).andThen(
|
||||
(buf, type) -> type.getParametersFactory().read((ParticleType) type, buf),
|
||||
ParticleEffect::getType,
|
||||
(buf, effect) -> effect.write(buf)
|
||||
);
|
||||
PacketCodec<Optional<ParticleEffect>> OPTIONAL_PARTICLE_EFFECT_CODEC = PARTICLE_EFFECT_CODEC.asOptional();
|
||||
PacketCodec<Vec3d> VECTOR_CODEC = new PacketCodec<>(
|
||||
|
@ -39,6 +33,7 @@ public interface ParticleFactoryHelper {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends ParticleEffect> T read(StringReader reader) throws CommandSyntaxException {
|
||||
reader.expect(' ');
|
||||
return (T)ParticleEffectArgumentType.readParameters(reader, Registries.PARTICLE_TYPE.getReadOnlyWrapper());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
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 SpiralParticleEffect(
|
||||
WeakTarget centerPoint,
|
||||
float angularVelocity,
|
||||
ParticleEffect effect
|
||||
) implements ParticleEffect {
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final Factory<SpiralParticleEffect> FACTORY = ParticleFactoryHelper.of(SpiralParticleEffect::new, SpiralParticleEffect::new);
|
||||
|
||||
protected SpiralParticleEffect(ParticleType<SpiralParticleEffect> type, StringReader reader) throws CommandSyntaxException {
|
||||
this(new WeakTarget(reader),
|
||||
ParticleFactoryHelper.readFloat(reader),
|
||||
ParticleFactoryHelper.read(reader)
|
||||
);
|
||||
}
|
||||
|
||||
protected SpiralParticleEffect(ParticleType<SpiralParticleEffect> type, PacketByteBuf buf) {
|
||||
this(new WeakTarget(buf),
|
||||
buf.readFloat(),
|
||||
ParticleFactoryHelper.PARTICLE_EFFECT_CODEC.read(buf)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleType<?> getType() {
|
||||
return UParticles.SPIRAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PacketByteBuf buffer) {
|
||||
centerPoint.write(buffer);
|
||||
buffer.writeFloat(angularVelocity);
|
||||
ParticleFactoryHelper.PARTICLE_EFFECT_CODEC.write(buffer, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ public interface UParticles {
|
|||
ParticleType<SphereParticleEffect> DISK = register("disk", FabricParticleTypes.complex(true, SphereParticleEffect.FACTORY));
|
||||
|
||||
ParticleType<FollowingParticleEffect> HEALTH_DRAIN = register("health_drain", FabricParticleTypes.complex(true, FollowingParticleEffect.FACTORY));
|
||||
ParticleType<SpiralParticleEffect> SPIRAL = register("spiral", FabricParticleTypes.complex(true, SpiralParticleEffect.FACTORY));
|
||||
|
||||
DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple());
|
||||
DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true));
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
package com.minelittlepony.unicopia.util.serialization;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public record PacketCodec<T>(PacketByteBuf.PacketReader<T> reader, PacketByteBuf.PacketWriter<T> writer) {
|
||||
public static final PacketCodec<Float> FLOAT = new PacketCodec<>(PacketByteBuf::readFloat, PacketByteBuf::writeFloat);
|
||||
public static final PacketCodec<Integer> INT = new PacketCodec<>(PacketByteBuf::readInt, PacketByteBuf::writeInt);
|
||||
public static final PacketCodec<Byte> BYTE = new PacketCodec<>(PacketByteBuf::readByte, (b, v) -> b.writeByte(v));
|
||||
public static final PacketCodec<Long> LONG = new PacketCodec<>(PacketByteBuf::readLong, PacketByteBuf::writeLong);
|
||||
public static final PacketCodec<String> STRING = new PacketCodec<>(PacketByteBuf::readString, PacketByteBuf::writeString);
|
||||
|
||||
public static final PacketCodec<Identifier> IDENTIFIER = STRING.xMap(Identifier::new, Identifier::toString);
|
||||
|
||||
public static final <T> PacketCodec<T> ofRegistry(Registry<T> registry) {
|
||||
return INT.xMap(registry::get, registry::getRawId);
|
||||
}
|
||||
|
||||
public static final <T extends Enum<T>> PacketCodec<T> ofEnum(Supplier<T[]> valuesGetter) {
|
||||
final T[] values = valuesGetter.get();
|
||||
return INT.xMap(id -> values[MathHelper.clamp(id, 0, values.length)], Enum::ordinal);
|
||||
}
|
||||
|
||||
public T read(PacketByteBuf buf) {
|
||||
return reader().apply(buf);
|
||||
|
@ -17,4 +40,17 @@ public record PacketCodec<T>(PacketByteBuf.PacketReader<T> reader, PacketByteBuf
|
|||
public PacketCodec<Optional<T>> asOptional() {
|
||||
return new PacketCodec<>(buf -> buf.readOptional(reader), (buf, v) -> buf.writeOptional(v, writer));
|
||||
}
|
||||
|
||||
public <X> PacketCodec<X> xMap(Function<T, X> to, Function<X, T> from) {
|
||||
return new PacketCodec<>(buf -> to.apply(reader.apply(buf)), (buf, v) -> writer.accept(buf, from.apply(v)));
|
||||
}
|
||||
|
||||
public <X> PacketCodec<X> andThen(BiFunction<PacketByteBuf, T, X> to, Function<X, T> from, BiConsumer<PacketByteBuf, X> write) {
|
||||
return new PacketCodec<>(buf -> {
|
||||
return to.apply(buf, reader.apply(buf));
|
||||
}, (buf, v) -> {
|
||||
writer.accept(buf, from.apply(v));
|
||||
write.accept(buf, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
5
src/main/resources/assets/unicopia/particles/spiral.json
Normal file
5
src/main/resources/assets/unicopia/particles/spiral.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"textures": [
|
||||
"minecraft:heart"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue