-
Notifications
You must be signed in to change notification settings - Fork 435
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
Fabric Transfer API: "fluid only" edition #1356
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.
keys gooder and best, other than that I approve
...-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java
Show resolved
Hide resolved
...ic-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidStorage.java
Outdated
Show resolved
Hide resolved
Ok, I have added a base fluid storage that will be usable by most implementors. Multiple "slots" can be combined into a single I am also hosting builds of this module on my "maven" so that it's easier to try it out: https://github.com/Technici4n/Technici4n-maven. Again, any feedback is appreciated. Cheers! |
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.
All in all, I like it.
Most of my comments are smaller things I noticed, except the thread-safety one.
I only inspected the code visually, so I didn't do any testing or check the documentation, but I think I got a decent understanding of it and can approve of the general structure and implementation.
...nsfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidPreconditions.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java
Outdated
Show resolved
Hide resolved
...r-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/CombinedStorage.java
Outdated
Show resolved
Hide resolved
...r-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/CombinedStorage.java
Outdated
Show resolved
Hide resolved
...v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/ExtractionOnlyStorage.java
Outdated
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Outdated
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Outdated
Show resolved
Hide resolved
...c-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/CauldronWrapper.java
Outdated
Show resolved
Hide resolved
...sfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/transaction/TransactionImpl.java
Outdated
Show resolved
Hide resolved
...sfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/transaction/TransactionImpl.java
Outdated
Show resolved
Hide resolved
...c-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/CauldronWrapper.java
Outdated
Show resolved
Hide resolved
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.
Remove the locking, please. It's not sensible. Anyone experienced in Minecraft modding will back me up here that it's up to the modder to not concurrently access data from the client or server thread, and if they do, it's up to the modder, not Fabric API, to use locks.
Done. 😉 I also added an |
...-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java
Outdated
Show resolved
Hide resolved
...ansfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/Transaction.java
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Show resolved
Hide resolved
...-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/base/SingleFluidStorage.java
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Movement.java
Outdated
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Outdated
Show resolved
Hide resolved
...nsfer-api-v1/src/testmod/java/net/fabricmc/fabric/test/transfer/fluid/FluidTransferTest.java
Outdated
Show resolved
Hide resolved
Did another documentation pass - |
...er-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/ResourceAmount.java
Outdated
Show resolved
Hide resolved
Ok so I think this should target 1.17 and be experimental because it's a very complicated API addition. |
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java
Outdated
Show resolved
Hide resolved
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.
a few minor changes, however I would still like to see
- Iterator -> insert
- Snapshot -> Key (not that big a priority though)
...-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java
Show resolved
Hide resolved
...-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java
Show resolved
Hide resolved
...nsfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidPreconditions.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Movement.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/Storage.java
Outdated
Show resolved
Hide resolved
...c-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/StorageView.java
Outdated
Show resolved
Hide resolved
...r-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/CombinedStorage.java
Show resolved
Hide resolved
...ansfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/Transaction.java
Show resolved
Hide resolved
|
||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; | ||
|
||
public class TransactionManagerImpl { |
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.
a useful debug feature is to record the stacktrace from where the Transaction was created, if someone forgets to close their transaction, the exception can help narrow down who's responsible.
https://github.com/Astrarre/Astrarre/blob/4913a4cb9fa6e88183f31e5f2e5f77fb4f485bd4/astrarre-transfer-v0/src/main/java/io/github/astrarre/transfer/v0/api/transaction/Transaction.java#L38
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.
Hmmm acquiring the stacktrace is quite an expensive operation, I certainly don't want this to happen by default. The risk that someone forgets to close the transaction is abysmal assuming they are always used within a try
-with-resources block?
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.
Hmmm acquiring the stacktrace is quite an expensive operation, I certainly don't want this to happen by default.
ye atm I only do it in dev or with a system variable
...ansfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/Transaction.java
Outdated
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Outdated
Show resolved
Hide resolved
.../src/main/java/net/fabricmc/fabric/api/transfer/v1/transaction/base/SnapshotParticipant.java
Outdated
Show resolved
Hide resolved
...c-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/CauldronStorage.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/WorldLocation.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidKey.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidKey.java
Outdated
Show resolved
Hide resolved
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/FluidKeyImpl.java
Outdated
Show resolved
Hide resolved
Updated with fluid key rendering. I will test all the recent changes in production with Modern Industrialization today or tomorrow. 1.17 is coming in about a week, and I hope this PR can be in last call by then. If you have some time, I would appreciate a review. |
Typical use case would be something like: public class MachineBE extends BlockEntity {
private final SingleFluidStorage inputTank = new SingleFluidStorage() {
protected getCapacity() { ... }
protected canExtract() { return false; }
};
private final SingleFluidStorage outputTank = new SingleFluidStorage() {
protected getCapacity() { ... }
protected canInsert() { return false; }
};
private final Storage<FluidVariant> storage = new CombinedStorage<>(List.of(inputTank, outputTank));
} Need to access amount directly, and can't use insert or extract cause they are designed for pipes, and not for a machine's own use. |
And the same particpant multple times. This also doesn't work with something like simulate mode.
I am not, I am comparing them to JTA transactions, a different thing and closer to what you have.
Which again is my critique. Why not do? You have to override the class anyway to do the other policy changes.
The alternative for the paranoid like me is:
|
Hmmm? What exactly do you mean by simulate mode and side effects here?.
Ah ok, no clue what JTA is at all then, looks quite different though, but please keep suggesting stuff and we can go over it part by part.
Participants should not abort or commit a transaction. Only the user of the API who created the transaction is allowed to decide whether it is committed or aborted. That's why this information only makes sense in the close callbacks, to properly handle state updates.
Personally I dislike such boilerplate. I think your IDE can highlight uses of the public fields if you wish.
What exactly are you afraid of? |
Simulate mode is what forge does.
Side effects are when things happen outside the transaction.
The problem comes if you want to do multiple things including the above in a transaction but one fails. And before you say add a commit callback so it only gets done when the transaction commits. |
The old "a tool will solve the problem" excuse of api designers. :-) |
Ah, well simulate mode can be emulated by opening a new transaction and not committing it.
Well, that's precisely what transactions are intended to solve. You can't just have "things that transactions are there to fix, but please do it without transactions". At least that's how I see it. 😆
Fair. :-P |
Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> Co-authored-by: Player <player@player.to>
Updated with a separation between |
@warjort I haven't received an update from you, not sure if I managed to address your concerns? Or maybe you are just busy with something else. 😄 |
I think you largely ignored my concerns :-)
Incidently, I think the lack of concurrency will likely show up in "recursive" rather than real concurrent usage. |
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 weird stuff i guess, allowed me to look at the pr and I can't say enough how impressed I am with the javadocs, they are pretty big. amazing job
...r-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/StoragePreconditions.java
Show resolved
Hide resolved
...v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/ExtractionOnlyStorage.java
Show resolved
Hide resolved
...c-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/fluid/CauldronStorage.java
Show resolved
Hide resolved
I guess that's fair... I agree with your summary though. ^^
Good point, in that case a workaround would be to schedule an update for the next tick. I think that would be reasonable. :D |
Co-authored-by: frqnny <45723631+frqnny@users.noreply.github.com>
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidKey.java
Outdated
Show resolved
Hide resolved
* | ||
* <p>Implementation note: Fluids are saved using their raw registry integer id. | ||
*/ | ||
void toPacket(PacketByteBuf buf); |
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 was an old review comment, I forgot to add this probably weeks ago. Ignore it 😄
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.
Hmmm ok. 😄
I chose toPacket
to match fromPacket
, perhaps both could be changed to writeToPacket
and readFromPacket
?
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 I can change it but it won't match toNbt
and fromNbt
. In doubt, probably better to leave it as-is.
* | ||
* <p>Implementation note: Objects are saved using their raw registry integer id. | ||
*/ | ||
void toPacket(PacketByteBuf buf); |
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 doesn't match up with Yarn conventions about serialisation, might be worth changing to match (though definitely not a blocking issue for this PR)
* Original fluid API design * Rework the transaction system * First javadoc pass * Add a testmod, a base implementation for fluid storages and fix some little bugs * Fix checkstyle * Make Movement#move extract from the view and not the whole Storage * Document and update FluidPreconditions * Use for-each in CombinedStorage and document a little * Remove useless overrides in Insertion/ExtractionOnlyStorage * Move SnapshotParticipant#snapshots to the top of the class, and make updateSnapshots public * Fix garbage collection of unused CauldronWrappers * Use ArrayList directly * Remove locking, reorganize transaction implementation, and add outer close callback * Add more javadoc * Rework Storage#forEach into Storage#iterator * Add a few missing `transaction.addCloseCallback(iterator)` * Add anyView(), exactView(), capacity() and isEmpty() * Add Storage#iterable to make iteration friendlier to for loops * Storages may now have multiple open iterators Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> * Make CombinedStorage#supportsInsertion/Extraction iterate through the parts * Block updates should be used when the supportsInsertion/Extraction status changes * Fluid -> FluidKey * Remove all references to ItemKey inside FluidKey, and other minor tweaks * Cache FluidKeys with a null tag inside Fluid directly * Fluid unit convention * Add FluidKeyRendering and RenderHandler * Bump version for more testing (also published to my maven) * Add SingleViewIterator, massively reduce code duplication! * Make API experimental, and add README * Bump version * Apparently Fluids.EMPTY is flowing * Add package info * Minor adjustements * 1.17 port, cauldron support, add ResourceKey * Checkstyle, gas rendering, use record for ResourceAmount * Add a few helpers, rename some stuff * Remove anyView, allow nullable in StorageUtil#find*, fix missing try block * Slight findStoredResource cleanup * Slightly improve implementation * Bump version * Fix wrong transaction * I wrote in a comment that this could happen... * Fix SingleFluidStorage bugs, add tests in the testmod, add testmod assets * Add extract stick * Rename a few things * `ResourceKey<T>` -> `TransferKey<O>` * `ResourceKey#getResource()` -> `TransferKey#getObject()` as resource is already widely used through the API for the keys themselves. * `tag` -> `nbt` * Add `get` prefixes to `StorageView` functions * Bump version * FluidKey -> FluidVariant * Bump version * Expand getVersion() documentation, make it thread-safe and use long. Co-authored-by: Player <player@player.to> * empty resource -> blank resource, and update SingleFluidStorage Co-authored-by: Player <player@player.to> * Make CauldronFluidContent a final class instead of a record. Co-authored-by: Player <player@player.to> * Get rid of CauldronFluidContent#minLevel (was always 1) * Fix nested commits. (Thanks @warjort!) * Separate Transaction and TransactionContext Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> Co-authored-by: Player <player@player.to> * Change WorldLocation into a private record * Bump version * Guard against exceptions thrown in close callbacks * Make sure blank fluid variants don't have a tag * Add documentation, make CauldronStorage clearer Co-authored-by: frqnny <45723631+frqnny@users.noreply.github.com> * Allow null storages in StorageUtil#move, and clarify sidedness of FluidStorage * Add explicit hashCode and equals for transfer variants * Remove ugly equals and hashCode overrides, and add constant time hashcode spec Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> Co-authored-by: liach <liach@users.noreply.github.com> Co-authored-by: Player <player@player.to> Co-authored-by: frqnny <45723631+frqnny@users.noreply.github.com> (cherry picked from commit c09be4c)
* Original fluid API design * Rework the transaction system * First javadoc pass * Add a testmod, a base implementation for fluid storages and fix some little bugs * Fix checkstyle * Make Movement#move extract from the view and not the whole Storage * Document and update FluidPreconditions * Use for-each in CombinedStorage and document a little * Remove useless overrides in Insertion/ExtractionOnlyStorage * Move SnapshotParticipant#snapshots to the top of the class, and make updateSnapshots public * Fix garbage collection of unused CauldronWrappers * Use ArrayList directly * Remove locking, reorganize transaction implementation, and add outer close callback * Add more javadoc * Rework Storage#forEach into Storage#iterator * Add a few missing `transaction.addCloseCallback(iterator)` * Add anyView(), exactView(), capacity() and isEmpty() * Add Storage#iterable to make iteration friendlier to for loops * Storages may now have multiple open iterators Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> * Make CombinedStorage#supportsInsertion/Extraction iterate through the parts * Block updates should be used when the supportsInsertion/Extraction status changes * Fluid -> FluidKey * Remove all references to ItemKey inside FluidKey, and other minor tweaks * Cache FluidKeys with a null tag inside Fluid directly * Fluid unit convention * Add FluidKeyRendering and RenderHandler * Bump version for more testing (also published to my maven) * Add SingleViewIterator, massively reduce code duplication! * Make API experimental, and add README * Bump version * Apparently Fluids.EMPTY is flowing * Add package info * Minor adjustements * 1.17 port, cauldron support, add ResourceKey * Checkstyle, gas rendering, use record for ResourceAmount * Add a few helpers, rename some stuff * Remove anyView, allow nullable in StorageUtil#find*, fix missing try block * Slight findStoredResource cleanup * Slightly improve implementation * Bump version * Fix wrong transaction * I wrote in a comment that this could happen... * Fix SingleFluidStorage bugs, add tests in the testmod, add testmod assets * Add extract stick * Rename a few things * `ResourceKey<T>` -> `TransferKey<O>` * `ResourceKey#getResource()` -> `TransferKey#getObject()` as resource is already widely used through the API for the keys themselves. * `tag` -> `nbt` * Add `get` prefixes to `StorageView` functions * Bump version * FluidKey -> FluidVariant * Bump version * Expand getVersion() documentation, make it thread-safe and use long. Co-authored-by: Player <player@player.to> * empty resource -> blank resource, and update SingleFluidStorage Co-authored-by: Player <player@player.to> * Make CauldronFluidContent a final class instead of a record. Co-authored-by: Player <player@player.to> * Get rid of CauldronFluidContent#minLevel (was always 1) * Fix nested commits. (Thanks @warjort!) * Separate Transaction and TransactionContext Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> Co-authored-by: Player <player@player.to> * Change WorldLocation into a private record * Bump version * Guard against exceptions thrown in close callbacks * Make sure blank fluid variants don't have a tag * Add documentation, make CauldronStorage clearer Co-authored-by: frqnny <45723631+frqnny@users.noreply.github.com> * Allow null storages in StorageUtil#move, and clarify sidedness of FluidStorage * Add explicit hashCode and equals for transfer variants * Remove ugly equals and hashCode overrides, and add constant time hashcode spec Co-authored-by: Devan-Kerman <dev.sel20@gmail.com> Co-authored-by: liach <liach@users.noreply.github.com> Co-authored-by: Player <player@player.to> Co-authored-by: frqnny <45723631+frqnny@users.noreply.github.com>
Fabric Transfer API: "fluid only" edition
Building on #1234, this PR adds a new
fabric-transfer-api-v1
for transfer of generic game resources, and uses it to define a "Fluid API" for blocks.This PR replaces #1278 that I deemed too big to be implemented and reviewed properly. Let's go for quality above quantity.
I am also hosting builds of this module on my "maven" so that it's easier to try it out: https://github.com/Technici4n/Technici4n-maven. Please give it a try, any feedback is appreciated!
Problem scope
This PR is centered around fluid transfer between blocks: Reading fluids stored in a block, extracting fluids from a block and inserting fluids into a block.
Contrarily to #1278, this PR does NOT cover:
I will talk about these things a bit later.
API overview
Transactions
This PR introduces the transaction concept. Essentially, a transaction allows setting checkpoints like in a video game: if something doesn't go as expected, the state of the game reverts to what it was at the previous checkpoint. Game objects that take part in a transaction are commonly referred to as "participants" or "endpoints".
Here is an example that hopefully makes this clearer:
Transaction aborting or committing is done by registering a callback with
Transaction#addCloseCallback
. This gives full freedom to participants to manage their state the way they want to. In practice, this is very low-level and participants that wish to save their state before modification so that changes can be reverted when a transaction is aborted can subclassSnapshotParticipant
and callupdateSnapshots
right before mutating their internal state. That way, modifications will be cancelled by applying a previously saved state if necessary. Uncancellable modifications such asmarkDirty()
or neighbor block updates should be deferred untilonFinalCommit
.More details can be found in the Transaction javadoc, and I will be happy to answer any question.
Storage
Building on the transaction concept, this PR introduces
Storage<T>
: an interface that containers of game resources of typeT
can implement.The rest of the
storage
package provides related base implementations and helpers.As an example of how this API works, have a look at the generic
StorageUtil#move
function that moves game resources between two storages.Storage<FluidVariant>
This API then defines an API lookup for
Storage<FluidVariant>
so that mods can start using this API for fluid transfer right away.Cauldron compatibility for water is builtin. That and fluid constant definitions and a few preconditons can be found in the
fluid
package.It is expected that most modders will use subclasses of
SingleFluidStorage
to implement their containers in most cases. These subclasses can be combined usingCombinedStorage
for fluid inventories that have multiple "tanks"/"slots".What exactly is a
FluidVariant
? It is the immutable combination of aFluid
and an optional NBT tag, the methods should be quite straightforward. Client-side fluid variant rendering is also provided by this PR.Cauldron support
Empty, water and lava cauldrons are supported. Mods can register mappings for other vanilla cauldrons, or for their own cauldrons. Mappings can be inspected. For example, a mod adding a powder snow fluid would first check for an existing mapping for the powder snow cauldron, before trying to register its own fluid. More details in
CauldronFluidContent
.The fluid unit
Fluid transfer happens in discrete amounts: 1/81000s of a bucket. There have been attempts to allow per-call denominators (a denominator for every function call) or fractions. Unfortunately, none of those have proven to be practical.
Essentially we are left with the choice of a denominator. 81000 is divisible by all the relevant numbers and can be easily expressed as millibuckets with a slight rounding error (possibly displayed only when shifting) - how the fluid amounts are displayed to the end user is not specified by this API. This API however provides a name for 1/81000 of a bucket: a droplet.
What about future-proofing or other denominator choices? Well, thanks to fallback providers that can be registered with API Lookups, we can provide an easy migration path if this choice of denominator proves to be wrong at some point in the future. In general, anyone can define their
Storage<FluidVariant>
lookup and register the suitable fallback providers atFluidTransfer.SIDED
. The only place where the unit is encoded is with the cauldron compatibility, and the various constants inFluidConstants
.Unsided fluid transfer
Not all fluid transfer is sided. However, most of it is. That's why the API uses a non-null
Direction
context. Another lookup that would be unsided may be introduced in the future if it turns out to be useful. Note that 3rd-party mods can all refer to aBlockApiLookup<Storage<FluidVariant>, Void>
with a common agreed-upon ID, andBlockApiLookup#get
will return the same instance for every query with that ID.The future
Item Transfer
In a subsequent PR, immutable count-less item stacks called
ItemVariant
are to be introduced, similar toFluidVariant
s. They are not included in this PR because providing aStorage<ItemVariant>
implementation that wrapsInventory
,SidedInventory
andPlayerInventory
adds a lot of implementation, and I would like reviews to focus on the generic API for this PR.Do however keep in mind that
Storage<T>
can only work with immutable resource typesT
. This means thatStorage<ItemStack>
is not an option, and that must be considered before this PR is merged! I believe that usingItemVariant
s makes the API much less error-prone: inventory contents cannot be mutated, and there is no risk that someone forgets to copy a stack somewhere, leading to duplication or voiding bugs.Fluid-containing items
Once #1352 is merged, we can look into providing an
ItemApiLookup
for access toStorage<FluidVariant>
instances. There will be two challenges here: designing a context typeC
that is suitable for all kinds of inventories that may store fluid-containing items, and providing ad-hoc helpers to allow multiple mods to register fluid empty/fill actions for the same item (so that for example mod A could add a honey fluid to fill honey bottles and mod B could add a milk fluid and milk bottles - while allowing bottles to be filled with either fluid). I do however not expect that to be an issue.