From 37b9455c00fd3a985ab3e7a263203f3e7283b060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=9B=9F=E9=BE=99?= <75253383+TheFloodDragon@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:55:50 +0800 Subject: [PATCH] Reimplement Hide specified item components (#215) * [Reimplement] Hide specified item components * cleanup --- .../0078-Hide-specified-item-components.patch | 47 +++++++++++ ...during-inactive-ticks-for-non-aware.patch} | 0 ...zombie-reinforcements-loading-chunk.patch} | 0 ...aperPR-Fix-some-beacon-event-issues.patch} | 0 ...82-Dont-send-useless-entity-packets.patch} | 0 ...n-t-spawn-if-lastSpawnState-is-null.patch} | 0 ...patch => 0084-Multithreaded-Tracker.patch} | 0 ...> 0085-Nitori-Async-playerdata-Save.patch} | 0 ...e-nearby-alive-players-for-spawning.patch} | 0 ...> 0087-Cache-blockstate-cache-array.patch} | 0 ....patch => 0088-Asynchronous-locator.patch} | 0 ...tities-in-NearestLivingEntitySensor.patch} | 0 ...uce-memory-footprint-of-CompoundTag.patch} | 0 ... 0091-Optimize-Entity-distanceToSqr.patch} | 0 ...e-snapshots-for-TileEntity-getOwner.patch} | 0 ... => 0093-Cache-tile-entity-position.patch} | 0 ...patch => 0094-TT20-Lag-compensation.patch} | 0 ...tch => 0095-C2ME-Reduce-Allocations.patch} | 0 ...cessary-calculations-if-player-is-n.patch} | 0 ...til.patch => 0097-Lithium-fast-util.patch} | 0 ...atch => 0098-Lithium-CompactSineLUT.patch} | 0 ...099-Lithium-cached-iterate-outwards.patch} | 0 ...atch => 0100-Smooth-teleport-config.patch} | 0 ...read-safe-ban-list-date-format-pars.patch} | 0 ...tartEachNonRunningBehavior-in-Brain.patch} | 0 ... => 0103-Lithium-equipment-tracking.patch} | 0 ...> 0104-C2ME-Optimize-world-gen-math.patch} | 0 ...k-key.patch => 0105-Cache-chunk-key.patch} | 0 ...0106-Cache-random-tick-block-status.patch} | 0 ...7-Cache-part-of-canHoldFluid-result.patch} | 0 ... => 0108-Configurable-tripwire-dupe.patch} | 0 .../modules/gameplay/HideItemComponent.java | 62 ++++++++++++++ .../leaf/util/item/ItemStackStripper.java | 80 +++++++++++++++++++ 33 files changed, 189 insertions(+) create mode 100644 leaf-server/minecraft-patches/features/0078-Hide-specified-item-components.patch rename leaf-server/minecraft-patches/features/{0078-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch => 0079-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch} (100%) rename leaf-server/minecraft-patches/features/{0079-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch => 0080-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch} (100%) rename leaf-server/minecraft-patches/features/{0080-PaperPR-Fix-some-beacon-event-issues.patch => 0081-PaperPR-Fix-some-beacon-event-issues.patch} (100%) rename leaf-server/minecraft-patches/features/{0081-Dont-send-useless-entity-packets.patch => 0082-Dont-send-useless-entity-packets.patch} (100%) rename leaf-server/minecraft-patches/features/{0082-Don-t-spawn-if-lastSpawnState-is-null.patch => 0083-Don-t-spawn-if-lastSpawnState-is-null.patch} (100%) rename leaf-server/minecraft-patches/features/{0083-Multithreaded-Tracker.patch => 0084-Multithreaded-Tracker.patch} (100%) rename leaf-server/minecraft-patches/features/{0084-Nitori-Async-playerdata-Save.patch => 0085-Nitori-Async-playerdata-Save.patch} (100%) rename leaf-server/minecraft-patches/features/{0085-Optimize-nearby-alive-players-for-spawning.patch => 0086-Optimize-nearby-alive-players-for-spawning.patch} (100%) rename leaf-server/minecraft-patches/features/{0086-Cache-blockstate-cache-array.patch => 0087-Cache-blockstate-cache-array.patch} (100%) rename leaf-server/minecraft-patches/features/{0087-Asynchronous-locator.patch => 0088-Asynchronous-locator.patch} (100%) rename leaf-server/minecraft-patches/features/{0088-Smart-sort-entities-in-NearestLivingEntitySensor.patch => 0089-Smart-sort-entities-in-NearestLivingEntitySensor.patch} (100%) rename leaf-server/minecraft-patches/features/{0089-Further-reduce-memory-footprint-of-CompoundTag.patch => 0090-Further-reduce-memory-footprint-of-CompoundTag.patch} (100%) rename leaf-server/minecraft-patches/features/{0090-Optimize-Entity-distanceToSqr.patch => 0091-Optimize-Entity-distanceToSqr.patch} (100%) rename leaf-server/minecraft-patches/features/{0091-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch => 0092-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch} (100%) rename leaf-server/minecraft-patches/features/{0092-Cache-tile-entity-position.patch => 0093-Cache-tile-entity-position.patch} (100%) rename leaf-server/minecraft-patches/features/{0093-TT20-Lag-compensation.patch => 0094-TT20-Lag-compensation.patch} (100%) rename leaf-server/minecraft-patches/features/{0094-C2ME-Reduce-Allocations.patch => 0095-C2ME-Reduce-Allocations.patch} (100%) rename leaf-server/minecraft-patches/features/{0095-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch => 0096-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch} (100%) rename leaf-server/minecraft-patches/features/{0096-Lithium-fast-util.patch => 0097-Lithium-fast-util.patch} (100%) rename leaf-server/minecraft-patches/features/{0097-Lithium-CompactSineLUT.patch => 0098-Lithium-CompactSineLUT.patch} (100%) rename leaf-server/minecraft-patches/features/{0098-Lithium-cached-iterate-outwards.patch => 0099-Lithium-cached-iterate-outwards.patch} (100%) rename leaf-server/minecraft-patches/features/{0099-Smooth-teleport-config.patch => 0100-Smooth-teleport-config.patch} (100%) rename leaf-server/minecraft-patches/features/{0100-Use-faster-and-thread-safe-ban-list-date-format-pars.patch => 0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch} (100%) rename leaf-server/minecraft-patches/features/{0101-Collect-then-startEachNonRunningBehavior-in-Brain.patch => 0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch} (100%) rename leaf-server/minecraft-patches/features/{0102-Lithium-equipment-tracking.patch => 0103-Lithium-equipment-tracking.patch} (100%) rename leaf-server/minecraft-patches/features/{0103-C2ME-Optimize-world-gen-math.patch => 0104-C2ME-Optimize-world-gen-math.patch} (100%) rename leaf-server/minecraft-patches/features/{0104-Cache-chunk-key.patch => 0105-Cache-chunk-key.patch} (100%) rename leaf-server/minecraft-patches/features/{0105-Cache-random-tick-block-status.patch => 0106-Cache-random-tick-block-status.patch} (100%) rename leaf-server/minecraft-patches/features/{0106-Cache-part-of-canHoldFluid-result.patch => 0107-Cache-part-of-canHoldFluid-result.patch} (100%) rename leaf-server/minecraft-patches/features/{0107-Configurable-tripwire-dupe.patch => 0108-Configurable-tripwire-dupe.patch} (100%) create mode 100644 leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/HideItemComponent.java create mode 100644 leaf-server/src/main/java/org/dreeam/leaf/util/item/ItemStackStripper.java diff --git a/leaf-server/minecraft-patches/features/0078-Hide-specified-item-components.patch b/leaf-server/minecraft-patches/features/0078-Hide-specified-item-components.patch new file mode 100644 index 00000000..3f166fce --- /dev/null +++ b/leaf-server/minecraft-patches/features/0078-Hide-specified-item-components.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheFloodDragon <1610105206@qq.com> +Date: Fri, 7 Feb 2025 18:41:55 +0800 +Subject: [PATCH] Hide specified item components + + +diff --git a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +index 828fbe03e7beb860cd0816c7ac8adbffe196533b..f602c4c55483a189f973929b982f1834ca7e9952 100644 +--- a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +@@ -53,8 +53,8 @@ public class ClientboundContainerSetContentPacket implements Packet> hiddenTypes = List.of(); + + @Override + public void onLoaded() { + config.addCommentRegionBased(getBasePath(), """ + Controls whether specified component information would be sent to clients. + It may break resource packs and mods that rely on the information. + Also, it can avoid some frequent client animations. + Attention: This is not same as Paper's item-obfuscation, we only hide specified component information from player's inventory.""", + """ + 控制哪些物品组件信息会被发送至客户端. + 可能会导致依赖物品组件的资源包/模组无法正常工作. + 可以避免一些客户端动画效果. + 注意: 此项与 Paper 的 item-obfuscation 不同, 我们只从玩家背包中隐藏物品指定的组件信息."""); + List list = config.getList(getBasePath() + ".hidden-types", new ArrayList<>(), config.pickStringRegionBased(""" + Which type of components will be hidden from clients. + It needs a component type list, incorrect things will not work.""", + """ + 被隐藏的物品组件类型列表. + 该配置项接受一个物品组件列表, 格式不正确将不会启用.""")); + enabled = config.getBoolean(getBasePath() + ".enabled", enabled, config.pickStringRegionBased( + "If enabled, specified item component information from player's inventory will be hided.", + "启用后, 玩家背包内物品的指定组件信息会被隐藏." + )); + + final List> types = new ArrayList<>(list.size()); + + for (String componentType : list) { + BuiltInRegistries.DATA_COMPONENT_TYPE.get(ResourceLocation.parse(componentType)).ifPresentOrElse( + optional -> types.add(optional.value()), + () -> LeafConfig.LOGGER.warn("Unknown component type: {}", componentType) + ); + } + + hiddenTypes = types; + } +} diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/item/ItemStackStripper.java b/leaf-server/src/main/java/org/dreeam/leaf/util/item/ItemStackStripper.java new file mode 100644 index 00000000..9e70d46e --- /dev/null +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/item/ItemStackStripper.java @@ -0,0 +1,80 @@ +package org.dreeam.leaf.util.item; + +import net.minecraft.core.component.DataComponentMap; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.world.item.ItemStack; +import org.dreeam.leaf.config.modules.gameplay.HideItemComponent; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * ItemStackStripper + * + * @author TheFloodDragon + * @since 2025/2/4 19:04 + */ +public class ItemStackStripper { + + public static ItemStack strip(final ItemStack itemStack, final boolean copy) { + if (!HideItemComponent.enabled || itemStack.isEmpty() || itemStack.getComponentsPatch().isEmpty()) + return itemStack; + + final ItemStack copied = copy ? itemStack.copy() : itemStack; + + // Remove specified types + for (DataComponentType type : HideItemComponent.hiddenTypes) { + // Only remove, no others + copied.remove(type); + } + + return copied; + } + + public static List strip(final List itemStacks, final boolean copy) { + if (!HideItemComponent.enabled) return itemStacks; + + final List copiedItems = new ArrayList<>(); + + for (ItemStack itemStack : itemStacks) { + if (itemStack.isEmpty() || itemStack.getComponentsPatch().isEmpty()) { + copiedItems.add(itemStack); + continue; + } + + final ItemStack copied = copy ? itemStack.copy() : itemStack; + + // Remove specified types + for (DataComponentType type : HideItemComponent.hiddenTypes) { + // Only remove, no others + copied.remove(type); + } + + copiedItems.add(copied); + } + + return copiedItems; + } + + /** + * Check if two ItemStacks are the same after stripping components + */ + public static boolean matchesStripped(ItemStack left, ItemStack right) { + if (HideItemComponent.enabled) { + return left == right || ( + left.is(right.getItem()) && left.getCount() == right.getCount() && + (left.isEmpty() && right.isEmpty() || Objects.equals(strip(left.getComponents()), strip(right.getComponents()))) + ); + } + + return ItemStack.matches(left, right); + } + + /** + * @return a new DataComponentMap with all hidden components removed + */ + private static DataComponentMap strip(final DataComponentMap map) { + return map.filter(c -> !HideItemComponent.hiddenTypes.contains(c)); + } +}