9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-06 15:52:03 +00:00

配方后处理器的准备

This commit is contained in:
XiaoMoMi
2025-07-17 16:02:50 +08:00
parent fd2c9e637b
commit 5e3115c08c
18 changed files with 118 additions and 46 deletions

View File

@@ -46,14 +46,12 @@ import static java.util.Objects.requireNonNull;
public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
private static int[] ordinalToIbdID;
private final Extent extent;
private final Set<CEChunk> chunksToSave;
private final CEWorld ceWorld;
private final Set<ChunkPos> brokenChunks = Collections.synchronizedSet(new HashSet<>());
protected FastAsyncWorldEditDelegate(EditSessionEvent event, Extent extent) {
super(extent);
this.extent = extent;
this.chunksToSave = new HashSet<>();
World weWorld = event.getWorld();
org.bukkit.World world = Bukkit.getWorld(requireNonNull(weWorld).getName());
@@ -77,8 +75,9 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
public void onEditSessionEvent(EditSessionEvent event) {
World weWorld = event.getWorld();
if (weWorld == null) return;
Extent currentExtent = event.getExtent();
if (event.getStage() == EditSession.Stage.BEFORE_CHANGE) {
event.setExtent(new FastAsyncWorldEditDelegate(event, event.getExtent()));
event.setExtent(new FastAsyncWorldEditDelegate(event, currentExtent));
}
}
});
@@ -138,7 +137,7 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) {
boolean result = extent.setBlock(x, y, z, block);
boolean result = super.setBlock(x, y, z, block);
if (result) {
Mask mask = getMask();
if (mask != null && !mask.test(BlockVector3.at(x, y, z))) return true;

View File

@@ -42,13 +42,13 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
}
@Override
public Item<ItemStack> buildItem(ItemBuildContext context) {
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, 1));
public Item<ItemStack> buildItem(ItemBuildContext context, int count) {
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(this.item, count));
Item<ItemStack> wrapped = BukkitCraftEngine.instance().itemManager().wrap(item);
for (ItemDataModifier<ItemStack> modifier : dataModifiers()) {
modifier.apply(wrapped, context);
}
return BukkitCraftEngine.instance().itemManager().wrap(wrapped.getItem());
return wrapped;
}
public Object clientItem() {

View File

@@ -29,8 +29,6 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce
import net.momirealms.craftengine.core.plugin.logger.Debugger;
import net.momirealms.craftengine.core.util.*;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -165,11 +163,11 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public Optional<BuildableItem<ItemStack>> getVanillaItem(Key key) {
Material material = Registry.MATERIAL.get(KeyUtils.toNamespacedKey(key));
if (material == null) {
ItemStack vanilla = createVanillaItemStack(key);
if (vanilla == null) {
return Optional.empty();
}
return Optional.of(new CloneableConstantItem(key, new ItemStack(material)));
return Optional.of(new CloneableConstantItem(key, this.wrap(vanilla)));
}
@Override

View File

@@ -1,15 +1,16 @@
package net.momirealms.craftengine.bukkit.item;
import net.momirealms.craftengine.core.item.BuildableItem;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.inventory.ItemStack;
public class CloneableConstantItem implements BuildableItem<ItemStack> {
private final ItemStack item;
private final Item<ItemStack> item;
private final Key id;
public CloneableConstantItem(Key id, ItemStack item) {
public CloneableConstantItem(Key id, Item<ItemStack> item) {
this.item = item;
this.id = id;
}
@@ -19,10 +20,13 @@ public class CloneableConstantItem implements BuildableItem<ItemStack> {
return this.id;
}
@Override
public Item<ItemStack> buildItem(ItemBuildContext context, int count) {
return this.item.copyWithCount(count);
}
@Override
public ItemStack buildItemStack(ItemBuildContext context, int count) {
ItemStack itemStack = this.item.clone();
itemStack.setAmount(count);
return itemStack;
return this.item.copyWithCount(count).getItem();
}
}

View File

@@ -561,7 +561,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
}
CustomStoneCuttingRecipe<ItemStack> ceRecipe = new CustomStoneCuttingRecipe<>(
id, recipe.group(), Ingredient.of(holders),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
);
this.registerInternalRecipe(id, ceRecipe);
}
@@ -590,7 +590,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
}
CustomShapelessRecipe<ItemStack> ceRecipe = new CustomShapelessRecipe<>(
id, recipe.category(), recipe.group(), ingredientList,
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
);
if (hasCustomItemInTag) {
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
@@ -627,7 +627,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
CustomShapedRecipe<ItemStack> ceRecipe = new CustomShapedRecipe<>(
id, recipe.category(), recipe.group(),
new CustomShapedRecipe.Pattern<>(recipe.pattern(), ingredients),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
);
if (hasCustomItemInTag) {
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
@@ -651,7 +651,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
id, recipe.category(), recipe.group(),
Ingredient.of(holders),
recipe.cookingTime(), recipe.experience(),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null)
);
if (hasCustomItemInTag) {
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
@@ -680,7 +680,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
baseHolders.isEmpty() ? null : Ingredient.of(baseHolders),
templateHolders.isEmpty() ? null : Ingredient.of(templateHolders),
additionHolders.isEmpty() ? null : Ingredient.of(additionHolders),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), BukkitItemManager.instance().wrap(result)), recipe.result().count(), null),
true,
List.of()
);

