diff --git a/build.gradle b/build.gradle index 3cb849fc..eb17d037 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ //file:noinspection GradlePackageVersionRange plugins { - id 'fabric-loom' version '1.4-SNAPSHOT' + id 'fabric-loom' version '1.5-SNAPSHOT' id 'maven-publish' } @@ -119,7 +119,7 @@ loom { } dependencies { - modLocalRuntime("me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}") +// modLocalRuntime("me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}") modCompileOnly("me.shedaniel:RoughlyEnoughItems-default-plugin:${project.rei_version}") modCompileOnly("me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}") diff --git a/gradle.properties b/gradle.properties index abc6029a..111fa03c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,16 +2,16 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_base_version=1.20.3 -minecraft_version=1.20.3 -yarn_mappings=1.20.3+build.1 -loader_version=0.15.0 +minecraft_base_version=1.20.5 +minecraft_version=24w07a +yarn_mappings=24w07a+build.4 +loader_version=0.15.7 # Mod Properties mod_version=0.12.5 maven_group=io.wispforest archives_base_name=owo-lib # Dependencies -fabric_version=0.91.1+1.20.3 +fabric_version=0.96.3+1.20.5 # https://maven.shedaniel.me/me/shedaniel/RoughlyEnoughItems-fabric/ rei_version=14.0.688 diff --git a/src/main/java/io/wispforest/owo/client/screens/ScreenInternals.java b/src/main/java/io/wispforest/owo/client/screens/ScreenInternals.java index 46c610b8..8ae123ac 100644 --- a/src/main/java/io/wispforest/owo/client/screens/ScreenInternals.java +++ b/src/main/java/io/wispforest/owo/client/screens/ScreenInternals.java @@ -1,38 +1,70 @@ package io.wispforest.owo.client.screens; import io.wispforest.owo.Owo; +import io.wispforest.owo.serialization.Endec; +import io.wispforest.owo.serialization.endec.BuiltInEndecs; +import io.wispforest.owo.serialization.endec.StructEndecBuilder; import io.wispforest.owo.util.pond.OwoScreenHandlerExtension; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; @ApiStatus.Internal public class ScreenInternals { - public static final Identifier LOCAL_PACKET = new Identifier("owo", "local_packet"); public static final Identifier SYNC_PROPERTIES = new Identifier("owo", "sync_screen_handler_properties"); public static void init() { - ServerPlayNetworking.registerGlobalReceiver(LOCAL_PACKET, (server, player, handler, buf, responseSender) -> { - buf.retain(); - server.execute(() -> { - var screenHandler = player.currentScreenHandler; + PayloadTypeRegistry.playS2C().register(LocalPacket.ID, LocalPacket.ENDEC.packetCodec()); + PayloadTypeRegistry.playC2S().register(LocalPacket.ID, LocalPacket.ENDEC.packetCodec()); + PayloadTypeRegistry.playS2C().register(SyncPropertiesPacket.ID, SyncPropertiesPacket.ENDEC.packetCodec()); - if (screenHandler == null) { - Owo.LOGGER.error("Received local packet for null ScreenHandler"); - return; - } + ServerPlayNetworking.registerGlobalReceiver(LocalPacket.ID, (payload, context) -> { + var screenHandler = context.player().currentScreenHandler; - ((OwoScreenHandlerExtension) screenHandler).owo$handlePacket(buf, false); - buf.release(); - }); + if (screenHandler == null) { + Owo.LOGGER.error("Received local packet for null ScreenHandler"); + return; + } + + ((OwoScreenHandlerExtension) screenHandler).owo$handlePacket(payload, false); }); } + public record LocalPacket(int packetId, PacketByteBuf payload) implements CustomPayload { + public static final Id ID = new Id<>(new Identifier("owo", "local_packet")); + public static final Endec ENDEC = StructEndecBuilder.of( + Endec.VAR_INT.fieldOf("packetId", LocalPacket::packetId), + BuiltInEndecs.PACKET_BYTE_BUF.fieldOf("payload", LocalPacket::payload), + LocalPacket::new + ); + + @Override + public Id getId() { + return ID; + } + } + + public record SyncPropertiesPacket(PacketByteBuf payload) implements CustomPayload { + public static final Id ID = new Id<>(SYNC_PROPERTIES); + public static final Endec ENDEC = StructEndecBuilder.of( + BuiltInEndecs.PACKET_BYTE_BUF.fieldOf("payload", SyncPropertiesPacket::payload), + SyncPropertiesPacket::new + ); + + @Override + public Id getId() { + return ID; + } + } + @Environment(EnvType.CLIENT) public static class Client { public static void init() { @@ -41,38 +73,26 @@ public static void init() { ((OwoScreenHandlerExtension) handled.getScreenHandler()).owo$attachToPlayer(client.player); }); - ClientPlayNetworking.registerGlobalReceiver(LOCAL_PACKET, (client, handler, buf, responseSender) -> { - if (client.player == null) return; - - buf.retain(); - client.execute(() -> { - var screenHandler = client.player.currentScreenHandler; + ClientPlayNetworking.registerGlobalReceiver(LocalPacket.ID, (payload, context) -> { + var screenHandler = context.player().currentScreenHandler; - if (screenHandler == null) { - Owo.LOGGER.error("Received local packet for null ScreenHandler"); - return; - } + if (screenHandler == null) { + Owo.LOGGER.error("Received local packet for null ScreenHandler"); + return; + } - ((OwoScreenHandlerExtension) screenHandler).owo$handlePacket(buf, true); - buf.release(); - }); + ((OwoScreenHandlerExtension) screenHandler).owo$handlePacket(payload, true); }); - ClientPlayNetworking.registerGlobalReceiver(SYNC_PROPERTIES, (client, handler, buf, responseSender) -> { - buf.retain(); - - client.execute(() -> { - if (client.player == null) return; - - if (client.player.currentScreenHandler == null) { - Owo.LOGGER.error("Received sync properties packet for null ScreenHandler"); - return; - } + ClientPlayNetworking.registerGlobalReceiver(SyncPropertiesPacket.ID, (payload, context) -> { + var screenHandler = context.player().currentScreenHandler; - ((OwoScreenHandlerExtension) client.player.currentScreenHandler).owo$readPropertySync(buf); + if (screenHandler == null) { + Owo.LOGGER.error("Received sync properties packet for null ScreenHandler"); + return; + } - buf.release(); - }); + ((OwoScreenHandlerExtension) screenHandler).owo$readPropertySync(payload); }); } } diff --git a/src/main/java/io/wispforest/owo/command/debug/DumpdataCommand.java b/src/main/java/io/wispforest/owo/command/debug/DumpdataCommand.java index 7f6d9fb0..afd6690b 100644 --- a/src/main/java/io/wispforest/owo/command/debug/DumpdataCommand.java +++ b/src/main/java/io/wispforest/owo/command/debug/DumpdataCommand.java @@ -144,7 +144,7 @@ private static int executeBlock(CommandContext context, Nbt final var blockEntity = player.getWorld().getBlockEntity(pos); if (blockEntity != null) { feedback(source, TextOps.withFormatting("Block Entity NBT" + formatPath(path) + ": ", Formatting.GRAY) - .append(NbtHelper.toPrettyPrintedText(getPath(blockEntity.createNbt(), path)))); + .append(NbtHelper.toPrettyPrintedText(getPath(blockEntity.createNbt(player.getRegistryManager()), path)))); } else { feedback(source, TextOps.withFormatting("No block entity", Formatting.GRAY)); } diff --git a/src/main/java/io/wispforest/owo/compat/rei/OwoReiPlugin.java b/src/main/java/io/wispforest/owo/compat/rei/OwoReiPlugin.java index 6f3702ea..b9ccc81a 100644 --- a/src/main/java/io/wispforest/owo/compat/rei/OwoReiPlugin.java +++ b/src/main/java/io/wispforest/owo/compat/rei/OwoReiPlugin.java @@ -140,19 +140,19 @@ private static void renderOverlay(Screen screen, Runnable renderFunction) { final var time = System.currentTimeMillis(); float scale = .75f + (float) (Math.sin(time / 500d) * .5f); - modelView.push(); + modelView.pushMatrix(); modelView.translate(screen.width / 2f - scale / 2f * screen.width, screen.height / 2f - scale / 2f * screen.height, 0); modelView.scale(scale, scale, 1f); modelView.translate((float) (Math.sin(time / 1000d) * .75f) * screen.width, (float) (Math.sin(time / 500d) * .75f) * screen.height, 0); modelView.translate(screen.width / 2f, screen.height / 2f, 0); - modelView.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((float) (time / 25d % 360d))); + modelView.rotate(RotationAxis.POSITIVE_Z.rotationDegrees((float) (time / 25d % 360d))); modelView.translate(screen.width / -2f, screen.height / -2f, 0); for (int i = 0; i < 20; i++) { - modelView.push(); + modelView.pushMatrix(); modelView.translate(screen.width / 2f, screen.height / 2f, 0); - modelView.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(i * 18)); + modelView.rotate(RotationAxis.POSITIVE_Z.rotationDegrees(i * 18)); modelView.translate(screen.width / -2f, screen.height / -2f, 0); RenderSystem.applyModelViewMatrix(); @@ -160,10 +160,10 @@ private static void renderOverlay(Screen screen, Runnable renderFunction) { renderFunction.run(); GlStateManager._enableScissorTest(); ScissorStack.pop(); - modelView.pop(); + modelView.popMatrix(); } - modelView.pop(); + modelView.popMatrix(); RenderSystem.applyModelViewMatrix(); } else { ScissorStack.pushDirect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); diff --git a/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java b/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java index b6f6597b..940a1113 100644 --- a/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java +++ b/src/main/java/io/wispforest/owo/config/ConfigSynchronizer.java @@ -4,20 +4,21 @@ import io.wispforest.owo.Owo; import io.wispforest.owo.mixin.ServerCommonNetworkHandlerAccessor; import io.wispforest.owo.ops.TextOps; +import io.wispforest.owo.serialization.Endec; +import io.wispforest.owo.serialization.endec.BuiltInEndecs; +import io.wispforest.owo.serialization.endec.StructEndecBuilder; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.*; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.ClientConnection; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; @@ -32,6 +33,7 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.function.BiConsumer; +import java.util.function.Function; public class ConfigSynchronizer { @@ -72,78 +74,56 @@ static void register(ConfigWrapper config) { return getClientOptions(player, config.name()); } - private static void write(PacketByteBuf packet, Option.SyncMode targetMode) { - packet.writeVarInt(KNOWN_CONFIGS.size()); - - var configBuf = PacketByteBufs.create(); - var optionBuf = PacketByteBufs.create(); + private static ConfigSyncPacket toPacket(Option.SyncMode targetMode) { + Map configs = new HashMap<>(); KNOWN_CONFIGS.forEach((configName, config) -> { - packet.writeString(configName); - - configBuf.resetReaderIndex().resetWriterIndex(); - configBuf.writeVarInt((int) config.allOptions().values().stream().filter(option -> option.syncMode().ordinal() >= targetMode.ordinal()).count()); + var entry = new ConfigEntry(new HashMap<>()); config.allOptions().forEach((key, option) -> { if (option.syncMode().ordinal() < targetMode.ordinal()) return; - configBuf.writeString(key.asString()); - - optionBuf.resetReaderIndex().resetWriterIndex(); + PacketByteBuf optionBuf = PacketByteBufs.create(); option.write(optionBuf); - configBuf.writeVarInt(optionBuf.readableBytes()); - configBuf.writeBytes(optionBuf); + entry.options().put(key.asString(), optionBuf); }); - packet.writeVarInt(configBuf.readableBytes()); - packet.writeBytes(configBuf); + configs.put(configName, entry); }); + + return new ConfigSyncPacket(configs); } - private static void read(PacketByteBuf buf, BiConsumer, PacketByteBuf> optionConsumer) { - int configCount = buf.readVarInt(); - for (int i = 0; i < configCount; i++) { - var configName = buf.readString(); + private static void read(ConfigSyncPacket packet, BiConsumer, PacketByteBuf> optionConsumer) { + for (var configEntry : packet.configs().entrySet()) { + var configName = configEntry.getKey(); var config = KNOWN_CONFIGS.get(configName); if (config == null) { Owo.LOGGER.error("Received overrides for unknown config '{}', skipping", configName); - - // skip size of current config - buf.skipBytes(buf.readVarInt()); continue; } - // ignore size - buf.readVarInt(); - - int optionCount = buf.readVarInt(); - for (int j = 0; j < optionCount; j++) { - var optionKey = new Option.Key(buf.readString()); + for (var optionEntry : configEntry.getValue().options().entrySet()) { + var optionKey = new Option.Key(optionEntry.getKey()); var option = config.optionForKey(optionKey); if (option == null) { Owo.LOGGER.error("Received override for unknown option '{}' in config '{}', skipping", optionKey, configName); - - // skip size of current option - buf.skipBytes(buf.readVarInt()); continue; } - // ignore size - buf.readVarInt(); - - optionConsumer.accept(option, buf); + optionConsumer.accept(option, optionEntry.getValue()); } } } @Environment(EnvType.CLIENT) - private static void applyClient(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender sender) { + private static void applyClient(ConfigSyncPacket payload, ClientPlayNetworking.Context context) { Owo.LOGGER.info("Applying server overrides"); var mismatchedOptions = new HashMap, Object>(); - if (!(client.isIntegratedServerRunning() && client.getServer().isSingleplayer())) { - read(buf, (option, packetByteBuf) -> { + if (!(context.client().isIntegratedServerRunning() && context.client().getServer().isSingleplayer())) { + read(payload, (option, packetByteBuf) -> { var mismatchedValue = option.read(packetByteBuf); if (mismatchedValue != null) mismatchedOptions.put(option, mismatchedValue); }); @@ -174,48 +154,65 @@ private static void applyClient(MinecraftClient client, ClientPlayNetworkHandler errorMessage.append(TextOps.withFormatting("they require your client to be restarted\n", Formatting.GRAY)); errorMessage.append(TextOps.withFormatting("change them manually and restart if you want to join this server", Formatting.GRAY)); - handler.getConnection().disconnect(TextOps.concat(PREFIX, errorMessage)); + context.player().networkHandler.getConnection().disconnect(TextOps.concat(PREFIX, errorMessage)); return; } } Owo.LOGGER.info("Responding with client values"); - var packet = PacketByteBufs.create(); - write(packet, Option.SyncMode.INFORM_SERVER); - - sender.sendPacket(CONFIG_SYNC_CHANNEL, packet); + context.responseSender().sendPacket(toPacket(Option.SyncMode.INFORM_SERVER)); } - private static void applyServer(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender sender) { + private static void applyServer(ConfigSyncPacket payload, ServerPlayNetworking.Context context) { Owo.LOGGER.info("Receiving client config"); - var connection = ((ServerCommonNetworkHandlerAccessor) player.networkHandler).owo$getConnection(); + var connection = ((ServerCommonNetworkHandlerAccessor) context.player().networkHandler).owo$getConnection(); - read(buf, (option, optionBuf) -> { + read(payload, (option, optionBuf) -> { var config = CLIENT_OPTION_STORAGE.computeIfAbsent(connection, $ -> new HashMap<>()).computeIfAbsent(option.configName(), s -> new HashMap<>()); config.put(option.key(), optionBuf.read(option.endec())); }); } + private record ConfigSyncPacket(Map configs) implements CustomPayload { + public static final Id ID = new Id<>(CONFIG_SYNC_CHANNEL); + public static final Endec ENDEC = StructEndecBuilder.of( + Endec.map(Function.identity(), Function.identity(), ConfigEntry.ENDEC).fieldOf("configs", ConfigSyncPacket::configs), + ConfigSyncPacket::new + ); + + @Override + public Id getId() { + return ID; + } + } + + private record ConfigEntry(Map options) { + public static final Endec ENDEC = StructEndecBuilder.of( + Endec.map(Function.identity(), Function.identity(), BuiltInEndecs.PACKET_BYTE_BUF).fieldOf("options", ConfigEntry::options), + ConfigEntry::new + ); + } + static { + PayloadTypeRegistry.playS2C().register(ConfigSyncPacket.ID, ConfigSyncPacket.ENDEC.packetCodec()); + PayloadTypeRegistry.playC2S().register(ConfigSyncPacket.ID, ConfigSyncPacket.ENDEC.packetCodec()); + var earlyPhase = new Identifier("owo", "early"); ServerPlayConnectionEvents.JOIN.addPhaseOrdering(earlyPhase, Event.DEFAULT_PHASE); ServerPlayConnectionEvents.JOIN.register(earlyPhase, (handler, sender, server) -> { Owo.LOGGER.info("Sending server config values to client"); - var packet = PacketByteBufs.create(); - write(packet, Option.SyncMode.OVERRIDE_CLIENT); - - sender.sendPacket(CONFIG_SYNC_CHANNEL, packet); + sender.sendPacket(toPacket(Option.SyncMode.OVERRIDE_CLIENT)); }); if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - ClientPlayNetworking.registerGlobalReceiver(CONFIG_SYNC_CHANNEL, ConfigSynchronizer::applyClient); + ClientPlayNetworking.registerGlobalReceiver(ConfigSyncPacket.ID, ConfigSynchronizer::applyClient); ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> { KNOWN_CONFIGS.forEach((name, config) -> config.forEachOption(Option::reattach)); }); } - ServerPlayNetworking.registerGlobalReceiver(CONFIG_SYNC_CHANNEL, ConfigSynchronizer::applyServer); + ServerPlayNetworking.registerGlobalReceiver(ConfigSyncPacket.ID, ConfigSynchronizer::applyServer); } } diff --git a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java index 182c4a56..c6ada99b 100644 --- a/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java +++ b/src/main/java/io/wispforest/owo/itemgroup/json/WrapperGroup.java @@ -34,9 +34,9 @@ public WrapperGroup(ItemGroup parent, Identifier parentId, List ta int parentRawId = Registries.ITEM_GROUP.getRawId(parent); - ((SimpleRegistryAccessor) Registries.ITEM_GROUP).owo$getValueToEntry().remove(parent); - ((SimpleRegistryAccessor) Registries.ITEM_GROUP).owo$getEntryToLifecycle().remove(parent); - ((SimpleRegistry) Registries.ITEM_GROUP).set(parentRawId, RegistryKey.of(RegistryKeys.ITEM_GROUP, parentId), this, Lifecycle.stable()); + // TODO: set doesn't exist anymore. figure out what to do. +// ((SimpleRegistryAccessor) Registries.ITEM_GROUP).owo$getValueToEntry().remove(parent); +// ((SimpleRegistry) Registries.ITEM_GROUP).set(parentRawId, RegistryKey.of(RegistryKeys.ITEM_GROUP, parentId), this, Lifecycle.stable()); ((ItemGroupAccessor) this).owo$setDisplayName(parent.getDisplayName()); ((ItemGroupAccessor) this).owo$setColumn(parent.getColumn()); diff --git a/src/main/java/io/wispforest/owo/mixin/ScreenHandlerMixin.java b/src/main/java/io/wispforest/owo/mixin/ScreenHandlerMixin.java index 42fd680a..336435e2 100644 --- a/src/main/java/io/wispforest/owo/mixin/ScreenHandlerMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/ScreenHandlerMixin.java @@ -13,13 +13,13 @@ import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.screen.ScreenHandler; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -91,36 +91,37 @@ public void sendMessage(@NotNull R message) { } var buf = PacketByteBufs.create(); - buf.writeVarInt(messageData.id()); buf.write(messageData.endec(), message); + var packet = new ScreenInternals.LocalPacket(messageData.id(), buf); + if (messageData.clientbound()) { if (!(this.owo$player instanceof ServerPlayerEntity serverPlayer)) { throw new NetworkException("Tried to send clientbound message on the server"); } - ServerPlayNetworking.send(serverPlayer, ScreenInternals.LOCAL_PACKET, buf); + ServerPlayNetworking.send(serverPlayer, packet); } else { if (!this.owo$player.getWorld().isClient) { throw new NetworkException("Tried to send serverbound message on the client"); } - this.owo$sendToServer(ScreenInternals.LOCAL_PACKET, buf); + this.owo$sendToServer(packet); } } + @Unique @Environment(EnvType.CLIENT) - private void owo$sendToServer(Identifier channel, PacketByteBuf data) { - ClientPlayNetworking.send(channel, data); + private void owo$sendToServer(CustomPayload payload) { + ClientPlayNetworking.send(payload); } @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public void owo$handlePacket(PacketByteBuf buf, boolean clientbound) { - int id = buf.readVarInt(); - ScreenhandlerMessageData messageData = (clientbound ? this.owo$clientboundMessages : this.owo$serverboundMessages).get(id); + public void owo$handlePacket(ScreenInternals.LocalPacket packet, boolean clientbound) { + ScreenhandlerMessageData messageData = (clientbound ? this.owo$clientboundMessages : this.owo$serverboundMessages).get(packet.packetId()); - messageData.handler().accept(buf.read(messageData.endec())); + messageData.handler().accept(packet.payload().read(messageData.endec())); } @Override @@ -131,12 +132,12 @@ public SyncedProperty createProperty(Class clazz, Endec endec, T in } @Override - public void owo$readPropertySync(PacketByteBuf buf) { - int count = buf.readVarInt(); + public void owo$readPropertySync(ScreenInternals.SyncPropertiesPacket packet) { + int count = packet.payload().readVarInt(); for (int i = 0; i < count; i++) { - int idx = buf.readVarInt(); - this.owo$properties.get(idx).read(buf); + int idx = packet.payload().readVarInt(); + this.owo$properties.get(idx).read(packet.payload()); } } @@ -152,6 +153,7 @@ private void syncOnSendContentUpdates(CallbackInfo ci) { this.syncProperties(); } + @Unique private void syncProperties() { if (this.owo$player == null) return; if (!(this.owo$player instanceof ServerPlayerEntity player)) return; @@ -174,7 +176,7 @@ private void syncProperties() { prop.write(buf); } - ServerPlayNetworking.send(player, ScreenInternals.SYNC_PROPERTIES, buf); + ServerPlayNetworking.send(player, new ScreenInternals.SyncPropertiesPacket(buf)); } } diff --git a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java index 6a652da5..0cea7587 100644 --- a/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/recipe_remainders/RecipeManagerMixin.java @@ -9,6 +9,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.recipe.*; +import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.Util; @@ -27,7 +28,7 @@ public abstract class RecipeManagerMixin { @Inject(method = "deserialize", at = @At(value = "RETURN")) - private static void deserializeRecipeSpecificRemainders(Identifier id, JsonObject json, CallbackInfoReturnable> cir) { + private static void deserializeRecipeSpecificRemainders(Identifier id, JsonObject json, RegistryWrapper.WrapperLookup registryLookup, CallbackInfoReturnable> cir) { if (!json.has("owo:remainders")) return; var remainders = new HashMap(); diff --git a/src/main/java/io/wispforest/owo/mixin/ui/EntityRendererMixin.java b/src/main/java/io/wispforest/owo/mixin/ui/EntityRendererMixin.java index 54cadff0..e0626d3a 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/EntityRendererMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/EntityRendererMixin.java @@ -24,13 +24,13 @@ public class EntityRendererMixin { protected EntityRenderDispatcher dispatcher; @Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true) - private void cancelLabel(T entity, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + private void cancelLabel(T entity, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float tickDelta, CallbackInfo ci) { if (((OwoEntityRenderDispatcherExtension) this.dispatcher).owo$showNametag()) return; ci.cancel(); } @Inject(method = "renderLabelIfPresent", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;multiply(Lorg/joml/Quaternionf;)V", shift = At.Shift.AFTER)) - private void adjustLabelRotation(T entity, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + private void adjustLabelRotation(T entity, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float tickDelta, CallbackInfo ci) { if (!((OwoEntityRenderDispatcherExtension) this.dispatcher).owo$counterRotate()) return; matrices.multiply(new Quaternionf(this.dispatcher.getRotation()).invert()); diff --git a/src/main/java/io/wispforest/owo/mixin/ui/SimpleRegistryAccessor.java b/src/main/java/io/wispforest/owo/mixin/ui/SimpleRegistryAccessor.java index 8658c54e..a51860a5 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/SimpleRegistryAccessor.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/SimpleRegistryAccessor.java @@ -14,6 +14,4 @@ public interface SimpleRegistryAccessor { @Accessor("valueToEntry") Map> owo$getValueToEntry(); - @Accessor("entryToLifecycle") - Map owo$getEntryToLifecycle(); } diff --git a/src/main/java/io/wispforest/owo/mixin/ui/access/ClickableWidgetAccessor.java b/src/main/java/io/wispforest/owo/mixin/ui/access/ClickableWidgetAccessor.java index f66bf416..18d53f2f 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/access/ClickableWidgetAccessor.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/access/ClickableWidgetAccessor.java @@ -1,6 +1,6 @@ package io.wispforest.owo.mixin.ui.access; -import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.tooltip.TooltipState; import net.minecraft.client.gui.widget.ClickableWidget; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -21,5 +21,5 @@ public interface ClickableWidgetAccessor { void owo$setY(int y); @Accessor("tooltip") - Tooltip owo$getTooltip(); + TooltipState owo$getTooltip(); } diff --git a/src/main/java/io/wispforest/owo/mixin/ui/layers/MouseMixin.java b/src/main/java/io/wispforest/owo/mixin/ui/layers/MouseMixin.java index 300b7009..885fe4a5 100644 --- a/src/main/java/io/wispforest/owo/mixin/ui/layers/MouseMixin.java +++ b/src/main/java/io/wispforest/owo/mixin/ui/layers/MouseMixin.java @@ -14,7 +14,7 @@ public class MouseMixin { @Shadow private int activeButton; - @Inject(method = "method_1602", at = @At("HEAD"), cancellable = true) + @Inject(method = "method_55795", at = @At("HEAD"), cancellable = true) private void captureScreenMouseDrag(Screen screen, double mouseX, double mouseY, double deltaX, double deltaY, CallbackInfo ci) { boolean handled = false; for (var instance : Layers.getInstances(screen)) { diff --git a/src/main/java/io/wispforest/owo/network/OwoHandshake.java b/src/main/java/io/wispforest/owo/network/OwoHandshake.java index 69578d92..62a02ed7 100644 --- a/src/main/java/io/wispforest/owo/network/OwoHandshake.java +++ b/src/main/java/io/wispforest/owo/network/OwoHandshake.java @@ -7,6 +7,7 @@ import io.wispforest.owo.particles.systems.ParticleSystemController; import io.wispforest.owo.serialization.endec.BuiltInEndecs; import io.wispforest.owo.serialization.Endec; +import io.wispforest.owo.serialization.endec.StructEndecBuilder; import io.wispforest.owo.util.OwoFreezer; import io.wispforest.owo.util.ServicesFrozenException; import net.fabricmc.api.EnvType; @@ -14,14 +15,11 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.fabricmc.fabric.api.networking.v1.ServerConfigurationConnectionEvents; -import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking; +import net.fabricmc.fabric.api.networking.v1.*; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientConfigurationNetworkHandler; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerConfigurationNetworkHandler; import net.minecraft.text.MutableText; @@ -70,15 +68,18 @@ public static void requireHandshake() { } static { + PayloadTypeRegistry.configurationS2C().register(HandshakeRequest.ID, HandshakeRequest.ENDEC.packetCodec()); + PayloadTypeRegistry.configurationC2S().register(HandshakeResponse.ID, HandshakeResponse.ENDEC.packetCodec()); + ServerConfigurationConnectionEvents.CONFIGURE.register(OwoHandshake::configureStart); - ServerConfigurationNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncServer); + ServerConfigurationNetworking.registerGlobalReceiver(HandshakeResponse.ID, OwoHandshake::syncServer); if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { if (!ENABLED) { - ClientConfigurationNetworking.registerGlobalReceiver(OwoHandshake.OFF_CHANNEL_ID, (client, handler, buf, responseSender) -> {}); + ClientConfigurationNetworking.registerGlobalReceiver(HandshakeOff.ID, (payload, context) -> {}); } - ClientConfigurationNetworking.registerGlobalReceiver(OwoHandshake.CHANNEL_ID, OwoHandshake::syncClient); + ClientConfigurationNetworking.registerGlobalReceiver(HandshakeRequest.ID, OwoHandshake::syncClient); ClientConfigurationConnectionEvents.READY.register(OwoHandshake::handleReadyClient); ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> QUERY_RECEIVED = false); @@ -110,49 +111,39 @@ private static void configureStart(ServerConfigurationNetworkHandler handler, Mi return; } - var request = PacketByteBufs.create(); - writeHashes(request, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); - ServerConfigurationNetworking.send(handler, OwoHandshake.CHANNEL_ID, request); + var optionalChannels = formatHashes(OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); + ServerConfigurationNetworking.send(handler, new HandshakeRequest(optionalChannels)); Owo.LOGGER.info("[Handshake] Sending channel packet"); } @Environment(EnvType.CLIENT) - private static void syncClient(MinecraftClient client, ClientConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender sender) { + private static void syncClient(HandshakeRequest request, ClientConfigurationNetworking.Context context) { Owo.LOGGER.info("[Handshake] Sending client channels"); QUERY_RECEIVED = true; - if (buf.readableBytes() > 0) { - final var serverOptionalChannels = buf.read(CHANNEL_HASHES_ENDEC); - ((OwoClientConnectionExtension) ((ClientCommonNetworkHandlerAccessor) handler).getConnection()).owo$setChannelSet(filterOptionalServices(serverOptionalChannels, OwoNetChannel.REGISTERED_CHANNELS, OwoHandshake::hashChannel)); - } + // TODO: get the actual network handler here. +// ((OwoClientConnectionExtension) ((ClientCommonNetworkHandlerAccessor) MinecraftClient.getInstance().getNetworkHandler()).getConnection()).owo$setChannelSet(filterOptionalServices(request.optionalChannels(), OwoNetChannel.REGISTERED_CHANNELS, OwoHandshake::hashChannel)); - var response = PacketByteBufs.create(); - writeHashes(response, OwoNetChannel.REQUIRED_CHANNELS, OwoHandshake::hashChannel); - writeHashes(response, ParticleSystemController.REGISTERED_CONTROLLERS, OwoHandshake::hashController); - writeHashes(response, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); + var requiredChannels = formatHashes(OwoNetChannel.REQUIRED_CHANNELS, OwoHandshake::hashChannel); + var requiredControllers = formatHashes(ParticleSystemController.REGISTERED_CONTROLLERS, OwoHandshake::hashController); + var optionalChannels = formatHashes(OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel); - sender.sendPacket(CHANNEL_ID, response); + context.responseSender().sendPacket(new HandshakeResponse(requiredChannels, requiredControllers, optionalChannels)); } - private static void syncServer(MinecraftServer server, ServerConfigurationNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + private static void syncServer(HandshakeResponse response, ServerConfigurationNetworking.Context context) { Owo.LOGGER.info("[Handshake] Receiving client channels"); - final var clientChannels = buf.read(CHANNEL_HASHES_ENDEC); - final var clientParticleControllers = buf.read(CHANNEL_HASHES_ENDEC); - StringBuilder disconnectMessage = new StringBuilder(); - boolean isAllGood = verifyReceivedHashes("channels", clientChannels, OwoNetChannel.REQUIRED_CHANNELS, OwoHandshake::hashChannel, disconnectMessage); - isAllGood &= verifyReceivedHashes("controllers", clientParticleControllers, ParticleSystemController.REGISTERED_CONTROLLERS, OwoHandshake::hashController, disconnectMessage); + boolean isAllGood = verifyReceivedHashes("channels", response.requiredChannels(), OwoNetChannel.REQUIRED_CHANNELS, OwoHandshake::hashChannel, disconnectMessage); + isAllGood &= verifyReceivedHashes("controllers", response.requiredControllers(), ParticleSystemController.REGISTERED_CONTROLLERS, OwoHandshake::hashController, disconnectMessage); if (!isAllGood) { - handler.disconnect(TextOps.concat(PREFIX, Text.of(disconnectMessage.toString()))); + context.responseSender().disconnect(TextOps.concat(PREFIX, Text.of(disconnectMessage.toString()))); } - if (buf.readableBytes() > 0) { - final var clientOptionalChannels = buf.read(CHANNEL_HASHES_ENDEC); - ((OwoClientConnectionExtension) ((ServerCommonNetworkHandlerAccessor) handler).owo$getConnection()).owo$setChannelSet(filterOptionalServices(clientOptionalChannels, OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel)); - } + ((OwoClientConnectionExtension) ((ServerCommonNetworkHandlerAccessor) context.networkHandler()).owo$getConnection()).owo$setChannelSet(filterOptionalServices(response.optionalChannels(), OwoNetChannel.OPTIONAL_CHANNELS, OwoHandshake::hashChannel)); Owo.LOGGER.info("[Handshake] Handshake completed successfully"); } @@ -228,14 +219,14 @@ private static boolean verifyReceivedHashes(String serviceNamePlural, Map void writeHashes(PacketByteBuf buffer, Map values, ToIntFunction hashFunction) { + private static Map formatHashes(Map values, ToIntFunction hashFunction) { Map hashes = new HashMap<>(); for (var entry : values.entrySet()) { hashes.put(entry.getKey(), hashFunction.applyAsInt(entry.getValue())); } - buffer.write(CHANNEL_HASHES_ENDEC, hashes); + return hashes; } private static Pair, Set> findCollisions(Set first, Set second) { @@ -258,7 +249,7 @@ private static int hashChannel(OwoNetChannel channel) { for (var entry : channel.endecsByIndex.int2ObjectEntrySet()) { serializersHash += entry.getIntKey() * 31 + entry.getValue().getRecordClass().getName().hashCode(); } - return 31 * channel.packetId.hashCode() + serializersHash; + return 31 * channel.packetId.id().hashCode() + serializersHash; } private static int hashController(ParticleSystemController controller) { @@ -268,4 +259,43 @@ private static int hashController(ParticleSystemController controller) { } return 31 * controller.channelId.hashCode() + serializersHash; } + + public record HandshakeRequest(Map optionalChannels) implements CustomPayload { + public static Endec ENDEC = StructEndecBuilder.of( + CHANNEL_HASHES_ENDEC.fieldOf("optionalChannels", HandshakeRequest::optionalChannels), + HandshakeRequest::new + ); + public static Id ID = new Id<>(OwoHandshake.CHANNEL_ID); + + @Override + public Id getId() { + return ID; + } + } + + public record HandshakeOff() implements CustomPayload { + public static Id ID = new Id<>(OwoHandshake.OFF_CHANNEL_ID); + + @Override + public Id getId() { + return ID; + } + } + + private record HandshakeResponse(Map requiredChannels, + Map requiredControllers, + Map optionalChannels) implements CustomPayload { + public static Endec ENDEC = StructEndecBuilder.of( + CHANNEL_HASHES_ENDEC.fieldOf("requiredChannels", HandshakeResponse::requiredChannels), + CHANNEL_HASHES_ENDEC.fieldOf("requiredControllers", HandshakeResponse::requiredControllers), + CHANNEL_HASHES_ENDEC.fieldOf("optionalChannels", HandshakeResponse::optionalChannels), + HandshakeResponse::new + ); + public static Id ID = new Id<>(OwoHandshake.CHANNEL_ID); + + @Override + public Id getId() { + return ID; + } + } } diff --git a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java index 1d21362f..b45551f2 100644 --- a/src/main/java/io/wispforest/owo/network/OwoNetChannel.java +++ b/src/main/java/io/wispforest/owo/network/OwoNetChannel.java @@ -14,6 +14,7 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.api.FabricLoader; @@ -22,6 +23,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.ClientConnection; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; @@ -71,7 +73,7 @@ public class OwoNetChannel { private final Reference2IntMap> deferredClientEndecs = new Reference2IntOpenHashMap<>(); - final Identifier packetId; + final CustomPayload.Id packetId; private final String ownerClassName; final boolean required; @@ -115,7 +117,7 @@ private OwoNetChannel(Identifier id, String ownerClassName, boolean required) { deferredClientEndecs.defaultReturnValue(-1); - this.packetId = id; + this.packetId = new CustomPayload.Id<>(id); this.ownerClassName = ownerClassName; this.required = required; @@ -124,17 +126,30 @@ private OwoNetChannel(Identifier id, String ownerClassName, boolean required) { OwoHandshake.requireHandshake(); } - ServerPlayNetworking.registerGlobalReceiver(packetId, (server, player, handler, buf, responseSender) -> { - int handlerIndex = buf.readVarInt(); - final Record message = buf.read(endecsByIndex.get(handlerIndex).endec); - server.execute(() -> serverHandlers.get(handlerIndex).handle(message, new ServerAccess(player))); + Endec serverEndec = Endec.dispatched( + index -> this.endecsByIndex.get(index).endec, + msg -> this.endecsByClass.get(msg.getClass()).serverHandlerIndex, + Endec.VAR_INT + ) + .xmap(x -> new MessagePayload(packetId, x), x -> x.message); + + Endec clientEndec = Endec.dispatched( + index -> this.endecsByIndex.get(-index).endec, + msg -> this.endecsByClass.get(msg.getClass()).clientHandlerIndex, + Endec.VAR_INT + ) + .xmap(x -> new MessagePayload(packetId, x), x -> x.message); + + PayloadTypeRegistry.playC2S().register(packetId, serverEndec.packetCodec()); + PayloadTypeRegistry.playS2C().register(packetId, clientEndec.packetCodec()); + + ServerPlayNetworking.registerGlobalReceiver(packetId, (payload, context) -> { + serverHandlers.get(endecsByClass.get(payload.message().getClass()).serverHandlerIndex).handle(payload.message, new ServerAccess(context.player())); }); if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - ClientPlayNetworking.registerGlobalReceiver(packetId, (client, handler, buf, responseSender) -> { - int handlerIndex = buf.readVarInt(); - final Record message = buf.read(endecsByIndex.get(-handlerIndex).endec); - client.execute(() -> clientHandlers.get(handlerIndex).handle(message, new ClientAccess(handler))); + ClientPlayNetworking.registerGlobalReceiver(packetId, (payload, context) -> { + clientHandlers.get(endecsByClass.get(payload.message.getClass()).clientHandlerIndex).handle(payload.message, new ClientAccess(context.player().networkHandler)); }); } @@ -438,7 +453,7 @@ public class ClientHandle { * @see #send(Record[]) */ public void send(R message) { - ClientPlayNetworking.send(OwoNetChannel.this.packetId, OwoNetChannel.this.encode(message, EnvType.SERVER)); + ClientPlayNetworking.send(new MessagePayload(packetId, message)); } /** @@ -465,7 +480,7 @@ public class ServerHandle { * @see #send(Record[]) */ public void send(R message) { - this.targets.forEach(player -> ServerPlayNetworking.send(player, OwoNetChannel.this.packetId, OwoNetChannel.this.encode(message, EnvType.CLIENT))); + this.targets.forEach(player -> ServerPlayNetworking.send(player, new MessagePayload(packetId, message))); this.targets = null; } @@ -480,7 +495,7 @@ public void send(R message) { public final void send(R... messages) { this.targets.forEach(player -> { for (R message : messages) { - ServerPlayNetworking.send(player, OwoNetChannel.this.packetId, OwoNetChannel.this.encode(message, EnvType.CLIENT)); + ServerPlayNetworking.send(player, new MessagePayload(packetId, message)); } }); this.targets = null; @@ -580,5 +595,12 @@ public Class getRecordClass(){ return this.recordClass; } } + + record MessagePayload(CustomPayload.Id id, Record message) implements CustomPayload { + @Override + public Id getId() { + return id; + } + } } diff --git a/src/main/java/io/wispforest/owo/offline/OfflineDataLookup.java b/src/main/java/io/wispforest/owo/offline/OfflineDataLookup.java index 099de921..cc44ae65 100644 --- a/src/main/java/io/wispforest/owo/offline/OfflineDataLookup.java +++ b/src/main/java/io/wispforest/owo/offline/OfflineDataLookup.java @@ -5,7 +5,7 @@ import net.minecraft.datafixer.Schemas; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NbtTagSizeTracker; +import net.minecraft.nbt.NbtSizeTracker; import net.minecraft.util.Util; import net.minecraft.util.WorldSavePath; import org.jetbrains.annotations.Nullable; @@ -61,7 +61,7 @@ public static void put(UUID player, NbtCompound nbt) { try { Path savedPlayersPath = Owo.currentServer().getSavePath(WorldSavePath.PLAYERDATA); Path savedDataPath = savedPlayersPath.resolve(player.toString() + ".dat"); - NbtCompound rawNbt = NbtIo.readCompressed(savedDataPath, NbtTagSizeTracker.ofUnlimitedBytes()); + NbtCompound rawNbt = NbtIo.readCompressed(savedDataPath, NbtSizeTracker.ofUnlimitedBytes()); int dataVersion = rawNbt.contains("DataVersion", 3) ? rawNbt.getInt("DataVersion") : -1; return DataFixTypes.PLAYER.update(Schemas.getFixer(), rawNbt, dataVersion); } catch (IOException e) { diff --git a/src/main/java/io/wispforest/owo/ops/ItemOps.java b/src/main/java/io/wispforest/owo/ops/ItemOps.java index 219cc478..036cf5a9 100644 --- a/src/main/java/io/wispforest/owo/ops/ItemOps.java +++ b/src/main/java/io/wispforest/owo/ops/ItemOps.java @@ -22,7 +22,7 @@ private ItemOps() { * @return {@code true} if addition can stack onto base */ public static boolean canStack(ItemStack base, ItemStack addition) { - return base.isEmpty() || (canIncreaseBy(base, addition.getCount()) && ItemStack.canCombine(base, addition)); + return base.isEmpty() || (canIncreaseBy(base, addition.getCount()) && ItemStack.areItemsAndNbtEqual(base, addition)); } /** diff --git a/src/main/java/io/wispforest/owo/ops/WorldOps.java b/src/main/java/io/wispforest/owo/ops/WorldOps.java index 6588cda7..b474bbf6 100644 --- a/src/main/java/io/wispforest/owo/ops/WorldOps.java +++ b/src/main/java/io/wispforest/owo/ops/WorldOps.java @@ -118,7 +118,7 @@ public static void teleportToWorld(ServerPlayerEntity player, ServerWorld target player.addExperience(0); player.getStatusEffects().forEach(effect -> { - player.networkHandler.sendPacket(new EntityStatusEffectS2CPacket(player.getId(), effect)); + player.networkHandler.sendPacket(new EntityStatusEffectS2CPacket(player.getId(), effect, false)); }); } diff --git a/src/main/java/io/wispforest/owo/particles/systems/ParticleSystemController.java b/src/main/java/io/wispforest/owo/particles/systems/ParticleSystemController.java index 46f56bb8..ef1f08d8 100644 --- a/src/main/java/io/wispforest/owo/particles/systems/ParticleSystemController.java +++ b/src/main/java/io/wispforest/owo/particles/systems/ParticleSystemController.java @@ -1,10 +1,11 @@ package io.wispforest.owo.particles.systems; -import io.wispforest.owo.Owo; import io.wispforest.owo.network.NetworkException; import io.wispforest.owo.network.OwoHandshake; import io.wispforest.owo.serialization.Endec; +import io.wispforest.owo.serialization.endec.BuiltInEndecs; import io.wispforest.owo.serialization.endec.ReflectiveEndecBuilder; +import io.wispforest.owo.serialization.endec.StructEndecBuilder; import io.wispforest.owo.util.OwoFreezer; import io.wispforest.owo.util.ReflectionUtils; import io.wispforest.owo.util.VectorSerializer; @@ -14,17 +15,17 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import org.jetbrains.annotations.ApiStatus; import java.util.HashMap; @@ -48,6 +49,7 @@ public class ParticleSystemController { public final Int2ObjectMap> systemsByIndex = new Int2ObjectOpenHashMap<>(); public final Identifier channelId; + private final CustomPayload.Id payloadId; private int maxIndex = 0; private final String ownerClassName; @@ -69,13 +71,31 @@ public ParticleSystemController(Identifier channelId) { } this.channelId = channelId; + this.payloadId = new CustomPayload.Id<>(channelId); this.ownerClassName = ReflectionUtils.getCallingClassName(2); + var instanceEndec = Endec., Integer>dispatched( + index -> { + @SuppressWarnings("unchecked") + var system = (ParticleSystem) systemsByIndex.get(index); + return system.endec.xmap(x -> new ParticleSystemInstance<>(system, x), x -> x.data); + }, + instance -> instance.system.index, + Endec.VAR_INT + ); + var endec = StructEndecBuilder.of( + BuiltInEndecs.VEC3D.fieldOf("pos", ParticleSystemPayload::pos), + instanceEndec.fieldOf("instance", ParticleSystemPayload::instance), + (pos, instance) -> new ParticleSystemPayload(payloadId, pos, instance) + ); + + PayloadTypeRegistry.playS2C().register(payloadId, endec.packetCodec()); + OwoHandshake.enable(); OwoHandshake.requireHandshake(); if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - ClientPlayNetworking.registerGlobalReceiver(channelId, new Client()::handler); + ClientPlayNetworking.registerGlobalReceiver(payloadId, new Client()::handler); } REGISTERED_CONTROLLERS.put(channelId, this); @@ -133,13 +153,10 @@ public ParticleSystem registerDeferred(Class dataClass) { } void sendPacket(ParticleSystem particleSystem, ServerWorld world, Vec3d pos, T data) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeVarInt(particleSystem.index); - VectorSerializer.write(buf, pos); - buf.write(particleSystem.endec, data); + ParticleSystemPayload payload = new ParticleSystemPayload(payloadId, pos, new ParticleSystemInstance<>(particleSystem, data)); for (var player : PlayerLookup.tracking(world, BlockPos.ofFloored(pos))) { - ServerPlayNetworking.send(player, channelId, buf); + ServerPlayNetworking.send(player, payload); } } @@ -161,22 +178,23 @@ private void verify() { }); } - @Environment(EnvType.CLIENT) - private class Client { - @SuppressWarnings("unchecked") - private void handler(MinecraftClient client, ClientPlayNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) { - int index = buf.readVarInt(); - - Vec3d pos = VectorSerializer.read(buf); + private record ParticleSystemInstance(ParticleSystem system, T data) { + public void execute(World world, Vec3d pos) { + system.handler.executeParticleSystem(world, pos, data); + } + } - if (maxIndex <= index || index < 0) { - Owo.LOGGER.warn("Received unknown particle system index {} on channel {}", index, channelId); - return; - } + private record ParticleSystemPayload(CustomPayload.Id id, Vec3d pos, ParticleSystemInstance instance) implements CustomPayload { + @Override + public Id getId() { + return id; + } + } - ParticleSystem system = (ParticleSystem) systemsByIndex.get(index); - var data = buf.read(system.endec); - client.execute(() -> system.handler.executeParticleSystem(client.world, pos, data)); + @Environment(EnvType.CLIENT) + private static class Client { + private void handler(ParticleSystemPayload payload, ClientPlayNetworking.Context context) { + payload.instance.execute(context.client().world, payload.pos); } } } diff --git a/src/main/java/io/wispforest/owo/serialization/Endec.java b/src/main/java/io/wispforest/owo/serialization/Endec.java index cca934fe..59c9231f 100644 --- a/src/main/java/io/wispforest/owo/serialization/Endec.java +++ b/src/main/java/io/wispforest/owo/serialization/Endec.java @@ -6,7 +6,12 @@ import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import io.wispforest.owo.serialization.endec.*; +import io.wispforest.owo.serialization.format.bytebuf.ByteBufDeserializer; +import io.wispforest.owo.serialization.format.bytebuf.ByteBufSerializer; import io.wispforest.owo.serialization.format.edm.*; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.codec.PacketCodec; import net.minecraft.util.Util; import org.jetbrains.annotations.Nullable; @@ -215,6 +220,15 @@ static Endec ofCodec(Codec codec) { ); } + static Endec ofPacketCodec(PacketCodec codec) { + return BuiltInEndecs.PACKET_BYTE_BUF + .xmap(codec::decode, value -> { + var buf = PacketByteBufs.create(); + codec.encode(buf, value); + return buf; + }); + } + // --- /** @@ -445,6 +459,21 @@ public DataResult encode(T input, DynamicOps ops, D prefix) { }; } + + default PacketCodec packetCodec() { + return new PacketCodec<>() { + @Override + public T decode(PacketByteBuf buf) { + return Endec.this.decodeFully(ByteBufDeserializer::of, buf); + } + + @Override + public void encode(PacketByteBuf buf, T value) { + Endec.this.encodeFully(() -> ByteBufSerializer.of(buf), value); + } + }; + } + /** * Create a new keyed endec which (de)serializes the entry * with key {@code key} into/from a {@link io.wispforest.owo.serialization.util.MapCarrier}, diff --git a/src/main/java/io/wispforest/owo/serialization/endec/ReflectiveEndecBuilder.java b/src/main/java/io/wispforest/owo/serialization/endec/ReflectiveEndecBuilder.java index fa50e7b5..2bbcad8f 100644 --- a/src/main/java/io/wispforest/owo/serialization/endec/ReflectiveEndecBuilder.java +++ b/src/main/java/io/wispforest/owo/serialization/endec/ReflectiveEndecBuilder.java @@ -241,22 +241,23 @@ private static Endec createSealedSerializer(Class commonClass) { register(BuiltInEndecs.BITSET, BitSet.class); register(BuiltInEndecs.TEXT, Text.class); - register(BuiltInEndecs.PACKET_BYTE_BUF.xmap( - byteBuf -> { - //noinspection rawtypes - final ParticleType particleType = Registries.PARTICLE_TYPE.get(byteBuf.readInt()); - //noinspection unchecked, ConstantConditions - - return particleType.getParametersFactory().read(particleType, byteBuf); - }, - particleEffect -> { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeInt(Registries.PARTICLE_TYPE.getRawId(particleEffect.getType())); - particleEffect.write(buf); - - return buf; - } - ), ParticleEffect.class); + // TODO: properly implement this after RegistryByteBuf support is done +// register(BuiltInEndecs.PACKET_BYTE_BUF.xmap( +// byteBuf -> { +// //noinspection rawtypes +// final ParticleType particleType = Registries.PARTICLE_TYPE.get(byteBuf.readInt()); +// //noinspection unchecked, ConstantConditions +// +// return particleType.getParametersFactory().read(particleType, byteBuf); +// }, +// particleEffect -> { +// PacketByteBuf buf = PacketByteBufs.create(); +// buf.writeInt(Registries.PARTICLE_TYPE.getRawId(particleEffect.getType())); +// particleEffect.write(buf); +// +// return buf; +// } +// ), ParticleEffect.class); register(BuiltInEndecs.VEC3D, Vec3d.class); register(BuiltInEndecs.VECTOR3F, Vector3f.class); diff --git a/src/main/java/io/wispforest/owo/serialization/format/nbt/NbtEndec.java b/src/main/java/io/wispforest/owo/serialization/format/nbt/NbtEndec.java index 32a35911..6ce1fb69 100644 --- a/src/main/java/io/wispforest/owo/serialization/format/nbt/NbtEndec.java +++ b/src/main/java/io/wispforest/owo/serialization/format/nbt/NbtEndec.java @@ -5,7 +5,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NbtTagSizeTracker; +import net.minecraft.nbt.NbtSizeTracker; import java.io.IOException; @@ -43,7 +43,7 @@ public NbtElement decode(Deserializer deserializer) { } try { - return NbtIo.read(ByteStreams.newDataInput(deserializer.readBytes()), NbtTagSizeTracker.ofUnlimitedBytes()); + return NbtIo.read(ByteStreams.newDataInput(deserializer.readBytes()), NbtSizeTracker.ofUnlimitedBytes()); } catch (IOException e) { throw new RuntimeException("Failed to parse binary NBT in NbtEndec", e); } diff --git a/src/main/java/io/wispforest/owo/serialization/util/EndecRecipeSerializer.java b/src/main/java/io/wispforest/owo/serialization/util/EndecRecipeSerializer.java index e67d620a..37920e42 100644 --- a/src/main/java/io/wispforest/owo/serialization/util/EndecRecipeSerializer.java +++ b/src/main/java/io/wispforest/owo/serialization/util/EndecRecipeSerializer.java @@ -5,18 +5,20 @@ import io.wispforest.owo.serialization.SerializationAttribute; import io.wispforest.owo.serialization.StructEndec; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeSerializer; public abstract class EndecRecipeSerializer> implements RecipeSerializer { private final StructEndec endec; - private final Endec networkEndec; + private final PacketCodec packetCodec; private final Codec codec; protected EndecRecipeSerializer(StructEndec endec, Endec networkEndec) { this.endec = endec; - this.networkEndec = networkEndec; + this.packetCodec = networkEndec.packetCodec(); this.codec = this.endec.mapCodec(SerializationAttribute.HUMAN_READABLE).codec(); } @@ -29,13 +31,10 @@ public Codec codec() { return this.codec; } + @SuppressWarnings("unchecked") @Override - public R read(PacketByteBuf buf) { - return buf.read(this.networkEndec); - } - - @Override - public void write(PacketByteBuf buf, R recipe) { - buf.write(this.networkEndec, recipe); + public PacketCodec packetCodec() { + // Don't ya just love Java generics? + return (PacketCodec)(Object) packetCodec; } } diff --git a/src/main/java/io/wispforest/owo/ui/component/BlockComponent.java b/src/main/java/io/wispforest/owo/ui/component/BlockComponent.java index 8c98c23f..86f962e9 100644 --- a/src/main/java/io/wispforest/owo/ui/component/BlockComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/BlockComponent.java @@ -74,8 +74,10 @@ public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partial protected static void prepareBlockEntity(BlockState state, BlockEntity blockEntity, @Nullable NbtCompound nbt) { if (blockEntity == null) return; + var world = MinecraftClient.getInstance().world; + ((BlockEntityAccessor) blockEntity).owo$setCachedState(state); - blockEntity.setWorld(MinecraftClient.getInstance().world); + blockEntity.setWorld(world); if (nbt == null) return; @@ -85,7 +87,7 @@ protected static void prepareBlockEntity(BlockState state, BlockEntity blockEnti nbtCopy.putInt("y", 0); nbtCopy.putInt("z", 0); - blockEntity.readNbt(nbtCopy); + blockEntity.readNbt(nbtCopy, world.getRegistryManager()); } public static BlockComponent parse(Element element) { diff --git a/src/main/java/io/wispforest/owo/ui/component/ButtonComponent.java b/src/main/java/io/wispforest/owo/ui/component/ButtonComponent.java index e831c10d..c7615b9c 100644 --- a/src/main/java/io/wispforest/owo/ui/component/ButtonComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/ButtonComponent.java @@ -51,8 +51,8 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY, float delt } var tooltip = ((ClickableWidgetAccessor) this).owo$getTooltip(); - if (this.hovered && tooltip != null) - context.drawTooltip(textRenderer, tooltip.getLines(MinecraftClient.getInstance()), HoveredTooltipPositioner.INSTANCE, mouseX, mouseY); + if (this.hovered && tooltip.getTooltip() != null) + context.drawTooltip(textRenderer, tooltip.getTooltip().getLines(MinecraftClient.getInstance()), HoveredTooltipPositioner.INSTANCE, mouseX, mouseY); } public ButtonComponent onPress(Consumer onPress) { diff --git a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java index 3a12dfef..c1dfa8af 100644 --- a/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/EntityComponent.java @@ -254,7 +254,7 @@ protected RenderablePlayerEntity(GameProfile profile) { profile, new WorldSession(TelemetrySender.NOOP, false, Duration.ZERO, ""), MinecraftClient.getInstance().world.getRegistryManager().toImmutable(), MinecraftClient.getInstance().world.getEnabledFeatures(), - "Wisp Forest Enterprises", null, null + "Wisp Forest Enterprises", null, null, Map.of() )), null, null, false, false ); diff --git a/src/main/java/io/wispforest/owo/ui/component/ItemComponent.java b/src/main/java/io/wispforest/owo/ui/component/ItemComponent.java index 4ebc6d30..451623ad 100644 --- a/src/main/java/io/wispforest/owo/ui/component/ItemComponent.java +++ b/src/main/java/io/wispforest/owo/ui/component/ItemComponent.java @@ -23,6 +23,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryWrapper; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; @@ -32,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Stream; public class ItemComponent extends BaseComponent { @@ -186,7 +188,8 @@ public void parseProperties(UIModel model, Element element, Map UIParsing.apply(children, "stack", $ -> $.getTextContent().strip(), stackString -> { try { - var result = ItemStringReader.item(Registries.ITEM.getReadOnlyWrapper(), new StringReader(stackString)); + var result = new ItemStringReader(RegistryWrapper.WrapperLookup.of(Stream.of(Registries.ITEM.getReadOnlyWrapper()))) + .consume(new StringReader(stackString)); var stack = new ItemStack(result.item()); stack.setNbt(result.nbt()); diff --git a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java index cdb15418..18c73f89 100644 --- a/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java +++ b/src/main/java/io/wispforest/owo/ui/core/OwoUIAdapter.java @@ -71,7 +71,7 @@ public static OwoUIAdapter create(Screen screen, var adapter = new OwoUIAdapter<>(0, 0, screen.width, screen.height, rootComponent); screen.addDrawableChild(adapter); - screen.focusOn(adapter); + screen.setFocused(adapter); return adapter; } diff --git a/src/main/java/io/wispforest/owo/util/pond/OwoScreenHandlerExtension.java b/src/main/java/io/wispforest/owo/util/pond/OwoScreenHandlerExtension.java index c58cce24..5149bf90 100644 --- a/src/main/java/io/wispforest/owo/util/pond/OwoScreenHandlerExtension.java +++ b/src/main/java/io/wispforest/owo/util/pond/OwoScreenHandlerExtension.java @@ -1,12 +1,12 @@ package io.wispforest.owo.util.pond; +import io.wispforest.owo.client.screens.ScreenInternals; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketByteBuf; public interface OwoScreenHandlerExtension { void owo$attachToPlayer(PlayerEntity player); - void owo$readPropertySync(PacketByteBuf buf); + void owo$readPropertySync(ScreenInternals.SyncPropertiesPacket packet); - void owo$handlePacket(PacketByteBuf buf, boolean clientbound); + void owo$handlePacket(ScreenInternals.LocalPacket packet, boolean clientbound); } diff --git a/src/testmod/java/io/wispforest/uwu/Uwu.java b/src/testmod/java/io/wispforest/uwu/Uwu.java index 3e867730..36350340 100644 --- a/src/testmod/java/io/wispforest/uwu/Uwu.java +++ b/src/testmod/java/io/wispforest/uwu/Uwu.java @@ -8,6 +8,8 @@ import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.logging.LogUtils; +import io.netty.buffer.Unpooled; +import io.wispforest.owo.Owo; import io.wispforest.owo.config.ConfigSynchronizer; import io.wispforest.owo.config.Option; import io.wispforest.owo.itemgroup.Icon; @@ -58,6 +60,7 @@ import net.minecraft.nbt.NbtHelper; import net.minecraft.nbt.NbtOps; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.particle.ParticleTypes; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; @@ -92,7 +95,11 @@ public class Uwu implements ModInitializer { public static final Identifier OWO_ICON_TEXTURE = new Identifier("uwu", "textures/gui/icon.png"); public static final Identifier ANIMATED_BUTTON_TEXTURE = new Identifier("uwu", "textures/gui/animated_icon_test.png"); - public static final ScreenHandlerType EPIC_SCREEN_HANDLER_TYPE = new ScreenHandlerType<>(EpicScreenHandler::new, FeatureFlags.VANILLA_FEATURES); + public static final ScreenHandlerType EPIC_SCREEN_HANDLER_TYPE = Registry.register( + Registries.SCREEN_HANDLER, + new Identifier("uwu", "epic_screen_handler"), + new ScreenHandlerType<>(EpicScreenHandler::new, FeatureFlags.VANILLA_FEATURES) + ); public static final OwoItemGroup FOUR_TAB_GROUP = OwoItemGroup.builder(new Identifier("uwu", "four_tab_group"), () -> Icon.of(Items.AXOLOTL_BUCKET)) .disableDynamicTitle() @@ -452,7 +459,8 @@ public void onInitialize() { iterations("Vanilla", (buf) -> { ItemStack stack = source.getPlayer().getStackInHand(Hand.MAIN_HAND); - var stackFromByte = buf.writeItemStack(stack).readItemStack(); + ItemStack.PACKET_CODEC.encode(buf, stack); + var stackFromByte = ItemStack.PACKET_CODEC.decode(buf); }); //Codeck @@ -480,7 +488,7 @@ public void onInitialize() { UwuOptionalNetExample.init(); } - private static void iterations(String label, Consumer action){ + private static void iterations(String label, Consumer action){ int maxTrials = 3; int maxIterations = 50; @@ -493,7 +501,7 @@ private static void iterations(String label, Consumer action){ durations.clear(); for (int i = 0; i < maxIterations; i++) { - PacketByteBuf buf = PacketByteBufs.create(); + RegistryByteBuf buf = new RegistryByteBuf(Unpooled.buffer(), Owo.currentServer().getRegistryManager()); long startTime = System.nanoTime(); diff --git a/src/testmod/java/io/wispforest/uwu/recipe/EndecRecipeSerializer.java b/src/testmod/java/io/wispforest/uwu/recipe/EndecRecipeSerializer.java deleted file mode 100644 index 8afca3d5..00000000 --- a/src/testmod/java/io/wispforest/uwu/recipe/EndecRecipeSerializer.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.wispforest.uwu.recipe; - -import com.mojang.serialization.Codec; -import io.wispforest.owo.serialization.Endec; -import io.wispforest.owo.serialization.SerializationAttribute; -import io.wispforest.owo.serialization.format.bytebuf.ByteBufDeserializer; -import io.wispforest.owo.serialization.format.bytebuf.ByteBufSerializer; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeSerializer; - -public class EndecRecipeSerializer> implements RecipeSerializer { - - public final Endec endec; - public final Codec codec; - - public EndecRecipeSerializer(Endec endec){ - this.codec = endec.codec(SerializationAttribute.HUMAN_READABLE); - this.endec = endec; - } - - @Override - public Codec codec() { - return this.codec; - } - - @Override - public void write(PacketByteBuf buf, T recipe) { - buf.write(this.endec, recipe); - } - - @Override - public T read(PacketByteBuf buf) { - return buf.read(this.endec); - } -}