LibBlockAttributes icon indicating copy to clipboard operation
LibBlockAttributes copied to clipboard

Deprecate (and eventually remove) fractions, and move to fixed-integer for fluid amounts

Open AlexIIL opened this issue 2 years ago • 0 comments

First of all, fractions have some distinct advantages: they can handle any denominator (although not every combination at once) and I'm somewhat sad to see them go. All advantages / disadvantages being compared here should only affect developers though (and potentially pack developers or recipe writers, since fluid amounts can be parsed from json files).

However they have some pretty big drawbacks that make them much, much worse than fixed-integer denominators:

  • They require devs to think about the unlikely situation where adding two fractions might overflow.
  • Since Java doesn't have operator overloading devs need to use methods to perform basic arithmetic, which is painful.
  • Any operation that isn't directly provided by the FluidAmount class needs to be written manually, which can be fairly complicated since it's mixed fractions (whole + numerator / denominator).

LBA will most likely move to 81000 as the new fixed denominator, in line with fabric's transfer API. (This isn't a certainty though). LBA will also use long as it's base type rather than int, since 81000 (or 81k) only permits a maximum fluid tank size of 26,000 buckets - less than normal amount of oil in a single buildcraft oil well! Some of the maths below assume using 81k though, so they'd need to be reconsidered if LBA doesn't end up with 81k. The main consideration for a denominator is that it needs to be divisible by 81 (as there's 81 nuggets of gold per block), and it shouldn't be too big (since players will actually have to think about 1/<unit> buckets of fluid).

To make the transition a bit easier I'll be sticking to my usual "keep backwards compatibility for long periods of time" ideal, to give lots of time for mods to move away from fractions. However, some parts will be kept around forever:

  • Parsing fractions as fluid amounts. Fractions that don't use the same base (or a divisor of the real base) will result in rounding (likely up). Fluid amount parsing utilities in LBA will continue to parse fluid amounts in buckets, so "amount": "1" would result in an amount of 1 bucket (81000 base units), not 1 base unit (or 1/81000, or ~0.0000123 buckets
  • Reading fractions as amounts from NBT. (Like how LBA still supports reading 1620-based fluid amounts), since there's no reason to ever remove this. (FluidVolume currently saves 1620-based values as Amount, fraction based amounts as AmountF, and 81k will probably be saved as Amount81k)

As for display:

  • LBA will continue to display fluid amounts as decimal, at least by default. This will use exactly 0, 3, or 6 digits of precision depending on whether the amount of fluid divides evenly by 81000, 81, or 1. For example 1.670 Buckets for 135270 or 1.670099 for 135278
  • LBA will gain a config option (set by the user) to instead display with 3 digits of precision and display the fraction at the end, similar to fabric's transfer API. (For example 1.670 + ⁸/₈₁ Buckets for 135278). I might add a config option to not use super/subscripts though, and instead just display 8/81 instead. Note that display only matters where devs use LBA's classes and methods for tooltips - like FluidUnit or FluidUnitSet, or methods that call it like FluidVolume.addTooltipNameAmount.

AlexIIL avatar Mar 30 '22 11:03 AlexIIL