-
Notifications
You must be signed in to change notification settings - Fork 324
Spoilage #3874
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
base: 1.20.1-v8.0.0
Are you sure you want to change the base?
Spoilage #3874
Conversation
jurrejelle
left a comment
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.
Very quick review before I have to go do other things, these are my initial thoughts
| @Inject(at = @At("HEAD"), method = "isSameItemSameTags", cancellable = true) | ||
| private static void mergeSpoilables(ItemStack stack, ItemStack other, CallbackInfoReturnable<Boolean> cir) { | ||
| CompoundTag tag1 = stack.getTagElement("GTCEu_spoilable"); | ||
| CompoundTag tag2 = other.getTagElement("GTCEu_spoilable"); | ||
| boolean isSameItem = ItemStack.isSameItem(stack, other) && stack.areCapsCompatible(other); | ||
| if (tag1 != null && tag2 != null) { | ||
| long tick1 = tag1.getLong("creation_tick"); | ||
| long tick2 = tag2.getLong("creation_tick"); | ||
| if (tick1 != tick2) { | ||
| long avg = (tick1 * stack.getCount() + tick2 * other.getCount()) / | ||
| (stack.getCount() + other.getCount()); | ||
| tag1.putLong("creation_tick", avg); | ||
| tag2.putLong("creation_tick", avg); | ||
| } | ||
| } | ||
| cir.setReturnValue(isSameItem && Objects.equals(stack.getTag(), other.getTag())); | ||
| cir.cancel(); | ||
| } |
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.
Why is this done in isSameItemSameTags? Now, when we e.g. compare two itemstacks for recipe checking but the recipe can't run, it will still assign the average spoil value
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.
To be fair, it's very difficult to know when to merge spoilability status and items don't really have a "merge" function. I'm not sure how we would implement this
|
Some thoughts I had laid out in the discord, ramble style, that I'd like to document here:
|
src/main/java/com/gregtechceu/gtceu/api/item/ISpoilableItemStackExtension.java
Show resolved
Hide resolved
src/main/java/com/gregtechceu/gtceu/core/mixins/ItemStackMixin.java
Outdated
Show resolved
Hide resolved
src/main/java/com/gregtechceu/gtceu/core/mixins/ItemStackMixin.java
Outdated
Show resolved
Hide resolved
src/main/java/com/gregtechceu/gtceu/core/mixins/ItemStackMixin.java
Outdated
Show resolved
Hide resolved
src/main/java/com/gregtechceu/gtceu/core/mixins/ItemStackMixin.java
Outdated
Show resolved
Hide resolved
src/main/java/com/gregtechceu/gtceu/core/mixins/ItemStackMixin.java
Outdated
Show resolved
Hide resolved
Co-authored-by: screret <[email protected]>
jurrejelle
left a comment
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 initial questions/notes. Maybe also make an v8.0.0 change docs where you mention you added spoilage and link here, see gustavo's sync PR for how to do that.
| - A block and an item handler (contains `Level`, `BlockPos`, `IItemHandler` and an `int` slot, that may be `-1`) | ||
| - An entity, usually a player (contains `Entity` and an `int` slot, that may be `-1`) | ||
|
|
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.
What does the int slot represent?
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.
The slot of the item in the IItemHandler
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.
The slot of the item in the IItemHandler
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.
Maybe consider adding that to the docs then
| - `.result(Function<ItemStack, ItemStack>)` | ||
| used to specify the resulting stack that may depend on the original stack | ||
| - `.result(EntityType<? extends Mob>)` | ||
| used to specify the mob into which the item will spoil (it can still spoil into an item as well, but it has to be specified first) |
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.
What is "it" here? Does the ItemStack have to be specified first, or the EntityType?
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.
The stack has to be specified first, ig i should make that more clear
| ItemStack carried = gui.getModularUIContainer().getCarried().copy(); | ||
| ISpoilableItem spoilable = GTCapabilityHelper.getSpoilable(carried); | ||
| if (spoilable != null) spoilable.freezeSpoiling(); | ||
| slotReference.set(carried); |
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.
Will need to eventually do stuff like this in MUI2 in GTM too when that's implemented
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.
yep
| public MachineBuilder<DEFINITION> addRecipeModifier(RecipeModifier recipeModifier) { | ||
| if (this.recipeModifier instanceof RecipeModifierList list) { | ||
| this.recipeModifier = new RecipeModifierList(ArrayUtils.add(list.getModifiers(), recipeModifier)); | ||
| } else { | ||
| this.recipeModifier = new RecipeModifierList(this.recipeModifier, recipeModifier); | ||
| } | ||
| return this; | ||
| } | ||
|
|
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.
Needs a similar method in MultiblockMachineBuilder since the return type of that is different
| import javax.annotation.Nullable; | ||
|
|
||
| @Mixin(ItemStack.class) | ||
| public abstract class ItemStackMixin implements ISpoilableItemStackExtension { |
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.
Not really an actionable point, but having 13 mixins into ItemStack for spoilage is making my skin crawl and I do not look forward to all the conflicts and problems this will cause with minecraft let alone other mods
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.
well it shouldn't cause any conflicts with anything really, since all it does is call the upsate function
| ISpoilableItem spoilable = GTCapabilityHelper.getSpoilable(stack); | ||
| if (spoilable != null && spoilable.shouldSpoil() && spoilableCount > 0) { | ||
| double spoiled = spoilProgress / spoilableCount; | ||
| spoilable.setTicksUntilSpoiled((long) (spoiled * spoilable.getSpoilTicks())); | ||
| } |
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.
Early return if stack doesn't have a spoilable higher up in the function maybe?
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.
Also what happens if you start a recipe with spoiled inputs + outputs, shut down the world, start it up again? Does it just make a full freshness item?
What
Spoilage yay!
Added API to modify item outputs and read item inputs in recipe modifiers.
Also made an event that fires just before a machine is registered to allow modifying it's parameters from addons (most notably add recipe modifiers)
Implementation Details
Stores the creation tick of a spoilable item in its nbt, thus bypassing the need to actively tick it.
Should be noted that the item has to be updated at least once after it finished crafting for it to start spoiling (done by updating items inserted into
CustomItemStackHandler)Basically everything is done via a mixin into
ItemStacklolsDoesn't actually make any items spoilable, only adds the functionality to do so.
Outcome
GLEBA