mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-26 02:19:23 +00:00
Merge branch 'Xiao-MoMi:dev' into dev
This commit is contained in:
@@ -26,9 +26,9 @@ resource-pack:
|
||||
obfuscation:
|
||||
enable: false
|
||||
seed: 0 # 0 = random seed
|
||||
fake-directory: true
|
||||
escape-unicode: true
|
||||
break-json: true
|
||||
fake-directory: false
|
||||
escape-unicode: false
|
||||
break-json: false
|
||||
resource-location:
|
||||
enable: true
|
||||
random-namespace:
|
||||
@@ -184,12 +184,14 @@ gui:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:smelting>"
|
||||
smoking:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:smoking>"
|
||||
campfire:
|
||||
campfire-cooking:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:campfire>"
|
||||
crafting:
|
||||
title: "<white><shift:-11><image:internal:crafting_recipe>"
|
||||
stonecutting:
|
||||
title: "<white><shift:-11><image:internal:stonecutting_recipe>"
|
||||
smithing-transform:
|
||||
title: "<white><shift:-11><image:internal:smithing_transform_recipe>"
|
||||
|
||||
performance:
|
||||
# Maximum chain update depth when fixing client visuals
|
||||
|
||||
@@ -329,4 +329,70 @@ recipes#11:
|
||||
B: "minecraft:stick"
|
||||
result:
|
||||
id: default:topaz_pickaxe
|
||||
count: 1
|
||||
default:topaz_helmet:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "AAA"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_helmet
|
||||
count: 1
|
||||
default:topaz_chestplate:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "A A"
|
||||
- "AAA"
|
||||
- "AAA"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_chestplate
|
||||
count: 1
|
||||
default:topaz_leggings:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "AAA"
|
||||
- "A A"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_leggings
|
||||
count: 1
|
||||
default:topaz_boots:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "A A"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_boots
|
||||
count: 1
|
||||
default:topaz_bow:
|
||||
type: smithing_transform
|
||||
base: minecraft:bow
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_bow
|
||||
count: 1
|
||||
default:topaz_crossbow:
|
||||
type: smithing_transform
|
||||
base: minecraft:crossbow
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_crossbow
|
||||
count: 1
|
||||
default:topaz_rod:
|
||||
type: smithing_transform
|
||||
base: minecraft:fishing_rod
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_rod
|
||||
count: 1
|
||||
@@ -53,12 +53,18 @@ images:
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/stonecutting_recipe.png
|
||||
char: '\ub008'
|
||||
internal:smithing_transform_recipe:
|
||||
height: 142
|
||||
ascent: 20
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/smithing_transform_recipe.png
|
||||
char: '\ub009'
|
||||
internal:no_recipe:
|
||||
height: 140
|
||||
ascent: 18
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/no_recipe.png
|
||||
char: '\ub009'
|
||||
char: '\ub00a'
|
||||
|
||||
templates:
|
||||
internal:icon/2d:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -213,6 +213,7 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
|
||||
@Override
|
||||
protected void maxStackSize(ItemWrapper<ItemStack> item, Integer maxStackSize) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -229,7 +230,9 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
@Override
|
||||
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
Object itemStack = ItemObject.copy(item2.getLiteralObject());
|
||||
ItemObject.setCustomDataTag(itemStack, ItemObject.getCustomDataTag(item1.getLiteralObject()));
|
||||
ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject())));
|
||||
// one more step than vanilla
|
||||
TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
||||
return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count());
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CraftEngine.instance().logger().warn("Failed to convert campfire recipe", e);
|
||||
}
|
||||
});
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONE_CUTTING, (key, recipe) -> {
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONECUTTING, (key, recipe) -> {
|
||||
CustomStoneCuttingRecipe<ItemStack> ceRecipe = (CustomStoneCuttingRecipe<ItemStack>) recipe;
|
||||
List<ItemStack> itemStacks = new ArrayList<>();
|
||||
for (Holder<Key> item : ceRecipe.ingredient().items()) {
|
||||
@@ -382,9 +382,13 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
this.byType.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe);
|
||||
this.byId.put(id, recipe);
|
||||
this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe);
|
||||
HashSet<Key> usedKeys = new HashSet<>();
|
||||
for (Ingredient<ItemStack> ingredient : recipe.ingredientsInUse()) {
|
||||
for (Holder<Key> holder : ingredient.items()) {
|
||||
this.byIngredient.computeIfAbsent(holder.value(), k -> new ArrayList<>()).add(recipe);
|
||||
Key key = holder.value();
|
||||
if (usedKeys.add(key)) {
|
||||
this.byIngredient.computeIfAbsent(key, k -> new ArrayList<>()).add(recipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -765,7 +769,8 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
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()),
|
||||
List.of(CustomSmithingTransformRecipe.ItemDataProcessor.MERGE_ALL)
|
||||
true,
|
||||
List.of()
|
||||
);
|
||||
|
||||
SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result,
|
||||
|
||||
@@ -835,6 +835,7 @@ public class RecipeEventListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSmithingTransform(PrepareSmithingEvent event) {
|
||||
if (!ConfigManager.enableRecipeSystem()) return;
|
||||
SmithingInventory inventory = event.getInventory();
|
||||
if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return;
|
||||
|
||||
@@ -872,6 +873,21 @@ public class RecipeEventListener implements Listener {
|
||||
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base));
|
||||
event.setResult(processed);
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
|
||||
private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe<ItemStack> recipe) {
|
||||
Object holderOrRecipe = recipeManager.getRecipeHolderByRecipe(recipe);
|
||||
if (holderOrRecipe == null) {
|
||||
// it's a vanilla recipe but not injected
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object resultInventory = Reflections.field$CraftResultInventory$resultInventory.get(inventory);
|
||||
Reflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to correct used recipe", e);
|
||||
}
|
||||
}
|
||||
|
||||
private OptimizedIDItem<ItemStack> getOptimizedIDItem(@Nullable ItemStack itemStack) {
|
||||
|
||||
@@ -4414,6 +4414,18 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$CraftResultInventory = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleCBClass("inventory.CraftResultInventory")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$CraftResultInventory$resultInventory = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$CraftResultInventory, clazz$Container, 0
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Method method$ItemStack$hurtAndBreak =
|
||||
ReflectionUtils.getMethod(
|
||||
|
||||
@@ -7,13 +7,16 @@ import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
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.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
import net.momirealms.craftengine.core.util.TriConsumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
@@ -22,6 +25,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
private final Ingredient<T> base;
|
||||
private final Ingredient<T> template;
|
||||
private final Ingredient<T> addition;
|
||||
private final boolean mergeComponents;
|
||||
private final List<ItemDataProcessor> processors;
|
||||
|
||||
public CustomSmithingTransformRecipe(Key id,
|
||||
@@ -29,6 +33,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
@Nullable Ingredient<T> template,
|
||||
@Nullable Ingredient<T> addition,
|
||||
CustomRecipeResult<T> result,
|
||||
boolean mergeComponents,
|
||||
List<ItemDataProcessor> processors
|
||||
) {
|
||||
this.id = id;
|
||||
@@ -37,6 +42,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
this.template = template;
|
||||
this.addition = addition;
|
||||
this.processors = processors;
|
||||
this.mergeComponents = mergeComponents;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -79,12 +85,12 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return id;
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T result(ItemBuildContext context) {
|
||||
return result.buildItemStack(context);
|
||||
return this.result.buildItemStack(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -92,10 +98,13 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
T result = this.result(context);
|
||||
Item<T> wrappedResult = (Item<T>) CraftEngine.instance().itemManager().wrap(result);
|
||||
Item<T> finalResult = wrappedResult;
|
||||
for (ItemDataProcessor processor : this.processors) {
|
||||
finalResult = (Item<T>) processor.apply(base, wrappedResult);
|
||||
if (this.mergeComponents) {
|
||||
finalResult = base.merge(wrappedResult);
|
||||
}
|
||||
return finalResult.getItem();
|
||||
for (ItemDataProcessor processor : this.processors) {
|
||||
processor.accept(base, wrappedResult, finalResult);
|
||||
}
|
||||
return finalResult.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,7 +114,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
|
||||
@Nullable
|
||||
public Ingredient<T> base() {
|
||||
return base;
|
||||
return this.base;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -124,12 +133,16 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
@Override
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
List<String> base = MiscUtils.getAsStringList(arguments.get("base"));
|
||||
List<String> addition = MiscUtils.getAsStringList(arguments.get("addition-input"));
|
||||
List<String> addition = MiscUtils.getAsStringList(arguments.get("addition"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-type"));
|
||||
boolean mergeComponents = (boolean) arguments.getOrDefault("merge-components", true);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> processors = (List<Map<String, Object>>) arguments.getOrDefault("post-processors", List.of());
|
||||
return new CustomSmithingTransformRecipe<>(
|
||||
id,
|
||||
toIngredient(base), toIngredient(template),toIngredient(addition), parseResult(arguments),
|
||||
List.of(ItemDataProcessor.MERGE_ALL)
|
||||
mergeComponents,
|
||||
ItemDataProcessors.fromMapList(processors)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -146,16 +159,42 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ItemDataProcessor extends BiFunction<Item<?>, Item<?>, Item<?>> {
|
||||
MergeAllDataProcessor MERGE_ALL = new MergeAllDataProcessor();
|
||||
public static class ItemDataProcessors {
|
||||
|
||||
public static List<ItemDataProcessor> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<ItemDataProcessor> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
functions.add(fromMap(map));
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static ItemDataProcessor fromMap(Map<String, Object> map) {
|
||||
String type = (String) map.get("type");
|
||||
if (type == null) {
|
||||
throw new NullPointerException("processor type cannot be null");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
ItemDataProcessor.Factory factory = BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown processor type: " + type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
public static void register(Key key, ItemDataProcessor.Factory factory) {
|
||||
Holder.Reference<ItemDataProcessor.Factory> holder = ((WritableRegistry<ItemDataProcessor.Factory>) BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.SMITHING_RESULT_PROCESSOR_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MergeAllDataProcessor implements ItemDataProcessor {
|
||||
@FunctionalInterface
|
||||
public interface ItemDataProcessor extends TriConsumer<Item<?>, Item<?>, Item<?>> {
|
||||
|
||||
@Override
|
||||
public Item<?> apply(Item<?> item1, Item<?> item2) {
|
||||
return item1.merge(item2);
|
||||
interface Factory {
|
||||
ItemDataProcessor create(Map<String, Object> arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class CustomStoneCuttingRecipe<T> extends AbstractGroupedRecipe<T> {
|
||||
|
||||
@Override
|
||||
public @NotNull Key type() {
|
||||
return RecipeTypes.STONE_CUTTING;
|
||||
return RecipeTypes.STONECUTTING;
|
||||
}
|
||||
|
||||
public Ingredient<T> ingredient() {
|
||||
|
||||
@@ -16,7 +16,7 @@ public class RecipeTypes {
|
||||
public static final Key BLASTING = Key.of("minecraft:blasting");
|
||||
public static final Key SMOKING = Key.of("minecraft:smoking");
|
||||
public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking");
|
||||
public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting");
|
||||
public static final Key STONECUTTING = Key.of("minecraft:stonecutting");
|
||||
public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform");
|
||||
public static final Key SMITHING_TRIM = Key.of("minecraft:smithing_trim");
|
||||
|
||||
@@ -27,7 +27,7 @@ public class RecipeTypes {
|
||||
register(SMOKING, CustomSmokingRecipe.FACTORY);
|
||||
register(BLASTING, CustomBlastingRecipe.FACTORY);
|
||||
register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY);
|
||||
register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY);
|
||||
register(STONECUTTING, CustomStoneCuttingRecipe.FACTORY);
|
||||
register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@ public class VanillaStoneCuttingRecipe extends VanillaGroupedRecipe {
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.STONE_CUTTING;
|
||||
return RecipeTypes.STONECUTTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class NumberProviders {
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
static List<NumberProvider> fromMapList(List<Map<String, Object>> mapList) {
|
||||
public static List<NumberProvider> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<NumberProvider> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
|
||||
@@ -249,6 +249,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smelting.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/campfire.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/cooking_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/crafting_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/no_recipe.png");
|
||||
|
||||
@@ -65,6 +65,7 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser {
|
||||
public static String RECIPE_CAMPFIRE_TITLE;
|
||||
public static String RECIPE_CRAFTING_TITLE;
|
||||
public static String RECIPE_STONECUTTING_TITLE;
|
||||
public static String RECIPE_SMITHING_TRANSFORM_TITLE;
|
||||
public static Key RECIPE_BACK;
|
||||
public static Key RECIPE_EXIT;
|
||||
public static Key RECIPE_NEXT_PAGE_AVAILABLE;
|
||||
@@ -100,9 +101,10 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser {
|
||||
RECIPE_BLASTING_TITLE = getOrThrow(section, "recipe.blasting.title");
|
||||
RECIPE_SMELTING_TITLE = getOrThrow(section, "recipe.smelting.title");
|
||||
RECIPE_SMOKING_TITLE = getOrThrow(section, "recipe.smoking.title");
|
||||
RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire.title");
|
||||
RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire-cooking.title");
|
||||
RECIPE_CRAFTING_TITLE = getOrThrow(section, "recipe.crafting.title");
|
||||
RECIPE_STONECUTTING_TITLE = getOrThrow(section, "recipe.stonecutting.title");
|
||||
RECIPE_SMITHING_TRANSFORM_TITLE = getOrThrow(section, "recipe.smithing-transform.title");
|
||||
RECIPE_BACK = Key.of(getOrThrow(section, "recipe.page-navigation.return"));
|
||||
RECIPE_EXIT = Key.of(getOrThrow(section, "recipe.page-navigation.exit"));
|
||||
RECIPE_NEXT_PAGE_AVAILABLE = Key.of(getOrThrow(section, "recipe.page-navigation.next.available"));
|
||||
|
||||
@@ -349,10 +349,215 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
openCookingRecipePage(player, (CustomCookingRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
if (recipeType == RecipeTypes.STONE_CUTTING) {
|
||||
if (recipeType == RecipeTypes.STONECUTTING) {
|
||||
openStoneCuttingRecipePage(player, (CustomStoneCuttingRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
if (recipeType == RecipeTypes.SMITHING_TRANSFORM) {
|
||||
openSmithingTransformRecipePage(player, (CustomSmithingTransformRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void openSmithingTransformRecipePage(Player player, CustomSmithingTransformRecipe<Object> recipe, Gui parentGui, List<Recipe<Object>> recipes, int index, int depth, boolean canOpenNoRecipePage) {
|
||||
Key previous = index > 0 ? Constants.RECIPE_PREVIOUS_PAGE_AVAILABLE : Constants.RECIPE_PREVIOUS_PAGE_BLOCK;
|
||||
Key next = index + 1 < recipes.size() ? Constants.RECIPE_NEXT_PAGE_AVAILABLE : Constants.RECIPE_NEXT_PAGE_BLOCK;
|
||||
Key result = recipe.result().item().id();
|
||||
GuiLayout layout = new GuiLayout(
|
||||
" ",
|
||||
" ",
|
||||
" ABC X ",
|
||||
" ^ ",
|
||||
" ",
|
||||
" < = > "
|
||||
)
|
||||
.addIngredient('X', GuiElement.constant(this.plugin.itemManager().createWrappedItem(result, player).count(recipe.result().count()), (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(result, player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(result);
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(result);
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
.addIngredient('^', player.hasPermission(GET_ITEM_PERMISSION) ? GuiElement.constant(this.plugin.itemManager().createWrappedItem(Constants.RECIPE_GET_ITEM, player), (e, c) -> {
|
||||
c.cancel();
|
||||
player.playSound(Constants.SOUND_PICK_ITEM);
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
player.giveItem(this.plugin.itemManager().createWrappedItem(result, player));
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(result, player);
|
||||
player.giveItem(item.count(item.maxStackSize()));
|
||||
}
|
||||
}) : GuiElement.EMPTY)
|
||||
.addIngredient('=', GuiElement.constant(this.plugin.itemManager().getCustomItem(parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.EMPTY)))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + (parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT))),
|
||||
((element, click) -> {
|
||||
click.cancel();
|
||||
player.playSound(Constants.SOUND_RETURN_PAGE, 0.25f, 1);
|
||||
if (parentGui != null) {
|
||||
parentGui.open(player);
|
||||
} else {
|
||||
player.closeInventory();
|
||||
}
|
||||
}))
|
||||
)
|
||||
.addIngredient('>', GuiElement.constant(this.plugin.itemManager()
|
||||
.getCustomItem(next)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder()
|
||||
.withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1))
|
||||
.withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size()))
|
||||
.build())))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + next)), (e, c) -> {
|
||||
c.cancel();
|
||||
if (index + 1 < recipes.size()) {
|
||||
player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1);
|
||||
openRecipePage(player, parentGui, recipes, index + 1, depth, canOpenNoRecipePage);
|
||||
}
|
||||
}))
|
||||
.addIngredient('<', GuiElement.constant(this.plugin.itemManager()
|
||||
.getCustomItem(previous)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder()
|
||||
.withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1))
|
||||
.withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size()))
|
||||
.build())))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + previous)), (e, c) -> {
|
||||
c.cancel();
|
||||
if (index > 0) {
|
||||
player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1);
|
||||
openRecipePage(player, parentGui, recipes, index - 1, depth, canOpenNoRecipePage);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
List<Item<?>> templates = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.template()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
templates.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('A', templates.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(templates, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
List<Item<?>> bases = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.base()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
bases.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('B', bases.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(bases, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
List<Item<?>> additions = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.addition()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
additions.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('C', additions.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(additions, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
BasicGui.builder()
|
||||
.layout(layout)
|
||||
.inventoryClickConsumer(c -> {
|
||||
if (MOVE_TO_OTHER_INV.contains(c.type()) || DOUBLE_CLICK.contains(c.type())) {
|
||||
c.cancel();
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
|
||||
public void openStoneCuttingRecipePage(Player player, CustomStoneCuttingRecipe<Object> recipe, Gui parentGui, List<Recipe<Object>> recipes, int index, int depth, boolean canOpenNoRecipePage) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditionFactory;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
|
||||
@@ -43,6 +44,7 @@ public class BuiltInRegistries {
|
||||
public static final Registry<ApplyBonusCountFunction.FormulaFactory> FORMULA_FACTORY = createRegistry(Registries.FORMULA_FACTORY);
|
||||
public static final Registry<PathMatcherFactory> PATH_MATCHER_FACTORY = createRegistry(Registries.PATH_MATCHER_FACTORY);
|
||||
public static final Registry<ResolutionFactory> RESOLUTION_FACTORY = createRegistry(Registries.RESOLUTION_FACTORY);
|
||||
public static final Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory> SMITHING_RESULT_PROCESSOR_FACTORY = createRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY);
|
||||
|
||||
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new MappedRegistry<>(key);
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditionFactory;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
|
||||
@@ -44,4 +45,5 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<ApplyBonusCountFunction.FormulaFactory>> FORMULA_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("formula_factory"));
|
||||
public static final ResourceKey<Registry<PathMatcherFactory>> PATH_MATCHER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));
|
||||
public static final ResourceKey<Registry<ResolutionFactory>> RESOLUTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory"));
|
||||
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory>> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user