#1.21.2 Snapshots
1 messages · Page 5 of 1
yes
theoretically, this would just work
unfortunately, itemstacks and fluidstacks aren't hashable
they will never be hashable
that's fine
but there needs to be some way to distinguish the target "type" here
and filtering for ItemStackContentsFactory instances is dumb
because there may be other implementors of DisplayContentsFactory<ItemStack>
instanceof
in fact I was going to suggest that we check for instanceof DisplayContentsFactory.ForStacks<T>
wdym?
ForStacks still doesn't constrain the output type properly
it's clear that it is MEANT for item stacks
but there are displays that could output, for instance, just the item holder
not our problem IMO
we can't be certain that ForStacks outputs ItemStacks
hmm
there is probably a reason why vanilla chose not to constrain types here
wdym?
this interface
there is CURRENTLY only one implementor in vanilla
(and none for ForRemainders, oddly)
ForRemainders was added for EMI etc
right
what i'm saying is this doesn't restrict the type sufficiently
for example if, ignoring the fact you're an AE2 dev
you used the information from slot displays to make ItemKeys for example
nothing in vanilla assumes that ForStacks PRODUCES item stacks
only that it CONSUMES them
we would have to assume that ForStacks produces ItemStacks for our purposes
(in other words a more appropriate generic signature for this interface would probably be DisplayContentsFactory<out T, in U> but i digress)
oh right
we could make our own implementation of ForStacks that returns the stacks directly
ForItemStacks?
i mean, here's the thing
if mojang are receptive to changes to this system anyways, then we could see if this system can't be altered slightly
to just make our lives a little easier 
Ugh I see I really need to read up on what the changes actually are. Right now I am blissfully ignorant.
especially since this design is probably gonna bite them in the ass eventually
ForStacks is maybe a bit of a misnomer, because it indicates that the interface consumes stacks
just like ForRemainders consumes remainders
return factory instanceof DisplayContentsFactory.ForStacks<T> forstacks ? baseDisplay.resolve(context, new DisplayContentsFactory<ItemStack>() { public ItemStack forStack(stack) { return stack; } }).filter(s -> !excludedSet.contains(s.getItem())).map(forstacks::forStack) : Stream.of()

looks reasonable I hope? 😄
it won't propagate the type of the factory to other displays, but I don't think we really have a choice
if we do this, should we force subtracted to be a simple ingredient?
yeah honestly
simple just means that it doesn’t need info that we can‘t send over a vanilla channel right
so a kubejs ModIngredient for example is simple
@fathom compass some thoughts related to remainders:
- remainders aren't retrievable through
TagSlotDisplayeven though the recipe uses them - in general, remainders are dependent on the stack that you pass, so it's weird to retrieve them without context information about stack that the recipe will use. And in practice, the remainder is just
stack.getItem().getCraftingRemainder(); how about just returning that from theSlotDisplayby default? - remainders are controlled by the recipe ATM; should they be moved to the ingredient instead? You might want to unify
matches,assemble, andgetRemainingItemsin that case. 😄
also tech real quick — this can just use ItemStackContentsFactory.INSTANCE
simple means that test(stack) is equivalent to items().anyMatch(item -> stack.is(item))
true! nice
which is essentially the same thing as being sendable over a vanilla channel then
then all of kubejs‘ ingredients are simple
which is great news for me

either way, i‘m fine with the tunneling through ItemStack that we‘re doing above
it does mean we will need a different slot display for fluid ingredients
or actually nevermind!
we can instance check for ForFluidStacks
and just do the same thing again
I don't think it's a good idea to mix the two
if you're making a custom one, yet another is cheap 😄
well
the logic is the same
and SlotDisplay is meant to provide us with abstract logic
so i figured we might as well combine the two
either way, not a big deal
This schema is mostly aligned with our plans for recipes:
- Recipe is supposed to be a main (and probably only) "decision-maker" when it comes to crafting
- That includes remainders (so
Item.getCraftingRemainder()will be gone) - Displays are meant to represent static list of potential outputs (or some representative selection of it) since calculation of actual outputs will depend on many conditions in the future (loot table style, probably). It will be up to recipe creator to write them (outside of some defaults for trivial recipes)
the last bit is a nice bit of reassurance
i‘m on a train so my data is extremely spotty
and in typical DB fashion the wifi isn‘t showing me the captive auth flow 
but right now i‘ve basically just done what you‘ve shown tech
we might want to add a utility method to resolve to an ItemStack stream using an extension interface
(which we can also use for utility methods like resolveForFluidStacks)
because vanilla only gives us resolving to a list currently
because i assume this pattern of tunneling through item stacks (and later fluid stacks) will become more and more common with the custom ingredient displays
oh ew intersection ingredients are gonna be a bit of a pain
Ok that makes sense, thanks. That also explains why the displays have a Codec!
I think we have to enforce that either 0 or 1 is non-simple
OR
we make the slot display part of the ingredient's JSON 😄
and honestly I'm kinda tempted to do that; provide a default that makes sense for simple ingredients, and let people override the slot display
wait what
why would intersection have to be non trivial
what about (TAG A) x (TAG B)
also intersection is n-ary
yeah uh no
with respect to intersection ingredients?
shit is fucked!
Does that mean we should eye a platform introspection API for recipes if the output becomes less predictable for recipe viewers or calculators like AE2?
well, nothing really changes right
recipes were unpredictable before this
they are unpredictable now
I suppose so
displays just expose the same information as before
it‘s the implementation details that kill us
specifically again the lack of IS hashing
AE2 is gonna have an interesting time
i mean the ItemKey idea honestly doesn‘t seem the like worst thing on the planet
I said simple
Tag ingredients are simple because they don't depend on NBT
Can't we give the json writer a way to override the SlotDisplay, btw?
it looks like you are the person behind recipe stuff... brewing recipes as json when? /s
every time they're asked, they have to push it back by another year
next rc
brewing recipes as json needs component inputs
or a custom recipe type
that specifically filters for the potion component
and that is gonna mean bikeshed
of course it needs its own recipe type just like smithing and furnaces
I have an implementation ready as a PR
👀 once the second point is implemented I can yeet my custom recipe
depends if the remainder logic is data-driven or not 😉
what else would it be if the method is gone?
hardcoded map

