Skip to content

Commit fa23283

Browse files
Simplify DataComponentWrapper a bit
1 parent 9d3f887 commit fa23283

File tree

1 file changed

+69
-116
lines changed

1 file changed

+69
-116
lines changed

src/main/java/dev/latvian/mods/kubejs/component/DataComponentWrapper.java

Lines changed: 69 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
77
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
88
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
9-
import com.mojang.datafixers.util.Pair;
109
import com.mojang.serialization.Codec;
1110
import com.mojang.serialization.DataResult;
1211
import com.mojang.serialization.DynamicOps;
@@ -45,14 +44,15 @@
4544

4645
import java.lang.reflect.Modifier;
4746
import java.lang.reflect.ParameterizedType;
47+
import java.util.HashMap;
4848
import java.util.HashSet;
4949
import java.util.Map;
5050
import java.util.Objects;
5151
import java.util.Set;
52+
import java.util.StringJoiner;
53+
import java.util.function.BiConsumer;
5254
import java.util.function.Consumer;
5355
import java.util.function.Function;
54-
import java.util.stream.Collectors;
55-
import java.util.stream.Stream;
5656

5757
import static com.mojang.serialization.DataResult.error;
5858
import static com.mojang.serialization.DataResult.success;
@@ -359,68 +359,20 @@ static DataResult<DataComponentMap> tryMapOf(Context cx, @Nullable Object o) {
359359
case Map<?, ?> map -> {
360360
var builder = DataComponentMap.builder();
361361

362-
var failed = false;
363-
Stream.Builder<Pair<DataComponentType<?>, String>> errors = Stream.builder();
364-
365362
Map<DataComponentType<?>, ?> wrapped = Objects.requireNonNull(cx.optionalMapOf(map, COMPONENT_TYPE, TypeInfo.NONE));
363+
Map<DataComponentType<?>, String> errors = new HashMap<>();
366364

367365
for (var entry : wrapped.entrySet()) {
368-
var type = entry.getKey();
369-
var valueType = getTypeInfo(type);
370-
371-
var value = entry.getValue();
372-
EvaluatorException evalError = null;
373-
374-
if (value == null || value instanceof Undefined) {
375-
continue;
376-
}
377-
378-
// TODO: remove once shouldConvert check is in Rhino
379-
if (valueType != TypeInfo.NONE && cx.canConvert(value, valueType)) {
380-
try {
381-
Object converted = cx.jsToJava(value, valueType);
382-
if (converted != null) {
383-
//noinspection rawtypes, unchecked
384-
builder.set((DataComponentType) type, converted);
385-
continue;
386-
}
387-
} catch (EvaluatorException e) {
388-
evalError = e;
389-
}
390-
}
391-
392-
var codec = type.codec();
393-
394-
if (codec == null) {
395-
failed = true;
396-
errors.add(Pair.of(type, "Component has non-serializable type"));
397-
continue;
398-
}
399-
400-
switch (codec.parse(reg.json(), JsonUtils.of(cx, value))) {
401-
case DataResult.Success<?> success ->
402-
//noinspection rawtypes, unchecked
403-
builder.set((DataComponentType) type, success.value());
404-
case DataResult.Error<?> error -> {
405-
failed = true;
406-
String message = evalError != null
407-
? "Failed to parse component from type wrappers and codec! Native: %s, Codec: %s".formatted(evalError.details(), error.message())
408-
: "Failed to parse component from codec: %s!".formatted(error.message());
409-
errors.add(Pair.of(type, message));
410-
}
411-
}
366+
wrapEntry(cx, entry, null, builder::set, errors::put);
412367
}
413368

414-
if (failed) {
415-
var msg = errors.build().map(pair -> {
416-
var type = pair.getFirst();
417-
var error = pair.getSecond();
418-
369+
if (!errors.isEmpty()) {
370+
var joiner = new StringJoiner("; ");
371+
errors.forEach((type, error) -> {
419372
var id = reg.access().registryOrThrow(Registries.DATA_COMPONENT_TYPE).getKeyOrNull(type);
420-
421-
return "'%s' -> %s".formatted(id, error);
422-
}).collect(Collectors.joining("; "));
423-
yield error(() -> "Invalid component map format, errored input: [%s]".formatted(msg), builder.build());
373+
joiner.add("'%s' -> %s".formatted(id, error));
374+
});
375+
yield error(() -> "Invalid component map format, errored input: [%s]".formatted(joiner.toString()), builder.build());
424376
} else {
425377
yield success(builder.build());
426378
}
@@ -448,69 +400,20 @@ static DataResult<DataComponentPatch> tryPatchOf(Context cx, @Nullable Object o)
448400
case Map<?, ?> map -> {
449401
var builder = DataComponentPatch.builder();
450402

451-
var failed = false;
452-
Stream.Builder<Pair<DataComponentType<?>, String>> errors = Stream.builder();
453-
454403
Map<DataComponentType<?>, ?> wrapped = Objects.requireNonNull(cx.optionalMapOf(map, COMPONENT_TYPE, TypeInfo.NONE));
404+
Map<DataComponentType<?>, String> errors = new HashMap<>();
455405

456406
for (var entry : wrapped.entrySet()) {
457-
var type = entry.getKey();
458-
var valueType = getTypeInfo(type);
459-
460-
var value = entry.getValue();
461-
EvaluatorException evalError = null;
462-
463-
if (value == null || value instanceof Undefined) {
464-
builder.remove(type);
465-
continue;
466-
}
467-
468-
// TODO: remove once shouldConvert check is in Rhino
469-
if (valueType != TypeInfo.NONE && cx.canConvert(value, valueType)) {
470-
try {
471-
Object converted = cx.jsToJava(value, valueType);
472-
if (converted != null) {
473-
//noinspection rawtypes, unchecked
474-
builder.set((DataComponentType) type, converted);
475-
continue;
476-
}
477-
} catch (EvaluatorException e) {
478-
evalError = e;
479-
}
480-
}
481-
482-
var codec = type.codec();
483-
484-
if (codec == null) {
485-
failed = true;
486-
errors.add(Pair.of(type, "Component has non-serializable type"));
487-
continue;
488-
}
489-
490-
switch (codec.parse(reg.json(), JsonUtils.of(cx, value))) {
491-
case DataResult.Success<?> success ->
492-
//noinspection rawtypes, unchecked
493-
builder.set((DataComponentType) type, success.value());
494-
case DataResult.Error<?> error -> {
495-
failed = true;
496-
String message = evalError != null
497-
? "Failed to parse component from type wrappers and codec! Native: %s, Codec: %s".formatted(evalError.details(), error.message())
498-
: "Failed to parse component from codec: %s!".formatted(error.message());
499-
errors.add(Pair.of(type, message));
500-
}
501-
}
407+
wrapEntry(cx, entry, builder::remove, builder::set, errors::put);
502408
}
503409

504-
if (failed) {
505-
var msg = errors.build().map(pair -> {
506-
var type = pair.getFirst();
507-
var error = pair.getSecond();
508-
410+
if (!errors.isEmpty()) {
411+
var joiner = new StringJoiner("; ");
412+
errors.forEach((type, error) -> {
509413
var id = reg.access().registryOrThrow(Registries.DATA_COMPONENT_TYPE).getKeyOrNull(type);
510-
511-
return "'%s' -> %s".formatted(id, error);
512-
}).collect(Collectors.joining("; "));
513-
yield error(() -> "Invalid component map format, errored input: [%s]".formatted(msg), builder.build());
414+
joiner.add("'%s' -> %s".formatted(id, error));
415+
});
416+
yield error(() -> "Invalid component map format, errored input: [%s]".formatted(joiner.toString()), builder.build());
514417
} else {
515418
yield success(builder.build());
516419
}
@@ -527,6 +430,56 @@ static DataResult<DataComponentPatch> tryPatchOf(Context cx, @Nullable Object o)
527430
};
528431
}
529432

433+
private static void wrapEntry(
434+
Context cx,
435+
Map.Entry<DataComponentType<?>, ?> entry,
436+
@Nullable Consumer<DataComponentType<?>> ifNull,
437+
@SuppressWarnings("rawtypes") BiConsumer<DataComponentType, Object> builder,
438+
BiConsumer<DataComponentType<?>, String> error
439+
) {
440+
var reg = RegistryAccessContainer.of(cx);
441+
442+
var type = entry.getKey();
443+
var valueType = getTypeInfo(type);
444+
445+
var value = entry.getValue();
446+
447+
if (value == null || value instanceof Undefined) {
448+
if (ifNull != null) {
449+
ifNull.accept(type);
450+
}
451+
452+
return;
453+
}
454+
455+
EvaluatorException evalError = null;
456+
457+
if (valueType.shouldConvert() && cx.canConvert(value, valueType)) {
458+
try {
459+
Object converted = cx.jsToJava(value, valueType);
460+
if (converted != null) {
461+
builder.accept(type, converted);
462+
return;
463+
}
464+
} catch (EvaluatorException e) {
465+
evalError = e;
466+
}
467+
}
468+
469+
var codec = type.codec();
470+
471+
if (codec != null) {
472+
switch (codec.parse(reg.json(), JsonUtils.of(cx, value))) {
473+
case DataResult.Success<?> success -> builder.accept(type, success.value());
474+
case DataResult.Error<?> err -> error.accept(type, evalError != null
475+
? "Failed to parse component from type wrappers and codec! Native: %s, Codec: %s".formatted(evalError.details(), err.message())
476+
: "Failed to parse component from codec: %s!".formatted(err.message()));
477+
}
478+
} else {
479+
error.accept(type, "Component has non-serializable type");
480+
}
481+
}
482+
530483
private static <B, T> DataResult<T> fnToBuilder(Context cx, Class<B> builderType, BaseFunction fn, Function<B, T> build) {
531484
try {
532485
B builder = Cast.to(cx.createInterfaceAdapter(TypeInfo.of(builderType), fn));

0 commit comments

Comments
 (0)