Improve reliability of Shapeless Recipe logic

per feedback from @liach about a bug with vanillas previous logic
that we essentially just reverted to. complex recipes could run into
cases where a recipe that does have enough items can be unsatisfied
if the items are in certain orders, making them not truely shapeless.

this scenario doesn't occur in vanilla, but users can load custom recipes.

this improves the logic to do some sorting on the lists to improve
chances of matching the recipes harder ingredients before the easier
to satisfy ingredients.

the likelyhood of someone adding a recipe that still fails this is too
extreme to care about. i doubt mojangs implementation is perfect either.

we can improve this logic more later if we actually get bug reports on it.
This commit is contained in:
Aikar 2019-02-28 00:02:20 -05:00
parent 0aa65d90c1
commit 62ba4fbc95

View file

@ -10,18 +10,18 @@ This made the Bukkit RecipeChoice API not work for Shapeless.
This reimplements vanilla logic using the same test logic as Shaped
diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java
index 819b4ac2da..1dc9a1c93c 100644
index 819b4ac2da..ea4083a45a 100644
--- a/src/main/java/net/minecraft/server/ShapelessRecipes.java
+++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java
@@ -0,0 +0,0 @@ public class ShapelessRecipes implements IRecipe {
if (!(iinventory instanceof InventoryCrafting)) {
return false;
} else {
- AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager();
- int i = 0;
-
+ // Paper start - use RecipeItemStack.test
AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager();
int i = 0;
+ // Paper start
+ java.util.List<ItemStack> providedItems = new java.util.ArrayList<>();
+ co.aikar.util.Counter<ItemStack> matchedProvided = new co.aikar.util.Counter<>();
+ co.aikar.util.Counter<RecipeItemStack> matchedIngredients = new co.aikar.util.Counter<>();
+ // Paper end
for (int j = 0; j < iinventory.n(); ++j) {
for (int k = 0; k < iinventory.U_(); ++k) {
ItemStack itemstack = iinventory.getItem(k + j * iinventory.U_());
@ -29,13 +29,25 @@ index 819b4ac2da..1dc9a1c93c 100644
if (!itemstack.isEmpty()) {
- ++i;
- autorecipestackmanager.b(new ItemStack(itemstack.getItem()));
+ providedItems.add(itemstack.cloneItemStack());
+ // Paper start
+ itemstack = itemstack.cloneItemStack();
+ providedItems.add(itemstack);
+ for (RecipeItemStack ingredient : ingredients) {
+ if (ingredient.test(itemstack)) {
+ matchedProvided.increment(itemstack);
+ matchedIngredients.increment(ingredient);
+ }
+ }
+ // Paper end
}
}
}
-
- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null);
+ // Paper start
+ java.util.List<RecipeItemStack> ingredients = new java.util.ArrayList<>(this.ingredients);
+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed());
+ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c)));
+
+ PROVIDED:
+ for (ItemStack provided : providedItems) {