diff --git a/src/main/java/io/wispforest/owo/serialization/CodecUtils.java b/src/main/java/io/wispforest/owo/serialization/CodecUtils.java index 4a2ddd9d..ae75e445 100644 --- a/src/main/java/io/wispforest/owo/serialization/CodecUtils.java +++ b/src/main/java/io/wispforest/owo/serialization/CodecUtils.java @@ -271,6 +271,8 @@ public T decode(B buf) { ? SerializationContext.attributes(RegistriesAttribute.of(registryByteBuf.getRegistryManager())) : SerializationContext.empty(); + ctx = ctx.withAttributes(MinecraftSerializationAttributes.NETWORK); + return endec.decode(ctx, ByteBufDeserializer.of(buf)); } @@ -280,6 +282,8 @@ public void encode(B buf, T value) { ? SerializationContext.attributes(RegistriesAttribute.of(registryByteBuf.getRegistryManager())) : SerializationContext.empty(); + ctx = ctx.withAttributes(MinecraftSerializationAttributes.NETWORK); + endec.encode(ctx, ByteBufSerializer.of(buf), value); } }; diff --git a/src/main/java/io/wispforest/owo/serialization/MinecraftSerializationAttributes.java b/src/main/java/io/wispforest/owo/serialization/MinecraftSerializationAttributes.java new file mode 100644 index 00000000..596e7df6 --- /dev/null +++ b/src/main/java/io/wispforest/owo/serialization/MinecraftSerializationAttributes.java @@ -0,0 +1,14 @@ +package io.wispforest.owo.serialization; + +import io.wispforest.endec.SerializationAttribute; + +public final class MinecraftSerializationAttributes { + private MinecraftSerializationAttributes() { } + + /** + * This format will be sent over the network. + *

+ * Registries and block states can be represented as integer IDs. + */ + public static final SerializationAttribute.Marker NETWORK = SerializationAttribute.marker("network"); +} diff --git a/src/main/java/io/wispforest/owo/serialization/endec/MinecraftEndecs.java b/src/main/java/io/wispforest/owo/serialization/endec/MinecraftEndecs.java index 96df755f..c4b8eb76 100644 --- a/src/main/java/io/wispforest/owo/serialization/endec/MinecraftEndecs.java +++ b/src/main/java/io/wispforest/owo/serialization/endec/MinecraftEndecs.java @@ -1,14 +1,20 @@ package io.wispforest.owo.serialization.endec; import com.mojang.datafixers.util.Function3; -import io.wispforest.endec.Endec; -import io.wispforest.endec.SerializationAttributes; +import io.wispforest.endec.*; import io.wispforest.endec.impl.ReflectiveEndecBuilder; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.CodecUtils; +import io.wispforest.owo.serialization.MinecraftSerializationAttributes; +import net.fabricmc.fabric.api.event.registry.RegistryAttribute; +import net.fabricmc.fabric.api.event.registry.RegistryAttributeHolder; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.tag.TagKey; @@ -87,6 +93,11 @@ private MinecraftEndecs() {} : BlockHitResult.createMissed(pos, side, blockPos) ); + public static final Endec BLOCK_STATE = Endec.ifAttr( + MinecraftSerializationAttributes.NETWORK, Endec.VAR_INT.xmap(Block.STATE_IDS::get, Block.STATE_IDS::getRawId) + ) + .orElse(CodecUtils.toEndec(BlockState.CODEC)); + // --- Constructors for MC types --- public static ReflectiveEndecBuilder addDefaults(ReflectiveEndecBuilder builder) { @@ -105,11 +116,39 @@ public static ReflectiveEndecBuilder addDefaults(ReflectiveEndecBuilder builder) builder.register(BLOCK_HIT_RESULT, BlockHitResult.class); + builder.register(ofRegistry(Registries.ITEM), Item.class) + .register(ofRegistry(Registries.BLOCK), Block.class); + + builder.register(BLOCK_STATE, BlockState.class); + return builder; } public static Endec ofRegistry(Registry registry) { - return IDENTIFIER.xmap(registry::get, registry::getId); + Endec idEndec = IDENTIFIER.xmap(registry::get, registry::getId); + Endec rawIdEndec = Endec.VAR_INT.xmap(registry::get, registry::getRawId); + + return new Endec<>() { + @Override + public void encode(SerializationContext ctx, Serializer serializer, T value) { + if (RegistryAttributeHolder.get(registry).hasAttribute(RegistryAttribute.SYNCED) + && ctx.hasAttribute(MinecraftSerializationAttributes.NETWORK)) { + rawIdEndec.encode(ctx, serializer, value); + } else { + idEndec.encode(ctx, serializer, value); + } + } + + @Override + public T decode(SerializationContext ctx, Deserializer deserializer) { + if (RegistryAttributeHolder.get(registry).hasAttribute(RegistryAttribute.SYNCED) + && ctx.hasAttribute(MinecraftSerializationAttributes.NETWORK)) { + return rawIdEndec.decode(ctx, deserializer); + } else { + return idEndec.decode(ctx, deserializer); + } + } + }; } public static Endec> unprefixedTagKey(RegistryKey> registry) { diff --git a/src/testmod/java/io/wispforest/uwu/network/DispatchedSubclassThree.java b/src/testmod/java/io/wispforest/uwu/network/DispatchedSubclassThree.java new file mode 100644 index 00000000..a722b3ba --- /dev/null +++ b/src/testmod/java/io/wispforest/uwu/network/DispatchedSubclassThree.java @@ -0,0 +1,12 @@ +package io.wispforest.uwu.network; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.Item; + +public record DispatchedSubclassThree(Item item, Block block, BlockState state) implements DispatchedInterface { + @Override + public String getName() { + return "three"; + } +} diff --git a/src/testmod/java/io/wispforest/uwu/network/UwuNetworkExample.java b/src/testmod/java/io/wispforest/uwu/network/UwuNetworkExample.java index a8a82d25..5999dd59 100644 --- a/src/testmod/java/io/wispforest/uwu/network/UwuNetworkExample.java +++ b/src/testmod/java/io/wispforest/uwu/network/UwuNetworkExample.java @@ -1,7 +1,6 @@ package io.wispforest.uwu.network; import io.wispforest.endec.impl.RecordEndec; -import io.wispforest.endec.impl.ReflectiveEndecBuilder; import io.wispforest.owo.network.OwoNetChannel; import io.wispforest.endec.Endec; import io.wispforest.endec.StructEndec; @@ -9,9 +8,13 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.block.Blocks; +import net.minecraft.block.HorizontalFacingBlock; import net.minecraft.client.option.KeyBinding; +import net.minecraft.item.Items; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; import org.lwjgl.glfw.GLFW; import java.util.HashMap; @@ -28,6 +31,7 @@ public static void init() { REGISTRY.put("one", RecordEndec.create(CHANNEL.builder(), DispatchedSubclassOne.class)); REGISTRY.put("two", RecordEndec.create(CHANNEL.builder(), DispatchedSubclassTwo.class)); + REGISTRY.put("three", RecordEndec.create(CHANNEL.builder(), DispatchedSubclassThree.class)); CHANNEL.registerClientbound(StringPacket.class, (message, access) -> { access.player().sendMessage(Text.of(message.value()), false); @@ -67,6 +71,11 @@ public static void init() { CHANNEL.clientHandle().send(new MaldingPacket(new DispatchedSubclassOne("base"))); CHANNEL.clientHandle().send(new MaldingPacket(new DispatchedSubclassTwo(20))); + CHANNEL.clientHandle().send(new MaldingPacket(new DispatchedSubclassThree( + Items.ACACIA_BOAT, + Blocks.DRAGON_EGG, + Blocks.OAK_STAIRS.getDefaultState().with(HorizontalFacingBlock.FACING, Direction.EAST) + ))); CHANNEL.clientHandle().send(new NullablePacket(null, null)); CHANNEL.clientHandle().send(new NullablePacket("Weeee", null));