personthecat.catlib.serialization.codec.EasyMapReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of catlib-quilt Show documentation
Show all versions of catlib-quilt Show documentation
Utilities for serialization, commands, noise generation, IO, and some new data types.
The newest version!
package personthecat.catlib.serialization.codec;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.MapLike;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
@SuppressWarnings("unused")
public class EasyMapReader {
private final DynamicOps ops;
private final T prefix;
public EasyMapReader(final DynamicOps ops, final T prefix) {
this.ops = ops;
this.prefix = prefix;
}
public DataResult run(final Function, A> runner) {
final DataResult> mapResult = this.ops.getMap(this.prefix);
if (mapResult.error().isPresent()) {
return DataResult.error(mapResult.error().get().message());
}
assert mapResult.result().isPresent();
final Context ctx = new Context<>(mapResult.result().get(), this.ops, this.prefix);
try {
return DataResult.success(runner.apply(ctx));
} catch (final EasyMapException e) {
return DataResult.error(e.getMessage());
}
}
public DataResult> runPaired(final Function, A> runner) {
return run(ctx -> Pair.of(runner.apply(ctx), this.ops.createList(Stream.empty())));
}
public static class Context {
private final MapLike map;
private final DynamicOps ops;
private final T prefix;
private Class extends T> listClass;
private Class extends T> mapClass;
private Context(final MapLike map, final DynamicOps ops, final T prefix) {
this.map = map;
this.ops = ops;
this.prefix = prefix;
}
@Nullable
public T get(final String key) {
return this.map.get(key);
}
public T mapOrNew(final String key) {
// Invalid type will be handled later
final T map = this.map.get(key);
return map == null ? this.ops.emptyMap() : map;
}
public T easyListOrNew(final String key) {
final T list = this.easyList(key);
return list == null ? this.ops.emptyList() : list;
}
@Nullable
public T easyList(final String key) {
final T list = this.map.get(key);
if (list == null) return null;
return asOrToList(list);
}
private T asOrToList(final T list) {
if (list.getClass() != this.getListClass()) {
final T newList = this.ops.emptyList();
final DataResult result = this.ops.mergeToList(newList, list);
if (result.error().isPresent()) {
throw new EasyMapException("Creating list: " + result.error().get().message());
}
assert result.result().isPresent();
return result.result().get();
}
return list;
}
public A readThis(final Codec codec) {
return this.getOrThrow(codec, this.prefix);
}
public boolean readBool(final String key) {
return this.read(Codec.BOOL, key);
}
public boolean readBool(final String key, final Supplier def) {
return this.read(Codec.BOOL, key, def);
}
public double readDouble(final String key) {
return this.read(Codec.DOUBLE, key);
}
public double readDouble(final String key, final Supplier def) {
return this.read(Codec.DOUBLE, key, def);
}
public float readFloat(final String key) {
return this.read(Codec.FLOAT, key);
}
public float readFloat(final String key, final Supplier def) {
return this.read(Codec.FLOAT, key, def);
}
public int readInt(final String key) {
return this.read(Codec.INT, key);
}
public int readInt(final String key, final Supplier def) {
return this.read(Codec.INT, key, def);
}
public String readString(final String key) {
return this.read(Codec.STRING, key);
}
public String readString(final String key, final Supplier def) {
return this.read(Codec.STRING, key, def);
}
public A read(final Codec codec, final String key) {
final T t = this.map.get(key);
if (t == null) throw this.missingValue(key);
return this.getOrThrow(codec, t);
}
public A read(final Codec codec, final String key, final Supplier def) {
final T t = this.map.get(key);
if (t == null) return def.get();
return this.getOrThrow(codec, t);
}
public Optional readOptional(final Codec codec, final String key) {
final T t = this.map.get(key);
if (t == null) return Optional.empty();
return Optional.of(this.getOrThrow(codec, t));
}
public A error(final String message) {
throw new EasyMapException(message);
}
@SuppressWarnings("unchecked")
private Class extends T> getListClass() {
if (this.listClass == null) {
this.listClass = (Class extends T>) this.ops.emptyList().getClass();
}
return this.listClass;
}
@SuppressWarnings("unchecked")
private Class extends T> getMapClass() {
if (this.mapClass == null) {
this.mapClass = (Class extends T>) this.ops.emptyMap().getClass();
}
return this.mapClass;
}
private EasyMapException missingValue(final String key) {
return new EasyMapException("Missing value: " + key);
}
private A getOrThrow(final Codec codec, final T t) {
return codec.parse(this.ops, t).get().map(Function.identity(), partial -> {
throw new EasyMapException(partial.message());
});
}
}
private static class EasyMapException extends RuntimeException {
EasyMapException(final String msg) {
super(msg);
}
}
}