9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-04 15:41:38 +00:00

add slime world support

This commit is contained in:
XiaoMoMi
2025-03-29 01:49:37 +08:00
parent 7b1855d76f
commit 81ac75adb0
6 changed files with 80 additions and 16 deletions

View File

@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.compatibility.slimeworld;
import com.infernalsuite.asp.api.AdvancedSlimePaperAPI;
import com.infernalsuite.asp.api.events.LoadSlimeWorldEvent;
import com.infernalsuite.asp.api.world.SlimeWorld;
import net.momirealms.craftengine.core.util.ReflectionUtils;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldManager;
import net.momirealms.craftengine.core.world.chunk.storage.DefaultStorageAdaptor;
@@ -12,13 +13,18 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
public class SlimeFormatStorageAdaptor extends DefaultStorageAdaptor implements Listener {
private final WorldManager worldManager;
private final Class<?> byteArrayTagClass = ReflectionUtils.getClazz("net{}kyori{}adventure{}nbt{}ByteArrayBinaryTag".replace("{}", "."));
private final Method method$ByteArrayBinaryTag$byteArrayBinaryTag = ReflectionUtils.getStaticMethod(byteArrayTagClass, byteArrayTagClass, byte.class.arrayType());
private final Method method$ByteArrayBinaryTag$value = ReflectionUtils.getMethod(byteArrayTagClass, byte.class.arrayType());
@EventHandler
public void onWorldLoad(LoadSlimeWorldEvent event) {
org.bukkit.World world = Bukkit.getWorld(event.getSlimeWorld().getName());
this.worldManager.loadWorld(this.worldManager.wrap(world));
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world), new SlimeWorldDataStorage(event.getSlimeWorld(), this)));
}
public SlimeFormatStorageAdaptor(WorldManager worldManager) {
@@ -29,12 +35,29 @@ public class SlimeFormatStorageAdaptor extends DefaultStorageAdaptor implements
return AdvancedSlimePaperAPI.instance().getLoadedWorld(name);
}
// 请注意在加载事件的时候无法通过AdvancedSlimePaperAPI.instance().getLoadedWorld来判断是否为slime世界
@Override
public @NotNull WorldDataStorage adapt(@NotNull World world) {
SlimeWorld slimeWorld = getWorld(world.name());
if (slimeWorld == null) {
return super.adapt(world);
}
return new SlimeWorldDataStorage(slimeWorld);
return new SlimeWorldDataStorage(slimeWorld, this);
}
public byte[] byteArrayTagToBytes(Object byteArrayTag) {
try {
return (byte[]) method$ByteArrayBinaryTag$value.invoke(byteArrayTag);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Failed to convert byte array tag to byte[]", e);
}
}
public Object bytesToByteArrayTag(byte[] bytes) {
try {
return method$ByteArrayBinaryTag$byteArrayBinaryTag.invoke(null, (Object) bytes);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Failed to convert byte array tag to byte[]", e);
}
}
}

View File

@@ -2,8 +2,6 @@ package net.momirealms.craftengine.bukkit.compatibility.slimeworld;
import com.infernalsuite.asp.api.world.SlimeChunk;
import com.infernalsuite.asp.api.world.SlimeWorld;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.ByteArrayBinaryTag;
import net.momirealms.craftengine.core.world.ChunkPos;
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
import net.momirealms.sparrow.nbt.CompoundTag;
@@ -14,12 +12,15 @@ import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Map;
public class SlimeWorldDataStorage implements WorldDataStorage {
private final WeakReference<SlimeWorld> slimeWorld;
private final SlimeFormatStorageAdaptor adaptor;
public SlimeWorldDataStorage(SlimeWorld slimeWorld) {
public SlimeWorldDataStorage(SlimeWorld slimeWorld, SlimeFormatStorageAdaptor adaptor) {
this.slimeWorld = new WeakReference<>(slimeWorld);
this.adaptor = adaptor;
}
public SlimeWorld getWorld() {
@@ -31,16 +32,16 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
public CompoundTag readChunkTagAt(ChunkPos pos) {
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
if (slimeChunk == null) return null;
BinaryTag tag = slimeChunk.getExtraData().get("craftengine");
Object tag = slimeChunk.getExtraData().get("craftengine");
if (tag == null) return null;
ByteArrayBinaryTag byteArrayBinaryTag = (ByteArrayBinaryTag) tag;
try {
return NBT.readCompound(new DataInputStream(new ByteArrayInputStream(byteArrayBinaryTag.value())));
} catch (IOException e) {
return NBT.readCompound(new DataInputStream(new ByteArrayInputStream(adaptor.byteArrayTagToBytes(tag))));
} catch (Exception e) {
throw new RuntimeException("Failed to read chunk tag from slime world. " + pos, e);
}
}
@SuppressWarnings("unchecked")
@Override
public void writeChunkTagAt(ChunkPos pos, @Nullable CompoundTag nbt) {
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
@@ -48,13 +49,14 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
if (nbt == null) {
slimeChunk.getExtraData().remove("craftengine");
} else {
slimeChunk.getExtraData().computeIfAbsent("craftengine", l -> {
try {
return ByteArrayBinaryTag.byteArrayBinaryTag(NBT.toBytes(nbt));
} catch (IOException e) {
throw new RuntimeException("Failed to write chunk tag to slime world. " + pos, e);
}
});
try {
Object tag = adaptor.bytesToByteArrayTag(NBT.toBytes(nbt));
Map<String, ?> data1 = slimeChunk.getExtraData();
Map<String, Object> data2 = (Map<String, Object>) data1;
data2.put("craftengine", tag);
} catch (Exception e) {
throw new RuntimeException("Failed to write chunk tag to slime world. " + pos, e);
}
}
}