From dd3ac39530921e6c32a25bd30cb813dec6cc3445 Mon Sep 17 00:00:00 2001 From: Sen Date: Thu, 19 Jun 2025 18:28:10 +0200 Subject: [PATCH] add block map properly --- common/src/main/java/common/Version.java | 2 - server/src/main/java/server/Server.java | 3 +- .../src/main/java/server/world/Converter.java | 42 ++--- server/src/main/java/server/world/Region.java | 157 +++++++++--------- 4 files changed, 98 insertions(+), 106 deletions(-) diff --git a/common/src/main/java/common/Version.java b/common/src/main/java/common/Version.java index c2f059ab..bc57bfa9 100644 --- a/common/src/main/java/common/Version.java +++ b/common/src/main/java/common/Version.java @@ -8,6 +8,4 @@ public abstract class Version { public static final int MAJOR = 2; public static final int MINOR = 3; public static final int PATCH = 0; - - public static final int DATA = 0; } diff --git a/server/src/main/java/server/Server.java b/server/src/main/java/server/Server.java index bd453e95..c58b21f1 100755 --- a/server/src/main/java/server/Server.java +++ b/server/src/main/java/server/Server.java @@ -215,8 +215,6 @@ public final class Server implements IThreadListener, Executor { } private long loadServerConfig() { - Region.loadMaps(); - File file = new File("server.cdt"); if(!file.exists()) file = new File("server.cdt.tmp"); @@ -406,6 +404,7 @@ public final class Server implements IThreadListener, Executor { } public void run(long time) { + Region.loadMap(); Converter.convert(this); long wtime = this.loadServerConfig(); if(this.keyPair == null) { diff --git a/server/src/main/java/server/world/Converter.java b/server/src/main/java/server/world/Converter.java index 62bded83..8e2efbff 100644 --- a/server/src/main/java/server/world/Converter.java +++ b/server/src/main/java/server/world/Converter.java @@ -17,7 +17,6 @@ import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; -import common.Version; import common.biome.Biome; import common.block.Block; import common.block.BlockColored; @@ -1092,6 +1091,7 @@ public abstract class Converter { NbtTag[] sects = tag.getTagList("Sections"); entities = Lists.newArrayList(); + char[] mapping = Region.getEncodeMap(); for(NbtTag sect : sects) { TagObject nsect = new TagObject(); nsect.setInt("Y", sect.getByte("Y")); @@ -1105,39 +1105,25 @@ public abstract class Converter { int cz = c >> 4 & 15; int ca = adddata != null ? adddata.get(cx, cy, cz) : 0; char block = (char)((ca << 8) | (blocks[c] & 255)); -// if(block == 0) -// continue; -//// else if(block <= 197) { -//// if((blocks[c] = BLOCK_MAP[block]) != (byte)block) -//// data.set(cx, cy, cz, DATA_MAP[block]); -//// } - if(block >= 256) { - blocks[c] = (byte)1; - data.set(cx, cy, cz, 0); - } - else if(block > 0) { - int dt = block == 111 ? RANDOM.zrange(4) : data.get(cx, cy, cz); - char cd = BLOCK_MAP[(block << 4) | dt]; -// if(cd == (char)0x000f) -// cd = (char)BlockRegistry.STATEMAP.get(BLOCK_FUNCS.get((char)((block << 4) | dt)).getState(block, dt)); - if(cd >> 12 != 0) { - if(adddata == null) - adddata = new NibbleArray(); - adddata.set(cx, cy, cz, cd >> 12); - } - blocks[c] = (byte)(cd >> 4 & 255); - data.set(cx, cy, cz, cd & 15); + if(block == 0) + continue; + int dt = block == 111 ? RANDOM.zrange(4) : data.get(cx, cy, cz); + char cd = mapping[block >= 256 ? BLOCK_MAP[1 << 4] : BLOCK_MAP[(block << 4) | dt]]; + if(cd >> 12 != 0) { + if(adddata == null) + adddata = new NibbleArray(); + adddata.set(cx, cy, cz, cd >> 12); } + blocks[c] = (byte)(cd & 255); + data.set(cx, cy, cz, cd >> 8 & 15); } - nsect.setByteArray("Blocks", blocks); - nsect.setByteArray("Data", data.getData()); + nsect.setByteArray("Dat0", blocks); + nsect.setByteArray("Dat1", data.getData()); if(adddata != null) - nsect.setByteArray("Add", adddata.getData()); + nsect.setByteArray("Dat2", adddata.getData()); entities.add(nsect); } ntag.setList("Sections", entities); - - ntag.setInt("Version", Version.DATA); return ntag; } diff --git a/server/src/main/java/server/world/Region.java b/server/src/main/java/server/world/Region.java index 1c94523b..3a005257 100755 --- a/server/src/main/java/server/world/Region.java +++ b/server/src/main/java/server/world/Region.java @@ -19,7 +19,6 @@ import java.util.Set; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import common.Version; import common.block.Block; import common.collect.Lists; import common.collect.Maps; @@ -74,83 +73,97 @@ public class Region { return sb.toString(); } - private static TagObject makeMap() { - TagObject tag = new TagObject(); + private static boolean makeMap(TagObject tag) { + Map mapping = Maps.newHashMap(); + Map> current = Maps.newHashMap(); + Set taken = Sets.newHashSet(); + List missing = Lists.newArrayList(); for(int z = 0; z < 4096; z++) { Block block = BlockRegistry.getBlockById(z); if(block != Blocks.air) { Set stored = getSavedProperties(block); for(int n = 0; n < 16; n++) { - String id = filterProperties(block.getStateFromMeta(n), stored); - MAPPING.put(id, (char)z); - tag.setChar(id, (char)z); - // Log.IO.info("Block-ID %d:%d [%d] = %s", z, n, z << 4 | n, id); + State state = block.getStateFromMeta(n); + String id = filterProperties(state, stored); + List ids = current.get(id); + char mid = (char)BlockRegistry.STATEMAP.get(state); + if(ids == null) { + current.put(id, Lists.newArrayList(mid)); + } + else { + ids.add(mid); + continue; + } + if(tag.hasChar(id)) { + char bid = tag.getChar(id); + if(bid == 0) { + missing.add(id); + continue; + } + mapping.put(id, bid); + taken.add(bid); + tag.remove(id); + Log.IO.debug("Bestehende Block-ID %d = %s", (int)bid, id); + } + else { + missing.add(id); + } } } } - return tag; - } - - private static void cacheMap(TagObject tag, int version) { - char[] map = new char[65536]; - for(String key : tag.keySet()) { - if(tag.hasChar(key)) - map[tag.getChar(key)] = MAPPING.getOrDefault(key, (char)0); + char bid = 1; + for(String id : missing) { + while(taken.contains(bid)) { + ++bid; + } + mapping.put(id, bid); + tag.setChar(id, bid); + taken.add(bid); + Log.IO.debug("Neue Block-ID %d = %s", (int)bid, id); } - MAPS.put(version, map); + for(Entry entry : mapping.entrySet()) { + bid = entry.getValue(); + List ids = current.get(entry.getKey()); + DECODE_MAP[bid] = ids.get(0); + for(char id : ids) { + ENCODE_MAP[id] = bid; + } + } + for(String id : tag.keySet()) { + if(tag.hasChar(id)) + Log.IO.debug("Entfernte Block-ID %d = %s", (int)tag.getChar(id), id); + } + return !missing.isEmpty() || !tag.isEmpty(); } - public static void loadMaps() { - TagObject map = makeMap(); - File mapFile = new File(new File("mapping"), "m." + Version.DATA + ".cdt"); - if(!mapFile.exists()) { - mapFile.getParentFile().mkdirs(); + public static void loadMap() { + File mapFile = new File("blocks.cdt"); + TagObject tag; + if(mapFile.exists()) { try { - TagObject.writeGZip(map, mapFile); + tag = TagObject.readGZip(mapFile); } catch(Exception e) { - Log.IO.error(e, "Fehler beim Schreiben von " + mapFile); + tag = new TagObject(); + Log.IO.error(e, "Fehler beim Lesen von %s", mapFile); } } - File[] maps = new File("mapping").listFiles(file -> file.isFile() && file.getName().startsWith("m.") && file.getName().endsWith(".cdt")); - if(maps != null) { - for(File file : maps) { - String str = file.getName().substring(2, file.getName().length() - 4); - if(str.isEmpty()) - continue; - int version; - try { - version = Integer.parseUnsignedInt(str); - } - catch(NumberFormatException e) { - continue; - } - if(version == Version.DATA) - continue; - TagObject tag; - try { - tag = TagObject.readGZip(file); - } - catch(Exception e) { - Log.IO.error(e, "Fehler beim Lesen von " + file); - continue; - } - cacheMap(tag, version); + else { + tag = new TagObject(); + } + if(makeMap(tag)) { + Log.IO.info("Block-IDs haben sich geändert, schreibe %s", mapFile); + try { + TagObject.writeGZip(tag, mapFile); + } + catch(Exception e) { + Log.IO.error(e, "Fehler beim Schreiben von %s", mapFile); } } } - private static boolean remap(char[] data, int version, int x, int z) { - char[] map = MAPS.get(version); - if(map == null) { - Log.IO.error("Chunk %d, %d: Konnte keine Block-Datenbank für Version #%d finden", x, z, version); - return false; - } - Log.IO.info("Chunk %d, %d: Konvertiere Block-IDs von Version #%d zu #%d", x, z, version, Version.DATA); - for(int n = 0; n < data.length; n++) { - data[n] = map[data[n]]; - } - return true; + public static char[] getEncodeMap() { + return ENCODE_MAP; } private static class ChunkBuffer extends ByteArrayOutputStream { @@ -177,8 +190,8 @@ public class Region { private static final Map CACHE = Maps.newHashMap(); private static final List QUEUE = Collections.synchronizedList(Lists.newArrayList()); - private static final Map MAPS = Maps.newHashMap(); - private static final Map MAPPING = Maps.newHashMap(); + private static final char[] DECODE_MAP = new char[65536]; + private static final char[] ENCODE_MAP = new char[65536]; private static volatile long queued; private static volatile long saved; @@ -502,9 +515,9 @@ public class Region { TagObject sect = sects.get(n); int y = sect.getInt("Y"); BlockArray storage = new BlockArray(y << 4, light, null); - byte[] blocks = sect.getByteArray("Blocks"); - NibbleArray data = new NibbleArray(sect.getByteArray("Data")); - NibbleArray adddata = sect.hasByteArray("Add") ? new NibbleArray(sect.getByteArray("Add")) : null; + byte[] blocks = sect.getByteArray("Dat0"); + NibbleArray data = new NibbleArray(sect.getByteArray("Dat1")); + NibbleArray adddata = sect.hasByteArray("Dat2") ? new NibbleArray(sect.getByteArray("Dat2")) : null; char[] seg = new char[blocks.length]; for(int c = 0; c < seg.length; ++c) { @@ -512,11 +525,8 @@ public class Region { int cy = c >> 8 & 15; int cz = c >> 4 & 15; int ca = adddata != null ? adddata.get(cx, cy, cz) : 0; - seg[c] = (char)(ca << 12 | (blocks[c] & 255) << 4 | data.get(cx, cy, cz)); + seg[c] = DECODE_MAP[ca << 12 | data.get(cx, cy, cz) << 8 | (blocks[c] & 255)]; } - -// if(version != Version.DATA) -// remap(seg, version, x, z); storage.setData(seg); storage.setBlocklight(new NibbleArray(sect.getByteArray("BlockLight"))); @@ -602,7 +612,6 @@ public class Region { public static TagObject writeChunk(WorldServer world, ChunkServer chunk) { TagObject tag = new TagObject(); - tag.setInt("Version", Version.DATA); tag.setLong("LastUpdate", world.getTime()); tag.setIntArray("HeightMap", chunk.getHeights()); tag.setBool("TerrainPopulated", chunk.isTerrainPopulated()); @@ -621,7 +630,7 @@ public class Region { NibbleArray adddata = null; for(int c = 0; c < storage.getData().length; ++c) { - char cd = storage.getData()[c]; + char cd = ENCODE_MAP[storage.getData()[c]]; int cx = c & 15; int cy = c >> 8 & 15; int cz = c >> 4 & 15; @@ -634,15 +643,15 @@ public class Region { adddata.set(cx, cy, cz, cd >> 12); } - blocks[c] = (byte)(cd >> 4 & 255); - data.set(cx, cy, cz, cd & 15); + blocks[c] = (byte)(cd & 255); + data.set(cx, cy, cz, cd >> 8 & 15); } - sect.setByteArray("Blocks", blocks); - sect.setByteArray("Data", data.getData()); + sect.setByteArray("Dat0", blocks); + sect.setByteArray("Dat1", data.getData()); if(adddata != null) { - sect.setByteArray("Add", adddata.getData()); + sect.setByteArray("Dat2", adddata.getData()); } sect.setByteArray("BlockLight", storage.getBlocklight().getData());