diff --git a/build.gradle.kts b/build.gradle.kts index d55e5c7b..1a9298a3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,8 @@ import net.fabricmc.loom.task.RemapJarTask import java.net.URI plugins { - id("fabric-loom") version "1.3-SNAPSHOT" apply false - id("io.github.juuxel.loom-quiltflower") version "1.6.0" - id("io.github.ladysnake.chenille") version "0.11.3" + id("fabric-loom") version "1.5-SNAPSHOT" + id("io.github.ladysnake.chenille") version "0.12.0-SNAPSHOT+build.1" id("org.cadixdev.licenser") version "0.6.1" } @@ -15,9 +14,8 @@ val fabricApiVersion: String = providers.gradleProperty("fabric_api_version").ge allprojects { apply(plugin = "java-library") apply(plugin = "maven-publish") - apply(plugin = "io.github.ladysnake.chenille") - apply(plugin = "org.cadixdev.licenser") apply(plugin = "fabric-loom") + apply(plugin = "io.github.ladysnake.chenille") chenille { javaVersion = 17 @@ -63,10 +61,6 @@ allprojects { compileOnly("org.jetbrains:annotations:24.0.1") } - repositories { - mavenLocal() - } - tasks.processResources { inputs.property("version", project.version) diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentKey.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentKey.java index c89f418a..62d32cf8 100644 --- a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentKey.java +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentKey.java @@ -26,7 +26,14 @@ import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; import dev.onyxstudios.cca.api.v3.component.sync.PlayerSyncPredicate; import dev.onyxstudios.cca.internal.base.asm.CcaBootstrap; -import net.minecraft.network.packet.Packet; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.network.PacketCallbacks; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.ApiStatus; @@ -47,6 +54,13 @@ */ @ApiStatus.NonExtendable public abstract class ComponentKey { + public static final PacketCodec> PACKET_CODEC = PacketCodecs.STRING.xmap( + id -> Objects.requireNonNull( + ComponentRegistry.get(new Identifier(id)), + "No component key with id " + id + ), + key -> key.getId().toString() + ); public final Identifier getId() { return this.id; @@ -193,10 +207,14 @@ public void syncWith(ServerPlayerEntity player, ComponentProvider provider) { @ApiStatus.Experimental public void syncWith(ServerPlayerEntity player, ComponentProvider provider, ComponentPacketWriter writer, PlayerSyncPredicate predicate) { if (predicate.shouldSyncWith(player)) { - Packet packet = provider.toComponentPacket(this, writer, player); + RegistryByteBuf buf = new RegistryByteBuf(Unpooled.buffer(), player.getServerWorld().getRegistryManager()); + writer.writeSyncPacket(buf, player); + CustomPayload payload = provider.toComponentPacket(this, buf); - if (packet != null) { - player.networkHandler.sendPacket(packet); + if (payload != null) { + ServerPlayNetworking.getSender(player).sendPacket(payload, PacketCallbacks.always(buf::release)); + } else { + buf.release(); } } } diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentProvider.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentProvider.java index 1c4720d5..2bbd3b90 100644 --- a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentProvider.java +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ComponentProvider.java @@ -23,11 +23,12 @@ package dev.onyxstudios.cca.api.v3.component; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; import dev.onyxstudios.cca.api.v3.component.sync.PlayerSyncPredicate; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; -import org.jetbrains.annotations.ApiStatus; import javax.annotation.Nullable; import java.util.List; @@ -61,15 +62,15 @@ default Iterable getRecipientsForComponentSync() { /** * Produces a sync packet using the given information. * - * @param key the key describing the component being synchronized - * @param writer a {@link ComponentPacketWriter} writing the component's data to the packet - * @param recipient the player receiving the packet - * @return a {@link net.minecraft.network.packet.Packet} that has all the information required to perform the component sync - * @since 3.0.0 + *

It is the responsibility of the caller to {@link ByteBuf#release() release} the buffer after this method returns. + * + * @param key the key describing the component being synchronized + * @param data the component's raw sync data + * @return a {@link ComponentUpdatePayload} that has all the information required to perform the component sync + * @since 6.0.0 */ @Nullable - @ApiStatus.Experimental // TODO change the return value to Packet - default CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { + default CustomPayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { return null; } } diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/CcaClientInternals.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/CcaClientInternals.java new file mode 100644 index 00000000..cb523e91 --- /dev/null +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/CcaClientInternals.java @@ -0,0 +1,48 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2024 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal.base; + +import dev.onyxstudios.cca.api.v3.component.Component; +import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.minecraft.network.packet.CustomPayload; + +import java.util.Optional; +import java.util.function.BiFunction; + +public final class CcaClientInternals { + public static > void registerComponentSync(CustomPayload.Id packetId, BiFunction> getter) { + ClientPlayNetworking.registerGlobalReceiver(packetId, (payload, ctx) -> { + try { + getter.apply(payload, ctx).ifPresent(c -> { + if (c instanceof AutoSyncedComponent synced) { + synced.applySyncPacket(payload.buf()); + } + }); + } finally { + payload.buf().release(); + } + }); + } + +} diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentUpdatePayload.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentUpdatePayload.java new file mode 100644 index 00000000..5d0e68c7 --- /dev/null +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentUpdatePayload.java @@ -0,0 +1,59 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2024 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal.base; + +import dev.onyxstudios.cca.api.v3.component.ComponentKey; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.packet.CustomPayload; + +public record ComponentUpdatePayload( + Id> id, + T targetData, + ComponentKey componentKey, + RegistryByteBuf buf +) implements CustomPayload { + public static CustomPayload.Id> id(String path) { + return CustomPayload.id("cardinal-components:" + path); + } + + public static void register(Id> id, PacketCodec targetDataCodec) { + PayloadTypeRegistry.playS2C().register(id, codec(id, targetDataCodec)); + } + + public static PacketCodec> codec(Id> id, PacketCodec targetDataCodec) { + return MorePacketCodecs.tuple( + PacketCodec.unit(id), ComponentUpdatePayload::id, + targetDataCodec, ComponentUpdatePayload::targetData, + ComponentKey.PACKET_CODEC, ComponentUpdatePayload::componentKey, + MorePacketCodecs.REG_BYTE_BUF, ComponentUpdatePayload::buf, + ComponentUpdatePayload::new + ); + } + + @Override + public Id getId() { + return id; + } +} diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/MorePacketCodecs.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/MorePacketCodecs.java new file mode 100644 index 00000000..0d397557 --- /dev/null +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/MorePacketCodecs.java @@ -0,0 +1,93 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2024 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal.base; + +import com.mojang.datafixers.util.Function4; +import com.mojang.datafixers.util.Unit; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.util.math.ChunkPos; + +import java.util.function.Function; + +public final class MorePacketCodecs { + public static final PacketCodec EMPTY = PacketCodec.unit(Unit.INSTANCE); + + public static final PacketCodec REG_BYTE_BUF = PacketCodec.ofStatic( + (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 RegistryByteBuf(copy, buf.getRegistryManager()); + } + ); + + /** + * A codec for a {@link ChunkPos}. + * + * @see PacketByteBuf#readChunkPos() + * @see PacketByteBuf#writeChunkPos(ChunkPos) + */ + public static final PacketCodec CHUNKPOS = PacketCodec.ofStatic( + PacketByteBuf::writeChunkPos, + PacketByteBuf::readChunkPos + ); + + /** + * {@return a codec for encoding three values} + */ + public static PacketCodec tuple( + PacketCodec codec1, + Function from1, + PacketCodec codec2, + Function from2, + PacketCodec codec3, + Function from3, + PacketCodec codec4, + Function from4, + Function4 to + ) { + return PacketCodec.ofStatic( + (buf, value) -> { + codec1.encode(buf, from1.apply(value)); + codec2.encode(buf, from2.apply(value)); + codec3.encode(buf, from3.apply(value)); + codec4.encode(buf, from4.apply(value)); + }, + (buf) -> { + T1 object2 = codec1.decode(buf); + T2 object3 = codec2.decode(buf); + T3 object4 = codec3.decode(buf); + T4 object5 = codec4.decode(buf); + return to.apply(object2, object3, object4, object5); + } + ); + } +} diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/BlockEntityAddress.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/BlockEntityAddress.java new file mode 100644 index 00000000..b983bb63 --- /dev/null +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/BlockEntityAddress.java @@ -0,0 +1,42 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2024 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal; + +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.registry.Registries; +import net.minecraft.util.math.BlockPos; + +public record BlockEntityAddress( + BlockEntityType beType, + BlockPos bePos +) { + + public static final PacketCodec CODEC = PacketCodec.tuple( + PacketCodecs.entryOf(Registries.BLOCK_ENTITY_TYPE), BlockEntityAddress::beType, + BlockPos.PACKET_CODEC, BlockEntityAddress::bePos, + BlockEntityAddress::new + ); +} diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CardinalComponentsBlock.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CardinalComponentsBlock.java index 132c267f..0037218f 100644 --- a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CardinalComponentsBlock.java +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CardinalComponentsBlock.java @@ -27,29 +27,26 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerBlockEntityEvents; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; public class CardinalComponentsBlock { + /** - * {@link CustomPayloadS2CPacket} channel for default entity component synchronization. - * - *

Packets emitted on this channel must begin with, in order, the {@link BlockEntity#getType() BE type} (as an identifier), - * the {@link BlockEntity#getPos() position} (using {@link PacketByteBuf#writeBlockPos(BlockPos)}), - * and the {@link ComponentKey#getId() component's type} (as an Identifier). + * {@link CustomPayloadS2CPacket} channel for default block entity component synchronization. * *

Components synchronized through this channel will have {@linkplain AutoSyncedComponent#applySyncPacket(PacketByteBuf)} * called on the game thread. */ - public static final Identifier PACKET_ID = new Identifier("cardinal-components", "block_entity_sync"); + public static final CustomPayload.Id> PACKET_ID = CustomPayload.id("cardinal-components:block_entity_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(PACKET_ID, BlockEntityAddress.CODEC); BlockEntitySyncCallback.EVENT.register((player, tracked) -> { ComponentProvider provider = (ComponentProvider) tracked; diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CcaBlockClient.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CcaBlockClient.java index 926f5356..338efed6 100644 --- a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CcaBlockClient.java +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/CcaBlockClient.java @@ -22,50 +22,20 @@ */ package dev.onyxstudios.cca.internal; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; public class CcaBlockClient { public static void initClient() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { - ClientPlayNetworking.registerGlobalReceiver(CardinalComponentsBlock.PACKET_ID, (client, handler, buffer, res) -> { - try { - Identifier blockEntityTypeId = buffer.readIdentifier(); - BlockPos position = buffer.readBlockPos(); - Identifier componentTypeId = buffer.readIdentifier(); - BlockEntityType blockEntityType = Registries.BLOCK_ENTITY_TYPE.get(blockEntityTypeId); - ComponentKey componentType = ComponentRegistry.get(componentTypeId); - - if (componentType == null || blockEntityType == null) { - return; - } - - buffer.retain(); - - client.execute(() -> { - try { - componentType.maybeGet(blockEntityType.get(client.world, position)) - .filter(c -> c instanceof AutoSyncedComponent) - .ifPresent(c -> ((AutoSyncedComponent) c).applySyncPacket(buffer)); - } finally { - buffer.release(); - } - }); - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading block entity components from network", e); - throw e; - } - }); + CcaClientInternals.registerComponentSync(CardinalComponentsBlock.PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(payload.targetData().beType().get( + ctx.client().world, + payload.targetData().bePos() + )) + ); } if (FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1")) { ClientBlockEntityEvents.BLOCK_ENTITY_LOAD.register((be, world) -> ((ComponentProvider) be).getComponentContainer().onServerLoad()); diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/mixin/block/common/MixinBlockEntity.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/mixin/block/common/MixinBlockEntity.java index f4a9d635..4b1b75e7 100644 --- a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/mixin/block/common/MixinBlockEntity.java +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/mixin/block/common/MixinBlockEntity.java @@ -26,18 +26,16 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.BlockEntityAddress; import dev.onyxstudios.cca.internal.CardinalComponentsBlock; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.block.CardinalBlockInternals; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -118,15 +116,14 @@ public Iterable getRecipientsForComponentSync() { return List.of(); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeIdentifier(BlockEntityType.getId(this.getType())); - buf.writeBlockPos(this.getPos()); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsBlock.PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsBlock.PACKET_ID, + new BlockEntityAddress(this.getType(), this.getPos()), + key, + data + ); } } diff --git a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CardinalComponentsChunk.java b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CardinalComponentsChunk.java index 6e22228d..a7c3ec15 100644 --- a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CardinalComponentsChunk.java +++ b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CardinalComponentsChunk.java @@ -25,15 +25,19 @@ import dev.onyxstudios.cca.api.v3.chunk.ChunkSyncCallback; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; +import dev.onyxstudios.cca.internal.base.MorePacketCodecs; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.util.Identifier; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.math.ChunkPos; public final class CardinalComponentsChunk { - public static final Identifier PACKET_ID = new Identifier("cardinal-components", "chunk_sync"); + public static final CustomPayload.Id> PACKET_ID = CustomPayload.id("cardinal-components:chunk_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(PACKET_ID, MorePacketCodecs.CHUNKPOS); ChunkSyncCallback.EVENT.register((player, tracked) -> { for (ComponentKey key : tracked.asComponentProvider().getComponentContainer().keys()) { key.syncWith(player, (ComponentProvider) tracked); diff --git a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CcaChunkClient.java b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CcaChunkClient.java index ca7a5527..94f2dd69 100644 --- a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CcaChunkClient.java +++ b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/CcaChunkClient.java @@ -22,46 +22,23 @@ */ package dev.onyxstudios.cca.internal.chunk; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.util.Identifier; import java.util.Objects; public class CcaChunkClient { public static void initClient() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { - ClientPlayNetworking.registerGlobalReceiver(CardinalComponentsChunk.PACKET_ID, (client, handler, buffer, res) -> { - try { - int chunkX = buffer.readInt(); - int chunkZ = buffer.readInt(); - Identifier componentTypeId = buffer.readIdentifier(); - ComponentKey componentType = ComponentRegistry.get(componentTypeId); - if (componentType == null) { - return; - } - buffer.retain(); - client.execute(() -> { - try { - // Note: on the client, unloaded chunks return EmptyChunk - componentType.maybeGet(Objects.requireNonNull(client.world).getChunk(chunkX, chunkZ)) - .filter(c -> c instanceof AutoSyncedComponent) - .ifPresent(c -> ((AutoSyncedComponent) c).applySyncPacket(buffer)); - } finally { - buffer.release(); - } - }); - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading chunk components from network", e); - throw e; - } - }); + CcaClientInternals.registerComponentSync( + CardinalComponentsChunk.PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(Objects.requireNonNull(ctx.client().world).getChunk( + payload.targetData().x, + payload.targetData().z + )) + ); } if (FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1")) { ClientChunkEvents.CHUNK_LOAD.register((world, chunk) -> ((ComponentProvider) chunk).getComponentContainer().onServerLoad()); diff --git a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/mixin/chunk/common/MixinWorldChunk.java b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/mixin/chunk/common/MixinWorldChunk.java index 786e8473..94a14398 100644 --- a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/mixin/chunk/common/MixinWorldChunk.java +++ b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/mixin/chunk/common/MixinWorldChunk.java @@ -25,13 +25,10 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.chunk.CardinalComponentsChunk; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.registry.Registry; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -72,14 +69,13 @@ public Iterable getRecipientsForComponentSync() { } @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - ChunkPos pos = this.getPos(); - buf.writeInt(pos.x); - buf.writeInt(pos.z); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsChunk.PACKET_ID, buf); + public @javax.annotation.Nullable ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsChunk.PACKET_ID, + this.getPos(), + key, + data + ); } @Inject(method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/ProtoChunk;Lnet/minecraft/world/chunk/WorldChunk$EntityLoader;)V", at = @At("RETURN")) diff --git a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CardinalComponentsEntity.java b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CardinalComponentsEntity.java index 5fc74a39..c8710b4a 100644 --- a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CardinalComponentsEntity.java +++ b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CardinalComponentsEntity.java @@ -30,13 +30,15 @@ import dev.onyxstudios.cca.api.v3.entity.PlayerSyncCallback; import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy; import dev.onyxstudios.cca.api.v3.entity.TrackingStartCallback; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.entity.Entity; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; import net.minecraft.world.GameRules; import java.util.Set; @@ -45,16 +47,14 @@ public final class CardinalComponentsEntity { /** * {@link CustomPayloadS2CPacket} channel for default entity component synchronization. * - *

Packets emitted on this channel must begin with, in order, the {@link Entity#getId() entity id} (as an int), - * and the {@link ComponentKey#getId() component's type} (as an Identifier). - * *

Components synchronized through this channel will have {@linkplain AutoSyncedComponent#applySyncPacket(PacketByteBuf)} * called on the game thread. */ - public static final Identifier PACKET_ID = new Identifier("cardinal-components", "entity_sync"); + public static final CustomPayload.Id> PACKET_ID = CustomPayload.id("cardinal-components:entity_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(PACKET_ID, PacketCodecs.VAR_INT); PlayerSyncCallback.EVENT.register(player -> syncEntityComponents(player, player)); TrackingStartCallback.EVENT.register(CardinalComponentsEntity::syncEntityComponents); } diff --git a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CcaEntityClient.java b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CcaEntityClient.java index c8290d82..8a985aac 100644 --- a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CcaEntityClient.java +++ b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/CcaEntityClient.java @@ -22,45 +22,20 @@ */ package dev.onyxstudios.cca.internal.entity; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; import java.util.Objects; public final class CcaEntityClient { public static void initClient() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { - ClientPlayNetworking.registerGlobalReceiver(CardinalComponentsEntity.PACKET_ID, (client, handler, buffer, res) -> { - try { - int entityId = buffer.readInt(); - Identifier componentTypeId = buffer.readIdentifier(); - ComponentKey componentType = ComponentRegistry.get(componentTypeId); - if (componentType == null) { - return; - } - PacketByteBuf copy = new PacketByteBuf(buffer.copy()); - client.execute(() -> { - try { - componentType.maybeGet(Objects.requireNonNull(client.world).getEntityById(entityId)) - .filter(c -> c instanceof AutoSyncedComponent) - .ifPresent(c -> ((AutoSyncedComponent) c).applySyncPacket(copy)); - } finally { - copy.release(); - } - }); - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading entity components from network", e); - throw e; - } - }); + CcaClientInternals.registerComponentSync( + CardinalComponentsEntity.PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(Objects.requireNonNull(ctx.client().world).getEntityById(payload.targetData())) + ); } if (FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1")) { ClientEntityEvents.ENTITY_LOAD.register((entity, world) -> ((ComponentProvider) entity).getComponentContainer().onClientLoad()); diff --git a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/mixin/entity/common/MixinEntity.java b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/mixin/entity/common/MixinEntity.java index e95b2296..e18cb4b9 100644 --- a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/mixin/entity/common/MixinEntity.java +++ b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/mixin/entity/common/MixinEntity.java @@ -26,16 +26,13 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.entity.CardinalComponentsEntity; import dev.onyxstudios.cca.internal.entity.CardinalEntityInternals; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; @@ -47,7 +44,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; @@ -96,14 +92,13 @@ public Iterable getRecipientsForComponentSync() { return List.of(); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeInt(this.getId()); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsEntity.PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsEntity.PACKET_ID, + this.getId(), + key, + data + ); } - } diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CardinalComponentsLevel.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CardinalComponentsLevel.java index 3a87e41f..704a46e4 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CardinalComponentsLevel.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CardinalComponentsLevel.java @@ -22,29 +22,31 @@ */ package dev.onyxstudios.cca.internal.level; +import com.mojang.datafixers.util.Unit; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; import dev.onyxstudios.cca.api.v3.world.WorldSyncCallback; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; +import dev.onyxstudios.cca.internal.base.MorePacketCodecs; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; -import net.minecraft.util.Identifier; import net.minecraft.world.WorldProperties; public final class CardinalComponentsLevel { + /** * {@link CustomPayloadS2CPacket} channel for default level component synchronization. * - *

Packets emitted on this channel must begin with the - * {@link ComponentKey#getId() component's type} (as an Identifier). - * *

Components synchronized through this channel will have {@linkplain AutoSyncedComponent#applySyncPacket(PacketByteBuf)} * called on the game thread. */ - public static final Identifier PACKET_ID = new Identifier("cardinal-components", "level_sync"); + public static final CustomPayload.Id> PACKET_ID = CustomPayload.id("cardinal-components:level_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(PACKET_ID, MorePacketCodecs.EMPTY); if (FabricLoader.getInstance().isModLoaded("cardinal-components-world")) { WorldSyncCallback.EVENT.register((player, world) -> { WorldProperties props = world.getLevelProperties(); diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelClient.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelClient.java index 2694bcbc..b8232dc8 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelClient.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelClient.java @@ -22,46 +22,18 @@ */ package dev.onyxstudios.cca.internal.level; -import dev.onyxstudios.cca.api.v3.component.Component; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; + +import java.util.Objects; public final class CcaLevelClient { public static void initClient() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { - ClientPlayNetworking.registerGlobalReceiver(CardinalComponentsLevel.PACKET_ID, (client, handler, buffer, res) -> { - try { - Identifier componentTypeId = buffer.readIdentifier(); - ComponentKey componentKey = ComponentRegistry.get(componentTypeId); - - if (componentKey == null) { - return; - } - - PacketByteBuf copy = new PacketByteBuf(buffer.copy()); - client.execute(() -> { - try { - assert client.world != null; - Component c = componentKey.get(client.world.getLevelProperties()); - - if (c instanceof AutoSyncedComponent) { - ((AutoSyncedComponent) c).applySyncPacket(copy); - } - } finally { - copy.release(); - } - }); - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading world save components from network", e); - throw e; - } - }); + CcaClientInternals.registerComponentSync( + CardinalComponentsLevel.PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(Objects.requireNonNull(ctx.client().world).getLevelProperties()) + ); } } } diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelUpdatePayload.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelUpdatePayload.java new file mode 100644 index 00000000..a471420a --- /dev/null +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/CcaLevelUpdatePayload.java @@ -0,0 +1,46 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2024 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal.level; + +import dev.onyxstudios.cca.api.v3.component.ComponentKey; +import dev.onyxstudios.cca.internal.base.MorePacketCodecs; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.packet.CustomPayload; + +public record CcaLevelUpdatePayload( + ComponentKey componentKey, + RegistryByteBuf buf +) implements CustomPayload { + + public static final PacketCodec CODEC = PacketCodec.tuple( + ComponentKey.PACKET_CODEC, CcaLevelUpdatePayload::componentKey, + MorePacketCodecs.REG_BYTE_BUF, CcaLevelUpdatePayload::buf, + CcaLevelUpdatePayload::new + ); + + @Override + public Id getId() { + return CardinalComponentsLevel.PACKET_ID; + } +} diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/mixin/level/common/MixinLevelProperties.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/mixin/level/common/MixinLevelProperties.java index e9057630..ca70909c 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/mixin/level/common/MixinLevelProperties.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/mixin/level/common/MixinLevelProperties.java @@ -22,23 +22,22 @@ */ package dev.onyxstudios.cca.mixin.level.common; +import com.mojang.datafixers.util.Unit; import com.mojang.serialization.Dynamic; import com.mojang.serialization.Lifecycle; import dev.onyxstudios.cca.api.v3.component.ComponentContainer; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.level.CardinalComponentsLevel; import dev.onyxstudios.cca.internal.level.StaticLevelComponentPlugin; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.boss.dragon.EnderDragonFight; import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.border.WorldBorder; import net.minecraft.world.gen.GeneratorOptions; import net.minecraft.world.level.LevelInfo; @@ -53,7 +52,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Set; import java.util.UUID; @@ -62,8 +60,8 @@ public abstract class MixinLevelProperties implements ServerWorldProperties, Com @Unique private ComponentContainer components; - @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;ZIIIFJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/entity/boss/dragon/EnderDragonFight$Data;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lnet/minecraft/world/level/LevelProperties$SpecialProperty;Lcom/mojang/serialization/Lifecycle;)V", at = @At("RETURN")) - private void initComponents(NbtCompound playerData, boolean modded, int spawnX, int spawnY, int spawnZ, float spawnAngle, long time, long timeOfDay, int version, int clearWeatherTime, int rainTime, boolean raining, int thunderTime, boolean thundering, boolean initialized, boolean difficultyLocked, WorldBorder.Properties worldBorder, int wanderingTraderSpawnDelay, int wanderingTraderSpawnChance, UUID wanderingTraderId, Set serverBrands, Set removedFeatures, Timer scheduledEvents, NbtCompound customBossEvents, EnderDragonFight.Data dragonFight, LevelInfo levelInfo, GeneratorOptions generatorOptions, LevelProperties.SpecialProperty specialProperty, Lifecycle lifecycle, CallbackInfo ci) { + @Inject(method = "(Lnet/minecraft/nbt/NbtCompound;ZLnet/minecraft/util/math/BlockPos;FJJIIIZIZZZLnet/minecraft/world/border/WorldBorder$Properties;IILjava/util/UUID;Ljava/util/Set;Ljava/util/Set;Lnet/minecraft/world/timer/Timer;Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/entity/boss/dragon/EnderDragonFight$Data;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/world/gen/GeneratorOptions;Lnet/minecraft/world/level/LevelProperties$SpecialProperty;Lcom/mojang/serialization/Lifecycle;)V", at = @At("RETURN")) + private void initComponents(NbtCompound playerData, boolean modded, BlockPos spawnPos, float spawnAngle, long time, long timeOfDay, int version, int clearWeatherTime, int rainTime, boolean raining, int thunderTime, boolean thundering, boolean initialized, boolean difficultyLocked, WorldBorder.Properties worldBorder, int wanderingTraderSpawnDelay, int wanderingTraderSpawnChance, UUID wanderingTraderId, Set serverBrands, Set removedFeatures, Timer scheduledEvents, NbtCompound customBossEvents, EnderDragonFight.Data dragonFight, LevelInfo levelInfo, GeneratorOptions generatorOptions, LevelProperties.SpecialProperty specialProperty, Lifecycle lifecycle, CallbackInfo ci) { this.components = StaticLevelComponentPlugin.createContainer(this); } @@ -88,13 +86,14 @@ public Iterable getRecipientsForComponentSync() { throw new UnsupportedOperationException("Please call LevelComponents#sync(MinecraftServer) instead of ComponentKey#sync"); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsLevel.PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsLevel.PACKET_ID, + Unit.INSTANCE, + key, + data + ); } } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CardinalComponentsScoreboard.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CardinalComponentsScoreboard.java index 07c48665..0e927f2f 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CardinalComponentsScoreboard.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CardinalComponentsScoreboard.java @@ -22,41 +22,42 @@ */ package dev.onyxstudios.cca.internal.scoreboard; +import com.mojang.datafixers.util.Unit; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; import dev.onyxstudios.cca.api.v3.scoreboard.ScoreboardSyncCallback; import dev.onyxstudios.cca.api.v3.scoreboard.TeamAddCallback; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; +import dev.onyxstudios.cca.internal.base.MorePacketCodecs; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.network.packet.CustomPayload; import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; import net.minecraft.scoreboard.Team; -import net.minecraft.util.Identifier; public final class CardinalComponentsScoreboard { /** * {@link CustomPayloadS2CPacket} channel for default scoreboard component synchronization. * - *

Packets emitted on this channel must begin with the {@link Identifier} for the component's type. - * *

Components synchronized through this channel will have {@linkplain AutoSyncedComponent#applySyncPacket(PacketByteBuf)} * called on the game thread. */ - public static final Identifier SCOREBOARD_PACKET_ID = new Identifier("cardinal-components", "scoreboard_sync"); + public static final CustomPayload.Id> SCOREBOARD_PACKET_ID = CustomPayload.id("cardinal-components:scoreboard_sync"); /** * {@link CustomPayloadS2CPacket} channel for default team component synchronization. * - *

Packets emitted on this channel must begin with, in order, the team's name as a {@link String}, - * and the {@link Identifier} for the component's type. - * *

Components synchronized through this channel will have {@linkplain AutoSyncedComponent#applySyncPacket(PacketByteBuf)} * called on the game thread. */ - public static final Identifier TEAM_PACKET_ID = new Identifier("cardinal-components", "team_sync"); + public static final CustomPayload.Id> TEAM_PACKET_ID = CustomPayload.id("cardinal-components:team_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(SCOREBOARD_PACKET_ID, MorePacketCodecs.EMPTY); + ComponentUpdatePayload.register(TEAM_PACKET_ID, PacketCodecs.STRING); ScoreboardSyncCallback.EVENT.register((player, tracked) -> { for (ComponentKey key : tracked.asComponentProvider().getComponentContainer().keys()) { key.syncWith(player, tracked.asComponentProvider()); diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CcaScoreboardClient.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CcaScoreboardClient.java index 60c591e6..865af156 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CcaScoreboardClient.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/CcaScoreboardClient.java @@ -22,57 +22,22 @@ */ package dev.onyxstudios.cca.internal.scoreboard; -import dev.onyxstudios.cca.api.v3.component.Component; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.Identifier; -import java.util.Optional; -import java.util.function.BiFunction; -import java.util.function.Function; +import java.util.Objects; public final class CcaScoreboardClient { public static void initClient() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { - registerScoreboardSync(CardinalComponentsScoreboard.TEAM_PACKET_ID, buf -> { - String teamName = buf.readString(); - return (componentType, scoreboard) -> componentType.maybeGet(scoreboard.getTeam(teamName)); - }); - registerScoreboardSync(CardinalComponentsScoreboard.SCOREBOARD_PACKET_ID, - buf -> ComponentKey::maybeGet + CcaClientInternals.registerComponentSync( + CardinalComponentsScoreboard.TEAM_PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(Objects.requireNonNull(ctx.client().world).getScoreboard().getTeam(payload.targetData())) + ); + CcaClientInternals.registerComponentSync( + CardinalComponentsScoreboard.SCOREBOARD_PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(Objects.requireNonNull(ctx.client().world).getScoreboard()) ); } } - - private static void registerScoreboardSync(Identifier packetId, Function, Scoreboard, Optional>> reader) { - ClientPlayNetworking.registerGlobalReceiver(packetId, (client, handler, buffer, res) -> { - try { - BiFunction, Scoreboard, Optional> getter = reader.apply(buffer); - Identifier componentTypeId = buffer.readIdentifier(); - ComponentKey componentType = ComponentRegistry.get(componentTypeId); - - if (componentType != null) { - buffer.retain(); - client.execute(() -> { - try { - getter.apply(componentType, handler.getWorld().getScoreboard()) - .filter(c -> c instanceof AutoSyncedComponent) - .ifPresent(c -> ((AutoSyncedComponent) c).applySyncPacket(buffer)); - } finally { - buffer.release(); - } - }); - } - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading scoreboard components from network", e); - throw e; - } - }); - } } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinServerScoreboard.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinServerScoreboard.java index 0d337f5e..a0b2e7e9 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinServerScoreboard.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinServerScoreboard.java @@ -22,17 +22,15 @@ */ package dev.onyxstudios.cca.mixin.scoreboard; +import com.mojang.datafixers.util.Unit; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; import dev.onyxstudios.cca.api.v3.scoreboard.TeamAddCallback; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.scoreboard.CardinalComponentsScoreboard; import dev.onyxstudios.cca.internal.scoreboard.ScoreboardComponentContainerFactory; import dev.onyxstudios.cca.internal.scoreboard.StaticScoreboardComponentPlugin; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.ServerScoreboard; import net.minecraft.scoreboard.Team; @@ -46,7 +44,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import javax.annotation.Nullable; import java.util.List; import java.util.function.Supplier; @@ -69,13 +66,14 @@ public Iterable getRecipientsForComponentSync() { return List.of(); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsScoreboard.SCOREBOARD_PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsScoreboard.SCOREBOARD_PACKET_ID, + Unit.INSTANCE, + key, + data + ); } @Inject(method = "", at = @At("RETURN")) diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinTeam.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinTeam.java index 92358380..592f795e 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinTeam.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinTeam.java @@ -26,13 +26,10 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.scoreboard.CardinalComponentsScoreboard; import dev.onyxstudios.cca.internal.scoreboard.StaticScoreboardComponentPlugin; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.server.network.ServerPlayerEntity; @@ -45,7 +42,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nonnull; -import javax.annotation.Nullable; @Mixin(Team.class) public abstract class MixinTeam implements ComponentProvider, TeamAccessor { @@ -78,14 +74,13 @@ public Iterable getRecipientsForComponentSync() { return this.scoreboard.asComponentProvider().getRecipientsForComponentSync(); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeString(this.getName()); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsScoreboard.TEAM_PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsScoreboard.TEAM_PACKET_ID, + this.getName(), + key, + data + ); } - } diff --git a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CardinalComponentsWorld.java b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CardinalComponentsWorld.java index d9080dfd..f4d6629a 100644 --- a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CardinalComponentsWorld.java +++ b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CardinalComponentsWorld.java @@ -22,18 +22,22 @@ */ package dev.onyxstudios.cca.internal.world; +import com.mojang.datafixers.util.Unit; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentProvider; import dev.onyxstudios.cca.api.v3.world.WorldSyncCallback; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; +import dev.onyxstudios.cca.internal.base.MorePacketCodecs; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.util.Identifier; +import net.minecraft.network.packet.CustomPayload; public final class CardinalComponentsWorld { - public static final Identifier PACKET_ID = new Identifier("cardinal-components", "world_sync"); + public static final CustomPayload.Id> PACKET_ID = ComponentUpdatePayload.id("world_sync"); public static void init() { if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + ComponentUpdatePayload.register(PACKET_ID, MorePacketCodecs.EMPTY); WorldSyncCallback.EVENT.register((player, world) -> { ComponentProvider provider = (ComponentProvider) world; for (ComponentKey key : provider.getComponentContainer().keys()) { diff --git a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CcaWorldClient.java b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CcaWorldClient.java index c7add4cf..de0fe01d 100644 --- a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CcaWorldClient.java +++ b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/CcaWorldClient.java @@ -22,42 +22,16 @@ */ package dev.onyxstudios.cca.internal.world; -import dev.onyxstudios.cca.api.v3.component.Component; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.internal.base.ComponentsInternals; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.minecraft.util.Identifier; +import dev.onyxstudios.cca.internal.base.CcaClientInternals; +import net.fabricmc.loader.api.FabricLoader; public final class CcaWorldClient { public static void initClient() { - ClientPlayNetworking.registerGlobalReceiver(CardinalComponentsWorld.PACKET_ID, (client, handler, buf, res) -> { - try { - Identifier componentTypeId = buf.readIdentifier(); - ComponentKey componentType = ComponentRegistry.get(componentTypeId); - - if (componentType == null) { - return; - } - - buf.retain(); - - client.execute(() -> { - try { - assert client.world != null; - Component c = componentType.get(client.world); - if (c instanceof AutoSyncedComponent) { - ((AutoSyncedComponent) c).applySyncPacket(buf); - } - } finally { - buf.release(); - } - }); - } catch (Exception e) { - ComponentsInternals.LOGGER.error("Error while reading world components from network", e); - throw e; - } - }); + if (FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1")) { + CcaClientInternals.registerComponentSync( + CardinalComponentsWorld.PACKET_ID, + (payload, ctx) -> payload.componentKey().maybeGet(ctx.client().world) + ); + } } } diff --git a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/mixin/world/common/MixinServerWorld.java b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/mixin/world/common/MixinServerWorld.java index 8f4473e1..2ba286c4 100644 --- a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/mixin/world/common/MixinServerWorld.java +++ b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/mixin/world/common/MixinServerWorld.java @@ -22,15 +22,13 @@ */ package dev.onyxstudios.cca.mixin.world.common; +import com.mojang.datafixers.util.Unit; import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter; +import dev.onyxstudios.cca.internal.base.ComponentUpdatePayload; import dev.onyxstudios.cca.internal.world.CardinalComponentsWorld; import dev.onyxstudios.cca.internal.world.ComponentPersistentState; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.RegistryByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.world.PersistentStateManager; @@ -41,7 +39,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import javax.annotation.Nullable; import java.util.List; import java.util.function.BooleanSupplier; @@ -78,12 +75,13 @@ public Iterable getRecipientsForComponentSync() { return this.getPlayers(); } - @Nullable @Override - public CustomPayloadS2CPacket toComponentPacket(ComponentKey key, ComponentPacketWriter writer, ServerPlayerEntity recipient) { - PacketByteBuf buf = PacketByteBufs.create(); - buf.writeIdentifier(key.getId()); - writer.writeSyncPacket(buf, recipient); - return (CustomPayloadS2CPacket) ServerPlayNetworking.createS2CPacket(CardinalComponentsWorld.PACKET_ID, buf); + public ComponentUpdatePayload toComponentPacket(ComponentKey key, RegistryByteBuf data) { + return new ComponentUpdatePayload<>( + CardinalComponentsWorld.PACKET_ID, + Unit.INSTANCE, + key, + data + ); } } diff --git a/gradle.properties b/gradle.properties index 3045466a..135615f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,11 +4,11 @@ org.gradle.parallel=true fabric.loom.multiProjectOptimisation=true #see https://fabricmc.net/develop/ -minecraft_version=1.20.4 +minecraft_version=24w04a yarn_mappings=3 -loader_version=0.15.3 +loader_version=0.15.6 #Fabric api -fabric_api_version=0.92.0+1.20.4 +fabric_api_version=0.95.3+1.20.5 elmendorf_version=0.12.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84a0b92f..a5952066 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index cd561c59..ed6214d3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,7 @@ pluginManagement { url = 'https://server.bbkr.space/artifactory/libs-release/' } gradlePluginPortal() + mavenLocal() } } rootProject.name = 'cardinal-components-api' diff --git a/src/testmod/java/dev/onyxstudios/componenttest/content/TestComponents.java b/src/testmod/java/dev/onyxstudios/componenttest/content/TestComponents.java index 762db675..0f8209f1 100644 --- a/src/testmod/java/dev/onyxstudios/componenttest/content/TestComponents.java +++ b/src/testmod/java/dev/onyxstudios/componenttest/content/TestComponents.java @@ -79,7 +79,7 @@ public void registerItemComponentFactories(ItemComponentFactoryRegistry registry // this first line adds data to every stack, which is a fairly bad idea for several reasons // it also initializes the component with volatile data (stack count), which is an even worse idea and will cause desync registry.register(i -> true, ALT_VITA, (stack) -> { - ItemVita ret = new ItemVita(stack); + ItemVita ret = new ItemVita(stack, ALT_VITA); ret.setVitality(stack.getItem() == Items.DIAMOND_CHESTPLATE ? 3 : stack.getCount()); return ret; }); diff --git a/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityCondenser.java b/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityCondenser.java index 265cc547..bd435db6 100644 --- a/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityCondenser.java +++ b/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityCondenser.java @@ -30,7 +30,6 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; @@ -51,14 +50,12 @@ public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Ran Vita.get(world).transferTo(Vita.get(world.getChunk(pos)), 1); } - @SuppressWarnings("deprecation") - @ApiStatus.OverrideOnly @Override - public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hitInfo) { + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { // only on client side, to confirm that sync works if (world.isClient) { player.sendMessage(Text.translatable("componenttest:action.chunk_vitality", - Objects.requireNonNull(CcaBlockTestMod.VITA_API_LOOKUP.find(world, pos, state, null, hitInfo.getSide())).getVitality()), true); + Objects.requireNonNull(CcaBlockTestMod.VITA_API_LOOKUP.find(world, pos, state, null, hit.getSide())).getVitality()), true); } return ActionResult.SUCCESS; } diff --git a/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityStickItem.java b/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityStickItem.java index 0385db77..ec8330f2 100644 --- a/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityStickItem.java +++ b/src/testmod/java/dev/onyxstudios/componenttest/content/VitalityStickItem.java @@ -107,7 +107,7 @@ public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity holder vita.ifPresent(v -> v.transferTo(Vita.get(team), 1)); } - stack.damage(1, holder, e -> e.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND)); + stack.damage(1, holder, EquipmentSlot.MAINHAND); return true; } diff --git a/src/testmod/java/dev/onyxstudios/componenttest/content/vita/ItemVita.java b/src/testmod/java/dev/onyxstudios/componenttest/content/vita/ItemVita.java index 52f44c29..9b2e1585 100644 --- a/src/testmod/java/dev/onyxstudios/componenttest/content/vita/ItemVita.java +++ b/src/testmod/java/dev/onyxstudios/componenttest/content/vita/ItemVita.java @@ -22,6 +22,7 @@ */ package dev.onyxstudios.componenttest.content.vita; +import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.item.ItemComponent; import dev.onyxstudios.cca.test.base.Vita; import net.minecraft.item.ItemStack; @@ -31,6 +32,10 @@ public ItemVita(ItemStack stack) { super(stack); } + public ItemVita(ItemStack stack, ComponentKey key) { + super(stack, key); + } + @Override public int getVitality() { return this.getInt("vitality");