View File

@@ -2,10 +2,8 @@ package net.momirealms.craftengine.core.entity;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MCUtils;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.sparrow.nbt.util.MathUtil;
import java.util.UUID;

View File

@@ -93,6 +93,11 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
}
}
@Override
public Function<Object, ItemDataModifier<I>> getDataType(String key) {
return this.dataFunctions.get(key);
}
@Override
public ConfigParser[] parsers() {
return new ConfigParser[]{this.itemParser, this.equipmentParser};

View File

@@ -8,6 +8,16 @@ public interface BuildableItem<I> {
Key id();
Item<I> buildItem(ItemBuildContext context, int count);
default Item<I> buildItem(Player player) {
return buildItem(ItemBuildContext.of(player));
}
default Item<I> buildItem(ItemBuildContext context) {
return buildItem(context, 1);
}
I buildItemStack(ItemBuildContext context, int count);
default I buildItemStack(ItemBuildContext context) {

View File

@@ -1,6 +1,5 @@
package net.momirealms.craftengine.core.item;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
@@ -35,12 +34,6 @@ public interface CustomItem<I> extends BuildableItem<I> {
return settings().tags().contains(tag);
}
default Item<I> buildItem(Player player) {
return buildItem(ItemBuildContext.of(player));
}
Item<I> buildItem(ItemBuildContext context);
void execute(PlayerOptionalContext context, EventTrigger trigger);
@NotNull

View File

@@ -24,6 +24,8 @@ public interface ItemManager<T> extends Manageable, ModelGenerator {
void registerDataType(Function<Object, ItemDataModifier<T>> factory, String... alias);
Function<Object, ItemDataModifier<T>> getDataType(String key);
Map<Key, Equipment> equipments();
ConfigParser[] parsers();

View File

@@ -1,7 +1,6 @@
package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.Nullable;
@@ -16,11 +15,6 @@ public abstract class AbstractGroupedRecipe<T> implements FixedResultRecipe<T> {
this.result = result;
}
@Override
public T assemble(RecipeInput input, ItemBuildContext context) {
return this.result(context);
}
@Nullable
public String group() {
return group;

View File

@@ -47,11 +47,6 @@ public class CustomBrewingRecipe<T> implements FixedResultRecipe<T> {
return this.container.test(brewingInput.container()) && this.ingredient.test(brewingInput.ingredient());
}
@Override
public T assemble(RecipeInput input, ItemBuildContext context) {
return this.result(context);
}
@Override
public List<Ingredient<T>> ingredientsInUse() {
List<Ingredient<T>> ingredients = new ArrayList<>();

View File

@@ -1,11 +1,74 @@
package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.item.BuildableItem;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Registries;
import net.momirealms.craftengine.core.registry.WritableRegistry;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceKey;
public record CustomRecipeResult<T>(BuildableItem<T> item, int count) {
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@SuppressWarnings("unchecked")
public record CustomRecipeResult<T>(BuildableItem<T> item, int count, PostProcessor<T>[] postProcessors) {
public T buildItemStack(ItemBuildContext context) {
return item.buildItemStack(context, count);
Item<T> builtItem = this.item.buildItem(context, count);
if (this.postProcessors != null) {
for (PostProcessor<T> postProcessor : this.postProcessors) {
builtItem = postProcessor.process(builtItem, context);
}
}
return builtItem.getItem();
}
static {
registerPostProcessorType(Key.of("apply_data"), args -> {
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
for (Map.Entry<String, Object> entry : args.entrySet()) {
Optional.ofNullable(CraftEngine.instance().itemManager().getDataType(entry.getKey())).ifPresent(it -> {
modifiers.add(it.apply(entry.getValue()));
});
}
return new ApplyItemDataProcessor<>(modifiers.toArray(new ItemDataModifier[0]));
});
}
public static void registerPostProcessorType(Key id, PostProcessor.Type<?> type) {
((WritableRegistry<PostProcessor.Type<?>>) BuiltInRegistries.RECIPE_POST_PROCESSOR_TYPE).register(ResourceKey.create(Registries.RECIPE_POST_PROCESSOR_TYPE.location(), id), type);
}
@FunctionalInterface
public interface PostProcessor<T> {
Item<T> process(Item<T> item, ItemBuildContext context);
interface Type<T> {
PostProcessor<T> create(Map<String, Object> args);
}
}
public static class ApplyItemDataProcessor<T> implements PostProcessor<T> {
private final ItemDataModifier<T>[] modifiers;
public ApplyItemDataProcessor(ItemDataModifier<T>[] modifiers) {
this.modifiers = modifiers;
}
@Override
public Item<T> process(Item<T> item, ItemBuildContext context) {
for (ItemDataModifier<T> modifier : this.modifiers) {
item.apply(modifier, context);
}
return item;
}
}
}

View File

@@ -154,6 +154,7 @@ public class CustomSmithingTransformRecipe<T> implements FixedResultRecipe<T> {
public static class ItemDataProcessors {
public static final Key KEEP_COMPONENTS = Key.of("craftengine:keep_components");
public static final Key KEEP_TAGS = Key.of("craftengine:keep_tags");
public static final Key APPLY_DATA = Key.of("craftengine:apply_data");
static {
if (VersionHelper.isOrAbove1_20_5()) {

View File

@@ -1,10 +1,16 @@
package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
public interface FixedResultRecipe<T> extends Recipe<T> {
T result(ItemBuildContext context);
CustomRecipeResult<T> result();
@Override
default T assemble(RecipeInput input, ItemBuildContext context) {
return this.result(context);
}
}

View File

@@ -27,7 +27,8 @@ public interface RecipeFactory<T> {
return new CustomRecipeResult(
CraftEngine.instance().itemManager().getBuildableItem(Key.of(id)).orElseThrow(
() -> new LocalizedResourceConfigException("warning.config.recipe.invalid_result", id)),
count
count,
null
);
}

View File

@@ -6,6 +6,7 @@ import net.momirealms.craftengine.core.block.properties.PropertyFactory;
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
import net.momirealms.craftengine.core.item.recipe.CustomRecipeResult;
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
@@ -74,6 +75,7 @@ public class BuiltInRegistries {
public static final Registry<SlotDisplay.Type> SLOT_DISPLAY_TYPE = createConstantBoundRegistry(Registries.SLOT_DISPLAY_TYPE);
public static final Registry<RecipeDisplay.Type> RECIPE_DISPLAY_TYPE = createConstantBoundRegistry(Registries.RECIPE_DISPLAY_TYPE);
public static final Registry<LegacyRecipe.Type> LEGACY_RECIPE_TYPE = createConstantBoundRegistry(Registries.LEGACY_RECIPE_TYPE);
public static final Registry<CustomRecipeResult.ApplyItemDataProcessor.Type<?>> RECIPE_POST_PROCESSOR_TYPE = createConstantBoundRegistry(Registries.RECIPE_POST_PROCESSOR_TYPE);
private static <T> Registry<T> createConstantBoundRegistry(ResourceKey<? extends Registry<T>> key) {
return new ConstantBoundRegistry<>(key);

View File

@@ -6,6 +6,7 @@ import net.momirealms.craftengine.core.block.properties.PropertyFactory;
import net.momirealms.craftengine.core.entity.furniture.HitBoxFactory;
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
import net.momirealms.craftengine.core.item.recipe.CustomRecipeResult;
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
@@ -42,7 +43,6 @@ import net.momirealms.craftengine.core.util.ResourceKey;
public class Registries {
public static final Key ROOT_REGISTRY = Key.withDefaultNamespace("root");
public static final ResourceKey<Registry<CustomBlock>> BLOCK = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block"));
public static final ResourceKey<Registry<Key>> OPTIMIZED_ITEM_ID = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("optimized_item_id"));
public static final ResourceKey<Registry<PropertyFactory>> PROPERTY_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("property_factory"));
public static final ResourceKey<Registry<BlockBehaviorFactory>> BLOCK_BEHAVIOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_behavior_factory"));
public static final ResourceKey<Registry<ItemBehaviorFactory>> ITEM_BEHAVIOR_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("item_behavior_factory"));
@@ -77,4 +77,5 @@ public class Registries {
public static final ResourceKey<Registry<SlotDisplay.Type>> SLOT_DISPLAY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("slot_display_type"));
public static final ResourceKey<Registry<RecipeDisplay.Type>> RECIPE_DISPLAY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_display_type"));
public static final ResourceKey<Registry<LegacyRecipe.Type>> LEGACY_RECIPE_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("legacy_recipe_type"));
public static final ResourceKey<Registry<CustomRecipeResult.ApplyItemDataProcessor.Type<?>>> RECIPE_POST_PROCESSOR_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_post_processor_type"));
}