Skip to content

Commit

Permalink
Added resource key recipe component
Browse files Browse the repository at this point in the history
  • Loading branch information
LatvianModder committed Oct 21, 2024
1 parent 2f62e5d commit 4a5391b
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
import dev.latvian.mods.kubejs.recipe.component.NestedRecipeComponent;
import dev.latvian.mods.kubejs.recipe.component.NumberComponent;
import dev.latvian.mods.kubejs.recipe.component.RegistryComponent;
import dev.latvian.mods.kubejs.recipe.component.ResourceKeyComponent;
import dev.latvian.mods.kubejs.recipe.component.SizedFluidIngredientComponent;
import dev.latvian.mods.kubejs.recipe.component.SizedIngredientComponent;
import dev.latvian.mods.kubejs.recipe.component.StringComponent;
Expand Down Expand Up @@ -697,12 +698,16 @@ public void registerRecipeComponents(RecipeComponentFactoryRegistry registry) {
registry.register(BookCategoryComponent.CRAFTING_BOOK_CATEGORY);
registry.register(BookCategoryComponent.COOKING_BOOK_CATEGORY);

registry.register(ResourceKeyComponent.DIMENSION);
registry.register(ResourceKeyComponent.LOOT_TABLE);

registry.register("tag", TagKeyComponent.FACTORY);
registry.register("registry_element", RegistryComponent.FACTORY);
registry.register("enum", EnumComponent.FACTORY);
registry.register("map", MapRecipeComponent.FACTORY);
registry.register("pattern", MapRecipeComponent.PATTERN_FACTORY);
registry.register("either", EitherRecipeComponent.FACTORY);
registry.register("resource_key", ResourceKeyComponent.FACTORY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.latvian.mods.kubejs.recipe.component;

import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import dev.latvian.mods.kubejs.error.KubeRuntimeException;
import dev.latvian.mods.kubejs.recipe.schema.RecipeComponentFactory;
import dev.latvian.mods.rhino.type.EnumTypeInfo;
Expand All @@ -22,24 +23,13 @@ public record EnumComponent<T extends Enum<T> & StringRepresentable>(String cust
}

var clazz = Class.forName(cname);

var typeInfo = TypeInfo.of(clazz);

if (!(typeInfo instanceof EnumTypeInfo enumTypeInfo)) {
throw new KubeRuntimeException("Class " + clazz.getTypeName() + " is not an enum!");
}

return new EnumComponent("", enumTypeInfo, Codec.STRING.xmap(s -> {
for (var c : enumTypeInfo.enumConstants()) {
if (c instanceof RemappedEnumConstant r && r.getRemappedEnumConstantName().equalsIgnoreCase(s)) {
return c;
} else if (c instanceof Enum<?> e && e.name().equalsIgnoreCase(s)) {
return c;
}
}

throw new KubeRuntimeException("Enum value '" + s + "' of " + clazz.getName() + " not found");
}, EnumTypeInfo::getName));
return new EnumComponent<>(enumTypeInfo);
} catch (Exception ex) {
throw new KubeRuntimeException("Error loading class " + cname + " for EnumComponent", ex);
}
Expand All @@ -49,6 +39,20 @@ public static <T extends Enum<T> & StringRepresentable> EnumComponent<T> of(Stri
return new EnumComponent<>(customName, (EnumTypeInfo) TypeInfo.of(enumClass), codec);
}

public EnumComponent(EnumTypeInfo typeInfo) {
this("", typeInfo, (Codec) Codec.STRING.flatXmap(s -> {
for (var c : typeInfo.enumConstants()) {
if (c instanceof RemappedEnumConstant r && r.getRemappedEnumConstantName().equalsIgnoreCase(s)) {
return DataResult.success(c);
} else if (c instanceof Enum<?> e && e.name().equalsIgnoreCase(s)) {
return DataResult.success(c);
}
}

return DataResult.error(() -> "Enum value '" + s + "' of " + typeInfo.asClass().getName() + " not found");
}, o -> DataResult.success(EnumTypeInfo.getName(o))));
}

@Override
public Codec<T> codec() {
return codec;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
import com.google.gson.JsonPrimitive;
import com.mojang.serialization.Codec;
import dev.latvian.mods.kubejs.fluid.FluidWrapper;
import dev.latvian.mods.kubejs.holder.HolderWrapper;
import dev.latvian.mods.kubejs.item.ItemStackJS;
import dev.latvian.mods.kubejs.recipe.KubeRecipe;
import dev.latvian.mods.kubejs.recipe.schema.RecipeComponentFactory;
import dev.latvian.mods.kubejs.registry.RegistryType;
import dev.latvian.mods.kubejs.script.KubeJSContext;
import dev.latvian.mods.kubejs.util.ID;
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
import dev.latvian.mods.rhino.Context;
import dev.latvian.mods.rhino.type.TypeInfo;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.RegistryFixedCodec;
Expand All @@ -22,20 +25,25 @@
import net.neoforged.neoforge.fluids.FluidStack;
import org.jetbrains.annotations.Nullable;

public record RegistryComponent<T>(Registry<T> registry, @Nullable RegistryType<T> regType, Codec<T> codec) implements RecipeComponent<T> {
@SuppressWarnings({"unchecked", "rawtypes"})
public record RegistryComponent<T>(Registry<T> registry, @Nullable RegistryType<T> regType, Codec<Holder<T>> codec) implements RecipeComponent<Holder<T>> {
@SuppressWarnings({"rawtypes"})
public static final RecipeComponentFactory FACTORY = (registries, storage, reader) -> {
reader.skipWhitespace();
reader.expect('<');
reader.skipWhitespace();
var regId = ResourceLocation.read(reader);
reader.expect('>');
var key = ResourceKey.createRegistryKey(regId);
return new RegistryComponent(registries.access().registry(key).orElseThrow(), RegistryType.ofKey(key), RegistryFixedCodec.create(key));
return new RegistryComponent(registries, key);
};

@SuppressWarnings({"unchecked", "rawtypes"})
public RegistryComponent(RegistryAccessContainer registries, ResourceKey key) {
this((Registry) registries.access().registry(key).orElseThrow(), (RegistryType) RegistryType.ofKey(key), RegistryFixedCodec.create(key));
}

@Override
public Codec<T> codec() {
public Codec<Holder<T>> codec() {
return codec;
}

Expand All @@ -46,29 +54,31 @@ public TypeInfo typeInfo() {

@Override
@SuppressWarnings("unchecked")
public T wrap(Context cx, KubeRecipe recipe, Object from) {
public Holder<T> wrap(Context cx, KubeRecipe recipe, Object from) {
if (registry == BuiltInRegistries.ITEM) {
if (from instanceof ItemStack is) {
return (T) is.getItem();
} else if (from instanceof Item) {
return (T) from;
return (Holder<T>) is.getItem().builtInRegistryHolder();
} else if (from instanceof Item item) {
return (Holder<T>) item.builtInRegistryHolder();
} else {
return (T) ItemStackJS.wrap(RegistryAccessContainer.of(cx), from).getItem();
return (Holder<T>) ItemStackJS.wrap(RegistryAccessContainer.of(cx), from).getItemHolder();
}
} else if (registry == BuiltInRegistries.FLUID) {
if (from instanceof FluidStack fs) {
return (T) fs.getFluid();
} else if (from instanceof Fluid) {
return (T) from;
return (Holder<T>) fs.getFluid().builtInRegistryHolder();
} else if (from instanceof Fluid fluid) {
return (Holder<T>) fluid.builtInRegistryHolder();
} else {
return (T) FluidWrapper.wrap(RegistryAccessContainer.of(cx), from).getFluid();
return (Holder<T>) FluidWrapper.wrap(RegistryAccessContainer.of(cx), from).getFluidHolder();
}
} else if (regType != null) {
return (Holder<T>) HolderWrapper.wrap((KubeJSContext) cx, from, regType.type());
} else if (from instanceof ResourceKey<?> key) {
return registry.getHolderOrThrow((ResourceKey) key);
} else if (from instanceof CharSequence || from instanceof ResourceLocation) {
return registry.getHolderOrThrow(ResourceKey.create(registry.key(), ID.mc(from.toString())));
} else {
if (regType != null && regType.baseClass().isInstance(from)) {
return (T) from;
}

return registry.get(ID.mc(from));
throw new IllegalStateException("Missing key in " + registry.key() + ": " + from);
}
}

Expand All @@ -78,11 +88,11 @@ public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) {
}

@Override
public void buildUniqueId(UniqueIdBuilder builder, T value) {
var id = registry.getKey(value);
public void buildUniqueId(UniqueIdBuilder builder, Holder<T> value) {
var id = value.getKey();

if (id != null) {
builder.append(id);
builder.append(id.location());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package dev.latvian.mods.kubejs.recipe.component;

import com.mojang.serialization.Codec;
import dev.latvian.mods.kubejs.recipe.KubeRecipe;
import dev.latvian.mods.kubejs.recipe.schema.RecipeComponentFactory;
import dev.latvian.mods.kubejs.registry.RegistryType;
import dev.latvian.mods.kubejs.util.ID;
import dev.latvian.mods.rhino.Context;
import dev.latvian.mods.rhino.type.TypeInfo;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.loot.LootTable;

public record ResourceKeyComponent<T>(ResourceKey<? extends Registry<T>> registryKey) implements RecipeComponent<ResourceKey<T>> {
public static final RecipeComponent<ResourceKey<Level>> DIMENSION = new ResourceKeyComponent<>(Registries.DIMENSION);
public static final RecipeComponent<ResourceKey<LootTable>> LOOT_TABLE = new ResourceKeyComponent<>(Registries.LOOT_TABLE);

@SuppressWarnings({"rawtypes"})
public static final RecipeComponentFactory FACTORY = (registries, storage, reader) -> {
reader.skipWhitespace();
reader.expect('<');
reader.skipWhitespace();
var regId = ResourceLocation.read(reader);
reader.expect('>');
var key = ResourceKey.createRegistryKey(regId);
return new ResourceKeyComponent(key);
};

@Override
public Codec<ResourceKey<T>> codec() {
return ResourceKey.codec(registryKey);
}

@Override
public TypeInfo typeInfo() {
var reg = RegistryType.ofKey(registryKey);
return reg == null ? TypeInfo.of(ResourceKey.class) : TypeInfo.of(ResourceKey.class).withParams(reg.type());
}

@Override
public ResourceKey<T> wrap(Context cx, KubeRecipe recipe, Object from) {
return ResourceKey.create(registryKey, ID.mc(from));
}

@Override
public String toString() {
var key = (ResourceKey) registryKey;

if (key == Registries.DIMENSION) {
return "dimension_resource_key";
} else if (key == Registries.LOOT_TABLE) {
return "loot_table_resource_key";
} else {
return "resource_key<" + registryKey.location() + ">";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ public record TagKeyComponent<T>(ResourceKey<? extends Registry<T>> registry, Ty
public static final RecipeComponent<TagKey<Biome>> BIOME = new TagKeyComponent<>(Registries.BIOME, TypeInfo.of(Biome.class));
public static final RecipeComponent<TagKey<Fluid>> FLUID = new TagKeyComponent<>(Registries.FLUID, TypeInfo.of(Fluid.class));

private static TagKeyComponent<?> of(ResourceKey<? extends Registry<?>> registry) {
var r = RegistryType.ofKey(registry);
return new TagKeyComponent<>((ResourceKey) registry, r != null ? r.type() : TypeInfo.NONE);
}

public static final RecipeComponentFactory FACTORY = (registries, storage, reader) -> {
reader.skipWhitespace();
reader.expect('<');
reader.skipWhitespace();
var registry = ResourceKey.createRegistryKey(ResourceLocation.read(reader));
reader.expect('>');

var r = RegistryType.ofKey(registry);
return new TagKeyComponent<>(registry, r != null ? r.type() : TypeInfo.NONE);
return of(registry);
};

@Override
Expand Down

0 comments on commit 4a5391b

Please sign in to comment.