Skip to content

Conversation

@Notenoughmail
Copy link
Contributor

Makes some adjustments so dealing with ServerEvents.registry is relatively nice.

  • During the event, the RegistryAccessContainer has 'access' to non-static registries by making an empty registry on demand and providing that. This is needed for wrapping Holders and HolderSets of server registries
  • Server registry builders now have their tags loaded
  • Add a wrapper specifically for reference holders. Helpful for when a holder needs to be serialized as the DeferredHolder which is typically made cannot serialize

These changes were tested locally against this commit

var registry = cx.lookupRegistry(param, from);

if (from instanceof Holder<?> h) {
return Holder.Reference.createStandAlone(Cast.to(registry.holderOwner()), h.getKey());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is createStandAlone guaranteed to be safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what context? When serializing with a registry present (the intent & use case I have), yes. For retrieving a value/id from the registry itself (or the holder even), no

Comment on lines +59 to +77
static Holder.Reference<?> wrapRef(KubeJSContext cx, Object from, TypeInfo param) {
if (from instanceof Holder.Reference<?> h) {
return h;
} else if (from == null) {
throw Context.reportRuntimeError("Can't interpret 'null' as a holder", cx);
}

var registry = cx.lookupRegistry(param, from);

if (from instanceof Holder<?> h) {
return Holder.Reference.createStandAlone(Cast.to(registry.holderOwner()), h.getKey());
} else if (!ID.isKey(from)) {
throw Context.reportRuntimeError("Can't interpret '" + from + "' as a reference holder", cx);
}

var id = ID.mc(from);
return Holder.Reference.createStandAlone(Cast.to(registry.holderOwner()), ResourceKey.create(registry.key(), id));
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, more general question, is there any time where we shouldn't just be using the regular wrap() method and then convert that (either cast or retrieve delegate) to a reference holder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only time a holder's delegate would be a reference holder is reference holders themselves and bound deferred holders, and the latter has problems due to only being bound if the registry has the id registered and the actual registry either being non-existent or frozen.
But wrapping as a holder and simply using its key if present should work the same (possibly more?) that what I currently have

@MaxNeedsSnacks
Copy link
Member

MaxNeedsSnacks commented Dec 11, 2025

  • During the event, the RegistryAccessContainer has 'access' to non-static registries by making an empty registry on demand and providing that. This is needed for wrapping Holders and HolderSets of server registries

Mind explaining / giving a brief example on why this is needed and why we specifically need to create a new RAC instance here?

@Notenoughmail
Copy link
Contributor Author

  • During the event, the RegistryAccessContainer has 'access' to non-static registries by making an empty registry on demand and providing that. This is needed for wrapping Holders and HolderSets of server registries

Mind explaining / giving a brief example on why this is needed and why we specifically need to create a new RAC instance here?

It is quite common for server registry objects to reference other objects via holders (placed features are literally a configured feature holder and a list of placement modifiers) and holder sets (TFC's forest feature; builder). Kube's wrappers for these two types requires the registry they're for to be present and the codecs will only serialize to the object/tag id if the registry is present in the RegistryOps.

Even if scriptors passed in a ResourceLocation/TagKey and they were lifted to a holder/holder set, the codec would try to encode them as their contents which neither would have. This is also why reference holders specifically have to be used as deferred holders require a value to serialize.

I tried to find a place where these registries existed and that was before datapacks were parsed, but there does not seem to be such a place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants