9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2026-01-06 15:51:30 +00:00

implement dynamic tile entities

This commit is contained in:
Julian Krings
2024-08-14 20:02:08 +02:00
parent b6457e47e6
commit f58078e8a0
29 changed files with 876 additions and 804 deletions

View File

@@ -10,11 +10,17 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -22,6 +28,8 @@ import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
@@ -30,6 +38,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -54,8 +63,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
@@ -127,55 +134,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -10,11 +10,17 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -22,6 +28,8 @@ import org.bukkit.craftbukkit.v1_19_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R2.CraftServer;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
@@ -30,6 +38,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -55,8 +64,6 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
@@ -128,55 +135,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -10,11 +10,17 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -22,6 +28,8 @@ import org.bukkit.craftbukkit.v1_19_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
@@ -30,6 +38,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -55,8 +64,6 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
@@ -129,55 +136,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -17,20 +17,23 @@ import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.scheduling.J;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -44,6 +47,8 @@ import org.bukkit.craftbukkit.v1_20_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
@@ -54,6 +59,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.entity.EntityType;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
@@ -67,6 +73,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
@@ -132,55 +139,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -10,17 +10,25 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
@@ -30,6 +38,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -55,8 +64,6 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
@@ -130,55 +137,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -10,17 +10,25 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
@@ -30,6 +38,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -55,8 +64,6 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
@@ -130,55 +137,106 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata();
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata();
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
if (tag instanceof CollectionTag<?> collection) {
KList<Object> list = new KList<>();
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
return list;
}
if (tag instanceof net.minecraft.nbt.CompoundTag compound) {
KMap<String, Object> map = new KMap<>();
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
return map;
}
return null;
if (tag instanceof NumericTag numeric)
return numeric.getAsNumber();
return tag.getAsString();
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
if (object instanceof Map<?,?> map) {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
return tag;
}
if (object instanceof List<?> list) {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
return tag;
}
if (object instanceof Byte number) return ByteTag.valueOf(number);
if (object instanceof Short number) return ShortTag.valueOf(number);
if (object instanceof Integer number) return IntTag.valueOf(number);
if (object instanceof Long number) return LongTag.valueOf(number);
if (object instanceof Float number) return FloatTag.valueOf(number);
if (object instanceof Double number) return DoubleTag.valueOf(number);
if (object instanceof String string) return StringTag.valueOf(string);
return EndTag.INSTANCE;
}
@Override

View File

@@ -1,24 +1,35 @@
package com.volmit.iris.core.nms.v1_20_R4;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.*;
import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.*;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.EndTag;
import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.LongTag;
import net.minecraft.nbt.ShortTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.commands.data.DataCommands;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.bukkit.*;
import org.bukkit.block.Biome;
@@ -26,6 +37,9 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R4.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockType;
import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack;
@@ -35,6 +49,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -49,19 +64,11 @@ import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
@@ -134,55 +141,109 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata(registry());
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata(registry());
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
}
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
return switch (tag) {
case CollectionTag<?> collection -> {
KList<Object> list = new KList<>();
return null;
}
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
yield list;
}
case net.minecraft.nbt.CompoundTag compound -> {
KMap<String, Object> map = new KMap<>();
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
yield map;
}
case NumericTag numeric -> numeric.getAsNumber();
default -> tag.getAsString();
};
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
return switch (object) {
case Map<?, ?> map -> {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
yield tag;
}
case List<?> list -> {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
yield tag;
}
case Byte number -> ByteTag.valueOf(number);
case Short number -> ShortTag.valueOf(number);
case Integer number -> IntTag.valueOf(number);
case Long number -> LongTag.valueOf(number);
case Float number -> FloatTag.valueOf(number);
case Double number -> DoubleTag.valueOf(number);
case String string -> StringTag.valueOf(string);
default -> EndTag.INSTANCE;
};
}
@Override
@@ -422,13 +483,13 @@ public class NMSBinding implements INMSBinding {
@Override
public MCAPaletteAccess createPalette() {
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId");
Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT");
Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId");
Field cf = IdMapper.class.getDeclaredField("tToId");
Field df = IdMapper.class.getDeclaredField("idToT");
Field bf = IdMapper.class.getDeclaredField("nextId");
cf.setAccessible(true);
df.setAccessible(true);
bf.setAccessible(true);
net.minecraft.core.IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
int b = bf.getInt(blockData);
Object2IntMap<BlockState> c = (Object2IntMap<BlockState>) cf.get(blockData);
List<BlockState> d = (List<BlockState>) df.get(blockData);

View File

@@ -8,18 +8,20 @@ import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import org.bukkit.*;
@@ -28,6 +30,8 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_21_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_21_R1.CraftServer;
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_21_R1.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_21_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
@@ -37,6 +41,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@@ -62,8 +67,6 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
@@ -136,55 +139,109 @@ public class NMSBinding implements INMSBinding {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Material material) {
return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material));
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
@SuppressWarnings("unchecked")
public KMap<String, Object> serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), false);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata(registry());
return convert(tag);
net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata(registry());
return (KMap<String, Object>) convertFromTag(tag, 0, 64);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
}
@Contract(value = "null, _, _ -> null", pure = true)
private Object convertFromTag(net.minecraft.nbt.Tag tag, int depth, int maxDepth) {
if (tag == null || depth > maxDepth) return null;
return switch (tag) {
case CollectionTag<?> collection -> {
KList<Object> list = new KList<>();
return null;
}
for (Object i : collection) {
if (i instanceof net.minecraft.nbt.Tag t)
list.add(convertFromTag(t, depth + 1, maxDepth));
else list.add(i);
}
yield list;
}
case net.minecraft.nbt.CompoundTag compound -> {
KMap<String, Object> map = new KMap<>();
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
for (String key : compound.getAllKeys()) {
var child = compound.get(key);
if (child == null) continue;
var value = convertFromTag(child, depth + 1, maxDepth);
if (value == null) continue;
map.put(key, value);
}
yield map;
}
case NumericTag numeric -> numeric.getAsNumber();
default -> tag.getAsString();
};
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
public void deserializeTile(KMap<String, Object> map, Location pos) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) convertToTag(map, 0, 64);
var level = ((CraftWorld) pos.getWorld()).getHandle();
var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
J.s(() -> merge(level, blockPos, tag));
}
private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) {
var blockEntity = level.getBlockEntity(blockPos);
if (blockEntity == null) {
Iris.warn("[NMS] BlockEntity not found at " + blockPos);
var state = level.getBlockState(blockPos);
if (!state.hasBlockEntity())
return;
blockEntity = ((EntityBlock) state.getBlock())
.newBlockEntity(blockPos, state);
}
var accessor = new BlockDataAccessor(blockEntity, blockPos);
accessor.setData(tag.merge(accessor.getData()));
}
private Tag convertToTag(Object object, int depth, int maxDepth) {
if (object == null || depth > maxDepth) return EndTag.INSTANCE;
return switch (object) {
case Map<?, ?> map -> {
var tag = new net.minecraft.nbt.CompoundTag();
for (var i : map.entrySet()) {
tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth));
}
yield tag;
}
case List<?> list -> {
var tag = new net.minecraft.nbt.ListTag();
for (var i : list) {
tag.add(convertToTag(i, depth + 1, maxDepth));
}
yield tag;
}
case Byte number -> ByteTag.valueOf(number);
case Short number -> ShortTag.valueOf(number);
case Integer number -> IntTag.valueOf(number);
case Long number -> LongTag.valueOf(number);
case Float number -> FloatTag.valueOf(number);
case Double number -> DoubleTag.valueOf(number);
case String string -> StringTag.valueOf(string);
default -> EndTag.INSTANCE;
};
}
@Override