diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index cab845559..cc347e0bb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -47,6 +47,7 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Registry; +import org.bukkit.block.BlockType; import org.bukkit.block.data.BlockData; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; @@ -885,4 +886,21 @@ public final class BukkitBlockManager extends AbstractBlockManager { } } } + + @Override + protected int getBlockRegistryId(Key id) { + Object block = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id)); + return FastNMS.INSTANCE.method$IdMap$getId(MBuiltInRegistries.BLOCK, block).orElseThrow(() -> new IllegalStateException("Block " + id + " not found")); + } + + @Override + protected boolean isVanillaBlock(Key id) { + if (!id.namespace().equals("minecraft")) { + return false; + } + if (id.value().equals("air")) { + return true; + } + return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id)) != MBlocks.AIR; + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java index 680d5b8e5..6a5d6bab2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java @@ -12,9 +12,11 @@ import net.momirealms.craftengine.bukkit.util.ItemStackUtils; import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.sparrow.nbt.Tag; import org.bukkit.inventory.ItemStack; +import java.util.Objects; import java.util.Optional; public class ComponentItemWrapper implements ItemWrapper { @@ -104,6 +106,18 @@ public class ComponentItemWrapper implements ItemWrapper { return FastNMS.INSTANCE.method$ItemStack$hasComponent(getLiteralObject(), ensureDataComponentType(type)); } + public boolean hasNonDefaultComponent(Object type) { + if (VersionHelper.isOrAbove1_21_4()) { + return FastNMS.INSTANCE.method$ItemStack$hasNonDefaultComponent(getLiteralObject(), ensureDataComponentType(type)); + } else { + Object item = FastNMS.INSTANCE.method$ItemStack$getItem(this.getLiteralObject()); + Object componentMap = FastNMS.INSTANCE.method$Item$components(item); + Object componentType = ensureDataComponentType(type); + Object defaultComponent = FastNMS.INSTANCE.method$DataComponentMap$get(componentMap, componentType); + return !Objects.equals(defaultComponent, getComponentExact(componentType)); + } + } + public void setComponentExact(Object type, final Object value) { FastNMS.INSTANCE.method$ItemStack$setComponent(this.getLiteralObject(), ensureDataComponentType(type), value); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java index 19838cdc9..c8f760d99 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java @@ -165,6 +165,11 @@ public abstract class BukkitItemFactory> extend throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); } + @Override + protected boolean hasNonDefaultComponent(W item, Object type) { + throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); + } + @Override protected void setComponent(W item, Object type, Object value) { throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java index 3dfeab143..447500af0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java @@ -267,6 +267,11 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory section) { + if (isVanillaBlock(id)) { + parseVanillaBlock(pack, path, id, section); + } else { + // check duplicated config + if (AbstractBlockManager.this.byId.containsKey(id)) { + throw new LocalizedResourceConfigException("warning.config.block.duplicate"); + } + parseCustomBlock(pack, path, id, section); + } + } + + private void parseVanillaBlock(Pack pack, Path path, Key id, Map section) { + Map settings = MiscUtils.castToMap(section.get("settings"), true); + if (settings != null) { + Object clientBoundTags = settings.get("client-bound-tags"); + if (clientBoundTags instanceof List list) { + List clientSideTags = MiscUtils.getAsStringList(list).stream().filter(ResourceLocation::isValid).toList(); + AbstractBlockManager.this.clientBoundTags.put(getBlockRegistryId(id), clientSideTags); + } + } + } + + private void parseCustomBlock(Pack pack, Path path, Key id, Map section) { + // 获取方块设置 + BlockSettings settings = BlockSettings.fromMap(id, MiscUtils.castToMap(section.get("settings"), true)); + // + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index 3f7a75d8f..5d5799233 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -371,6 +371,11 @@ public class AbstractItem, I> implements Item { return this.factory.hasComponent(this.item, type); } + @Override + public boolean hasNonDefaultComponent(Object type) { + return this.factory.hasNonDefaultComponent(this.item, type); + } + @Override public void removeComponent(Object type) { this.factory.removeComponent(this.item, type); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index 8e8b9e043..cd324882a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -73,7 +73,12 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl for (Map.Entry dataEntry : dataSection.entrySet()) { Object value = dataEntry.getValue(); if (value == null) continue; - Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(dataEntry.getKey(), Key.DEFAULT_NAMESPACE))).ifPresent(factory -> { + String key = dataEntry.getKey(); + int idIndex = key.indexOf('#'); + if (idIndex != -1) { + key = key.substring(0, idIndex); + } + Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(key, Key.DEFAULT_NAMESPACE))).ifPresent(factory -> { try { callback.accept((ItemDataModifier) factory.create(value)); } catch (LocalizedResourceConfigException e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java index 69c9a68f8..8c48642be 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java @@ -163,6 +163,8 @@ public interface Item { boolean hasComponent(Object type); + boolean hasNonDefaultComponent(Object type); + void removeComponent(Object type); void setExactComponent(Object type, Object value); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java index 43de1de6f..b2cac48ba 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java @@ -69,6 +69,8 @@ public abstract class ItemFactory, I> { protected abstract void resetComponent(W item, Object type); + protected abstract boolean hasNonDefaultComponent(W item, Object type); + protected abstract I getItem(W item); protected abstract void customModelData(W item, Integer data); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java index f120401e8..7828a2dc8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemDataModifiers.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.item.modifier; import net.momirealms.craftengine.core.item.ItemDataModifierFactory; +import net.momirealms.craftengine.core.item.modifier.lore.OverwritableLoreModifier; import net.momirealms.craftengine.core.item.modifier.lore.DynamicLoreModifier; import net.momirealms.craftengine.core.item.modifier.lore.LoreModifier; import net.momirealms.craftengine.core.registry.BuiltInRegistries; @@ -40,10 +41,15 @@ public final class ItemDataModifiers { public static final Key LORE = Key.of("craftengine:lore"); public static final Key UNBREAKABLE = Key.of("craftengine:unbreakable"); public static final Key DYNAMIC_LORE = Key.of("craftengine:dynamic-lore"); + public static final Key OVERWRITABLE_LORE = Key.of("craftengine:overwritable-lore"); public static void register(Key key, ItemDataModifierFactory factory) { ((WritableRegistry>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY) .register(ResourceKey.create(Registries.ITEM_DATA_MODIFIER_FACTORY.location(), key), factory); + if (key.value().contains("-")) { + ((WritableRegistry>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY) + .register(ResourceKey.create(Registries.ITEM_DATA_MODIFIER_FACTORY.location(), new Key(key.namespace(), key.value().replace("-", "_"))), factory); + } } public static void init() {} @@ -52,6 +58,7 @@ public final class ItemDataModifiers { register(EXTERNAL, ExternalModifier.FACTORY); register(LORE, LoreModifier.FACTORY); register(DYNAMIC_LORE, DynamicLoreModifier.FACTORY); + register(OVERWRITABLE_LORE, OverwritableLoreModifier.FACTORY); register(DYED_COLOR, DyedColorModifier.FACTORY); register(TAGS, TagsModifier.FACTORY); register(NBT, TagsModifier.FACTORY); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/lore/OverwritableLoreModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/lore/OverwritableLoreModifier.java new file mode 100644 index 000000000..82c944859 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/lore/OverwritableLoreModifier.java @@ -0,0 +1,64 @@ +package net.momirealms.craftengine.core.item.modifier.lore; + +import net.momirealms.craftengine.core.item.ComponentKeys; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.ItemDataModifierFactory; +import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; +import net.momirealms.craftengine.core.item.modifier.ItemDataModifiers; +import net.momirealms.craftengine.core.item.modifier.SimpleNetworkItemDataModifier; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.sparrow.nbt.CompoundTag; + +public final class OverwritableLoreModifier implements SimpleNetworkItemDataModifier { + public static final Factory FACTORY = new Factory<>(); + private final LoreModifier loreModifier; + + public OverwritableLoreModifier(LoreModifier loreModifier) { + this.loreModifier = loreModifier; + } + + @Override + public Key type() { + return ItemDataModifiers.OVERWRITABLE_LORE; + } + + @Override + public Item apply(Item item, ItemBuildContext context) { + if (item.hasNonDefaultComponent(ComponentKeys.LORE)) { + return item; + } + return this.loreModifier.apply(item, context); + } + + @Override + public Key componentType(Item item, ItemBuildContext context) { + return ComponentKeys.LORE; + } + + @Override + public Object[] nbtPath(Item item, ItemBuildContext context) { + return new Object[]{"display", "Lore"}; + } + + @Override + public String nbtPathString(Item item, ItemBuildContext context) { + return "display.Lore"; + } + + public static class Factory implements ItemDataModifierFactory { + @Override + public ItemDataModifier create(Object arg) { + LoreModifier lore = LoreModifier.createLoreModifier(arg); + return new OverwritableLoreModifier<>(lore); + } + } + + @Override + public Item prepareNetworkItem(Item item, ItemBuildContext context, CompoundTag networkData) { + if (item.hasNonDefaultComponent(ComponentKeys.LORE)) { + return item; + } + return SimpleNetworkItemDataModifier.super.prepareNetworkItem(item, context, networkData); + } +} diff --git a/gradle.properties b/gradle.properties index 4d209dd7a..75cc0ec10 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.18 -nms_helper_version=1.0.55 +nms_helper_version=1.0.56 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23