From 907479dbffcfe6afcef28ffcae677a0374e5f66f Mon Sep 17 00:00:00 2001 From: Up <10714589+UpcraftLP@users.noreply.github.com> Date: Tue, 30 Jun 2026 00:41:26 +0200 Subject: [PATCH] fix bytebufs being treated as immutable port of #229 for Minecraft 26.1 (fixes #228) --- .../cca/api/v3/component/ComponentKey.java | 31 ++++++++++--------- .../api/v3/component/ComponentProvider.java | 3 +- .../cca/internal/base/CcaClientInternals.java | 11 +++++-- .../internal/base/ComponentUpdatePayload.java | 4 +-- .../cca/internal/base/MorePacketCodecs.java | 15 --------- .../mixin/block/common/MixinBlockEntity.java | 2 +- .../mixin/chunk/common/MixinLevelChunk.java | 2 +- .../v3/entity/C2SSelfMessagingComponent.java | 10 ++++-- .../entity/CardinalComponentsEntity.java | 7 +++-- .../cca/mixin/entity/common/MixinEntity.java | 2 +- .../mixin/level/common/MixinServerLevel.java | 2 +- .../common/MixinPrimaryLevelData.java | 2 +- .../cca/mixin/scoreboard/MixinPlayerTeam.java | 2 +- .../scoreboard/MixinServerScoreboard.java | 2 +- 14 files changed, 47 insertions(+), 48 deletions(-) diff --git a/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentKey.java b/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentKey.java index dc5e4019..394bc322 100644 --- a/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentKey.java +++ b/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentKey.java @@ -203,23 +203,24 @@ public void syncWith(ServerPlayer player, ComponentProvider provider) { public void syncWith(ServerPlayer player, ComponentProvider provider, ComponentPacketWriter writer, PlayerSyncPredicate predicate) { if (predicate.shouldSyncWith(player)) { RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), player.level().registryAccess()); - writer.writeSyncPacket(buf, player); - CustomPacketPayload payload = provider.toComponentPacket(this, predicate.isRequiredOnClient(), buf); - - if (payload != null) { - if (ServerPlayNetworking.canSend(player, payload.type())) { - ServerPlayNetworking.getSender(player).sendPacket(payload, PacketSendListener.thenRun(buf::release)); - } else { - if (predicate.isRequiredOnClient()) { - String specificMod = FabricLoader.getInstance().getModContainer(this.id.getNamespace()).map(c -> c.getMetadata().getName() + " and ").orElse(""); - player.connection.disconnect(literal( - "This server requires " + specificMod + "Cardinal Components API " + - "(unhandled packet: " + payload.type().id() + ")" + - ComponentsInternals.getClientOptionalModAdvice())); + try { + writer.writeSyncPacket(buf, player); + CustomPacketPayload payload = provider.toComponentPacket(this, predicate.isRequiredOnClient(), buf); + if (payload != null) { + if (ServerPlayNetworking.canSend(player, payload.type())) { + buf.retain(); // only release the buffer after the packet is sent, in case an implementation retains a reference to it + ServerPlayNetworking.getSender(player).sendPacket(payload, PacketSendListener.thenRun(buf::release)); + } else { + if (predicate.isRequiredOnClient()) { + String specificMod = FabricLoader.getInstance().getModContainer(this.id.getNamespace()).map(c -> c.getMetadata().getName() + " and ").orElse(""); + player.connection.disconnect(literal( + "This server requires " + specificMod + "Cardinal Components API " + + "(unhandled packet: " + payload.type().id() + ")" + + ComponentsInternals.getClientOptionalModAdvice())); + } } - buf.release(); } - } else { + } finally { buf.release(); } } diff --git a/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentProvider.java b/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentProvider.java index a5d7a6a2..14bcd47a 100644 --- a/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentProvider.java +++ b/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/ComponentProvider.java @@ -29,7 +29,6 @@ import org.jspecify.annotations.Nullable; import org.ladysnake.cca.api.v3.component.sync.AutoSyncedComponent; import org.ladysnake.cca.api.v3.component.sync.PlayerSyncPredicate; -import org.ladysnake.cca.internal.base.ComponentUpdatePayload; import java.util.List; @@ -67,7 +66,7 @@ default Iterable getRecipientsForComponentSync() { * @param key the key describing the component being synchronized * @param required {@code true} if attempting to sync a component key unknown to the client should disconnect it * @param data the component's raw sync data - * @return a {@link ComponentUpdatePayload} that has all the information required to perform the component sync + * @return a {@link CustomPacketPayload} that has all the information required to perform the component sync * @since 6.0.0 */ @Nullable diff --git a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/CcaClientInternals.java b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/CcaClientInternals.java index fbd13e27..49cc5fcc 100644 --- a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/CcaClientInternals.java +++ b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/CcaClientInternals.java @@ -22,8 +22,10 @@ */ package org.ladysnake.cca.internal.base; +import io.netty.buffer.Unpooled; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.minecraft.network.DisconnectionDetails; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import org.ladysnake.cca.api.v3.component.sync.AutoSyncedComponent; import org.ladysnake.cca.api.v8.component.CardinalComponent; @@ -39,15 +41,18 @@ public static > void registerComponentSync(C try { getter.apply(payload, ctx).ifPresent(c -> { if (c instanceof AutoSyncedComponent synced) { - synced.applySyncPacket(payload.buf()); + var buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.rawPayload()), ctx.client().level.registryAccess()); + try { + synced.applySyncPacket(buf); + } finally { + buf.release(); + } } }); } catch (UnknownComponentException e) { ctx.player().connection.onDisconnect(new DisconnectionDetails(literal( e.getMessage() + "\n(you are probably missing a mod installed on the server)" + ComponentsInternals.getClientOptionalModAdvice()) )); - } finally { - payload.buf().release(); } }); } diff --git a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/ComponentUpdatePayload.java b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/ComponentUpdatePayload.java index fbc3ef20..577a51b6 100644 --- a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/ComponentUpdatePayload.java +++ b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/ComponentUpdatePayload.java @@ -38,7 +38,7 @@ public record ComponentUpdatePayload( T targetData, boolean required, Identifier componentKeyId, - RegistryFriendlyByteBuf buf + byte[] rawPayload ) implements CustomPacketPayload { public static CustomPacketPayload.Type> id(String path) { return new CustomPacketPayload.Type<>(Identifier.fromNamespaceAndPath("cardinal-components", path)); @@ -54,7 +54,7 @@ public static StreamCodec targetDataCodec, ComponentUpdatePayload::targetData, ByteBufCodecs.BOOL, ComponentUpdatePayload::required, Identifier.STREAM_CODEC, ComponentUpdatePayload::componentKeyId, - MorePacketCodecs.REG_BYTE_BUF, ComponentUpdatePayload::buf, + ByteBufCodecs.BYTE_ARRAY, ComponentUpdatePayload::rawPayload, ComponentUpdatePayload::new ); } diff --git a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/MorePacketCodecs.java b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/MorePacketCodecs.java index 0a252718..bc7287cc 100644 --- a/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/MorePacketCodecs.java +++ b/cardinal-components-base/src/main/java/org/ladysnake/cca/internal/base/MorePacketCodecs.java @@ -24,23 +24,8 @@ import com.mojang.datafixers.util.Unit; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; public final class MorePacketCodecs { public static final StreamCodec EMPTY = StreamCodec.unit(Unit.INSTANCE); - - public static final StreamCodec REG_BYTE_BUF = StreamCodec.of( - (buf, value) -> { - buf.writeVarInt(value.readableBytes()); - buf.writeBytes(value); - }, - (buf) -> { - int readableBytes = buf.readVarInt(); - ByteBuf copy = Unpooled.buffer(readableBytes, readableBytes); - buf.readBytes(copy, readableBytes); - return new RegistryFriendlyByteBuf(copy, buf.registryAccess()); - } - ); } diff --git a/cardinal-components-block/src/main/java/org/ladysnake/cca/mixin/block/common/MixinBlockEntity.java b/cardinal-components-block/src/main/java/org/ladysnake/cca/mixin/block/common/MixinBlockEntity.java index 7f415c9a..7d067900 100644 --- a/cardinal-components-block/src/main/java/org/ladysnake/cca/mixin/block/common/MixinBlockEntity.java +++ b/cardinal-components-block/src/main/java/org/ladysnake/cca/mixin/block/common/MixinBlockEntity.java @@ -109,7 +109,7 @@ public Iterable getRecipientsForComponentSync() { new BlockEntityAddress(this.getType(), this.getBlockPos(), world.dimension()), required, key.getId(), - data + data.array() ); } } diff --git a/cardinal-components-chunk/src/main/java/org/ladysnake/cca/mixin/chunk/common/MixinLevelChunk.java b/cardinal-components-chunk/src/main/java/org/ladysnake/cca/mixin/chunk/common/MixinLevelChunk.java index f242f7b2..54d059f1 100644 --- a/cardinal-components-chunk/src/main/java/org/ladysnake/cca/mixin/chunk/common/MixinLevelChunk.java +++ b/cardinal-components-chunk/src/main/java/org/ladysnake/cca/mixin/chunk/common/MixinLevelChunk.java @@ -74,7 +74,7 @@ public Iterable getRecipientsForComponentSync() { this.getPos(), required, key.getId(), - data + data.array() ); } diff --git a/cardinal-components-entity/src/main/java/org/ladysnake/cca/api/v3/entity/C2SSelfMessagingComponent.java b/cardinal-components-entity/src/main/java/org/ladysnake/cca/api/v3/entity/C2SSelfMessagingComponent.java index f9eb67f7..798099a0 100644 --- a/cardinal-components-entity/src/main/java/org/ladysnake/cca/api/v3/entity/C2SSelfMessagingComponent.java +++ b/cardinal-components-entity/src/main/java/org/ladysnake/cca/api/v3/entity/C2SSelfMessagingComponent.java @@ -82,7 +82,13 @@ default void sendC2SMessage(C2SComponentPacketWriter writer) { static void sendC2SMessage(ComponentKey key, C2SComponentPacketWriter writer) { PacketSender sender = ClientPlayNetworking.getSender(); // checks that the player is in game RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(FriendlyByteBufs.create(), Objects.requireNonNull(Minecraft.getInstance().getConnection()).registryAccess()); - writer.writeC2SPacket(buf); - sender.sendPacket(new ComponentUpdatePayload<>(CardinalComponentsEntity.C2S_SELF_PACKET_ID, Unit.INSTANCE, true, key.getId(), buf), PacketSendListener.thenRun(buf::release)); + byte[] bytes; + try { + writer.writeC2SPacket(buf); + bytes = buf.array(); + } finally { + buf.release(); + } + sender.sendPacket(new ComponentUpdatePayload<>(CardinalComponentsEntity.C2S_SELF_PACKET_ID, Unit.INSTANCE, true, key.getId(), bytes)); } } diff --git a/cardinal-components-entity/src/main/java/org/ladysnake/cca/internal/entity/CardinalComponentsEntity.java b/cardinal-components-entity/src/main/java/org/ladysnake/cca/internal/entity/CardinalComponentsEntity.java index d9c4f657..26104d18 100644 --- a/cardinal-components-entity/src/main/java/org/ladysnake/cca/internal/entity/CardinalComponentsEntity.java +++ b/cardinal-components-entity/src/main/java/org/ladysnake/cca/internal/entity/CardinalComponentsEntity.java @@ -23,6 +23,7 @@ package org.ladysnake.cca.internal.entity; import com.mojang.datafixers.util.Unit; +import io.netty.buffer.Unpooled; import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents; import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; @@ -30,6 +31,7 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.core.HolderLookup; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; @@ -82,11 +84,12 @@ public static void init() { PlayerSyncCallback.EVENT.register(player -> syncEntityComponents(player, player)); TrackingStartCallback.EVENT.register(CardinalComponentsEntity::syncEntityComponents); ServerPlayNetworking.registerGlobalReceiver(CardinalComponentsEntity.C2S_SELF_PACKET_ID, (payload, ctx) -> { + var buf = new RegistryFriendlyByteBuf(Unpooled.wrappedBuffer(payload.rawPayload()), ctx.player().registryAccess()); try { Optional> componentKey = payload.componentKey(); if (componentKey.isPresent()) { if (componentKey.get().getNullable(ctx.player()) instanceof C2SSelfMessagingComponent synced) { - synced.handleC2SMessage(payload.buf()); + synced.handleC2SMessage(buf); } else if (payload.required() && (unknownC2SPlayerComponents.add(payload.componentKeyId()) || FabricLoader.getInstance().isDevelopmentEnvironment())) { // In prod, only log the first time an unknown component update is received ComponentsInternals.LOGGER.warn("[Cardinal Components API] Received an update for component {} from player {}, but this component is not registered for player entities", payload.componentKeyId(), ctx.player()); @@ -95,7 +98,7 @@ public static void init() { ComponentsInternals.LOGGER.warn("[Cardinal Components API] Received an update for unknown component {} from player {}", payload.componentKeyId(), ctx.player()); } } finally { - payload.buf().release(); + buf.release(); } }); } diff --git a/cardinal-components-entity/src/main/java/org/ladysnake/cca/mixin/entity/common/MixinEntity.java b/cardinal-components-entity/src/main/java/org/ladysnake/cca/mixin/entity/common/MixinEntity.java index b10f4b1a..cd47a57b 100644 --- a/cardinal-components-entity/src/main/java/org/ladysnake/cca/mixin/entity/common/MixinEntity.java +++ b/cardinal-components-entity/src/main/java/org/ladysnake/cca/mixin/entity/common/MixinEntity.java @@ -98,7 +98,7 @@ public ComponentUpdatePayload toComponentPack this.getId(), required, key.getId(), - data + data.array() ); } } diff --git a/cardinal-components-level/src/main/java/org/ladysnake/cca/mixin/level/common/MixinServerLevel.java b/cardinal-components-level/src/main/java/org/ladysnake/cca/mixin/level/common/MixinServerLevel.java index b9947c55..ebf6f9c6 100644 --- a/cardinal-components-level/src/main/java/org/ladysnake/cca/mixin/level/common/MixinServerLevel.java +++ b/cardinal-components-level/src/main/java/org/ladysnake/cca/mixin/level/common/MixinServerLevel.java @@ -75,7 +75,7 @@ public ComponentUpdatePayload toComponentPack Unit.INSTANCE, required, key.getId(), - data + data.array() ); } } diff --git a/cardinal-components-leveldata/src/main/java/org/ladysnake/cca/mixin/leveldata/common/MixinPrimaryLevelData.java b/cardinal-components-leveldata/src/main/java/org/ladysnake/cca/mixin/leveldata/common/MixinPrimaryLevelData.java index 458f1c42..44d300a1 100644 --- a/cardinal-components-leveldata/src/main/java/org/ladysnake/cca/mixin/leveldata/common/MixinPrimaryLevelData.java +++ b/cardinal-components-leveldata/src/main/java/org/ladysnake/cca/mixin/leveldata/common/MixinPrimaryLevelData.java @@ -88,7 +88,7 @@ public ComponentUpdatePayload toComponentPack Unit.INSTANCE, required, key.getId(), - data + data.array() ); } diff --git a/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinPlayerTeam.java b/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinPlayerTeam.java index 766d29d0..3e751b71 100644 --- a/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinPlayerTeam.java +++ b/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinPlayerTeam.java @@ -89,7 +89,7 @@ public ComponentUpdatePayload toComponentPack this.getName(), required, key.getId(), - data + data.array() ); } } diff --git a/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinServerScoreboard.java b/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinServerScoreboard.java index 06fe6882..ef42a263 100644 --- a/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinServerScoreboard.java +++ b/cardinal-components-scoreboard/src/main/java/org/ladysnake/cca/mixin/scoreboard/MixinServerScoreboard.java @@ -96,7 +96,7 @@ public ComponentUpdatePayload toComponentPack Unit.INSTANCE, required, key.getId(), - data + data.array() ); }