add block map properly

This commit is contained in:
Sen 2025-06-19 18:28:10 +02:00
parent 64cff6a171
commit dd3ac39530
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
4 changed files with 98 additions and 106 deletions

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -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<String, Character> mapping = Maps.newHashMap();
Map<String, List<Character>> current = Maps.newHashMap();
Set<Character> taken = Sets.newHashSet();
List<String> missing = Lists.newArrayList();
for(int z = 0; z < 4096; z++) {
Block block = BlockRegistry.getBlockById(z);
if(block != Blocks.air) {
Set<IProperty> 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<Character> 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<String, Character> entry : mapping.entrySet()) {
bid = entry.getValue();
List<Character> 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<String, Region> CACHE = Maps.<String, Region>newHashMap();
private static final List<WorldServer> QUEUE = Collections.<WorldServer>synchronizedList(Lists.<WorldServer>newArrayList());
private static final Map<Integer, char[]> MAPS = Maps.newHashMap();
private static final Map<String, Character> 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());