package game.gui.world; import java.io.File; import game.color.TextColor; import game.dimension.DimType; import game.dimension.Dimension; import game.dimension.Space; import game.gui.Gui; import game.gui.element.ActButton; import game.gui.element.Label; import game.gui.element.Textbox; import game.gui.element.ActButton.Mode; import game.gui.element.Textbox.Action; import game.gui.element.TransparentBox; import game.init.Config; import game.init.UniverseRegistry; import game.log.Log; import game.nbt.NBTLoader; import game.nbt.NBTTagCompound; import game.network.NetHandlerPlayServer; import game.rng.Random; import game.util.Util; import game.world.Region; import game.world.World; public class GuiCreate extends Gui implements ActButton.Callback, Textbox.Callback { public static final GuiCreate INSTANCE = new GuiCreate(); private static final String MBASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?-_<3"; private static final String MBASE64A_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-!"; private static final String MBASE64B_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz<_"; private Textbox worldNameField; private Textbox worldSeedField; private Textbox worldUserField; private ActButton dimButton; private ActButton createButton; private Label actionLabel; private Label nameLabel; private Label userLabel; private Label seed; private Label decoded; private TransparentBox descLines; private boolean alreadyGenerated; private boolean fileExists; private int dimension; private static long getSeed(String str) { if(str == null || str.isEmpty()) return (new Random()).longv(); try { return Long.parseLong(str); } catch(NumberFormatException e) { } long seed = 0L; if(str.length() <= 9) { for(int z = 0; z < str.length(); z++) { seed <<= 7; char c = str.charAt(z); if(c >= 0x80) { seed = -1L; break; } seed |= (long)c; } } else if(str.length() == 10) { String ch = str.indexOf('<') != -1 || str.indexOf('_') != -1 ? MBASE64B_CHARS : MBASE64A_CHARS; for(int z = 0; z < str.length(); z++) { seed <<= 6; int idx = ch.indexOf(str.charAt(z)); if(idx == -1) { seed = -1L; break; } seed |= (long)idx; } if(seed != -1L) seed |= ch == MBASE64B_CHARS ? 0xb000000000000000L : 0xa000000000000000L; } else if(str.length() <= 12) { for(int z = 0; z < str.length(); z++) { seed <<= 5; int idx = MBASE32_CHARS.indexOf(Character.toUpperCase(str.charAt(z))); if(idx == -1) { seed = -1L; break; } seed |= (long)idx; } if(seed != -1L) seed |= str.length() == 12 ? 0x9000000000000000L : 0x8000000000000000L; } else { seed = -1L; } if(seed == -1L) { seed = 0L; for(int z = 0; z < str.length(); z++) { seed <<= 7; seed |= (long)((char)(str.charAt(z) & 0x7f)); } seed = (seed ^ (((long)str.hashCode()) | (~((long)str.hashCode()) << 32))) | 0xc000000000000000L; } return seed; } private static String decodeSeed(long seed, String def) { if(seed == 0L) return (def == null ? ("" + seed) : def); if((seed & 0x8000000000000000L) == 0L) { String str = ""; long value = seed; while(value != 0L) { char c = (char)(value & 0x7fL); if(c < 32 || c > 126) return (def == null ? ("" + seed) : def); str = c + str; value >>= 7; } try { Long.parseLong(str); } catch(NumberFormatException e) { return str; } return (def == null ? ("" + seed) : def); } String chset; int len; int shift; long mask; long type = (seed >> 60) & 0xf; switch((int)type) { case 0x8: chset = MBASE32_CHARS; len = 11; shift = 5; mask = 0x1fL; break; case 0x9: chset = MBASE32_CHARS; len = 12; shift = 5; mask = 0x1fL; break; case 0xa: chset = MBASE64A_CHARS; len = 10; shift = 6; mask = 0x3fL; break; case 0xb: chset = MBASE64B_CHARS; len = 10; shift = 6; mask = 0x3fL; break; default: return (def == null ? ("" + seed) : def); } String str = ""; for(int z = 0; z < len; z++) { str = chset.charAt((int)(seed & mask)) + str; seed >>= shift; } try { Long.parseLong(str); } catch(NumberFormatException e) { return str; } return (def == null ? ("" + seed) : def); } private GuiCreate() { } public void updateScreen() { String text = this.worldSeedField.getText(); if(text.isEmpty()) { this.seed.setText("Startwert [Zufällig]"); this.decoded.setText("Dekodiert: -"); } else { this.seed.setText("Startwert [" + getSeed(text) + "]"); try { this.decoded.setText("Dekodiert: " + decodeSeed(Long.parseLong(text), "-")); } catch(NumberFormatException e) { this.decoded.setText("Dekodiert: " + decodeSeed(getSeed(text), "-")); } } this.fileExists = false; text = this.worldNameField.getText().trim(); this.createButton.enabled = !text.isEmpty() && !this.worldUserField.getText().isEmpty(); if(this.fileExists = (!text.isEmpty() && new File(Region.SAVE_DIR, text).exists())) this.createButton.enabled = false; this.actionLabel.setText(this.getFolderDesc()); this.userLabel.setText(this.getUserDesc()); } public void init(int width, int height) { UniverseRegistry.clear(); this.alreadyGenerated = false; this.dimension = Integer.MAX_VALUE; this.createButton = this.add(new ActButton(width / 2 - 155, height - 28, 150, 20, (ActButton.Callback)this, "Neue Welt erstellen")); this.add(new ActButton(width / 2 + 5, height - 28, 150, 20, (Gui)GuiWorlds.INSTANCE, "Abbrechen")); this.dimButton = this.add(new ActButton(width / 2 - 155, 220, 310, 20, (ActButton.Callback)this, "")); this.worldNameField = this.add(new Textbox(width / 2 - 100, 60, 200, 20, 256, true, this, GuiWorlds.VALID_FILE, "")); this.worldNameField.setSelected(); this.worldSeedField = this.add(new Textbox(width / 2 - 100, 136, 200, 20, 256, true, this, "")); this.worldUserField = this.add(new Textbox(width / 2 - 100, 98, 200, 20, NetHandlerPlayServer.MAX_USER_LENGTH, true, this, NetHandlerPlayServer.VALID_USER, "")); this.createButton.enabled = false; this.actionLabel = this.add(new Label(width / 2 - 100, 49, 200, 20, this.getFolderDesc(), true)); this.userLabel = this.add(new Label(width / 2 - 100, 87, 200, 20, this.getUserDesc(), true)); this.seed = this.add(new Label(width / 2 - 100, 125, 200, 20, "", true)); this.decoded = this.add(new Label(width / 2 - 100, 160, 200, 20, "", true)); this.descLines = this.add(new TransparentBox(width / 2 - 153, 242, 306, 160, "")); this.setDimButton(); } public String getTitle() { return "Neue Welt erstellen"; } private void setDimButton() { Dimension dim = this.dimension == Integer.MAX_VALUE ? Space.INSTANCE : UniverseRegistry.getBaseDimensions().get(this.dimension); this.dimButton.setText((dim == Space.INSTANCE ? "" : ((dim.getDimensionId() >= UniverseRegistry.MORE_DIM_ID ? "Vorlage" : (dim.getType() == DimType.PLANET ? "Heimplanet" : "Dimension")) + ": ")) + (dim.getDimensionId() >= UniverseRegistry.MORE_DIM_ID ? dim.getCustomName() : dim.getFormattedName(false))); this.descLines.setText(Util.buildLines(dim.getFormattedName(true).split(" / "))); } public void use(ActButton button, Mode mode) { if (button == this.createButton) { // this.gm.displayGuiScreen(null); if(this.alreadyGenerated) return; this.alreadyGenerated = true; Config.clear(); UniverseRegistry.clear(); Dimension dim = this.dimension == Integer.MAX_VALUE ? Space.INSTANCE : UniverseRegistry.getBaseDimensions().get(this.dimension); dim.setSeed(getSeed(this.worldSeedField.getText())); File dir = new File(Region.SAVE_DIR, this.worldNameField.getText().trim()); Dimension[] dims = UniverseRegistry.registerPreset(dim); Config.set("spawnDim", "" + dims[0].getDimensionId(), null); Region.saveWorldInfo(dir, World.START_TIME, this.worldUserField.getText()); for(Dimension sdim : dims) { NBTTagCompound data = new NBTTagCompound(); data.setTag("Generator", sdim.toNbt(true)); File chunkDir = new File(new File(dir, "chunk"), sdim.getDimensionName()); chunkDir.mkdirs(); File file = new File(chunkDir, "data.nbt"); try { NBTLoader.writeGZip(data, file); } catch(Exception e) { Log.IO.error(e, "Konnte Weltdaten nicht speichern"); } } this.gm.startServer(dir, this.worldUserField.getText()); } else if (button == this.dimButton) { if(mode == Mode.TERTIARY) { this.dimension = Integer.MAX_VALUE; } else if(this.dimension == Integer.MAX_VALUE) { this.dimension = mode == Mode.SECONDARY ? UniverseRegistry.getBaseDimensions().size() - 1 : 0; } else { if(mode == Mode.SECONDARY) { if(--this.dimension < 0) this.dimension = Integer.MAX_VALUE; } else { if(++this.dimension >= UniverseRegistry.getBaseDimensions().size()) this.dimension = Integer.MAX_VALUE; } } this.setDimButton(); } } public void use(Textbox elem, Action action) { if(action == Action.SEND) this.use(this.createButton, Mode.PRIMARY); } private String getFolderDesc() { // FontRenderer.drawStringWithShadow("Startwert [" + this.seed + "]", this.width / 2 - 100, 125, -6250336); // FontRenderer.drawStringWithShadow("Dekodiert: " + this.decoded, this.width / 2 - 100, 160, -6250336); // FontRenderer.drawStringWithShadow(, this.width / 2 - 100, 49, -6250336); // FontRenderer.drawStringWithShadow((this.worldUserField.getText().isEmpty() ? TextColor.DARK_RED : "") + "Spielername", this.width / 2 - 100, 87, -6250336); // // for(int z = 1; z < this.descLines.length; z++) { // FontRenderer.drawStringWithShadow(this.descLines[z], this.width / 2 - 153, 242 + (z - 1) * (FontRenderer.FONT_HEIGHT + 1), -6250336); // } return (this.worldNameField.getText().trim().isEmpty() || this.fileExists ? TextColor.DRED : "") + "Ordner der Welt" + (this.fileExists ? " - Existiert bereits" : ""); } private String getUserDesc() { return (this.worldUserField.getText().isEmpty() ? TextColor.DRED : "") + "Spielername"; } }