#1.20.5/6 Snapshots
1 messages Β· Page 5 of 1
We don't currently fix either of those bugs - We did briefly before some pvp client weirdos came and complained it was cheating
oh
some pvp client weirdos?
They can't just modify the attribute in the client with a mod?
They could, the vanilla server validates the range as if the bug was fixed but the client doesn't permit it by default
but idk
Mojang could simply fix this bug...
Maybe those pvp client people could stop cheatingβ¦ oops, I mean βusing quality of life toolsβ
is it snapshot day?
tomorrow
Heads up for today so you don't get a tennis elbow pressing F5 - the Minecraft snapshot is scheduled for Thursday this week!
pre1?
he doesn't say that 
pre-pre-1
it is a funny way to say "No snapshot today, we hope to release it tomorrow instead"
yeah...
I don't think it will be a pre
at what point do we just add a Tweet bot in this thread solely for slicedlime 
idk if that is possible for free
then the answer is simple: to the fediverse we go! https://mastodon.gamedev.place/@slicedlime
well zapier has no direct triggers for either mastodon or twitter (both need another application) and sending a webhook is a premium feature (they have a direct message to channel action tho)
he's also on bluesky
Heads up for today so you don't get a tennis elbow pressing F5 - the Minecraft snapshot is scheduled for Thursday this week!
no idea what kind of API bsky has
made by @fierce niche
well I wanted to not use another bot
make a server, that creates a webhook 
meh, the more the merrier or whatever
next order of business: getting actions to run on the snapshot branch
the easiest (but not ideal) way would be to open a draft PR against 1.20.x
that would also setup PR publishing and therefore publishing of the snapshots hehe
@elder swallow I wonder - would it be better to use the last commit's time as the timestamp, rather than the current system time?
otherwise it seems I'll have to write some cursed logic in my CI to detect what version got published to maven local
is this available to use in mods? this helps port mods easier as well
https://neoforged.net/news/neoforge-snapshots/
As of this post, these versions must be built manually. They are not available from our installer or our Maven repository.
not necessarily a fan of that
If you know what your doing then yes, it's possible, but also as the blog post said, you shouldn't be releasing versions of mods for this
do you have a better solution in mind?
as usual, what are you trying to do in the first place π
you could just publish a version to a snapshot maven of yours and reference that
have my mod's CI compile the snapshot version, publish to maven local, and then compile the mod against it
I do not have a maven I can use to host Neo snapshot builds myself, so the CI needs to rebuild it each time
another potential solution is that we publish these builds to our snapshot maven
smh pr publishing is a smart idea that wouldn't involve whole new infra
does the "pr maven" remain up forever?
mhhm
(i.e. if I close the PR does it stay there)
mhhm
indeed
Mojang seems to have started fixing regressions from previous snapshots, so probably the pre-release phase is coming soon.
not really?
there is no indication to that
just that they moved the snapshot to tomorrow
By "soon" I mean in a few weeks.
tbh they are "late" already
can't be much longer until 1.20.5, if they still plan on releasing 1.21 in late june
I mean...
maybe
just maybe
they have been working on 1.21 for a good while now
but. they have different people fixing up 1.20.5
meaning that the nbt changes and such, were done to prep us for 1.21
and then drop the nuke 
Is the port/24w10a branch supposed to be buildable?
yes
RegistryOps<JsonElement> registryops = net.neoforged.neoforge.common.conditions.ConditionalOps.create(RegistryOps.create(JsonOps.INSTANCE, p_321612_), net.neoforged.neoforge.common.conditions.ICondition.IContext.TAGS_INVALID);
^
method RegistryOps.<T#1>create(DynamicOps<T#1>,Provider) is not applicable
(cannot infer type-variable(s) T#1,T#2
(argument mismatch; IContext cannot be converted to Provider))
method RegistryOps.<T#2>create(DynamicOps<T#2>,RegistryInfoLookup) is not applicable
(cannot infer type-variable(s) T#2,T#2
(argument mismatch; IContext cannot be converted to RegistryInfoLookup))
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>create(DynamicOps<T#1>,Provider)
T#2 extends Object declared in method <T#2>create(DynamicOps<T#2>,RegistryInfoLookup)
/mnt/76561DD3561D94C9/NeoForge 24w10a/NeoForge/projects/neoforge/src/main/java/net/minecraft/world/level/biome/BiomeSpecialEffects.java:231: warning: [removal] BIOME_INFO_NOISE in Biome has been deprecated and marked for removal
double d0 = Biome.BIOME_INFO_NOISE.getValue(p_48097_ * 0.0225, p_48098_ * 0.0225, false);
why this?
Eclipse?
OH
smhmh
#project-talk message
[Reference to](#project-talk message) #project-talk [β€ ](#project-talk message)a bit scary hehe
well easy fix in the end π
/neoforge debug_blockentity_renderbounds true is broken
also, is this normal?
[18:31:51] [Render thread/WARN] [minecraft/ClientPacketListener]: Entity Skeleton['Skeleton'/12843, l='ClientLevel', x=-60.50, y=-15.00, z=44.50] does not have attribute neoforge:swim_speed
[18:31:52] [Render thread/WARN] [minecraft/ClientPacketListener]: Entity Zombie['Zombie'/13111, l='ClientLevel', x=111.50, y=-1.00, z=37.30] does not have attribute neoforge:swim_speed
[18:31:52] [Render thread/WARN] [minecraft/ClientPacketListener]: Entity Bat['Bat'/12753, l='ClientLevel', x=10.75, y=32.69, z=96.25] does not have attribute neoforge:swim_speed
[18:31:52] [Render thread/WARN] [minecraft/ClientPacketListener]: Entity Bat['Bat'/12672, l='ClientLevel', x=19.72, y=-16.92, z=11.54] does not have attribute neoforge:swim_speed
[18:31:52] [Render thread/WARN] [minecraft/ClientPacketListener]: Entity Drowned['Drowned'/13218, l='ClientLevel', x=18.50, y=35.00, z=-42.50] does not have attribute neoforge:swim_speed
[18:31:58] [Server thread/INFO] [minecraft/IntegratedServer]: Saving and pausing game...
The render bounds debug renderer is my fault. I misinterpreted how the model view matrix passed around in level rendering relates to the PoseStack used by consumers of the various events fired from level rendering. I'll push a fix for that later
π that's a thing? I'll need to use that
what is /spawn_armor_trims?
spawns armor stands with all armor trims
similar to how the debug world has all blockstates
it's neoforge only?
no, that vanilla, but dev only
oh
It should be on all NeoForge dev envs, because NF enables the Vanilla dev flag in dev
The best issue tracker is called Discord (forums > GitHub)
wait there was a corresponding vanilla bug and scenario it could occur?
I didn't even realize that it was possible in vanilla when making that
vanilla's new gui stuff doesn't fix that yet?
nope
surprising
Another bug in the port: there seems to be weird desynchronization when the player places a block.
can you be more specific
Well, sometimes when I place a block, the client behaves as if the block was never placed (no hand animation, no sound), but the server places the block.
like this
idk if it's a Vanilla bug, or NeoForge bug
This happens when the client believes a block placement is invalid
The client always sends the click packet regardless of if it thinks the placement is valid
But if the placement is valid here, I'd say it's a Neo bug that the client thinks it's invalid
Created Gist at the request of @stiff galleon: https://gist.github.com/NeoCamelot/7d8bda7bf60ca559766a4d447e7ba273
not this shit again ```
java.lang.NullPointerException: Cannot invoke "net.minecraft.world.entity.EntityDimensions.eyeHeight()" because the return value of "net.minecraft.world.entity.Entity.getDimensions(net.minecraft.world.entity.Pose)" is null
can we just remove the size events/stuff and direct people to using the attribute that mojang is adding?
my guess is it would fix that null pointer commoble linked
and presumably cover all use cases?
Yeah we should just axe it
I have always been a proponent of removing old features that don't quite make sense in the new version, and then adding something back if people still have a need of it
any reason the background panorama speeds up when in the mods menu?
or is just an optical illusion and isnt actually speeding, just seeing less so it looks sped up
not optical illusion
I'm going to guess some patch duplicated a method call
and it's incrementing something twice
The ScrollPanel class currently renders the default background texture only if a world isn't loaded but renders a custom gradient if a world is loaded
is the port/24w10a branch supposed to work in userdev when published locally?
i mean i am able to setup a workspace with it and compile my mode against it
but when i try launch the client in intellij or gradlew runClient in cmd, it crashes saying some log4j method could not be found
java.lang.NoSuchMethodError: 'java.lang.Object org.apache.logging.log4j.util.LoaderUtil.newCheckedInstanceOfProperty(java.lang.String, java.lang.Class, java.util.function.Supplier)'
whats weird though, if i use WSL (ubuntu) and run the same command gradlew runClient, the game launches fine and loads my mod
It's supposed to work in userdev but I haven't tried it π
I might try later today
should we throw in-dev if FluidStack.equals is called?
I am asking because FluidStack does not implement equals at all anymore
Is there a snapshot today?
Ok
I see the point in throwing because people may expect .equals() to continue working, but I really really hate that this means anyone who understands .equals is a by-reference comparison is also prevented from using the class in a set unless they explicitly use an identity-based set instead of a "standard" one
It is probaby the correct thing to do regardless, I just don't like it :p
I just realised that the background for the mod list screen is currently being rendered 3 times for 1 frame
looks better now, imho
Nice
and a repost in #squirrels-π¦ too 
smh people it's not that hard.
if it talks about minecraft, #general
if it isnt' even about minecraft, #squirrels-π¦
only if it's specifically about 1.20.5 snapshots as related to the changes mojang made and how they will affect the porting effort, it should be here
well let's go for it - happy to reconsider π
that would explain why it moves too fast -- it's updating 3 times each tick :P
thoughts?
hm what's the reason for skipping validation in records?
they always override equals and hashcode
oh right
it's just to make sure that you don't use e.g. a fluid stack as a component
WHICH I DID like an idiot
oops
would there be a point of calling getMethod in line so that the || short-circuits the second getMethod call?
it should be slightly faster, but it's only in IDE so maybe it doesn't matter
https://twitter.com/Minecraft/status/1767564702333247862
This tweet got posted in the game announcements channel category in the official Minecraft discord server
There is no way to validate this otherwise?
not really, the registry is a Registry<DataComponentType<?>>
btw I just realized that DataComponentType is an interface not a class
I would rather flip the check on its head
which means that we can make our own extended type if we want to
if the equals and hashcode is not in the type of the component itself then it errors
we can't get the type class from a componenttype
I don't really want to have think of the case where somebody has some abstract class
Why not?
could use getDeclaredMethod there instead of getMethod
well it's correct as I wrote it
you can't instantiate an abstract class π
you can create subclasses though
and class X extends Y {} where Y implements equals & hashcode but X doesn't would still be problematic
getMethod walks the class hierarchy
No but you can put the equals and hashcode in it, while the underlying type that is instantiated adds more stuff
which is what Orion is concerned about
Correct
see this
yes but you check if it's declared in Object
that's why I check for method.getDeclaringClass() == Objects.class
Orion is suggesting we check it's declared in the actual type
method.getDeclaringClass() == clazz
and DISALLOW the case where X extends Y, and equals/hashcode is only declared in Y
Is basically what I am asking you to implement
aka, getDeclaredMethod()
well idk, there could be valid cases where a subclass doesn't need to override equals
the main goal here is to educate modders about the system
That same argument could be said for the Object case as well
if they go for more complex setups it's on them
What if a component does not need an equals or hashcode at all
Then the declaring class is object
the only case where that would make sense would be a singleton component
Which do exist
at which point you should probably ask yourself why not use a boolean π
I have singleton capabilities
Which represent pieces of logic
Markers
And are used to identify internal pieces of logically processed objects
My point is
components are data though, not logic
Either do it properly
And disallow them all
Or don't do the check
This really feels halfassed
no, it's just how I chose to do it π
both can work, but since we are adding checks I don't want to overdo it
Vanilla uses Unit.INSTANCE for singletons for components
Components are data holders!, They themselves are not data. They represent it. They can represent the piece of information that something is processed
Which can be a singleton
Or any other construct
You don't know
And assuming in an API that something is not possible is how we get into problems with API design
I would suggest to not do this check
it does
Or enforce it to be a record at all times (which is my preferred solution)
however that is an enum and should therefore implement equals π
I have to check
Or enforce the checks so that it is always in the leave
yeah it has an equals implementation in Enum.class
You are adding this check, to ensure that people properly implement the equals and hashcode, so that comparisons are easier and better.
that doesn't work, vanilla uses non-records too and there's good reasons not to use them
that's probably not going to work for enums (such as Unit.INSTANCE)
because Enum has a final equals method
Can enums be used as components here?
yes
why?
Because the API allows Object
Yeah and I can pass new Object()
And your system will fail
Even though it is allowed to be used as a data component
and in doing so you will break copying and comparisons
which is the entire reason why there is a check in the first place
Why?
because when you copy a stack, the components are shallow-copied
well it's way more performant π
Yes but it makes 0 sense
that's why they also have to be immutable (which we sadly can't check)
Because previously it was a deep copy, due to the nature of NBT
this is really nice, it makes stack copies a lot cheaper
Yeah and a lot more dangerous as the same time
I understand your issue here...
That is a pickle for sure
this is also one of the reasons why we can't just blindly replace attachments by components in BEs, entities, etc
I would have expected these things to have a codec attached
So that you can clone them efficiently
And properly
it's quite rare to be changing the data inside of a stack after all
It is also a lot more dangerous
Not really
A lot of people mutate data in a stack
yes but there are orders of magnitude more item transfers where stacks are frequently copied
For example tools, based on energy
Or or backpacks
Or magnets which are toggleable
all of that stuff is player-triggered and therefore only happens comparatively rarely
I would say that entirely depends on your context
eh. if the data component API essentially requires (deep) immutability (even if we don't see that specific code statement), it is fine to rely on that immutability to avoid costs in copy operations
and it seems Mojang went that way
Yeah but they don't
The API does not enforce it
A good start would have been to make the components Records
That would at least ensure base type immutability
it's why Guava's ImmutableCollections recommend using the explicit immutable collection type (i.e. ImmutableList in place of List) in method parameters or return types if immutability is part of the contract
Yes
But the point still stands
The API clearly allows mutable objects
Just its sementical usage does not allow it
here is an example of a non-record component
Yeah but that is a completly mutable object
it's not mutable hehe
mutable in what sense?
It could have been a record
Well it is not mutable probably
But that is purely an implementation detail
they wanted to guard mutations on the underlying map I suppose
"immutable" is a separate concept from "being a record"
Because p_331044_ can still be mutated outside of teh scope
Even after a stack is cloned
records are by nature immutable at least on their field level
before records existed, we considered classes that had no setters or any way to change the fields of the object to be immutable
Yes to make something properly immutable, it needs immutable fields
No actually. Their are several books out there on this topic. And they specifically do not define that as Immutable.
And object is only truely immutable if it and its contents are not modifiable by external access to the references
Which is a different then having a setter or a getter
But that is besides the point
I guess tech is right
There is no really great solution here
I simplified my explanation -- I agree on that definition of immutability
And some guarding is better then none
But this really needs some very very very good documentation
From our end
but that does not refute the point that records are not the sole way to achieve immutability
because this is shoot yourself and the entire community in the foor territory
You are right, but in modern J17+ they are a very easy and good start to indicate that you want immutability in your semantical usage of the object
I assume the API on Mojang's end is documented adequately on its objects needing to be deeply immutable
and I assume Mojang have their reasons for not using records for data components
I'm planning to have it in the update blog post
maybe even in all caps
perhaps so they don't have to have boilerplate to the effect of DataComponentType<ItemDamage> and record ItemDamage(int damage) in multiple places
Yes
DO NOT MUTATE A DATA COMPONENT EVER EVER DO NOT PLEASE ARGHHHH THEY'RE COMING FOR YOU
If it were up to me, I would also log if a data component does not have an equals and hashcode in the concrete type in dev
Yes it is allowed and won't crash
(as in, having to surround anything that isn't a record which they wish to use as a component, into a record, and avoiding auto-boxing and more boilerplate)
but it is for me something really headscratching
well I suppose that a log isn't the end of the world
we can also exclude enums from the check
i.e.
-> no hashCode or equals at all -> crash
-> no hashCode or equals on the target class -> log
It not being a record, is then also an indication that maybe, maybe you did something wrong in your design.... But yeah wrong topc
Yes that would be my prefferred solution
ok that is fine by me as well
Where Enum is skipped just like Record
And we should write in the documentation that people should design their API around record
an indication, but not the sole one, and needs to be supported in context
And only in exceptional circumstances use a none record type
Obviously as discussed it is not a clean solution
But it helps to get started
Maybe also point to things like Immutable Collections from guava
And the like
[11:49:54] [pool-7-thread-1/WARN] [ne.ne.ne.co.CommonHooks/]: Data component class class java.util.ImmutableCollections$ListN does not override equals and hashCode. Make sure that they are correct. Keep in mind that they must also be immutable. lol
LOL
I don't know if there is a way to check for that
We should not log that for reasonable defaults
Where Record and Enum are probably a start
yeah that is the only log when initializing vanilla items atm
True
But I mean ImmutableCollections are also a reasonable object
Like Enum and Record
So them being there makes a reasonable amount of sense in my eyes
But that this thing does not in and of it self implement equals and hashcode, has me raising an eyebrow
well it extends from ImmutableCollections.AbstractImmutableList
Which probably implements it right?
You might want to check if the object extends AbstractImmutableCollection and also accept those, like Record and Enum
Or at least AbstractImmutableList
I don't think anybody is going to be so crazy to extend that
And then tack on data
these classes are jdk internal
the entire ImmutableCollections class is package private
mmmmm, API-impl isolation
Guava ImmutableLists have the same problem
but honestly: I think that we will catch most cases with the check against Object already
Fine
@elder swallow I don't have write access to the NeoForge repo so I had to pr it
no since I mainly work on NeoForm and help with snapshots
beautiful
we can either add you to the neoforge maintainers team or have you go through PRs
as you prefer
Wait, why does it print FluidStack as the problematic class?
because I did this...
Ah
which is wrong and exactly why we need that sort of check π
the question is now what to use for FluidStack components
personally I would love an immutable fluid stack class
π
I really don't like "Stack" for fluids :p
but π€·ββοΈ
do components need to be immutable, or even benefit from it?
I haven't looked at the code but I would assume most of them are mutable, thinking of like, Damage, Custom Name, etc.
the component object must be immutable
weird
if you need to change the damage you replace it with a new component object
so they are creating a whole new instance when the damage changes? that seems like a horrible design choice to me
what's the problem?
feels wrong
in exchange, stack copies become dirt cheap
this will massively improve the performance of IItemHandler et al
it probably isn't wrong, it just feels wrong
and yeah I suppose being able to copy the component references as-is is nice
is the component list itself immutable though?
or does copying a stack still make a copy of the list, just shallow copy
it makes a lazy copy of the component map
how cursed would this be? 
it would be the perfect return type of IFluidHandler.getFluidInTank
instead of SERIOUSLY: DO NOT MODIFY THE RETURNED FLUIDSTACK
since this does not exist for itemstack, very
we could consider a similar thing for item stacks
When building the initial components for items they also use an interner
yeah I patched in a check for the component class there
that would make us have to make it non final which will prompt people to do stupid things
and sealing classes is not supported by AT
It makes the api so much better to have these immutable
I would prefer having ItemStack, ItemStack.Mutable and ItemStack.Immutable tbh
or BaseItemStack (read-only), ItemStack (mutable) and ImmutableItemStack
it's just that you'll get a runtime crash if you try to mutate it
whereas with a different hierarchy you could express in the API whether the stack can be mutated or not
I will also note that it's super cheap to convert between mutable and immutable stacks since the entire DataComponentPatch can be shared thanks to lazy copies
instead of rejecting the immutable fluidstack on this basis, we should do the opposite and have an ImmutableItemStack :P
knows about a mod that makes ItemStack non-final
people should assume that itemstacks returned from stuff like getStackInSlot are immutable
and if anyone does mutate the stack, they will have to learn to fix that
wouldn't it be better to return a class or interface like ItemStackView directly
yeah of course
the main advantage of an immutable subclass is that you can pass it to any function that expects ItemStack
and vanilla has a ton of these
however vanilla also does stack mutation a lot and you might accidentally give an immutable stack and cause crashes down the line 
I hope that whatever we do mojang will copy the idea and fix their pervasive stack mutation
Enum?
I do not like that I see bedrock buttons....
Well presumably that is Bedrock Edition
Yeah, so they can take screenshots on whatever
Nah, they tweet things from both editions (they do push BE, just not here)
BE has more total players afaik
younger players too
1 to 2 hours until snapshot
only if you count all platforms, if you only count PC then java has more
mostly switch and xbox
yes but bedrock means all platforms 
they are doing it incrementally already
what about OpenGL upgrades, and a full render overhaul
and just give the finger to Apple?
won't happen because mac
read the message under that 
they will never do that and you know it
When does Mojang add En passant to Mc?!
yup but for the purposes of the social media based PR, all is what counts, and that tilts the balance hard toward bedrock
isn't damage just an int?
They're all records
damage is just an int
It's a record around an int, no?
Oh it is, interesting
which i mean. is not mutable. you can't call int i = stack.get(DAMAGE); and i++ and expect it to update in the component
yeah thankfully
imagine if numbers were by-reference
1 = 2; and now everyone referencing 1 gets the value of 2
Note: https://www.minecraft.net/en-us/article/minecraft-snapshot-24w11a (error 404 rn)
That's assuming it is a snapshot (probably) and not a pre release
Yeap
https://www.minecraft.net/en-us/article/minecraft-preview-1-20-80-22
This reveals some of the details, including both new items. ||We got a weapon finally||
is it out now?
No, the version manifest hasn't been updated
now?
Frogs are on their way soon - and come heavily armed today!
that's the new weapon yeah
the custom item predicate patch will need updating I guess ^^
maybe that fixes the blur idk
Question, can we make the Snapshot Alarm role selectable in id:customize?
I think it grants access to #wisdoms-private atm - be careful
but I'd generally agree
it does not, because I can't access that either
No, it should be a ping only role currently
This week we're expanding your arsenal with a smashing new weapon, the Mace! Use this weapon's special smash attack while leaping from a high place and watch your enemies get knocked back. The longer you fall, the harder you hit β but make sure you time it right! Your fall damage is only negated if you land the blow.
neat!
what channel would that be?
wisdoms
Go nuts with the role
It did originally give access to another channel
alr then I'll add it to the role selector
#maintainer-applications ??
I gave it to someone thinking it was solely a pingable role, but that was fixed rather quickly
It was either wisdoms or internaltalk
Remove embedded! He is a maintainer now
i used "view server as role" and i can see maintainer applications as snapshot alarm

Community Porter can be deleted as a whole
I wish they included pictures of the new stuff
huhhh i have a manual user override on that channel for some reason, so view server as role didn't work
Snowman available
Too much effort to go look at the new sherds and trims
@cloud raven if you're ok with it, I'm gonna delete Community Porter
USE_DEVONLY π
mmmm, BlockBox
Is that basically just BlockPos#betweenClosedStream(AABB) ?
looks like it, yeah
should I make an announcement for the snapshot alarm role being a public thing now?
entity variant as well?
yep
Likely, although may be better to ask in one of the -talk channels
how the heck do you use gitcraft. it keeps trying to get version metadata for a combat "snapshot" on some discord server
The problem with this is that the immutable must be the parent class, not the child, otherwise you will get untraceable crashes from people handing the subclass around
If we make FluidStack immutable and add FluidStack.Mutable it can work out
but its a big change for mods
In mekanism I call the following methods the given number of times:
FluidStack#setAmount: 3
FluidStack#grow: 6
FluidStack#shrink: 1
Granted some of that is that I have helpers for my tanks that call those, so then I basically can easily change the implementation detail
I'd rather make a completely separate thing since I want the abstraction to also work for items
It may be weird trying to solve it via wrapper when we have the authority to solve it properly for fluids
Well I value symmetry between fluid and item stacks more
what if the concrete class is mutable and the ['immutable'] fluidstack is an interface, same as how Component works
my role isn't special anymore :(
What the hell π
I have an idea but it will have to wait for tomorrow
Re the current snapshot, I don't see a reason to port to it. Best to focus on 24w10a for now
interesting
#builds message welp I'm gonna start on this (shouldn't be too bad, just a bunch of patch nuking)
[Jump to referenced message](#builds message) in #builds
24w11a-20240314.182754
1.20.5-dev
24w11a
I missed the earlier conversation, what if I want to use a Block as a component
blocks don't override equals/hashcode
Yeah, I disagree with the check. There are plenty of singletons that aren't enums
don't make me mixin into norge to disable stupid validation 
While the check is good in theory, there are a lot of objects that have (and should have) identity equals and hashCode
I agree with Commoble that the validation shouldn't exist. There are ways to get around it that aren't mixins, although they're silly.
For your own types, you can always override equals to implement reference equality, even if it's pointless. But it bypasses the validation. This doesn't help for Block, though, in which case, you can use this very silly wrapper:
record RefEq<T>(T t) {}
You can now store a RefEq<Block> as a component. Hence bypassing the validation, just with some extra pointless indirection. Mildly annoying.
We whitelist known singletons
?
I mean, the validation likely whitelists primitive type wrappers too π
what if I make my own singleton
If it's that important to you, the validation could come with an associated annotation to declare that you know what you are doing β’οΈ
or we could just not put the validation in
I don't get why neo would add validation like that. At most, add a jdoc that tells users to be mindful about it
I strongly disagree
The only "known singletons" whitelisted are records and enums, if the commit is to go by.
People will fuck this up in the common case
Not catching those common mistakes with validation
is just inviting pain and suffering
especially once they jarjar my lib that mixins out the validation 
If you have a smart "i know what I am doing" case for the non-common case, you gotta go the extra mile and declare your own downfall π
And people will be able to detect which mods are likely candidates for causing issues based on including it. Every one wins.
Debugging and finding which mod fucked this up in a large modpack is a nightmare
The check is disabled in production
So you really don't need to distribute shit
You just need to supply a proper equals and hashcode
So that everything works
no, that's stupid
why should a singleton override equals and hashcode
It is enforced by the design mojang makes!
Even mojangs singleton does it

Then, Orion, why would a data component of Block not work under mojang's design?
Because it requires a proper implementation of equals and hashcode for the patching system in data components and the copying of itemstacks to work
So if you want a Block
Then you need to wrap it in something
That does the equals and hashcode, based on for example the registry name of the block
Blocks should work fine since they are essentially singletons π€
Without the required equals and hashcode sadly
So they don't
using identity equals/hashCode is fine for them
well, no, I'd just override -- yeah that ^
Well yeah
That is domain knowledge, however
identity hashcode and super.equals
And in reality people can fuck this up so badly so quickly
That enforcing this (in dev only)
Is just a good idea
Even though I fully understands commobles position
As I said before I wanted it to be Records only....
So that it helps to indicate in the API that it should be immutable and comparable
But yeah
No dice
Because mojang decided it wanted things like tooltip logic, and Unit.INSTANCE
I can see the position of allowing known singletons explicitly, or declaring "yes I DECLARE this is guaranteed to be immutable"
But not "we should not have a validator"
Then is there any issue with attaching this, for example, as a component.
record Box(Block b) {}
Something like a marker interface right
That will work π
Because of the domain logic of how Blocks work
Basically they are instance specific (as in kind of singletons on their own right)
So, the only reason Block doesn't work by itself, is because NeoForge has a validation that prevents it. Not because it's mojang's design. Because it is otherwise a singleton.
Yes and no
Yes it would work without the check
But no it is kind of a bad idea, because it implicitly depends on the specific domain behaviour of Blocks/Items etc
The point of that check
Is that you make that domain behaviour explicitly known to the system
So that the semantical behaviour of that system is guaranteed
I mean our validator is in the domain. We can whitelist at the very least the known Minecraft singletons (Item, Block, BlockState(?)), I suppose
We could probably whitelist all registry types
is there a valid use case for wanting a block as a component though
And their subtypes
Probably?
Probably
I mean BlockItem?
fair enough
I see that really as a component for example in the future
There's a non-zero chance that mojang just makes one blockitem with a blockstate component in the future 
please no
unlikely since the item itself is a singleton too
Unlikely yeah
StateHolder > BlockState for this case
Yeah, those are explicitly compared with identity in many places
It'd be more a BlockItemType and the block items themselves defined in data
The fact of the matter is: we can iterate on this
But yeah, I'd say just whitelist all registry types and any other singletons (like StateHolder)
The current special cases do not need to be set in stone
We can start with what we have now
And if the community wants more types
It is just a couple of lines of code
And then it is releassed 2 days later
Done
Sooo did we get the obvious awesome new feature this time?
no, banana dog is still a myth
breeze rods?
the mace?
that's not exactly easy
We could just whitelist Holder and tell people to use that
fair
hmm now that we have the porting progress on main I can use the action to port to the next snapshot
Holder.Direct would like to have a word with you π
well, that's already a record and therefore whitelisted 
How did I miss that... 
No signature of method: java.lang.String.formatted() is applicable for argument types: (String, String, String) values: [20.5, 24w10a, 20240314.204139]
Possible solutions: format(java.lang.String, [Ljava.lang.Object;), format(java.util.Locale, java.lang.String, [Ljava.lang.Object;)
I don't think it does in 1.20.4
It's also a record in 1.20.4. I was looking at 24w10a sources at that moment anyway though
you can fix it too, it's easy
well then what do you think you ought to do
maty you broke it you fix it (you can even use the web editor)
I didn't remember that Direct was a record. I also don't think I've ever used Direct
(except indirectly with playsound)
no I can't use the web editor on mobile so unless you feel like waiting 14 hours to get it fixed you're going to do it yourself
Β―_(γ)_/Β―
what did you even break?
nothing lol
more like what did tech break https://github.com/neoforged/NeoForge/blob/port%2F24w10a/build.gradle#L18
to make the buildscript incompatible with j8
did he actually use string.formatted in a language with interpolation....
damn it tech smh
and the mix of gstring and string... ew
@elder swallow ^
J8 Compat is not relevant
Due to the use of spotless NF Development we need J17 as far as I understand it
well that workflow doesn't have J17 and it worked when starting this snapshot cycle
it needs 11
formatted is a java 15 thing
but also groovy has string interpolation lol
I don't think it uses J8 (probably J11)
Hmm
if it needs 11 just bump it to 17 then
That is kind of my point
Block components are useful
However we also need some form of checking
Potentially we can add a hook for modders to say "this class is a singleton and therefore acceptable"
E.g. CommonHooks.markComponentTypeAsValid(clazz)
the workflow currently does not define a java version but uses the one groovy comes with
12 reject files
https://github.com/actions/runner-images/blob/releases/ubuntu22/20240310/images/ubuntu/Ubuntu2204-Readme.md
Java 11 is the default java version installed on github-hosted runners
we have another case of the patcher putting the class header after a constant

Noticed LocalPlayer localplayer = this.minecraft.player; on the on the last line of an if statement
Seems like it wasn't a decompiler error
do we still need PotionColorCalculationEvent? or can I nuke the patch in LivingEntity (it now works with a List<ParticleOptions>)
ok, only client and networking left
3 rejects left
I just went over all of vanilla's data component types and we do in fact need to whitelist Holder because it's used for instruments (the goat horn), otherwise you can't even get into the creative inventory. I added Holder.class.isAssignableFrom(clazz) locally to fix that
what if someone makes a nonsense Holder implementation to skirt restrictions 
@KeyFor? 
why is the checkerframework in my project libs
I thought about annotations but that would limit it to your own types. Maybe both, though? π€
such a developer could also implement a contractually incorrect equals and hashCode, so it's not a concern
why are we restricting what types people are allowed to use as components if Mojang doesn't
β¨ validation β¨
So people who don't read jdocs or those who are ignorant to proper implementations are forced to at least try not to screw it up
not again
eh, i don't like it
Mojang probably doesn't need to
Mojang doesnt make stuff so that modders will use it, its just a happy accident that we exist, or atleast that is prob what Mojang thinks.
Does DeferredHolder even implement equals and hashCode properly?
For applying damage from the mace from falling it checks if the player is holding the mace in Player.attack
ToolAction time?
nah most of mojang these days are former modders, they just can't justify new features/designs based on modding, so they have to find excuses to do so while giving things a vanilla purpose
Well, if something benefits modding it often benefits minecraft itself as well
Since we generally want stuff to be more flexible;)
Yep
I'm not sure, I don't think I was around to review the retargetted PR to 20.2
It should just defer the equals/hashcode to the underlying resourcekey
That's probably gonna break symmetry of equals if Holder doesn't implement it correctly itself
So e.g. a stack with a normal Holder might not stack with a stack with a corresponding DH
should direct holders try to find the object in the registry, then?
I have a removal of ICustomItemPredicate locally along with moving the current neoforge item predicates to mojang's item sub predicate system
or maybe direct holders are just always unequal to reference holders
Probably. I'm pretty sure the only real use of direct holders is during worldgen data load
Also this is the registry value of mojang's item sub predicate registry: public static record Type<T extends ItemSubPredicate>(Codec<T> codec)
we can probably add default impl on holder - kind() to determine reference vs direct, and i assume deferred holders are considered reference holders
Weird. Wonder why its not just a straight codec registry
how many holder subtypes are there
just direct, vanilla reference, and deferred?
not too bad i guess
sounds good
should I squash the 24w11a port and push it to the main repo?
yea remove sources and squash
ok
I just found out that they implemented the same system for entity predicates
yep
coeh are you taking care of the item and entity predicate removal?
ok yeah Holders don't implement equals and/or hashcode
and DH.equals(normal holder) will return false
is there anything that would break if we add it? [anything storing them in maps that assume identity equals]
the patch for item predicate is gone already
yeah but we need to also remove the patch for entity predicates, remove our custom related classes, update our tool action predicate, and re-run datagen to update the loot tables
I suppose that we don't have the choice anyway
I can add a test for it too
i mean we could simply not
yeah that means that stacks that contain a deferred holder will not stack with stacks that contain a normal holder
that is unacceptable
....oh, are components compared by equality?
yes
i thought this was just about restricting allowed types
that is the entire reason why we check for equals and hash code
we're not in the business of adding arbitrary restrictions
but in this case it is far from arbitrary
is there a way to, like, have some mechanism to lookup a comparison provider? that'd also let us fall back on serialization
I don't see why we'd do that
it's a step backwards compared to mojang's current design
hmm... vanilla reference holders are interned anyway right? so there shouldn't be any impact to implementing it on them and on DH [do we want/need to touch direct holders?]
oh god, are there non-synchronized data component types in vanilla
we potentially need to check that else the creative inventory will nuke them
(I get capability flashbacks already)
there's what now
I would just go ping boq or smth lmao
That will cause vanilla bugs
mojang really needs to fix their creative mode lol
well no
they are potentially planning on adding components to non-itemstacks too
OK nevermind
it defaults to the regular codec if no stream codec is provided
that's good considering how the creative menu works
but it's really annoying we can't have server-only data in the stack
so much unnecessary synchronization
The entire creative menu is fucked ye
server only data would be great if it wasn't so weird
pretty sure its notchcode still
well it's great for mods that stacks are the same on the client side
e.g. "drag filter from JEI" can't work well if the client doesn't see the full stack
Usually the only data you would hide would be like backpack contents or other bulky data
i'm not sure it's really worth supporting
backpacks that support 27 slots or less aren't going to be any bulkier than shulker boxes, those that support more should arguably implement their own off-stack system
its less of an issue now, especially with the packet splitter in place
Turns out when specifying a sub predicate for entities the predicate becomes
"predicate": {
"type_specific": {
"type": "neoforge:piglin_neutral_armor"
}
}
for items its
"item": {
"predicates": {
"neoforge:piglin_currency": {}
}
}
that is odd
adding this
did you add that somewhere? cause I can enter the creative inventory just fine locally
is there a reason not to allow adding classes that are otherwise valid?
that's what this method is for
i am asking why the throws
cause that probably means that someone doesn't know what they're doing
it's annoying to have to change if refactoring a type that previously wasn't a record into one
idk, i guess it's not a big deal, i just don't see the harm either way
Yeah because you brick the system otherwise.
The need for equals, hashcode and immutability is semantically defined in the component system. There is no syntactical requirement for it.
However to prevent you from shooting yourself in the food and everybody else in the room in the head when you process an itemstack, we enforce this requirement to prevent this mistake
right but i assume this enforcement is done by doing, like, "if(set.contains(clazz) || expensive_reflection_checks(clazz))"
what is wrong with adding classes that would pass the checks to the set
why would you call the method in the first place if your classes already pass the check?
there is no reason to call markComponentClassAsValid if the class is already valid
refactoring, i'm mainly curious about what Orion is saying and I think he misunderstood my question
if you refactor it will be trivial for you to fix the test
in fact, being able to remove the check would be a good reason to refactor to a record
No i did not....
Given class A, already existing, you asked me for a reason as to why we could not allow adding that class A even if it is otherwise valid.
And I told you why
Because the component system has ssemantical requirements that are not expressed in the syntax of the api
my question was why not allow adding records to the whitelist, not why not allow adding random [non-record, non-whitelisted] classes to the components
i think you're still misunderstanding what I was talking about 'adding' things to
sounds like a pointless discussion in any case
we should disallow collection types as well
because an array list has equals and hashcode but is mutable
Whatβs the actual tangible result if someone messes up
we'd have to special case them sadly
if you fuck up equals: stacks that should stack will not stack and vice versa
if you fuck up immutability: modify multiple copies of the stack at the same time
we can't protect all the cases
if people use arraylist so be it
hmm quantum entangled stacks
a cursed thought would be a special mode that tests for collection immutability by trying to remove from the collection, expecting and catching the resulting exception
even if we went that far, which IMO is way too far
all it takes is someone making their own custom class that holds a List in a field
record Lulz(List<X>){}
and I think it's 100x more likely people will use mutable fields in their class, than a List<>
we just need a big warning in the documentation
Or you modify every stack that has that item and for equals you could also turn a component into another one of the same type (like what mojang did with attributes)

and how is that useful?
also fluidstack doesn't include amount in equals and hashcode unless you changed that
I would say a FluidStack.Immutable is more apropo
I assume it says "of an empty fluid" cos it's a fluid variant
it's incredibly useful for transfer but that is just spitballing / early POC at the moment
of an amount
now it doesn't implement it at all
i don't see the empty fluid as being a measure of amount
that is definitely going to lead to bugs
but rather of content type
of people who use fluidstacks as keys
empty/air vs something else
I might override it just to make it throw
using a fluid stack as a key is pretty stupid anyway π
you could use a fluid variant though π
just don't mutate it
I don't think we should add an immutable subclass. Someone will inevitably end up doing player.setItemInHand(new ItemStack.Immutable(xxx)) and cause a crash down the line
I am thinking of a separate ImmutableFluidStack/ImmutableItemStack class (but ideally with a better name)
I would then not name it FluidStack
But something like ImmutableXXXContainer
So that it is immediatly clear what the fuck we are talking about
And maybe even make the Stack variant extend it
So that if somebody is just interested in a Container
They can accept the common type
I don't think that having two completely distinct types is a great idea
Alone from the required brainpower to apprehend the concept
ideally the immutable variant would be the superclass
Yes
in an ideal world we would have the mutable stack, an immutable stack, and potentially also a count-less "stack" for use in maps, transfer, etc
container has the implication of inventory tho
- some common superclass / superinterface
The name is not really the point, I would not use variant though
but that is too many classes anyway
Well the countless one should be read-only anyway
So it could be the root type in the tree
yeah definitely
Then the immutable one on top
yea variant and container are not good for the usecase
And then the mutable one on that
Maybe with some generics you can get away with only a handfull classes
That would be worth it in my opinion
Because this problem with mutability has plagued us since -beta times
generic over item/fluid stack? that would be a good step towards unification
Yeah
or well, I mean "common abstraction" is more appropriate than "unification"
If your whole concept is that the FluidStack and ItemStack types should have the same API surface
it is
Then I would argue that their Immutable, and Countless super types should simply be generic
record ItemVariant(Item, Components) {}
interface ItemHolder { ItemVariant getVariant(), Item getItem(), Components getComponents(), getCount() }
record ItemResource(ItemVariant, count) implements ItemHodler
class ItemStack implements ItemHolder
Or something like that
Point is
There are many ways to skin this cat
And, IMHO, we should not stop with this road, just because it adds 5 or 6 classes
yeah ItemVariant and ItemHolder could be made into like, Variant<Item> and ResourceHolder<Item>
We have systems which add like 20 classes
And we give 0 fucks about that either
Given that this system would solve something we have been strugling with since the beginning of modding, I would even add 100 Classes to solve it
don't be mean to the kitties πΏ
Sorry
// Generic
record Variant<T>(T, Components) {}
interface ResourceHolder<T> { Variant<T> getVariant(), T getResource(), Components getComponents(), int getCount() }
interface ResourceStack<T> extends ResourceHolder<T> { void setCount(int); <X> void setComponent(ComponentType<X>, X); }
// Specialized
interface ItemHolder extends ResourceHolder<Item> { Item getItem() -> getResource(); /* needed for ItemStack existing method name compatibility */ }
record ItemResource(Variant<Item>, int count) implements ItemHodler
class ItemStack implements ItemHolder, ResourceStack<Item>
interface FluidHolder extends ResourceHolder<Fluid> { Fluid getFluid() -> getResource(); /* consistency */ }
record FluidResource(Variant<Fluid>, int count) implements FluidHodler
class FluidStack implements FluidHolder, ResourceStack<Fluid>
I'm not sure we'd gain much from those being generic though, and we can't just add an abstract ResourceStack<T> superclass to ItemStack
Sure we can add ResourceStack<Item> to ItemStack
as an interface yes, but we can't pull the logic up
Hmm, maybe we should make them an interface then
Not sure
what does Stack add over ResourceHolder?
setCount and setComponent?
thats a lot of objects
Probably yeah
I added those to the mockup
Again it should be doable
It will need a lot of iteration to get an acceptable design for sure
The end game for me (not for 1.20.5 but maybe we get to do it between 1.21 and 1.22) would be to use this hierarchy to simplify our transfer handlers as well
yeah
To fix all the "do not modify the returned stack", "this stack is yours", "this stack is not yours " crap
Variant<Energy> 
FORGE_ENERGY = ENERGY.register("fe", ...) 
EnergyStack 
To be even clearer, I would like the interface for I/O to be java // Returns how much was inserted int insert(int slot, CountlessStack what, int howMuch, Action action);
Energy would probably keep its own cap
It's not worth dealing with slots etc for energy IMO
interface ResourceHandler<T> {
int insert(int slot, Variant<T>, int count, ...);
int extract(int slot, Variant<T>, int count, ...);
}
oops yes I forgot the slot too
Hehe yeah that'd be ideal
(that made no sense, reverted)
interface ResourceContainer<T> {
Variant<T> getContentsType(int slot);
int getContentsCount(int slot);
}
interface ResourceInventory<T> extends ResourceContainer<T> {
ResourceHolder<T> pickupContents(int slot)
ResourceHolder<T> swapContents(int slot, ResourceHolder<T>)
ResourceHolder<T> splitContents(int slot, int quantity);
}
π€
Well I'm not a fan of splitting the transfer interfaces into multiple pieces
It makes sense to be able to query the content from a resource handler
yeah I was picturing it as a superinterface
And in principle pickup/swap/split can be done with helper functions on top of insert/extract
I really don't think that's how pickup/place/split should work
it's the part I dislike the most about the current IItemHandler
pickup/place should have their own separate logic, not insert/extract
Isn't pickup just extract?
no
not to me, at least
in almost every single inventory I have implemented, pick up bypasses the restrictions of insert/extract
The usual solution is to have multiple handlers
yes, and I would like not to require that crutch in the API
that's why all my proposals for an item handler API refactor include this separate "gui handler" vs "automation handler"
of course the big exception for me right now is Ender-rift, where the whole inventory network is based on a concept of "transaction fee", by having an energy cost on insert/extract proportional to the number of slots present in the network
in that concept I do have to route everything through insert/extract just because using IItemHandlerModifiable would bypass too much :P
I would love immutable resources in that API because it would remove the possibility of someone mutating a stack without the energy fee taking effect :P
but separating automation and gui into different interfaces would still allow me to apply the appropriate fees
Hmmm
In my experience it's quite easy to manage an "internal inventory" and external wrappers
new mod?
so what we really need is:
- FluidStack
- immutable FluidStack
- amount-less immutable FluidStack
ideally sharing some code but without overdoing it
FluidKey?
that would be the amount-less immutable one
Honestly the name "Stack" sucks, you don't stack fluids
FluidDefinition, FluidInstance, naming like that...
Or, you know. FluidType
the exact names are TBD (it's not the tricky part)
It's splitting the concept of what a fluid is vs how much there is
Im partial to Key, but only because we settled on that in AE
precisely
I mean you already have ItemKey and BlockKey
We do?
however I still want to keep FluidStack around very similarly to how we have ItemStack, since an essential goal is to have maximal symmetry between items and fluids
Well, ResourceKey<Item>
