Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip binding references on SimpleRegistry#freeze #4123

Open
wants to merge 1 commit into
base: 1.21.1
Choose a base branch
from

Conversation

PersonTheCat
Copy link

Registry Order Fix

Description

These changes fix a rare bug where overwritten registry entries get bound to the wrong value.

Explanation

This problem occurs on SimpleRegistry#freeze at valueToEntry.forEach whenever a new value has been assigned to an existing key. The issue is that SimpleRegistry#valueToEntry is an instance of IdentityHashMap, which does not guarantee that its forEach method will run in order of insertion. Thus, occasionally, registry entries can get bound in an unpredictable order. The actual order is based on object identity; however, this order is also not guaranteed.

Design Considerations

One downside to this solution is that any existing mixins wrapping this operation may not get invoked. Thus, there is some potential for breakage with existing mods. However, I am not aware of any such mods and believe this change to be largely safe.

Alternate Strategies

In fixing this issue, I had also considered switching the implementation of valueToEntry to be a LinkedHashMap, which would guarantee order by insertion; however, such a change would alter fundamental systems involving registry operations. In my opinion, the scope of this change is greater than simply skipping that binding in the first place.

Automated Testing

This change is already covered by an existing test in RegistrySyncTest at registerBlocks, which confirms that this bind operation was unnecessary.

@apple502j apple502j added the registry-sync Pull requests and issues related to registry sync label Sep 28, 2024
@apple502j
Copy link
Contributor

Registry overwriting is a cursed practice that is technically not supported, but is useful anyway... (For reference: vanilla does not re-bind, it occurs at the mixin, L161)

@PersonTheCat
Copy link
Author

For reference, this is impacting a mod of mine in 2 ways:

  1. Dynamic registry generation based on data pack configurations. Conflicts are expected to be handled by data pack order.
  2. World gen changes, such as dynamically modifying noise router settings. IMO, it's probably safer to just re-register the data than attempt to modify it.

Not all of this code is public yet, but it's similar to what Lithostitched does with its Modifier API.

Maybe there are better ways to achieve that, but I have seen mods overwrite registry entries in the past.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
registry-sync Pull requests and issues related to registry sync
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants