From 64cff6a171699ee06c326b202789a03ee1f97a9e Mon Sep 17 00:00:00 2001 From: Sen Date: Thu, 19 Jun 2025 16:21:15 +0200 Subject: [PATCH] add block map (will reimplement this) --- common/src/main/java/common/Version.java | 2 + server/src/main/java/server/Server.java | 2 + .../src/main/java/server/world/Converter.java | 3 + server/src/main/java/server/world/Region.java | 127 +++++++++++++++++- 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/common/Version.java b/common/src/main/java/common/Version.java index bc57bfa9..c2f059ab 100644 --- a/common/src/main/java/common/Version.java +++ b/common/src/main/java/common/Version.java @@ -8,4 +8,6 @@ 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 2145dda8..bd453e95 100755 --- a/server/src/main/java/server/Server.java +++ b/server/src/main/java/server/Server.java @@ -215,6 +215,8 @@ 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"); diff --git a/server/src/main/java/server/world/Converter.java b/server/src/main/java/server/world/Converter.java index 7b7bc10f..62bded83 100644 --- a/server/src/main/java/server/world/Converter.java +++ b/server/src/main/java/server/world/Converter.java @@ -17,6 +17,7 @@ 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; @@ -1135,6 +1136,8 @@ public abstract class Converter { 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 114c9639..1c94523b 100755 --- a/server/src/main/java/server/world/Region.java +++ b/server/src/main/java/server/world/Region.java @@ -14,26 +14,145 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; 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; +import common.collect.Sets; import common.entity.Entity; import common.init.BlockRegistry; import common.init.Blocks; import common.init.EntityRegistry; import common.log.Log; +import common.properties.IProperty; import common.tags.TagObject; import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.NibbleArray; import common.util.Util; import common.world.BlockArray; +import common.world.State; public class Region { + private static Set getSavedProperties(Block block) { + Set stored = Sets.newHashSet(); + Map map = Maps.newHashMap(); + for(int z = 0; z < 16; z++) { + State sub = block.getStateFromMeta(z); + for(Entry entry : sub.getProperties().entrySet()) { + if(map.containsKey(entry.getKey())) { + if(!map.get(entry.getKey()).equals(entry.getValue())) + stored.add(entry.getKey()); + } + else { + map.put(entry.getKey(), entry.getValue()); + } + } + } + for(int z = 0; z < 16; z++) { + State sub = block.getStateFromMeta(z); + Map smap = sub.getProperties(); + for(IProperty prop : map.keySet()) { + if(!smap.containsKey(prop)) + stored.add(prop); + } + } + return stored; + } + + private static String filterProperties(State state, Set stored) { + StringBuilder sb = new StringBuilder(BlockRegistry.getNameFromBlock(state.getBlock())); + for(Entry entry : state.getProperties().entrySet()) { + if(stored.contains(entry.getKey())) + sb.append(',').append(entry.getKey().getName()).append('=').append(entry.getKey().getName(entry.getValue())); + } + return sb.toString(); + } + + private static TagObject makeMap() { + TagObject tag = new TagObject(); + 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); + } + } + } + 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); + } + MAPS.put(version, map); + } + + public static void loadMaps() { + TagObject map = makeMap(); + File mapFile = new File(new File("mapping"), "m." + Version.DATA + ".cdt"); + if(!mapFile.exists()) { + mapFile.getParentFile().mkdirs(); + try { + TagObject.writeGZip(map, mapFile); + } + catch(Exception e) { + Log.IO.error(e, "Fehler beim Schreiben von " + 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); + } + } + } + + 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; + } + private static class ChunkBuffer extends ByteArrayOutputStream { public ChunkBuffer() { super(8096); @@ -58,6 +177,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 volatile long queued; private static volatile long saved; @@ -367,6 +488,7 @@ public class Region { Log.IO.warn("Chunk-Datei bei " + x + "," + z + " hat keine Block-Daten, überspringe"); return null; } + int version = tag.getInt("Version"); ChunkServer chunk = new ChunkServer(world, x, z); chunk.setHeights(tag.getIntArray("HeightMap")); chunk.setTerrainPopulated(tag.getBool("TerrainPopulated")); @@ -392,6 +514,9 @@ public class Region { int ca = adddata != null ? adddata.get(cx, cy, cz) : 0; seg[c] = (char)(ca << 12 | (blocks[c] & 255) << 4 | data.get(cx, cy, cz)); } + +// if(version != Version.DATA) +// remap(seg, version, x, z); storage.setData(seg); storage.setBlocklight(new NibbleArray(sect.getByteArray("BlockLight"))); @@ -477,7 +602,7 @@ public class Region { public static TagObject writeChunk(WorldServer world, ChunkServer chunk) { TagObject tag = new TagObject(); -// tag.setShort("V", (short)Config.PROTOCOL); + tag.setInt("Version", Version.DATA); tag.setLong("LastUpdate", world.getTime()); tag.setIntArray("HeightMap", chunk.getHeights()); tag.setBool("TerrainPopulated", chunk.isTerrainPopulated());