The Fluid API discussion issue
i509VCB opened this issue ยท 7 comments
This is an issue for discussing the fluid transfer api. Welcome here is discussion on implementation, api, documentation and use cases for this api. This is also loosely related to an item transfer api and the framework of an energy api (fabric api will not provide one explicitly). Discussion here should be on topic. If discussion is disorderly or misconduct is found this issue will be closed and locked to collaborators.
What will Fabric API not do:
Redefine cauldrons to be 4 bottles.
Game breaking changes
Design an api which completely prohibits alternative implementations from existing.
While I do agree that the idea of 1 bucket = 1000L is a good idea, I have my concerns over smaller amounts, and mods that may require more precision.
As a few mods have already shown in the past, Fractions are a very clear method of using fluids. Not only does it not limit you to the minimum of 1 Liter (and 1000L being 1/1), it also allows for more creative usage for e.g. chemistry mods. Also, instead of using millibuckets or storage units, we can use the real-world Liters instead.
As for Fractions, many may be against it due to it being counterintuitive or issues with displaying. For the first part, I'd like to let you think about how half a liter or a third of a liter is still easy to understand, though the issue can indeed arise where a value may be e.g. 999967/999980
. This is where the display issues come in. Mod devs can choose to display either the fraction as a whole (which I recommend against), or they can choose to round to N digits, and display that value.
This makes it so that for most machines, it will stay close to the minimum being e.g. 10 liters (depending on what they choose), whereas chemistry mods can use the full fractions or up to a certain significant amount of digits.
If this system were to be chosen, ideally the transfer system would include a method for a fluid container BE to give its preferred minimum value (e.g. 1/100 for multiples of 10L, 1/10 for multiples of 100L, 0 for any).
Imo fractions should be avoided because they are annoying to work with in Java, there are underflow/overflow issues with pipe systems, and most importantly current mods don't have a use for it. Regarding the classic We want to allow different design decisions in the future, I'll let you know that currently millibuckets are the only solution that is kinda of correctly supported in the ecosystem, and current mod developers will most likely not accept fractions, including me.
Speaking of said ecosystem, the current compatibility is not great, as for example Tech Reborn machines don't seem to see LBA fluid inventories, and AE2 fluid interfaces void anything smaller than millibuckets, just to name a few. My point is that not doing anything will be worse than accepting fixed denominators.
To solve the bottle/ingot/nugget problem, I think 81000 is the best solution because it can be displayed as x+y/81 mb. We are currently experimenting with that idea on FastTransferLib (https://github.com/Technici4n/FastTransferLib). We have experimented with per-container denominators, but it's just too hard to work with correctly (what is the denominator for cauldrons? 1? 3? depends on the fluid...), and doesn't bring a lot of benefits in practice.
Regarding API access itself (as a replacement for e.g. LBA attributes or Forge caps), I will PR something this week...
'current mod developers will most likely not accept fractions' - I've already adopted fractions in my mod. Granted, not for representing an amount of fluid exactly (though I probably will, before this mod is complete), but for representing the amount of a substance inside of a liquid. Initially, I used doubles, but the rounding issues became an issue immediately, and I didn't want to use a magic constant as a unit, so I tried Fractions out, and lo and behold, it was almost painless to implement and quite easy to use. After using fractions for a couple hours my opinion switched from "Fractions would be a terrible way to represent fluids" to "this should be the default"; I recommend trying them yourself.
I have a prototype for a transfer api PR that will allow working with fractions if really necessary, but I am making the assumption that most mods will want to use some fixed denominator, and the api I am writing will not enforce a particular one. Come have a chat on #fluid-volume-api-debating on Fabricord if you want, it will be much more interactive than this issue.
We should use the next six months of snapshots to experiment with all our options, and see what works best in production.
I will give a start on this. I have read a lot of discussions on the fluid volume debate, this debate will be really not necessary if Vanilla sets up a 1 Bucket = 4 Bottle / 8 Bottle / 10 Bottle standard... but anyway.
I hope we can discuss this proposal.
Volume API
1000MB
I personally think we should just stick with the old way Forge did: 1 Bucket = 1000 Liter.
First and above all, A 1000 Liter (milibucket) = 1 Bucket system is easy for normal players to memorize and understand since it uses a standard used in normal life (1000L = 1m^3). It is not counter-intuitive for a normal player!
Secondly, I am not saying we should just clone what Forge did but I would say a similar fashion fluid volume api with essential functions that don't compel with the above listed three things Fabric API won't do is a good choice. Also, I believe it would ease people porting mods from older version of Minecraft or Forge. They don't have to worry about refactoring their fluid system entirely and can save a lot of time. Yes you can say porting from older version to either modern (1.14+) Forge or Fabric is nearly a rewrite, but it could save some time at least. It could also invite people who originally worked in Forge ecosystem to join Fabric.
An Issue I want to address
There is one issue with this, and a long-discussed one, which is the 3 bottles = 1 cauldron equivalence set up by Vanilla that makes one Bottle = 333.3... Liter. I suggest Fabric API to not provide a default implementation of any kind for the bottle system. This can enable others who like to use the bottle system to create their own API.
Personally, I, as a developer who develops tech mods mostly, don't consider the cauldron to be an extremely important thing in the game. Indeed, I would probably choose a 1 Bucket standard for all my fluids instead of a 1 Bottle standard. I know there are people who likes the 1 Bottle standard. But, this freedom can be well-preserved in any case, since people can choose to create new alternatives for implementing the bottle system. And according to my view, most mods are are eager to add more fluids are looking forward to use a 1 Bucket system.
We are modding API, we respect the Vanilla way but we shouldn't prevent from creating a standard. Vanilla don't have a lot of fluids! WE should start this API to let mods to create their own liked system, whatever is MY_BOTTLE = 100MB or 250MB. We don't need to follow the quite not clever Vanilla standard. We just have to allow Vanilla bottle to exist. The importance is to make the transfer API so that mods start to get compatibility without a 3-rd party mod.
Recall what I said in the first point and second point. We don't need to be perfect, but we need is an Fluid API is an important interoperation that deserves implementation for Fabric to grow strong and powerful at this very moment of 1.17 development cycle.
81000SU
Another alternative I saw in Fabricord is the 81000SU = 1 Bucket System. I consider it as a second-best choice:
su: Storage Units
mb: Mili-Bucket
- We display as su / 81 to create 1000mb / bucket
- Water bottles and potions = 27000su = 1/3 bucket
- 1 Honey Bottle = 20250su = 250mb
- 1 Molten Ingot = 9000su
- 1 Molten Nugget = 1000su
We store data as SU, but MB is the unit that develops and players use. SU prevents from rounding errors such as bottle to buckets in cauldron.
The problem I saw in this: molten nuggets and blocks cannot be displayed in integers.
Transfer API
Use Cases
-
Store Fluids in Blocks, Items, BlockEntities (And Entities, World, so on, but they are not priority).
-
Display Fluid amount in a GUI that uses Mb or Bucket as unit.
-
Insert fluid from one fluid container object to another.
-
Extract fluid from one fluid container object to another.
-
Methods to get the Fluid itself, number of types of fluids in a fluid container object, the volume, and whether it is empty or not.
Example Scenario
You want to create a BlockEntity called Advanced Furnace that intakes Lava to proceed normal Furnace recipes and output Liquid Experience while finishing a recipe. The Advanced Furnace has to:
- Store Lava and Liquid Experience in itself.
- Be able to display how much Mb or Bucket of Lava and Liquid Experience are inside the Advanced Furnace GUI.
- Be able to use a fluid container object from another mod (such as a fluid funnel block entity) to extract the Liquid Experience inside it.
- Be able to use a fluid container object from another mod (such as a fluid funnel block entity) to insert Lava into it.
Closed by #1356.