Skip to content

Commit 937ccc0

Browse files
Further cleanup of schema datagen, RecipeOptional, docs
1 parent 623415f commit 937ccc0

File tree

5 files changed

+65
-43
lines changed

5 files changed

+65
-43
lines changed

src/main/java/dev/latvian/mods/kubejs/recipe/RecipeKey.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
* be serialized or written to the value map unless it is declared as {@link #alwaysWrite}.
3535
* <p>
3636
* By default, each key will have a "builder" method generated for scripts using the first {@link #functionNames} name.
37-
* You can disable this by setting {@link #noFunctions()} to true.
37+
* You can disable this by setting {@link #noFunctions()}.
3838
* <p>
3939
* Finally, some types of components such as items or fluids may perform validation to ensure that they
4040
* aren't holding empty data.
@@ -96,13 +96,12 @@ public String toString() {
9696
* @param value The default value of this key; note that the instance supplied here
9797
* will be used directly and across multiple recipes, so make sure
9898
* to only pass immutable objects!
99-
* @apiNote Note that this method <i>does not</i> actually set the value during
100-
* recipe initialization unless {@link #alwaysWrite} is also set! This is mostly
101-
* meant to be used as information for mods like ProbeJS.
99+
* @apiNote This that this method <i>does not</i> write the default value during
100+
* recipe initialization unless {@link #alwaysWrite} is also set!
102101
* @see #optional(RecipeOptional)
103102
*/
104103
public RecipeKey<T> optional(T value) {
105-
return optional(new RecipeOptional.Constant<>(value));
104+
return optional(RecipeOptional.unit(value));
106105
}
107106

108107
/**
@@ -112,9 +111,8 @@ public RecipeKey<T> optional(T value) {
112111
* @param value The default value of this key; unlike in {@link #optional(Object)},
113112
* the value will be computed at recipe initialization time, which makes
114113
* it safe to pass mutable objects here.
115-
* @apiNote Note that this method <i>does not</i> actually set the value during
116-
* recipe initialization unless {@link #alwaysWrite} is also set! This is mostly
117-
* meant to be used as information for mods like ProbeJS.
114+
* @apiNote This method <i>does not</i> write the default value during
115+
* recipe initialization unless {@link #alwaysWrite} is also set!
118116
* @see #optional(RecipeOptional)
119117
*/
120118
public RecipeKey<T> optional(RecipeOptional<T> value) {
@@ -164,7 +162,7 @@ public RecipeKey<T> alt(String... names) {
164162

165163
/**
166164
* Excludes this key from auto-generated constructors.
167-
* <i>Requires</i> optional() value to also be set.
165+
* <b>Requires</b> optional() value to also be set.
168166
* <p>
169167
* This method does nothing if a custom constructor has been set.
170168
*/
@@ -183,7 +181,7 @@ public RecipeKey<T> noFunctions() {
183181

184182
/**
185183
* Sets a list of names that are used to auto-generate builder functions in JS, e.g. <code>.xp(value)</code>.
186-
* The first one will be the preferred one that ProbeJS and other third-party documentation should recommend.
184+
* The first one of these names will be the preferred one that documentation should recommend.
187185
*/
188186
public RecipeKey<T> functionNames(List<String> names) {
189187
functionNames = names;
@@ -192,7 +190,7 @@ public RecipeKey<T> functionNames(List<String> names) {
192190

193191
/**
194192
* Sets a list of names that are used to auto-generate builder functions in JS, e.g. <code>.xp(value)</code>.
195-
* The first one will be the preferred one that ProbeJS and other third-party documentation should recommend.
193+
* The first one of these names will be the preferred one that documentation should recommend.
196194
*/
197195
public RecipeKey<T> functionNames(String... names) {
198196
return functionNames(List.of(name));

src/main/java/dev/latvian/mods/kubejs/recipe/RecipeSchemaProvider.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ public RecipeSchemaData.RecipeKeyData keyData(RecipeKey<?> key) {
103103
key.role,
104104
key.component,
105105
Optional.ofNullable(key.optional)
106-
.map(o -> o.isDefault() ?
107-
null :
108-
key.codec.encodeStart(
109-
registryAccessContainer.json(),
110-
Cast.to(o.getValueForDataGeneration())
111-
).getOrThrow()),
106+
// this is `null` for default so we can safely ignore it
107+
.map(RecipeOptional::getInformativeValue)
108+
.map(value -> key.codec.encodeStart(
109+
registryAccessContainer.json(),
110+
Cast.to(value)
111+
).getOrThrow()),
112112
key.optional == RecipeOptional.DEFAULT,
113113
new ArrayList<>(key.names),
114114
key.excluded,

src/main/java/dev/latvian/mods/kubejs/recipe/schema/JsonRecipeSchemaLoader.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,17 @@ private RecipeSchema getSchema(DynamicOps<JsonElement> jsonOps) {
177177
var functionMap = new HashMap<String, RecipeSchemaFunction>();
178178
gatherFunctions(functionMap);
179179

180-
var keyOverrides = new Reference2ObjectOpenHashMap<RecipeKey<?>, RecipeOptional<?>>(overrideKeys == null ? 0 : overrideKeys.size());
180+
Map<RecipeKey<?>, RecipeOptional<?>> keyOverrides = Map.of();
181181

182182
if (overrideKeys != null) {
183+
keyOverrides = new Reference2ObjectOpenHashMap<>(overrideKeys.size());
184+
183185
for (var entry : overrideKeys.entrySet()) {
184186
var key = keyMap.get(entry.getKey());
185187

186188
if (key != null) {
187189
try {
188-
keyOverrides.put(key, new RecipeOptional.Constant(key.codec.decode(jsonOps, entry.getValue()).getOrThrow().getFirst()));
190+
keyOverrides.put(key, RecipeOptional.unit(key.codec.decode(jsonOps, entry.getValue()).getOrThrow().getFirst()));
189191
} catch (Exception ex) {
190192
throw new IllegalArgumentException("Failed to create optional value for key '" + key + "' of '" + id + "' from " + entry.getValue(), ex);
191193
}
@@ -341,7 +343,8 @@ public static void load(RecipeTypeRegistryContext ctx, DynamicOps<JsonElement> j
341343
var optionalJson = keyData.optional().get();
342344

343345
try {
344-
key.optional = new RecipeOptional.Constant(key.codec.decode(jsonOps, optionalJson).getOrThrow().getFirst());
346+
//noinspection unchecked, rawtypes
347+
key.optional = (RecipeOptional) RecipeOptional.unit(key.codec.decode(jsonOps, optionalJson).getOrThrow().getFirst());
345348
} catch (Exception ex) {
346349
throw new IllegalArgumentException("Failed to create optional value for key '" + key + "' of '" + builder.id + "' from " + optionalJson, ex);
347350
}

src/main/java/dev/latvian/mods/kubejs/recipe/schema/RecipeConstructor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import dev.latvian.mods.kubejs.util.Cast;
1414
import dev.latvian.mods.kubejs.util.ErrorStack;
1515
import dev.latvian.mods.kubejs.util.OpsContainer;
16+
import dev.latvian.mods.kubejs.util.RegistryAccessContainer;
1617
import dev.latvian.mods.rhino.Context;
1718
import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap;
1819

@@ -46,7 +47,7 @@ public <T> RecipeConstructor override(RecipeKey<T> key, RecipeOptional<T> value)
4647
}
4748

4849
public <T> RecipeConstructor overrideValue(RecipeKey<T> key, T value) {
49-
return override(key, new RecipeOptional.Constant<>(value));
50+
return override(key, RecipeOptional.unit(value));
5051
}
5152

5253
public <T> RecipeConstructor defaultValue(RecipeKey<T> key, RecipeOptional<T> value) {
@@ -60,7 +61,7 @@ public <T> RecipeConstructor defaultValue(RecipeKey<T> key, RecipeOptional<T> va
6061

6162
@Override
6263
public String toString() {
63-
return toString(OpsContainer.DEFAULT);
64+
return toString(RegistryAccessContainer.current);
6465
}
6566

6667
public String toString(OpsContainer ops) {
Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,74 @@
11
package dev.latvian.mods.kubejs.recipe.schema;
22

3+
import dev.latvian.mods.kubejs.recipe.RecipeSchemaProvider;
4+
import dev.latvian.mods.kubejs.util.Cast;
5+
import org.jetbrains.annotations.ApiStatus;
36
import org.jetbrains.annotations.NotNull;
47
import org.jetbrains.annotations.Nullable;
58

69
@FunctionalInterface
710
public interface RecipeOptional<T> {
8-
RecipeOptional<?> DEFAULT = new Constant<>(null);
9-
10-
record Constant<T>(T value) implements RecipeOptional<T> {
11+
RecipeOptional<?> DEFAULT = new Unit<>() {
1112
@Override
12-
public T getDefaultValue(RecipeSchemaType type) {
13-
return value;
13+
public @Nullable Object value() {
14+
return null;
1415
}
1516

1617
@Override
17-
@Nullable
18-
public T getInformativeValue() {
19-
return value;
20-
}
21-
22-
@Override
23-
public T getValueForDataGeneration() {
24-
return value;
18+
public String toString() {
19+
return "null";
2520
}
21+
};
2622

23+
/**
24+
* @deprecated This type will be hidden soon, use {@link RecipeOptional#unit(T)} instead where possible
25+
*/
26+
@ApiStatus.Internal
27+
record Constant<T>(T value) implements Unit<T> {
2728
@Override
2829
@NotNull
2930
public String toString() {
3031
return String.valueOf(value);
3132
}
3233
}
3334

34-
T getDefaultValue(RecipeSchemaType type);
35+
interface Unit<T> extends RecipeOptional<T> {
36+
@Nullable T value();
3537

36-
@Nullable
37-
default T getInformativeValue() {
38-
return null;
38+
@Override
39+
default T getDefaultValue(RecipeSchemaType type) {
40+
return value();
41+
}
42+
43+
@Override
44+
@Nullable
45+
default T getInformativeValue() {
46+
return value();
47+
}
48+
49+
@ApiStatus.Internal
50+
record Impl<T>(T value) implements Unit<T> {
51+
}
3952
}
4053

54+
T getDefaultValue(RecipeSchemaType type);
55+
4156
/**
42-
* Gets a value that can be encoded into json by a recipe key's codec.
43-
* For use in {@link dev.latvian.mods.kubejs.recipe.RecipeSchemaProvider data generation}
57+
* Gets a value that is used during {@link RecipeSchemaProvider data generation} of recipe schema JSONs,
58+
* as well as during debugging of recipe constructors.
4459
* <p>
45-
* This <strong>must</strong> be implemented if you intend to use data generation with a custom optional type
60+
* This <strong>needs to be</strong> implemented if you intend to use data generation with a custom optional type
4661
*/
47-
default T getValueForDataGeneration() {
62+
@Nullable
63+
default T getInformativeValue() {
4864
return null;
4965
}
5066

5167
default boolean isDefault() {
5268
return this == DEFAULT;
5369
}
70+
71+
static <T> RecipeOptional<T> unit(@Nullable T value) {
72+
return value == null ? Cast.to(DEFAULT) : new Unit.Impl<>(value);
73+
}
5474
}

0 commit comments

Comments
 (0)