Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/core/TagLoaderKJS.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public interface TagLoaderKJS<T> {
}
}

hasDefaultTags |= !kjs$getResources().kjs$getServerScriptManager().serverRegistryTags.isEmpty();

if (hasDefaultTags || ServerEvents.TAGS.hasListeners(objStorage.key)) {
var preEvent = kjs$getResources().kjs$getServerScriptManager().preTagEvents.get(reg.key());

Expand All @@ -56,6 +58,12 @@ public interface TagLoaderKJS<T> {
}
}

for (var e : kjs$getResources().kjs$getServerScriptManager().serverRegistryTags.entrySet()) {
for (var tag : e.getValue()) {
event.add(tag, new TagEventFilter.ID(e.getKey()));
}
}

if (preEvent == null) {
ServerEvents.TAGS.post(event, objStorage.key);
} else {
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/holder/HolderWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ static Holder<?> wrap(KubeJSContext cx, Object from, TypeInfo param) {
return holder.isEmpty() ? DeferredHolder.create(registry.key(), id) : holder.get();
}

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());
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

} 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));
}

Comment on lines +59 to +77
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

static HolderSet<?> wrapSet(KubeJSContext cx, Object from, TypeInfo param) {
var registry = cx.lookupRegistry(param, from);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public Scriptable wrapAsJavaObject(Scriptable scope, Object javaObject, TypeInfo
public int internalConversionWeightLast(Object fromObj, TypeInfo target) {
var c = target.asClass();

if (c == Optional.class || c == ResourceKey.class || c == Holder.class || c == HolderSet.class || c == TagKey.class) {
if (c == Optional.class || c == ResourceKey.class || c == Holder.class || c == HolderSet.class || c == TagKey.class || c == Holder.Reference.class) {
return CONVERSION_TRIVIAL;
} else if (c != Object.class) {
var reg = RegistryType.allOfClass(target.asClass());
Expand Down Expand Up @@ -144,6 +144,8 @@ protected Object internalJsToJavaLast(Object from, TypeInfo target) {
return ResourceKey.create(registryType.key(), id);
} else if (c == Holder.class) {
return HolderWrapper.wrap(this, from, target.param(0));
} else if (c == Holder.Reference.class) {
return HolderWrapper.wrapRef(this, from, target.param(0));
} else if (c == HolderSet.class) {
return HolderWrapper.wrapSet(this, from, target.param(0));
} else if (c == TagKey.class) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.latvian.mods.kubejs.server;

import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle;
import dev.latvian.mods.kubejs.KubeJS;
import dev.latvian.mods.kubejs.KubeJSPaths;
import dev.latvian.mods.kubejs.error.KubeRuntimeException;
Expand All @@ -24,7 +25,9 @@
import dev.latvian.mods.kubejs.util.Cast;
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
Expand All @@ -36,11 +39,15 @@

import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ServerScriptManager extends ScriptManager {
private static ServerScriptManager staticInstance;
Expand Down Expand Up @@ -92,6 +99,7 @@ public static ServerScriptManager release() {
public final VirtualDataPack internalDataPack;
public final VirtualDataPack registriesDataPack;
public final Map<GeneratedDataStage, VirtualDataPack> virtualPacks;
public final Map<ResourceLocation, Set<ResourceLocation>> serverRegistryTags;
public boolean firstLoad;

private ServerScriptManager() {
Expand All @@ -103,6 +111,7 @@ private ServerScriptManager() {
this.internalDataPack = new VirtualDataPack(GeneratedDataStage.INTERNAL, this::getRegistries);
this.registriesDataPack = new VirtualDataPack(GeneratedDataStage.REGISTRIES, this::getRegistries);
this.virtualPacks = GeneratedDataStage.forScripts(stage -> new VirtualDataPack(stage, this::getRegistries));
serverRegistryTags = new HashMap<>();

this.firstLoad = true;

Expand Down Expand Up @@ -177,6 +186,26 @@ public void loadAdditional() {
if (ServerEvents.REGISTRY.hasListeners()) {
var builders = new ArrayList<BuilderBase<?>>();

var current = RegistryAccessContainer.current;
RegistryAccessContainer.current = new RegistryAccessContainer(new RegistryAccess.Frozen() {

final Map<ResourceKey<? extends Registry<?>>, Optional<Registry<?>>> registries = new HashMap<>();

@Override
public <E> Optional<Registry<E>> registry(ResourceKey<? extends Registry<? extends E>> registryKey) {
return Cast.to(registries.computeIfAbsent(registryKey, key -> {
var c = current.access().registry(key);
if (c.isPresent()) return Cast.to(c);
return Optional.of(new MappedRegistry(key, Lifecycle.experimental()));
}));
}

@Override
public Stream<RegistryEntry<?>> registries() {
return current.access().registries();
}
});

var ops = RegistryAccessContainer.current.json();

var codecs = new Reference2ObjectOpenHashMap<ResourceKey<?>, Codec<?>>();
Expand All @@ -196,6 +225,10 @@ public void loadAdditional() {

for (var b : builders) {
b.generateData(registriesDataPack);

if (!b.defaultTags.isEmpty()) {
serverRegistryTags.put(b.id, b.defaultTags);
}
}

for (var b : builders) {
Expand Down Expand Up @@ -226,6 +259,8 @@ public void loadAdditional() {
}

registriesDataPack.flush();

RegistryAccessContainer.current = current;
}
}
}
Expand Down