From 401fa59825a7cde589f93feed5f70f925ed9a184 Mon Sep 17 00:00:00 2001 From: Morlok8k Date: Tue, 1 Mar 2011 04:13:33 -0800 Subject: [PATCH] Moved to a new folder --- Main.java | 535 ------------------------------------------------------ 1 file changed, 535 deletions(-) delete mode 100644 Main.java diff --git a/Main.java b/Main.java deleted file mode 100644 index bb11ff0..0000000 --- a/Main.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package corrodias.minecraft.landgenerator; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.jnbt.CompoundTag; -import org.jnbt.IntTag; -import org.jnbt.NBTInputStream; -import org.jnbt.NBTOutputStream; -import org.jnbt.Tag; - -/** - * - * @author Corrodias - */ -public class Main { - - private static final String separator = System.getProperty("file.separator"); - //private static final String classpath = System.getProperty("java.class.path"); - //private static final String javaPath = System.getProperty("java.home") + separator + "bin" + separator + "java"; - private static final String VERSION = "1.2.0"; - private int increment = 300; - private ProcessBuilder minecraft = null; - private String javaLine = null; - private String serverPath = null; - private String worldPath = null; - private int xRange = 0; - private int yRange = 0; - private Integer xOffset = null; - private Integer yOffset = null; - private boolean verbose = false; - - /** - * @param args the command line arguments - */ - public static void main(String[] args) { - (new Main()).run(args); - } - - private void run(String[] args) { - System.out.println("Minecraft Land Generator version " + VERSION); - System.out.println("Uses a Minecraft server to generate square land of a specified size."); - System.out.println(""); - - // ===================================================================== - // INSTRUCTIONS - // ===================================================================== - - if (args.length == 0 || args[0].equals("-version") || args[0].equals("-help") || args[0].equals("/?")) { - System.out.println("Usage: java -jar MinecraftLandGenerator.jar x y [serverpath] [switches]"); - System.out.println(""); - System.out.println("Arguments:"); - System.out.println(" x : X range to generate"); - System.out.println(" y : Y range to generate"); - System.out.println(" serverpath : the path to the directory in which the server runs (takes precedence over the config file setting)"); - System.out.println(""); - System.out.println("Switches:"); - System.out.println(" -verbose : causes the application to output the server's messages to the console"); - System.out.println(" -v : same as -verbose"); - System.out.println(" -i# : override the iteration spawn offset increment (default 300) (example: -i100)"); - System.out.println(" -x# : set the X offset to generate land around (example: -x0)"); - System.out.println(" -y# : set the X offset to generate land around (example: -y0)"); - System.out.println(""); - System.out.println("Other options:"); - System.out.println(" java -jar MinecraftLandGenerator.jar -printspawn"); - System.out.println(" java -jar MinecraftLandGenerator.jar -ps"); - System.out.println(" Outputs the current world's spawn point coordinates."); - System.out.println(""); - System.out.println(" java -jar MinecraftLandGenerator.jar -conf"); - System.out.println(" Generates a MinecraftLandGenerator.conf file."); - System.out.println(""); - System.out.println(" java -jar MinecraftLandGenerator.jar -version"); - System.out.println(" java -jar MinecraftLandGenerator.jar -help"); - System.out.println(" java -jar MinecraftLandGenerator.jar /?"); - System.out.println(" Prints this message."); - System.out.println(""); - System.out.println("When launched with the -conf switch, this application creates a MinecraftLandGenerator.conf file that contains configuration options."); - System.out.println("If this file does not exist or does not contain all required properties, the application will not run."); - System.out.println(""); - System.out.println("MinecraftLandGenerator.conf properties:"); - System.out.println(" java : the command line to use to launch the server"); - System.out.println(" serverpath : the path to the directory in which the server runs (can be overridden by the serverpath argument)"); - return; - } - - // ===================================================================== - // STARTUP AND CONFIG - // ===================================================================== - - // the arguments are apparently okay so far. parse the conf file. - if (args[0].equalsIgnoreCase("-conf")) { - try { - File config = new File("MinecraftLandGenerator.conf"); - BufferedWriter out = new BufferedWriter(new FileWriter(config)); - out.write("java=java -Xms1024m -Xmx1024m -jar minecraft_server.jar nogui"); - out.newLine(); - out.write("serverpath=."); - out.newLine(); - out.close(); - System.out.println("MinecraftLandGenerator.conf file created."); - return; - } catch (IOException ex) { - System.err.println("Could not create MinecraftLandGenerator.conf."); - return; - } - } else if (args[0].equalsIgnoreCase("-ps") || args[0].equalsIgnoreCase("-printspawn")) { - // okay, sorry, this is an ugly hack, but it's just a last-minute feature. - printSpawn(); - return; - } else if (args.length == 1) { - System.out.println("For help, use java -jar MinecraftLandGenerator.jar -help"); - return; - } - - try { - File config = new File("MinecraftLandGenerator.conf"); - BufferedReader in = new BufferedReader(new FileReader(config)); - String line; - while ((line = in.readLine()) != null) { - int pos = line.indexOf('='); - if (pos != -1) { - if (line.substring(0, pos).toLowerCase().equals("serverpath")) { - serverPath = line.substring(pos + 1); - } else if (line.substring(0, pos).toLowerCase().equals("java")) { - javaLine = line.substring(pos + 1); - } - } - } - in.close(); - - if (serverPath == null || javaLine == null) { - System.err.println("MinecraftLandGenerator.conf does not contain all requird properties. Please recreate it by running this application with no arguments."); - return; - } - } catch (FileNotFoundException ex) { - System.out.println("Could not find MinecraftLandGenerator.conf. It is recommended that you run the application with the -conf option to create it."); - return; - } catch (IOException ex) { - System.err.println("Could not read MinecraftLandGenerator.conf"); - return; - } - - // ARGUMENTS - try { - xRange = Integer.parseInt(args[0]); - yRange = Integer.parseInt(args[1]); - } catch (NumberFormatException ex) { - System.err.println("Invalid X or Y argument."); - return; - } - - // This is embarrassing. Don't look. - try { - for (int i = 0; i < args.length - 2; i++) { - String nextSwitch = args[i + 2].toLowerCase(); - if (nextSwitch.equals("-verbose") || nextSwitch.equals("-v")) { - verbose = true; - } else if (nextSwitch.startsWith("-i")) { - increment = Integer.parseInt(args[i + 2].substring(2)); - } else if (nextSwitch.startsWith("-x")) { - xOffset = Integer.valueOf(args[i + 2].substring(2)); - } else if (nextSwitch.startsWith("-y")) { - yOffset = Integer.valueOf(args[i + 2].substring(2)); - } else { - serverPath = args[i + 2]; - } - } - } catch (NumberFormatException ex) { - System.err.println("Invalid -i switch value."); - return; - } - - { - // verify that we ended up with a good server path, either from the file or from an argument. - File file = new File(serverPath); - if (!file.exists() || !file.isDirectory()) { - System.err.println("The server directory is invalid: " + serverPath); - return; - } - } - - try { - // read the name of the current world from the server.properties file - BufferedReader props = new BufferedReader(new FileReader(new File(serverPath + separator + "server.properties"))); - String line; - while ((line = props.readLine()) != null) { - int pos = line.indexOf('='); - if (pos != -1) { - if (line.substring(0, pos).toLowerCase().equals("level-name")) { - worldPath = serverPath + separator + line.substring(pos + 1); - } - } - } - - } catch (FileNotFoundException ex) { - System.err.println("Could not open " + serverPath + separator + "server.properties"); - return; - } catch (IOException ex) { - Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); - return; - } - - { - File backupLevel = new File(worldPath + separator + "level_backup.dat"); - if (backupLevel.exists()) { - System.err.println("There is a level_backup.dat file left over from a previous attempt that failed. You should go determine whether to keep the current level.dat" - + " or restore the backup."); - return; - } - } - - // ===================================================================== - // PROCESSING - // ===================================================================== - - System.out.println("Processing world \"" + worldPath + "\", in " + increment + " block increments, with: " + javaLine); - System.out.println(""); - - // prepare our two ProcessBuilders - //minecraft = new ProcessBuilder(javaLine, "-Xms1024m", "-Xmx1024m", "-jar", jarFile, "nogui"); - minecraft = new ProcessBuilder(javaLine.split("\\s")); // is this always going to work? i don't know. - minecraft.directory(new File(serverPath)); - minecraft.redirectErrorStream(true); - - try { - System.out.println("Launching server once to make sure there is a world."); - runMinecraft(minecraft, verbose); - System.out.println(""); - - File serverLevel = new File(worldPath + separator + "level.dat"); - File backupLevel = new File(worldPath + separator + "level_backup.dat"); - - System.out.println("Backing up level.dat to level_backup.dat."); - copyFile(serverLevel, backupLevel); - System.out.println(""); - - Integer[] spawn = getSpawn(serverLevel); - System.out.println("Spawn point detected: [" + spawn[0] + ", " + spawn[2] + "]"); - { - boolean overridden = false; - if (xOffset == null) { - xOffset = spawn[0]; - } else { - overridden = true; - } - if (yOffset == null) { - yOffset = spawn[2]; - } else { - overridden = true; - } - if (overridden) { - System.out.println("Centering land generation on [" + xOffset + ", " + yOffset + "] due to switches."); - } - } - System.out.println(""); - - int totalIterations = (xRange / increment + 1) * (yRange / increment + 1); - int currentIteration = 0; - - long differenceTime = System.currentTimeMillis(); - Long[] timeTracking = new Long[]{differenceTime, differenceTime, differenceTime, differenceTime}; - for (int currentX = 0 - xRange / 2; currentX <= xRange / 2; currentX += increment) { - for (int currentY = 0 - yRange / 2; currentY <= yRange / 2; currentY += increment) { - currentIteration++; - System.out.println("Setting spawn to [" + Integer.toString(currentX + xOffset) + ", " + Integer.toString(currentY + yOffset) + "] (" + currentIteration + "/" + totalIterations + ")"); - - // Time Remaining estimate - timeTracking[0] = timeTracking[1]; - timeTracking[1] = timeTracking[2]; - timeTracking[2] = timeTracking[3]; - timeTracking[3] = System.currentTimeMillis(); - if (currentIteration >= 4) { - differenceTime = (timeTracking[3] - timeTracking[0]) / 3; // well, this is what it boils down to - differenceTime *= 1 + (totalIterations - currentIteration); - System.out.println(String.format("Estimated time remaining: %dh%dm%ds", - differenceTime / (1000 * 60 * 60), (differenceTime % (1000 * 60 * 60)) / (1000 * 60), ((differenceTime % (1000 * 60 * 60)) % (1000 * 60)) / 1000)); - } - - // Set the spawn point - setSpawn(serverLevel, currentX + xOffset, 128, currentY + yOffset); - - // Launch the server - runMinecraft(minecraft, verbose); - System.out.println(""); - } - } - - System.out.println("Finished generating chunks."); - copyFile(backupLevel, serverLevel); - backupLevel.delete(); - System.out.println("Restored original level.dat."); - } catch (IOException ex) { - Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); - } - } - - protected static Integer[] getSpawn(File level) throws IOException { - try { - NBTInputStream input = new NBTInputStream(new FileInputStream(level)); - CompoundTag originalTopLevelTag = (CompoundTag) input.readTag(); - input.close(); - - Map originalData = ((CompoundTag) originalTopLevelTag.getValue().get("Data")).getValue(); - // This is our map of data. It is an unmodifiable map, for some reason, so we have to make a copy. - Map newData = new LinkedHashMap(originalData); - // .get() a couple of values, just to make sure we're dealing with a valid level file, here. Good for debugging, too. - IntTag spawnX = (IntTag) newData.get("SpawnX"); - IntTag spawnY = (IntTag) newData.get("SpawnY"); - IntTag spawnZ = (IntTag) newData.get("SpawnZ"); - - Integer[] ret = new Integer[]{spawnX.getValue(), spawnY.getValue(), spawnZ.getValue()}; - return ret; - } catch (ClassCastException ex) { - throw new IOException("Invalid level format."); - } catch (NullPointerException ex) { - throw new IOException("Invalid level format."); - } - } - - /** - * Changes the spawn point in the given Alpha level to the given coordinates. - * Note that, in Minecraft levels, the Y coordinate is height, while Z is - * what may normally be thought of as Y. - * @param level the level file to change the spawn point in - * @param x the new X value - * @param z the new Y value - * @param y the new Z value - * @throws IOException if there are any problems reading/writing the file - */ - protected static void setSpawn(File level, Integer x, Integer y, Integer z) throws IOException { - try { - NBTInputStream input = new NBTInputStream(new FileInputStream(level)); - CompoundTag originalTopLevelTag = (CompoundTag) input.readTag(); - input.close(); - -// -// Structure: -// -//TAG_Compound("Data"): World data. -// * TAG_Long("Time"): Stores the current "time of day" in ticks. There are 20 ticks per real-life second, and 24000 ticks per Minecraft day, making the day length 20 minutes. 0 appears to be sunrise, 12000 sunset and 24000 sunrise again. -// * TAG_Long("LastPlayed"): Stores the Unix time stamp (in milliseconds) when the player saved the game. -// * TAG_Compound("Player"): Player entity information. See Entity Format and Mob Entity Format for details. Has additional elements: -// o TAG_List("Inventory"): Each TAG_Compound in this list defines an item the player is carrying, holding, or wearing as armor. -// + TAG_Compound: Inventory item data -// # TAG_Short("id"): Item or Block ID. -// # TAG_Short("Damage"): The amount of wear each item has suffered. 0 means undamaged. When the Damage exceeds the item's durability, it breaks and disappears. Only tools and armor accumulate damage normally. -// # TAG_Byte("Count"): Number of items stacked in this inventory slot. Any item can be stacked, including tools, armor, and vehicles. Range is 1-255. Values above 127 are not displayed in-game. -// # TAG_Byte("Slot"): Indicates which inventory slot this item is in. -// o TAG_Int("Score"): Current score, doesn't appear to be implemented yet. Always 0. -// * TAG_Int("SpawnX"): X coordinate of the player's spawn position. Default is 0. -// * TAG_Int("SpawnY"): Y coordinate of the player's spawn position. Default is 64. -// * TAG_Int("SpawnZ"): Z coordinate of the player's spawn position. Default is 0. -// * TAG_Byte("SnowCovered"): 1 enables, 0 disables, see Winter Mode -// * TAG_Long("SizeOnDisk"): Estimated size of the entire world in bytes. -// * TAG_Long("RandomSeed"): Random number providing the Random Seed for the terrain. -// - - Map originalData = ((CompoundTag) originalTopLevelTag.getValue().get("Data")).getValue(); - // This is our map of data. It is an unmodifiable map, for some reason, so we have to make a copy. - Map newData = new LinkedHashMap(originalData); - // .get() a couple of values, just to make sure we're dealing with a valid level file, here. Good for debugging, too. - IntTag spawnX = (IntTag) newData.get("SpawnX"); - IntTag spawnY = (IntTag) newData.get("SpawnY"); - IntTag spawnZ = (IntTag) newData.get("SpawnZ"); - newData.put("SpawnX", new IntTag("SpawnX", x)); - newData.put("SpawnY", new IntTag("SpawnY", y)); - newData.put("SpawnZ", new IntTag("SpawnZ", z)); - - // Again, we can't modify the data map in the old Tag, so we have to make a new one. - CompoundTag newDataTag = new CompoundTag("Data", newData); - Map newTopLevelMap = new HashMap(1); - newTopLevelMap.put("Data", newDataTag); - CompoundTag newTopLevelTag = new CompoundTag("", newTopLevelMap); - - NBTOutputStream output = new NBTOutputStream(new FileOutputStream(level)); - output.writeTag(newTopLevelTag); - output.close(); - } catch (ClassCastException ex) { - throw new IOException("Invalid level format."); - } catch (NullPointerException ex) { - throw new IOException("Invalid level format."); - } - } - - /** - * Starts the process in the given ProcessBuilder, monitors its output for a - * "[INFO] Done!" message, and sends it a "stop\r\n" message. One message is printed - * to the console before launching and one is printed to the console when the - * Done! message is detected. If "verbose" is true, the process's output will - * also be printed to the console. - * @param minecraft - * @param verbose - * @throws IOException - */ - protected static void runMinecraft(ProcessBuilder minecraft, boolean verbose) throws IOException { - System.out.println("Starting server."); - Process process = minecraft.start(); - - // monitor output and print to console where required. - // STOP the server when it's done. - BufferedReader pOut = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = pOut.readLine()) != null) { - if (verbose) { - System.out.println(line); - } - if (line.contains("[INFO] Done!")) { - System.out.println("Stopping server."); - byte[] stop = {'s', 't', 'o', 'p', '\r', '\n'}; - OutputStream outputStream = process.getOutputStream(); - outputStream.write(stop); - outputStream.flush(); - } - } - // readLine() returns null when the process exits - } - - // I'd love to use nio, but it requires Java 7. - // I could use Apache Commons, but i don't want to include a library for one little thing. - // Copies src file to dst file. - // If the dst file does not exist, it is created - public static void copyFile(File src, File dst) throws IOException { - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst); - - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) >= 0) { - if (len > 0) { - out.write(buf, 0, len); - } - } - in.close(); - out.flush(); - out.close(); - } - - private boolean printSpawn() { - // ugh, sorry, this is an ugly hack, but it's a last-minute feature. - // this is a lot of duplicated code. - - try { - File config = new File("MinecraftLandGenerator.conf"); - BufferedReader in = new BufferedReader(new FileReader(config)); - String line; - while ((line = in.readLine()) != null) { - int pos = line.indexOf('='); - if (pos != -1) { - if (line.substring(0, pos).toLowerCase().equals("serverpath")) { - serverPath = line.substring(pos + 1); - } else if (line.substring(0, pos).toLowerCase().equals("java")) { - javaLine = line.substring(pos + 1); - } - } - } - in.close(); - - if (serverPath == null || javaLine == null) { - System.err.println("MinecraftLandGenerator.conf does not contain all requird properties. Please recreate it by running this application with no arguments."); - return false; - } - } catch (FileNotFoundException ex) { - System.out.println("Could not find MinecraftLandGenerator.conf. It is recommended that you run the application with the -conf option to create it."); - return false; - } catch (IOException ex) { - System.err.println("Could not read MinecraftLandGenerator.conf"); - return false; - } - - { - // verify that we ended up with a good server path, either from the file or from an argument. - File file = new File(serverPath); - if (!file.exists() || !file.isDirectory()) { - System.err.println("The server directory is invalid: " + serverPath); - return false; - } - } - - try { - // read the name of the current world from the server.properties file - BufferedReader props = new BufferedReader(new FileReader(new File(serverPath + separator + "server.properties"))); - String line; - while ((line = props.readLine()) != null) { - int pos = line.indexOf('='); - if (pos != -1) { - if (line.substring(0, pos).toLowerCase().equals("level-name")) { - worldPath = serverPath + separator + line.substring(pos + 1); - } - } - } - - } catch (FileNotFoundException ex) { - System.err.println("Could not open " + serverPath + separator + "server.properties"); - return false; - } catch (IOException ex) { - Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); - return false; - } - - File level = new File(worldPath + separator + "level.dat"); - if (!level.exists() || !level.isFile()) { - System.err.println("The currently-configured world does not exist. Please launch the server once, first."); - return false; - } - - try { - Integer[] spawn = getSpawn(level); - System.out.println("The current spawn point is: [" + spawn[0] + ", " + spawn[2] + "]"); - return true; - } catch (IOException ex) { - System.err.println("Error while reading " + level.getPath()); - return false; - } - } -}