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

[1.21] Storage Rework (ItemHandler, FluidHandler, ItemContext for item caps) #944

Draft
wants to merge 17 commits into
base: 1.20.x
Choose a base branch
from

Conversation

CodexAdrian
Copy link

The Big Storage Rework!

Motivation

NeoForge's storage situation is not great. ItemHandler and FluidHandler are both extremely helpful to devs trying to create a unified standard for storage of resources, but aren't consistent with each other and rely on the usage of mutable resources with amounts attached for transfer. This creates situations where devs have to return copies of their resources in order to safely ensure a dev isnt trying to manipulate their storage directly, or copy the stack passed into the insert method before its inserted in order to ensure the implementor of insert method doesn't attempt to modify the stack when its inserted. Not to mention the inconvenient issues that arise when the resource (item + components) are joined in the same object where so much copying and mutation needs to occur to the stack when most of the time the developer just wants to change the amount the stack contains or insert the same stack into a container with a different amount.

The ideal solution to these problems would be creating a single unified storage class (for consistency) that uses immutable resources (for the mutation problems) whose count is separated from the resource (for the inconvenience problems).

Implementation

Much of the implementation was inspired by FabricMC/fabric#1356 and how it was subsequently built out in the later years, and is a continuation of Tech's initial PR to introduce immutable resources in #715

IStorage

IStorage is a new interface that will eventually fully replace usages of IItemHandler and IFluidHandler. It is a slotted container that stores an integer amount of a resource of type T. This type doesn't necessarily have to be an IResource class, but utilities will be provided for storage classes that do. In this implementation, T should be immutable and should be countless, as the amount is retrieved in a separate getAmount(slot) method.

IResource and FluidResource/ItemResource

IResource is the basis for the Neo provided storage capabilities. Its an immutable data component holder with a utility methods that return a new resource with modified components without mutating the resource to make it easy to interact with. Lastly, it contains an isBlank method to indicate whether or not the resource should be considered blank or empty, like if the resource is of Items.AIR or Fluids.EMPTY. The default resources provided by Neo are FluidResource and ItemResource and represent immutable types of a fluid/item and data components.

ResourceStack

ResourceStack is a utility class that contains an instance of IResource and an integer amount. It provides the same utility methods IResource methods provides for copying with modifications while also providing similar utilities for amount based copying. ResourceStack should largely replace the usage of ItemStack or FluidStack in the usage of code.

IItemContext

ItemContext is a new interface for general usage when interacting with inventories. Its centered around a main slot, whose contents IItemContext can be used to get its current state (resource and amount). This context also allows devs to manipulate the ItemResource and amount in the main slot, by extracting, inserting or exchanging items into it. Extracting will extract items of a given ItemResource and amount from the slot, returning how much was extracted from the main slot. Inserting into the context will not only insert into the main slot, but is also intended to insert whatever does not fit into the main slot into some kind of outer container. This can be an outer container like a buffer or a context could choose to drop the excess onto the ground, its up to the implementor of IItemContext to say where items go. Exchanging allows devs to extract however many items that are requested to be exchanged and then inserting a new resource in its place up to the amount extracted. Devs should also dump excess items that were not successfully inserted into the main slot into some kind of overflow as well (if you choose to support having an overflow for your items).

This new class largely replaces the need for any item specific capabilities, like IFluidHandlerItem, while also providing devs with much needed utility to insert excess into a slot other than itself. This should make it possible to, for example, have a stacked fluid container where only 1 of 16 items are drained. The fluid storage can simply call exchange with 1 empty storage container, without needing to worry about whether or not the stack is of stack size 1.

ItemContext also contains a helpful utility which you can use to retrieve the capability found on item in the main slot without needing to pass in an ItemStack

The Fallen

This PR also sets IItemHandler and IFluidHandler for deprecation and marked them for removal in 1.22. Currently these classes have been retrofit to extend IStorage<ItemResource> and IStorage<FluidResource> respectively, and will eventually be phased out entirely for just using the base storage classes. While consideration to keeping some of the old API around has been made, this PR does still make a breaking change in the removal of IFluidHandlerItem, and the modification of existing Item capabilities to have the aforementioned IItemContext as its new context class (which also replaces the need of having the getContainer method in IFluidHandlerItem).

Interaction changes

