From 425ddea1c122509d22787579f97df9ba850d265b Mon Sep 17 00:00:00 2001 From: Morlok8k Date: Thu, 24 May 2012 02:39:28 -0700 Subject: [PATCH] 1.6.2 - Major Optimizations --- README | 13 +- bin/MLG-BuildID | 1 + bin/MinecraftLandGenerator.conf | 4 +- bin/MinecraftLandGenerator.jar | Bin 69682 -> 69112 bytes .../minecraft/landgenerator/Main.java | 644 ++++-------------- .../minecraft/landgenerator/DownloadFile.java | 109 +++ src/morlok8k/minecraft/landgenerator/MD5.java | 50 ++ .../landgenerator/Readme_and_HelpInfo.java | 290 ++++++++ src/org/w3c/bert_bos/UTF8URL/Unescape.java | 83 +++ 9 files changed, 686 insertions(+), 508 deletions(-) create mode 100644 src/morlok8k/minecraft/landgenerator/DownloadFile.java create mode 100644 src/morlok8k/minecraft/landgenerator/MD5.java create mode 100644 src/morlok8k/minecraft/landgenerator/Readme_and_HelpInfo.java create mode 100644 src/org/w3c/bert_bos/UTF8URL/Unescape.java diff --git a/README b/README index cc54bc0..7e50fda 100644 --- a/README +++ b/README @@ -1,10 +1,10 @@ -Minecraft Land Generator version 1.6.11 +Minecraft Land Generator version 1.6.2 -Updated May 2, 2012 -(BuildID: 1335956100000) +Updated May 24, 2012 +(BuildID: 1337852365000) Original Code by Corrodias November 2010 -Enhanced Code by Morlok8k Feb. 2011 to Now (or at least to May 2, 2012!) +Enhanced Code by Morlok8k Feb. 2011 to Now (or at least to May 24, 2012!) Additional Code by pr0f1x October 2011 Website: https://sites.google.com/site/minecraftlandgenerator/ @@ -27,6 +27,11 @@ Other Public Domain code has been used in this program, and references to source Version History: Morlok8k: +1.6.2 +- Major Code Optimization +- Updated Time Output again. Now says "1 Minute" instead of "1 Minutes". +- Updated Location Code - the center of the square is now truely centered, and it trys to get as close to the given size as possible. + 1.6.11 - Removed End-of-Generation ASCII-Graphic - It didn't really fit with MLG. - Updated Time Output. diff --git a/bin/MLG-BuildID b/bin/MLG-BuildID index 370f5e9..bacdc8c 100644 --- a/bin/MLG-BuildID +++ b/bin/MLG-BuildID @@ -36,3 +36,4 @@ F1B044CD44634EDDB85DC44384CB8F0F=1334484354000# MLG v1.6.1 36A1C89EFD4967C19AA001B64EE99C80=1334484954000# MLG v1.6.1 891492F60015683B98CD7A4F4430AE16=1334739407000# MLG v1.6.1 22EAF4CE6AD4089527919E8D8A5CA055=1335956100000# MLG v1.6.11 +6C91BF8786B4966B67ACC64EB2C4A896=1337852365000# MLG v1.6.2 diff --git a/bin/MinecraftLandGenerator.conf b/bin/MinecraftLandGenerator.conf index aec29ee..e1e3aaf 100644 --- a/bin/MinecraftLandGenerator.conf +++ b/bin/MinecraftLandGenerator.conf @@ -1,6 +1,6 @@ -#Minecraft Land Generator Configuration File: Version: 1.6.11 +#Minecraft Land Generator Configuration File: Version: 1.6.2 #Authors: Corrodias, Morlok8k, pr0f1x -#Auto-Generated: Wednesday, May 2, 2012 at 3:55 AM Pacific Daylight Time +#Auto-Generated: Thursday, May 24, 2012 at 2:39 AM Pacific Daylight Time #Line to run server: Java=java -Djava.awt.headless=true -Djline.terminal=jline.UnsupportedTerminal -Duser.language=en -Xms1024m -Xmx1024m -Xincgc -jar minecraft_server.jar nogui diff --git a/bin/MinecraftLandGenerator.jar b/bin/MinecraftLandGenerator.jar index 99c3e6799ab67bd18a20270616d5e6eb4e96dd17..c1255890f3a5fd5b1201d652e875f3d6c7c899f2 100755 GIT binary patch delta 51099 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 WbRGdl2|i^8WriETdx^PNKxzPE`~VsN delta 51877 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 diff --git a/src/corrodias/minecraft/landgenerator/Main.java b/src/corrodias/minecraft/landgenerator/Main.java index 4d3ca01..b829153 100644 --- a/src/corrodias/minecraft/landgenerator/Main.java +++ b/src/corrodias/minecraft/landgenerator/Main.java @@ -1,7 +1,5 @@ package corrodias.minecraft.landgenerator; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -14,12 +12,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.math.BigInteger; -import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -37,6 +32,10 @@ import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import morlok8k.minecraft.landgenerator.DownloadFile; +import morlok8k.minecraft.landgenerator.MD5; +import morlok8k.minecraft.landgenerator.Readme_and_HelpInfo; + import org.jnbt.CompoundTag; import org.jnbt.IntTag; import org.jnbt.LongTag; @@ -52,12 +51,12 @@ import org.jnbt.Tag; public class Main { // Version Number! - private static final String PROG_NAME = "Minecraft Land Generator"; - private static final String VERSION = "1.6.11"; - private static final String AUTHORS = "Corrodias, Morlok8k, pr0f1x"; + public static final String PROG_NAME = "Minecraft Land Generator"; + public static final String VERSION = "1.6.2"; + public static final String AUTHORS = "Corrodias, Morlok8k, pr0f1x"; - private static final String fileSeparator = System.getProperty("file.separator"); - private static final String newLine = System.getProperty("line.separator"); + public static final String fileSeparator = System.getProperty("file.separator"); + public static final String newLine = System.getProperty("line.separator"); private int increment = 380; private static ProcessBuilder minecraft = null; @@ -94,19 +93,19 @@ public class Main { private static boolean ignoreWarnings = false; private static LongTag randomSeed = null; - private static String MLG = "[MLG] "; - private static String MLGe = "[MLG-ERROR] "; + public static String MLG = "[MLG] "; + public static String MLGe = "[MLG-ERROR] "; private static DateFormat dateFormat = null; //private static DateFormat dateFormatBuildID = null; - private static DateFormat dateFormat_MDY = null; + public static DateFormat dateFormat_MDY = null; private static Date date = null; - private static Date MLG_Last_Modified_Date = null; + public static Date MLG_Last_Modified_Date = null; private static Long MLG_Last_Modified_Long = 0L; private static final Class cls = Main.class; private static String MLGFileName = null; - private static String MLGFileNameShort = null; + public static String MLGFileNameShort = null; private static final String rsrcError = "rsrcERROR"; private static String buildIDFile = "MLG-BuildID"; private static boolean isCompiledAsJar = false; @@ -117,8 +116,8 @@ public class Main { private static ArrayList timeStamps = new ArrayList(); - private static final String MinecraftLandGeneratorConf = "MinecraftLandGenerator.conf"; - private static final String defaultReadmeFile = "_MLG_Readme.txt"; + public static final String MinecraftLandGeneratorConf = "MinecraftLandGenerator.conf"; + public static final String defaultReadmeFile = "_MLG_Readme.txt"; private static final String MLG_JarFile = "MinecraftLandGenerator.jar"; private static final String github_URL = @@ -133,7 +132,7 @@ public class Main { ////// - private static final boolean testing = false; // display more output when debugging + public static final boolean testing = false; // display more output when debugging ////// @@ -422,6 +421,7 @@ public class Main { err("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."); err("You most likely will want to restore the backup!"); + waitTenSec(false); return; } } @@ -484,23 +484,98 @@ public class Main { } out(""); - int totalIterations = (xRange / increment + 1) * (zRange / increment + 1); + // new code to optimize the locations + Integer incrementX, incrementZ; + Double blah; + double xLoops, zLoops; + + // X + blah = ((double) xRange / (double) increment); //How many loops do we need? + xLoops = Math.ceil(blah); //round up to find out! + blah = Math.floor(xRange / xLoops); //optimal distance calculations here + incrementX = blah.intValue(); //save to an int + blah = + Math.floor((double) xRange + / Math.ceil(((double) xRange / ((double) increment + 20)))); + if (blah < increment) { //should we use 380 or 400 as our original increment? This decides it. + incrementX = blah.intValue(); + } + if (blah.isInfinite()) { + incrementX = 0; // An Infinity error. this should never be less than (increment/2)! + } else if (incrementX < (increment / 2)) { + incrementX = 0; // Should never happen except for the Infinity error + } else if (incrementX > increment) { + incrementX = increment; // Should never happen. Just in case! + } + + // Z + blah = ((double) zRange / (double) increment); //How many loops do we need? + zLoops = Math.ceil(blah); //round up to find out! + blah = Math.floor(zRange / zLoops); //optimal distance calculations here + incrementZ = blah.intValue(); //save to an int + blah = + Math.floor((double) zRange + / Math.ceil(((double) zRange / ((double) increment + 20)))); + if (blah < increment) { //should we use 380 or 400 as our original increment? This decides it. + incrementZ = blah.intValue(); + } + if (blah.isInfinite()) { + incrementZ = 0; // An Infinity error. this should never be less than (increment/2)! + } else if (incrementZ < (increment / 2)) { + incrementZ = 0; // Should never happen except for the Infinity error + } else if (incrementZ > increment) { + incrementZ = increment; // Should never happen. Just in case! + } + + blah = null; // I'm done with this temporary variable now. I used it to make my code simplier, + // and so I wouldn't need to constantly use casting + // (as java will do it if one of the numbers is already a double) + + if (verbose) { + if (incrementX != increment) { + out("Optimized X increments from: " + increment + " to: " + incrementX); + } + if (incrementZ != increment) { + out("Optimized Z increments from: " + increment + " to: " + incrementZ); + } + } + // end new code for location optimizations + + int totalIterations = (int) (xLoops * zLoops); int currentIteration = 0; + int curXloops = 0; + int curZloops = 0; + long differenceTime = System.currentTimeMillis(); - //Long[] timeTracking = new Long[] { differenceTime, differenceTime, differenceTime, differenceTime }; + Long timeTracking = 0L; - for (int currentX = 0 - xRange / 2; currentX <= xRange / 2; currentX += increment) { - for (int currentZ = 0 - zRange / 2; currentZ <= zRange / 2; currentZ += increment) { + for (int currentX = (((0 - xRange) / 2) + (incrementX / 2)); currentX <= (xRange / 2); currentX += + incrementX) { + curXloops++; + if (curXloops == 1) { + currentX = (((0 - xRange) / 2) + (increment / 2)); + } else if (curXloops == xLoops) { + currentX = (xRange / 2) - (increment / 2); + } + + for (int currentZ = (((0 - zRange) / 2) + (incrementZ / 2)); currentZ <= (zRange / 2); currentZ += + incrementZ) { currentIteration++; + curZloops++; + if (curZloops == 1) { + currentZ = (((0 - zRange) / 2) + (increment / 2)); + } else if (curZloops == zLoops) { + currentZ = (zRange / 2) - (increment / 2); + } + String curX = Integer.toString(currentX + xOffset); //String curY = "64"; //Y is always set to 64 String curZ = Integer.toString(currentZ + zOffset); String percentDone = - Float.toString((Float.parseFloat(Integer.toString(currentIteration)) / Float - .parseFloat(Integer.toString(totalIterations))) * 100); + Double.toString((double) (currentIteration / totalIterations) * 100); int percentIndex = ((percentDone.indexOf(".") + 3) > percentDone.length()) ? percentDone .length() : (percentDone.indexOf(".") + 3); //fix index on numbers like 12.3 @@ -513,45 +588,17 @@ public class Main { + currentIteration + "/" + totalIterations + ") " + percentDone + "% Done"); // Time Remaining estimate - //timeTracking[0] = timeTracking[1]; - //timeTracking[1] = timeTracking[2]; - //timeTracking[2] = timeTracking[3]; - //timeTracking[3] = System.currentTimeMillis(); + if (testing) { + out("X:" + curXloops + ", Z:" + curZloops); + } + timeTracking = System.currentTimeMillis(); //NEW CODE: differenceTime = (timeTracking - generationStartTimeTracking) / (currentIteration + 1); // Updated. we now count all runs, instead of the last 4. - differenceTime *= 1 + (totalIterations - currentIteration); //this should provide a more accurate result. - out("Estimated time remaining: " + displayTime(differenceTime)); - - //OLD CODE: - /* - if (currentIteration >= 4) { - differenceTime = (timeTracking[3] - timeTracking[0]) / 3; // well, this is what it boils down to - differenceTime *= 1 + (totalIterations - currentIteration); - out(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)); - } else if (currentIteration == 3) { - differenceTime = (timeTracking[3] - timeTracking[1]) / 2; // well, this is what it boils down to - differenceTime *= 1 + (totalIterations - currentIteration); - out(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)); - } else if (currentIteration == 2) { - differenceTime = (timeTracking[3] - timeTracking[2]); // well, this is what it boils down to - differenceTime *= 1 + (totalIterations - currentIteration); - out(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)); - } else if (currentIteration <= 1) { - out("Estimated time remaining: Calculating..."); - } - */ + differenceTime *= 1 + (totalIterations - currentIteration); // this should provide a more accurate result. + out("Estimated time remaining: " + displayTime(differenceTime)); // I've noticed it gets pretty accurate after about 8 launches! // Set the spawn point setSpawn(serverLevel, currentX + xOffset, 64, currentZ + zOffset); @@ -559,6 +606,15 @@ public class Main { // Launch the server runMinecraft(verbose, alternate); out(""); + + if (curZloops == 1) { + currentZ = (((0 - zRange) / 2) + (incrementZ / 2)); + } + + } + curZloops = 0; + if (curXloops == 1) { + currentX = (((0 - xRange) / 2) + (incrementX / 2)); } } @@ -636,6 +692,9 @@ public class Main { //@formatter:off + //Note: The Following Information is Old (from 2010), compared to the Data inside a current "level.dat". + //However, What we look at (SpawnX,Y,Z and RandomSeed) have not changed. + /* * Structure: * @@ -704,7 +763,9 @@ public class Main { * @author Corrodias */ protected static void runMinecraft(boolean verbose, boolean alternate) throws IOException { - out("Starting server."); + if (verbose) { + out("Starting server."); + } boolean warning = false; boolean cantKeepUp = false; @@ -713,11 +774,6 @@ public class Main { // monitor output and print to console where required. // STOP the server when it's done. - // Damn it Java! I hate you so much! - // I can't reuse code the way I want to, like in other langauges. - // So, here is a bunch of duplicate code... - // Stupid compile errors... - if (alternate) { // Alternate - a replication (slightly stripped down) of MLG 1.3.0's code. simplest code possible. out("Alternate Launch"); Process process = minecraft.start(); @@ -1019,179 +1075,11 @@ public class Main { */ private static void readMe(String readmeFile) { - if (readmeFile == "" || readmeFile == null) { - readmeFile = defaultReadmeFile; - } - - String showHelpSTR = ""; - showHelpSTR = showHelp(false); //stored as a string for easier manipulation in the future - - //@formatter:off - String ReadMeText = ""; - ReadMeText = PROG_NAME + " version " + VERSION + newLine - + newLine - + "Updated " + dateFormat_MDY.format(MLG_Last_Modified_Date) + newLine - + "(BuildID: " + MLG_Last_Modified_Date.getTime() + ")" + newLine - + newLine - + "Original Code by Corrodias November 2010" + newLine - + "Enhanced Code by Morlok8k Feb. 2011 to Now (or at least to " + dateFormat_MDY.format(MLG_Last_Modified_Date) + "!)" + newLine - + "Additional Code by pr0f1x October 2011" + newLine - + newLine - + "Website: https://sites.google.com/site/minecraftlandgenerator/" + newLine - + "Forum: http://www.minecraftforum.net/topic/187737-minecraft-land-generator/" + newLine - + "Source: https://github.com/Morlok8k/MinecraftLandGenerator" + newLine - + newLine - + "-----------------------------------------------" + newLine - + newLine - + "This program lets you generate an area of land with your Minecraft Beta SMP server (and is prossibly future-proof for newer versions). You set up your java command line and minecraft server paths in the MinecraftLandGenerator.conf file, set up the server's server.properties file with the name of the world you wish to use, and then run this program." + newLine - + "When a Minecraft server is launched, it automatically generates chunks within a square area of 25x25 chunks (400x400 blocks), centered on the current spawn point (formally 20x20 chunks, 320x320 blocks). When provided X and Z ranges as arguments, this program will launch the server repeatedly, editing the level.dat file between sessions, to generate large amounts of land without players having to explore them. The generated land will have about the X and Z ranges as requested by the arguments, though it will not be exact due to the spawn point typically not on the border of a chunk. (Because of this, MLG by default adds a slight overlap with each pass - 380x380 blocks) You can use the -x and -z switches to override the spawn offset and center the land generation on a different point." + newLine - + "The program makes a backup of level.dat as level_backup.dat before editing, and restores the backup at the end. In the event that a level_backup.dat file already exists, the program will refuse to proceed, leaving the user to determine why the level_backup.dat file exists and whether they would rather restore it or delete it, which must be done manually." + newLine - + newLine - + "This program is public domain, and the source code is included in the .jar file. (If accidently missing, like in 1.3.0 and 1.4.0, it is always available at Github.)" + newLine - + "The JNLP library is included (inside the .jar). It is not public domain. Its license is included, as LICENSE.TXT." + newLine - + "It is also available at: http://jnbt.sourceforge.net/" + newLine - + newLine - + "The \"unescape\" method/function is also not Public Domain. Its License is the W3C\u00A9 Software License, and located here: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231" - + newLine - + "Other Public Domain code has been used in this program, and references to sources are included in the comments of " + PROG_NAME + "'s source code." - + newLine - + "-----------------------------------------------" + newLine - + newLine - + "Version History:" + newLine - + "Morlok8k:" + newLine - + "1.6.11" + newLine - + "- Removed End-of-Generation ASCII-Graphic - It didn't really fit with MLG." + newLine - + "- Updated Time Output." + newLine - + "- Changed estimated time remaining to count all runs, not just the last four." + newLine - + "- Added the time it took to complete at the end of generation." + newLine - + newLine - + "1.6.1" + newLine - + "- Added some modifications for scripting (Mainly for a new Initial setup script)" + newLine - + "- Changed MLG's Y to Z. Now it matches Minecraft. Y in the game is Height." + newLine - + "- Renamed -y switch to -z. MLG will remain backwards compatible if you use the old -y switch." + newLine - + "- Updated -printspawn to show X,Y,Z" + newLine - + "- Added End-of-Generation ASCII-Graphic" + newLine - + "- Slightly altered some text output" + newLine - + newLine - + "1.6.05" + newLine - + "- MLG displays if the server is converting the Map format, when not in verbose mode. (McRegion -> Anvil, or Chunk-File -> McRegion)" + newLine - + "- Minor fixes/edits/typos" + newLine - + "- Added link to new MLG website to readme file" - + newLine - + "1.6.03" + newLine - + "- added decoding of escape characters of URL's (so a space is a \" \" and not \"%20\")" + newLine - + "- added \"-downloadlist [list]\" where [list] is a text file with URL's on each line" + newLine - + newLine - + "1.6.02" + newLine - + "- small fix on caculating md5sum where old version didnt pad out to 32chars with zeros on the left side" - + "- quick Archive intergity fix after injecting source code into .jar after it compiled." - + "- no new functionality, md5 issue doesnt affect -update on old versions." - + newLine - + "1.6.0" + newLine - + "- NOW DOES NOT NEED ANY SCRIPT FILES!" + newLine - + "- Added the ability to download files from the internet" + newLine - + "- Added a switch to download any file off the internet, if needed (useless for most people, but included it in case I wanted it in the future.)" + newLine - + "- Added the ability to check what version the .jar is. (Using MD5 hashes, timestamps, and the BuildID file)" + newLine - + "- Added \"-update\" to download new versions of MLG directly from github." + newLine - + "- Updated estimated time. Now shows up on loop 2+ instead of loop 4+." + newLine - + "- Standard % output of the Server should look nicer now." + newLine - + "- Code Refactoring" + newLine - + "- Code Formatting" + newLine - + "- Code Optimization" + newLine - + "- Duplicate sections of code have been turned into Methods/\"Functions\"" + newLine - + newLine - + "1.5.1" + newLine - + "- pr0f1x: Added the \"save-all\" command to be sent to the server before shutting it down." + newLine - + "- pr0f1x: Added a 40 second wait before shutting down." + newLine - + "- Morlok8k: Made 40 second wait optional." + newLine - + "- Morlok8k: Changed the Dimensions code. (I had assumed it would be DIM-1, DIM-2, etc. but it turned out to be DIM-1 and DIM1. Change reflects Server output of \"Level n\")" + newLine - + "- Morlok8k: Config file is automatically updated to reflect these changes." + newLine - + "- Morlok8k: Cleaned up code." + newLine - + newLine - + "1.5.0" + newLine - + "- Supports Server Beta 1.6.4 (& hopefully future versions as well, while remaining backward compatible.)" + newLine - + "- Added \"-a\",\"-alt\" to use alternate method (a slightly simplier version of 1.3.0's code - pure verbose only)" + newLine - + "- Added world specific output for 9 dimensions (DIM-1 is the Nether, DIM-2 through DIM-9 dont exist yet, but if and when they do, you can configure it's text). (\"Level 0\", the default world, is displayed as the worlds name)" + newLine - + "- Updated Config File for these Dimensions." + newLine - + "- Reads and outputs the Seed to the output. (If you had used text for the Seed, Minecraft converts it into a number. This outputs the number.)" + newLine - + "- Changed the default 300 blocks to 380. The server now makes a 400x400 square block terrain instead of 320x320. Thus it is faster because there are less loops. To use the old way, use \"-i300\"" + newLine - + "- Added total Percentage done (technically, it displays the % done once the server finishes...)" + newLine - + "- Added debugging output vars of conf file (disabled - need to re-compile source to activate)" + newLine - + newLine - + "\t\t+ (the goal is to have MLG be configureable, so it can work on any version of the server, past or present.)" + newLine - + newLine - + "*** 1.4.5 (pre 1.5.0) ***" + newLine - + "- sorry! I shouldn't release untested code..." + newLine - + "*************************" + newLine - + newLine - + "1.4.4" + newLine - + "- Added ablilty to ignore [WARNING] and [SEVERE] errors with \"-w\"" + newLine - + newLine - + "1.4.3" + newLine - + "- Fixed \"-ps\",\"-printspawn\" as I had forgot I had broken it in 1.4.0 - due to config file change." + newLine - + newLine - + "1.4.2" + newLine - + "- No New Features" + newLine - + "- Changed non-verbose mode to display server progress on the same line, saving a lot of space." + newLine - + " - This couldn't wait for 1.5.0 ... I (Morlok8k) liked it too much." + newLine - + newLine - + "1.4.0" + newLine - + "- Future Proofing" + newLine - + "- Configurble Server Message reading. (If server updates and breaks MLG, you can add the new text!)" + newLine - + "- Updated config file, and auto updating from old format." + newLine - + "- Added % of spawn area to non-verbose output." + newLine - + "- Removed datetime stamps from server output in verbose mode" + newLine - + "- Other Misc fixes." + newLine - + newLine - + "1.3.0" + newLine - + "- Fixed Problems with Minecraft Beta 1.3 -- Morlok8k" + newLine - + newLine - + "-----------------------------------------------" + newLine - + newLine - + "Corrodias:" + newLine - + "1.2.0" + newLine - + "- land generation now centers on the spawn point instead of [0, 0]" + newLine - + "- the server is launched once before the spawn point is changed, to verify that it can run and to create a world if one doesn't exist" + newLine - + "- added -printspawn [-ps] switch to print the current spawn coordinates to the console" + newLine - + "- added -x and -y switches to override the X and Y offsets" + newLine - + "- added -v switch, does the same as -verbose" + newLine - + "- improved status message spacing to make things easier to read" + newLine - + "- improved time estimation algorithm: it now averages the last 3 launches" + newLine - + newLine - + "1.1.0" + newLine - + "- added MinecraftLandGenerator.conf file to hold the java command line and the server path" + newLine - + "- added -conf solo switch to generate a .conf file" + newLine - + "- added -verbose switch to output server output to the console (default is to ignore it)" + newLine - + "- added -i switch to allow customizing the block increment size (default is 300)" + newLine - + "- added instructions output in this version, i think" + newLine - + "- improved status message output to include current iteration and total iterations" + newLine - + newLine - + "1.0.0" + newLine - + "- initial release" + newLine - + newLine - + "-----------------------------------------------" + newLine - + newLine - + "Notes:" + newLine - + "Due to changes in server beta 1.6, it now generates the nether as well as the world at the same time." + newLine - + "However, Since beta 1.9 and Minecraft 1.0, the nether or the end is no longer generated." - + "I recommend using MCEDIT to relight the map after you generate it. This will take a long time, but should fix all those incorrectly dark spots in your level." + newLine - + newLine - + "-----------------------------------------------" + newLine - + newLine; - //@formatter:on - - writeTxtFile(readmeFile, ReadMeText + showHelpSTR); + Readme_and_HelpInfo.readMe(readmeFile); } /** - * - * Downloads a File using a URL in a String.
- * (If the file is a dynamic URL (Not like "http://example.com/file.txt") and it can't get the filename, it saves it as "System.currentTimeMillis();")
- *
- * Thanks to bs123 at
- * http://www.daniweb.com/software-development/java/threads/84370 - * * @author Morlok8k * @param URL * URL in a String @@ -1200,80 +1088,8 @@ public class Main { * @return Boolean: true if download was successful, false if download wasn't */ private static boolean downloadFile(String URL, boolean Output) { - - boolean success = true; - - String fileName = URL.substring(URL.lastIndexOf("/") + 1, URL.length()); - - if (fileName.startsWith("\"")) { - if (fileName.substring(fileName.length() - 1, fileName.length()) == "\"") { - fileName = fileName.substring(1, fileName.length() - 1); - } - } - - int size = 1024 * 4; // 1024 * n should be tested to get the optimum size (for download speed.) - - if (fileName.equals("")) { - fileName = String.valueOf(System.currentTimeMillis()); - } - - fileName = unescape(fileName); - - if (Output) { - out("Downloading: " + URL); - out("Saving as: " + fileName); - } - - long differenceTime = System.currentTimeMillis(); - Long[] timeTracking = new Long[] { differenceTime, differenceTime }; - timeTracking[0] = System.currentTimeMillis(); - - if (Output) { - outP(MLG + "*"); - } - - try { - BufferedInputStream in; - in = new BufferedInputStream(new URL(URL).openStream()); - FileOutputStream fos; - fos = new FileOutputStream(fileName); - BufferedOutputStream bout = new BufferedOutputStream(fos, size); - byte[] data = new byte[size]; - int x = 0; - int count = 0; - while ((x = in.read(data, 0, size)) >= 0) { - bout.write(data, 0, x); - count = count + x; - if (Output) { - outP("*"); - } - } - bout.close(); - in.close(); - if (Output) { - outP(newLine); - out(count + " byte(s) copied"); - } - - timeTracking[1] = System.currentTimeMillis(); - //differenceTime = (timeTracking[1] - timeTracking[0]); - if (Output) { - out("Elapsed Time: " + displayTime(timeTracking[0], timeTracking[1])); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - success = false; - } catch (MalformedURLException e) { - e.printStackTrace(); - success = false; - } catch (IOException e) { - e.printStackTrace(); - success = false; - } - if (Output) { - out("Done"); - } - return success; + //This exists so I don't need to type "DownloadFile.downloadFile" every time. + return DownloadFile.downloadFile(URL, Output); } /** @@ -1661,38 +1477,12 @@ public class Main { /** * This gets the MD5 of a file
- *
- * Thanks to R.J. Lorimer at
- * http://www. javalobby.org/java/forums/t84420.html * * @author Morlok8k */ private static String fileMD5(String fileName) throws NoSuchAlgorithmException, FileNotFoundException { - // out(""); - // out(""); - MessageDigest digest = MessageDigest.getInstance("MD5"); - InputStream is = new FileInputStream(fileName); - byte[] buffer = new byte[8192]; - int read = 0; - try { - while ((read = is.read(buffer)) > 0) { - digest.update(buffer, 0, read); - } - byte[] md5sum = digest.digest(); - BigInteger bigInt = new BigInteger(1, md5sum); - String output = String.format("%1$032X", bigInt); //pad on left to 32 chars with 0's, also capitalize. - // out("MD5: " + output); - return output.toUpperCase(Locale.ENGLISH); - } catch (IOException e) { - throw new RuntimeException("Unable to process file for MD5", e); - } finally { - try { - is.close(); - } catch (IOException e) { - throw new RuntimeException("Unable to close input stream for MD5 calculation", e); - } - } + return MD5.fileMD5(fileName); } /** @@ -1705,86 +1495,8 @@ public class Main { * @author Morlok8k */ private static String showHelp(boolean SysOut) { - String Str = null; - String NewLine = newLine; - if (SysOut) { - NewLine = newLine + MLG; - } - - //@formatter:off - Str = "Usage: java -jar " + MLGFileNameShort + " x z [serverpath] [switches]" + NewLine - + NewLine - + "Arguments:" + NewLine - + " x : X range to generate" + NewLine - + " z : Z range to generate" + NewLine - + " serverpath : the path to the directory in which the server runs (takes precedence over the config file setting)" + NewLine - + NewLine - + "Switches:" + NewLine - + " -verbose : causes the application to output the server's messages to the console" + NewLine - + " -v : same as -verbose" + NewLine - + " -w : Ignore [WARNING] and [SEVERE] messages." + NewLine - + " -alt : alternate server launch sequence" + NewLine - + " -a : same as -alt" + NewLine - + " -i# : override the iteration spawn offset increment (default 380) (example: -i100)" + NewLine - + " -x# : set the X offset to generate land around (example: -x0 or -x1000 or -x-500)" + NewLine - + " -z# : set the Z offset to generate land around (example: -z0 or -z1000 or -z-500)" + NewLine - + NewLine - + "Other options:" + NewLine - + " java -jar " + MLGFileNameShort + " -update" + NewLine - + " Checks for and downloads new versions of MLG online." + NewLine - + NewLine - + " java -jar " + MLGFileNameShort + " -printspawn" + NewLine - + " java -jar " + MLGFileNameShort + " -ps" + NewLine - + " Outputs the current world's spawn point coordinates." + NewLine - + NewLine - + " java -jar " + MLGFileNameShort + " -conf" + NewLine - + " java -jar " + MLGFileNameShort + " -conf download" + NewLine - + " Generates or downloads a "+ MinecraftLandGeneratorConf + " file." + NewLine - + NewLine - + " java -jar " + MLGFileNameShort + " -readme readme.txt" + NewLine - + " java -jar " + MLGFileNameShort + " -readme" + NewLine - + " Generates a readme file using supplied name or the default " + defaultReadmeFile + NewLine - + NewLine - + " java -jar " + MLGFileNameShort + " -downloadfile http://example.com/file.txt" + NewLine - + " Downloads whatever file from the internet you give it." + NewLine - + " java -jar " + MLGFileNameShort + " -downloadlist list.txt" + NewLine - + " list.txt (or any other file) contains a URL on each line which will be downloaded." + NewLine - + NewLine - + " java -jar " + MLGFileNameShort + " -version" + NewLine - + " java -jar " + MLGFileNameShort + " -help" + NewLine - + " java -jar " + MLGFileNameShort + " /?" + NewLine - + " Prints this message." + NewLine - + NewLine - + "When launched with the -conf switch, this application creates a " + MinecraftLandGeneratorConf + " file that contains configuration options." + NewLine - + "If this file does not exist or does not contain all required properties, the application will not run." + NewLine - + NewLine - + MinecraftLandGeneratorConf + " properties:" + NewLine - + " Java : The command line to use to launch the server" + NewLine - + " ServerPath : The path to the directory in which the server runs (can be overridden by the serverpath argument)" + NewLine - + " Done_Text : The output from the server that tells us that we are done" + NewLine - + " Preparing_Text : The output from the server that tells us the percentage" + NewLine - + "Preparing_Level : The output from the server that tells us the level it is working on" + NewLine - + " Level-0 : Name of Level 0: The Overworld" + NewLine - + " Level-1 : Name of Level 1: The Nether" + NewLine - + " Level-2 : Name of Level 2: The End" + NewLine - + " Level-3 : Name of Level 3: (Future Level)" + NewLine - + " Level-4 : Name of Level 4: (Future Level)" + NewLine - + " Level-5 : Name of Level 5: (Future Level)" + NewLine - + " Level-6 : Name of Level 6: (Future Level)" + NewLine - + " Level-7 : Name of Level 7: (Future Level)" + NewLine - + " Level-8 : Name of Level 8: (Future Level)" + NewLine - + " Level-9 : Name of Level 9: (Future Level)" + NewLine - + " WaitSave : Optional: Wait before saving." + NewLine; - //@formatter:on - - if (SysOut) { - out(Str); - out(""); - return null; - } else { - return Str; - } + return Readme_and_HelpInfo.showHelp(SysOut); } /** @@ -2045,7 +1757,7 @@ public class Main { } - private static void writeTxtFile(String file, String txt) { + public static void writeTxtFile(String file, String txt) { //TODO: element comment /* @@ -2077,7 +1789,7 @@ public class Main { * String to display and format * @author Morlok8k */ - private static void out(String str) { + public static void out(String str) { System.out.println(MLG + str); // is there a better/easier way to do this? I just wanted a lazier way to write "System.out.println(MLG + blah..." } @@ -2088,7 +1800,7 @@ public class Main { * String to display and format * @author Morlok8k */ - private static void err(String str) { + public static void err(String str) { System.err.println(MLGe + str); } @@ -2099,7 +1811,7 @@ public class Main { * String to display and format * @author Morlok8k */ - private static void outP(String str) { + public static void outP(String str) { System.out.print(str); } @@ -2183,7 +1895,7 @@ public class Main { * @author Morlok8k * @return String of Readable Time */ - private static String displayTime(long startTimeMillis, long endTimeMillis) { + public static String displayTime(long startTimeMillis, long endTimeMillis) { long millis = (endTimeMillis - startTimeMillis); //I just duplicated displayTime to have a start & end times, because it just made things simpler to code. @@ -2197,7 +1909,7 @@ public class Main { * @author Morlok8k * @return String of Readable Time */ - private static String displayTime(long timeMillis) { + public static String displayTime(long timeMillis) { long seconds = timeMillis / 1000; long minutes = seconds / 60; @@ -2206,91 +1918,19 @@ public class Main { long years = days / 365; String took = - (years > 0 ? String.format("%d Years, ", years) : "") - + (days > 0 ? String.format("%d Days, ", days % 365) : "") - + (hours > 0 ? String.format("%d Hours, ", hours % 24) : "") - + (minutes > 0 ? String.format("%d Minutes, ", minutes % 60) : "") - + String.format("%d Seconds", seconds % 60); + (years > 0 ? String.format("%d " + ((years) == 1 ? "Year, " : "Years, "), years) + : "") + + (days > 0 ? String.format("%d " + + ((days % 365) == 1 ? "Day, " : "Days, "), days % 365) : "") + + (hours > 0 ? String.format("%d " + + ((hours % 24) == 1 ? "Hour, " : "Hours, "), hours % 24) : "") + + (minutes > 0 ? String.format("%d " + + ((minutes % 60) == 1 ? "Minute, " : "Minutes, "), minutes % 60) + : "") + + String.format("%d " + ((seconds % 60) == 1 ? "Second, " : "Seconds, "), + seconds % 60); return (took); } - /* Morlok8k: - * Just a note about this unescape method: - * I am quite amazed at this code. It is vastly superior to my own coding ability. - * I had to look up many things in it to see how it works, and I still don't quite follow it. - * (I have never worked with raw bytes in Java... Never needed to.) - * But it works and it works very well. I tip my hat at you Bert! - * - * I just needed to say this somewhere, even though very few people will ever read this. - */ - /** - * Created: 17 April 1997
- * Author: Bert Bos <bert@w3.org>
- *
- * unescape: http://www.w3.org/International/unescape.java
- *
- * Copyright © 1997 World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University). All Rights Reserved. - * This work is distributed under the W3C® Software License [1] in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE.
- *
- * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - * - * @param s - * string of URL - * @return decoded string of URL - * @author Bert Bos - */ - private static String unescape(String s) { - StringBuffer sbuf = new StringBuffer(); - int l = s.length(); - int ch = -1; - int b, sumb = 0; - for (int i = 0, more = -1; i < l; i++) { - /* Get next byte b from URL segment s */ - switch (ch = s.charAt(i)) { - case '%': - ch = s.charAt(++i); - int hb = - (Character.isDigit((char) ch) ? ch - '0' : 10 + Character - .toLowerCase((char) ch) - 'a') & 0xF; - ch = s.charAt(++i); - int lb = - (Character.isDigit((char) ch) ? ch - '0' : 10 + Character - .toLowerCase((char) ch) - 'a') & 0xF; - b = (hb << 4) | lb; - break; - case '+': - b = ' '; - break; - default: - b = ch; - } - /* Decode byte b as UTF-8, sumb collects incomplete chars */ - if ((b & 0xc0) == 0x80) { // 10xxxxxx (continuation byte) - sumb = (sumb << 6) | (b & 0x3f); // Add 6 bits to sumb - if (--more == 0) sbuf.append((char) sumb); // Add char to sbuf - } else if ((b & 0x80) == 0x00) { // 0xxxxxxx (yields 7 bits) - sbuf.append((char) b); // Store in sbuf - } else if ((b & 0xe0) == 0xc0) { // 110xxxxx (yields 5 bits) - sumb = b & 0x1f; - more = 1; // Expect 1 more byte - } else if ((b & 0xf0) == 0xe0) { // 1110xxxx (yields 4 bits) - sumb = b & 0x0f; - more = 2; // Expect 2 more bytes - } else if ((b & 0xf8) == 0xf0) { // 11110xxx (yields 3 bits) - sumb = b & 0x07; - more = 3; // Expect 3 more bytes - } else if ((b & 0xfc) == 0xf8) { // 111110xx (yields 2 bits) - sumb = b & 0x03; - more = 4; // Expect 4 more bytes - } else /*if ((b & 0xfe) == 0xfc)*/{ // 1111110x (yields 1 bit) - sumb = b & 0x01; - more = 5; // Expect 5 more bytes - } - /* We don't test if the UTF-8 encoding is well-formed */ - } - return sbuf.toString(); - } - } diff --git a/src/morlok8k/minecraft/landgenerator/DownloadFile.java b/src/morlok8k/minecraft/landgenerator/DownloadFile.java new file mode 100644 index 0000000..fc75043 --- /dev/null +++ b/src/morlok8k/minecraft/landgenerator/DownloadFile.java @@ -0,0 +1,109 @@ +package morlok8k.minecraft.landgenerator; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.w3c.bert_bos.UTF8URL.Unescape; + +import corrodias.minecraft.landgenerator.Main; + +public class DownloadFile { + + /** + * + * Downloads a File using a URL in a String.
+ * (If the file is a dynamic URL (Not like "http://example.com/file.txt") and it can't get the filename, it saves it as "System.currentTimeMillis();")
+ *
+ * Thanks to bs123 at
+ * http://www.daniweb.com/software-development/java/threads/84370 + * + * @author Morlok8k + * @param URL + * URL in a String + * @param Output + * Displays output if true + * @return Boolean: true if download was successful, false if download wasn't + */ + public static boolean downloadFile(String URL, boolean Output) { + + boolean success = true; + + String fileName = URL.substring(URL.lastIndexOf("/") + 1, URL.length()); + + if (fileName.startsWith("\"")) { + if (fileName.substring(fileName.length() - 1, fileName.length()) == "\"") { + fileName = fileName.substring(1, fileName.length() - 1); + } + } + + int size = 1024 * 4; // 1024 * n should be tested to get the optimum size (for download speed.) + + if (fileName.equals("")) { + fileName = String.valueOf(System.currentTimeMillis()); + } + + fileName = Unescape.unescape(fileName); + + if (Output) { + Main.out("Downloading: " + URL); + Main.out("Saving as: " + fileName); + } + + long differenceTime = System.currentTimeMillis(); + Long[] timeTracking = new Long[] { differenceTime, differenceTime }; + timeTracking[0] = System.currentTimeMillis(); + + if (Output) { + Main.outP(Main.MLG + "*"); + } + + try { + BufferedInputStream in; + in = new BufferedInputStream(new URL(URL).openStream()); + FileOutputStream fos; + fos = new FileOutputStream(fileName); + BufferedOutputStream bout = new BufferedOutputStream(fos, size); + byte[] data = new byte[size]; + int x = 0; + int count = 0; + while ((x = in.read(data, 0, size)) >= 0) { + bout.write(data, 0, x); + count = count + x; + if (Output) { + Main.outP("*"); + } + } + bout.close(); + in.close(); + if (Output) { + Main.outP(Main.newLine); + Main.out(count + " byte(s) copied"); + } + + timeTracking[1] = System.currentTimeMillis(); + //differenceTime = (timeTracking[1] - timeTracking[0]); + if (Output) { + Main.out("Elapsed Time: " + Main.displayTime(timeTracking[0], timeTracking[1])); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + success = false; + } catch (MalformedURLException e) { + e.printStackTrace(); + success = false; + } catch (IOException e) { + e.printStackTrace(); + success = false; + } + if (Output) { + Main.out("Done"); + } + return success; + } + +} diff --git a/src/morlok8k/minecraft/landgenerator/MD5.java b/src/morlok8k/minecraft/landgenerator/MD5.java new file mode 100644 index 0000000..e7badbe --- /dev/null +++ b/src/morlok8k/minecraft/landgenerator/MD5.java @@ -0,0 +1,50 @@ +package morlok8k.minecraft.landgenerator; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; + +public class MD5 { + + /** + * This gets the MD5 of a file
+ *
+ * Thanks to R.J. Lorimer at
+ * http://www. javalobby.org/java/forums/t84420.html + * + * @author Morlok8k + */ + public static String fileMD5(String fileName) throws NoSuchAlgorithmException, + FileNotFoundException { + // out(""); + // out(""); + MessageDigest digest = MessageDigest.getInstance("MD5"); + InputStream is = new FileInputStream(fileName); + byte[] buffer = new byte[8192]; + int read = 0; + try { + while ((read = is.read(buffer)) > 0) { + digest.update(buffer, 0, read); + } + byte[] md5sum = digest.digest(); + BigInteger bigInt = new BigInteger(1, md5sum); + String output = String.format("%1$032X", bigInt); //pad on left to 32 chars with 0's, also capitalize. + // out("MD5: " + output); + return output.toUpperCase(Locale.ENGLISH); + } catch (IOException e) { + throw new RuntimeException("Unable to process file for MD5", e); + } finally { + try { + is.close(); + } catch (IOException e) { + throw new RuntimeException("Unable to close input stream for MD5 calculation", e); + } + } + } + +} diff --git a/src/morlok8k/minecraft/landgenerator/Readme_and_HelpInfo.java b/src/morlok8k/minecraft/landgenerator/Readme_and_HelpInfo.java new file mode 100644 index 0000000..03dcde4 --- /dev/null +++ b/src/morlok8k/minecraft/landgenerator/Readme_and_HelpInfo.java @@ -0,0 +1,290 @@ +package morlok8k.minecraft.landgenerator; + +import corrodias.minecraft.landgenerator.Main; + +public class Readme_and_HelpInfo { + + static String newLine = Main.newLine; + static String MLGFileNameShort = Main.MLGFileNameShort; + static String MinecraftLandGeneratorConf = Main.MinecraftLandGeneratorConf; + static String defaultReadmeFile = Main.defaultReadmeFile; + + /** + * Saves a Readme file. + * + * @param readmeFile + * @author Morlok8k + * + */ + public static void readMe(String readmeFile) { + + if (readmeFile == "" || readmeFile == null) { + readmeFile = defaultReadmeFile; + } + + String MLG_Last_Modified_MDY = Main.dateFormat_MDY.format(Main.MLG_Last_Modified_Date); + String PROG_NAME = Main.PROG_NAME; + String VERSION = Main.VERSION; + + String showHelpSTR = ""; + showHelpSTR = showHelp(false); //stored as a string for easier manipulation in the future + + //@formatter:off + String ReadMeText = ""; + ReadMeText = PROG_NAME + " version " + VERSION + newLine + + newLine + + "Updated " + MLG_Last_Modified_MDY + newLine + + "(BuildID: " + Main.MLG_Last_Modified_Date.getTime() + ")" + newLine + + newLine + + "Original Code by Corrodias November 2010" + newLine + + "Enhanced Code by Morlok8k Feb. 2011 to Now (or at least to " + MLG_Last_Modified_MDY + "!)" + newLine + + "Additional Code by pr0f1x October 2011" + newLine + + newLine + + "Website: https://sites.google.com/site/minecraftlandgenerator/" + newLine + + "Forum: http://www.minecraftforum.net/topic/187737-minecraft-land-generator/" + newLine + + "Source: https://github.com/Morlok8k/MinecraftLandGenerator" + newLine + + newLine + + "-----------------------------------------------" + newLine + + newLine + + "This program lets you generate an area of land with your Minecraft Beta SMP server (and is prossibly future-proof for newer versions). You set up your java command line and minecraft server paths in the MinecraftLandGenerator.conf file, set up the server's server.properties file with the name of the world you wish to use, and then run this program." + newLine + + "When a Minecraft server is launched, it automatically generates chunks within a square area of 25x25 chunks (400x400 blocks), centered on the current spawn point (formally 20x20 chunks, 320x320 blocks). When provided X and Z ranges as arguments, this program will launch the server repeatedly, editing the level.dat file between sessions, to generate large amounts of land without players having to explore them. The generated land will have about the X and Z ranges as requested by the arguments, though it will not be exact due to the spawn point typically not on the border of a chunk. (Because of this, MLG by default adds a slight overlap with each pass - 380x380 blocks) You can use the -x and -z switches to override the spawn offset and center the land generation on a different point." + newLine + + "The program makes a backup of level.dat as level_backup.dat before editing, and restores the backup at the end. In the event that a level_backup.dat file already exists, the program will refuse to proceed, leaving the user to determine why the level_backup.dat file exists and whether they would rather restore it or delete it, which must be done manually." + newLine + + newLine + + "This program is public domain, and the source code is included in the .jar file. (If accidently missing, like in 1.3.0 and 1.4.0, it is always available at Github.)" + newLine + + "The JNLP library is included (inside the .jar). It is not public domain. Its license is included, as LICENSE.TXT." + newLine + + "It is also available at: http://jnbt.sourceforge.net/" + newLine + + newLine + + "The \"unescape\" method/function is also not Public Domain. Its License is the W3C\u00A9 Software License, and located here: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231" + + newLine + + "Other Public Domain code has been used in this program, and references to sources are included in the comments of " + PROG_NAME + "'s source code." + + newLine + + "-----------------------------------------------" + newLine + + newLine + + "Version History:" + newLine + + "Morlok8k:" + newLine + + "1.6.2" + newLine + + "- Major Code Optimization" + newLine + + "- Updated Time Output again. Now says \"1 Minute\" instead of \"1 Minutes\"." + newLine + + "- Updated Location Code - the center of the square is now truely centered, and it trys to get as close to the given size as possible." + newLine + + newLine + + "1.6.11" + newLine + + "- Removed End-of-Generation ASCII-Graphic - It didn't really fit with MLG." + newLine + + "- Updated Time Output." + newLine + + "- Changed estimated time remaining to count all runs, not just the last four." + newLine + + "- Added the time it took to complete at the end of generation." + newLine + + newLine + + "1.6.1" + newLine + + "- Added some modifications for scripting (Mainly for a new Initial setup script)" + newLine + + "- Changed MLG's Y to Z. Now it matches Minecraft. Y in the game is Height." + newLine + + "- Renamed -y switch to -z. MLG will remain backwards compatible if you use the old -y switch." + newLine + + "- Updated -printspawn to show X,Y,Z" + newLine + + "- Added End-of-Generation ASCII-Graphic" + newLine + + "- Slightly altered some text output" + newLine + + newLine + + "1.6.05" + newLine + + "- MLG displays if the server is converting the Map format, when not in verbose mode. (McRegion -> Anvil, or Chunk-File -> McRegion)" + newLine + + "- Minor fixes/edits/typos" + newLine + + "- Added link to new MLG website to readme file" + + newLine + + "1.6.03" + newLine + + "- added decoding of escape characters of URL's (so a space is a \" \" and not \"%20\")" + newLine + + "- added \"-downloadlist [list]\" where [list] is a text file with URL's on each line" + newLine + + newLine + + "1.6.02" + newLine + + "- small fix on caculating md5sum where old version didnt pad out to 32chars with zeros on the left side" + + "- quick Archive intergity fix after injecting source code into .jar after it compiled." + + "- no new functionality, md5 issue doesnt affect -update on old versions." + + newLine + + "1.6.0" + newLine + + "- NOW DOES NOT NEED ANY SCRIPT FILES!" + newLine + + "- Added the ability to download files from the internet" + newLine + + "- Added a switch to download any file off the internet, if needed (useless for most people, but included it in case I wanted it in the future.)" + newLine + + "- Added the ability to check what version the .jar is. (Using MD5 hashes, timestamps, and the BuildID file)" + newLine + + "- Added \"-update\" to download new versions of MLG directly from github." + newLine + + "- Updated estimated time. Now shows up on loop 2+ instead of loop 4+." + newLine + + "- Standard % output of the Server should look nicer now." + newLine + + "- Code Refactoring" + newLine + + "- Code Formatting" + newLine + + "- Code Optimization" + newLine + + "- Duplicate sections of code have been turned into Methods/\"Functions\"" + newLine + + newLine + + "1.5.1" + newLine + + "- pr0f1x: Added the \"save-all\" command to be sent to the server before shutting it down." + newLine + + "- pr0f1x: Added a 40 second wait before shutting down." + newLine + + "- Morlok8k: Made 40 second wait optional." + newLine + + "- Morlok8k: Changed the Dimensions code. (I had assumed it would be DIM-1, DIM-2, etc. but it turned out to be DIM-1 and DIM1. Change reflects Server output of \"Level n\")" + newLine + + "- Morlok8k: Config file is automatically updated to reflect these changes." + newLine + + "- Morlok8k: Cleaned up code." + newLine + + newLine + + "1.5.0" + newLine + + "- Supports Server Beta 1.6.4 (& hopefully future versions as well, while remaining backward compatible.)" + newLine + + "- Added \"-a\",\"-alt\" to use alternate method (a slightly simplier version of 1.3.0's code - pure verbose only)" + newLine + + "- Added world specific output for 9 dimensions (DIM-1 is the Nether, DIM-2 through DIM-9 dont exist yet, but if and when they do, you can configure it's text). (\"Level 0\", the default world, is displayed as the worlds name)" + newLine + + "- Updated Config File for these Dimensions." + newLine + + "- Reads and outputs the Seed to the output. (If you had used text for the Seed, Minecraft converts it into a number. This outputs the number.)" + newLine + + "- Changed the default 300 blocks to 380. The server now makes a 400x400 square block terrain instead of 320x320. Thus it is faster because there are less loops. To use the old way, use \"-i300\"" + newLine + + "- Added total Percentage done (technically, it displays the % done once the server finishes...)" + newLine + + "- Added debugging output vars of conf file (disabled - need to re-compile source to activate)" + newLine + + newLine + + "\t\t+ (the goal is to have MLG be configureable, so it can work on any version of the server, past or present.)" + newLine + + newLine + + "*** 1.4.5 (pre 1.5.0) ***" + newLine + + "- sorry! I shouldn't release untested code..." + newLine + + "*************************" + newLine + + newLine + + "1.4.4" + newLine + + "- Added ablilty to ignore [WARNING] and [SEVERE] errors with \"-w\"" + newLine + + newLine + + "1.4.3" + newLine + + "- Fixed \"-ps\",\"-printspawn\" as I had forgot I had broken it in 1.4.0 - due to config file change." + newLine + + newLine + + "1.4.2" + newLine + + "- No New Features" + newLine + + "- Changed non-verbose mode to display server progress on the same line, saving a lot of space." + newLine + + " - This couldn't wait for 1.5.0 ... I (Morlok8k) liked it too much." + newLine + + newLine + + "1.4.0" + newLine + + "- Future Proofing" + newLine + + "- Configurble Server Message reading. (If server updates and breaks MLG, you can add the new text!)" + newLine + + "- Updated config file, and auto updating from old format." + newLine + + "- Added % of spawn area to non-verbose output." + newLine + + "- Removed datetime stamps from server output in verbose mode" + newLine + + "- Other Misc fixes." + newLine + + newLine + + "1.3.0" + newLine + + "- Fixed Problems with Minecraft Beta 1.3 -- Morlok8k" + newLine + + newLine + + "-----------------------------------------------" + newLine + + newLine + + "Corrodias:" + newLine + + "1.2.0" + newLine + + "- land generation now centers on the spawn point instead of [0, 0]" + newLine + + "- the server is launched once before the spawn point is changed, to verify that it can run and to create a world if one doesn't exist" + newLine + + "- added -printspawn [-ps] switch to print the current spawn coordinates to the console" + newLine + + "- added -x and -y switches to override the X and Y offsets" + newLine + + "- added -v switch, does the same as -verbose" + newLine + + "- improved status message spacing to make things easier to read" + newLine + + "- improved time estimation algorithm: it now averages the last 3 launches" + newLine + + newLine + + "1.1.0" + newLine + + "- added MinecraftLandGenerator.conf file to hold the java command line and the server path" + newLine + + "- added -conf solo switch to generate a .conf file" + newLine + + "- added -verbose switch to output server output to the console (default is to ignore it)" + newLine + + "- added -i switch to allow customizing the block increment size (default is 300)" + newLine + + "- added instructions output in this version, i think" + newLine + + "- improved status message output to include current iteration and total iterations" + newLine + + newLine + + "1.0.0" + newLine + + "- initial release" + newLine + + newLine + + "-----------------------------------------------" + newLine + + newLine + + "Notes:" + newLine + + "Due to changes in server beta 1.6, it now generates the nether as well as the world at the same time." + newLine + + "However, Since beta 1.9 and Minecraft 1.0, the nether or the end is no longer generated." + + "I recommend using MCEDIT to relight the map after you generate it. This will take a long time, but should fix all those incorrectly dark spots in your level." + newLine + + newLine + + "-----------------------------------------------" + newLine + + newLine; + //@formatter:on + + Main.writeTxtFile(readmeFile, ReadMeText + showHelpSTR); + + } + + /** + * Displays or returns Help information + * + * @param SysOut + *
+ * Set TRUE to display info to System.out. (Returns null)
+ * Set FALSE to return info as String. + * @author Morlok8k + */ + public static String showHelp(boolean SysOut) { + String Str = null; + String NewLine = newLine; + if (SysOut) { + NewLine = NewLine + Main.MLG; + } + + String MLGFileNameShort = Main.MLGFileNameShort; + String MinecraftLandGeneratorConf = Main.MinecraftLandGeneratorConf; + String defaultReadmeFile = Main.defaultReadmeFile; + + //@formatter:off + Str = "Usage: java -jar " + MLGFileNameShort + " x z [serverpath] [switches]" + NewLine + + NewLine + + "Arguments:" + NewLine + + " x : X range to generate" + NewLine + + " z : Z range to generate" + NewLine + + " serverpath : the path to the directory in which the server runs (takes precedence over the config file setting)" + NewLine + + NewLine + + "Switches:" + NewLine + + " -verbose : causes the application to output the server's messages to the console" + NewLine + + " -v : same as -verbose" + NewLine + + " -w : Ignore [WARNING] and [SEVERE] messages." + NewLine + + " -alt : alternate server launch sequence" + NewLine + + " -a : same as -alt" + NewLine + + " -i# : override the iteration spawn offset increment (default 380) (example: -i100)" + NewLine + + " -x# : set the X offset to generate land around (example: -x0 or -x1000 or -x-500)" + NewLine + + " -z# : set the Z offset to generate land around (example: -z0 or -z1000 or -z-500)" + NewLine + + NewLine + + "Other options:" + NewLine + + " java -jar " + MLGFileNameShort + " -update" + NewLine + + " Checks for and downloads new versions of MLG online." + NewLine + + NewLine + + " java -jar " + MLGFileNameShort + " -printspawn" + NewLine + + " java -jar " + MLGFileNameShort + " -ps" + NewLine + + " Outputs the current world's spawn point coordinates." + NewLine + + NewLine + + " java -jar " + MLGFileNameShort + " -conf" + NewLine + + " java -jar " + MLGFileNameShort + " -conf download" + NewLine + + " Generates or downloads a "+ MinecraftLandGeneratorConf + " file." + NewLine + + NewLine + + " java -jar " + MLGFileNameShort + " -readme readme.txt" + NewLine + + " java -jar " + MLGFileNameShort + " -readme" + NewLine + + " Generates a readme file using supplied name or the default " + defaultReadmeFile + NewLine + + NewLine + + " java -jar " + MLGFileNameShort + " -downloadfile http://example.com/file.txt" + NewLine + + " Downloads whatever file from the internet you give it." + NewLine + + " java -jar " + MLGFileNameShort + " -downloadlist list.txt" + NewLine + + " list.txt (or any other file) contains a URL on each line which will be downloaded." + NewLine + + NewLine + + " java -jar " + MLGFileNameShort + " -version" + NewLine + + " java -jar " + MLGFileNameShort + " -help" + NewLine + + " java -jar " + MLGFileNameShort + " /?" + NewLine + + " Prints this message." + NewLine + + NewLine + + "When launched with the -conf switch, this application creates a " + MinecraftLandGeneratorConf + " file that contains configuration options." + NewLine + + "If this file does not exist or does not contain all required properties, the application will not run." + NewLine + + NewLine + + MinecraftLandGeneratorConf + " properties:" + NewLine + + " Java : The command line to use to launch the server" + NewLine + + " ServerPath : The path to the directory in which the server runs (can be overridden by the serverpath argument)" + NewLine + + " Done_Text : The output from the server that tells us that we are done" + NewLine + + " Preparing_Text : The output from the server that tells us the percentage" + NewLine + + "Preparing_Level : The output from the server that tells us the level it is working on" + NewLine + + " Level-0 : Name of Level 0: The Overworld" + NewLine + + " Level-1 : Name of Level 1: The Nether" + NewLine + + " Level-2 : Name of Level 2: The End" + NewLine + + " Level-3 : Name of Level 3: (Future Level)" + NewLine + + " Level-4 : Name of Level 4: (Future Level)" + NewLine + + " Level-5 : Name of Level 5: (Future Level)" + NewLine + + " Level-6 : Name of Level 6: (Future Level)" + NewLine + + " Level-7 : Name of Level 7: (Future Level)" + NewLine + + " Level-8 : Name of Level 8: (Future Level)" + NewLine + + " Level-9 : Name of Level 9: (Future Level)" + NewLine + + " WaitSave : Optional: Wait before saving." + NewLine; + //@formatter:on + + if (SysOut) { + Main.out(Str); + Main.out(""); + return null; + } else { + return Str; + } + + } +} diff --git a/src/org/w3c/bert_bos/UTF8URL/Unescape.java b/src/org/w3c/bert_bos/UTF8URL/Unescape.java new file mode 100644 index 0000000..02bc104 --- /dev/null +++ b/src/org/w3c/bert_bos/UTF8URL/Unescape.java @@ -0,0 +1,83 @@ +package org.w3c.bert_bos.UTF8URL; + +public class Unescape { + + /* Morlok8k: + * Just a note about this unescape method: + * I am quite amazed at this code. It is vastly superior to my own coding ability. + * I had to look up many things in it to see how it works, and I still don't quite follow it. + * (I have never worked with raw bytes in Java... Never needed to.) + * But it works and it works very well. I tip my hat at you Bert! + * + * I just needed to say this somewhere, even though very few people will ever read this. + */ + /** + * Created: 17 April 1997
+ * Author: Bert Bos <bert@w3.org>
+ *
+ * unescape: http://www.w3.org/International/unescape.java
+ *
+ * Copyright © 1997 World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University). All Rights Reserved. + * This work is distributed under the W3C® Software License [1] in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE.
+ *
+ * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + * + * @param s + * string of URL + * @return decoded string of URL + * @author Bert Bos + */ + + public static String unescape(final String s) { + StringBuffer sbuf = new StringBuffer(); + int l = s.length(); + int ch = -1; + int b, sumb = 0; + for (int i = 0, more = -1; i < l; i++) { + /* Get next byte b from URL segment s */ + switch (ch = s.charAt(i)) { + case '%': + ch = s.charAt(++i); + int hb = + (Character.isDigit((char) ch) ? ch - '0' : 10 + Character + .toLowerCase((char) ch) - 'a') & 0xF; + ch = s.charAt(++i); + int lb = + (Character.isDigit((char) ch) ? ch - '0' : 10 + Character + .toLowerCase((char) ch) - 'a') & 0xF; + b = (hb << 4) | lb; + break; + case '+': + b = ' '; + break; + default: + b = ch; + } + /* Decode byte b as UTF-8, sumb collects incomplete chars */ + if ((b & 0xc0) == 0x80) { // 10xxxxxx (continuation byte) + sumb = (sumb << 6) | (b & 0x3f); // Add 6 bits to sumb + if (--more == 0) sbuf.append((char) sumb); // Add char to sbuf + } else if ((b & 0x80) == 0x00) { // 0xxxxxxx (yields 7 bits) + sbuf.append((char) b); // Store in sbuf + } else if ((b & 0xe0) == 0xc0) { // 110xxxxx (yields 5 bits) + sumb = b & 0x1f; + more = 1; // Expect 1 more byte + } else if ((b & 0xf0) == 0xe0) { // 1110xxxx (yields 4 bits) + sumb = b & 0x0f; + more = 2; // Expect 2 more bytes + } else if ((b & 0xf8) == 0xf0) { // 11110xxx (yields 3 bits) + sumb = b & 0x07; + more = 3; // Expect 3 more bytes + } else if ((b & 0xfc) == 0xf8) { // 111110xx (yields 2 bits) + sumb = b & 0x03; + more = 4; // Expect 4 more bytes + } else /*if ((b & 0xfe) == 0xfc)*/{ // 1111110x (yields 1 bit) + sumb = b & 0x01; + more = 5; // Expect 5 more bytes + } + /* We don't test if the UTF-8 encoding is well-formed */ + } + return sbuf.toString(); + } +}