mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 14:07:43 +01:00
Improve tag value sharing
This commit is contained in:
parent
edabb19891
commit
8dcb3191f6
@ -35,29 +35,34 @@ public class Tag<T> {
|
||||
final Function<T, NBT> writeFunction;
|
||||
private final Supplier<T> defaultValue;
|
||||
|
||||
final Function<?, ?> originalRead;
|
||||
// Optional properties
|
||||
final List<PathEntry> path;
|
||||
final UnaryOperator<T> copy;
|
||||
final int listScope;
|
||||
|
||||
Tag(int index, String key,
|
||||
Function<NBT, T> readFunction,
|
||||
Function<T, NBT> writeFunction,
|
||||
@Nullable Supplier<T> defaultValue, @Nullable List<PathEntry> path,
|
||||
@Nullable UnaryOperator<T> copy) {
|
||||
Function<?, ?> originalRead,
|
||||
Function<NBT, T> readFunction, Function<T, NBT> writeFunction,
|
||||
Supplier<T> defaultValue, List<PathEntry> path, UnaryOperator<T> copy, int listScope) {
|
||||
assert index == INDEX_MAP.get(key);
|
||||
this.index = index;
|
||||
this.key = key;
|
||||
this.originalRead = originalRead;
|
||||
this.readFunction = readFunction;
|
||||
this.writeFunction = writeFunction;
|
||||
this.defaultValue = defaultValue;
|
||||
this.path = path;
|
||||
this.copy = copy;
|
||||
this.listScope = listScope;
|
||||
}
|
||||
|
||||
static <T, N extends NBT> Tag<T> tag(@NotNull String key,
|
||||
@NotNull Function<N, T> readFunction,
|
||||
@NotNull Function<T, N> writeFunction) {
|
||||
return new Tag<>(INDEX_MAP.get(key), key, (Function<NBT, T>) readFunction, (Function<T, NBT>) writeFunction,
|
||||
null, null, null);
|
||||
return new Tag<>(INDEX_MAP.get(key), key, readFunction,
|
||||
(Function<NBT, T>) readFunction, (Function<T, NBT>) writeFunction,
|
||||
null, null, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +76,7 @@ public class Tag<T> {
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public Tag<T> defaultValue(@NotNull Supplier<T> defaultValue) {
|
||||
return new Tag<>(index, key, readFunction, writeFunction, defaultValue, path, copy);
|
||||
return new Tag<>(index, key, originalRead, readFunction, writeFunction, defaultValue, path, copy, listScope);
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
@ -83,6 +88,7 @@ public class Tag<T> {
|
||||
public <R> Tag<R> map(@NotNull Function<T, R> readMap,
|
||||
@NotNull Function<R, T> writeMap) {
|
||||
return new Tag<>(index, key,
|
||||
readMap,
|
||||
// Read
|
||||
readFunction.andThen(t -> {
|
||||
if (t == null) return null;
|
||||
@ -92,13 +98,13 @@ public class Tag<T> {
|
||||
writeMap.andThen(writeFunction),
|
||||
// Default value
|
||||
() -> readMap.apply(createDefault()),
|
||||
path, null);
|
||||
path, null, listScope);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@Contract(value = "-> new", pure = true)
|
||||
public Tag<List<T>> list() {
|
||||
return new Tag<>(index, key,
|
||||
return new Tag<>(index, key, originalRead,
|
||||
read -> {
|
||||
var list = (NBTList<?>) read;
|
||||
final int size = list.getSize();
|
||||
@ -138,14 +144,15 @@ public class Tag<T> {
|
||||
array[i] = copy;
|
||||
}
|
||||
return shallowCopy ? List.copyOf(ts) : List.of(array);
|
||||
} : List::copyOf);
|
||||
} : List::copyOf, listScope + 1);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public Tag<T> path(@NotNull String @Nullable ... path) {
|
||||
final List<PathEntry> entries = path != null ? Arrays.stream(path).map(s -> new PathEntry(s, INDEX_MAP.get(s))).toList() : null;
|
||||
return new Tag<>(index, key, readFunction, writeFunction, defaultValue, entries, copy);
|
||||
return new Tag<>(index, key, originalRead,
|
||||
readFunction, writeFunction, defaultValue, entries, copy, listScope);
|
||||
}
|
||||
|
||||
public @Nullable T read(@NotNull NBTCompoundLike nbt) {
|
||||
@ -186,7 +193,7 @@ public class Tag<T> {
|
||||
final boolean shareValue(@NotNull Tag<?> other) {
|
||||
// Verify if these 2 tags can share the same cached value
|
||||
// Key/Default value/Path are ignored
|
||||
return this == other || this.readFunction == other.readFunction;
|
||||
return this == other || (this.originalRead == other.originalRead && this.listScope == other.listScope);
|
||||
}
|
||||
|
||||
public static @NotNull Tag<Byte> Byte(@NotNull String key) {
|
||||
|
@ -2,6 +2,8 @@ package net.minestom.server.tag;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ -10,6 +12,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
*/
|
||||
public class TagEqualityTest {
|
||||
|
||||
record Entry(int value) {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void same() {
|
||||
var tag = Tag.String("test");
|
||||
@ -37,17 +42,58 @@ public class TagEqualityTest {
|
||||
assertFalse(tag.shareValue(tag2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapSame() {
|
||||
// Force identical functions
|
||||
Function<Integer, Entry> t1 = Entry::new;
|
||||
Function<Entry, Integer> t2 = Entry::value;
|
||||
|
||||
var tag = Tag.Integer("key");
|
||||
var map1 = tag.map(t1, t2);
|
||||
var map2 = tag.map(t1, t2);
|
||||
assertTrue(map1.shareValue(map2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapChild() {
|
||||
var intTag = Tag.Integer("key");
|
||||
var tag = intTag.map(Entry::new, Entry::value);
|
||||
assertFalse(intTag.shareValue(tag));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() {
|
||||
var tag = Tag.String("test").list();
|
||||
assertTrue(tag.shareValue(tag));
|
||||
}
|
||||
|
||||
//@Test
|
||||
@Test
|
||||
public void listScope() {
|
||||
var tag = Tag.String("test");
|
||||
assertFalse(tag.shareValue(tag.list()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void similarList() {
|
||||
// TODO make work
|
||||
var tag = Tag.String("test").list();
|
||||
var tag2 = Tag.String("test").list();
|
||||
assertTrue(tag.shareValue(tag2));
|
||||
assertTrue(tag.list().shareValue(tag2.list()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void differentList() {
|
||||
var tag = Tag.String("test").list();
|
||||
var tag2 = Tag.String("test").list();
|
||||
assertFalse(tag.shareValue(tag2.list()));
|
||||
assertFalse(tag.list().shareValue(tag2.list().list()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void differentListType() {
|
||||
var tag = Tag.String("test").list();
|
||||
var tag2 = Tag.Integer("test").list();
|
||||
assertFalse(tag.shareValue(tag2));
|
||||
assertFalse(tag.list().shareValue(tag2.list()));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user