diff --git a/patches/server/0036-Jade-Protocol.patch b/patches/server/0036-Jade-Protocol.patch index f9842905..4ea85964 100644 --- a/patches/server/0036-Jade-Protocol.patch +++ b/patches/server/0036-Jade-Protocol.patch @@ -124,7 +124,7 @@ index 30d0133a42ce990352f5c492fcf9beb105364848..1ab2eab686b3a89d406f127a6036c0e2 protected CompositeLootItemCondition(List terms, Predicate predicate) { diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java new file mode 100644 -index 0000000000000000000000000000000000000000..eb26708fafa054ba32c5deed43c8496d5496f6a9 +index 0000000000000000000000000000000000000000..438dfee78f7114e7c8d3d57c5dcc90e1fcc75a4c --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java @@ -0,0 +1,311 @@ @@ -196,7 +196,7 @@ index 0000000000000000000000000000000000000000..eb26708fafa054ba32c5deed43c8496d +import org.leavesmc.leaves.protocol.jade.provider.block.CommandBlockProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.FurnaceProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.HopperLockProvider; -+import org.leavesmc.leaves.protocol.jade.provider.block.ItemStorageProvider; ++import org.leavesmc.leaves.protocol.jade.provider.ItemStorageProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.JukeboxProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.LecternProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.MobSpawnerCooldownProvider; @@ -442,20 +442,18 @@ index 0000000000000000000000000000000000000000..eb26708fafa054ba32c5deed43c8496d \ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java new file mode 100644 -index 0000000000000000000000000000000000000000..9c9b469f805196dd97e02d93a11232d043f5e854 +index 0000000000000000000000000000000000000000..1a637045d9375ae357ca1e592ec0dc7b45fa47fa --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java -@@ -0,0 +1,37 @@ +@@ -0,0 +1,32 @@ +package org.leavesmc.leaves.protocol.jade.accessor; + -+import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamEncoder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.HitResult; -+import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface Accessor { @@ -464,9 +462,6 @@ index 0000000000000000000000000000000000000000..9c9b469f805196dd97e02d93a11232d0 + + Player getPlayer(); + -+ @NotNull -+ CompoundTag getServerData(); -+ + Tag encodeAsNbt(StreamEncoder codec, D value); + + T getHitResult(); @@ -485,20 +480,18 @@ index 0000000000000000000000000000000000000000..9c9b469f805196dd97e02d93a11232d0 +} diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..38d6b146d9135fb7c985f1f4e8a804bb490ff0df +index 0000000000000000000000000000000000000000..a04fbb45b466d8999b40717d8d48f650b81fe82a --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java -@@ -0,0 +1,92 @@ +@@ -0,0 +1,83 @@ +package org.leavesmc.leaves.protocol.jade.accessor; + +import java.util.function.Supplier; + +import org.apache.commons.lang3.ArrayUtils; -+import org.jetbrains.annotations.NotNull; + +import io.netty.buffer.Unpooled; +import net.minecraft.nbt.ByteArrayTag; -+import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamEncoder; @@ -510,20 +503,18 @@ index 0000000000000000000000000000000000000000..38d6b146d9135fb7c985f1f4e8a804bb + + private final Level level; + private final Player player; -+ private final CompoundTag serverData; + private final Supplier hit; + private final boolean serverConnected; + private final boolean showDetails; + protected boolean verify; + private RegistryFriendlyByteBuf buffer; + -+ public AccessorImpl(Level level, Player player, CompoundTag serverData, Supplier hit, boolean serverConnected, boolean showDetails) { ++ public AccessorImpl(Level level, Player player, Supplier hit, boolean serverConnected, boolean showDetails) { + this.level = level; + this.player = player; + this.hit = hit; + this.serverConnected = serverConnected; + this.showDetails = showDetails; -+ this.serverData = serverData == null ? new CompoundTag() : serverData.copy(); + } + + @Override @@ -536,11 +527,6 @@ index 0000000000000000000000000000000000000000..38d6b146d9135fb7c985f1f4e8a804bb + return player; + } + -+ @Override -+ public final @NotNull CompoundTag getServerData() { -+ return serverData; -+ } -+ + private RegistryFriendlyByteBuf buffer() { + if (buffer == null) { + buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), level.registryAccess()); @@ -639,10 +625,10 @@ index 0000000000000000000000000000000000000000..12d689ca80887dcd5dbf68ea2c38a8ad +} diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..4a2cd64c7911b756f737ed34f245f7366668f417 +index 0000000000000000000000000000000000000000..9e4a321b91a8afc480ef506487608255db2b9c89 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java -@@ -0,0 +1,166 @@ +@@ -0,0 +1,163 @@ +package org.leavesmc.leaves.protocol.jade.accessor; + +import java.util.function.Supplier; @@ -653,7 +639,6 @@ index 0000000000000000000000000000000000000000..4a2cd64c7911b756f737ed34f245f736 + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; -+import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; @@ -678,7 +663,7 @@ index 0000000000000000000000000000000000000000..4a2cd64c7911b756f737ed34f245f736 + private final Supplier blockEntity; + + private BlockAccessorImpl(Builder builder) { -+ super(builder.level, builder.player, builder.serverData, Suppliers.ofInstance(builder.hit), builder.connected, builder.showDetails); ++ super(builder.level, builder.player, Suppliers.ofInstance(builder.hit), builder.connected, builder.showDetails); + blockState = builder.blockState; + blockEntity = builder.blockEntity; + } @@ -718,7 +703,6 @@ index 0000000000000000000000000000000000000000..4a2cd64c7911b756f737ed34f245f736 + + private Level level; + private Player player; -+ private CompoundTag serverData; + private boolean connected; + private boolean showDetails; + private BlockHitResult hit; @@ -765,7 +749,6 @@ index 0000000000000000000000000000000000000000..4a2cd64c7911b756f737ed34f245f736 + public Builder from(BlockAccessor accessor) { + level = accessor.getLevel(); + player = accessor.getPlayer(); -+ serverData = accessor.getServerData(); + connected = accessor.isServerConnected(); + showDetails = accessor.showDetails(); + hit = accessor.getHitResult(); @@ -862,14 +845,13 @@ index 0000000000000000000000000000000000000000..454360d5e5c01cad3c197b078d536a9f \ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..f670ac9b7ee72bbf3fa4f509cc2cdaeee238ccff +index 0000000000000000000000000000000000000000..65d16c0024372ede4cec230b7aad54de28de15f2 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java -@@ -0,0 +1,126 @@ +@@ -0,0 +1,123 @@ +package org.leavesmc.leaves.protocol.jade.accessor; + +import com.google.common.base.Suppliers; -+import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; @@ -889,7 +871,7 @@ index 0000000000000000000000000000000000000000..f670ac9b7ee72bbf3fa4f509cc2cdaee + private final Supplier entity; + + public EntityAccessorImpl(Builder builder) { -+ super(builder.level, builder.player, builder.serverData, builder.hit, builder.connected, builder.showDetails); ++ super(builder.level, builder.player, builder.hit, builder.connected, builder.showDetails); + entity = builder.entity; + } + @@ -914,7 +896,6 @@ index 0000000000000000000000000000000000000000..f670ac9b7ee72bbf3fa4f509cc2cdaee + public boolean showDetails; + private Level level; + private Player player; -+ private CompoundTag serverData; + private boolean connected; + private Supplier hit; + private Supplier entity; @@ -953,7 +934,6 @@ index 0000000000000000000000000000000000000000..f670ac9b7ee72bbf3fa4f509cc2cdaee + public Builder from(EntityAccessor accessor) { + level = accessor.getLevel(); + player = accessor.getPlayer(); -+ serverData = accessor.getServerData(); + connected = accessor.isServerConnected(); + showDetails = accessor.showDetails(); + hit = accessor::getHitResult; @@ -1251,10 +1231,10 @@ index 0000000000000000000000000000000000000000..6e32eed15f028020223e2500849b4db3 \ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java new file mode 100644 -index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe348c895b14 +index 0000000000000000000000000000000000000000..797558f3804a1a8143eafafd5dc46cc72ea19a42 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java -@@ -0,0 +1,142 @@ +@@ -0,0 +1,138 @@ +package org.leavesmc.leaves.protocol.jade.provider; + +import com.google.common.cache.Cache; @@ -1263,7 +1243,6 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 +import net.minecraft.world.Container; +import net.minecraft.world.LockCode; +import net.minecraft.world.RandomizableContainer; -+import net.minecraft.world.WorldlyContainer; +import net.minecraft.world.WorldlyContainerHolder; +import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.player.Player; @@ -1274,6 +1253,8 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.minecraft.world.level.block.entity.EnderChestBlockEntity; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.LeavesLogger; +import org.leavesmc.leaves.protocol.jade.JadeProtocol; +import org.leavesmc.leaves.protocol.jade.accessor.Accessor; @@ -1290,21 +1271,16 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 + INSTANCE; + + public static final Cache> targetCache = CacheBuilder.newBuilder().weakKeys().expireAfterAccess(60, TimeUnit.SECONDS).build(); -+ public static final Cache> containerCache = CacheBuilder.newBuilder().weakKeys().expireAfterAccess(120, TimeUnit.SECONDS).build(); + + private static final ResourceLocation UNIVERSAL_ITEM_STORAGE = JadeProtocol.mc_id("item_storage.default"); + + @Override + public List> getGroups(Accessor request) { + Object target = request.getTarget(); -+ if (target == null && request instanceof BlockAccessor blockAccessor && blockAccessor.getBlock() instanceof WorldlyContainerHolder holder) { -+ WorldlyContainer container = holder.getContainer(blockAccessor.getBlockState(), request.getLevel(), blockAccessor.getPosition()); -+ return containerGroup(container, request); -+ } + + switch (target) { + case null -> { -+ return List.of(); ++ return createItemCollector(request).update(request); + } + case RandomizableContainer te when te.getLootTable() != null -> { + return List.of(); @@ -1325,22 +1301,18 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 + + if (target instanceof EnderChestBlockEntity) { + PlayerEnderChestContainer inventory = player.getEnderChestInventory(); -+ return new ItemCollector<>(new ItemIterator.ContainerItemIterator(0)).update(inventory, request.getLevel().getGameTime()); ++ return new ItemCollector<>(new ItemIterator.ContainerItemIterator(x -> inventory, 0)).update(request); + } + + ItemCollector itemCollector; + try { -+ itemCollector = targetCache.get(target, () -> createItemCollector(target)); ++ itemCollector = targetCache.get(target, () -> createItemCollector(request)); + } catch (ExecutionException e) { + LeavesLogger.LOGGER.severe("Failed to get item collector for " + target); + return null; + } + -+ if (itemCollector == ItemCollector.EMPTY) { -+ return null; -+ } -+ -+ return itemCollector.update(target, request.getLevel().getGameTime()); ++ return itemCollector.update(request); + } + + @Override @@ -1348,16 +1320,8 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 + return UNIVERSAL_ITEM_STORAGE; + } + -+ public static List> containerGroup(Container container, Accessor accessor) { -+ try { -+ return containerCache.get(container, () -> new ItemCollector<>(new ItemIterator.ContainerItemIterator(0))).update(container, accessor.getLevel().getGameTime()); -+ } catch (ExecutionException e) { -+ return null; -+ } -+ } -+ -+ public static ItemCollector createItemCollector(Object target) { -+ if (target instanceof AbstractHorse) { ++ public static ItemCollector createItemCollector(Accessor request) { ++ if (request.getTarget() instanceof AbstractHorse) { + return new ItemCollector<>(new ItemIterator.ContainerItemIterator(o -> { + if (o instanceof AbstractHorse horse) { + return horse.inventory; @@ -1368,8 +1332,9 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 + + // TODO BlockEntity like fabric's ItemStorage + -+ if (target instanceof Container) { -+ if (target instanceof ChestBlockEntity) { ++ final Container container = findContainer(request); ++ if (container != null) { ++ if (container instanceof ChestBlockEntity) { + return new ItemCollector<>(new ItemIterator.ContainerItemIterator(o -> { + if (o instanceof ChestBlockEntity blockEntity) { + if (blockEntity.getBlockState().getBlock() instanceof ChestBlock chestBlock) { @@ -1392,11 +1357,117 @@ index 0000000000000000000000000000000000000000..7680ff97d99e15a9b3475ef83f7cfe34 + return ItemCollector.EMPTY; + } + ++ public static @Nullable Container findContainer(@NotNull Accessor accessor) { ++ Object target = accessor.getTarget(); ++ if (target == null && accessor instanceof BlockAccessor blockAccessor && ++ blockAccessor.getBlock() instanceof WorldlyContainerHolder holder) { ++ return holder.getContainer(blockAccessor.getBlockState(), accessor.getLevel(), blockAccessor.getPosition()); ++ } else if (target instanceof Container container) { ++ return container; ++ } ++ return null; ++ } ++ + @Override + public int getDefaultPriority() { + return IServerExtensionProvider.super.getDefaultPriority() + 1000; + } +} +diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8289b5c48213348a7346dfdbb30ee1b8787d2a2d +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java +@@ -0,0 +1,88 @@ ++package org.leavesmc.leaves.protocol.jade.provider; ++ ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.RegistryFriendlyByteBuf; ++import net.minecraft.network.codec.StreamCodec; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.LockCode; ++import net.minecraft.world.RandomizableContainer; ++import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; ++import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; ++import org.jetbrains.annotations.NotNull; ++import org.leavesmc.leaves.protocol.jade.JadeProtocol; ++import org.leavesmc.leaves.protocol.jade.accessor.Accessor; ++import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; ++import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; ++import org.leavesmc.leaves.protocol.jade.util.CommonUtil; ++import org.leavesmc.leaves.protocol.jade.util.ItemCollector; ++import org.leavesmc.leaves.protocol.jade.util.ViewGroup; ++ ++import java.util.List; ++import java.util.Map; ++ ++public abstract class ItemStorageProvider> implements IServerDataProvider { ++ ++ private static final StreamCodec>>> STREAM_CODEC = ViewGroup.listCodec( ++ ItemStack.OPTIONAL_STREAM_CODEC); ++ ++ private static final ResourceLocation UNIVERSAL_ITEM_STORAGE = JadeProtocol.mc_id("item_storage"); ++ ++ public static ForBlock getBlock() { ++ return ForBlock.INSTANCE; ++ } ++ ++ public static ForEntity getEntity() { ++ return ForEntity.INSTANCE; ++ } ++ ++ public static class ForBlock extends ItemStorageProvider { ++ private static final ForBlock INSTANCE = new ForBlock(); ++ } ++ ++ public static class ForEntity extends ItemStorageProvider { ++ private static final ForEntity INSTANCE = new ForEntity(); ++ } ++ ++ public static void putData(CompoundTag tag, @NotNull Accessor accessor) { ++ Object target = accessor.getTarget(); ++ Player player = accessor.getPlayer(); ++ Map.Entry>> entry = CommonUtil.getServerExtensionData(accessor, JadeProtocol.itemStorageProviders); ++ if (entry != null) { ++ List> groups = entry.getValue(); ++ for (ViewGroup group : groups) { ++ if (group.views.size() > ItemCollector.MAX_SIZE) { ++ group.views = group.views.subList(0, ItemCollector.MAX_SIZE); ++ } ++ } ++ tag.put(UNIVERSAL_ITEM_STORAGE.toString(), accessor.encodeAsNbt(STREAM_CODEC, entry)); ++ return; ++ } ++ if (target instanceof RandomizableContainer containerEntity && containerEntity.getLootTable() != null) { ++ tag.putBoolean("Loot", true); ++ } else if (!player.isCreative() && !player.isSpectator() && target instanceof BaseContainerBlockEntity te) { ++ if (te.lockKey != LockCode.NO_LOCK) { ++ tag.putBoolean("Locked", true); ++ } ++ } ++ } ++ ++ @Override ++ public ResourceLocation getUid() { ++ return UNIVERSAL_ITEM_STORAGE; ++ } ++ ++ @Override ++ public void appendServerData(CompoundTag tag, @NotNull T accessor) { ++ if (accessor.getTarget() instanceof AbstractFurnaceBlockEntity) { ++ return; ++ } ++ putData(tag, accessor); ++ } ++ ++ @Override ++ public int getDefaultPriority() { ++ return 9999; ++ } ++} +\ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..52887edb3359c5eb1900cd1eec912e52afef2c9f @@ -1776,105 +1847,6 @@ index 0000000000000000000000000000000000000000..a3937081bd923d3b6f2ee966dc95aa23 + } +} \ No newline at end of file -diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ItemStorageProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ItemStorageProvider.java -new file mode 100644 -index 0000000000000000000000000000000000000000..f4eb38d4b5d98a286964cdb68581bb9a2d836def ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ItemStorageProvider.java -@@ -0,0 +1,92 @@ -+package org.leavesmc.leaves.protocol.jade.provider.block; -+ -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.network.RegistryFriendlyByteBuf; -+import net.minecraft.network.codec.StreamCodec; -+import net.minecraft.resources.ResourceLocation; -+import net.minecraft.world.LockCode; -+import net.minecraft.world.RandomizableContainer; -+import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -+import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; -+import org.jetbrains.annotations.NotNull; -+import org.leavesmc.leaves.protocol.jade.JadeProtocol; -+import org.leavesmc.leaves.protocol.jade.accessor.Accessor; -+import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; -+import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; -+import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; -+import org.leavesmc.leaves.protocol.jade.util.CommonUtil; -+import org.leavesmc.leaves.protocol.jade.util.ItemCollector; -+import org.leavesmc.leaves.protocol.jade.util.ViewGroup; -+ -+import java.util.List; -+import java.util.Map; -+ -+public abstract class ItemStorageProvider> implements IServerDataProvider { -+ -+ private static final StreamCodec>>> STREAM_CODEC = ViewGroup.listCodec( -+ ItemStack.OPTIONAL_STREAM_CODEC); -+ -+ private static final ResourceLocation UNIVERSAL_ITEM_STORAGE = JadeProtocol.mc_id("item_storage.default"); -+ -+ public static ForBlock getBlock() { -+ return ForBlock.INSTANCE; -+ } -+ -+ public static ForEntity getEntity() { -+ return ForEntity.INSTANCE; -+ } -+ -+ public static class ForBlock extends ItemStorageProvider { -+ private static final ForBlock INSTANCE = new ForBlock(); -+ } -+ -+ public static class ForEntity extends ItemStorageProvider { -+ private static final ForEntity INSTANCE = new ForEntity(); -+ } -+ -+ public static void putData(Accessor accessor) { -+ CompoundTag tag = accessor.getServerData(); -+ Object target = accessor.getTarget(); -+ Player player = accessor.getPlayer(); -+ Map.Entry>> entry = CommonUtil.getServerExtensionData( -+ accessor, -+ JadeProtocol.itemStorageProviders); -+ if (entry != null) { -+ List> groups = entry.getValue(); -+ for (ViewGroup group : groups) { -+ if (group.views.size() > ItemCollector.MAX_SIZE) { -+ group.views = group.views.subList(0, ItemCollector.MAX_SIZE); -+ } -+ } -+ tag.put(UNIVERSAL_ITEM_STORAGE.toString(), accessor.encodeAsNbt(STREAM_CODEC, entry)); -+ return; -+ } -+ if (target instanceof RandomizableContainer containerEntity && containerEntity.getLootTable() != null) { -+ tag.putBoolean("Loot", true); -+ } else if (!player.isCreative() && !player.isSpectator() && target instanceof BaseContainerBlockEntity te) { -+ if (te.lockKey != LockCode.NO_LOCK) { -+ tag.putBoolean("Locked", true); -+ } -+ } -+ } -+ -+ @Override -+ public ResourceLocation getUid() { -+ return UNIVERSAL_ITEM_STORAGE; -+ } -+ -+ @Override -+ public void appendServerData(CompoundTag tag, @NotNull T accessor) { -+ if (accessor.getTarget() instanceof AbstractFurnaceBlockEntity) { -+ return; -+ } -+ putData(accessor); -+ } -+ -+ @Override -+ public int getDefaultPriority() { -+ return 9999; -+ } -+} -\ No newline at end of file diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/JukeboxProvider.java b/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/JukeboxProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..0b6e224ebc8d6acdc29abf51f7d98b667baf0984 @@ -2830,10 +2802,10 @@ index 0000000000000000000000000000000000000000..137cdf619879390477b4fc8c4b7ecee5 + diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java b/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java new file mode 100644 -index 0000000000000000000000000000000000000000..769c331035e59408064b63a29d8bf2194b386aa0 +index 0000000000000000000000000000000000000000..8f57cb0714dc684bd90325a6d2e84d5b1b303d6e --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java -@@ -0,0 +1,114 @@ +@@ -0,0 +1,116 @@ +package org.leavesmc.leaves.protocol.jade.util; + +import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; @@ -2843,6 +2815,7 @@ index 0000000000000000000000000000000000000000..769c331035e59408064b63a29d8bf219 +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; ++import org.leavesmc.leaves.protocol.jade.accessor.Accessor; + +import java.util.List; +import java.util.Locale; @@ -2877,15 +2850,16 @@ index 0000000000000000000000000000000000000000..769c331035e59408064b63a29d8bf219 + this.iterator = iterator; + } + -+ public List> update(Object target, long gameTime) { ++ public List> update(Accessor request) { + if (iterator == null) { + return null; + } -+ T container = iterator.find(target); ++ T container = iterator.find(request.getTarget()); + if (container == null) { + return null; + } + long currentVersion = iterator.getVersion(container); ++ long gameTime = request.getLevel().getGameTime(); + if (mergedResult != null && iterator.isFinished()) { + if (version == currentVersion) { + return mergedResult; // content not changed