Skip to content
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

Enchantment api #291

Draft
wants to merge 13 commits into
base: 1.19.4
Choose a base branch
from
Draft

Enchantment api #291

wants to merge 13 commits into from

Conversation

Platymemo
Copy link
Contributor

@Platymemo Platymemo commented Mar 30, 2023

This is a reboot of #20. Below are quoted points by @Vaerian when constructing the original PR.

Preface: I recognize this is not where the repo's priority is right now, and considering how much of a rough draft this PR is, don't waste your time reviewing it unless you care deeply about the direction of this specific module (i.e. you provided/wanted to provide input on issue #13).

This PR adds a custom enchantment API similar to the one discussed in #13. I'm making this a draft PR so the discussion around this API can have something to conceptualize what would be required to make these changes a reality. The specific structure of the implementation is still up for debate, but this is generally what it could look like.

As previously mentioned this is still definitely a draft. It is likely that the majority of the structure of this PR will change including everything from javadocs and class names, to implementation details and method signatures. Don't waste your time nit-picking every individual detail at this point (I'm sure something somewhere is misspelled). Focus more on the big picture.

Discussion Questions

What additional information could developers benefit from having in the enchantment context?
Should the equipment slot array system be modified? If so, how? Is there a way to allow expandability of EquipmentSlots for something like Trinkets?
Which library does the API belong in? Should it stay in content_other?
How should event callbacks for random enchantments and anvil application work?
What kind of information should developers have access to when determining the compatibility of enchantments?
Enchantments use a variety of values such as the amount of bookcases, the "power" of the enchantment table, the level of the enchantment (i.e. I, II, III, etc.), the enchantment tier (the three boxes in the menu), etc. This gets kind of confusing in code. > Is there a way we can standardize these terms both in the API and in the mappings? If so, what should that look like?
How can the API be modified to be more straightforward to use?
What kind of enchantment helper methods should the API include for developers to use?
Should there be some kind of framework/a couple methods to help developers create custom enchantment tables? What are the potential use cases for that? Would enough people use that? Is that in the scope of QSL?
Closes #13

This is a question concerning API design. Enchantments are used in a wide variety of places such as random loot, mob equipment with random enchantments, villager tool trades, the enchantment table, and more. Ideally this API would give developers control over whether their enchantment can be added in any of those scenarios. The only issue is that all total that makes up about 6 different contexts in which enchantments can be used. It doesn't really make sense to create a method for every single one of those contexts so instead should we create a common interface for enchantment contexts and allow developers to check if the context is an instance of a specific type of context? The only issue I see with that is each scenario is a little bit different and it doesn't really make much sense for someone to have to write an if else statement with 6 conditions every time they want to write complicated functionality, but then again it's a little weird for someone to have to write implementations for 6 different methods. Additionally, making it a common interface might make it easier for developers to create their own enchantment contexts with special logic.

Currently, I have implemented a common enchanting context, that is then expanded upon by more specific scopes. It currently requires 3 different contexts (base, entity, and player+block) to reach all 6 locations.

Progress

  • Support for customizable item groups for custom enchanted books
  • Powerful "enchantment targets" (using Enchantment#isAcceptableItem and QuiltEnchantment#isAcceptableContext)
  • Developers have access to the World, PlayerEntity, enchantment power, enchantment level, ItemStack, BlockPos, BlockState, and BlockEntity.
  • Enchantment weight can be defined per level/context
  • Enchantment weight free from the rarity enum
  • Add proper handling of treasure logic to the enchantment context
  • Support for more a powerful anvil application context
  • Support random enchants for entity spawns, enchanted tool trades, and loot functions
  • Custom interface for items to take priority over enchantment compatibility
  • Event callbacks for random enchantment and anvil application
  • Enchantment compatibility takes into account the enchantment level (potentially the entire enchantment context) (superceded by event callbacks which can do just as much)

Vaerian and others added 4 commits March 16, 2023 18:15
- Added support for customizable item groups for custom enchantment books
- Added more powerful "enchantment targets"
    - Enchantment weight can now be defined per level/context
    - Developers have access to the full world, player, enchantment power, etc.
- Added a test mod illustrating a custom enchantment target for only hoes
- Does not include support for more a powerful anvil application context
- Is in a very rough stage and will be changed significantly before stable
@ix0rai ix0rai added new: module A pull request which adds a new module library: item Related to the item library. t: new api This adds a new API. s: wip This pull request is being worked on. labels Apr 3, 2023
Comment on lines +29 to +40
/**
* Determines whether the provided enchantment can be applied to this item.
* <p>
* This takes highest priority for applying enchantments.
* @param stack the stack containing this item
* @param enchantment the enchantment to apply to this item
* @return {@code true} if the enchantment can be applied, or {@code false} otherwise
*/
@Contract(pure = true)
default boolean canEnchant(ItemStack stack, Enchantment enchantment) {
return enchantment.isAcceptableItem(stack);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if a TriState might be better? Either override true, override false, or default to enchantment choice. As of now, it's a complete override if the item implements this interface, hence the default implementation, so calling super will allow the enchantment to decide (Note that the enchantment's decision likely doesn't take the other enchantments on the item into account, as there's the separate Enchantment#canCombine(Enchantment)).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do a tristate. Maybe an enum would be clear? Not sure what best way is to convey meaning of overriding behaviors

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, the modder does have the enchantment and can just check the enchantment's canEnchant directly if they want to know what the default was

@Ampflower
Copy link
Contributor

A random thought given the approach chosen here for handling contexts; it does seem fragile, especially for maintenance as there's a point of failure if the context fails to be cleared for a given thread.

Wouldn't a better approach to be sending an event with the context that could be in use, given it looks to be intended for mods?

There doesn't seem to be any concurrency issues with same thread, as the context looks to be created and destroyed within the same method, tho the potential for error is there if it gets spread around multiple threads tho.

Copy link
Contributor

@EnnuiL EnnuiL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a full review yet, but

@EnnuiL EnnuiL mentioned this pull request Apr 12, 2023
9 tasks
@Platymemo
Copy link
Contributor Author

A random thought given the approach chosen here for handling contexts; it does seem fragile, especially for maintenance as there's a point of failure if the context fails to be cleared for a given thread.

Wouldn't a better approach to be sending an event with the context that could be in use, given it looks to be intended for mods?

There doesn't seem to be any concurrency issues with same thread, as the context looks to be created and destroyed within the same method, tho the potential for error is there if it gets spread around multiple threads tho.

I like events! They're in the planned todo above but I just hadn't gotten to them. But yeah, I wish there were a safer, more robust way to gather the context.

Copy link
Contributor

@Leo40Git Leo40Git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@NathanX-S
Copy link

Any reason this hasn't been merged yet?

@OroArmor
Copy link
Member

It's still a draft PR, plus it doesn't target the current development version for QSL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library: item Related to the item library. new: module A pull request which adds a new module s: wip This pull request is being worked on. t: new api This adds a new API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EnchantmentTarget enum needs a proper fix
9 participants