Skip to content

[WIP] ItemExpression: Like regexes for ItemStacks #22

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

Draft
wants to merge 108 commits into
base: master
Choose a base branch
from

Conversation

Ameliorate
Copy link

@Ameliorate Ameliorate commented Feb 28, 2019

With ItemExpressions, you can in a YAML config write a definition for an ItemStack that can be compared to other ItemStacks to evaluate a conditional. Think of Regexes are for Strings, ItemExpressions are for ItemStacks. Notably, if you leave a field in an ItemExpression empty, it'll accept any value for that field when matching it over an ItemStack.

Example

match:
  present:
    material: PLAYER_HEAD
    name: §6Present!
    skull.name: MHF_Present1

It should be noted that you can not create an ItemStack from an ItemExpression, just like you can't create a String from a Regex. This is because many parts of an ItemExpression embed regular expressions as part of their functionality.

Matching checklist

Properties of an ItemStack that can be matched:

Text in (parentheses) indicates the features of the property that can be matched, text in [brackets] indicates examples of items where the property is used in vanilla.

  • Material (regex, exact)
  • Amount (range, exact)
  • Durability (range, exact)
  • Lore (multiline regex, list of strings)
  • Name (regex, exact)
  • Enchantments (list of (exactly enchant, level (range, exact)) for any in list, all, and none in list)
  • Held Enchantments [Enchanted book enchantments] (same as enchantments)
  • Player Skulls (list of names, list of uuids, single name, single uuid)
  • Player Skulls (regex)
  • Unbreakable Status (true, false)
  • Inventory [Shulker boxes, creative mode middle-click chests] (arbitrary ItemExpressions)
  • Banner patterns (???)
  • Potion effects (list of (exact effect, level (range, exact)) for any in list, all, and none in list)
  • Book (author: (exact name, regex name, uuid), generation: (exact, range), title: (exact, regex), pages: ???)
  • Firework (???)
  • Knowledge book (???)
  • Leather armor colour (???)
  • Maps (??? (???) (???))
  • Tropical Fish Bucket (body color: (exact, in list, not in list), pattern: (exact, in list, not in list), pattern colour: (exact, in list, not in list))
  • Mob spawner (spawned mob: (exact, in list, not in list), delay: (amount), max nearby entities: (amount), max delay: (amount), min delay: (amount), max range: (amount), spawn count: (amount), spawn range: (amount))
  • Shulker box color (exact, in list, not in list)
  • Item flags (for each flag: (true, false)
  • Attributes (???)

Other Checklist

  • Write a big .md file with all the options for other plugin authors to link to in their documentation
  • (maybe) Squash all these commits
  • (maybe) Change everything for the checkstyle config to not complain

Amelorate added 30 commits February 1, 2019 23:08
The goal of this new API is to be able to have a unified syntax for
matching the various elements that make up an ItemStack.
Think ItemStack.isSimilar() on steroids.
In other words, a regular expression-like syntax for ItemStacks.
Now it used more yaml and less parsing the syntax out of a string.
Was going to have a complicated or function for amount but it was
complicated and I don't want to hvae to implement config parsing
for that right now. This was used in the complicated config parsing.
Now instead of material.exactly: STONE it's material: STONE
Forgot to do that when adding them.
It gets an ItemExpression from a config.
…ument

Now you can reuse them to refer to identical but duplicated options.
I have my font set so small I can barely see when I have a double enter
It only matches if none of the listed enchantments are on the item
Like enchanted books and things
I wrote a simple command that tests ItemExpression with the item in your
hand and found all the bugs.
I couldn't figure out the whole list of regexes thing.
Ameliorate added 8 commits March 13, 2019 00:10
Now it'll ignore matchers == null, in case it is passed in.
It now has a function to implement its logic, and functions to get
each mode's name as UpperCamelCase or lowerCamelCase.

Also adds GenericMatcher, which is implemented for all the *Matcher's.
This is used in the implementation of
ListMatchingMode.matches(Collection<Matcher>, Collection<Thing>).
Basically a bunch of magic. Now all the *matcher interfaces don't have
to say boolean matches(TheThing theThing);. It's automagically infered
by the java compiler somehow. It works, and it even is backwards-
compatible with almost all the classes.
This touches basically everything, but also fixes a lot of bugs and
edge cases.
Now it used NEGATIVE_INFINITY and INFINITY, accepting any number.
@Maxopoly
Copy link

I looked a bit more through what you're doing, seems like very good work. I'd be in favor of entirely deprecating the current ItemMaps in favor of a replacement, which wraps a set of item expressions and offers a clean API to do stuff with them (pretty much anything offered in the current ItemMap). Ideally this would be in its own class not littered with parsing stuff and offer constructors for inventories, item stacks, collections of item stacks, collections of item expressions etc.. That'd be what ItemMaps were always intended to do and one of the few wild carding functionalities old ItemMaps had (durability) is gone with 1.13 anyway.

Thoughts?

Also do you think it'd be possible do add a matcher for arbitrary nbt tags?

@Ameliorate
Copy link
Author

I think ItemMaps are also useful for representing the contents of an inventory, where you can go from a list of ItemStacks to an ItemMap and do something with that ItemMap mutating it, and then turn that ItemMap back into a list of ItemStacks. You can't really do that with ItemExpressions. You sort of could if I add turning a subset of ItemExpressions into ItemStacks, but it wouldn't be fast, nor easy to think about.

However, if ItemMaps are just for matching over lists of ItemStacks where ItemExpressions match over a single ItemStack, then refactoring ItemMap to be like that would be a good idea. Maybe ItemMap should be split into two APIs, one for the List of ItemExpressions thing, and one for the List of ItemStacks thing.


It is possible to add a matcher for arbitrary NBT tags, however matching over nested structural data is a completely different thing. It'd likely be just "Does this item have this tag with exactly this value?".

@Maxopoly
Copy link

You sort of could if I add turning a subset of ItemExpressions into ItemStacks, but it wouldn't be fast, nor easy to think about.

This is IMO a requirement for really getting ItemExpressions usable for something like FactoryMod. Just use minimal behavior everywhere, if something is wildcarded don't have it at all and if an explicit value is specified, use that one.

However, if ItemMaps are just for matching over lists of ItemStacks where ItemExpressions match over a single ItemStack, then refactoring ItemMap to be like that would be a good idea. Maybe ItemMap should be split into two APIs, one for the List of ItemExpressions thing, and one for the List of ItemStacks thing.

Not sure what you mean with the last sentence there. I only really want a thing that holds a set of ItemExpressions as a state and can then answer me questions like "How often is this set contained in that inventory" and do stuff like "Remove X instances of the set from that inventory"

Ameliorate added 11 commits May 19, 2019 10:02
Not yet tested, but oops i accidentally added like 1000 loc for a
feature that was supposed to be minor
Now the any all none stuff is basically the same for everything,
although one to one isn't very widely supported.
Should be slightly more efficent now, although it barely matters.
because testing spigot plugins is aparently a hard problem
Most were regarding ItemExpression solving
Now they reload from the config each time they're used.
I didn't want to document the fact that shulkerbox.inventory also works
for a +NBT inventory chest.
@Ameliorate
Copy link
Author

I've gotten back around to finishing up this PR. Currently I'm writing the documentation at http://amel.pw/wiki/#ItemExpressionConfig:ItemExpression%20ItemExpressionConfig, and I think most of the bugs are fixed, though there are a few untested things.

@ProgrammerDan
Copy link

ProgrammerDan commented Aug 12, 2019 via email

Some bugs might generate items that don't match, but it is also possible
to create ItemExpressions that when solved don't produce an item that
matches.
@Maxopoly
Copy link

Could you put the documentation in a github wiki and not something that looks like a shady ip grabber?

@ProgrammerDan
Copy link

You should have general wiki access here, Amel

@ProgrammerDan
Copy link

Just a heads up that while you were working, a team of folks decided to push for 1.14.4 update. Consequentially, it is quite likely that significant drift from this PR and master has occurred, and a rebase or similar conflict resolution may be necessary before merging. I do look forward to this work completing, however!

Maxopoly added a commit that referenced this pull request Jan 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants