109 lines
4.4 KiB
Java
109 lines
4.4 KiB
Java
package at.petrak.hexcasting.common.network;
|
|
|
|
import at.petrak.hexcasting.api.casting.ParticleSpray;
|
|
import at.petrak.hexcasting.api.pigment.FrozenPigment;
|
|
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
|
|
import io.netty.buffer.ByteBuf;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.network.FriendlyByteBuf;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
import java.util.Random;
|
|
|
|
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
|
|
|
/**
|
|
* Sent server->client to spray particles everywhere.
|
|
*/
|
|
public record MsgCastParticleAck(ParticleSpray spray, FrozenPigment colorizer) implements IMessage {
|
|
public static final ResourceLocation ID = modLoc("cprtcl");
|
|
|
|
@Override
|
|
public ResourceLocation getFabricId() {
|
|
return ID;
|
|
}
|
|
|
|
public static MsgCastParticleAck deserialize(ByteBuf buffer) {
|
|
var buf = new FriendlyByteBuf(buffer);
|
|
var posX = buf.readDouble();
|
|
var posY = buf.readDouble();
|
|
var posZ = buf.readDouble();
|
|
var velX = buf.readDouble();
|
|
var velY = buf.readDouble();
|
|
var velZ = buf.readDouble();
|
|
var fuzziness = buf.readDouble();
|
|
var spread = buf.readDouble();
|
|
var count = buf.readInt();
|
|
var tag = buf.readAnySizeNbt();
|
|
var colorizer = FrozenPigment.fromNBT(tag);
|
|
return new MsgCastParticleAck(
|
|
new ParticleSpray(new Vec3(posX, posY, posZ), new Vec3(velX, velY, velZ), fuzziness, spread, count),
|
|
colorizer);
|
|
}
|
|
|
|
@Override
|
|
public void serialize(FriendlyByteBuf buf) {
|
|
buf.writeDouble(this.spray.getPos().x);
|
|
buf.writeDouble(this.spray.getPos().y);
|
|
buf.writeDouble(this.spray.getPos().z);
|
|
buf.writeDouble(this.spray.getVel().x);
|
|
buf.writeDouble(this.spray.getVel().y);
|
|
buf.writeDouble(this.spray.getVel().z);
|
|
buf.writeDouble(this.spray.getFuzziness());
|
|
buf.writeDouble(this.spray.getSpread());
|
|
buf.writeInt(this.spray.getCount());
|
|
buf.writeNbt(this.colorizer.serializeToNBT());
|
|
}
|
|
|
|
|
|
private static final Random RANDOM = new Random();
|
|
|
|
// https://math.stackexchange.com/questions/44689/how-to-find-a-random-axis-or-unit-vector-in-3d
|
|
private static Vec3 randomInCircle(double maxTh) {
|
|
var th = RANDOM.nextDouble(0.0, maxTh + 0.001);
|
|
var z = RANDOM.nextDouble(-1.0, 1.0);
|
|
return new Vec3(Math.sqrt(1.0 - z * z) * Math.cos(th), Math.sqrt(1.0 - z * z) * Math.sin(th), z);
|
|
}
|
|
|
|
public static void handle(MsgCastParticleAck msg) {
|
|
Minecraft.getInstance().execute(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
var colProvider = msg.colorizer().getColorProvider();
|
|
for (int i = 0; i < msg.spray().getCount(); i++) {
|
|
// For the colors, pick any random time to get a mix of colors
|
|
var color = colProvider.getColor(RANDOM.nextFloat() * 256f, Vec3.ZERO);
|
|
|
|
var offset = randomInCircle(Mth.TWO_PI).normalize()
|
|
.scale(RANDOM.nextFloat() * msg.spray().getFuzziness() / 2);
|
|
var pos = msg.spray().getPos().add(offset);
|
|
|
|
var phi = Math.acos(1.0 - RANDOM.nextDouble() * (1.0 - Math.cos(msg.spray().getSpread())));
|
|
var theta = Math.PI * 2.0 * RANDOM.nextDouble();
|
|
var v = msg.spray().getVel().normalize();
|
|
// pick any old vector to get a vector normal to v with
|
|
Vec3 k;
|
|
if (v.x == 0.0 && v.y == 0.0) {
|
|
// oops, pick a *different* normal
|
|
k = new Vec3(1.0, 0.0, 0.0);
|
|
} else {
|
|
k = v.cross(new Vec3(0.0, 0.0, 1.0));
|
|
}
|
|
var velUnlen = v.scale(Math.cos(phi))
|
|
.add(k.scale(Math.sin(phi) * Math.cos(theta)))
|
|
.add(v.cross(k).scale(Math.sin(phi) * Math.sin(theta)));
|
|
var vel = velUnlen.scale(msg.spray().getVel().length() / 20);
|
|
|
|
Minecraft.getInstance().level.addParticle(
|
|
new ConjureParticleOptions(color),
|
|
pos.x, pos.y, pos.z,
|
|
vel.x, vel.y, vel.z
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|