With immutable resources and IStorage<ItemResource> and IItemContext, its safe to say that modifying the ItemStack in which a capability was retrieved from will not always achieve the desired effect. As such, developers should now take care to use ItemContext to make any modifications needed to the main stack using the methods provided in ItemContext, even if those changes are just component or size related changes. Developers should treat that ItemStack given to them in the capability provider as read only, and should also take care to note it is only accurate at the time of creation of the cap class, and may not be updated to reflect changes made with IItemContext. Devs should use the resource and amount provided in IItemContext as an accurate image of what the item in its slot currently looks like

Notes

This was a doozy to write, and might not be a complete overlook of this PR when it is time to merge it. I'll do my best to update the description as needed. This PR is (as of May 8th, 2024) not complete, but was opened so others could see what the changes I was making were and could comment on them while in dev.

@CLAassistant
Copy link

CLAassistant commented May 9, 2024

CLA assistant check
All committers have signed the CLA.

@neoforged-pr-publishing
Copy link

  • Publish PR to GitHub Packages

@Technici4n Technici4n self-assigned this May 9, 2024
@Spinoscythe
Copy link
Contributor

@CodexAdrian isBlank -> isEmpty?

@CodexAdrian
Copy link
Author

@CodexAdrian isBlank -> isEmpty?

Yeah i can make that change

@Technici4n
Copy link
Member

I disagree. isBlank was chosen for immutable resources because it does not have any connotation of an "amount" with it.

@Spinoscythe
Copy link
Contributor

I disagree. isBlank was chosen for immutable resources because it does not have any connotation of an "amount" with it.

isAbsent maybe then?

@CodexAdrian
Copy link
Author

isBlank is better than isAbsent, I do personally think isEmpty works best for Minecraft related content. It's what Mojang uses for the empty fluid as well.

@Spinoscythe
Copy link
Contributor

isBlank just sounds blegh to me

@Technici4n
Copy link
Member

@Spinoscythe you'll get used to it. Trust me.

@robotgryphon
Copy link
Contributor

+1 for isEmpty over isBlank/isAbsent - akin to ItemStack.EMPTY and FluidStack.EMPTY

@Technici4n
Copy link
Member

FluidStack and ItemStack have the notion of amount that fluid resources do not have. Hence isEmpty will get two subtly different meanings. This is closer to Item.isAir() (if it exists). Technically you can have 0 of a non-blank resource. Yet that would be an empty slot.

@Spinoscythe
Copy link
Contributor

Any reason for not merging this in 1.21?

@CodexAdrian
Copy link
Author

I'm not sure what you mean, the PR is targeting 1.21

@Spinoscythe
Copy link
Contributor

image

@CodexAdrian
Copy link
Author

The idea is to allow the older containers to work to make it easier on devs to transition, but to remove them on the next major version.

