diff --git a/client/src/client/Client.java b/client/src/client/Client.java index ddeec71..e0ab9f0 100755 --- a/client/src/client/Client.java +++ b/client/src/client/Client.java @@ -162,7 +162,6 @@ import common.util.Util; import common.util.HitPosition.ObjectType; import common.world.Chunk; import common.world.LightType; -import common.world.Region; import common.world.State; import common.world.World; import common.world.WorldClient; @@ -280,7 +279,7 @@ public class Client implements IThreadListener, IClient { private final List chat = Lists.newArrayList(); private final List feed = Lists.newArrayList(); private final List hotbar = Lists.newArrayList(); - private final File config = new File(System.getProperty("config.file", "game.cfg")); + private final File config = new File(System.getProperty("config.file", "client.cfg")); private boolean primary; private boolean secondary; @@ -1775,8 +1774,8 @@ public class Client implements IThreadListener, IClient { String.format("XYZ: %.3f / %.3f / %.3f", this.viewEntity.posX, this.viewEntity.getEntityBoundingBox().minY, this.viewEntity.posZ) + "\n" + String.format("Block: %d %d %d, R: '%s/%s'", blockpos.getX(), blockpos.getY(), blockpos.getZ(), - Region.getRegionFolder(blockpos.getX() >> 4, blockpos.getZ() >> 4), - Region.getRegionName(blockpos.getX() >> 4, blockpos.getZ() >> 4)) + "\n" + + Util.getRegionFolder(blockpos.getX() >> 4, blockpos.getZ() >> 4), + Util.getRegionName(blockpos.getX() >> 4, blockpos.getZ() >> 4)) + "\n" + String.format("Chunk: %d %d %d + %d %d %d, FOV: %.1f °%s", blockpos.getX() >> 4, blockpos.getY() >> 4, blockpos.getZ() >> 4, blockpos.getX() & 15, blockpos.getY() & 15, blockpos.getZ() & 15, this.zooming ? (this.fov / this.zoomLevel) : this.fov, this.zooming ? @@ -2217,7 +2216,6 @@ public class Client implements IThreadListener, IClient { Log.SYSTEM.info("Beende ..."); unload(false); this.getSoundManager().unload(); - Region.killIO(); this.renderGlobal.stopChunkBuilders(); if(audio.end()) Log.SOUND.info("Audiogerät geschlossen"); diff --git a/client/src/client/gui/GuiConvert.java b/client/src/client/gui/GuiConvert.java deleted file mode 100755 index e3e0a31..0000000 --- a/client/src/client/gui/GuiConvert.java +++ /dev/null @@ -1,214 +0,0 @@ -package client.gui; - -import java.io.File; -import java.io.FileFilter; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; - -import client.Client.FileMode; -import client.gui.element.ActButton; -import client.gui.element.ActButton.Mode; -import client.gui.element.GuiList; -import client.gui.element.ListEntry; -import client.gui.element.NavButton; -import client.renderer.Drawing; -import client.world.Converter; -import common.color.TextColor; -import common.dimension.Space; -import common.log.Log; -import common.world.Region; -import common.world.World; -import common.world.Region.FolderInfo; -import common.world.Region.SaveVersion; - -public class GuiConvert extends GuiList implements ActButton.Callback -{ - protected class SaveInfo implements Comparable, ListEntry { - private final String file; - private final int dimensions; - private final int players; - private final long seed; - private final FolderInfo info; - - public SaveInfo(String file, int dimensions, int players, long seed, FolderInfo info) { - this.file = file; - this.dimensions = dimensions; - this.players = players; - this.seed = seed; - this.info = info; - } - - public String getFile() { - return this.file; - } - - public int getDimensions() { - return this.dimensions; - } - - public int getPlayers() { - return this.players; - } - - public boolean mustConvert() { - return this.info.legacy != null; - } - - public String getVersion() { - return this.info.legacy == null ? (this.info.version == null ? "" : this.info.version) : this.info.legacy.toString(); - } - - public boolean isIncompatible() { - return this.info.legacy == SaveVersion.RELEASE_1_13; - } - - public long getLastPlayed() { - return this.info.lastPlayed; - } - - public long getSeed() { - return this.seed; - } - - public int compareTo(SaveInfo comp) { - return this.info.lastPlayed < comp.info.lastPlayed ? 1 : (this.info.lastPlayed > comp.info.lastPlayed ? -1 : this.file.compareTo(comp.file)); - } - - public void select(boolean isDoubleClick, int mouseX, int mouseY) - { - boolean use = !this.isIncompatible() && this.mustConvert(); - GuiConvert.this.selectButton.enabled = use; - - if (isDoubleClick && use) - { - GuiConvert.this.use(GuiConvert.this.selectButton, Mode.PRIMARY); - } - } - - public void draw(int x, int y, int mouseXIn, int mouseYIn, boolean hover) - { - Drawing.drawText((this.isIncompatible() ? TextColor.DRED : "") + this.getFile() + (this.mustConvert() ? "" : - (TextColor.GRAY + " - " + TextColor.RESET + (this.getPlayers() > 0 ? this.getPlayers() + " Spieler" : "Keine Spieler"))), - x + 2, y, 0xffffffff); - Drawing.drawText((this.mustConvert() ? (this.isIncompatible() ? TextColor.CRIMSON : "") + this.getVersion() : (this.getDimensions() <= 0 ? "Keine Dimensionen" : this.getDimensions() + " Dimension" + (this.getDimensions() != 1 ? "en" : "") + " erschaffen")) - , x + 2, y + 18, 0xff808080); - Drawing.drawText(this.mustConvert() ? (this.isIncompatible() ? TextColor.CRIMSON + "Kann nicht konvertiert werden!" : - "Muss konvertiert werden!") : ( // "Kreativmodus: " + (info.isNoCreative() ? "Aus" : "An") + - "Zuletzt gespielt: " + DATE_FORMAT.format(new Date(this.getLastPlayed()))) + " " + TextColor.LGRAY + this.getVersion(), x + 2, y + 18 + 16, 0xff808080); - } - } - - public static final GuiConvert INSTANCE = new GuiConvert(); - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); - - private ActButton selectButton; - private File dir = null; - - private GuiConvert() - { - } - - private void load() { - this.elements.clear(); - if(this.dir == null || !this.dir.exists() || !this.dir.isDirectory()) - return; - try - { - File[] files = dir.listFiles(); - if(files == null) - throw new RuntimeException("Kann den Speicherordner für Welten nicht lesen oder öffnen!"); - for(File file : files) { - if(!file.isDirectory()) - continue; - FolderInfo info = Region.loadWorldInfo(file); - if(info == null) - info = Converter.convertMapFormat(file, false); - if(info == null) { - this.elements.add(new SaveInfo(file.getName(), -1, -1, - 0L, new FolderInfo(World.START_TIME, file.lastModified(), null, null))); - continue; - } - int dims = -1; - int players = -1; - if(info.legacy == null) { - dims = 0; - File[] folders = new File(new File(dir, file.getName()), "chunk").listFiles(new FileFilter() { - public boolean accept(File pathname) { - return pathname.isDirectory() && !pathname.getName().equals(Space.INSTANCE.getDimensionName()); - } - }); - if(folders != null) { - for(File sub : folders) { - File[] dim = sub.listFiles(); - if(dim != null && dim.length > 0) - dims++; - } - } - File[] plrs = new File(new File(dir, file.getName()), "players").listFiles(new FileFilter() { - public boolean accept(File pathname) { - return pathname.getName().endsWith(".nbt"); - } - }); - players = plrs == null ? 0 : plrs.length; - } - this.elements.add(new SaveInfo(file.getName(), dims, players, - 0L, info)); - } - Collections.sort(this.elements); - } - catch (Exception e) - { - Log.IO.error("Konnte Weltliste nicht laden", e); - this.elements.clear(); - } - } - - public void init(int width, int height) - { - super.init(width, height); - this.setDimensions(width, height, 32, height - 32); - - this.load(); - - this.add(this.selectButton = new ActButton(width / 2 - 383, height - 28, 150, 24, this, "Konvertieren")); - this.add(new NavButton(width / 2 + 233, height - 28, 150, 24, GuiMenu.INSTANCE, "Abbrechen")); - - this.add(new ActButton(4, 4, 200, 24, new ActButton.Callback() { - public void use(ActButton elem, ActButton.Mode action) { - if(GuiConvert.this.gm.world != null) - return; - GuiConvert.this.gm.showFileDialog(FileMode.DIRECTORY_LOAD, "Ordner wählen", GuiConvert.this.dir, new FileCallback() { - public void selected(File file) { - GuiConvert.this.dir = file; - GuiConvert.this.gm.displayGuiScreen(GuiConvert.this); - } - }); - } - }, "Ordner wählen ...")); - - this.selectButton.enabled = false; - } - - public String getTitle() { - return "Welt auswählen"; - } - - public int getListWidth() - { - return 660; - } - - public int getSlotHeight() - { - return 56; - } - - public void use(ActButton button, Mode mode) - { - String dir = this.getSelected().getFile(); - File folder = new File(this.dir, dir); - if(folder.isDirectory()) - Converter.convertMapFormat(folder, true); - } -} diff --git a/client/src/client/gui/GuiMenu.java b/client/src/client/gui/GuiMenu.java index 17a9f4e..54cbb34 100644 --- a/client/src/client/gui/GuiMenu.java +++ b/client/src/client/gui/GuiMenu.java @@ -94,12 +94,11 @@ public class GuiMenu extends Gui { } } }); - this.add(new NavButton(0, 102, 196, 24, GuiConvert.INSTANCE, "Welt konvertieren")); - this.add(new ActButton(204, 102, 196, 24, new ActButton.Callback() { + this.add(new ActButton(0, 102, 400, 24, new ActButton.Callback() { public void use(ActButton elem, ActButton.Mode action) { GuiMenu.this.gm.interrupted = true; } - }, "Spiel beenden")); + }, "Client schließen")); this.shift(); this.add(new Label(4, /* this.gm.fb_y - 2 */ 0, 200, 20, TextColor.VIOLET + Config.VERSION, true)); this.splashLabel = this.add(new Label(0, 160, width, 24, "")); diff --git a/common/src/common/util/Util.java b/common/src/common/util/Util.java index fe4734b..629ef96 100644 --- a/common/src/common/util/Util.java +++ b/common/src/common/util/Util.java @@ -389,4 +389,12 @@ int utf_len(const char *str) { public static double ftime() { return ((double)rtime()) / 1000000.0; } + + public static String getRegionFolder(int x, int z) { + return String.format("%c%03X%c%03X", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 9, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 9); + } + + public static String getRegionName(int x, int z) { + return String.format("r.%c%X%c%X.rgn", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 3, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 3); + } } diff --git a/common/src/common/world/Region.java b/common/src/common/world/Region.java index 06bbb84..ea0a6ae 100755 --- a/common/src/common/world/Region.java +++ b/common/src/common/world/Region.java @@ -22,9 +22,7 @@ import common.collect.Lists; import common.collect.Maps; import common.entity.Entity; import common.init.BlockRegistry; -import common.init.Config; import common.init.EntityRegistry; -import common.init.UniverseRegistry; import common.log.Log; import common.nbt.NBTLoader; import common.nbt.NBTTagCompound; @@ -33,39 +31,9 @@ import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.NextTickListEntry; import common.util.NibbleArray; +import common.util.Util; public class Region { - public static enum SaveVersion { - ALPHA_1_0("Alpha 1.0 - Beta 1.2"), - BETA_1_3("Beta 1.3 - Release 1.8.9"), - RELEASE_1_9("Release 1.9 - Release 1.12.2"), - RELEASE_1_13("Release 1.13 +"); - - private final String name; - - private SaveVersion(String name) { - this.name = name; - } - - public String toString() { - return this.name; - } - } - - public static class FolderInfo { - public final long time; - public final long lastPlayed; - public final SaveVersion legacy; - public final String version; - - public FolderInfo(long time, long lastPlayed, SaveVersion legacy, String version) { - this.time = time; - this.lastPlayed = lastPlayed; - this.legacy = legacy; - this.version = version; - } - } - private static class ChunkBuffer extends ByteArrayOutputStream { public ChunkBuffer() { super(8096); @@ -90,10 +58,7 @@ public class Region { private static final Map CACHE = Maps.newHashMap(); private static final List QUEUE = Collections.synchronizedList(Lists.newArrayList()); - -// public static long lastPlayed; -// public static int version; -// public static String owner; + private static volatile long queued; private static volatile long saved; private static volatile boolean waiting; @@ -113,10 +78,10 @@ public class Region { private boolean modified; public Region(File dir, int x, int z) { - File sdir = new File(dir, getRegionFolder(x << 3, z << 3)); + File sdir = new File(dir, Util.getRegionFolder(x << 3, z << 3)); if(!sdir.exists()) sdir.mkdirs(); - this.regFile = new File(sdir, getRegionName(x << 3, z << 3)); + this.regFile = new File(sdir, Util.getRegionName(x << 3, z << 3)); this.folder = dir; this.xPos = x; this.zPos = z; @@ -313,13 +278,6 @@ public class Region { this.write(x, z, buf.getData(), buf.size()); } -// public NBTTagCompound readTag(int x, int z) throws IOException { -// byte[] data = this.read(x, z); -// if(data == null) -// return null; -// return CompressedStreamTools.read(new DataInputStream(new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(data))))); -// } - public File getFile() { return this.regFile; } @@ -336,7 +294,7 @@ public class Region { } private static File getExpansionFile(File dir, int x, int z) { - File sdir = new File(dir, getRegionFolder(x, z)); + File sdir = new File(dir, Util.getRegionFolder(x, z)); if(!sdir.exists()) sdir.mkdirs(); return new File(sdir, String.format("c.%c%X%c%X.chk", x < 0 ? 'n' : 'p', (x < 0) ? -x : x, z < 0 ? 'n' : 'p', (z < 0) ? -z : z)); @@ -399,14 +357,6 @@ public class Region { // getRegionFile(dir, x >> 3, z >> 3).writeTag(x & 7, z & 7, tag); } - public static String getRegionFolder(int x, int z) { - return String.format("%c%03X%c%03X", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 9, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 9); - } - - public static String getRegionName(int x, int z) { - return String.format("r.%c%X%c%X.rgn", x < 0 ? 'n' : 'p', ((x < 0) ? -x : x) >> 3, z < 0 ? 'n' : 'p', ((z < 0) ? -z : z) >> 3); - } - public static Chunk readNbt(WorldServer world, int x, int z, NBTTagCompound tag) { // if(!tag.hasKey("Level", 10)) { // Log.error("Chunk-Datei bei " + x + "," + z + " hat keine Level-Daten, überspringe"); @@ -680,93 +630,4 @@ public class Region { public static void killIO() { killed = true; } - - public static void saveWorldInfo(File worldDir, long time) { - NBTTagCompound data = new NBTTagCompound(); - data.setLong("Time", time); - data.setLong("LastAccess", System.currentTimeMillis()); - data.setString("Version", Config.VERSION); - NBTTagCompound cfg = new NBTTagCompound(); - for(String cvar : Config.VARS.keySet()) { - cfg.setString(cvar, Config.VARS.get(cvar).getValue()); -// Config.Value value = Config.VARS.get(cvar); -// switch(value.getType()) { -// case BOOLEAN: -// cfg.setString(cvar, "" + value.getBoolean()); -// break; -// case INTEGER: -// cfg.setString(cvar, "" + value.getInt()); -// break; -// case FLOAT: -// cfg.setString(cvar, "" + value.getFloat()); -// break; -// case STRING: -// cfg.setString(cvar, value.getString()); -// break; -// } - } - data.setTag("Config", cfg); - data.setTag("Universe", UniverseRegistry.saveNbt()); - if(worldDir != null) - worldDir.mkdirs(); - File nfile = new File(worldDir, "level.nbt.tmp"); - File lfile = new File(worldDir, "level.nbt"); - try { -// File ofile = new File(worldDir, "level.nbt_old"); - NBTLoader.writeGZip(data, nfile); -// if(ofile.exists()) -// ofile.delete(); -// lfile.renameTo(ofile); - if(lfile.exists()) - lfile.delete(); - nfile.renameTo(lfile); -// if(nfile.exists()) -// nfile.delete(); - } - catch(Exception e) { - Log.JNI.error(e, "Fehler beim Schreiben von " + nfile); - } - } - - public static FolderInfo loadWorldInfo(File worldDir) { - Config.clear(); - UniverseRegistry.clear(); - File file = new File(worldDir, "level.nbt"); - if(!file.exists()) - file = new File(worldDir, "level.nbt.tmp"); - if(file.exists()) { - try { - NBTTagCompound tag = NBTLoader.readGZip(file); - NBTTagCompound cfg = tag.getCompoundTag("Config"); - for(String key : cfg.getKeySet()) { - Config.set(key, cfg.getString(key), null); - } - UniverseRegistry.loadNbt(tag.getCompoundTag("Universe")); - // tag.getInteger("Version"); - long lastPlayed = tag.getLong("LastAccess"); - String version = tag.hasKey("Version", 8) ? tag.getString("Version") : null; - version = version != null && version.isEmpty() ? null : version; - long time = tag.hasKey("Time", 4) ? tag.getLong("Time") : World.START_TIME; - return new FolderInfo(time, lastPlayed, null, version); - } - catch(Exception e) { - Log.JNI.error(e, "Fehler beim Lesen von " + file); - } - } - return null; - } - -// public static void reloadWorldInfo(File worldDir) { -// File file = new File(worldDir, "level.nbt"); -// if(file.exists()) { -// Config.clear(); -// try { -// Config.readFromNbt(NBTLoader.readGZip(file).getCompoundTag("Config"), true); -// } -// catch(Exception e) { -// Log.error("Fehler beim Lesen von " + file, e); -// return; -// } -// } -// } } diff --git a/server/src/server/Server.java b/server/src/server/Server.java index 728a53d..5fb29ea 100755 --- a/server/src/server/Server.java +++ b/server/src/server/Server.java @@ -6,9 +6,11 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; +import java.text.SimpleDateFormat; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -74,7 +76,6 @@ import common.util.WorldPos; import common.world.Region; import common.world.World; import common.world.WorldServer; -import common.world.Region.FolderInfo; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelException; @@ -92,6 +93,7 @@ import server.command.CommandEnvironment; import server.command.FixedExecutor; import server.network.HandshakeHandler; import server.network.Player; +import server.world.Converter; public final class Server implements IThreadListener, IServer { private static final LazyLoadBase SERVER_NIO_EVENTLOOP = new LazyLoadBase() { @@ -155,6 +157,63 @@ public final class Server implements IThreadListener, IServer { Log.flushLog(); } + public static void saveServerConfig(long time) { + NBTTagCompound data = new NBTTagCompound(); + data.setLong("Time", time); + data.setLong("LastAccess", System.currentTimeMillis()); + data.setString("Version", Config.VERSION); + NBTTagCompound cfg = new NBTTagCompound(); + for(String cvar : Config.VARS.keySet()) { + cfg.setString(cvar, Config.VARS.get(cvar).getValue()); + } + data.setTag("Config", cfg); + data.setTag("Universe", UniverseRegistry.saveNbt()); + File nfile = new File("server.nbt.tmp"); + File lfile = new File("server.nbt"); + try { + NBTLoader.writeGZip(data, nfile); + if(lfile.exists()) + lfile.delete(); + nfile.renameTo(lfile); + } + catch(Exception e) { + Log.IO.error(e, "Fehler beim Schreiben von " + nfile); + } + } + + public static long loadServerConfig() { + Config.clear(); + UniverseRegistry.clear(); + File file = new File("server.nbt"); + if(!file.exists()) + file = new File("server.nbt.tmp"); + if(file.exists()) { + try { + NBTTagCompound tag = NBTLoader.readGZip(file); + NBTTagCompound cfg = tag.getCompoundTag("Config"); + for(String key : cfg.getKeySet()) { + Config.set(key, cfg.getString(key), null); + } + UniverseRegistry.loadNbt(tag.getCompoundTag("Universe")); + long lastPlayed = tag.getLong("LastAccess"); + String version = tag.hasKey("Version", 8) ? tag.getString("Version") : null; + version = version != null && version.isEmpty() ? "" : version; + long time = tag.hasKey("Time", 4) ? tag.getLong("Time") : World.START_TIME; + Log.IO.info("Version: %s", version); + Log.IO.info("Weltzeit: %d Ticks / %d Sekunden", time, time / 20L); + Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(lastPlayed))); + return time; + } + catch(Exception e) { + Log.IO.error(e, "Fehler beim Lesen von " + file); + Config.clear(); + UniverseRegistry.clear(); + } + } + Log.IO.info("Erstelle neue Welt und Konfiguration"); + return World.START_TIME; + } + private Server(boolean debug, boolean ipc) { this.debug = debug; this.ipcpipe = ipc; @@ -182,7 +241,7 @@ public final class Server implements IThreadListener, IServer { public void saveWorldInfo() { if(!this.debug) { - Region.saveWorldInfo(null, this.space.getDayTime()); + saveServerConfig(this.space.getDayTime()); WorldServer.saveWarps(this.warps); } } @@ -257,13 +316,14 @@ public final class Server implements IThreadListener, IServer { long time = System.currentTimeMillis(); Log.JNI.info("Starte Server Version " + Config.VERSION); if(!this.debug) { + Converter.convert(); this.setMessage("Welt wird erstellt und geladen"); - FolderInfo info = Region.loadWorldInfo(null); + long wtime = loadServerConfig(); // if(dtime == -1L) // { // dtime = World.START_TIME; //// Config.set("spawnDim", "1", null); //// } - this.worlds.add(this.space = new WorldServer(this, info == null ? World.START_TIME : info.time, + this.worlds.add(this.space = new WorldServer(this, wtime, Space.INSTANCE, false)); this.dimensions.put(this.space.dimension.getDimensionId(), this.space); new File("players").mkdirs(); diff --git a/client/src/client/world/Converter.java b/server/src/server/world/Converter.java similarity index 79% rename from client/src/client/world/Converter.java rename to server/src/server/world/Converter.java index 33bf568..5bc9269 100644 --- a/client/src/client/world/Converter.java +++ b/server/src/server/world/Converter.java @@ -1,4 +1,4 @@ -package client.world; +package server.world; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -7,16 +7,14 @@ import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; +import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.Date; import java.util.Map; import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; -import client.Client; -import client.gui.GuiConvert; -import client.gui.GuiLoading; -import client.gui.GuiLoading.Callback; import common.biome.Biome; import common.block.Block; import common.block.BlockCactus; @@ -92,15 +90,26 @@ import common.world.Region; import common.world.State; import common.world.Weather; import common.world.World; -import common.world.Region.FolderInfo; -import common.world.Region.SaveVersion; +import server.Server; + +public abstract class Converter { + private static enum SaveVersion { + ALPHA_1_0("Alpha 1.0 - Beta 1.2"), + BETA_1_3("Beta 1.3 - Release 1.8.9"), + RELEASE_1_9("Release 1.9 - Release 1.12.2"), + RELEASE_1_13("Release 1.13 +"); + + private final String name; + + private SaveVersion(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } + } -public final class Converter { -// public static interface Callback { -// void postMessage(String msg); -// void postProgress(int progress); -// } - private static class AnvilRegion { private final int[] offsets = new int[1024]; @@ -182,11 +191,7 @@ public final class Converter { State getState(int id, int data); } - private Converter() { - } - - private long postProgress(long start, int progress) { -// SKC.info("... " + progress + "%"); + private static long postProgress(long start, int progress) { if(System.currentTimeMillis() - start >= 500L) { start = System.currentTimeMillis(); Log.JNI.info("... " + progress + "%"); @@ -198,16 +203,7 @@ public final class Converter { private static final Map ENTITY_MAP = Maps.newHashMap(); private static final Map TILE_MAP = Maps.newHashMap(); private static final char[] BLOCK_MAP = new char[65536]; -// private static final Map BLOCK_FUNCS = Maps.newHashMap(); private static final Map OLD_GAMERULES = Maps.newHashMap(); - - private String action; - private String task; - private String file; - private int totalRegions; - private int doneRegions; - private int totalChunks; - private int doneChunks; private static void mapEntity(Class clazz, String ... names) { String name = EntityRegistry.getEntityString(clazz); @@ -253,17 +249,6 @@ public final class Converter { } } -// private static void mapBlockDynamic(BlockFunction func, int id, int data) { -// BLOCK_MAP[(id << 4) | data] = (char)0x000f; -// BLOCK_FUNCS.put((char)((id << 4) | data), func); -// } -// -// private static void mapBlockDynamic(BlockFunction func, int id) { -// for(int z = 0; z < 16; z++) { -// mapBlockDynamic(func, id, z); -// } -// } - static { OLD_GAMERULES.put("doFireTick", "fireTick"); OLD_GAMERULES.put("mobGriefing", "mobGriefing"); @@ -273,7 +258,6 @@ public final class Converter { OLD_GAMERULES.put("doEntityDrops", "dropObjects"); OLD_GAMERULES.put("naturalRegeneration", "naturalRegeneration"); OLD_GAMERULES.put("doDaylightCycle", "daylightCycle"); -// OLD_GAMERULES.put("showDeathMessages", "deathMessages"); OLD_GAMERULES.put("keepInventory", "keepInventory"); OLD_GAMERULES.put("doWeatherCycle", "weatherChanges"); OLD_GAMERULES.put("randomTickSpeed", "randomTickSpeed"); @@ -306,7 +290,6 @@ public final class Converter { mapTile(TileEntityDaylightDetector.class, "DLDetector", "daylight_detector"); mapTile(TileEntityHopper.class, "Hopper", "hopper"); mapTile(TileEntityComparator.class, "Comparator", "comparator"); -// mapTile(TileEntityFlowerPot.class, "FlowerPot", "flower_pot"); mapTile(TileEntityBanner.class, "Banner", "banner"); mapBlock(Blocks.stone.getState(), 1); @@ -609,11 +592,6 @@ public final class Converter { mapBlockData(Blocks.stonebrick_stairs, 109); mapBlock(Blocks.mycelium, 110); mapBlockData(Blocks.waterlily, 111); -// mapBlockDynamic(new BlockFunction() { -// public IBlockState getState(int id, int data) { -// return Blocks.waterlily.getDefaultState().withProperty(BlockDirectional.FACING, Facing.randHorizontal(RANDOM)); -// } -// }, 111); mapBlock(Blocks.blood_brick, 112); mapBlockData(Blocks.blood_brick_fence, 113); mapBlockData(Blocks.blood_brick_stairs, 114); @@ -822,97 +800,7 @@ public final class Converter { return Blocks.stained_hardened_clay.getState().withProperty(BlockColored.COLOR, DyeColor.byMetadata(data)); } }, 252); - // 253, 254 mapBlock(Blocks.obsidian, 255); - -// addBlock(137, 49); // Command Block -// addBlock(166, 0); // Barrier -// addBlock(168, 98); // Prismarine -// // addBlock(169, 169); // Sea Lantern --> Lamp -// addBlock(179, 24); // Red Sandstone -// addBlock(180, 128); // Red Sandstone Stairs -// addBlock(181, 43, 1); // Red Sandstone Double Slab -// -// addBlock(198, 101); // End Rod -// addBlock(199, 102); // Chorus Plant -// addBlock(200, 102); // Chorus Flower -// addBlock(201, 155); // Purpur Block -// addBlock(203, 156); // Purpur Stairs -// addBlock(206, 98); // End Stone Bricks -// addBlock(207, 142); // Beetroot Block -// addBlock(208, 60); // Grass Path -// addBlock(209, 20); // End Gateway -// addBlock(210, 137); // Repeating Command Block -// addBlock(211, 137); // Chain Command Block -// addBlock(212, 79); // Frosted Ice -// addBlock(213, 87); // Magma Block -// addBlock(214, 100); // Nether Wart Block -// addBlock(215, 112); // Red Nether Brick -// addBlock(216, 155); // Bone Block -// addBlock(217, 20); // Structure Void -// addBlock(218, 158); // Observer -// addBlock(255, 49); // Structure Block -// addBlock(202, 155, 2); // Purpur Pillar -// addBlock(204, 43, 7); // Purpur Double Slab - -// if(block > 197 && adddata != null) -// adddata.set(cx, cy, cz, 0); -// if(block == 1 || block == 19) { // Stone, Sponge -// data.set(cx, cy, cz, 0); -// } -// else if(block == 29 || block == 33 || block == 34) { // Piston, Sticky Piston, Piston Head -// int dt = data.get(cx, cy, cz); -// if((dt & 7) == 6) -// data.set(cx, cy, cz, (dt & 8) | 1); -// } -// else if(block == 97) { // Monster Egg -// int dt = data.get(cx, cy, cz); -// switch(dt) { -// case 0: -// default: -// blocks[c] = (byte)1; -// data.set(cx, cy, cz, 0); -// break; -// case 1: -// blocks[c] = (byte)4; -// data.set(cx, cy, cz, 0); -// break; -// case 2: -// case 3: -// case 4: -// case 5: -// blocks[c] = (byte)98; -// data.set(cx, cy, cz, dt - 2); -// break; -// } -// } -// mapBlock(new BlockFunction() { -// public IBlockState getState(int id, int data) { -// return Blocks.waterlily.getDefaultState().withProperty(BlockDirectional.FACING, Facing.randHorizontal(RANDOM)); -// } -// }, 111); -// else if(block == 111) { // Water Lily -// data.set(cx, cy, cz, RANDOM.zrange(4)); -// } -// else if(block == 251 || block == 252) { // Concrete, Concrete Powder -// blocks[c] = (byte)159; -// } -// else if(block >= 235 && block <= 250) { // Glazed Terracotta -// blocks[c] = (byte)159; -// data.set(cx, cy, cz, block - 235); -// } -// else if(block >= 219 && block <= 234) { // Shulker Box -// blocks[c] = (byte)35; -// data.set(cx, cy, cz, block - 219); -// } -// else if(block == 205) { // Purpur Slab -// blocks[c] = (byte)44; -// data.set(cx, cy, cz, (data.get(cx, cy, cz) & 8) == 8 ? 15 : 7); -// } -// else if(block == 182) { // Red Sandstone Slab -// blocks[c] = (byte)44; -// data.set(cx, cy, cz, (data.get(cx, cy, cz) & 8) == 8 ? 9 : 1); -// } } private static void convertTile(NBTTagCompound ent) { @@ -1113,17 +1001,13 @@ public final class Converter { return tag; } - private long convertChunks(File dir, File file, long start, int progress, int total) { + private static long convertChunks(File dir, File file, long start, int progress, int total) { String name = file.getName(); - this.file = name; - this.totalChunks = 1024; boolean legacy = name.endsWith(".mcr"); int rx, rz; String[] reg = name.split("\\."); if(reg.length != 4) { Log.JNI.warn("Unbekannte Region " + file); - this.doneChunks = 0; - this.file = null; return start; } try { @@ -1132,8 +1016,6 @@ public final class Converter { } catch(NumberFormatException e) { Log.JNI.warn("Unbekannte Region " + file); - this.doneChunks = 0; - this.file = null; return start; } try { @@ -1146,7 +1028,6 @@ public final class Converter { for(int bx = 0; bx < 4; bx++) { for(int bz = 0; bz < 4; bz++) { if(!oldreg.hasRegion(bx, bz)) { - this.doneChunks += 64; continue; } areas++; @@ -1161,7 +1042,6 @@ public final class Converter { DataInputStream in = oldreg.getInputStream(x, z); if(in == null) { Log.JNI.warn("Konnte " + file.getPath() + "@" + x + "," + z + " nicht lesen"); - this.doneChunks += 1; continue; } NBTTagCompound tag = NBTLoader.read(in); @@ -1172,7 +1052,6 @@ public final class Converter { // out.close(); newreg.writeTag(nx, nz, tag); } - this.doneChunks += 1; } } newreg.close(false); @@ -1190,36 +1069,26 @@ public final class Converter { catch(IOException e) { e.printStackTrace(); } - this.doneChunks = 0; - this.file = null; return start; } - public static FolderInfo convertMapFormat(File dir, boolean load) { + public static boolean convert() { long cur = System.currentTimeMillis(); - if(load) - Log.JNI.info("Welt '" + dir + "' wird konvertiert"); - if(new File(dir, "level.nbt").exists()) { - if(load) - Log.JNI.error("Datei level.nbt existiert bereits"); - return null; - } - File ldat = new File(dir, "level.dat"); + if(new File("server.nbt").exists()) + return false; + File ldat = new File("level.dat"); if(!ldat.exists()) - ldat = new File(dir, "level.dat_old"); - if(!ldat.exists()) { - if(load) - Log.JNI.error("Datei level.dat und level.dat_old nicht gefunden"); - return null; - } + ldat = new File("level.dat_old"); + if(!ldat.exists()) + return false; + Log.JNI.info("Welt wird konvertiert"); NBTTagCompound nbt; try { nbt = NBTLoader.readGZip(ldat); } catch(Exception e) { - if(load) - Log.JNI.error(e, "Fehler beim Lesen von level.dat"); - return null; + Log.JNI.error(e, "Fehler beim Lesen von level.dat"); + return false; } nbt = nbt.getCompoundTag("Data"); int version = nbt.getInteger("version"); @@ -1227,182 +1096,77 @@ public final class Converter { // nbt.setBoolean("incompatible", data >= 1400); SaveVersion ver = data >= 1400 ? SaveVersion.RELEASE_1_13 : (data >= 100 ? SaveVersion.RELEASE_1_9 : (version == 19132 || version == 19133 ? SaveVersion.BETA_1_3 : (version == 0 ? SaveVersion.ALPHA_1_0 : null))); if(ver == null) { - if(load) - Log.IO.error("Version %d ist unbekannt", version); - return null; + Log.IO.error("Version %d ist unbekannt", version); + return false; } long wtime = nbt.getLong(nbt.hasKey("DayTime", 99) ? "DayTime" : "Time") + World.START_TIME; - if(!load) - return new FolderInfo(wtime, nbt.getLong("LastPlayed"), ver, null); -// nbt.setString("verdesc", ver); -// NBTTagCompound nbt = getLegacyWorldInfo(dir); -// if(nbt == null) -// return false; - final Converter conv = new Converter(); - Client.CLIENT.displayGuiScreen(new GuiLoading("Konvertiere Welt ...", new Callback() { - public void poll(Client gm, GuiLoading gui) { - if(conv.totalRegions > 0) { - gui.setBar(conv.task, "Regionen", conv.totalRegions); - gui.setProgress(conv.doneRegions); - } - else { - gui.resetBar(); - } - if(conv.totalChunks > 0) { - gui.setSub(conv.file, "Chunks", conv.totalChunks); - gui.setSubProgress(conv.doneChunks); - } - else { - gui.resetSub(); - } - gui.setTask(conv.action); - } - })); - final NBTTagCompound tag = nbt; - new Thread(new Runnable() { - public void run() { - Log.IO.info("Version: %s", ver); - if(ver != SaveVersion.RELEASE_1_13) { - conv.action = "Suche nach Chunk-Daten"; - Log.JNI.info("Konvertiere Chunk-Daten von region/*.mca,*.mcr"); - File regionDir = new File(dir, "region"); - if(regionDir.exists()) { - File chunkDir = new File(new File(dir, "chunk"), "terra"); - Log.JNI.info("Konvertiere Welt nach '" + chunkDir + "' ..."); - Log.JNI.info("Durchsuche Ordner unter '" + regionDir + "' nach .mca- und .mcr-Dateien ..."); - File[] files = regionDir.listFiles(new FilenameFilter() { - public boolean accept(File file, String name) { - return name.endsWith(".mca") || name.endsWith(".mcr"); - } - }); - if(files.length == 0) { - Log.JNI.info("Keine .mca- oder .mcr-Dateien gefunden."); - } - else { - conv.task = "Konvertiere Chunkdaten"; - conv.totalRegions = files.length; - Log.JNI.info("Ingesamt wurden " + files.length + " .mca-Dateien und .mcr-Dateien gefunden, konvertiere ..."); - if(ver == SaveVersion.RELEASE_1_9) - Log.JNI.info("Konvertiere von neuerer Version, dies wird Blöcke entfernen ..."); - chunkDir.mkdirs(); - int progress = 0; - long time = System.currentTimeMillis(); - long start = conv.postProgress(time, 0); - for(File file : files) { - int percent = (int)Math.round(100.0D * (double)progress / (double)files.length); - Log.JNI.info("Konvertiere Chunk-Daten: " + file.getName() + " (" + progress + "/" + files.length + ")"); - start = conv.convertChunks(chunkDir, file, start, progress, files.length); - ++progress; - start = conv.postProgress(start, percent); - conv.doneRegions += 1; - } - time = System.currentTimeMillis() - time; - Log.JNI.info("Fertig. Konversion dauerte " + ((time / 60000L) > 0 ? ((time / 60000L) + " Minuten und ") : "") + ((time / 1000L) % 60L) + " Sekunden."); - } - } - } - else { - Log.JNI.warn("Konvertiere keine Chunk-Daten, da Version zu neu"); - } - conv.doneRegions = 0; - conv.task = null; - conv.action = "Konvertiere level.dat"; - Log.JNI.info("Konvertiere Daten von level.dat"); - Config.clear(); - UniverseRegistry.clear(); - if(tag.hasKey("GameRules", 10)) { - NBTTagCompound rules = tag.getCompoundTag("GameRules"); - for(Entry rule : OLD_GAMERULES.entrySet()) { - if(rules.hasKey(rule.getKey(), 8)) - Config.set(rule.getValue(), rules.getString(rule.getKey()), null); - } - } - // Config.setVar("noRespawn", "" + nbt.getBoolean("hardcore"), false); - // int id = nbt.getInteger("GameType"); - // Config.set("defaultNoCreative", "" + (id == 2 || id == 0), false); - Log.JNI.info("Speichere neue level.nbt ..."); - Region.saveWorldInfo(dir, wtime); -// if(tag.hasKey("Player", 10)) { -// conv.action = "Konvertiere Spielerdaten"; -// NBTTagCompound player = tag.getCompoundTag("Player"); -// NBTTagList pos = player.getTagList("Pos", 6); -// NBTTagList motion = player.getTagList("Motion", 6); -// NBTTagList rotation = player.getTagList("Rotation", 5); -// boolean ground = player.getBoolean("OnGround"); -// BlockPos spawn = null; -// // boolean force = player.getBoolean("OnGround"); -// // int mode = -1; -// // if(player.hasKey("playerGameType", 99)) { -// // mode = player.getInteger("playerGameType"); -// // mode = mode == 0 || mode == 2 ? 0 : (mode == 1 || mode == 3 ? 1 : -1); -// // } -// if(player.hasKey("SpawnX", 99) && player.hasKey("SpawnY", 99) && player.hasKey("SpawnZ", 99)) { -// spawn = new BlockPos(player.getInteger("SpawnX"), player.getInteger("SpawnY"), -// player.getInteger("SpawnZ")); -// // force = player.getBoolean("SpawnForced"); -// } -// player.getKeySet().clear(); -// player.setTag("Pos", pos); -// player.setTag("Motion", motion); -// player.setTag("Rotation", rotation); -// player.setBoolean("OnGround", ground); -// player.setInteger("Dimension", 1); -// player.setString("id", EntityRegistry.getEntityString(EntityHuman.class)); -// if(spawn != null) { -// player.setInteger("SpawnX", spawn.getX()); -// player.setInteger("SpawnY", spawn.getY()); -// player.setInteger("SpawnZ", spawn.getZ()); -// player.setInteger("SpawnDim", 1); -// // player.setBoolean("SpawnForced", force); -// } -// player.setInteger("OriginX", tag.getInteger("SpawnX")); -// player.setInteger("OriginY", tag.getInteger("SpawnY")); -// player.setInteger("OriginZ", tag.getInteger("SpawnZ")); -// player.setInteger("OriginDim", 1); -// player.setString("CustomName", user.substring(0, 1).toUpperCase() + user.substring(1)); -// NBTTagCompound plr = new NBTTagCompound(); -// plr.setInteger("selected", 0); -// NBTTagList list = new NBTTagList(); -// list.appendTag(player); -// plr.setTag("characters", list); -// // if(mode >= 0) -// // player.setBoolean("creative", mode == 1); -// Log.JNI.info("Speichere neue Spielerdaten " + user.toLowerCase() + ".nbt ..."); -// File pdat = new File(new File(dir, "players"), user.toLowerCase() + ".nbt"); -// try { -// pdat.getParentFile().mkdirs(); -// NBTLoader.writeGZip(plr, pdat); -// } -// catch(Exception e) { -// Log.JNI.error(e, "Fehler beim Schreiben von " + pdat); -// } -// } - Weather weather = tag.getBoolean("thundering") ? Weather.THUNDER : (tag.getBoolean("raining") ? Weather.RAIN : Weather.CLEAR); - if(weather != Weather.CLEAR) { - conv.action = "Konvertiere Dimensionsdaten"; - NBTTagCompound dataTag = new NBTTagCompound(); - dataTag.setString("Weather", weather.getName()); - Log.JNI.info("Speichere neue data.nbt ..."); - File dataFile = new File(new File(new File(dir, "chunk"), "terra"), "data.nbt"); - try { - NBTLoader.writeGZip(dataTag, dataFile); - } - catch(Exception e) { - Log.JNI.error(e, "Konnte Weltdaten nicht speichern"); - } - } - Log.IO.info("Welt '" + dir + "' wurde in %d Sekunden konvertiert", (System.currentTimeMillis() - cur) / 1000L); - Client.CLIENT.schedule(new Runnable() { - public void run() { - Client.CLIENT.displayGuiScreen(GuiConvert.INSTANCE); + Log.IO.info("Version: %s", ver); + Log.IO.info("Weltzeit: %d Ticks / %d Sekunden", wtime, wtime / 20L); + Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(nbt.getLong("LastPlayed")))); + if(ver != SaveVersion.RELEASE_1_13) { + Log.JNI.info("Konvertiere Chunk-Daten von region/*.mca,*.mcr"); + File regionDir = new File("region"); + if(regionDir.exists()) { + File chunkDir = new File(new File("chunk"), "terra"); + Log.JNI.info("Konvertiere Welt nach '" + chunkDir + "' ..."); + Log.JNI.info("Durchsuche Ordner unter '" + regionDir + "' nach .mca- und .mcr-Dateien ..."); + File[] files = regionDir.listFiles(new FilenameFilter() { + public boolean accept(File file, String name) { + return name.endsWith(".mca") || name.endsWith(".mcr"); } }); + if(files.length == 0) { + Log.JNI.info("Keine .mca- oder .mcr-Dateien gefunden."); + } + else { + Log.JNI.info("Ingesamt wurden " + files.length + " .mca-Dateien und .mcr-Dateien gefunden, konvertiere ..."); + if(ver == SaveVersion.RELEASE_1_9) + Log.JNI.info("Konvertiere von neuerer Version, dies wird Blöcke entfernen ..."); + chunkDir.mkdirs(); + int progress = 0; + long time = System.currentTimeMillis(); + long start = postProgress(time, 0); + for(File file : files) { + int percent = (int)Math.round(100.0D * (double)progress / (double)files.length); + Log.JNI.info("Konvertiere Chunk-Daten: " + file.getName() + " (" + progress + "/" + files.length + ")"); + start = convertChunks(chunkDir, file, start, progress, files.length); + ++progress; + start = postProgress(start, percent); + } + time = System.currentTimeMillis() - time; + Log.JNI.info("Fertig. Konversion dauerte " + ((time / 60000L) > 0 ? ((time / 60000L) + " Minuten und ") : "") + ((time / 1000L) % 60L) + " Sekunden."); + } } - }, "Converter Thread").start(); - return new FolderInfo(wtime, System.currentTimeMillis(), null, Config.VERSION); + } + else { + Log.JNI.warn("Konvertiere keine Chunk-Daten, da Version zu neu"); + } + Log.JNI.info("Konvertiere Daten von level.dat"); + Config.clear(); + UniverseRegistry.clear(); + if(nbt.hasKey("GameRules", 10)) { + NBTTagCompound rules = nbt.getCompoundTag("GameRules"); + for(Entry rule : OLD_GAMERULES.entrySet()) { + if(rules.hasKey(rule.getKey(), 8)) + Config.set(rule.getValue(), rules.getString(rule.getKey()), null); + } + } + Log.JNI.info("Speichere neue server.nbt ..."); + Server.saveServerConfig(wtime); + Weather weather = nbt.getBoolean("thundering") ? Weather.THUNDER : (nbt.getBoolean("raining") ? Weather.RAIN : Weather.CLEAR); + if(weather != Weather.CLEAR) { + NBTTagCompound dataTag = new NBTTagCompound(); + dataTag.setString("Weather", weather.getName()); + Log.JNI.info("Speichere neue data.nbt ..."); + File dataFile = new File(new File(new File("chunk"), "terra"), "data.nbt"); + try { + NBTLoader.writeGZip(dataTag, dataFile); + } + catch(Exception e) { + Log.JNI.error(e, "Konnte Weltdaten nicht speichern"); + } + } + Log.IO.info("Welt wurde in %d Sekunden konvertiert", (System.currentTimeMillis() - cur) / 1000L); + return true; } - -// public static NBTTagCompound getLegacyWorldInfo(File worldDir) { -// return nbt; -// } }