diff --git a/gradle.properties b/gradle.properties index ff2ed4b0..846fc1cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.19.2 yarn_mappings=1.19.2+build.28 loader_version=0.14.10 -mod_version = 1.4.0 +mod_version = 1.4.1 maven_group = com.github.clevernucleus archives_base_name = dataattributes diff --git a/src/main/java/com/github/clevernucleus/dataattributes/DataAttributes.java b/src/main/java/com/github/clevernucleus/dataattributes/DataAttributes.java index 3c510b75..1ff694c3 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/DataAttributes.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/DataAttributes.java @@ -24,12 +24,10 @@ import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributes; -import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import net.minecraft.resource.ResourceType; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; public class DataAttributes implements ModInitializer { @@ -42,22 +40,13 @@ public class DataAttributes implements ModInitializer { private static void loginQueryStart(ServerLoginNetworkHandler handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer) { PacketByteBuf buf = PacketByteBufs.create(); - NbtCompound tag = new NbtCompound(); - DataAttributes.MANAGER.toNbt(tag); - buf.writeNbt(tag); + final byte[] bytes = DataAttributes.MANAGER.getCurrentData(); + buf.writeByteArray(bytes); sender.sendPacket(HANDSHAKE, buf); } private static void loginQueryResponse(MinecraftServer server, ServerLoginNetworkHandler handler, boolean understood, PacketByteBuf buf, LoginSynchronizer synchronizer, PacketSender responseSender) { - if(understood) { - byte[] verClient = buf.readByteArray(); - - if(verClient[0] != DataAttributes.semVer[0] || verClient[1] != DataAttributes.semVer[1]) { - handler.disconnect(Text.literal("Disconnected: version mismatch. Client has version " + verClient + ". Server has version " + DataAttributes.version + ".")); - } - } else { - handler.disconnect(Text.literal("Disconnected: network communication issue.")); - } + // Does doing nothing here make us compatible with Velocity plugin? } private static void refreshAttributes(final Entity entity) { diff --git a/src/main/java/com/github/clevernucleus/dataattributes/DataAttributesClient.java b/src/main/java/com/github/clevernucleus/dataattributes/DataAttributesClient.java index 3ee63b89..56be1c9a 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/DataAttributesClient.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/DataAttributesClient.java @@ -16,18 +16,15 @@ import net.minecraft.client.network.ClientLoginNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.world.ClientWorld; -import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; public class DataAttributesClient implements ClientModInitializer { private static CompletableFuture loginQueryReceived(MinecraftClient client, ClientLoginNetworkHandler handler, PacketByteBuf buf, Consumer>> listenerAdder) { - NbtCompound tag = buf.readNbt(); +final byte[] bytes = buf.readByteArray(); client.execute(() -> { - if(tag != null) { - DataAttributes.MANAGER.fromNbt(tag); - DataAttributes.MANAGER.apply(); - } + DataAttributes.MANAGER.readFromData(bytes); + DataAttributes.MANAGER.apply(); }); PacketByteBuf bufOut = PacketByteBufs.create(); @@ -37,14 +34,12 @@ private static CompletableFuture loginQueryReceived(MinecraftClie } private static void updateReceived(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - NbtCompound tag = buf.readNbt(); + final byte[] bytes = buf.readByteArray(); final int updateFlag = buf.readInt(); client.execute(() -> { - if(tag != null) { - DataAttributes.MANAGER.fromNbt(tag); - DataAttributes.MANAGER.apply(); - } + DataAttributes.MANAGER.readFromData(bytes); + DataAttributes.MANAGER.apply(); ClientWorld world = client.world; diff --git a/src/main/java/com/github/clevernucleus/dataattributes/impl/AttributeManager.java b/src/main/java/com/github/clevernucleus/dataattributes/impl/AttributeManager.java index 65027767..a1359180 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/impl/AttributeManager.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/impl/AttributeManager.java @@ -3,12 +3,17 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import java.util.zip.DataFormatException; +import java.util.zip.Deflater; +import java.util.zip.Inflater; import org.slf4j.Logger; @@ -23,6 +28,7 @@ import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.logging.LogUtils; import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener; @@ -32,6 +38,8 @@ import net.minecraft.entity.attribute.DefaultAttributeRegistry; import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.StringNbtReader; +import net.minecraft.nbt.visitor.StringNbtWriter; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; @@ -49,6 +57,7 @@ public final class AttributeManager implements SimpleResourceReloadListener entityAttributeData = ImmutableMap.of(); private Map entityTypeData = ImmutableMap.of(); public Map, DefaultAttributeContainer> containers = ImmutableMap.of(); + private byte[] currentData; protected static class Wrapper { public final Map entityAttributeData; @@ -248,11 +257,9 @@ private static void loadEntityTypes(ResourceManager manager, Map entityType) { - return this.containers.getOrDefault(entityType, DefaultAttributeRegistry.get(entityType)); - } - - public void toNbt(NbtCompound tag) { + private void generateCurrentData() { + StringNbtWriter writer = new StringNbtWriter(); + NbtCompound nbt = new NbtCompound(); NbtCompound entityAttributeNbt = new NbtCompound(); NbtCompound entityTypeNbt = new NbtCompound(); @@ -268,14 +275,60 @@ public void toNbt(NbtCompound tag) { entityTypeNbt.put(key.toString(), entry); }); - tag.put("Attributes", entityAttributeNbt); - tag.put("EntityTypes", entityTypeNbt); + nbt.put("Attributes", entityAttributeNbt); + nbt.put("EntityTypes", entityTypeNbt); + + String snbt = writer.apply(nbt); + byte[] bytes; + + try { + bytes = snbt.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + bytes = new byte[] {(byte)0}; + } + + Deflater deflater = new Deflater(); + deflater.setInput(bytes); + deflater.finish(); + + byte[] compressed = new byte[8192]; + int size = deflater.deflate(compressed); + deflater.end(); + this.currentData = Arrays.copyOf(compressed, size); + } + + public byte[] getCurrentData() { + if(this.currentData == null) return new byte[] {(byte)0}; + return this.currentData; } - public void fromNbt(NbtCompound tag) { - if(tag.contains("Attributes")) { + + public void readFromData(byte[] data) { + Inflater inflater = new Inflater(); + inflater.setInput(data); + + byte[] cache = new byte[8192]; + int size; + try { + size = inflater.inflate(cache); + } catch (DataFormatException e) { + size = 1; + } + + inflater.end(); + byte[] uncompressed = Arrays.copyOf(cache, size); + String snbt = new String(uncompressed); + NbtCompound nbt; + + try { + nbt = StringNbtReader.parse(snbt); + } catch (CommandSyntaxException e) { + nbt = new NbtCompound(); + } + + if(nbt.contains("Attributes")) { ImmutableMap.Builder builder = ImmutableMap.builder(); - NbtCompound nbtCompound = tag.getCompound("Attributes"); + NbtCompound nbtCompound = nbt.getCompound("Attributes"); nbtCompound.getKeys().forEach(key -> { NbtCompound entry = nbtCompound.getCompound(key); EntityAttributeData entityAttributeData = new EntityAttributeData(); @@ -286,9 +339,9 @@ public void fromNbt(NbtCompound tag) { this.entityAttributeData = builder.build(); } - if(tag.contains("EntityTypes")) { + if(nbt.contains("EntityTypes")) { ImmutableMap.Builder builder = ImmutableMap.builder(); - NbtCompound nbtCompound = tag.getCompound("EntityTypes"); + NbtCompound nbtCompound = nbt.getCompound("EntityTypes"); nbtCompound.getKeys().forEach(key -> { NbtCompound entry = nbtCompound.getCompound(key); EntityTypeData entityTypeData = new EntityTypeData(); @@ -300,6 +353,10 @@ public void fromNbt(NbtCompound tag) { } } + public DefaultAttributeContainer getContainer(EntityType entityType) { + return this.containers.getOrDefault(entityType, DefaultAttributeRegistry.get(entityType)); + } + public void apply() { MutableRegistryImpl.unregister(Registry.ATTRIBUTE); @@ -370,6 +427,7 @@ public CompletableFuture apply(AttributeManager.Wrapper data, ResourceMana data.entityTypeData.forEach(entityTypeData::put); this.entityTypeData = entityTypeData.build(); + this.generateCurrentData(); this.apply(); }, executor); } diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/LevelPropertiesMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/LevelPropertiesMixin.java index 8b153b5e..ebdd8285 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mixin/LevelPropertiesMixin.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/LevelPropertiesMixin.java @@ -22,7 +22,7 @@ import net.minecraft.world.level.storage.SaveVersionInfo; @Mixin(LevelProperties.class) -abstract class LevelPropertiesMixin implements MutableIntFlag { +abstract class LevelPropertiesMixin implements MutableWorldPropertiesMixin { @Unique private int data_updateFlag; diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/LivingEntityMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/LivingEntityMixin.java index 38dc46da..4ce3d493 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mixin/LivingEntityMixin.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/LivingEntityMixin.java @@ -16,6 +16,7 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.AttributeContainer; import net.minecraft.world.World; +import net.minecraft.world.WorldProperties; @Mixin(value = LivingEntity.class, priority = 999) abstract class LivingEntityMixin { @@ -27,10 +28,16 @@ abstract class LivingEntityMixin { @Unique private int data_updateFlag; + private int data_checkedUpdateFlag(World world) { + WorldProperties worldProperties = world.getLevelProperties(); + if(!(worldProperties instanceof MutableIntFlag)) return 0; + return ((MutableIntFlag)worldProperties).getUpdateFlag(); + } + @Inject(method = "", at = @At("TAIL")) private void data_init(EntityType entityType, World world, CallbackInfo ci) { this.attributes = new AttributeContainer(DataAttributes.MANAGER.getContainer(entityType)); - this.data_updateFlag = ((MutableIntFlag)world.getLevelProperties()).getUpdateFlag(); + this.data_updateFlag = this.data_checkedUpdateFlag(world); LivingEntity livingEntity = (LivingEntity)(Object)this; ((MutableAttributeContainer)livingEntity.getAttributes()).setLivingEntity(livingEntity); livingEntity.setHealth(livingEntity.getMaxHealth()); @@ -39,7 +46,7 @@ private void data_init(EntityType entityType, World worl @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;tickActiveItemStack()V")) private void data_tick(CallbackInfo ci) { LivingEntity livingEntity = (LivingEntity)(Object)this; - final int updateFlag = ((MutableIntFlag)livingEntity.world.getLevelProperties()).getUpdateFlag(); + final int updateFlag = this.data_checkedUpdateFlag(livingEntity.world); if(this.data_updateFlag != updateFlag) { AttributeContainer container = livingEntity.getAttributes(); diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/MutableWorldPropertiesMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/MutableWorldPropertiesMixin.java new file mode 100644 index 00000000..db524d4c --- /dev/null +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/MutableWorldPropertiesMixin.java @@ -0,0 +1,10 @@ +package com.github.clevernucleus.dataattributes.mixin; + +import org.spongepowered.asm.mixin.Mixin; + +import com.github.clevernucleus.dataattributes.mutable.MutableIntFlag; + +import net.minecraft.world.MutableWorldProperties; + +@Mixin(MutableWorldProperties.class) +public interface MutableWorldPropertiesMixin extends MutableIntFlag {} diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/ReloadCommandMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/ReloadCommandMixin.java index 13d06a99..fdcbad9d 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mixin/ReloadCommandMixin.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/ReloadCommandMixin.java @@ -14,7 +14,6 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ReloadCommand; @@ -41,9 +40,8 @@ private static void data_tryReloadDataPacks(Collection dataPacks, Server mutableUpdateFlag.setUpdateFlag(updateFlag2); PacketByteBuf buf = PacketByteBufs.create(); - NbtCompound tag = new NbtCompound(); - DataAttributes.MANAGER.toNbt(tag); - buf.writeNbt(tag); + final byte[] bytes = DataAttributes.MANAGER.getCurrentData(); + buf.writeByteArray(bytes); buf.writeInt(mutableUpdateFlag.getUpdateFlag()); PlayerLookup.all(server).forEach(player -> ServerPlayNetworking.send(player, DataAttributes.RELOAD, buf)); } diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/UnmodifiableLevelPropertiesMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/UnmodifiableLevelPropertiesMixin.java index 7b9e631d..23608257 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mixin/UnmodifiableLevelPropertiesMixin.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/UnmodifiableLevelPropertiesMixin.java @@ -10,7 +10,7 @@ import net.minecraft.world.level.UnmodifiableLevelProperties; @Mixin(UnmodifiableLevelProperties.class) -abstract class UnmodifiableLevelPropertiesMixin implements MutableIntFlag { +abstract class UnmodifiableLevelPropertiesMixin implements MutableWorldPropertiesMixin { @Final @Shadow diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mixin/client/ClientWorldPropertiesMixin.java b/src/main/java/com/github/clevernucleus/dataattributes/mixin/client/ClientWorldPropertiesMixin.java index b914f5f7..c88ff953 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mixin/client/ClientWorldPropertiesMixin.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mixin/client/ClientWorldPropertiesMixin.java @@ -3,12 +3,12 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; -import com.github.clevernucleus.dataattributes.mutable.MutableIntFlag; +import com.github.clevernucleus.dataattributes.mixin.MutableWorldPropertiesMixin; import net.minecraft.client.world.ClientWorld; @Mixin(ClientWorld.Properties.class) -abstract class ClientWorldPropertiesMixin implements MutableIntFlag { +abstract class ClientWorldPropertiesMixin implements MutableWorldPropertiesMixin { @Unique private int data_updateFlag; diff --git a/src/main/java/com/github/clevernucleus/dataattributes/mutable/MutableIntFlag.java b/src/main/java/com/github/clevernucleus/dataattributes/mutable/MutableIntFlag.java index 9af83003..bc8b3926 100644 --- a/src/main/java/com/github/clevernucleus/dataattributes/mutable/MutableIntFlag.java +++ b/src/main/java/com/github/clevernucleus/dataattributes/mutable/MutableIntFlag.java @@ -1,6 +1,6 @@ package com.github.clevernucleus.dataattributes.mutable; public interface MutableIntFlag { - void setUpdateFlag(int flag); - int getUpdateFlag(); + default void setUpdateFlag(int flag) {} + default int getUpdateFlag() { return 0; } } diff --git a/src/main/resources/dataattributes.mixins.json b/src/main/resources/dataattributes.mixins.json index bdf3d693..a0021f57 100644 --- a/src/main/resources/dataattributes.mixins.json +++ b/src/main/resources/dataattributes.mixins.json @@ -15,6 +15,7 @@ "PlayerEntityMixin", "MobEntityMixin", "ServerPlayerEntityMixin", + "MutableWorldPropertiesMixin", "LevelPropertiesMixin", "UnmodifiableLevelPropertiesMixin", "GameJoinS2CPacketMixin",