diff --git a/README.md b/README.md index 29b3c4950..6e4078716 100644 --- a/README.md +++ b/README.md @@ -129,11 +129,10 @@ The code you contribute will be open-sourced under the GPLv3 license. If you pre 3. Once done, submit a **pull request** for review. We appreciate your contributions! ## Differences Between Versions -| Version | Official Support | Max Players | Online Mode Required | Commercial Use | -|-------------------|------------------|-------------|----------------------|----------------| -| Community Edition | ❌ No | 20 | ✔️ Yes | ✔️ Allowed | -| GitHub Edition | ❌ No | Unlimited | ❌ No | ✔️ Allowed | -| Premium Edition | ✔️ Yes | Unlimited | ❌ No | ✔️ Allowed | +| Version | Official Support | Max Players | Dev Builds | +|-------------------|------------------|-------------|------------| +| Community Edition | ❌ No | 20 | ❌ No | +| Premium Edition | ✔️ Yes | Unlimited | ✔️ Yes | ### 💖 Support the Developer Help sustain CraftEngine's development by going Premium! diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index f72ecec0e..724ff7f4c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -60,56 +60,6 @@ public class BukkitItemManager extends AbstractItemManager { this.debugStickListener = new DebugStickListener(plugin); this.armorEventListener = new ArmorEventListener(); this.registerAllVanillaItems(); - if (plugin.hasMod()) { - Class clazz$CustomStreamCodec = ReflectionUtils.getClazz("net.momirealms.craftengine.mod.item.CustomStreamCodec"); - if (clazz$CustomStreamCodec != null) { - Field s2cProcessor = ReflectionUtils.getDeclaredField(clazz$CustomStreamCodec, Function.class, 0); - Field c2sProcessor = ReflectionUtils.getDeclaredField(clazz$CustomStreamCodec, Function.class, 1); - Function s2c = (raw) -> { - ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(raw); - Item wrapped = this.wrap(itemStack.clone()); - Optional> customItem = wrapped.getCustomItem(); - if (customItem.isEmpty()) { - return raw; - } - CustomItem custom = customItem.get(); - if (!custom.hasClientBoundDataModifier()) { - return raw; - } - for (NetworkItemDataProcessor processor : custom.networkItemDataProcessors()) { - processor.toClient(wrapped, ItemBuildContext.EMPTY); - } - wrapped.load(); - return wrapped.getLiteralObject(); - }; - - Function c2s = (raw) -> { - ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(raw); - Item wrapped = this.wrap(itemStack); - Optional> customItem = wrapped.getCustomItem(); - if (customItem.isEmpty()) { - return raw; - } - CustomItem custom = customItem.get(); - if (!custom.hasClientBoundDataModifier()) { - return raw; - } - for (NetworkItemDataProcessor processor : custom.networkItemDataProcessors()) { - processor.toServer(wrapped, ItemBuildContext.EMPTY); - } - wrapped.load(); - return wrapped.getLiteralObject(); - }; - try { - assert s2cProcessor != null; - s2cProcessor.set(null, s2c); - assert c2sProcessor != null; - c2sProcessor.set(null, c2s); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to load custom stream codec", e); - } - } - } } @Override @@ -123,6 +73,34 @@ public class BukkitItemManager extends AbstractItemManager { return instance; } + @SuppressWarnings("DuplicatedCode") + public Optional s2c(ItemStack itemStack, ItemBuildContext context) { + Item wrapped = this.wrap(itemStack.clone()); + if (wrapped == null) return Optional.empty(); + Optional> customItem = wrapped.getCustomItem(); + if (customItem.isEmpty()) return Optional.empty(); + CustomItem custom = customItem.get(); + if (!custom.hasClientBoundDataModifier()) return Optional.empty(); + for (NetworkItemDataProcessor processor : custom.networkItemDataProcessors()) { + processor.toClient(wrapped, context); + } + return Optional.of(wrapped.load()); + } + + @SuppressWarnings("DuplicatedCode") + public Optional c2s(ItemStack itemStack, ItemBuildContext context) { + Item wrapped = this.wrap(itemStack); + if (wrapped == null) return Optional.empty(); + Optional> customItem = wrapped.getCustomItem(); + if (customItem.isEmpty()) return Optional.empty(); + CustomItem custom = customItem.get(); + if (!custom.hasClientBoundDataModifier()) return Optional.empty(); + for (NetworkItemDataProcessor processor : custom.networkItemDataProcessors()) { + processor.toServer(wrapped, context); + } + return Optional.of(wrapped.load()); + } + @Override public Optional> getVanillaItem(Key key) { Material material = Registry.MATERIAL.get(KeyUtils.toNamespacedKey(key)); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index df14f8079..051d18e54 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -174,6 +174,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket()); registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); + registerByteBufPacketConsumer(PacketConsumers.CONTAINER_SET_CONTENT, this.packetIds.clientboundContainerSetContentPacket()); } public static BukkitNetworkManager instance() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 230f8d88f..0767a1f3c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -13,6 +13,7 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.pack.BukkitPackManager; @@ -27,6 +28,7 @@ import net.momirealms.craftengine.core.font.FontManager; import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData; @@ -2147,6 +2149,50 @@ public class PacketConsumers { } }; + public static final BiConsumer CONTAINER_SET_CONTENT = (user, event) -> { + try { + FriendlyByteBuf buf = event.getBuffer(); + int containerId = buf.readContainerId(); + int stateId = buf.readVarInt(); + int listSize = buf.readVarInt(); + ItemBuildContext context = ItemBuildContext.of((BukkitServerPlayer) user); + List items = new ArrayList<>(listSize); + boolean changed = false; + Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); + for (int i = 0; i < listSize; i++) { + ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + Optional optional = BukkitItemManager.instance().s2c(itemStack, context); + if (optional.isPresent()) { + items.add(optional.get()); + changed = true; + } else { + items.add(itemStack); + } + } + ItemStack carriedItem = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + ItemStack newCarriedItem = carriedItem; + Optional optional = BukkitItemManager.instance().s2c(carriedItem, context); + if (optional.isPresent()) { + changed = true; + newCarriedItem = optional.get(); + } + if (!changed) return; + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeContainerId(containerId); + buf.writeVarInt(stateId); + buf.writeVarInt(listSize); + Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); + for (ItemStack itemStack : items) { + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); + } + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newCarriedItem); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundContainerSetContentPacket", e); + } + }; + public static final TriConsumer RESOURCE_PACK_PUSH = (user, event, packet) -> { try { if (!VersionHelper.isOrAbove1_20_2()) return; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java index 3ac33c779..3433c5e56 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java @@ -41,4 +41,6 @@ public interface PacketIds { int clientboundPlayerInfoUpdatePacket(); int clientboundSetScorePacket(); + + int clientboundContainerSetContentPacket(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java index a1c2c9831..ea05910aa 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java @@ -104,4 +104,9 @@ public class PacketIds1_20 implements PacketIds { public int clientboundSetScorePacket() { return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundSetScorePacket); } + + @Override + public int clientboundContainerSetContentPacket() { + return PacketIdFinder.clientboundByClazz(Reflections.clazz$ClientboundContainerSetContentPacket); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java index ea3437281..f5838edf2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java @@ -103,4 +103,9 @@ public class PacketIds1_20_5 implements PacketIds { public int clientboundSetScorePacket() { return PacketIdFinder.clientboundByName("minecraft:set_score"); } + + @Override + public int clientboundContainerSetContentPacket() { + return PacketIdFinder.clientboundByName("minecraft:container_set_content"); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index e8c3f2fa4..c7403b55a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -6822,9 +6822,10 @@ public class Reflections { .orElse(ReflectionUtils.getMethod(clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$Block, clazz$BlockPos, boolean.class)) ); -// public static final Method method$BlockBehaviour$getEntityInsideCollisionShape = requireNonNull( -// ReflectionUtils.getDeclaredMethod( -// clazz$BlockBehaviour, clazz$VoxelShape, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos, clazz$Entity -// ) -// ); + public static final Class clazz$ClientboundContainerSetContentPacket = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "network.protocol.game.PacketPlayOutWindowItems", + "network.protocol.game.ClientboundContainerSetContentPacket" + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java index 8f12573cb..a21cc9692 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java @@ -48,6 +48,18 @@ public class FriendlyByteBuf extends ByteBuf { return BlockPos.of(buf.readLong()); } + public int readContainerId() { + return VersionHelper.isOrAbove1_21_2() ? this.readVarInt() : this.readUnsignedByte(); + } + + public void writeContainerId(int id) { + if (VersionHelper.isOrAbove1_21_2()) { + this.writeVarInt(id); + } else { + this.writeByte(id); + } + } + public List readStringList() { int i = this.readVarInt(); List list = new ArrayList<>(i); diff --git a/gradle.properties b/gradle.properties index eefd53031..261a2d7a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.17 -nms_helper_version=0.65.33 +nms_helper_version=0.66 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23