2020-04-15 14:22:03 +02:00
|
|
|
package com.minelittlepony.unicopia.util;
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2022-09-04 14:16:47 +02:00
|
|
|
import java.util.*;
|
2022-10-14 16:22:09 +02:00
|
|
|
import java.util.function.*;
|
2024-01-20 16:12:23 +01:00
|
|
|
import java.util.stream.Collectors;
|
2022-09-04 14:16:47 +02:00
|
|
|
import java.util.stream.Stream;
|
2021-08-23 13:42:04 +02:00
|
|
|
|
2022-10-07 16:52:35 +02:00
|
|
|
import com.mojang.datafixers.util.Pair;
|
2022-10-03 23:44:30 +02:00
|
|
|
import com.mojang.serialization.Codec;
|
|
|
|
|
2024-03-30 22:22:36 +01:00
|
|
|
import net.minecraft.item.ItemStack;
|
2022-09-04 14:16:47 +02:00
|
|
|
import net.minecraft.nbt.*;
|
2021-08-23 13:42:04 +02:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
2021-03-03 19:04:40 +01:00
|
|
|
import net.minecraft.util.math.Vec3d;
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2020-04-15 18:12:00 +02:00
|
|
|
public interface NbtSerialisable {
|
2022-10-03 23:44:30 +02:00
|
|
|
Serializer<BlockPos> BLOCK_POS = Serializer.of(NbtHelper::toBlockPos, NbtHelper::fromBlockPos);
|
2024-03-30 22:22:36 +01:00
|
|
|
Serializer<ItemStack> ITEM_STACK = Serializer.of(ItemStack::fromNbt, stack -> stack.writeNbt(new NbtCompound()));
|
2022-10-03 23:44:30 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
/**
|
|
|
|
* Called to save this to nbt to persist state on file or to transmit over the network
|
|
|
|
*
|
|
|
|
* @param compound Compound tag to write to.
|
|
|
|
*/
|
2021-12-23 17:52:40 +01:00
|
|
|
void toNBT(NbtCompound compound);
|
2020-01-16 12:35:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called to load this state from nbt
|
|
|
|
*
|
|
|
|
* @param compound Compound tag to read from.
|
|
|
|
*/
|
2021-12-23 17:52:40 +01:00
|
|
|
void fromNBT(NbtCompound compound);
|
2020-01-16 12:35:46 +01:00
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
default NbtCompound toNBT() {
|
|
|
|
NbtCompound compound = new NbtCompound();
|
2020-01-16 12:35:46 +01:00
|
|
|
toNBT(compound);
|
|
|
|
return compound;
|
|
|
|
}
|
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
static NbtList writeVector(Vec3d vector) {
|
|
|
|
NbtList list = new NbtList();
|
|
|
|
list.add(NbtDouble.of(vector.getX()));
|
|
|
|
list.add(NbtDouble.of(vector.getY()));
|
|
|
|
list.add(NbtDouble.of(vector.getZ()));
|
2021-03-03 19:04:40 +01:00
|
|
|
return list;
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
static Vec3d readVector(NbtList list) {
|
2021-03-03 19:04:40 +01:00
|
|
|
return new Vec3d(list.getDouble(0), list.getDouble(1), list.getDouble(2));
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|
2021-08-23 13:42:04 +02:00
|
|
|
|
2022-10-07 16:52:35 +02:00
|
|
|
static <T> Optional<T> decode(Codec<T> codec, NbtElement nbt) {
|
|
|
|
return codec.decode(NbtOps.INSTANCE, nbt).result().map(Pair::getFirst);
|
2021-08-23 13:42:04 +02:00
|
|
|
}
|
|
|
|
|
2022-10-03 23:44:30 +02:00
|
|
|
static <T> NbtElement encode(Codec<T> codec, T value) {
|
|
|
|
return codec.encodeStart(NbtOps.INSTANCE, value).result().get();
|
2021-08-23 13:42:04 +02:00
|
|
|
}
|
2022-09-04 14:16:47 +02:00
|
|
|
|
2022-10-14 16:22:09 +02:00
|
|
|
static NbtCompound subTag(String name, NbtCompound parent) {
|
|
|
|
NbtCompound child = new NbtCompound();
|
|
|
|
parent.put(name, child);
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NbtCompound subTag(String name, NbtCompound parent, Consumer<NbtCompound> writer) {
|
|
|
|
writer.accept(subTag(name, parent));
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
2024-01-20 16:12:23 +01:00
|
|
|
static <K, V> Map<K, V> readMap(NbtCompound nbt, Function<String, K> keyFunction, Function<NbtElement, V> valueFunction) {
|
|
|
|
return nbt.getKeys().stream().collect(Collectors.toMap(keyFunction, k -> valueFunction.apply(nbt.get(k))));
|
|
|
|
}
|
|
|
|
|
|
|
|
static <K, V> NbtCompound writeMap(Map<K, V> map, Function<K, String> keyFunction, Function<V, ? extends NbtElement> valueFunction) {
|
|
|
|
NbtCompound nbt = new NbtCompound();
|
|
|
|
map.forEach((k, v) -> {
|
|
|
|
nbt.put(keyFunction.apply(k), valueFunction.apply(v));
|
|
|
|
});
|
|
|
|
return nbt;
|
|
|
|
}
|
|
|
|
|
2022-09-04 14:16:47 +02:00
|
|
|
interface Serializer<T> {
|
|
|
|
T read(NbtCompound compound);
|
|
|
|
|
|
|
|
NbtCompound write(T t);
|
|
|
|
|
2022-10-03 23:44:30 +02:00
|
|
|
default Optional<T> readOptional(String name, NbtCompound compound) {
|
|
|
|
return compound.contains(name, NbtElement.COMPOUND_TYPE)
|
|
|
|
? Optional.ofNullable(read(compound.getCompound(name)))
|
|
|
|
: Optional.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
default void writeOptional(String name, NbtCompound compound, Optional<T> t) {
|
|
|
|
t.map(this::write).ifPresent(tag -> compound.put(name, tag));
|
|
|
|
}
|
|
|
|
|
2022-09-04 14:16:47 +02:00
|
|
|
default T read(NbtElement element) {
|
|
|
|
return read((NbtCompound)element);
|
|
|
|
}
|
|
|
|
|
2024-03-28 22:30:28 +01:00
|
|
|
default NbtList writeAll(Collection<? extends T> ts) {
|
2022-09-04 14:16:47 +02:00
|
|
|
NbtList list = new NbtList();
|
|
|
|
ts.stream().map(this::write).forEach(list::add);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
default Stream<T> readAll(NbtList list) {
|
|
|
|
return list.stream().map(this::read).filter(Objects::nonNull);
|
|
|
|
}
|
|
|
|
|
2022-10-14 16:22:09 +02:00
|
|
|
static <T extends NbtSerialisable> Serializer<T> of(Supplier<T> factory) {
|
|
|
|
return of(nbt -> {
|
|
|
|
T value = factory.get();
|
|
|
|
value.fromNBT(nbt);
|
|
|
|
return value;
|
|
|
|
}, value -> value.toNBT());
|
|
|
|
}
|
|
|
|
|
2022-09-04 14:16:47 +02:00
|
|
|
static <T> Serializer<T> of(Function<NbtCompound, T> read, Function<T, NbtCompound> write) {
|
|
|
|
return new Serializer<>() {
|
|
|
|
@Override
|
|
|
|
public T read(NbtCompound compound) {
|
|
|
|
return read.apply(compound);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public NbtCompound write(T t) {
|
|
|
|
return write.apply(t);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2020-01-16 12:35:46 +01:00
|
|
|
}
|