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 extends Registry> 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));