@Matyrobbrt Matyrobbrt added enhancement New (or improvement to existing) feature or request breaking change Breaks binary compatibility 1.20.6 Targeted at Minecraft 1.20.6 labels May 15, 2024
commit 8ac9f9c
Author: Minecraftschurli <minecraftschurli@gmail.com>
Date:   Tue May 21 15:25:59 2024 +0200

    [Testframework] Fix wrapping GameTestAssertException (neoforged#988)

commit 66197fe
Author: Max <max@someone.ky>
Date:   Sat May 18 20:11:00 2024 +0200

    Add a Fluid Ingredient system as an analogue to vanilla's Ingredient (neoforged#789)

commit b1c3fe0
Author: NeoForged Localizations <machine-l10n@neoforged.net>
Date:   Sun May 19 00:43:32 2024 +0800

    New Crowdin updates (neoforged#972)

commit a7edbae
Author: Sara Freimer <sara@freimer.com>
Date:   Fri May 17 01:32:34 2024 -0500

    Implement equals and hashCode for SizedIngredients (neoforged#965)

commit e9e8af0
Author: Dennis C <xfacthd@gmx.de>
Date:   Fri May 17 08:31:55 2024 +0200

    [1.20.6] Use extensible enum codec and streamcodec for rarity enum (neoforged#958)

commit 986e0e3
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Fri May 17 02:28:12 2024 -0400

    Patch in missing LivingJumpEvent for Slime and Camel (neoforged#966)

commit 2bf3073
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Fri May 17 02:26:49 2024 -0400

    Pass growing plant blockstate into onCropsGrowPre for various vine blocks (neoforged#967)

commit 0033435
Author: embeddedt <42941056+embeddedt@users.noreply.github.com>
Date:   Fri May 17 02:25:24 2024 -0400

    Fix ComputeCameraAngles event applying roll in global space (neoforged#968)

commit bb3537b
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Wed May 15 23:02:02 2024 -0400

    [no ci] Remove PitcherCrop patch TODO (neoforged#963)

commit d80f154
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Wed May 15 23:01:36 2024 -0400

    [no ci] Fixed Bubble Column gametest template size (neoforged#964)

commit c888a68
Author: Luke Bemish <lukebemish@lukebemish.dev>
Date:   Wed May 15 01:29:03 2024 -0500

    [1.20.6] Add KnownPacks for mods (neoforged#901)

commit a28986f
Author: shartte <shartte@users.noreply.github.com>
Date:   Mon May 13 09:13:19 2024 +0200

    Update FML to 3.0.29 (neoforged#957)

commit 2aadb61
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Sat May 11 14:11:06 2024 -0400

    Make StructureTemplate's Palette caches thread safe (neoforged#954)

commit 2bced72
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Sat May 11 13:49:18 2024 -0400

    Address POI memory leak and Generate Command issues (neoforged#937)

    Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>

commit abc54b7
Author: Sirttas <Sirttas@users.noreply.github.com>
Date:   Sat May 11 19:48:09 2024 +0200

    [Test Framework] Add a check in `StructureTemplateBuilder#set` to prevent placing block outside template bondaries (neoforged#950)

commit 2d93ce5
Author: embeddedt <42941056+embeddedt@users.noreply.github.com>
Date:   Sat May 11 01:28:34 2024 -0400

    Delete ItemModelShaper patch (neoforged#952)

commit 018e104
Author: embeddedt <42941056+embeddedt@users.noreply.github.com>
Date:   Fri May 10 19:58:05 2024 -0400

    Fix more particle culling issues (neoforged#951)

commit 03e346b
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Fri May 10 12:14:37 2024 -0400

    Fix MC-268617 to allow valid filepaths in Minecraft (neoforged#767)

commit fe57823
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Fri May 10 12:02:54 2024 -0400

    Fire Villager/Wandering Trader trade events on /reload (neoforged#922)

commit d0ed10a
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Fri May 10 12:02:04 2024 -0400

    Remove Unnecessary Stitcher patch (neoforged#948)

commit a598489
Author: Matyrobbrt <65940752+Matyrobbrt@users.noreply.github.com>
Date:   Fri May 10 14:44:48 2024 +0300

    Bump Mixin to 0.13.4 to fix local variable issues (neoforged#945)

    Fixes neoforged#768

commit 212f760
Author: sciwhiz12 <arnoldnunag12@gmail.com>
Date:   Fri May 10 10:29:47 2024 +0800

    Fix dedicated server GUI never showing up (neoforged#946)

commit 238a273
Author: embeddedt <42941056+embeddedt@users.noreply.github.com>
Date:   Thu May 9 17:07:08 2024 -0400

    Add more accurate culling for single quad particles (neoforged#885)

commit 27c5d7a
Author: Brennan Ward <Bward7864@gmail.com>
Date:   Thu May 9 10:50:55 2024 -0700

    Fix FinalizeSpawnEvent for trial spawners and fix SpawnGroupData propagation (neoforged#880)

    Closes neoforged#783
    Closes neoforged#939

commit 989ed3b
Author: TelepathicGrunt <40846040+TelepathicGrunt@users.noreply.github.com>
Date:   Thu May 9 13:40:34 2024 -0400

    [1.20.6] Fix several NeoForge command crashes and allow chat OpenFile click action on Integrated Server  (neoforged#915)
@pupnewfster
Copy link
Member

Unsure about the name change from handlers to storage. Given there are lots of handlers that implementation wise act as proxies and may not actually store anything directly on themselves. I understand from the point of view of wanting things like FluidTank to be a storage, but from the actual exposed capability object... it feels like it should be a handler. As someone who does a lot of stuff in their mods with handlers, storage really doesn't feel like it fits as a name for the caps.

Copy link
Contributor

@Spinoscythe Spinoscythe left a comment

Choose a reason for hiding this comment

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

Not too sure about the name FluidStorageAttachment😬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.20.6 Targeted at Minecraft 1.20.6 breaking change Breaks binary compatibility enhancement New (or improvement to existing) feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants