Fix conversion during tag update

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2022-07-29 16:51:45 +02:00
parent 5b8cc12108
commit 0e082634d5
2 changed files with 61 additions and 1 deletions

View File

@ -12,6 +12,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTType;
import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound;
import java.lang.invoke.VarHandle;
import java.util.Map;
import java.util.function.UnaryOperator;
final class TagHandlerImpl implements TagHandler {
@ -99,12 +100,32 @@ final class TagHandlerImpl implements TagHandler {
}
private synchronized <T> T updateTag0(@NotNull Tag<T> tag, @NotNull UnaryOperator<T> value, boolean returnPrevious) {
if (tag.isView()) {
Node node = traversePathWrite(root, tag, true);
final T previousValue = tag.read(node.compound());
final T newValue = value.apply(previousValue);
node.updateContent((NBTCompoundLike) tag.entry.write(newValue));
node.invalidate();
return returnPrevious ? previousValue : newValue;
}
final int tagIndex = tag.index;
final Node node = traversePathWrite(root, tag, true);
StaticIntMap<Entry<?>> entries = node.entries;
final Entry previousEntry = entries.get(tagIndex);
final T previousValue = previousEntry != null ? (T) previousEntry.value : tag.createDefault();
final T previousValue;
if (previousEntry != null) {
final Object previousTmp = previousEntry.value;
if (previousTmp instanceof Node n) {
final NBTCompound compound = NBT.Compound(Map.of(tag.getKey(), n.compound()));
previousValue = tag.read(compound);
} else {
previousValue = (T) previousTmp;
}
} else {
previousValue = tag.createDefault();
}
final T newValue = value.apply(previousValue);
if (newValue != null) entries.put(tagIndex, valueToEntry(node, tag, newValue));
else entries.remove(tagIndex);

View File

@ -109,6 +109,45 @@ public class TagUpdateTest {
assertEquals(5, handler.getTag(tag2));
}
@Test
public void updateStructureConversion() {
record Test(int coin) {
}
var tag1 = Tag.Integer("coin").path("path");
var tag2 = Tag.Structure("path", Test.class);
var handler = TagHandler.newHandler();
handler.setTag(tag1, 5);
assertEquals(5, handler.getTag(tag1));
assertEquals(new Test(5), handler.getTag(tag2));
assertDoesNotThrow(() -> handler.updateTag(tag2, value -> new Test(value.coin + 1)));
assertEquals(6, handler.getTag(tag1));
assertEquals(new Test(6), handler.getTag(tag2));
handler.updateTag(tag2, value -> null);
assertNull(handler.getTag(tag1));
assertNull(handler.getTag(tag2));
}
@Test
public void updateViewConversion() {
record Test(int coin) {
}
var tag1 = Tag.Integer("coin");
var tag2 = Tag.View(Test.class);
var handler = TagHandler.newHandler();
handler.setTag(tag1, 5);
assertDoesNotThrow(() -> handler.updateTag(tag2, value -> new Test(value.coin + 1)));
assertEquals(6, handler.getTag(tag1));
assertEquals(new Test(6), handler.getTag(tag2));
handler.updateTag(tag2, value -> null);
assertNull(handler.getTag(tag1));
assertNull(handler.getTag(tag2));
}
@Test
public void updateIncompatible() {
var tagI = Tag.Integer("coin");