diff --git a/src/test/java/com/modularmc/synceddata/test/SyncAnnotationTest.java b/src/test/java/com/modularmc/synceddata/test/SyncAnnotationTest.java index ea8e318..cfbe937 100644 --- a/src/test/java/com/modularmc/synceddata/test/SyncAnnotationTest.java +++ b/src/test/java/com/modularmc/synceddata/test/SyncAnnotationTest.java @@ -2,6 +2,7 @@ import com.modularmc.synceddata.api.sync_system.meta.ClassSyncData; +import net.minecraft.core.BlockPos; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -160,4 +161,52 @@ public static void item(GameTestHelper helper) { check(helper, restored.e == 500, "item rt"); helper.succeed(); } + + @TestHolder(value = "sync_registered_block_entity") + @EmptyTemplate("3") + @GameTest + public static void registeredBlockEntity(GameTestHelper helper) { + helper.setBlock(1, 1, 1, SyncedTestContent.TEST_SYNC_BLOCK.get()); + var blockEntity = helper.getBlockEntity(new BlockPos(1, 1, 1), SyncTestFixtures.TestManagedBlockEntity.class); + blockEntity.energy = 240; + blockEntity.config = "gt"; + blockEntity.target = 9; + + var saveTag = blockEntity.getSyncDataHolder().serializeToSaveNBT(helper.getLevel().registryAccess()); + check(helper, saveTag.getInt("energy").orElse(0) == 240, "energy save missing"); + + byte[] serverChanges = blockEntity.getSyncDataHolder().collectServerNetworkChanges(helper.getLevel().registryAccess()); + check(helper, serverChanges.length > 0, "server network payload missing"); + + var restored = new SyncTestFixtures.TestManagedBlockEntity(); + restored.getSyncDataHolder().applyServerNetworkUpdate(helper.getLevel().registryAccess(), serverChanges); + check(helper, restored.target == 9, "registered block entity target not restored"); + helper.succeed(); + } + + @TestHolder(value = "sync_registered_block_item") + @EmptyTemplate("3") + @GameTest + public static void registeredBlockItem(GameTestHelper helper) { + helper.setBlock(1, 1, 1, SyncedTestContent.TEST_SYNC_BLOCK.get()); + var blockEntity = helper.getBlockEntity(new BlockPos(1, 1, 1), SyncTestFixtures.TestManagedBlockEntity.class); + blockEntity.energy = 512; + blockEntity.config = "item-data"; + blockEntity.target = 33; + + ItemStack stack = SyncedTestContent.TEST_SYNC_BLOCK_ITEM.toStack(); + var components = blockEntity.collectItemComponentsForTest(); + stack.applyComponents(components); + + helper.setBlock(2, 1, 1, SyncedTestContent.TEST_SYNC_BLOCK.get()); + var restored = helper.getBlockEntity(new BlockPos(2, 1, 1), SyncTestFixtures.TestManagedBlockEntity.class); + restored.applyItemComponentsForTest(stack.getComponents()); + check(helper, restored.config.equals("item-data"), "block item config not restored"); + check(helper, restored.target == 0, "block item should not restore sync-only field"); + check(helper, restored.energy == 0, "block item should not restore save-only field"); + + restored.getSyncDataHolder().loadFromItemStack(stack, helper.getLevel().registryAccess()); + check(helper, restored.config.equals("item-data"), "loadFromItemStack config not restored"); + helper.succeed(); + } } diff --git a/src/test/java/com/modularmc/synceddata/test/SyncTestFixtures.java b/src/test/java/com/modularmc/synceddata/test/SyncTestFixtures.java index 85270db..a5826b2 100644 --- a/src/test/java/com/modularmc/synceddata/test/SyncTestFixtures.java +++ b/src/test/java/com/modularmc/synceddata/test/SyncTestFixtures.java @@ -1,6 +1,8 @@ package com.modularmc.synceddata.test; +import com.modularmc.synceddata.api.blockentity.BlockEntityCreationInfo; import com.modularmc.synceddata.api.sync_system.ISyncManaged; +import com.modularmc.synceddata.api.sync_system.ManagedSyncBlockEntity; import com.modularmc.synceddata.api.sync_system.annotations.ClientFieldChangeListener; import com.modularmc.synceddata.api.sync_system.annotations.ItemSave; import com.modularmc.synceddata.api.sync_system.annotations.RerenderOnChanged; @@ -11,6 +13,9 @@ import com.modularmc.synceddata.api.sync_system.holder.SyncDataHolder; import com.modularmc.synceddata.api.sync_system.meta.FieldCodecs; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponentGetter; +import net.minecraft.core.component.DataComponentMap; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; @@ -177,6 +182,44 @@ void onTarget() { } } + static final class TestManagedBlockEntity extends ManagedSyncBlockEntity { + + @SaveField + int energy; + @ItemSave + String config; + @SyncBoth + int target; + final List callbacks = new ArrayList<>(); + + TestManagedBlockEntity(BlockPos pos, net.minecraft.world.level.block.state.BlockState state) { + super(SyncedTestContent.TEST_SYNC_BLOCK_ENTITY.get(), pos, state); + } + + TestManagedBlockEntity() { + super(new BlockEntityCreationInfo(SyncedTestContent.TEST_SYNC_BLOCK_ENTITY.get(), BlockPos.ZERO, + SyncedTestContent.TEST_SYNC_BLOCK.get().defaultBlockState())); + } + + @ClientFieldChangeListener(fieldName = "target") + void onTargetChanged() { + callbacks.add("target"); + } + + @Override + public void scheduleRenderUpdate() {} + + DataComponentMap collectItemComponentsForTest() { + DataComponentMap.Builder builder = DataComponentMap.builder(); + collectImplicitComponents(builder); + return builder.build(); + } + + void applyItemComponentsForTest(DataComponentGetter components) { + applyImplicitComponents(components); + } + } + static class TestItemData implements ISyncManaged { final ItemSyncHolder itemSyncHolder = new ItemSyncHolder(this); diff --git a/src/test/java/com/modularmc/synceddata/test/SyncedTestContent.java b/src/test/java/com/modularmc/synceddata/test/SyncedTestContent.java new file mode 100644 index 0000000..463010b --- /dev/null +++ b/src/test/java/com/modularmc/synceddata/test/SyncedTestContent.java @@ -0,0 +1,62 @@ +package com.modularmc.synceddata.test; + +import com.modularmc.synceddata.SyncedData; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredItem; +import net.neoforged.neoforge.registries.DeferredRegister; + +import com.mojang.serialization.MapCodec; + +public final class SyncedTestContent { + + public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(SyncedData.MOD_ID); + public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(SyncedData.MOD_ID); + public static final DeferredRegister> BLOCK_ENTITY_TYPES = DeferredRegister.create(net.minecraft.core.registries.Registries.BLOCK_ENTITY_TYPE, SyncedData.MOD_ID); + + public static final DeferredBlock TEST_SYNC_BLOCK = BLOCKS.registerBlock("test_sync_block", TestSyncBlock::new, properties -> properties.strength(1.5F)); + public static final DeferredItem TEST_SYNC_BLOCK_ITEM = ITEMS.registerSimpleBlockItem("test_sync_block", TEST_SYNC_BLOCK); + public static final DeferredHolder, BlockEntityType> TEST_SYNC_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("test_sync_block_entity", + () -> new BlockEntityType<>(SyncTestFixtures.TestManagedBlockEntity::new, TEST_SYNC_BLOCK.get())); + + private SyncedTestContent() {} + + public static void register(IEventBus bus) { + BLOCKS.register(bus); + ITEMS.register(bus); + BLOCK_ENTITY_TYPES.register(bus); + } + + public static final class TestSyncBlock extends BaseEntityBlock { + + public static final MapCodec CODEC = simpleCodec(TestSyncBlock::new); + + public TestSyncBlock(BlockBehaviour.Properties properties) { + super(properties); + } + + @Override + protected MapCodec codec() { + return CODEC; + } + + @Override + protected RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new SyncTestFixtures.TestManagedBlockEntity(pos, state); + } + } +} diff --git a/src/test/java/com/modularmc/synceddata/test/SyncedTestFramework.java b/src/test/java/com/modularmc/synceddata/test/SyncedTestFramework.java index 553c27a..412be26 100644 --- a/src/test/java/com/modularmc/synceddata/test/SyncedTestFramework.java +++ b/src/test/java/com/modularmc/synceddata/test/SyncedTestFramework.java @@ -11,6 +11,7 @@ public final class SyncedTestFramework { public SyncedTestFramework(IEventBus bus, ModContainer container) { + SyncedTestContent.register(bus); FrameworkConfiguration.builder(SyncedData.id("tests")) .build() .create()