diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlockStateWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlockStateWrapper.java index cf4cda67b..d70727e34 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlockStateWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlockStateWrapper.java @@ -7,6 +7,8 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.util.Key; +import java.util.Collection; +import java.util.List; import java.util.Optional; public class BukkitCustomBlockStateWrapper extends AbstractBlockStateWrapper { @@ -51,6 +53,12 @@ public class BukkitCustomBlockStateWrapper extends AbstractBlockStateWrapper { return getImmutableBlockState().map(state -> state.owner().value().getProperty(propertyName) != null).orElse(false); } + @Override + public Collection getPropertyNames() { + Optional immutableBlockState = getImmutableBlockState(); + return immutableBlockState.>map(state -> state.getProperties().stream().map(Property::name).toList()).orElseGet(List::of); + } + @Override public String getAsString() { return getImmutableBlockState().map(ImmutableBlockState::toString).orElseGet(() -> BlockStateUtils.fromBlockData(super.blockState).getAsString()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitVanillaBlockStateWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitVanillaBlockStateWrapper.java index 61c5d7172..e03939e5e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitVanillaBlockStateWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitVanillaBlockStateWrapper.java @@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.block.StatePropertyAccessor; import net.momirealms.craftengine.core.util.Key; +import java.util.Collection; + public class BukkitVanillaBlockStateWrapper extends AbstractBlockStateWrapper { private final StatePropertyAccessor accessor; @@ -31,6 +33,11 @@ public class BukkitVanillaBlockStateWrapper extends AbstractBlockStateWrapper { return this.accessor.hasProperty(propertyName); } + @Override + public Collection getPropertyNames() { + return this.accessor.getPropertyNames(); + } + @Override public String getAsString() { return BlockStateUtils.fromBlockData(super.blockState).getAsString(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ModernNetworkItemHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ModernNetworkItemHandler.java index 107c11a60..b04605fd6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ModernNetworkItemHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ModernNetworkItemHandler.java @@ -18,7 +18,6 @@ import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.ListTag; import net.momirealms.sparrow.nbt.StringTag; import net.momirealms.sparrow.nbt.Tag; -import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; 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 2231d8908..93ffa8b96 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 @@ -609,4 +609,14 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory> blockState(ComponentItemWrapper item) { + return Optional.empty(); + } + + @Override + protected void blockState(ComponentItemWrapper item, Map state) { + + } } \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java index d8c97482b..6c5ca4693 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateWrapper.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.sparrow.nbt.*; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.Map; public interface BlockStateWrapper extends Comparable { @@ -18,6 +19,8 @@ public interface BlockStateWrapper extends Comparable { boolean hasProperty(String propertyName); + Collection getPropertyNames(); + BlockStateWrapper withProperty(String propertyName, String propertyValue); String getAsString(); 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 5d5799233..e219878b1 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 @@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Map; import java.util.Optional; public class AbstractItem, I> implements Item { @@ -110,6 +111,17 @@ public class AbstractItem, I> implements Item { return this.factory.maxDamage(this.item); } + @Override + public Item blockState(Map state) { + this.factory.blockState(this.item, state); + return this; + } + + @Override + public Optional> blockState() { + return this.factory.blockState(this.item); + } + @Override public Item dyedColor(Color data) { this.factory.dyedColor(this.item, data); 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 8c48642be..9c33b50a2 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 @@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Map; import java.util.Optional; /** @@ -76,6 +77,10 @@ public interface Item { int maxDamage(); + Item blockState(Map state); + + Optional> blockState(); + // todo 考虑部分版本的show in tooltip保留 Item dyedColor(Color data); 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 b2cac48ba..5125d57c6 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 @@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.util.UniqueKey; import net.momirealms.sparrow.nbt.Tag; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -216,4 +217,8 @@ public abstract class ItemFactory, I> { protected abstract UniqueKey recipeIngredientID(W item); protected abstract void attributeModifiers(W item, List modifiers); + + protected abstract Optional> blockState(W item); + + protected abstract void blockState(W item, Map state); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java index 63298239f..a01272ffe 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java @@ -17,6 +17,7 @@ import java.util.*; public class AttributeModifiersModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); public static final Map CONVERTOR = new HashMap<>(); + private static final Object[] NBT_PATH = new Object[]{"AttributeModifiers"}; static { if (VersionHelper.isOrAbove1_21_2()) { @@ -119,7 +120,7 @@ public class AttributeModifiersModifier implements SimpleNetworkItemDataModif @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"AttributeModifiers"}; + return NBT_PATH; } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/BlockStateModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/BlockStateModifier.java new file mode 100644 index 000000000..47061fbfe --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/BlockStateModifier.java @@ -0,0 +1,77 @@ +package net.momirealms.craftengine.core.item.modifier; + +import net.momirealms.craftengine.core.block.BlockStateWrapper; +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.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.LazyReference; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class BlockStateModifier implements SimpleNetworkItemDataModifier { + public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[]{"BlockStateTag"}; + private final LazyReference> wrapper; + + public BlockStateModifier(LazyReference> wrapper) { + this.wrapper = wrapper; + } + + @Override + public Key type() { + return ItemDataModifiers.BLOCK_STATE; + } + + @Override + public Item apply(Item item, ItemBuildContext context) { + return item.blockState(this.wrapper.get()); + } + + @Override + public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { + return NBT_PATH; + } + + @Override + public String nbtPathString(Item item, ItemBuildContext context) { + return "BlockStateTag"; + } + + @Override + public Key componentType(Item item, ItemBuildContext context) { + return ComponentKeys.BLOCK_STATE; + } + + public static class Factory implements ItemDataModifierFactory { + + @Override + public ItemDataModifier create(Object arg) { + if (arg instanceof Map map) { + Map properties = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + properties.put(entry.getKey().toString(), entry.getValue().toString()); + } + return new BlockStateModifier<>(LazyReference.lazyReference(() -> properties)); + } else { + String stateString = arg.toString(); + return new BlockStateModifier<>(LazyReference.lazyReference(() -> { + BlockStateWrapper blockState = CraftEngine.instance().blockManager().createBlockState(stateString); + if (blockState != null) { + Map properties = new HashMap<>(4); + for (String property : blockState.getPropertyNames()) { + properties.put(property, blockState.getProperty(property)); + } + return properties; + } + return Collections.emptyMap(); + })); + } + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java index 26c2ddbd3..0d2fb47c8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; public class CustomNameModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[]{"display", "Name"}; private final String argument; private final FormattedLine line; @@ -49,7 +50,7 @@ public class CustomNameModifier implements SimpleNetworkItemDataModifier { @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"display", "Name"}; + return NBT_PATH; } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java index 81e964094..caa5441fc 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java @@ -12,6 +12,7 @@ import org.joml.Vector3f; public class DyedColorModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[]{"display", "color"}; private final Color color; public DyedColorModifier(Color color) { @@ -39,7 +40,7 @@ public class DyedColorModifier implements SimpleNetworkItemDataModifier { @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"display", "color"}; + return NBT_PATH; } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentsModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentsModifier.java index 8dbb7a591..24ce81ff0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentsModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentsModifier.java @@ -12,6 +12,8 @@ import java.util.Map; public class EnchantmentsModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] STORED_ENCHANTMENTS = new Object[] {"StoredEnchantments"}; + private static final Object[] ENCHANTMENTS = new Object[] {"Enchantments"}; private final List enchantments; public EnchantmentsModifier(List enchantments) { @@ -43,7 +45,7 @@ public class EnchantmentsModifier implements SimpleNetworkItemDataModifier @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return item.vanillaId().equals(ItemKeys.ENCHANTED_BOOK) ? new Object[]{"StoredEnchantments"} : new Object[]{"Enchantments"}; + return item.vanillaId().equals(ItemKeys.ENCHANTED_BOOK) ? STORED_ENCHANTMENTS : ENCHANTMENTS; } @Override 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 82eafdef4..055746d59 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 @@ -46,6 +46,7 @@ public final class ItemDataModifiers { public static final Key DYNAMIC_LORE = Key.of("craftengine:dynamic-lore"); public static final Key OVERWRITABLE_LORE = Key.of("craftengine:overwritable-lore"); public static final Key MAX_DAMAGE = Key.of("craftengine:max-damage"); + public static final Key BLOCK_STATE = Key.of("craftengine:block-state"); public static void register(Key key, ItemDataModifierFactory factory) { ((WritableRegistry>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY) @@ -77,6 +78,7 @@ public final class ItemDataModifiers { register(ARGUMENTS, ArgumentsModifier.FACTORY); register(OVERWRITABLE_ITEM_NAME, OverwritableItemNameModifier.FACTORY); register(PDC, PDCModifier.FACTORY); + register(BLOCK_STATE, BlockStateModifier.FACTORY); if (VersionHelper.isOrAbove1_20_5()) { register(CUSTOM_NAME, CustomNameModifier.FACTORY); register(ITEM_NAME, ItemNameModifier.FACTORY); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java index cc36ef68d..c19f8bf10 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; public class ItemNameModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[]{"display", "Name"}; private final String argument; private final FormattedLine line; @@ -40,7 +41,7 @@ public class ItemNameModifier implements SimpleNetworkItemDataModifier { @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"display", "Name"}; + return NBT_PATH; } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java index 82c7a537e..f8e7d4257 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java @@ -14,6 +14,7 @@ import java.util.Map; public class TrimModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[] {"Trim"}; private final Key material; private final Key pattern; @@ -47,7 +48,7 @@ public class TrimModifier implements SimpleNetworkItemDataModifier { @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"Trim"}; + return NBT_PATH; } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java index e2799c35e..6ce5c9893 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; public class UnbreakableModifier implements SimpleNetworkItemDataModifier { public static final Factory FACTORY = new Factory<>(); + private static final Object[] NBT_PATH = new Object[]{"Unbreakable"}; private final boolean argument; public UnbreakableModifier(boolean argument) { @@ -38,7 +39,7 @@ public class UnbreakableModifier implements SimpleNetworkItemDataModifier @Override public @Nullable Object[] nbtPath(Item item, ItemBuildContext context) { - return new Object[]{"Unbreakable"}; + return NBT_PATH; } @Override