also depends on how extensive remainder logic is
like tools need to be returned with -1 durability for example
so it needs component transformation logic
unless that‘s what the loot table like system refers to
since i did think about implementing remainders using loot item functions in the past
in this case, I just need the water bucket to not empty itself but be consumed fully 
I imagine that would be default functionality in the future and then like what max said there would be some crafting function that replaces the ingredient with something else
well, if that's the case then I can yeet both custom recipes 
That includes remainders (so Item.getCraftingRemainder() will be gone)
oof, rip jumbo furnace giving you your lava's bucket back
It's already in the recipe
no no, when you use the lava bucket as a fuel
well, if they don't have a way to do that, even normal furnaces will have a problem 
Why are you using remainders at all for that?
normal furnaces just eat the bucket IIRC?
They could trivially hardcode the translation
ah no normal furnaces do give you the bucket back
that sounds wrong
But in NeoForgeland you can just use a Fluid handler to extract the 1000mb of lava and have it automatically give you the empty bucket
how WOULD that work in vanilla without crafting remainders
Since you're using it as a fluid container, not really a crafting ingredient
... hardcoded? 😛
hehe probably
no I'm using it as a fuel
Yes but the lava in the container is the fuel
let's say somebody makes... I dunno, a bowl of coal
if I eat the coal it should give the bowl back
data-driven fuels in vanilla 🤔
i'm sure some mojangster already looked at neoforge's datamaps
yeah but those are two simple ingredients
you said either 0 or 1 would have to be non-simple
unless you mean that only one ingredient in an intersection at most can be non-simple
And then they implemented it with two lists instead where you have to match up entries to each list or else crash
ah yes, map at home
Or the folder is the map and the files are the entry and you put just the burn time as the file content. The file name and path is the item
the best json content
an intersection of multiple non-simple ingredients seems... stupid
nah, they'd for sure componentize that rather than use a datamap-like solution

