#Fluid Unit Hell

3412 messages · Page 4 of 4 (latest)

astral stag
#

I'm aware of the issues with the use of millibuckets but we have to deal with them for now. No proposal that keeps mb will solve that problem. Bringing it up again is pointless.

pure lynx
#

if you dont need the api thats fine, the rest of us think its useful and it doesnt harm you in any way, so let us implement it

vernal bane
#

I do not

deep hamlet
#

No, I don't interact with any arbitrary fluid unless a pack maker also defines it via datapack (which also requires a melting temperature, specific heat capacity, etc.) So the fact a common tag exists doesn't help.

fluid mortar
#

alright, so for your case at most a tag that is "molten iron at the 100mb standard" would be useful

#

I think thats probably the simpliest way to handle these standards, have prefixes that mean "100mb", "90mb" and "250mb" for the common standards (and 144mb if people insist on reviving the bad legacy standard). Then you just use the appropitate prefix for what you do

#

We could do that alongside the tooltip, and people wishing to do conversions between standards just use multiple tags

#

Only awkward part here is coming up with names for each standard. I've been calling 90mb "metals", which is a bit weird if you apply it to redstone for instance but not the worst thing

#

I tossed in a section about unit standard tags to the fluid tooltip proposal, a fluid constant PR could reference those tag prefixes for relevant constants (e.g. INGOT would mention "tag fluids using this unit under c:metals/<fluid name>")

solemn sand
#

It means that you don't need to worry about an ingot "standard" size that's divisible by whatever people want -- you can just have each person set that themselves

#

And in the long run -- looking at versions further down the road -- it could solve the millibucket issue too

fluid mortar
#

yeah, its really just a question of how we want to solve this

#

everything the fluid unit API proposes apart from tooltip formatting could be done via other methods (tag conventions and mod added datamaps), however it is a lot more streamlined and potentially eaiser for pack devs to work with

#

I personally am not too partial to either approach, as long as we make no changes to the bucket divisions before we get some unit display in Neo

#

With either approach we can change the bucket divisions with minimal impact on players

pure lynx
fluid mortar
#

that is true, its easier to not have to special case each standard

#

it all comes down to how much do we expect conflicting standards to occur?

#

if its just 1 or 2 standards for a thing, its not a huge deal

#

if its regularly 2-4 standads, that becomes a pretty big maintenance burden on the modders side

#

The standard tags are arguably useful whether the unit API is added or not, since they grant a quick and easy way to detect fluids of a particular standard, though I'd call them non-essential with the unit API

#

without the unit API they are also arguably non-essential, though given we have some conflicting standards already its probably better to have them than not

pure lynx
#

I think so far we have 3 reasonable standards, 90 mb, 100 mb, and 144 mb

kind stratus
#

we don't have to have a completely separate set of tags for the standards

#

