Skip to content

Commit

Permalink
Fixed number component toString(), added dev command to attempt to ge…
Browse files Browse the repository at this point in the history
…nerate recipe schema json from code schemas
  • Loading branch information
LatvianModder committed Aug 29, 2024
1 parent 7f7818b commit 034f868
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 25 deletions.
59 changes: 59 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/command/KubeJSCommands.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package dev.latvian.mods.kubejs.command;

import com.google.common.base.Predicate;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.serialization.JsonOps;
import dev.latvian.mods.kubejs.CommonProperties;
import dev.latvian.mods.kubejs.KubeJS;
import dev.latvian.mods.kubejs.KubeJSPaths;
Expand All @@ -15,20 +18,24 @@
import dev.latvian.mods.kubejs.net.DisplayClientErrorsPayload;
import dev.latvian.mods.kubejs.net.DisplayServerErrorsPayload;
import dev.latvian.mods.kubejs.net.ReloadStartupScriptsPayload;
import dev.latvian.mods.kubejs.script.ConsoleJS;
import dev.latvian.mods.kubejs.script.KubeJSContext;
import dev.latvian.mods.kubejs.script.ScriptType;
import dev.latvian.mods.kubejs.script.data.ExportablePackResources;
import dev.latvian.mods.kubejs.server.BasicCommandKubeEvent;
import dev.latvian.mods.kubejs.server.DataExport;
import dev.latvian.mods.kubejs.util.JsonUtils;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.DimensionArgument;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.ResourceKeyArgument;
import net.minecraft.commands.arguments.ResourceLocationArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
Expand Down Expand Up @@ -229,6 +236,13 @@ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
.executes(ctx -> eval(ctx.getSource(), StringArgumentType.getString(ctx, "code")))
)
);

cmd.then(Commands.literal("generate-recipe-schema-json")
.requires(spOrOP)
.then(Commands.argument("recipe-type", ResourceKeyArgument.key(Registries.RECIPE_SERIALIZER))
.executes(ctx -> generateRecipeSchemaJson(ctx.getSource(), ctx.getArgument("recipe-type", ResourceKey.class)))
)
);
}

var cmd1 = dispatcher.register(cmd);
Expand Down Expand Up @@ -548,4 +562,49 @@ private static int eval(CommandSourceStack source, String code) {
cx.evaluateString(cx.topLevelScope, code, "eval", 1, null);
return 1;
}