well, that's a container remainder and is already an item component
oh, you mean minecraft:burnable int component?
ahhhh maybe that's what was meant by that
i was gonna say for furnace fuels, was that not already a thing
i'm not talking about just furnace fuels though
I'd imagine it'd be called "fuel", rather than burnable
there are non-item data maps
and that's part of their strength
it'll probably be a while before we see entity data components
even then, datamaps do not sound like a mojang kind of thing. They'd more likely just create new datapack registries for each aspect that they want to define in data
"ParrotImitationData" registry
it's the name, it doesn't matter
I'm just being nitpicky, let me be :p
Entity components will be cool when they get around to that
can i uh
try and nudge this back onto the ingredient discussion
because that's what's kinda important to me rn
has hasCustomOutlineRendering been accidentally removed from BE's (in the port)?
or is it intentional
Will be replaced by some new hook that works with the frame graph system
frame graph?
That's intentional. The flag is now computed when the frame graph is built. For entities, vanilla does this by checking for outlines when they collect the visible entities during frame graph building. BEs however are still iterated during actual rendering with the two separate loops (per-section and global) and I didn't really like the idea of patching that to make it work like the entity approach just to keep that hook. My current idea is to add an event during frame graph building which allows setting that flag.
alright
ended up discussing something with tech real quick
and i think we may in fact just use the item-only displays he has right now by default
and then instead provide a way to override the display manually
(so for example through json)
partially inspired by what boq said here as well
It will be up to recipe creator to write them (outside of some defaults for trivial recipes)
this sort of calls back to an old idea i had with kubejs
where we wanted to have an ingredient type that essentially just wraps another ingredient
and changes the display item stacks
ideally, we would want the system to:
- use
new SlotDisplay.Composite(items().map(Ingredient::displayForSingleItem).toList());by default (this is alright since the VAST MAJORITY of ingredients are simple, and in fact the only thing that makes an ingredient non-simple is if one of its children is a component ingredient - provide a way for the ingredient type to override this? (this is a maybe, theoretically only component ingredients should need this honestly)
- provide a way for the recipe creator to override this!!
- either with a custom ingredient (that basically does what i said the kubejs one would have done above)
- or a custom "neoforge:display" field that can be added to any ingredient
thankfully, slot displays already have a json codec (thank mr boq) so that part is made easier for us :p
I'm tempted to add an OverrideDisplay custom ingredient that just wraps some ingredient to override the display in a data oriented manner
maybe
i‘m fine with either or really
once that all is a thing
i'll do the same thing with fluids
yes
sweet
pasisng thought before i pass out (@silent ping me if needed)
this seems like a good start for a fluid display contents factory
however -- contents should usually be stacked, right?
so maybe it should be like ForStacks instead
but then we run into the problem of "how do we form 'default' fluid stacks"
also s/Fluid/Holder<Fluid>
there is potentially this extremely cursed hierarchy but even that has the issue of needing BUCKET_VOLUME in one place
this separation might actually make sense tho
to differentiate between contexts where we care about fluid amount and contexts where we don't
Is that really needed?
I'd just copy vanilla and only have a single thing that accepts stacks
right but what stacks do fluid ingredients produce then
iirc we made a conscious choice never to guarantee anything about stack size there
hmmm
SingleFluidIngredient uses FluidType.BUCKET_VOLUME
that's probably fine™️
Note: No guarantees are made as to the amount of the fluid, as FluidIngredients are generally not meant to match by amount and these stacks are mostly used for display.
right
we can add that disclaimer to ForFluidStacks
right then
what about the structure of the class
theoretically it‘s possible to combine Single and Tag into a holderset based FI
which would allow for other holdersets as well
i think i might do that in fact
Yeah
MC-277552 - Wandering traders look smaller than in previous versions
<@&1067092163520909374>
New version detected: 1.21.2-pre4.

we're rapidly approaching a RC
oh lord
New version detected: 1.21.2-pre4.
👀 if that kills the Action I screm

Maty
We need to add a proper debounce/throttle on that
hold on
did vanilla change its ingredient syntax in json?
is it now just #tag or namespaced:item
oh!
yup
from what I understand ingredients are just holdersets in vanilla now
that's standard holderset syntax
also no more mixed tag and item lists sadge
actually with neo's orholderset you can still mix that right
yes
yes
nice
btw this is why you can't use "type" for the ingredient type
the tricky bit now is respecting nbt in ingredients
I would recommend neoforge:ingredient_type
yeah i'll do that
maybe something like SizedIngredient but for datacomponents and the recipe serializer has to opt into it
it has to work with vanilla recipes
why
so hold on
so it must be done at the ingredient level
there is no explicit map syntax for simple item ingredients
so there shouldn't be any for simple fluid ingredients either
why does datacomponents have to work with vanilla recipes? sizedingredients don't
oh man i really need to just
nuke this entire fluid ingredient system

or at least the codecs rather
oh man
should SimpleFluidIngredient even be an explicit type anymore
make a HolderSetFluidIngredient?
as long as there are factory methods in FluidIngredient people don't have to know about it 😄
fluid ingredient types need a map codec though
should i just use a map codec that always errors
or wrap the existing codec in a field
like "values"
yeah I'd make one that always errors
in both directions
to make the format as aligned with vanilla's as possible
do we even need ingredient types now
yes we do, please stop
why do we need them
what use case do they have that can't be resolved with custom recipe serializers
the point is that having to make a custom recipe serializer and type every time you want NBT-aware matching is not good
it is too much effort for what is a very common use case
it's really not that much effort
sizedingredients would not be suitable for vanilla crafting recipes so it would have been a bad idea to integrate them with ingredients
in this case however it's just a matter of redirecting the test method a little bit 😉
Let me just make a custom recipe serializer for every possible ingredient combination that exists
better start now, it will take some time
case in point: mojang does it
what we could consider is removing the customizability of ICustomIngredient in favor of having a HolderSet + a component predicate
idk if that's a good idea however
Except Mojang doesn't have to deal with people wanting to use a Mekanism fluid ingredient along with a CraftTweaker Conditioned Ingredient and a MyMod SeedTypeIngredient all in the same recipe
Maybe an Extreme Crafting recipe that uses a different recipe type altogether but is otherwise fully the same as crafting table recipes
I'm not saying toss out the concept of component predicates, I'm saying separate them out like we did with sizedingredient
so you'd have a SchmancyIngredient(HolderSet, count, Predicate<ItemStack>) or similar
HolderSets don't support equals() and hashCode() btw
which is a bit odd
but that is another thing custom ingredients currently have over vanilla ones
oh that's annoying; Ingredients are supposed to be hashable and equals-comparable
why
err I mean
mojang-supposed-to or neoforge-supposed-to
neoforge
for the StreamCodec
since FluidIngredients are inherently modded, should i just ONLY use a dispatch codec there
i don't see the harm in it, why not
yeah I think dispatch only is fine
Only interesting change this update is one of the Font#drawInBatch overloads changing
@red jungle idk about you but this feels wrong 
then again, fluid stacks are supposed to ignore amounts, so whatever
with the difference ingredient i was thinking about doing return base().fluids().stream().filter(e -> !subtracted().fluids().contains(e));
but for intersection that is a bit more involved obviously
also holder equality is a problem
Reminder that the block item methods within the Items deferred register should also set useBlockDescriptionPrefix
what is this?
intersection?
yeah
fluids don't have a default instance
we explicitly never made one because we didn't want to declare 1000 as the default amount
should i actually add a getDefaultInstance
or just use FluidType.BUCKET_VOLUME specifically in these ingredients like i have already been doing
I prefer that
what theme is that
looks cool!
Imo use this until handler rework, then we can consider using a resource and not caring about the number

I use the same theme, with color changes. And eclipse syntax highlighting
So good choice lol
drafted for now, gotta work on some uni stuff
just wanted to get this out
feel free to change whatever you need
looks pretty good
oh my god the github actions notifications are so annoying
@ripe drum we need more github message email spam
smh smh
the emails max's talking about are the build actions failing
(yes those are annoying, also yes i can't do anything about it)
not as bad as fabric pr email spam. Dont ask how I know
oh
i just realised i messed up something hang on
alright, that's fixed
still gotta do some docs and test cleanup
tho if anybody else wants to, the branch is open to fixes from maintainers
Fabric takes reviews seriously 😅
i know this is more of a request, but would it be possible to have lambda$addMainPass$2 (the main level rendering in 1.21.2) not have a different descriptor to vanilla?
it makes any sort of multiloader level rendering injections absolute pain
actually, one second... I don't know why it is different to begin with
it's LevelRenderer so yes
We are recompiling the file
and the resulting bytecode gets "printed" onto the vanilla class in production via binpatches
code order is not guaranteed to be identical to mojangs sources when it comes out of vineflower
i know, I'm fine with the lambda names being different; i'm referring specifically to the descriptor usage
there's an extra boolean in the descriptor (it seems)
making any injections meant for Fabric/Vanilla fail
That is potentially caused by a patch to the method capturing an additional variable? (guess)
probably... i'm just wondering if it can be avoided
okay
looking at it again, the descriptor just has a different order
(Lnet/minecraft/client/renderer/FogParameters;Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/Camera;Lnet/minecraft/util/profiling/ProfilerFiller;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;Lnet/minecraft/client/renderer/culling/Frustum;ZLcom/mojang/blaze3d/resource/ResourceHandle;Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V
(Lnet/minecraft/client/renderer/FogParameters;Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/Camera;Lnet/minecraft/util/profiling/ProfilerFiller;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;Lcom/mojang/blaze3d/resource/ResourceHandle;ZLnet/minecraft/client/renderer/culling/Frustum;Lcom/mojang/blaze3d/resource/ResourceHandle;Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V```
the Z is moved to after frustum instead of before
fixing this would be really nice... it makes literally any multiloader project involving rendering pain on 1.21.2
Are those captured local variables?
seems so
captured from the main addMainPass function arguments
I'm pretty sure the argument in question is p_363964_ (?)
frustum is now used before it due to all the dispatchRenderStage calls
just a guess right now
I am not a big fan of patching a method to reorder the captured variables in a lambda since it's 1) never guaranteed to get the same lambda signatures as vanilla and 2) the effects and reasoning for doing this are completely hidden and will just fall on our feet in the next porting cycle
What are you injecting into that method for?
literally everything
it's Iris
it needs to constantly redirect and monitor the entire level rendering
alternatively, is it possible to not use arguments in a mixin injection (just have a CallbackInfo) then use @Local to dynamically get the things I need without relying on signature?
if so, this isn't nearly as much of an issue
Hm
Hey, just be thankful that this lambda has the same name in dev and prod, unlike some out there... but yes, that sort of mixin should in theory work?
Are there any injectors that force you to include args? I'm not sure
are you redirecting the entire lambda?
If so, just redirect the addMainPass call? 😅
Hm? Do you need the args at all in those? I thought you could omit em
not all of them, yeah
that's what I'm doing right now
but some of them do need some
going to try the @Local idea
good news
@Inject(method = { "method_62214", "lambda$addMainPass$2"}, require = 1, at = @At(value = "CONSTANT", args = "stringValue=translucent"))
private void iris$beginTranslucents(CallbackInfo ci, @Local(argsOnly = true) DeltaTracker deltaTracker, @Local(ordinal = 0, argsOnly = true) Matrix4f modelMatrix, @Local(argsOnly = true) Camera camera) {
pipeline.beginHand();
HandRenderer.INSTANCE.renderSolid(modelMatrix, deltaTracker.getGameTimeDeltaPartialTick(true), camera, Minecraft.getInstance().gameRenderer, pipeline);
Profiler.get().popPush("iris_pre_translucent");
pipeline.beginTranslucents();
}```
this does actually seem to work
now time to do this 50 more times and come back with results...
yep
Okay, good thing that's on both fabric and NF 😄
For the monitoring part, can you not just use RenderLevelStageEvent to track what stage it's at? The lambda issue sounds like an XY problem
Why do many method_?
On Look you can enable an option to use the $lambda$ normally
that doesn't work in production though, does it
i'm not going to rewrite this entire thing to use Neo only events when the multiplatform one works perfectly
Well if you're remapping mixins it will
Please tell me you're remapping mixins
Enable nameSyntheticParameters. Without it, Loom strips all mappings for synthetics (such as lambdas)
Which could also be said remapping issue
i just read up on fabrics blog post, what’s with blocks and items and entity types now being passed their id?
evidently it… doesn’t though 
we also had to write a mixin with three targets in kubejs back when we were multiplatform
due to signature shuffling
from what i remembered as soon as we went neo only that just became an event listener
well it does now with the local trick
the injections themselves are fine
Well, similarly, we're not going to rewrite a lambda signature to address a use case that would work perfectly fine with an event 😉
i mean that's fair
if there is a supported way the supported way should be used
everything else is just kinda... hacky
oh dear that reminds me i should probably replace some kubejs mixins with event calls
Speaking of lambdas... we do still need to address the whole "lambda names differ in prod and dev" thing
why do lambda names differ in prod and dev, first
The method_ thing is because you're using Loom and didn't disable Loom's "feature" of stripping lambdas from mappings
Slightly painful (mostly self-induced pain) but it runs. Some noteworthy stuff I either I already knew or found during some quick experiments:
RenderHighlightEvent.Blockfires twice, once during non-translucent and once during translucent rendering. This is a vanilla change with the intention to fix outlines in non-Fabulous modes (not that it actually achieves this: if you place a non-translucent block [i.e. glass] where you can see a translucent block [water, stained glass] behind the outline, the translucent block will still vanish behind the outlines)- Block outline rendering currently uses
ItemBlockRenderTypesinstead of the model-based render type lookup to decide in which of the two phases the outlines should be rendered RenderHighlightEvent.Entityis defunct as entities can now definitely not reach that codepath anymore (not that I'm aware of anyone using that anyway)- Standalone models registered via
ModelEvent.RegisterAdditionalare currently not loaded (I have a fix for that which I'll push tomorrow) - Render types specified in the JSON are ignored for most models (I have a fix for that which I'll push tomorrow)
How did you handle getLightBlock losing positional context?
Patched 😄
What do you mean by patched 
Patched the context back in during the Kits phase
Hm
Oh, wait, I'm confusing two methods
getLightBlock() was left as-is, the light emission methods were patched to regain the context
getLightBlock() could already not use any level context in 1.21.1 and earlier unless the block was marked as "dynamic shape" so it wasn't a loss that affected me
ah
Also, one thing I ran into in the very beginning: Gradle was complaining about not finding jtracy and I had to add libraries.minecraft.net to my repos to fix that
Recomp
Basically, in prod, classes that neo does not patch the source of, neo does not distribute binary patches to
So they're just the (remapped to mojmaps) vanilla class
In dev, however, those classes are instead the original class, decompiled, neoformed, and recompiled
So in specifically in classes that neo does not patch, you get methods that look like lambda$someContainingMethod$3 in dev but lambda$someContainingMethod$16 in prod, or the like
In classes neo does patch the lambda names are of course shuffled relative to vanilla, but they're (generally, reliant on some impl details of javac but eh) the same between dev and prod
But if neo doesn't distribute a binpatch for that class... all bets are off, including on stuff like the descriptor
(And I have found classes where due to generics stuff being kinda lossy in the decomp/recomp cycle, lambda descriptors also varied between prod and dev -- I'll try to dredge one up, I don't have a good example off the top of my head)
The two solutions -- and this is kinda a rather big issue so I feel like a solution is warranted -- are:
- distribute binpatches for every MC class, even unpatched ones. This'll incease the size of the binpatches a bit -- not sure how much, or if it's an appreciable amount. The resulting situation is still... not too great, as you're reliant on impl details of the compiler; worse, if, e.g., ecj were used, it wouldn't work. MDG allows the use of ECJ for recomp (unless this has changed?), so someone with such an option on can already get mysterious errors when depending on someone else with a mod with mixins to lambdas anywhere.
- avoid recomp. This has... all the issues that led to doing recomp in moddev in the first place, of course. But it would, fundamentally, guarantee that you had the same names in dev and prod, unlike option 1. The issues with using recomp in dev are all theoretically addressable -- even the line number stuff, I have a system I've been working with locally that makes the line numbers line up right -- but, well, the fixes add a lot of complexity.
Option 1 fixes the issue and shoves the cost off onto users, but we don't know how big that cost is. Option 2 fixes the issue, but would require extensive testing to not introduce other issues, and adds a lot of complexity. I've messed around with some other approaches -- such as transforming the remapped jar to get the lambda names to be correct again, potentially by storing some marker next to them in the source that could be erased in the source that finally gets linked, or whatever -- but that approach turned out to not be super viable due to just how much the lambda names can differ -- stuff like descriptor and the like that's more painful to fix -- and it introduced a fair amount of complexity itself
But in any case, this issue kinda means that no library mod can mixin to lambdas, without risking not working on other people's machines when folks depend on it, and mixing in to a lambda in a non-neo-patched class at all requires looking through the remapped-but-not-recomped bytecode -- which is a pain to locate, if you don't know where to look -- to determine the prod lambda name, to begin with
So it's kinda a bit of a big issue
to answer this, it's specifically used for loot tables and such. they want to be more explicit with stuff like that rather than just always assuming it to be the same as the id with a certain prefix or whatever
You have to update MDG to fix that
I hope the fix made it to the 1.x branch
Kind of. But we'll be in a better position to experiment with this once #1279375701115535410 is through
please have a look: https://github.com/neoforged/NeoForge/pull/1597
New version detected: 1.21.2-pre5.
[Jump to referenced message](#minecraft-updates message) in #minecraft-updates
This is a new version. Changes listed from 1.21.2-pre4.
Links:
client | client_mappings | server | server_mappings
New version detected: 1.21.2-pre5.
<@&1067092163520909374>
tiny
we're almost there (ig)
snowman : +3000-2000
I
N8N triggered twice again
Heh second one was in Slicedlime's video
6/191 
pain of n8n
well, partly with snowblower as well
perhaps I should poke that soon...
i mean, nevermind the fact that I don't know what Guardian is 
Pain of 54/191 and rising
Interesting. Ocelot says +92 -71
So close yet slightly different
Very interesting
Likely skips structure files?
This probably has something to do with it
Ocelot turns them into SNBT for proper diffing
The gradle.properties is used by the setup, since it's based on GH Actions and, well, Gradle
Basically the action checks for any releases since the release in the gradle.properties
I was writing an NBT comparar tool at once point, I should finish it.
wouldn't be useful for this, it was intended for use with tortoisegit diffing
the viewer part was done, but I wanted to have a means to transfer data from left to right
well "done"
I apparently never got around to synchronizing fold/unfold
or scroll
Reading another discussion about recipes just reminded me: did we check whether the TagEmptyCondition still works after the tag loading changes?
Good question. Isn't there a test for it?
No clue 😅
hey tech can you forgive me for not properly documenting fluid ingredients and generally finishing up my work on them for a bit ^^;
gotta deal with hacking together dockerfiles for the ctf challenge we're hosting at uni
as well as just my thesis
so the rest of this week is gonna be fucked
Oh, I definitely look forwards to the neodev gradle setup being easier to mess with! You're absolutely right that this shoud be easier to address afterwards -- I just want to make sure that we don't lose sight of it given the scope and impact of the issue
ugh 😅
is there really that much work left?
yes ofc; it's just hard to evaluate possible solutions right now
thankfully it's mostly docco work
and working on sized ingredient displays
...and tests
Well, it's not like there's a huge variety of possible solutions. We only have, like, 2 -- what I'd thought in the past might be a third turns out to not work or be impractical for other reasons. But sure, point taken
Pushed a fix for the last two points and the missing updates to generated files
Wait how do you get access to snowman?
By being a team member
Yes, snowblower is the tool used to generate snowman
Ok
@lucid totem I was curious what the implications of the blockstate changes are for a mod like FramedBlocks with very large amounts of blockstates and the difference is actually quite substantial (first is 1.21.1, second is 1.21.2). The cache is also significantly smaller now.
the shallow size of BlockState increased but maybe they deduplicate more aggressively to make up for it
I saw some basic deduplication for common shapes
Yeah, empty and full occlusion shapes use a shared "face shapes" array
but yeah, 2.5x reduction is very nice
JCC also fails on PRs against the port branches...
Does the blockstate stuff include "fixing" the neighbor state data structures to not waste insane amounts of memory?
That's the primary change, yes. Instead of a Table, the neighbors are now stored in a Rerefence2ObjectArrayMap<Property<?>, S[]> (the field is a plain Map in this case). The index into the array is provided by the respective Property
pre6 today, or rc1 
Heads
RC1
Tails
pre6
pre6

the bot is convinced it is pre6.
do we have
for today?
no confirmation, I just expect there to be a rc1 today with release planned for tuesday
if release tuesday then rc1 tomorrow is more likely
New version detected: 1.21.2-rc1.
Took ya long enough
New version detected: 1.21.2-rc1.
RC time
I 
whee release candidate!
so was this notification from a parallel universe where they released fifteen seconds later...?
It's the N8N automation being a bit fucky so it triggers multiple times
wondrous
why have people post the link by hand when we can have a bot that does the same thing but janky and slower? :p
Oh for this?
That's because the blog release tends to be behind the actual release
Those initial messages come from checking the version manifest (which then kicks starts some automated processes related to handling new MC versions)
No, it kills ones part way through which then means it fucks up the cache 
the snapshot bets site just polls the launcher manifest once a minute
yep, excluding all the version number changes, like ~10 changed lines
so many alarms this week
https://github.com/neoforged/Snowman/commit/8f851a8e12091398233916fc2cff3a7de9c3defd
9 files changed, +28 -24 lines changed :P
slicedlimes update video should be short and sweet today xD
The fix for the first one is this
I wonder why it wasn't using a loot table before 🤔
Oh FFS rc1 already -- I am not ready...
if you want them to release faster 

-# surely nothing can go wrong with faster releases, right...
wait what
was that like some kind of joke from mojang? theres no way that was an accident.
also nice job
oh lmao its linked to the version release date ok thats kinda cool
Which are mostly correct
There's a few that are fudged slightly on Mojang's side in the Version Manifest to effect sorting
lol
Roughly how soon do you think NeoForge will be updated to rc1?
40 seconds lol gotta be one of if not the shortest update videos
Whenever the necessary people get time, since it's so small it should be fairly fast once they do
We won't do a proper release until after Mojang drop 1.21.2, however you can see/use via the PR builds available from https://github.com/neoforged/NeoForge/pull/1590
So the passenger issue was this: if a client was told to make an entity ride an entity it believed was unserializable (like a transient creaking), it would reject it
So that check is now server-side only
Yeah I'm not asking about full release. I'm wondering when I can start my update process
Fabric discord brought up a good point
We need some way to update our tags with experimental stuff only when the experimental datapack is on
Do we have a way to inject into experimental pack?
wouldn't you just use optional tag values?
No the items are still there when the experimental datapack is off
You just don't want to include them in the tags then
right
Erm, this should be doable by adding a feature-flag sensitive datapack?
I think you could make a built-in datapack that would work with that with the current API; I'd have to test though
Neo could provide it own experimental pack which listens for winter drop flag (or any flag) and adds stuff to necessary tags, issue is the experiments screen enables via pack not via flag, so users would need to toggle on the vanilla winter drop pack + neos winter drop pack + any modders winter drop pack
Oh gah, you're right, it does work that way
Hrm. Can we make conditional stuff work with feature flags?
So you could then have conditional data based on which feature flags are enabled using normal neo data conditions
it should be possible to add a feature_flag condition but it won't work nicely with tag entries since those aren't conditional atm
That should be doable flags are loaded before conditions iirc so would be a simple condition which looks up enabled flags and validates them against a JSON list of flag ids
Luckily, anything can be conditional vai overlays
yes that can also work
accidentally opened the chest before they saved the structure nbt 
let's do a quick update to rc1
a few rejects; I'll have a look
probably just context differences
I expect one of the rejects to be the gui far plane stuff in GameRenderer#render() as the Z value changed again from 10k back to 11k
Yes
I think it makes more sense depend on the experimental datapack being enabled, not the feature flag. Because other things (like biomes) are only added by the datapack, so in theory the feature flag could be enabled without the biome existing.
That could be solved by optional entries then, but that doesn't seem like the cleanest solution.
Btw, as far as I can tell, we can remove the delta time patches for screen and overlay rendering in GameRenderer#render(). The associated Mojira ticket is marked as fixed and I can't find any visual differences between vanilla and our patch
We also need to fix the test world / mods button overlap. Conditionally shrinking the mods button (potentially even to a third instead of half the window size) and putting it next to the test world button seems like the best option to me since putting them above one another causes the options and quit buttons to go partially outside the window
Yeah that seems good to me
I'd replace the "else" branch of the ternary with (this.level().getBlockEntity(this.blockPos) instanceof BeehiveBlockEntity hive ? hive : null)
ok
so our previous patch (pre1) was wrong
10k - far plane is -11k
Yeah, the far plane computation wasn't adapted to take the -1k into account
Yup
I already went through this diff and fixed a bunch of stuff (some lambda parameters changed 😭)
I need to fix this one still
The diff looks fine to me, this ^ is the only thing that stood out to me as well

I think they removed the parameter
pushed to main repo
👌
oh god the PRs targeting port/1.21.2 are kinda screwed 😅
I saw your PRs but unless you say you need careful reviews just merge them when ready
Oof, yeah, those are kinda toast 😅 Nothing a force push can't fix though 😄
The main one I'd like reviews on is the frame graph setup event one, the rest is trivial
maybe a job for shartte
Heh
Finally done with a complete sweep over all the patch changes in the porting PR. A couple things that still need looking into:
- The
PanoramaRendereruses render types now, need to check whether the explicit disabling of the depth test is still necessary - The
EquipmentLayerRendererneeds to have #1541 re-implemented if possible - The
AbstractVillagerhas an odd patch (not a new one from this update) that makes no sense to me: https://github.com/neoforged/NeoForge/blob/f08da3eb01dc79fde0fc10999cfb1ffe9b0068e9/patches/net/minecraft/world/entity/npc/AbstractVillager.java.patch#L15-L21 - The
ReloadableServerRegistries/SimpleJsonResourceReloadListener/LootDataTypetrio needs a good look with respect to conditional codecs as both the second and the third apply conditions at the moment
Loot shouldn't use the json reloader as of a few releases ago
ah no, it goes through SimpleJsonResourceReloadListener.scanDirectory now
you're right, it looks like the condition handling might be duplicated
Can someone make the default branch of kits the one currently being worked on for release? It makes it easier to search things for the documentation
done, Kits branch changed to 1.21.2-rc1
FYI to all, pls ping me or an org admin whenever the Kits branch needs to be changed
I'd like some opinions on https://github.com/neoforged/NeoForge/pull/1598: I'm not familiar enough with the framegraph approach to be sure whether these events are actually useful for adding custom passes or whether it would be better to just have the current pre event (primarily for the entity outline post-processing) and then having people mixin between vanilla passes to add their custom ones (I'm not sure adding an event after every vanilla pass for that is a good idea)
Okay three more sections to go of the docs. Also the three sections that changed the most but, eh
Will probably hold off on recipes a bit though until it's been updated here
That's going to be a fun PR to review when you're done 😅
Yep. Writing the primer does help sometime
Not so much for figuring out what neoforge did :p
Heh 😄
As for the framegraph stuff, I think probably the best use would be to have a mixin that makes it easier to obtain the FrameGraphBuilder for other mixins
Since it really depends on the modder to see where they want to add their targets
The pre event is mostly useful for registering the internal and external resources along with the post chain frames, but that could also be done at any time as that purely depends on when it needs to be set
The graph builder is trivial to obtain in a mixin, it's unique in that entire method and can just be captured with MixinExtra's @Local
Ah, I thought you had to either capture all locals or none at all
In vanilla mixin you have to capture all locals until and including the one you need. With ME you can just target exactly what you need
Then, I don't see much point in the event in general unless we wanted to help modders enforce some sort of pass order
Only thing I could think of is to register the resource handles they need once, but even then, most people who would be mixining here should know how to do that
To be fair, the primary reason why I want an event there is the entity outline post-processing stuff since enabling it has to be done in a short window around where that PR adds the pre event
Is there even a benefit to using the passes outside Fabulous?
Technically, that's what the post effects also uses, so yes
I feel like I might be misunderstanding what you mean by outline the post-processing stuff here. Like are you talking about forcing the frame pass even when there are no entities to show the outlines or vice versa?
As far as I understand it, the frame graph does some optimizations to resource acquisition and allocation (from a bit of research that at least that seems to be the primary idea behind it), so more specific passes should be more efficient with respect to resources.
Forcing the outline post-processing effect even when there are no entities using it to allow using it in BERs and any other non-entity renderers that run during the main pass
Ah gotcha
But in that case, it would make more sense to modify the LevelRenderer#collectVisibleEntities method in some way to do that
Resources are just framebuffers though, right?
Primarily, yes, but some of them are so-called "internal" resources which are only relevant in a certain window spanning a given set of passes. The blog post I read about framegraphs explained that it for example allows re-using the same memory for two internal resources as long as the "usage window" of these two resources doesn't overlap. I'm not sure whether Minecraft actually makes use of such optimizations though
There is none, the cache is now initialized exactly once
Nothing has since 1.16
I think this only makes use of it for the post chains when dealing with multiple passes. I don't see how its handled in other places unless in fabulous for the render targets
we need to init it for newly registered blocks at some point
but we do not need to reinitialize it on each sync
ah I see
not sure what hook is appropriate for that
that's already the case atm
I think it's mimicking Mojang doing that themselves at some point?
Let me pull up 1.16
Even in 1.21.1 they resolved the loot table eagerly
weird
They stopped doing this in 1.21.2
indeed
Yeah, the loot table ID is now computed in the BlockBehaviour constructor
didn't we have a supplier for the loottable at some point?
We did
That means we need to do Jira and fill out tickets that we link to PRs!
OK I'll remove the getLootTable call tomorrow
Sky rendering seems broken with NeoForge (port/1.21.2) (fyi)
pretty sure the neoforge 1.21.2 port doesn't exist yet
It's right here: https://github.com/neoforged/NeoForge/pull/1590
Screenshots or it didn't happen
the transition is not smooth
Comparison?
Ah, the no interpolation between timesteps
Definitely had to rewatch that a few times
I feel like this could’ve be better described initially than just sky broken
My best guess without delving too deep is something to do with the ignore meLevel#advanceDaytime patch
I found the issue, the custom time sync didn't tell the client whether it should tick time or not
Ah okay
@toxic river the latest commit should fix it
can you please stop doing that, ever?
the thing where you say "x is broken" or "is x broken"
be specific
An image would also be useful
I don’t know what “this” is
I don't see any armor on the horses
wolf*
wolfs aren't horses
I don't think it's broken
Are you sure? /j
If there's no dyeable tag, it should come out as black
that's wrong
is this a new world or an old world that you loaded in 1.21.2
by default wolf armor isn't black, it has an armadillo pattern
almost 100% sure
yeah it should be looking like this
oh
i'm stupid
Ok, I think I found the issue
Getting the default dyed color doesn't check the component, so it returns the overlay color as an opaque black
This should return 0 if DataComponents.DYED_COLOR is not present
Vanilla still uses the opaque if the component is present
See DyedItemColor#getOrDefault
Oh i see
The wrapper
Yup
Got it now
I'm gonna put this in a local branch for later, the equipment rendering still needs some work anyway, so I can just combine that
I wonder if we could use the testframework in some manner during the porting process to ensure that things we expect to line up do line up and we just keep adding to it whenever we find misaligned patches or issues
We could, at least for some issues. I don't think this armor tinting issue is realistically testable though, unless we go to the effort of booting up a client in CI and then compare screenshots
I was thinking more we replicate the logic and read the values returned by the method, but fair
I don't think writing tests for individual methods like this is maintainable
Fair
Vanilla
The only way I could think of doing the screenshot is to basically spawn an nbt environment with the entities and the data, position the player at a certain location for both, and then check
No idea if MC is deterministic enough for that though
Well, it's not really broken, it just uses a unique randomization for all the blocks.
Re-implemented the ability to prevent effects from being removed by milk and totems: https://github.com/neoforged/NeoForge/pull/1603.
@red jungle you're a bit more well-versed on holder sets, let me know whether that lazy named holder set hack is fine.
@sand raven you were one of the people using this feature, let me know whether this is sufficient for your use case
What is happening here?
Did y'all already start working on neo? Or is this just the decomp-recomp stuff?
As long as I can make my effect not removable by milk
Probably is this: https://github.com/neoforged/Kits/blob/9490295fb5400d4143000e5753325147f5646fc1/patches/net/minecraft/client/resources/model/MultiPartBakedModel.java.patch#L49-L51
As a new random source is created each time and not passing in the one provided
It'd probably be fine if it was using the correct parameter j and not k
You would just add the effect to the respective tag like the test does: https://github.com/neoforged/NeoForge/pull/1603/files#diff-c1ad2efa96934e07e1f46e58084728b87499b51cc0c05e04166358a4efb70cfe
Yup, that's the issue. It should just use the incoming random source that is re-seeded on line 50
What happened to ElementsModel? It seems to have been removed
Finally deleted because it was a pointless duplicate of vanilla's SimpleBakedModel. The loader's additional behaviors are handled in the BlockModel#bake() now. This is also why UnbakedGeometryHelper is considerably smaller now
Ah, did we incorporate some of the things from my codec-models experiment?
Fun fact, I think Mojang introduced a "bug" in their blockstate refactor that I fixed in FC a week ago. If someone manages to call BlockState#setValue with e.g. an int property and a bool value (and yes, this has happened), it will crash with a very nondescript class cast exception instead of the usual "that's not a valid value" message.
that seems like something we should patch
Idk if it's worth checking for heap pollution
setValue is generic, right? Right?
Yeah, it's generic, so adding a check effectively just boils down to checking for heap pollution, and there's a lot of other places heap pollution can happen
Would be nice to at least get the block name though, which I suspect the ClassCastException won't show
Fair
It might be best to wrap the code in a try-catch and rethrow it as a ReportedException with context
Water is not rendered behind smoke particles in Fast/Fancy mode
I had a weird client/server desynchronization bug, I couldn't break any block, no idea how to reproduce the bug
spawn protection?
Do we have a doc for the registry order of 1.21.2? If not, I'll quickly generate one
registry_order.json in neo generated resources no? or is that oudated for 21.2?
That would do it thanks
spearking of generated resources, someone make sure to run the data generators
I just realized it didn't matter anyway since we don't force the item properties into a supplier in DeferredRegister.Items
Already done, the PR publish wouldn't work otherwise
uh i assume junit tests are not supposed to be failing to compile
IngredientTests to be specific
...\NeoForge\1.21.2\tests\src\junit\java\net\neoforged\neoforge\unittest\IngredientTests.java:37: error: cannot find symbol
Assertions.assertThat(a.stacks()).allMatch(ingredient, "first ingredient");
^
symbol: method stacks()
location: variable a of type Ingredient
or is someone working on ingredient stuff still?
Ingredients are still WIP
ah ok, just the only compile error i got
was wondering if it slipped through the cracks unnoticed
I mean, you kinda can't not notice it, it shows up as a CI error on every PR 
interesting
Someone ping me once this is done so I can doc it up
I'll probably be busy the next few days just rewriting all the item docs
I don't think so, it works when I restart the game.
maybe the server thread froze/deadlocked 🤷♀️
Yeah, probably
Misapplied patch 
Yeah, I'll push in a second
The name tags above the players/entities are not rendered correctly.
(I increased the opacity to make the bug more visible)
Once again, what's the comparison?
[Jump to referenced message](#mojira message) in #mojira
I found the issue: our custom text render types (they allow enabling blur on text) didn't match the vanilla ones. This brings up two questions though:
- Wouldn't we be better off just patching that single line in
RenderTypedirectly instead of duplicating the render types entirely? - Considering that rendering in UIs is a lot more batched now, does the conditional filtering even still work properly? If I do
enableFilter(); drawText(); disableFilter();(pseudocode), then the text will very likely not have blur applied becausedrawText()doesn't flush the buffer
Yeah, that doesn't sound right, the blur version needs to be its own render type as it has separate state
Yeah, that'd be the real solution. Bit of a pain, but doable. The only question is where to put the flag. I don't really want to patch all text rendering methods in Font and GuiGraphics, so the only option I can think of is to add a "semi-global" flag to Font, which would be safe since it would be used immediately to retrieve the render type in Font.StringRenderOutput
Also, I have noticed that in some rare cases, the BE are not rendered.
Screenshots with comparisons or it didn't happen. How many times do we have to tell you that??
Screenshot it next time you encounter it. As it stands, there is nothing for me to go off of and I'm not gonna go hunt a needle in a haystack
Any specific BEs in particular? If I had to go out on a limb and guess, it is probably something related to global BEs or the BE culling, so being close to them and at weird camera angles might be how you try to reproduce it for a picture lolo
It seems to affect the chests and pistons, I don't know about the other BEs.
like this
Here, the piston head is not rendered.
What does the render bounds debug renderer show for that piston?
nothing
Hmm, I'll have to look into that later
Ok, the fact that there are no render bounds is correct, the piston renderer uses infinite bounds
Ok, I have basically decided to write three new pages for the item docs since they've pretty much changed and need to be broken up into their own separate section
So woo!
And agh too
Doesn't look amazing, but the improved approach works and in an actual use case it serves its purpose (the artifacts have always existed, that's not new)
This should be better: https://github.com/neoforged/NeoForge/pull/1604
That is a really large patch for something I'm not even sure anyone is using....
I know that @dusty egret is using it somewhere
To be fair, I would also prefer a cleaner solution (especially visually), but I'm not sure there is any other way to achieve this due to fonts also using an atlas
Agree with better solution, if there would be any, but atlas has terrible resolution and AA is not even implemented, AA/multisampling can be somewhat simulated via fragment shader but hell no.. we're using it to rendering in zoomed environment where for small zooming levels (that have non-integer value) the text become pain to see/read, with filtering it's just 50% pain
@round perch btw in terms of breaking changes, could the public static flag stay in the same class?
I hadn't noticed the failing test
I'll fix it later
I'm still trying to find a way to reproduce this bug xd
I would prefer to not keep the flag in a barely related place, Font is a much better place for it since that's where it's used
um...
I don't know if it works, I tried to make a world to reproduce the bug.
Ok... Vanilla bug
@final sky should I finish the fluid ingredients?
uhh let me check i have nothing left unpushed
alright yeah, feel free to finish them
they still need additional tests for network serialisation imo
and idk if you've made a stacked SlotDisplay for SizedIngredient yet
but if so we need one for FI as well
I haven't and just removed the stacks() method
yeah maybe
I just want to make sure we don't add things prematurely in the porting rush
that said i don't think they need to be cached anymore right?
the displays
since vanilla also just creates and discards them
i think i actually had the 15 minutes to go and do most of what i had to do
also, does anyone know of a codec that always errors
i wonder if that already exists
(mostly docs)
the only thing coming to mind is the conditional codec
but that also only errors of ops.compressMaps is true
From a quick look, MapCodec.of(Encoder.error(""), Decoder.error("")) should do the trick
oh Encoder.error exists?
damn
wait no that won't work
MapCodec needs a MapEncoder
and that doesn't have an error method
do you want a codec or a mapcodec
MapCodec specifically
we can use assumeMapUnsafe here
anyways i think only what i said above now that i look at it again
^
this and moving things to unit tests was about it for my work iirc
and sized slot displays, which can be in a later PR
public static <T> MapCodec<T> error() {
return MapCodec.unit(0).flatXmap(x -> DataResult.error(() -> "error"), x -> DataResult.error(() -> "error"));
}
i just did this tbh
MapCodec<SimpleFluidIngredient> erroringMapCodec = new MapCodec<>() {
@Override
public <T> Stream<T> keys(DynamicOps<T> dynamicOps) {
return Stream.empty();
}
@Override
public <T> DataResult<SimpleFluidIngredient> decode(DynamicOps<T> ops, MapLike<T> mapLike) {
return DataResult.error(() -> "Simple fluid ingredients cannot be decoded using map syntax!");
}
@Override
public <T> RecordBuilder<T> encode(SimpleFluidIngredient ingredient, DynamicOps<T> ops, RecordBuilder<T> builder) {
return builder.withErrorsFrom(DataResult.error(() -> "Simple fluid ingredients cannot be encoded using map syntax! Please use vanilla syntax (namespaced:item or #tag) instead!"));
}
};
I think I'll just keep that 🤷
adding this:
/**
* Base fluid stack contents factory: directly returns the stacks.
*
* <p>Fluid equivalent of {@link SlotDisplay.ItemStackContentsFactory}.
*/
public class FluidStackContentsFactory implements ForFluidStacks<FluidStack> {
public static final FluidStackContentsFactory INSTANCE = new FluidStackContentsFactory();
@Override
public FluidStack forStack(FluidStack fluid) {
return fluid;
}
}
for "symmetry" with items
I went through the PR and I think we're good enough for a first pass tbh
one thing we definitely need to solve is how to do
- stacking slot displays
- with tags
- without losing the tag information in the SlotDisplay
if there's a bug in some stream codec it will be found soon enough
wdym "losing the tag information"?
I'm more concerned about losing remainder info
I think this is just a vanilla problem in general, unsure how we'll address it
(and to what extent)
that is true, i think the slot displays may need a second pass in future versions
that said, the tag slot display explicitly contains the tag key used
including when sent over network
especially for vanilla recipes; modders can always make their own displays to pass more info
which would mean no more guessing games for recipe viewers
yeah that's very nice
i'll just err on the side of caution and say all recipe viewers :p
i wonder if displays should be like... decorators almost?
so you can only ever add information on top
(or unwrap to a lower level with less information)
welp, not like that's for us to figure out, that's for mojang to think over 
forwarding to an inner display for unknown factories is quite easy
I pushed a fix for IngredientTests, now all PRs should pass CI
(once that is merged in of course)
@final sky why is there still a TagFluidIngredient?
wait nevermind
I am on the wrong branch 
niiice
love that FML bump 😄
tsss max using random values in a test

randoms in tests are good for one thing and one thing specifically -- making a value that deliberately should never matter :p
hmm rc2 tomorrow?


maty
