9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 09:59:15 +00:00

Reimplement Hide specified item components (#215)

* [Reimplement] Hide specified item components

* cleanup
This commit is contained in:
蛟龙
2025-02-08 22:55:50 +08:00
committed by GitHub
parent 055b650cd0
commit 37b9455c00
33 changed files with 189 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
package org.dreeam.leaf.config.modules.gameplay;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import org.dreeam.leaf.config.ConfigModules;
import org.dreeam.leaf.config.EnumConfigCategory;
import org.dreeam.leaf.config.LeafConfig;
import java.util.ArrayList;
import java.util.List;
/**
* HideItemComponent
*
* @author TheFloodDragon
* @since 2025/2/4 18:30
*/
public class HideItemComponent extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".hide-item-component";
}
public static boolean enabled = false;
public static List<DataComponentType<?>> 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<String> 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<DataComponentType<?>> 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;
}
}

View File

@@ -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<ItemStack> strip(final List<ItemStack> itemStacks, final boolean copy) {
if (!HideItemComponent.enabled) return itemStacks;
final List<ItemStack> 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));
}
}