-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding PredicateChoice to Paper API #9996
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing all sorts of // Paper
comments, but that's not a big deal.
Overall, this works with my initial testing. I haven't yet done any spark profiles yet to see if the performance is significantly worse or anything.
My main concern with this is the unnecessary replacement of MaterialChoice and ExactChoice. We should just be able to add a 3rd (PredicateChoice) to that lineup without needing to replace the others.
This is just a quick mockup of what I had in mind. Ignore the API, it is just quicker to make it not an interface+record. I didn't exhaustively test it, but the test in the test-plugin work so far. |
Looks good to me! :) My PR was more of a proof of concept. I am fine with your implementation. |
You can go ahead and fixup yours |
Allright |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created two new patches. Your implementation heavily inspires them. It is way cleaner to use the logic when a predicate is used.
Even fewer code changes than before. I tested things myself, and it works like a charm :)
Since we know that the extra map logic works, we use working code and add more item contents to its storage. In this case, the items that match any predicate choice.
It is a simple solution that brings many new possibilities to the table.
Hope there is no fatal flaw in this idea.
+ boolean isStackTypeRegistered = this.exactChoiceIds.getInt(stack) > -1; | ||
+ final int id = this.registerExact(stack); | ||
+ // We only want to add the stacking id to the list one time | ||
+ if(!isStackTypeRegistered) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should just be able to check the id
returned by registerExact
if it is -1, it's already been added to the exactChoice map.
+ return Objects.equals(itemPredicate, that.itemPredicate); | ||
+ } | ||
+ | ||
+ public static interface ItemPredicate extends Predicate<ItemStack> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type shouldn't exist
+ /** | ||
+ * Represents a choice that matches when the item predicate is fulfilled. | ||
+ */ | ||
+ public static class PredicateChoice implements RecipeChoice { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be an interface that is backed by a package-private record implementation with static methods to create instances of it.
|
||
public static final Ingredient EMPTY = new Ingredient(Stream.empty()); | ||
private final Ingredient.Value[] values; | ||
+ @Nullable private RecipeChoice.PredicateChoice.ItemPredicate itemPredicate; // Paper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just have a public field for Predicate
+ // Paper start - Adding PredicateChoice | ||
+ public Ingredient(RecipeChoice.PredicateChoice.ItemPredicate itemPredicate) { | ||
+ List<org.bukkit.inventory.ItemStack> bukkitChoices = itemPredicate.recipeBookExamples(); | ||
+ this.itemPredicate = itemPredicate; | ||
+ this.values = bukkitChoices.stream().map(CraftItemStack::asNMSCopy).map(ItemValue::new).toArray(Value[]::new); | ||
+ } | ||
+ // Paper end - Adding PredicateChoice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a custom constructor, do all the logic in CraftRecipe
+ // Paper start - Adding PredicateChoice | ||
+ @Nullable | ||
+ public RecipeChoice.PredicateChoice.ItemPredicate getItemPredicate() { | ||
+ return itemPredicate; | ||
+ } | ||
+ // Paper end - Adding PredicateChoice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with a public field, no need for a getter
+ } | ||
+ // Paper start - Adding PredicateChoice | ||
+ else if(bukkit instanceof RecipeChoice.PredicateChoice predicateChoice){ | ||
+ stack = new Ingredient(predicateChoice.getItemPredicate()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use the regular constructor and pass in the recipe book examples as itemstacks and then assign the predicate field on the next line.
PaperMC/Paper#9996 I merged this change, added @NotNull tags to get the API to build, and deleted the existing Purpur item predicate API since it was conflicting.
Is this still being worked on? |
Hello! I was working on my bachelor thesis lately so i was not able to fully work on this. |
- Fixed RecipeBook click not working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the diff in the server patch can be moved back to the patch that created it, such as simple renames, like the hasExactIngredients but that doesn't have to be done now, can be done before merging.
We also need to make it clear that mutating the stack within the Predicate provided in the create
method does not support mutating the stack in an way. I don't want to open that can of worms, and I also don't want to copy the itemstack each time that predicate might be called.
+ | ||
+ @Override | ||
+ public @NotNull RecipeChoice clone() { | ||
+ return new PredicateChoiceImpl(predicate, recipeBookExamples()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also has to clone each itemstack in the recipe book examples because ItemStack is a mutable type.
+ static PredicateChoice create(@NotNull Predicate<ItemStack> predicate, ItemStack... recipeBookExamples){ | ||
+ Objects.requireNonNull(predicate, "The item predicate cannot be null!"); | ||
+ Objects.requireNonNull(predicate, "The mustHaveRecipeBookExample cannot be null!"); | ||
+ if(recipeBookExamples.length == 0) | ||
+ throw new IllegalArgumentException("Please provide at least one recipe book example item!"); | ||
+ return new PredicateChoiceImpl(predicate, List.of(recipeBookExamples)); | ||
+ } | ||
+ | ||
+ static PredicateChoice create(@NotNull Predicate<ItemStack> predicate, java.util.Collection<ItemStack> recipeBookExamples){ | ||
+ Objects.requireNonNull(predicate, "The item predicate cannot be null!"); | ||
+ Objects.requireNonNull(predicate, "The mustHaveRecipeBookExample cannot be null!"); | ||
+ if(recipeBookExamples.isEmpty()) | ||
+ throw new IllegalArgumentException("Please provide at least one recipe book example item!"); | ||
+ return new PredicateChoiceImpl(predicate, List.copyOf(recipeBookExamples)); | ||
+ } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move these methods up 1 level to be on RecipeChoice itself and named createPredicateChoice
An alternative would be to just make PredicateChoice a top-level class next to RecipeChoice and have create
methods in it. Not a fan of the static factory methods inside an inner class.
+ interface PredicateChoice extends RecipeChoice { | ||
+ static PredicateChoice create(@NotNull Predicate<ItemStack> predicate, ItemStack... recipeBookExamples){ | ||
+ Objects.requireNonNull(predicate, "The item predicate cannot be null!"); | ||
+ Objects.requireNonNull(predicate, "The mustHaveRecipeBookExample cannot be null!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line checks the exactly same thing as the one above... I think here should be recipeBookExamples?
+ | ||
+ static PredicateChoice create(@NotNull Predicate<ItemStack> predicate, java.util.Collection<ItemStack> recipeBookExamples){ | ||
+ Objects.requireNonNull(predicate, "The item predicate cannot be null!"); | ||
+ Objects.requireNonNull(predicate, "The mustHaveRecipeBookExample cannot be null!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line checks the exactly same thing as the one above... I think here should be recipeBookExamples?
3 days ago I posted a pull request #9991 about adding CustomModelChoice. However, we came to the conclusion that we need a more generalized approach.
As a result, I began working on what is called PredicateChoice.
To make it work the StackedContents logic had to be edited.
In the ExtraContentsMap we don't store the exact ingredient items of every recipe ingredient. Instead, whenever we account a new stack in StackedContents logic we compare it to the provided predicates and store them as "ingredient items" if they fulfill at least one predicate.
We act like the items in the inventory of the player are the exact choices when any ingredient predicate returns true.
It gets more apparent when looking at the changes.
The first tests showed that it works like a charm.
Pros
Cons
Let me know your thoughts! :) Maybe I have missed something.