private static int generateRecipeSchemaJson(CommandSourceStack source, ResourceKey<?> id) {
var storage = source.getServer().getServerResources().managers().kjs$getServerScriptManager().recipeSchemaStorage;
var schemaType = storage.namespace(id.location().getNamespace()).get(id.location().getPath());
var ops = source.getServer().registryAccess().createSerializationContext(JsonOps.INSTANCE);

if (schemaType != null) {
var schema = schemaType.schema;
var json = new JsonObject();
var keys = new JsonArray();
json.add("keys", keys);

for (var key : schema.keys) {
keys.add(key.toJson(schemaType, ops));
}

if (!schema.uniqueIds().isEmpty()) {
var a = new JsonArray();

for (var key : schema.uniqueIds()) {
a.add(key.name);
}

if (!a.isEmpty()) {
json.add("unique", a);
}
}

if (!schema.constructorsGenerated()) {
var a = new JsonArray();

for (var c : schema.constructors().values()) {
a.add(c.toJson(schemaType, ops));
}

if (!a.isEmpty()) {
json.add("constructors", a);
}
}

ConsoleJS.SERVER.info("JSON of " + id.location() + ": (May be inaccurate!)\n" + JsonUtils.toPrettyString(json));
}

return 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public ResourceLocation getType() {
public ResourceLocation getOrCreateId() {
if (id == null) {
var js = getSerializationTypeFunction();
var ids = CommonProperties.get().ignoreCustomUniqueRecipeIds ? null : js.schemaType.schema.uniqueIdFunction.apply(this);
var ids = CommonProperties.get().ignoreCustomUniqueRecipeIds ? null : js.schemaType.schema.buildUniqueId(this);

var prefix = js.id.getNamespace() + ":kjs/";

Expand Down
57 changes: 57 additions & 0 deletions src/main/java/dev/latvian/mods/kubejs/recipe/RecipeKey.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package dev.latvian.mods.kubejs.recipe;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DynamicOps;
import dev.latvian.mods.kubejs.recipe.component.ComponentRole;
import dev.latvian.mods.kubejs.recipe.component.RecipeComponent;
import dev.latvian.mods.kubejs.recipe.schema.RecipeOptional;
import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema;
import dev.latvian.mods.kubejs.recipe.schema.RecipeSchemaType;
import dev.latvian.mods.kubejs.util.Cast;
import dev.latvian.mods.rhino.type.TypeInfo;

Expand Down Expand Up @@ -204,4 +210,55 @@ public RecipeKey<T> alwaysWrite() {
public String getPreferredBuilderKey() {
return functionNames == null ? name : functionNames.getFirst();
}

public JsonObject toJson(RecipeSchemaType type, DynamicOps<JsonElement> ops) {
var json = new JsonObject();
json.addProperty("name", name);

if (!role.isOther()) {
json.addProperty("role", role.getSerializedName());
}

json.addProperty("type", component.toString());

if (optional != null) {
if (optional.isDefault()) {
json.add("optional", JsonNull.INSTANCE);
} else {
json.add("optional", codec.encodeStart(ops, optional.getDefaultValue(type)).getOrThrow());
}
}

if (names.size() > 1) {
var a = new JsonArray();

for (var n : names) {
if (!n.equals(name)) {
a.add(n);
}
}

json.add("alternative_names", a);
}

if (excluded) {
json.addProperty("excluded", true);
}

if (functionNames != null) {
var a = new JsonArray();
functionNames.forEach(a::add);
json.add("function_names", a);
}

if (allowEmpty) {
json.addProperty("allow_empty", true);
}

if (alwaysWrite) {
json.addProperty("always_write", true);
}

return json;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ default NumberComponent<S, T> max(T max) {
return range(min(), max);
}

default String toString(String name, T min, T max) {
var mn = min();
var mx = max();

if (min.equals(mn) && max.equals(mx)) {
return name;
} else if (min.equals(mn)) {
return name + "<min," + mx + ">";
} else if (max.equals(mx)) {
return name + "<" + mn + ",max>";
} else {
return name + "<" + mn + "," + mx + ">";
}
}

record IntRange(Integer min, Integer max, Codec<Integer> codec) implements NumberComponent<IntRange, Integer> {
@Override
public Codec<Integer> codec() {
Expand All @@ -151,7 +166,7 @@ public IntRange range(Integer min, Integer max) {

@Override
public String toString() {
return "int";
return toString("int", Integer.MIN_VALUE, Integer.MAX_VALUE);
}
}

Expand Down Expand Up @@ -180,7 +195,7 @@ public LongRange range(Long min, Long max) {

@Override
public String toString() {
return "long";
return toString("long", Long.MIN_VALUE, Long.MAX_VALUE);
}
}

Expand All @@ -207,7 +222,7 @@ public FloatRange range(Float min, Float max) {

@Override
public String toString() {
return "float";
return toString("float", Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
}
}

Expand All @@ -234,7 +249,7 @@ public DoubleRange range(Double min, Double max) {

@Override
public String toString() {
return "double";
return toString("double", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dev.latvian.mods.kubejs.recipe.schema;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.DynamicOps;
import dev.latvian.mods.kubejs.recipe.KubeRecipe;
import dev.latvian.mods.kubejs.recipe.RecipeKey;
import dev.latvian.mods.kubejs.recipe.RecipeTypeFunction;
Expand Down Expand Up @@ -72,4 +75,28 @@ public void setValues(Context cx, KubeRecipe recipe, RecipeSchemaType schemaType
recipe.setValue(entry.getKey(), Cast.to(entry.getValue().getDefaultValue(schemaType)));
}
}

public JsonObject toJson(RecipeSchemaType type, DynamicOps<JsonElement> ops) {
var json = new JsonObject();

var k = new JsonArray(keys.size());

for (var key : keys) {
k.add(key.name);
}

json.add("keys", k);

if (!overrides.isEmpty()) {
var o = new JsonObject();

for (var entry : overrides.entrySet()) {
o.add(entry.getKey().name, entry.getKey().codec.encodeStart(ops, Cast.to(entry.getValue().getDefaultValue(type))).getOrThrow());
}

json.add("overrides", o);
}

return json;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public class RecipeSchema {
private int outputCount;
private int minRequiredArguments;
private Int2ObjectMap<RecipeConstructor> constructors;
public Function<KubeRecipe, String> uniqueIdFunction;
private boolean constructorsGenerated;
private List<RecipeKey<?>> uniqueIds;
boolean hidden;

/**
Expand Down Expand Up @@ -102,7 +103,7 @@ public RecipeSchema(Map<RecipeKey<?>, RecipeOptional<?>> keyOverrides, List<Reci
minRequiredArguments = includedKeys.size();
}

this.uniqueIdFunction = DEFAULT_UNIQUE_ID_FUNCTION;
this.uniqueIds = List.of();
this.hidden = false;
}

Expand Down Expand Up @@ -144,13 +145,22 @@ public RecipeSchema constructor(RecipeKey<?>... keys) {
return constructor(new RecipeConstructor(keys));
}

public RecipeSchema uniqueId(Function<KubeRecipe, String> uniqueIdFunction) {
this.uniqueIdFunction = uniqueIdFunction;
public RecipeSchema uniqueId(RecipeKey<?> key) {
uniqueIds = List.of(key);
return this;
}

public RecipeSchema uniqueId(RecipeKey<?> key) {
return uniqueId(r -> {
public RecipeSchema uniqueIds(SequencedCollection<RecipeKey<?>> keys) {
uniqueIds = List.copyOf(keys);
return this;
}

@Nullable
public String buildUniqueId(KubeRecipe r) {
if (uniqueIds.isEmpty()) {
return null;
} else if (uniqueIds.size() == 1) {
var key = uniqueIds.getFirst();
var value = r.getValue(key);

if (value != null) {
Expand All @@ -160,17 +170,7 @@ public RecipeSchema uniqueId(RecipeKey<?> key) {
}

return null;
});
}

public RecipeSchema uniqueIds(SequencedCollection<RecipeKey<?>> keys) {
if (keys.isEmpty()) {
return uniqueId(DEFAULT_UNIQUE_ID_FUNCTION);
} else if (keys.size() == 1) {
return uniqueId(keys.getFirst());
}

return uniqueId(r -> {
} else {
var sb = new StringBuilder();
var builder = new UniqueIdBuilder(new StringBuilder());
boolean first = true;
Expand All @@ -195,11 +195,12 @@ public RecipeSchema uniqueIds(SequencedCollection<RecipeKey<?>> keys) {
}

return sb.isEmpty() ? null : sb.toString();
});
}
}

public Int2ObjectMap<RecipeConstructor> constructors() {
if (constructors == null) {
constructorsGenerated = true;
constructors = includedKeys.isEmpty() ? new Int2ObjectArrayMap<>() : new Int2ObjectArrayMap<>(includedKeys.size() - minRequiredArguments + 1);
boolean dev = DevProperties.get().logRecipeDebug;

Expand All @@ -220,6 +221,10 @@ public Int2ObjectMap<RecipeConstructor> constructors() {
return constructors;
}

public List<RecipeKey<?>> uniqueIds() {
return uniqueIds;
}

public int minRequiredArguments() {
return minRequiredArguments;
}
Expand All @@ -236,6 +241,11 @@ public boolean isHidden() {
return hidden;
}

public boolean constructorsGenerated() {
constructors();
return constructorsGenerated;
}

public KubeRecipe deserialize(SourceLine sourceLine, RecipeTypeFunction type, @Nullable ResourceLocation id, JsonObject json) {
var r = recipeFactory.create(type, sourceLine);
r.id = id;
Expand Down
Loading

0 comments on commit 034f868

Please sign in to comment.