package lv.enes.mc.eris_alchemy.utils; import jakarta.annotation.Nonnull; import lombok.Getter; import lv.enes.mc.eris_alchemy.ErisAlchemyRegistry; import net.fabricmc.api.EnvType; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import org.quiltmc.loader.api.minecraft.MinecraftQuiltLoader; import org.quiltmc.qsl.networking.api.PacketByteBufs; import org.quiltmc.qsl.networking.api.ServerPlayNetworking; import org.quiltmc.qsl.networking.api.client.ClientPlayNetworking; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.HashMap; import java.util.Map; public sealed abstract class SyncedValue { private final static Map>> values = new HashMap<>(); private final long id; private boolean changed = true; @Getter private E value; public SyncedValue(E value) { this(genId(), value); } public SyncedValue(long id, E value) { this.id = id; this.value = value; values.put(this.id, new WeakReference<>(this)); } protected abstract @Nonnull E read(FriendlyByteBuf buf); protected abstract void write(FriendlyByteBuf buf, @Nonnull E value); public void serialize(FriendlyByteBuf buf) { buf.writeLongLE(id); write(buf, value); } public void setValue(E value) { this.value = value; this.changed = true; } public void syncIfChanged(Collection players) { if (!changed) { return; } var buf = PacketByteBufs.create(); serialize(buf); ServerPlayNetworking.send(players, ErisAlchemyRegistry.NetworkingConstants.UPDATE_SYNCED_VALUE, buf); changed = false; } private void readData(FriendlyByteBuf buf) { this.changed = false; this.value = read(buf); } private static long nextId = 0; private static long genId() { return nextId++; } static { if (MinecraftQuiltLoader.getEnvironmentType() == EnvType.CLIENT) { ClientPlayNetworking.registerGlobalReceiver( ErisAlchemyRegistry.NetworkingConstants.UPDATE_SYNCED_VALUE, (client, handler, buf, responseSender) -> { var id = buf.readLongLE(); var ref = values.get(id); var holder = ref == null ? null : ref.get(); if (holder != null) { holder.readData(buf); } } ); } } public static final class SyncedDouble extends SyncedValue { public SyncedDouble(double value) { super(value); } public SyncedDouble(long id, double value) { super(id, value); } public static SyncedDouble deserialize(FriendlyByteBuf buf) { var id = buf.readLongLE(); var value = buf.readDoubleLE(); return new SyncedDouble(id, value); } @Nonnull @Override protected Double read(FriendlyByteBuf buf) { return buf.readDoubleLE(); } @Override protected void write(FriendlyByteBuf buf, @Nonnull Double value) { buf.writeDoubleLE(value); } } }