mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-06 15:52:03 +00:00
Optimize Recipes
This commit is contained in:
@@ -24,7 +24,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.HexaFunction;
|
||||
import net.momirealms.craftengine.core.util.HeptaFunction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.PentaFunction;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -190,9 +190,6 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private final VanillaRecipeReader recipeReader;
|
||||
private final List<NamespacedKey> injectedDataPackRecipes;
|
||||
private final List<NamespacedKey> registeredCustomRecipes;
|
||||
// [internal:xxx] + [custom:custom]
|
||||
// includes injected vanilla recipes and custom recipes
|
||||
private final Set<Key> customRecipes;
|
||||
// data pack recipe resource locations [minecraft:xxx]
|
||||
private final Set<Key> dataPackRecipes;
|
||||
|
||||
@@ -206,7 +203,6 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
this.injectedDataPackRecipes = new ArrayList<>();
|
||||
this.registeredCustomRecipes = new ArrayList<>();
|
||||
this.dataPackRecipes = new HashSet<>();
|
||||
this.customRecipes = new HashSet<>();
|
||||
this.recipeEventListener = new RecipeEventListener(plugin, this, plugin.itemManager());
|
||||
if (VersionHelper.isVersionNewerThan1_21()) {
|
||||
this.crafterEventListener = new CrafterEventListener(plugin, this, plugin.itemManager());
|
||||
@@ -239,7 +235,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public boolean isCustomRecipe(Key key) {
|
||||
return this.customRecipes.contains(key);
|
||||
return this.byId.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,7 +275,6 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
this.recipes.clear();
|
||||
this.byId.clear();
|
||||
this.dataPackRecipes.clear();
|
||||
this.customRecipes.clear();
|
||||
|
||||
try {
|
||||
// do not unregister them
|
||||
@@ -314,17 +309,17 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
if (!ConfigManager.enableRecipeSystem()) return;
|
||||
if (this.customRecipes.contains(id)) {
|
||||
if (this.byId.containsKey(id)) {
|
||||
this.plugin.logger().warn(path, "Duplicated recipe " + id);
|
||||
return;
|
||||
}
|
||||
Recipe<ItemStack> recipe = RecipeTypes.fromMap(section);
|
||||
Recipe<ItemStack> recipe = RecipeTypes.fromMap(id, section);
|
||||
NamespacedKey key = NamespacedKey.fromString(id.toString());
|
||||
BUKKIT_RECIPE_REGISTER.get(recipe.type()).accept(key, recipe);
|
||||
try {
|
||||
this.registeredCustomRecipes.add(key);
|
||||
this.customRecipes.add(id);
|
||||
this.recipes.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe);
|
||||
this.byId.put(id, recipe);
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to add custom recipe " + id, e);
|
||||
}
|
||||
@@ -337,8 +332,8 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
|
||||
// example: stone button
|
||||
public void addVanillaInternalRecipe(Key id, Recipe<ItemStack> recipe) {
|
||||
this.customRecipes.add(id);
|
||||
this.recipes.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe);
|
||||
this.byId.put(id, recipe);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -357,20 +352,13 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
@Nullable
|
||||
@Override
|
||||
public Recipe<ItemStack> getRecipe(Key type, RecipeInput input, Key lastRecipe) {
|
||||
List<Recipe<ItemStack>> recipes = this.recipes.get(type);
|
||||
if (recipes == null) return null;
|
||||
if (lastRecipe != null) {
|
||||
Recipe<ItemStack> last = byId.get(lastRecipe);
|
||||
if (last != null && last.matches(input)) {
|
||||
return last;
|
||||
}
|
||||
for (Recipe<ItemStack> recipe : recipes) {
|
||||
if (recipe.matches(input)) {
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return getRecipe(type, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -524,6 +512,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
}
|
||||
|
||||
CustomShapelessRecipe<ItemStack> ceRecipe = new CustomShapelessRecipe<>(
|
||||
id,
|
||||
recipe.category(),
|
||||
recipe.group(),
|
||||
ingredientList,
|
||||
@@ -581,6 +570,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
}
|
||||
|
||||
CustomShapedRecipe<ItemStack> ceRecipe = new CustomShapedRecipe<>(
|
||||
id,
|
||||
recipe.category(),
|
||||
recipe.group(),
|
||||
new CustomShapedRecipe.Pattern<>(recipe.pattern(), ingredients),
|
||||
@@ -604,7 +594,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private void handleDataPackCookingRecipe(Key id,
|
||||
VanillaCookingRecipe recipe,
|
||||
PentaFunction<NamespacedKey, ItemStack, RecipeChoice, Float, Integer, org.bukkit.inventory.CookingRecipe<?>> constructor1,
|
||||
HexaFunction<CookingRecipeCategory, String, Ingredient<ItemStack>, Integer, Float, CustomRecipeResult<ItemStack>, CookingRecipe<ItemStack>> constructor2,
|
||||
HeptaFunction<Key, CookingRecipeCategory, String, Ingredient<ItemStack>, Integer, Float, CustomRecipeResult<ItemStack>, CookingRecipe<ItemStack>> constructor2,
|
||||
Method fromBukkitRecipeMethod,
|
||||
Consumer<Runnable> callback) {
|
||||
NamespacedKey key = new NamespacedKey(id.namespace(), id.value());
|
||||
@@ -638,6 +628,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
}
|
||||
|
||||
CookingRecipe<ItemStack> ceRecipe = constructor2.apply(
|
||||
id,
|
||||
recipe.category(),
|
||||
recipe.group(),
|
||||
Ingredient.of(holders),
|
||||
|
||||
@@ -158,27 +158,19 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
// though it might be inaccurate after reloading
|
||||
// but it's worthy to cache
|
||||
Recipe<ItemStack> lastRecipe = serverPlayer.lastUsedRecipe();
|
||||
if (lastRecipe != null && (lastRecipe.type() == RecipeTypes.SHAPELESS || lastRecipe.type() == RecipeTypes.SHAPED )) {
|
||||
if (lastRecipe.matches(input)) {
|
||||
inventory.setResult(lastRecipe.getResult(serverPlayer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
Key lastRecipe = serverPlayer.lastUsedRecipe();
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SHAPELESS, input);
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SHAPELESS, input, lastRecipe);
|
||||
if (ceRecipe != null) {
|
||||
inventory.setResult(ceRecipe.getResult(serverPlayer));
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe);
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||
return;
|
||||
}
|
||||
ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SHAPED, input);
|
||||
ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SHAPED, input, lastRecipe);
|
||||
if (ceRecipe != null) {
|
||||
inventory.setResult(ceRecipe.getResult(serverPlayer));
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe);
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ public class BukkitInjector {
|
||||
private static Class<?> clazz$InjectedCacheChecker;
|
||||
private static Field field$InjectedCacheChecker$recipeType;
|
||||
private static Field field$InjectedCacheChecker$lastRecipe;
|
||||
private static Field field$InjectedCacheChecker$lastCustomRecipe;
|
||||
|
||||
public static void init() {
|
||||
try {
|
||||
@@ -87,6 +88,7 @@ public class BukkitInjector {
|
||||
.implement(Reflections.clazz$RecipeManager$CachedCheck)
|
||||
.defineField("recipeType", Reflections.clazz$RecipeType, Visibility.PUBLIC)
|
||||
.defineField("lastRecipe", Object.class, Visibility.PUBLIC)
|
||||
.defineField("lastCustomRecipe", Key.class, Visibility.PUBLIC)
|
||||
.method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a")))
|
||||
.intercept(MethodDelegation.to(
|
||||
VersionHelper.isVersionNewerThan1_21_2() ?
|
||||
@@ -102,6 +104,7 @@ public class BukkitInjector {
|
||||
.getLoaded();
|
||||
field$InjectedCacheChecker$recipeType = clazz$InjectedCacheChecker.getDeclaredField("recipeType");
|
||||
field$InjectedCacheChecker$lastRecipe = clazz$InjectedCacheChecker.getDeclaredField("lastRecipe");
|
||||
field$InjectedCacheChecker$lastCustomRecipe = clazz$InjectedCacheChecker.getDeclaredField("lastCustomRecipe");
|
||||
|
||||
// Paletted Container
|
||||
clazz$InjectedPalettedContainer = byteBuddy
|
||||
@@ -336,20 +339,22 @@ public class BukkitInjector {
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Cache recipes, it might be incorrect on reloading
|
||||
field$InjectedCacheChecker$lastCustomRecipe.set(thisObj, ceRecipe.id());
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, resourceLocation);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(pair.getSecond()));
|
||||
@@ -392,20 +397,22 @@ public class BukkitInjector {
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Cache recipes, it might be incorrect on reloading
|
||||
field$InjectedCacheChecker$lastCustomRecipe.set(thisObj, ceRecipe.id());
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
@@ -447,20 +454,22 @@ public class BukkitInjector {
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Cache recipes, it might be incorrect on reloading
|
||||
field$InjectedCacheChecker$lastCustomRecipe.set(thisObj, ceRecipe.id());
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
@@ -503,20 +512,22 @@ public class BukkitInjector {
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input, lastCustomRecipe);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input, lastCustomRecipe);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Cache recipes, it might be incorrect on reloading
|
||||
field$InjectedCacheChecker$lastCustomRecipe.set(thisObj, ceRecipe.id());
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
|
||||
@@ -10,7 +10,6 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
@@ -61,7 +60,7 @@ public class BukkitServerPlayer extends Player {
|
||||
private int resentSoundTick;
|
||||
private int resentSwingTick;
|
||||
|
||||
private Recipe<ItemStack> lastUsedRecipe = null;
|
||||
private Key lastUsedRecipe = null;
|
||||
|
||||
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
|
||||
this.channel = channel;
|
||||
@@ -536,11 +535,11 @@ public class BukkitServerPlayer extends Player {
|
||||
return resentSwingTick == gameTicks();
|
||||
}
|
||||
|
||||
public Recipe<ItemStack> lastUsedRecipe() {
|
||||
public Key lastUsedRecipe() {
|
||||
return lastUsedRecipe;
|
||||
}
|
||||
|
||||
public void setLastUsedRecipe(Recipe<ItemStack> lastUsedRecipe) {
|
||||
public void setLastUsedRecipe(Key lastUsedRecipe) {
|
||||
this.lastUsedRecipe = lastUsedRecipe;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user