like, we could have recipes that are based on the intersection of c:molten_iron and c:ingot_is_90 [if we don't have intersection holdersets, or holderset-based ingredients, we should]

fluid mortar
#

250mb is the third reasonable standard

#

its mainly used for non-metals

fluid mortar
#

Neo should have intersection fluid ingredients if it does not already

pure lynx
#

it does as of a few weeks ago

fluid mortar
#

perfect, that solves that

#

Tag standard proposal:

  • c:metals/<name> or c:gems/<name> would be the standard place for metals and gems alike. What qualfies as either is the same semantics as using the item tags c:ingots/ and c:gems/ respectively
  • Not sure what to do with weird fluids like redstone or clay that are neither, probably just tag under root c:redstone or c:clay, though a generic c:molten/<name> might be an option
  • For units, we use c:units/<number> where <number> is the size of the most standard. e.g. the Tinkers ingot standard would use c:units/90, and the gem standard is under c:units/100
  • May be worth retroactively applying this standard to existing Neo fluid tags, e.g. c:honey and c:potion would typically use c:units/250 but you could if you wish use another standard.
#

This solves the problem of conflicting units by just telling people to publically expose which standard they are using in a way other mods can query

#

Not sure if the c:units/ proposal should be mutually exclusive with the unit API proposal. I think its probably still beneficial if that API exists as you may have a context where tags are way easier than querying the unit API

pure lynx
#

is c:units/90 just assumed nugget, thing, and block being 10, 90, 810?

fluid mortar
#

there is an assumption here the standard is named after the ingot, not the nugget

#

and since nugget/ingot/block is 1/9/81, you just multiply/divide the fluid unit as needed

#

non-9 ingots will break as much here as they will in item tags

#

plus, if you are using non-9, you probably don't need the 90mb standard, 4 is way better in the 250mb standard

pure lynx
#

maybe it should be

c:unit/ninth-ninth 10 : 90 : 810
c:unit/ninth-quarter 25 : 100 : 900
c:unit/quarter 250 : 1000
c:unit/third 333 : 1000 ? this one might just be unsupported for now

solemn sand
solemn sand
#

...though honestly I don't think people should be designing recipes that way to begin with. Like, your recipe shouldn't care that a fluid has 90-ingots

#

You should only care that that fluid has, say, an ingot unit and a nugget unit (and the one is 9 times the other)

pure lynx
#

it would be better yes

solemn sand
#

In what scenario do you actually need to know that it's a 90-ingot-fluid?

#

And how can we design an ingredient type that lets you represent that actual condition (fluid with ingot and nugget units) instead?

#

Could we have the c:ingot unit somehow define an implicit c:unit/has_ingot tag on the fluid or something?

#

And then "fluids with ingots and nuggets" is just a tag intersection

#

I'd have to think about hte practical end of that a bit more

pure lynx
#

oh, well no, recipes still need to take in a specific liquid in order to get an outcome generally speaking

#

very rare that you need a recipe that takes all ingots

#

the recipe could take in a tag and then filter out all the fluids in the tag that dont have the particular unit

solemn sand
#

Sure, guess I'm saying I don't really see the advantage of a ingot_90 tag. I'd argue we should be encouraging people not to rely on how "big" a given unit is for a given fluid, or hardcode stuff to only work on a certain unit size. People should instead only care which units something has (and that the ratios work as the mod expects I suppose)

solemn sand
#

I want molten copper, but only if its molten copper with an ingot unit

#

etc

pure lynx
#

i think the idea would be to use an intersection tag for that. All fluids that are both molten_iron and ingot_90, which the current fluid ingredient system supports

solemn sand
#

If you're filtering only fluids where a unit is equal to a certain value, and you have the fluid unit API available, you're doing something wrong imo

pure lynx
#

agreed. honestly the tag stuff does seem very annoying and i dont really plan on using it for anywhere other than just writing the 1 json it takes to tell mods its in that tag

#

fluid units are more ergonomic in basically every way but people are convinced that we dont need them, not really sure what else to say on that front :/

solemn sand
#

I don't know that people are convinced on that

#

Some people sure but I've also seen a lot of interest for it in this thread

#

Heck, I wasn't fully in favor to begin with but I think I've come around since. Just seems like the cleanest long-term solution

pure lynx
#

yeah, i guess the question is if this PR got created what would the maintainers do with it. cuz tech is still convinced we dont need it. but shadows seems to be good with it. I think the only real concern is that the existence of this system would disincentivize people from using the tag standards

solemn sand
#

Someone should make the PR as a draft at least just so there's something solid to work with

solemn sand
#

Cause then you encourage people to filter things based on a units value... which you really want people not to do

#

That said, c:units/ingot tag -- for fluids with an c:ingot unit definition (of any value) -- isn't a bad idea

#

The question is, is it possible to make such a tag automagically contain any fluids that have the c:ingot unit?

pure lynx
#

there is merit to having both imo. if you only want to work with things in 1 specific standard the tag is nice. the unit system currently doesnt really allow that. actually i guess you could do something like fluid.getUnit("ingot") == 90

solemn sand
# pure lynx there is merit to having both imo. if you only want to work with things in 1 spe...

My point is nobody should only ever want to work with things in 1 specific standard. Like, what's a case where you'd actually want that, when what you want isn't instead something about having a specific set of units and ratios between them? Saying "I want only fluids with with 90 units per ingot" is really an XY problem -- nobody ever wants that really, they want fluids where they can do certain unit conversions and have them work out, or grab fluid in certain unit sizes, or have certain guarantees about ratios of unit sizes or whatever.

#

Like, why would you want an ingot_90? Maybe it's that you want:

  • ingot unit exists
  • nugget unit exists
  • 9 nuggets to an ingot
  • bucket to be divisible by nugget
    And you should be checking that set of conditions instead, not just saying "I want things where ingot is 90"
#

Because you don't really want things where ingot is 90, you want those other conditions because something you're doing relies on those assumptions. A fluid where ingot was 180 would still work just as well in your system in that scenario, for instance.

#

So the question is: how do we design a fluid unit API that makes checking those conditions -- ideally from an ingredient or holderset thingy -- easy? Because that's the sort of stuff people actually need, not ingot_90 fluids

#

Custom holderset type maybe?

pure lynx
#

(currently looking up what the hell a holderset type is)

#

forge has custom holder sets?

solemn sand
#

I think you could extend such a system with some sort of "fluid unit holder set" for filtering, say, all fluids with a given unit defined or something? Haven't poked the system enough, could be wrong

pure lynx
#

no idea, i also need to take a look at this

#

i have not been in the "neo exclusive" game for very long lol. i have never really taken a hard look at neo's apis until like a month or 2 ago

solemn sand
#

Regardless, I think that sort of solution is the proper approach here if its possible -- having tags for different standards or whatever just, like, bakes in those standards -- when in the long run I think we should be getting rid of a lot of those standards, and in the long run hoping to make even the size of the bucket unit fluid-specific

#

This solution solves all the problems those standards are needed to solve, without the sort of limitations that they drag with them

fluid mortar
#

the reason why you need ot know the standard is one of two reasons

#

either a: you want to know for divisibility sake or b: you want to know how much fluid is needed for a recipe

#

both are handled by a unit API of course

#

so I think based on this discussion, I'll conclude the tag standards are only needed if we don't do a unit API

#

and tbh, maybe they are what we need to convince people a unit API is good, because otherwise they will have to do that nonsense 🙂

kind stratus
#

if we're gonna have units tags, they should probably say ingot, gem, bottle [though again that raises the question of what a unit of redstone is]

#

also, is a tag that's just a number legal?

kind stratus
#

anyway, if we have a unit quantity based ingredient it can simply not match fluids that don't have the unit, if we want to check it in code we could add a .hasUnit helper method to Fluid and/or FluidStack

pure lynx
#

or fluid resouce hehehehe

solemn sand
#

Then there's no magical tag generation

#

But yeah, regardless -- I'd just avoid the tags for units

#

Either they're redundant and a source of error (if the tag is just the same as checking if the fluid has the unit) or they include numbers which we should avoid, as you shouldn't be reasoning/filtering based off of a unit number (and a unit API would mean you don't need to)

kind stratus
#

there is maybe something to be said for something like "is it divisible by 4, recipe quantity is 3/4 unit" but that's niche enough that it can probably be left to whoever needs it

solemn sand
kind stratus
#

[i have been tempted to suggest a floating point unit quantity, but i don't actually think it's a good idea, and honestly it should really be rational, that's just ugly to try to implement in json]

fluid mortar
#

floating point has terrible percision at the points we are trying to get by changing bucket standards

#

thta is, 3, 9, 81, etc.

#

they only wnat powers of 2 for precise values

grizzled tulip
#

floating point precision has a much bigger issue than rounding: digits of precision.
float has 6-7 digits. that means you can't have a tank with 100 million buckets because if you extract one bucket at a time you would either lose additional fluid (if it rounds up) or duplicate fluid (if it rounds down)

kind stratus
compact lynx
#

https://factorio.com/blog/post/fff-416

Friday Facts #416 - Fluids 2.0

Hello,
Grab your best lube, because it's time to talk about fluids!

During one of the fluids discussions, Rseding proposed an algorithm very close to one he had played with several times, an algorithm from the Minecraft mod Thermal Expansion by team CoFH:

how topical kekw

weak blade
outer spade
#

obvious issue when gamers have different opinions how realistic a game should be^^... and minecraft is as far away as you can get while some mods try to relive the real world industrialisation kek

still iris
#

that's fun lol

desert folio
#

oh god I missed this sidebar somehow

#

how many other terrible ideas are brewing that I'm unaware of

echo lily
#

5, if I'm counting correctly kek

prisma skiff
#

well I have 4 extra ideas....

#

but those are for only a few to know

fluid mortar
#

Either purely for rendering fluid units in tooltips (similar to what tinkers does ) or extending the idea to work with logical fluid units

#

Logical fluid units means you could for instance make an item that holds 1 ingot, but 1 ingot may have different mb on different fluids

#

Or make an ingredient that matches 1 gem and not care whether a gem is 100mb or 90mb for that fluid

#

I think it's not worth changing the bucket capacity without at minimum having a fluid unit display API, so I've been in pushing for that being done before we further bikeshed the bucket divisions

#

There is more info in the pins if you want

compact lynx
#

hello fluid folks
just an FYI that I've made a comment on https://github.com/neoforged/NeoForge/pull/1138 (Define standard FluidConstants) proposing that PR to go forward if this discussion leads to nowhere concrete -- an issue or PR, as I've somewhat alluded to in my pinned message
just so we have something in place to discuss concretely

pure lynx
#

alright. well honestly i dont really know where we stand on this issue

#

i understand there was still some aprehension from tech, and orion insists on a PR being written before he can decide. idk where everyone else is on this

kind stratus
#

i'm not sure i understand what the blocker is - is it just that there's not a PR, or are there still serious objections to the proposal

drifting wraith
#

a PR might be needed to actually arrive at some definite conclusion, it looks like.

kind stratus
#

i'm tired of looking at or thinking about openblocks for a while, i might put together a PR

compact lynx
#

the phrase "out of the frying pan and into the fire" comes into mind /jk

tawdry wolf
#

aiui a PR is being requested for further discussion

#

But even if no PR arises, I don't think that #1138 should be merged, it will introduce more problems than it fixes.

kind stratus
#

ok i think i might have some code ready to PR, though I didn't do any ingredient stuff [i don't think we have fluid ingredient stuff at all yet do we?]

#

i do not have a good way to test this though, there's nothing in vanilla or neoforge itself that actually uses fluid stacks

pure lynx
#

the fluid ingredient PR was merged a while ago

kind stratus
#

ah... maybe i should have pulled before starting work on this

#

ok how do i make a codec that does this "maybe a list or object, maybe just an integer" stuff

tawdry wolf
#

should be an either codec?

kind stratus
#

how does that work

#

what i want is a codec for a single type with two json representations, not a codec that can represent two types of object

#

maybe i should just make a straightforward codec and let it be ugly, [[{"unit": "mb", "amount", 10}]] isn't that bad.

tawdry wolf
#

aiui what you want is a codec that allows both

10
```and
```json
{
  "amount": 10,
  "unit": "mb"
}
```Is that correct?
kind stratus
#

technically i want all of 10, {"amount": 10, "unit": "mb"}, [{"amount": 10, "unit": "mb"}], and [[{"amount": 10, "unit": "mb"}]]

echo lily
#

conecern why double list?

tawdry wolf
#

yeah, what are the lists doing there?

kind stratus
#

the inner lists are sums, the outer list is alternatives

#

so e.g. you can have "2 ingots and 1 nugget, or 2 gems"

tawdry wolf
#

please for the love of god, make that "fluid_any_of" and "fluid_all_of" (or similar naming)

#

as separate ingredient types

#

(I'm assuming this is about fluid unit ingredients)

kind stratus
#

ok it still at least needs the sum list for like "1 ingot and 3 nuggets", that's a single quantity

tawdry wolf
#

okay, a codec that is either a single element or a list thereof is pretty simple, hold on

echo lily
#

Codec.either(Thing.CODEC, Thing.CODEC.listOf())

#

and wrap that in another either if you want the single int too

kind stratus
#

how do i map that to "the single thing becomes a list of a single element at runtime" though?

echo lily
#

.xmap(either -> either.map(List::of, Function.identity()), Either::right)

kind stratus
#

do i just have to do it by hand with xmap

tawdry wolf
#

there's Codec.withAlternative(), which is just a wrapper over xmap

#

but otherwise, yeah what Platin suggested

echo lily
#

yeah ok, that would make it a bit nicer, since it would just be Codec.withAlternative(Thing.CODEC.listOf(), Thing.CODEC, List::of)

tawdry wolf
#

yeah

#

I also find that a bit nicer to read: "expect Thing.CODEC.listOf(), if it's just a Thing.CODEC then that's fine too, we'll just wrap that in List.of() and be done with it"

echo lily
#

it does turn everything into list on encode, but I doubt that matters here

tawdry wolf
#

yeah I figure that doesn't matter

kind stratus
#

is there any better alternative to .filter(Optional::isPresent).map(Optional::get)?

#

hmm technically the inner lists should be maps or sets

#

probably maps, they'll look nicer as json maps too

#

is there an open map codec that returns an ordered map? the ordering would be nice to keep for the toString, but isn't critical

kind stratus
#

thanks

#

ok i think i've got the ingredient type otherwise implemented, i need to go now but i'll tackle the codec later

#

...where's the open map codec at again?

tawdry wolf
#

checked Codec, ExtraCodecs, NeoForgeExtraCodecs?

kind stratus
#

i have checked but i don't remember what it's called either

#

oh, unbounded map

kind stratus
#

i still don't know how to test literally any of this though

pure lynx
#

you should be using the name of the unit as the key here

#

this is just really hard to read

#

it should be an either of an integer or an unbound map of string to number

kind stratus
#

i made it so the integer can only substitute for the whole list though, not the entries inside it

#

hmm did i? let me check again

#

oh, it accepts an integer but doesn't write it back out as an integer, but it does write single-element lists out as single values

tawdry wolf
pure lynx
#

i dont have ad astra on 1.21 yet otherwise id offer

#

oh wait no, i do have a mod using fluid ingredients i could use

#

this would be really useful to me rn for liquid experience. id love to have that unit be in terms of exp points

kind stratus
#

hmm

tawdry wolf
#

OpenBlocks also had an XP fluid iirc, that one could be used as well

kind stratus
#

i've been going back and forth on whether to have separate abbreviated and long translations for units, the issue is that most units don't have sensible abbreviations

pure lynx
#

maybe keep that as a lang thing? idk

kind stratus
#

I think for now I'm going to have just singular and plural, and have mb as "mb" but everything else longhand including "experience points"

tawdry wolf
#

I think using mb is fine, everything else should use "long" names (i.e., ingots, gems, nuggets, blocks, shards)

pure lynx
#

maybe the lang would be like 1 ingot(s)?

kind stratus
#

i already have plurals working

tawdry wolf
#

yeah, experience_points is fine because there is no user-facing xp anymore, and removing the _points makes it unclear

kind stratus
#

well, theoretically working as i have not tested anything

#

er i was using xp for the key but "Experience Points" to display to end users

tawdry wolf
kind stratus
#

[the translated names are capitalized because it's easier for a mod that wants to display in lowercase to lowercase it than to titlecase]

tawdry wolf
#

or at the very least, xp_points

#

because otherwise it could be interpreted as xp_levels

kind stratus
#

experience_point then? every other unit is singular internally

#

also

pure lynx
#

the game calls it totalExperience and experienceLevel, so it should be full "experience"

kind stratus
#

is there a resourcelocation codec that can use a different default namespace?

tawdry wolf
#

ah, yeah make it singular, that's fine

kind stratus
#

i'm half tempted to make one

#

tired of staring at "c:"

pure lynx
#

seems beyond scope, the way it works rn is fine imo

kind stratus
#

fair enough

#

so, experience_point

#

also, i set it up so you can put "bucket" or "mb" in the list for display purposes, but they're required to have the correct values

tawdry wolf
#

1 bucket is still a constant 1000 mb?

kind stratus
#

[i needed them in the map internally for the recipe stuff]

#

yeah, changing that is beyond scope

tawdry wolf
#

yeah that's fine then

pure lynx
#

maybe just make them properties of the datamap thing? cuz you'll have more data than just the list in the datamap no?

kind stratus
#

not sure what you mean

#

[why the hell doesn't applyAllFormatting actually fix any of the issues it complains about? isn't that the purpose of having check and apply separate?]

pure lynx
#

nvm, i just typed out what i was thinking and it was dumb

kind stratus
#

i guess it only applies whitespace

pure lynx
#

what other values are we putting in the individual entries for the datamap values

kind stratus
#

display_in_tooltip flag

pure lynx
#
"#tconstruct:fluid_units/metal": [
      { "name": "c:block",  "value": 810 },
      { "name": "c:ingot",  "value":  90 },
      { "name": "c:nugget", "value":  10 },
      { "name": "tconstruct:copper_can", "value": 90, "show_in_tooltips": false }
    ],
"#tconstruct:fluid_units/metal": {
  "c:block": 810,
  "c:ingot": 90,
  "c:nugget": 10,
  "tconstruct:coppper_can": {
    "amount": 90,
    "show_in_tooltips": false
  }
}

should be possible and how id prefer it to be written

#

i think this would just change the value codec to be an either

kind stratus
#

... can you do that?

pure lynx
#

i think so?

#

i can try it

kind stratus
#

oh

#

i can just make the entry codec not include the name

#

and use that as a value in the unboundedmapcodec

pure lynx
#

yeah, itd be an unbound map of string to either an int or "configuredint" or something

kind stratus
#

wait no how would i get the name into the entry when reconstructing the

#

do map codecs guarantee order?

#

actually, i don't need them ordered, nevermind

pure lynx
#

it doesnt really matter the order

#

its ordered by the value anyways

#

but in my experience yes, the order does usually stay the same

tawdry wolf
#

yeah, type should generally be int here

kind stratus
#

i just realized i don't actually need a class that includes both the key and the value

kind stratus
#

gah i'm getting an exception on this codec and i don't know why

#
public static final Codec<FluidUnitSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(
            Codec.unboundedMap(FluidUnit.CODEC, UnitInfo.CODEC).fieldOf("units").forGetter(s -> s.map),
            FluidUnit.CODEC.optionalFieldOf("default_unit", FluidUnit.BUCKET).forGetter(FluidUnitSpec::defaultUnit),
            Codec.INT.optionalFieldOf("smallest_decimals").forGetter(s -> s.smallestUnitDecimals)).apply(instance, FluidUnitSpec::new));```
#

[on actually statically initializing the codec, as far as i can tell]

#

...oh

#

it was caused by me putting the static public constants in the FluidUnit class above the map that holds them [toolaction style]

#

i guess that's why tool actions have a separate class for holding the constants, i guess i could do that

kind stratus
#

one last push, gonna leave it up overnight for people to look at before doing the PR

#

lol i just realized all my discussion from the last hour was in #neoforge-github

kind stratus
#

it wasn't a codec issue at all, i screwed up the static initializers in the FluidUnit class so it crashed on classload

pastel herald
#

ah

kind stratus
#

I posted the PR

compact lynx
#

enabled PR publishing

kind stratus
#

@fluid mortar @pure lynx

compact lynx
#

could you link the PR here so I can pin it

kind stratus
pure lynx
#

why optional of an int instead of just returning 0?

kind stratus
#

0 means round, empty means it's calculated based on the size of the unit being displayed fractionally

#

er, i assume you mean in the decimal places parameter, optional is a couple other places but it's used with map/orelse, you can't really do that with an int with a magic sentinel value

#

if we really don't like Optional<Integer> all uses of it can be replaced in principle but it's more and less elegant code

fluid mortar
#

We could also use -1 if we need a third state there

#

Though that gets awkward

#

I'll take a look when I have some free time and give my thoughts

pastel herald
#

Isn't there also an OptionalInt you could xmap with?

kind stratus
#

I tried OptionalInt first, it doesn't have the map methods

#

It's also not just about the code in the ingredient handler - getValue is arguably a user-facing API too, and returning 0 or -1 there is just asking for trouble, people will call it not expecting it and end up actually using that value

#

though looking again, i'm actually returning null there instead of an optional

#

the optional for decimals is mostly internal and fine to change i guess

#

i actually should probably do a pass through the codecs adding validations to prevent zero and negative values where inappropriate in general

#

i think i was stuck on the codec needing an optional, i'll go ahead and change the decimals field since it's internal

#

ok yeah most of my concern was actually for getAmount [which i misrembered as using an optional for, i think i had one at one time and then switched it to a nullable], not the decimals field

#

incidentally, i was half tempted to implement a system for allowing fractions to be printed as fractions too, but that seems out of scope.

#

hmm

#

should i put some of this codec stuff in NeoForgeExtraCodecs?

#

lol oops i completely forgot to make a stream codec

#

is there a built-in stream codec for maps?

kind stratus
#

found it - i do not understand why it cannot infer these types though ```
ByteBufCodecs.<RegistryFriendlyByteBuf, FluidUnit, Integer, Map<FluidUnit, Integer>>map(HashMap::new, FluidUnit.STREAM_CODEC, ByteBufCodecs.INT).apply(ByteBufCodecs.list()),

#

ok i've got a bunch of the codec stuff fixed, and that Optional removed, gonna push as soon as i can verify it still compiles and runs datagen

pure lynx
#

are there really languages where the way its currently setup wouldnt work? I know mandarin doesnt really make a distinction between plural and singular but that could just be solved by using the same text twice. Maybe the plural ibm thing would be helpful, i havent ever used it tho so idk how thatd work

kind stratus
#

gonna also add simple tests of the ingredient

#

the plural thing is something i was concerned about, but gave up since, well, i have no understanding of how PluralFormat is actually available using the Component system. I had actually assumed it wasn't available, and that adding support to it would be a different PR entirely.

#

@chrome dirge ???

chrome dirge
#

After I spent an hour looking into the Java side, I was a bit fed up with the topic and didn't look into the Minecraft side of things. However, at its base, what's behind the formatter is a lookup which of 6 translation forms to use. So even fi the formatter itself is useless, that lookup still should be in there and we may need to go traditional with 6 seperate lang keys instead of the modern 1-key-with-inlines format

kind stratus
#

ok but the function may be called on the server, and the user's locale is unavailable there

#

i think pluralization for languages that don't use a simple singular-plural form is outside of scope if there's no actual way to do it

#

it's worth looking into in general though

#

i wrote some gametests for the ingredient types, and my matching is failing for some reason

chrome dirge
#

oh, yes. there it is: com.ibm.icu.text.PluralRules

solemn sand
chrome dirge
#

um, getTooltipComponents() called on the server? seems odd

solemn sand
pure lynx
#

dont commands do that?

kind stratus
solemn sand
#

You often grab them there, then sync them to the client for whatever reason

chrome dirge
solemn sand
#

Does MC deal with this anywhere?

kind stratus
#

ah shit i forgot to run apply formatting before pushing

kind stratus
solemn sand
kind stratus
#

because it's ugly

pure lynx
#

(s) i think is fine?

solemn sand
#

1 bucket(s) looks fine to me

kind stratus
#

and it's mostly in command outputs, which is less user-facing

#

"1 block(s), 4 ingot(s), 4.5 nugget(s)"?

solemn sand
#

There's no good way to handle plural vs singular via translation components as they currently work

solemn sand
pure lynx
#

lets just make everyone learn mandarin or something, no distinction between singular and plural 😄

#

the optimal solution™️

kind stratus
#

how about this: people translating for languages that the english rules don't work for can put their equivalent of bucket(s) in both keys if they want, but we'll keep the plural system for those that do

#

[it'll work for french too, these never get printed with zero, at least not by the helper function]

kind stratus
#

Empty

pure lynx
#

im also personally iffy on the keys being singular. for ingredients it doesnt look correct

{ buckets: 1 } > { bucket: 1 }

solemn sand
#

Ah, okay

solemn sand
#

And in the data map for setting those, the plural versoin would look weird

pure lynx
#

well either way its going to look weird somewhere. the datamap one is more for the mod dev while the usage in recipes is more used for consumers and users, i say make the key plural :P

#

you write a data map once, you could end up writing dozens of recipes, it affects one more than the other

kind stratus
#

what if i made each one have two names

pure lynx
#

oh god no

#

aliases.. hm

kind stratus
#

have that and a special codec that omits the c: namespace, for maximum friendliness

#

[to be clear, having two names is not actually viable, they'd have to be registered in code instead of auto-interning like tool actions]

#

the no-namespace codec is viable though

solemn sand
#

No aliases. I'd rather have only-plural than that

#

no-namespace codec though -- that's a good idea. Stops you from accidentally using minecraft: units too

chrome dirge
#

aside from the decision for this specific case, what would be the general opinion in the room on patching proper pluralisation support into the translatable component? Naturally, using it for Components sent to vanilla clients wouldn't work, but aside from that I see no compatibility issues when hijacking the % placeholder as any other character than % and s after it is a fatal error atm.
(i.e. would it be a waste of time if I were to look into doing that)

pure lynx
#

as a separate PR it might be a nice feature

#

im sure this is not the first or last time someone will run into this issue

kind stratus
#

i like the idea

#

but i wonder if inline formatting might not be the best solution

#

actually nevermind, fuck messing with the component codecs

chrome dirge
#

my idea if to hijack the % and use e.g. "%(standard ICU plural format)" for this

kind stratus
#

[yeah inline formatting is fine]

#

yeah, i had a vague idea of using some sort of custom json format, then i just realized what a nightmare that would be to implement

#

i think there are some places in FML that use some kind of %{} thing, so it's not without precedent, though i think they only work for logging not for the game itself

#

what exactly is the ICU plural format? like, is %() part of it, or is that your own invention? all i can find just uses {}

#

and named variables instead of numbered ones

#

i guess as long as it works it doesn't matter what the particulars of the format are

chrome dirge
#

so in the json it'd be "key": "I see %s %(one{dog} other{dogs}) here!",

kind stratus
#

%1$(...) surely

#

[not passing the argument twice means we can in principle fix vanilla's (s)s with a resource pack]

chrome dirge
#

%s is the only allowed placeholder in vanilla, and while it would be great for localisation to provide positional ones, I'm not sure if that should be mixed in with pluralisation

#

oh, that

kind stratus
#

i'm pretty sure vanilla does support %1$s

#

it's been a while since i looked at it though

chrome dirge
#

yes, I think "key": "I see %(one{%s dog} other{%s dogs}) here!", could work
But I'll have a look ath what the ICU classes provide first before I spin my own thing here

elfin yacht
#

pluralization support is... complicated

chrome dirge
elfin yacht
#

its simple for english

kind stratus
#

it could, but not being able to reference the argument twice means you're limited in cases where a different variable needs to be printed in between the number and the pluralized form

elfin yacht
#

but some languages go up to... 6? different forms based on plurality

chrome dirge
#

Shadows, see above, I posted a reference link

kind stratus
#

yup, we're aware - i only used simple pluralization because fixing the component system to do more is outside the scope of this particular PR, but that doesn't mean it's not worth doing

#

(incidentally, it's not like complexity is foreign to english - our plurals are simple, but we have the same problem with ordinals)

#

some of the rules on that page for plurals actually remind me a lot of english ordinals, with the 1 vs 11 vs 101 thing

chrome dirge
#

yes, funnily enough, given how many different variants of languages there are, they all are a mix of very few building blocks

kind stratus
#

[i don't know for sure if there are places in vanilla or mods that do "1th" ordinals, but i don't particularly doubt it either]

chrome dirge
#

I'm pretty sure vanilla only uses number inserts in their strings very, very, rarely

elfin yacht
#

yeah vanilla doesn't do it very much

#

mostly in the options menu or debug

#

where they don't need to display X things, but rather Value: X

kind stratus
#

of course

#

there is another alternative

chrome dirge
#

"translation.test.complex": "Prefix, %s%2$s again %s and %1$s lastly %s and also %1$s again!", ok, there is a complex pattern. I just need to find the code that handles that

kind stratus
#

we could always print singular

#

eh scratch that

#

for some reason i had it in my head that vanilla does "1 [singular item name]" in tooltips, but the count isn't in the tooltip

chrome dirge
#

um, duh. found it. the code checks the second part before the fist part. I stopped reading before I got to that 🤦

kind stratus
#

anyway, we should probably split off another thread for this

elfin yacht
#

It looks like we can also just add new ComponentContents

#

So if we need a different "plural-sensitive-contents" that's a thing we can do, I guess

chrome dirge
#

finally found one in the vanilla lang file: "Chat message was too long (%s > maximum %s characters)", and chat.queue": "[+%s pending lines]",, "clear.failed.multiple": "No items were found on %s players",, "commands.banip.info": "This ban affects %s player(s): %s", "commands.banlist.list": "There are %s ban(s):", and a couple more command result messages

kind stratus
elfin yacht
#

yeah we have that thing

#

it's why we have a custom contents in the first place LUL

kind stratus
#

nice

#

that's probably a better path then, i just assumed it would be too difficult

elfin yacht
#

iirc there were some vanilla compat concerns but I guess they got that worked out

chrome dirge
#

grrr, not a single line of javadoc. how will anyone know how to use that? (re 1134)

elfin yacht
#

I don't think you are intended to interact with the contents object

kind stratus
#

i tried to document most of my public methods, i might have missed a few though

#

eh

#

i mean, javadoc isn't a totally non-viable venue for documentation of a json format

#

my ingredient type has json info in the javadocs on its codec fields [copied from sizedfluidingredient which also does it]

elfin yacht
chrome dirge
#

grrr, even after spending ten minutes reading that PR's diff, I still have no idea how I would use that thing other than copy&pasting the test that comes with it and trying out what works .-(

elfin yacht
chrome dirge
#

"When owo is installed, " Alt-F4.

;) ;)

chrome dirge
#

just a quick&dirty proof-of-concept hack. that patch is 5 lines plus a tool method to safely convert the parameter to double

tawdry wolf
#

A problem you will run into as well is existing resource packs

#

especially if you extend it to vanilla plurals

chrome dirge
#

should be no issue, unless someone uses "%(" somewhere...and I just noticed that that was an ignored, not an illegal combination. I may need to change it to e.g. "%n(", an actually illegal combination.

chrome dirge
#

very convenient one, already there and comes up when starting the server ;)

kind stratus
#

ugh i forgot to check notifications - i'll go through the PR review comments in the next few days

kind stratus
#

Its probably worth having a method on FluidStack to get the full tooltip including display name to standardize the order and color between that and the amount string. Plus would call appendHoverText

I thought about this and actually almost started writing one, but then it occurred to me that about half of the vanilla itemstack components that affect tooltips [e.g. name, lore, rarity, etc - maybe potion effects] could be applied to fluidstacks as well and figured it's something that deserves some discussion on its own.

kind stratus
#

is there a tool i can run to find public methods that don't have javadocs? i think i got all of them but it'd be nice to be sure

kind stratus
#

ugh i thought i did run datagen, apparently it failed

fluid mortar
#

we could start with a bare bones "getHoverText" then expand it in the future

#

alternatively, we could do that PR first and do the units PR after

#

only concern with that idea is the unit display would have to be fixed to millibuckets which makes it more difficult for mods with their own unit display in the meantime