9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-27 19:09:08 +00:00

构造抽象的自定义物品类

This commit is contained in:
XiaoMoMi
2025-05-19 16:52:58 +08:00
parent 15475b0538
commit e60a818331
7 changed files with 144 additions and 119 deletions

View File

@@ -1,6 +1,5 @@
package net.momirealms.craftengine.bukkit.item;
import com.google.common.collect.ImmutableMap;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.item.*;
@@ -13,113 +12,19 @@ import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class BukkitCustomItem implements CustomItem<ItemStack> {
private final Holder<Key> id;
private final Key materialKey;
public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
private final Material material;
private final ItemDataModifier<ItemStack>[] modifiers;
private final Map<String, ItemDataModifier<ItemStack>> modifierMap;
private final ItemDataModifier<ItemStack>[] clientBoundModifiers;
private final Map<String, ItemDataModifier<ItemStack>> clientBoundModifierMap;
private final NetworkItemDataProcessor<ItemStack>[] networkItemDataProcessors;
private final List<ItemBehavior> behaviors;
private final ItemSettings settings;
private final EnumMap<EventTrigger, List<Function<PlayerOptionalContext>>> events;
@SuppressWarnings("unchecked")
public BukkitCustomItem(Holder<Key> id,
Key materialKey,
Material material,
List<ItemDataModifier<ItemStack>> modifiers,
List<ItemDataModifier<ItemStack>> clientBoundModifiers,
public BukkitCustomItem(Holder<Key> id, Key materialKey, Material material,
List<ItemBehavior> behaviors,
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
ItemSettings settings,
EnumMap<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
this.id = id;
super(id, materialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
this.material = material;
this.materialKey = materialKey;
this.events = events;
// unchecked cast
this.modifiers = modifiers.toArray(new ItemDataModifier[0]);
// unchecked cast
this.clientBoundModifiers = clientBoundModifiers.toArray(new ItemDataModifier[0]);
this.behaviors = List.copyOf(behaviors);
this.settings = settings;
ImmutableMap.Builder<String, ItemDataModifier<ItemStack>> modifierMapBuilder = ImmutableMap.builder();
for (ItemDataModifier<ItemStack> modifier : modifiers) {
modifierMapBuilder.put(modifier.name(), modifier);
}
this.modifierMap = modifierMapBuilder.build();
ImmutableMap.Builder<String, ItemDataModifier<ItemStack>> clientSideModifierMapBuilder = ImmutableMap.builder();
List<NetworkItemDataProcessor<ItemStack>> networkItemDataProcessors = new ArrayList<>();
for (ItemDataModifier<ItemStack> modifier : clientBoundModifiers) {
String name = modifier.name();
clientSideModifierMapBuilder.put(name, modifier);
if (this.modifierMap.containsKey(name)) {
networkItemDataProcessors.add(NetworkItemDataProcessor.both(this.modifierMap.get(name), modifier));
} else {
networkItemDataProcessors.add(NetworkItemDataProcessor.clientOnly(modifier));
}
}
this.clientBoundModifierMap = clientSideModifierMapBuilder.build();
// unchecked cast
this.networkItemDataProcessors = networkItemDataProcessors.toArray(new NetworkItemDataProcessor[0]);
}
@Override
public void execute(PlayerOptionalContext context, EventTrigger trigger) {
for (Function<PlayerOptionalContext> function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) {
function.run(context);
}
}
@Override
public Key id() {
return this.id.value();
}
@Override
public Holder<Key> idHolder() {
return this.id;
}
@Override
public Key material() {
return this.materialKey;
}
@Override
public NetworkItemDataProcessor<ItemStack>[] networkItemDataProcessors() {
return this.networkItemDataProcessors;
}
@Override
public ItemDataModifier<ItemStack>[] dataModifiers() {
return this.modifiers;
}
@Override
public Map<String, ItemDataModifier<ItemStack>> dataModifierMap() {
return this.modifierMap;
}
@Override
public boolean hasClientBoundDataModifier() {
return this.clientBoundModifiers.length != 0;
}
@Override
public ItemDataModifier<ItemStack>[] clientBoundDataModifiers() {
return this.clientBoundModifiers;
}
@Override
public Map<String, ItemDataModifier<ItemStack>> clientBoundDataModifierMap() {
return this.clientBoundModifierMap;
}
@Override
@@ -133,11 +38,6 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
return wrapped.load();
}
@Override
public ItemSettings settings() {
return this.settings;
}
@Override
public Item<ItemStack> buildItem(ItemBuildContext context) {
ItemStack item = new ItemStack(this.material);
@@ -148,11 +48,6 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
return BukkitCraftEngine.instance().itemManager().wrap(wrapped.load());
}
@Override
public @NotNull List<ItemBehavior> behaviors() {
return this.behaviors;
}
public static Builder<ItemStack> builder(Material material) {
return new BuilderImpl(material);
}
@@ -162,9 +57,9 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
private Key materialKey;
private final Material material;
private final EnumMap<EventTrigger, List<Function<PlayerOptionalContext>>> events = new EnumMap<>(EventTrigger.class);
private final List<ItemBehavior> behaviors = new ArrayList<>();
private final List<ItemDataModifier<ItemStack>> modifiers = new ArrayList<>();
private final List<ItemDataModifier<ItemStack>> clientBoundModifiers = new ArrayList<>();
private final List<ItemBehavior> behaviors = new ArrayList<>(4);
private final List<ItemDataModifier<ItemStack>> modifiers = new ArrayList<>(4);
private final List<ItemDataModifier<ItemStack>> clientBoundModifiers = new ArrayList<>(4);
private ItemSettings settings;
public BuilderImpl(Material material) {
@@ -235,7 +130,8 @@ public class BukkitCustomItem implements CustomItem<ItemStack> {
@Override
public CustomItem<ItemStack> build() {
this.modifiers.addAll(this.settings.modifiers());
return new BukkitCustomItem(this.id, this.materialKey, this.material, List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), List.copyOf(this.behaviors), this.settings, this.events);
return new BukkitCustomItem(this.id, this.materialKey, this.material, List.copyOf(this.behaviors),
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
}
}
}

View File

@@ -193,7 +193,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public Item<ItemStack> createWrappedItem(Key id, @Nullable Player player) {
return Optional.ofNullable(customItems.get(id)).map(it -> it.buildItem(player)).orElseGet(() -> {
return Optional.ofNullable(this.customItems.get(id)).map(it -> it.buildItem(player)).orElseGet(() -> {
ItemStack itemStack = createVanillaItemStack(id);
return wrap(itemStack);
});
@@ -219,9 +219,9 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
}
@Override
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(Key materialId) {
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(Holder<Key> id, Key materialId) {
Material material = ResourceConfigUtils.requireNonNullOrThrow(Registry.MATERIAL.get(KeyUtils.toNamespacedKey(materialId)), () -> new LocalizedResourceConfigException("warning.config.item.invalid_material", materialId.toString()));
return BukkitCustomItem.builder(material);
return BukkitCustomItem.builder(material).material(materialId).id(id);
}
@SuppressWarnings("unchecked")

View File

@@ -0,0 +1,128 @@
package net.momirealms.craftengine.core.item;
import com.google.common.collect.ImmutableMap;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.function.Function;
import net.momirealms.craftengine.core.plugin.event.EventTrigger;
import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public abstract class AbstractCustomItem<I> implements CustomItem<I> {
protected final Holder<Key> id;
protected final Key material;
protected final ItemDataModifier<I>[] modifiers;
protected final Map<String, ItemDataModifier<I>> modifierMap;
protected final ItemDataModifier<I>[] clientBoundModifiers;
protected final Map<String, ItemDataModifier<I>> clientBoundModifierMap;
protected final NetworkItemDataProcessor<I>[] networkItemDataProcessors;
protected final List<ItemBehavior> behaviors;
protected final ItemSettings settings;
protected final EnumMap<EventTrigger, List<Function<PlayerOptionalContext>>> events;
protected final Item<I> base;
@SuppressWarnings("unchecked")
public AbstractCustomItem(Holder<Key> id, Key material,
List<ItemBehavior> behaviors,
List<ItemDataModifier<I>> modifiers,
List<ItemDataModifier<I>> clientBoundModifiers,
ItemSettings settings,
EnumMap<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
this.id = id;
this.material = material;
this.events = events;
// unchecked cast
this.modifiers = modifiers.toArray(new ItemDataModifier[0]);
// unchecked cast
this.clientBoundModifiers = clientBoundModifiers.toArray(new ItemDataModifier[0]);
this.behaviors = List.copyOf(behaviors);
this.settings = settings;
ImmutableMap.Builder<String, ItemDataModifier<I>> modifierMapBuilder = ImmutableMap.builder();
for (ItemDataModifier<I> modifier : modifiers) {
modifierMapBuilder.put(modifier.name(), modifier);
}
this.modifierMap = modifierMapBuilder.build();
ImmutableMap.Builder<String, ItemDataModifier<I>> clientSideModifierMapBuilder = ImmutableMap.builder();
List<NetworkItemDataProcessor<I>> networkItemDataProcessors = new ArrayList<>();
for (ItemDataModifier<I> modifier : clientBoundModifiers) {
String name = modifier.name();
clientSideModifierMapBuilder.put(name, modifier);
if (this.modifierMap.containsKey(name)) {
networkItemDataProcessors.add(NetworkItemDataProcessor.both(this.modifierMap.get(name), modifier));
} else {
networkItemDataProcessors.add(NetworkItemDataProcessor.clientOnly(modifier));
}
}
this.clientBoundModifierMap = clientSideModifierMapBuilder.build();
// unchecked cast
this.networkItemDataProcessors = networkItemDataProcessors.toArray(new NetworkItemDataProcessor[0]);
this.base = (Item<I>) CraftEngine.instance().itemManager().wrap(CraftEngine.instance().itemManager().getVanillaItem(material).get().buildItemStack());
}
@Override
public void execute(PlayerOptionalContext context, EventTrigger trigger) {
for (Function<PlayerOptionalContext> function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) {
function.run(context);
}
}
@Override
public Key id() {
return this.id.value();
}
@Override
public Holder<Key> idHolder() {
return this.id;
}
@Override
public Key material() {
return this.material;
}
@Override
public NetworkItemDataProcessor<I>[] networkItemDataProcessors() {
return this.networkItemDataProcessors;
}
@Override
public ItemDataModifier<I>[] dataModifiers() {
return this.modifiers;
}
@Override
public Map<String, ItemDataModifier<I>> dataModifierMap() {
return this.modifierMap;
}
@Override
public boolean hasClientBoundDataModifier() {
return this.clientBoundModifiers.length != 0;
}
@Override
public ItemDataModifier<I>[] clientBoundDataModifiers() {
return this.clientBoundModifiers;
}
@Override
public Map<String, ItemDataModifier<I>> clientBoundDataModifierMap() {
return this.clientBoundModifierMap;
}
@Override
public ItemSettings settings() {
return this.settings;
}
@Override
public @NotNull List<ItemBehavior> behaviors() {
return this.behaviors;
}
}

View File

@@ -254,7 +254,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
return VANILLA_ITEMS.contains(item);
}
protected abstract CustomItem.Builder<I> createPlatformItemBuilder(Key material);
protected abstract CustomItem.Builder<I> createPlatformItemBuilder(Holder<Key> id, Key material);
public class ItemParser implements ConfigParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"items", "item"};
@@ -302,7 +302,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
Key itemModelKey = null;
CustomItem.Builder<I> itemBuilder = createPlatformItemBuilder(material).id(holder);
CustomItem.Builder<I> itemBuilder = createPlatformItemBuilder(holder, material);
boolean hasItemModelSection = section.containsKey("item-model");
// To get at least one model provider

View File

@@ -127,7 +127,6 @@ public class LootTable<T> {
}
}
// TODO https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/loot-system/flat-format
public static <T> LootPool<T> readFlatFormatLootPool(String pool) {
return null;
}

View File

@@ -57,5 +57,6 @@ public final class DirectContextParameters {
public static final ContextKey<Boolean> IS_FLYING = ContextKey.direct("is_flying");
public static final ContextKey<Boolean> IS_SNEAKING = ContextKey.direct("is_sneaking");
public static final ContextKey<Boolean> IS_CUSTOM = ContextKey.direct("is_custom");
public static final ContextKey<Boolean> IS_BLOCK_ITEM = ContextKey.direct("is_block_item");
public static final ContextKey<GameMode> GAMEMODE = ContextKey.direct("gamemode");
}

View File

@@ -15,6 +15,7 @@ public class ItemParameterProvider implements ChainParameterProvider<Item<?>> {
CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Item::id);
CONTEXT_FUNCTIONS.put(DirectContextParameters.CUSTOM_MODEL_DATA, i -> i.customModelData().orElse(null));
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_CUSTOM, Item::isCustomItem);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_BLOCK_ITEM, Item::isBlockItem);
}
@SuppressWarnings("unchecked")