some untested 1.7.0 code. not ready yet, but most likely functional.

This commit is contained in:
Morlok8k 2012-07-03 03:36:35 -07:00
parent 9de8c2164a
commit 7580fe546b
6 changed files with 808 additions and 477 deletions

View File

@ -12,30 +12,24 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import morlok8k.minecraft.landgenerator.MLG_DownloadFile;
import morlok8k.minecraft.landgenerator.MLG_MD5;
import morlok8k.minecraft.landgenerator.MLG_Readme_and_HelpInfo;
import morlok8k.minecraft.landgenerator.MLG_StringArrayParse;
import morlok8k.minecraft.landgenerator.MLG_Update;
import morlok8k.minecraft.landgenerator.MLG_input_CLI;
import org.jnbt.CompoundTag;
@ -58,7 +52,7 @@ public class Main {
public static boolean testing = false; // display more output when debugging
public static final String PROG_NAME = "Minecraft Land Generator"; // Program Name
public static final String VERSION = "1.6.3"; // Version Number!
public static final String VERSION = "1.6.9 (1.7pre)"; // Version Number!
public static final String AUTHORS = "Corrodias, Morlok8k, pr0f1x"; // Authors
public static final String fileSeparator = System.getProperty("file.separator");
@ -80,6 +74,7 @@ public class Main {
//Private Vars:
private static int MinecraftServerChunkPlayerCache = 625;
private static int increment = (int) (Math.sqrt(MinecraftServerChunkPlayerCache) * 16) - 20; //private int increment = 380;
private static boolean incrementSwitch = false;
private static ProcessBuilder minecraft = null;
private static String javaLine = null;
@ -109,7 +104,7 @@ public class Main {
private int zRange = 0;
private Integer xOffset = null;
private Integer zOffset = null;
private static boolean verbose = false;
public static boolean verbose = false;
private boolean alternate = false;
private static boolean dontWait = false;
private static boolean waitSave = false;
@ -119,27 +114,27 @@ public class Main {
private static DateFormat dateFormat = new SimpleDateFormat( // Lets get a nice Date format for display
"EEEE, MMMM d, yyyy 'at' h:mm a zzzz", Locale.ENGLISH);
private static Date date = null; // date stuff
private static Long MLG_Last_Modified_Long = 0L;
public static Long MLG_Last_Modified_Long = 0L;
private static final Class<?> cls = Main.class;
private static String MLGFileName = null;
public static final Class<?> cls = Main.class;
public static String MLGFileName = null;
private static final String rsrcError = "rsrcERROR";
private static String buildIDFile = "MLG-BuildID";
private static boolean isCompiledAsJar = false;
private static String MLG_Current_Hash = null;
private static int inf_loop_protect_BuildID = 0;
private static boolean flag_downloadedBuildID = false;
public static final String rsrcError = "rsrcERROR";
public static String buildIDFile = "MLG-BuildID";
public static boolean isCompiledAsJar = false;
public static String MLG_Current_Hash = null;
public static int inf_loop_protect_BuildID = 0;
public static boolean flag_downloadedBuildID = false;
private static ArrayList<String> timeStamps = new ArrayList<String>();
public static ArrayList<String> timeStamps = new ArrayList<String>();
private static final String MLG_JarFile = "MinecraftLandGenerator.jar";
public static final String MLG_JarFile = "MinecraftLandGenerator.jar";
private static final String github_URL =
public static final String github_URL =
"https://raw.github.com/Morlok8k/MinecraftLandGenerator/master/bin/"; // just removing some redundancy
private static final String github_MLG_Conf_URL = github_URL + MinecraftLandGeneratorConf;
private static final String github_MLG_BuildID_URL = github_URL + buildIDFile;
private static final String github_MLG_jar_URL = github_URL + MLG_JarFile;
public static final String github_MLG_Conf_URL = github_URL + MinecraftLandGeneratorConf;
public static final String github_MLG_BuildID_URL = github_URL + buildIDFile;
public static final String github_MLG_jar_URL = github_URL + MLG_JarFile;
private static Boolean recheckFlag = false;
private static long startTime = 0L;
@ -186,10 +181,18 @@ public class Main {
}
boolean GUI = false;
boolean NOGUI = false;
String[] argsNOGUI = new String[args.length];
argsNOGUI = args;
argsNOGUI = MLG_StringArrayParse.Parse(argsNOGUI, "nogui"); //parse out "nogui"
if (!(args.equals(argsNOGUI))) { //do the freshly parsed args match the original?
args = argsNOGUI; //use the freshly parsed args for everything else now...
NOGUI = true;
}
//GUI Choosing code...
if (!java.awt.GraphicsEnvironment.isHeadless()
&& (args.length <= 0 || !args[0].equals("nogui"))) {
if (!java.awt.GraphicsEnvironment.isHeadless() || (!NOGUI)) {
GUI = true;
if (testing) {
outD("GUI: This is a graphical enviroment.");
@ -342,7 +345,6 @@ public class Main {
try {
origMD5 = fileMD5(config.toString());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader in = new BufferedReader(new FileReader(config));
@ -360,7 +362,6 @@ public class Main {
try {
recheckMD5 = fileMD5(config.toString());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
@ -465,6 +466,7 @@ public class Main {
} else if (nextSwitch.startsWith("-i")) {
increment = Integer.parseInt(args[i + 2].substring(2));
incrementSwitch = true;
out("Notice: Non-Default Increment: " + increment);
} else if (nextSwitch.startsWith("-w")) {
@ -585,6 +587,13 @@ public class Main {
Double blah;
double xLoops, zLoops;
//TODO: add code to check for user input for increment, and use that instead! (this should take priority)
//TODO: have main loop make an arraylist of spawnpoints
// read from a file if MLG has run before on this world. save to arraylist
// remove existing points from new list.
// run mlg on remaining list of spawn points.
// X
blah = ((double) xRange / (double) increment); //How many loops do we need?
xLoops = Math.ceil(blah); //round up to find out!
@ -623,6 +632,11 @@ public class Main {
// 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 (incrementSwitch) { //user input takes priority over any calculations we make!
incrementX = increment;
incrementZ = increment;
}
if (verbose) {
if (incrementX != increment) {
out("Optimized X increments from: " + increment + " to: " + incrementX);
@ -1001,6 +1015,7 @@ public class Main {
}
} else if (line.contains("server version") || line.contains("Converting map!")) { //TODO: add to .conf
outS(shortLine);
//TODO: if server version, save string to some variable, for use in arraylist save file.
}
if (line.contains(doneText)) { // now this is configurable!
@ -1138,7 +1153,7 @@ public class Main {
* @param dst
* @throws IOException
*/
private static void copyFile(File src, File dst) throws IOException {
public static void copyFile(File src, File dst) throws IOException {
InputStream copyIn = new FileInputStream(src);
OutputStream copyOut = new FileOutputStream(dst);
@ -1218,106 +1233,7 @@ public class Main {
* @author Morlok8k
*/
private static void buildID(boolean downloadOnly) {
// download BuildID from Github.
boolean fileSuccess = downloadFile(github_MLG_BuildID_URL, testing);
if (fileSuccess) {
out(buildIDFile + " file downloaded.");
flag_downloadedBuildID = true;
if (downloadOnly) { return; }
}
if (downloadOnly) {
err("Couldn't Download new " + buildIDFile);
return;
}
// If not available, create.
// After downloading, check to see if it matches hash.
if (MLGFileName == null) {
try {
MLGFileName = getClassLoader(cls);
} catch (Exception e) {
out("Error: Finding file failed");
e.printStackTrace();
}
if (MLGFileName.equals(rsrcError)) { return; }
}
if (MLG_Current_Hash == null) {
try {
MLG_Current_Hash = fileMD5(MLGFileName);
// out(hash + " " + MLGFileName);
} catch (Exception e) {
out("Error: MLG_MD5 from file failed");
e.printStackTrace();
}
}
Date time = new Date(new Long(0));
try {
time = getCompileTimeStamp(cls);
} catch (Exception e) {
out("Error: TimeStamp from file failed");
e.printStackTrace();
}
// out(d.toString());
boolean notNew = false;
String INFO = "";
if (isCompiledAsJar == false) {
INFO = " (Class File, Not .Jar)";
}
try {
String line;
BufferedReader inFile = new BufferedReader(new FileReader(buildIDFile));
BufferedWriter outFile = new BufferedWriter(new FileWriter(buildIDFile + ".temp"));
while ((line = inFile.readLine()) != null) {
if (line.contains(MLG_Current_Hash)) {
notNew = true;
if (testing) {
outD("NotNew");
}
}
outFile.write(line);
outFile.newLine();
}
if (notNew == false) {
outFile.write(MLG_Current_Hash + "=" + String.valueOf(time.getTime()) + "# MLG v"
+ VERSION + INFO);
outFile.newLine();
}
outFile.close();
inFile.close();
File fileDelete = new File(buildIDFile);
fileDelete.delete();
File fileRename = new File(buildIDFile + ".temp");
fileRename.renameTo(new File(buildIDFile));
} catch (FileNotFoundException ex) {
out("\"" + buildIDFile + "\" file not Found. Generating New \"" + buildIDFile
+ "\" File");
writeTxtFile(buildIDFile, MLG_Current_Hash + "=" + String.valueOf(time.getTime())
+ "#MLG v" + VERSION + INFO);
} catch (IOException ex) {
err("Could not create \"" + buildIDFile + "\".");
return;
}
MLG_Update.buildID(downloadOnly);
}
/**
@ -1326,164 +1242,8 @@ public class Main {
* @author Morlok8k
*
*/
private void readBuildID() {
if (inf_loop_protect_BuildID > 10) {
MLG_Last_Modified_Date = new Date(new Long(0)); //set the day to Jan 1, 1970 for failure
return;
}
inf_loop_protect_BuildID++; // this is to prevent an infinite loop (however unlikely)
if (MLGFileName == null) {
try {
MLGFileName = getClassLoader(cls);
} catch (Exception e) {
out("Error: Finding file failed");
e.printStackTrace();
}
if (MLGFileName.equals(rsrcError)) { return; }
}
MLGFileNameShort =
MLGFileName.substring(MLGFileName.lastIndexOf(fileSeparator) + 1,
MLGFileName.length());
if (testing) {
outD("Currently Running as file:" + MLGFileNameShort);
}
if (MLG_Current_Hash == null) {
try {
MLG_Current_Hash = fileMD5(MLGFileName);
// out(hash + " " + MLGFileName);
} catch (Exception e) {
out("Error: MLG_MD5 from file failed");
e.printStackTrace();
}
}
int tsCount = 0;
timeStamps.clear();
if (MLG_Last_Modified_Date == null) {
boolean foundLine = false;
try {
BufferedReader in = new BufferedReader(new FileReader(buildIDFile));
String line;
if (testing) {
outD("TimeStamps in buildIDFile:");
}
while ((line = in.readLine()) != null) {
int pos = line.indexOf('=');
int end = line.lastIndexOf('#'); // comments, ignored lines
if (end == -1) { // If we have no hash sign, then we read till the end of the line
end = line.length();
}
if (end <= (pos + 1)) { // If hash is before the '=', we may have an issue... it should be fine, cause we check for issues next, but lets make sure.
end = line.length();
pos = -1;
}
if (end == 0) { //hash is first char, meaning entire line is a comment
end = line.length();
pos = 0;
}
if (pos != -1) {
if (line.length() != 0) {
timeStamps.add(line.substring(pos + 1, end));
}
}
//timeStamps.add(line.substring(pos + 1, end));
if (testing) {
outD(timeStamps.get(tsCount));
}
tsCount++;
if (line.contains(MLG_Current_Hash)) {
// out("[DEBUG] Found!");
foundLine = true;
if (pos != -1) {
if (line.substring(0, pos).equals(MLG_Current_Hash)) {
MLG_Last_Modified_Long = new Long(line.substring(pos + 1, end));
MLG_Last_Modified_Date = new Date(MLG_Last_Modified_Long);
Long highestModTime = ZipGetModificationTime(MLGFileName);
long tCalc = MLG_Last_Modified_Long - highestModTime;
if (testing) {
outD("tCalc\tMLG_Last_Modified_Long\thighestModTime" + newLine
+ tCalc + "\t" + MLG_Last_Modified_Long + "\t"
+ highestModTime);
}
if (highestModTime == 0L) {
err("Archive Intergrity Check Failed: .zip/.jar file Issue.");
err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
} else {
if (tCalc < -15000L) {
//time is newer? (.zip file is newer than BuildID)
err("Archive Intergrity Check Failed: .zip file is newer than BuildID. Offset: "
+ (tCalc / 1000) + "sec.");
err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
}
if (tCalc < 15000L) {
//times are within 30 seconds (+/- 15 seconds) of each other. (typically 1-2 seconds, but left room for real-world error)
if (testing | flag_downloadedBuildID) {
out("Archive Intergrity Check Passed. Offset: "
+ (tCalc / 1000) + "sec.");
}
} else {
//times dont match. (.zip file is older than specified BuildID)
err("Archive Intergrity Check Failed: .zip file is older than BuildID. Offset: "
+ (tCalc / 1000) + "sec.");
err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
}
}
//return;
}
}
}
}
in.close();
if (foundLine == false) {
// out("[DEBUG] FoundLine False");
buildID(false);
readBuildID(); // yes I'm calling the function from itself. potential infinite loop? possibly. I haven't encountered it yet!
return;
}
} catch (Exception e) {
err("Cant Read " + buildIDFile + "!");
err(e.getLocalizedMessage());
err("");
// e.printStackTrace();
buildID(false);
readBuildID();
return;
}
}
private static void readBuildID() {
MLG_Update.readBuildID();
}
/**
@ -1492,117 +1252,9 @@ public class Main {
* @author Morlok8k
*
*/
private void updateMLG() {
private static void updateMLG() {
buildID(true); //get latest BuildID file.
MLG_Last_Modified_Date = null;
readBuildID();
Iterator<String> e = timeStamps.iterator();
String s;
int diff;
//boolean renameFailed = false;
while (e.hasNext()) {
s = e.next();
diff = MLG_Last_Modified_Date.compareTo(new Date(new Long(s)));
//out(diff);
if (diff < 0) { // if this is less than 0, there is a new version of MLG on the Internet!
out("There is a NEW VERSION Of " + PROG_NAME + " available online!");
try {
File fileRename = new File(MLG_JarFile);
fileRename.renameTo(new File(MLG_JarFile + ".old"));
} catch (Exception e1) {
out("Rename attempt #1 failed!");
e1.printStackTrace();
try {
copyFile(new File(MLG_JarFile), new File(MLG_JarFile + ".old"));
File fileDelete = new File(MLG_JarFile);
fileDelete.delete();
} catch (Exception e2) {
out("Rename attempt #2 failed!");
e2.printStackTrace();
//renameFailed = true;
return;
}
}
boolean fileSuccess = downloadFile(github_MLG_jar_URL, true);
if (fileSuccess) {
out(MLG_JarFile + " downloaded.");
return;
}
}
}
}
/**
* This gets the filename of a .jar (typically this one!)
*
* @author Morlok8k
*/
private static String getClassLoader(Class<?> classFile) throws IOException {
ClassLoader loader = classFile.getClassLoader();
String filename = classFile.getName().replace('.', '/') + ".class";
URL resource =
(loader != null) ? loader.getResource(filename) : ClassLoader
.getSystemResource(filename);
filename = URLDecoder.decode(resource.toString(), "UTF-8");
// out(filename);
// START Garbage removal:
int bang = filename.indexOf("!"); // remove everything after xxxx.jar
if (bang == -1) { // a real example:
bang = filename.length(); // jar:file:/home/morlok8k/test.jar!/me/Morlok8k/test/Main.class
}
int file = filename.indexOf("file:"); // removes junk from the beginning of the path
file = file + 5;
if (file == -1) {
file = 0;
}
if (filename.contains("rsrc:")) {
err("THIS WAS COMPILED USING \"org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader\"! ");
err("DO NOT PACKAGE YOUR .JAR'S WITH THIS CLASSLOADER CODE!");
err("(Your Libraries need to be extracted.)");
return rsrcError;
}
if (filename.contains(".jar")) {
isCompiledAsJar = true;
}
filename = filename.replace('/', File.separatorChar);
String returnString = filename.substring(file, bang);
// END Garbage removal
return returnString;
}
/**
* This gets the TimeStamp (last modified date) of a class file (typically this one!) <br>
* <br>
* Thanks to Roedy Green at <br>
* <a href="http://mindprod.com/jgloss/compiletimestamp.html">http://mindprod .com/jgloss/compiletimestamp.html</a>
*
* @author Morlok8k
*/
private static Date getCompileTimeStamp(Class<?> classFile) throws IOException {
ClassLoader loader = classFile.getClassLoader();
String filename = classFile.getName().replace('.', '/') + ".class";
// get the corresponding class file as a Resource.
URL resource =
(loader != null) ? loader.getResource(filename) : ClassLoader
.getSystemResource(filename);
URLConnection connection = resource.openConnection();
// Note, we are using Connection.getLastModified not File.lastModifed.
// This will then work both or members of jars or standalone class files.
// NOTE: NOT TRUE! IT READS THE JAR, NOT THE FILES INSIDE!
long time = connection.getLastModified();
return (time != 0L) ? new Date(time) : null;
MLG_Update.updateMLG();
}
/**
@ -1610,7 +1262,7 @@ public class Main {
*
* @author Morlok8k
*/
private static String fileMD5(String fileName) throws NoSuchAlgorithmException,
public static String fileMD5(String fileName) throws NoSuchAlgorithmException,
FileNotFoundException {
return MLG_MD5.fileMD5(fileName);
}
@ -1643,59 +1295,13 @@ public class Main {
* @param timeBuildID
* @author Morlok8k
*/
private static Long ZipGetModificationTime(String zipFile) {
Long highestModTime = 0L;
try {
ZipFile zipF = new ZipFile(zipFile);
/*
* Get list of zip entries using entries method of ZipFile class.
*/
Enumeration<? extends ZipEntry> e = zipF.entries();
if (testing) {
outD("File Name\t\tCRC\t\tModification Time\n---------------------------------\n");
}
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
Long modTime = entry.getTime();
if (entry.getName().toUpperCase().contains("MAIN.JAVA")) { //ignore highest timestamp for the source code, as that can be injected into the .jar file much later after compiling.
modTime = 0L;
}
if (highestModTime < modTime) {
highestModTime = modTime;
}
if (testing) {
String entryName = entry.getName();
Date modificationTime = new Date(modTime);
String CRC = Long.toHexString(entry.getCrc());
outD(entryName + "\t" + CRC + "\t" + modificationTime + "\t"
+ modTime.toString());
}
}
zipF.close();
return highestModTime;
} catch (IOException ioe) {
out("Error opening zip file" + ioe);
return 0L; //return Jan. 1, 1970 12:00 GMT for failures
}
public static Long ZipGetModificationTime(String zipFile) {
return MLG_Update.ZipGetModificationTime(zipFile);
}
/**
*
*/
private static void readConf() {
//TODO: element comment
//String errorMsg = "";
@ -1864,6 +1470,9 @@ public class Main {
}
/**
*
*/
private static void verifyWorld() {
//TODO: element comment
@ -1965,6 +1574,10 @@ public class Main {
}
/**
* @param file
* @param txt
*/
public static void writeTxtFile(String file, String txt) {
//TODO: element comment
@ -2078,31 +1691,6 @@ public class Main {
}
/*
private static void finishedImage() {
System.out.println(newLine + " .l0kkKMl lMKkk0l. " + newLine
+ ".;kMc ;KK; .,,lkkkkkkkl,,. ;KK, cMk,." + newLine
+ "KKxkc..lKK;.oKKxxl,;;;;lkkKKo.,KKl..ckkKK" + newLine
+ "Mx. ...;x0OOl'. .'lOOOx:... .xM" + newLine
+ "lKKk0l. ,KK; ,KK, .l0xKKl" + newLine
+ " .'',xOxOWl lMOxOx,''. " + newLine
+ " .,xWl lWx;. " + newLine
+ " lMl ,. ., lMl " + newLine
+ " ;XO';Odl:,.. .',:ldO;'OX; " + newLine
+ " ,KK,cxkkkc...ckxkx:,KK, " + newLine
+ " lMc .,,. .o. .,,. cMl " + newLine
+ " .lO;;' .lkl. ';;Ol. " + newLine
+ " .;;kMk. .kMk;;. " + newLine
+ " .lKKK0kl;;.......;,lk0KKKl. " + newLine
+ " .;llxOx;.'Ox;llxxldlxxll;xO'.;xOxll;. " + newLine
+ " ,KKcll. .l0KKl... ...lKK0l. .llcKK, " + newLine
+ " lMx'''..lXX;:X0:'. .':OX;,XXl..'''xMl " + newLine
+ " .lxXk. ,KM; .lkKKxkkKKkl. ,MK, .kXxl. " + newLine
+ " oKl;;kMk. .,,,,;. .kMk,,lKo " + newLine
+ " .0MMMMO' .OMMMMO. ");
}
*/
/**
* Returns the time in a readable format between two points of time given in Millis.
*
@ -2147,13 +1735,22 @@ public class Main {
seconds % 60);
if (!(verbose)) {
int end = took.indexOf(",");
if (end == -1) {
int commaFirst = took.indexOf(",");
int commaSecond = took.substring((commaFirst + 1), took.length()).indexOf(",");
int end = (commaFirst + 1 + commaSecond);
if (commaSecond == -1) {
end = commaFirst;
}
if (commaFirst == -1) {
end = took.length();
}
took = took.substring(0, end);
}
took.trim();
return (took);
}

View File

@ -0,0 +1,200 @@
package morlok8k.minecraft.landgenerator;
/**
* Coordinates are in the form of [X,Y,Z] or (X,Z)<br>
* <br>
* x-axis (longitude): the distance east (positive) or west (negative) of the origin point<br>
* z-axis (latitude): the distance south (positive) or north (negative) of the origin point<br>
* y-axis (elevation): how high or low (from 0 to 255 (previously 128), with 64 being sea level) <br>
* The origin point: When both X and Z are both zero. (elevation is irrelevant)<br>
*/
public class Coordinates {
//FYI: int's (Integer's) are good enough for Minecraft. They have a range of -2,147,483,648 to 2,147,483,647
// Minecraft starts failing around ± 12,550,820 and ends at either ± 30,000,000 or ± 32,000,000 (depending on the version).
// See: http://www.minecraftwiki.net/wiki/Far_Lands for more info.
public int X = 0;
public int Y = 0;
public int Z = 0;
/**
* @param x
* @param y
* @param z
*/
public Coordinates(int x, int y, int z) {
super();
X = x;
Y = y;
Z = z;
}
/**
* Someone created a new blank Coordinate! Lets set it to be [0,0,0].
*/
public Coordinates() {
clear();
}
/**
* @return the x
*/
public int getX() {
return X;
}
/**
* @return the y
*/
public int getY() {
return Y;
}
/**
* @return the z
*/
public int getZ() {
return Z;
}
/**
* @param x
* the x to set
*/
public void setX(int x) {
X = x;
}
/**
* @param y
* the y to set
*/
public void setY(int y) {
Y = y;
}
/**
* @param z
* the z to set
*/
public void setZ(int z) {
Z = z;
}
public void clear() {
X = 0;
Y = 0;
Z = 0;
}
public static Coordinates parseString(String StringOfCoords) {
//parse out string
StringOfCoords.trim();
int x = 0, y = 0, z = 0;
//TODO: add validity checks:
//TODO: add short version... (Y = 0)
int start = 0, end = 0, firstComma = 0, secComma = 0;
String sX = "", sY = "", sZ = "";
start = StringOfCoords.indexOf("[");
end = StringOfCoords.indexOf("]");
StringOfCoords = StringOfCoords.substring(start, end);
firstComma = StringOfCoords.indexOf(",");
secComma = StringOfCoords.lastIndexOf(",");
System.out.println(start + " " + end + " " + firstComma + " " + secComma);
sX = StringOfCoords.substring(start + 1, firstComma);
sY = StringOfCoords.substring(firstComma + 1, secComma);
sZ = StringOfCoords.substring(secComma + 1, end);
System.out.println(sX + " " + sY + " " + sZ);
x = Integer.parseInt(sX);
y = Integer.parseInt(sY);
z = Integer.parseInt(sZ);
return new Coordinates(x, y, z);
}
///////////////////////////////////////////////////////////////////////////////////////
// Java Language Specific Crap Below... Stuff *gotta* be there so Java won't cry... //
///////////////////////////////////////////////////////////////////////////////////////
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// I am overriding the inherited toString method.
// Because it doesn't know how to deal with my custom data.
// So instead of getting "blahblahblah.Coordinates@745f"
// (the location of the class and the hexstring of the hashcode)
// I return "[X,Y,Z]"
return ("[" + X + "," + Y + "," + Z + "]");
}
public String toString(boolean Short) {
if (Short) { // We are overloading toString with an additional option:
return ("(" + X + "," + Z + ")"); // Basically just an option to return just X and Z (formatted differently as well: "(X,Z)")
}
return toString(); // Idiot catch. default to: "[X,Y,Z]"
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
// I am overriding the inherited hashCode method.
// Because it doesn't know how to deal with my custom data.
// So instead of getting who knows what, we return valid data
final int prime = 31; // My hard coded prime number
int result = 1; // The hard coded number I start with
result = prime * result + X; // Add the X data
result = prime * result + Y; // Add the Y data
result = prime * result + Z; // Add the Z data
return result; //this result will consistently give the same result for the same data.
// [0,0,0] will always give 29791. [1,2,3] will always give 30817.
//yes, If I was lazy, I could just do a "return 0;" and it would still be technically valid.
//but if I'm going override the method, I might as well do it right...
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
// I am overriding the inherited equals method.
// Because it doesn't know how to deal with my custom data.
// So instead of always failing, it actually works!
// (by default it gets the memory addresses of each object.)
// An object must equal itself
if (this == obj) return true;
// No object equals null
if (obj == null) return false;
if (this == null) return false;
// Objects of different types are never equal
if (getClass() != obj.getClass()) return false;
// Cast to an Coordinates, then compare the data
Coordinates c = (Coordinates) obj;
if (X != c.X) return false;
if (Y != c.Y) return false;
if (Z != c.Z) return false;
return true; // If none of the above returned something, they must be equal!
}
}

View File

@ -0,0 +1,33 @@
/**
*
*/
package morlok8k.minecraft.landgenerator;
import java.util.ArrayList;
import corrodias.minecraft.landgenerator.Main;
/**
* @author morlok8k
*
*/
public class MLG_ArrayList {
public static ArrayList<Coordinates> arrayListRemove(ArrayList<Coordinates> list,
ArrayList<Coordinates> remove) {
boolean changed = false;
changed = list.removeAll(remove);
if (Main.verbose) {
System.out.println("ArrayList changed: " + changed);
}
return list;
}
//TODO: add read arraylist file
//TODO: add save arraylist file (save this file only after generation is complete)
}

View File

@ -62,6 +62,12 @@ public class MLG_Readme_and_HelpInfo {
+ newLine
+ "Version History:" + newLine
+ "Morlok8k:" + newLine
+ "1.7.0" + newLine
+ "- Major Code Optimization" + newLine
+ "- Drastically reduced the amount of time it takes for MLG to expand a world after it has already done so before!" + newLine
+ "- (To do this, I needed to rewrite the Main loop of the program, and add my own Coordinate object)" + newLine
+ "- Updated Time Output yet again." + newLine
+ "- Misc. Tweaks." + newLine
+ "1.6.3" + newLine
+ "- Minor Code Optimization" + newLine
+ "- Finely got on the ball and added the JNBT source and everything (as an internal .zip) to be completely faithful to his license" + newLine

View File

@ -18,7 +18,7 @@ public class MLG_StringArrayParse {
int ii = 0;
for (int i = 0; i < array.length; i++) {
workingArray[ii] = array[i]; // copy
if ((array[i].equals(ParseOut)) && (removed == false)) { // we only remove the first match!
if ((array[i].contains(ParseOut)) && (removed == false)) { // we only remove the first match!
workingArray[ii] = null; // we make sure this is set to null (if the last arg is the match it would otherwise be copied... granted it would later be removed... but whatever.)
ii = ii - 1; // we just simply move back one
removed = true; // set our flag

View File

@ -0,0 +1,495 @@
package morlok8k.minecraft.landgenerator;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import corrodias.minecraft.landgenerator.Main;
public class MLG_Update {
/**
* This is an "undocumented" function to create a BuildID file. It should only be used right after compiling a .jar file<br>
* The resulting BuildID file is uploaded to github, and also distributed with the program.<br>
* <b>THE FILE SHOULD ONLY BE MADE FROM SCRATCH AT THE TIME OF PUBLISHING!</b><br>
* (Otherwise, the purpose is defeated!)<br>
* <br>
* The problem is that when a .jar file is downloaded from the internet, it gets a new date stamp - the time that it was downloaded. Only the original copy that was compiled on the original
* computer will have the correct time stamp. (or possibly a copy from the original computer)<br>
* <br>
* This saves the hash and the timestamp (now known as the BuildID)
*
* @author Morlok8k
*/
public static void buildID(boolean downloadOnly) {
// download BuildID from Github.
boolean fileSuccess =
MLG_DownloadFile.downloadFile(Main.github_MLG_BuildID_URL, Main.testing);
if (fileSuccess) {
Main.out(Main.buildIDFile + " file downloaded.");
Main.flag_downloadedBuildID = true;
if (downloadOnly) { return; }
}
if (downloadOnly) {
Main.err("Couldn't Download new " + Main.buildIDFile);
return;
}
// If not available, create.
// After downloading, check to see if it matches hash.
if (Main.MLGFileName == null) {
try {
Main.MLGFileName = getClassLoader(Main.cls);
} catch (Exception e) {
Main.out("Error: Finding file failed");
e.printStackTrace();
}
if (Main.MLGFileName.equals(Main.rsrcError)) { return; }
}
if (Main.MLG_Current_Hash == null) {
try {
Main.MLG_Current_Hash = Main.fileMD5(Main.MLGFileName);
// out(hash + " " + MLGFileName);
} catch (Exception e) {
Main.out("Error: MLG_MD5 from file failed");
e.printStackTrace();
}
}
Date time = new Date(new Long(0));
try {
time = getCompileTimeStamp(Main.cls);
} catch (Exception e) {
Main.out("Error: TimeStamp from file failed");
e.printStackTrace();
}
// out(d.toString());
boolean notNew = false;
String INFO = "";
if (Main.isCompiledAsJar == false) {
INFO = " (Class File, Not .Jar)";
}
try {
String line;
BufferedReader inFile = new BufferedReader(new FileReader(Main.buildIDFile));
BufferedWriter outFile = new BufferedWriter(new FileWriter(Main.buildIDFile + ".temp"));
while ((line = inFile.readLine()) != null) {
if (line.contains(Main.MLG_Current_Hash)) {
notNew = true;
if (Main.testing) {
Main.outD("NotNew");
}
}
outFile.write(line);
outFile.newLine();
}
if (notNew == false) {
outFile.write(Main.MLG_Current_Hash + "=" + String.valueOf(time.getTime())
+ "# MLG v" + Main.VERSION + INFO);
outFile.newLine();
}
outFile.close();
inFile.close();
File fileDelete = new File(Main.buildIDFile);
fileDelete.delete();
File fileRename = new File(Main.buildIDFile + ".temp");
fileRename.renameTo(new File(Main.buildIDFile));
} catch (FileNotFoundException ex) {
Main.out("\"" + Main.buildIDFile + "\" file not Found. Generating New \""
+ Main.buildIDFile + "\" File");
Main.writeTxtFile(Main.buildIDFile,
Main.MLG_Current_Hash + "=" + String.valueOf(time.getTime()) + "#MLG v"
+ Main.VERSION + INFO);
} catch (IOException ex) {
Main.err("Could not create \"" + Main.buildIDFile + "\".");
return;
}
}
/**
* Gets the BuildID for MLG
*
* @author Morlok8k
*
*/
public static void readBuildID() {
if (Main.inf_loop_protect_BuildID > 10) {
Main.MLG_Last_Modified_Date = new Date(new Long(0)); //set the day to Jan 1, 1970 for failure
return;
}
Main.inf_loop_protect_BuildID++; // this is to prevent an infinite loop (however unlikely)
if (Main.MLGFileName == null) {
try {
Main.MLGFileName = getClassLoader(Main.cls);
} catch (Exception e) {
Main.out("Error: Finding file failed");
e.printStackTrace();
}
if (Main.MLGFileName.equals(Main.rsrcError)) { return; }
}
Main.MLGFileNameShort =
Main.MLGFileName.substring(Main.MLGFileName.lastIndexOf(Main.fileSeparator) + 1,
Main.MLGFileName.length());
if (Main.testing) {
Main.outD("Currently Running as file:" + Main.MLGFileNameShort);
}
if (Main.MLG_Current_Hash == null) {
try {
Main.MLG_Current_Hash = Main.fileMD5(Main.MLGFileName);
// out(hash + " " + MLGFileName);
} catch (Exception e) {
Main.out("Error: MLG_MD5 from file failed");
e.printStackTrace();
}
}
int tsCount = 0;
Main.timeStamps.clear();
if (Main.MLG_Last_Modified_Date == null) {
boolean foundLine = false;
try {
BufferedReader in = new BufferedReader(new FileReader(Main.buildIDFile));
String line;
if (Main.testing) {
Main.outD("TimeStamps in buildIDFile:");
}
while ((line = in.readLine()) != null) {
int pos = line.indexOf('=');
int end = line.lastIndexOf('#'); // comments, ignored lines
if (end == -1) { // If we have no hash sign, then we read till the end of the line
end = line.length();
}
if (end <= (pos + 1)) { // If hash is before the '=', we may have an issue... it should be fine, cause we check for issues next, but lets make sure.
end = line.length();
pos = -1;
}
if (end == 0) { //hash is first char, meaning entire line is a comment
end = line.length();
pos = 0;
}
if (pos != -1) {
if (line.length() != 0) {
Main.timeStamps.add(line.substring(pos + 1, end));
}
}
//timeStamps.add(line.substring(pos + 1, end));
if (Main.testing) {
Main.outD(Main.timeStamps.get(tsCount));
}
tsCount++;
if (line.contains(Main.MLG_Current_Hash)) {
// out("[DEBUG] Found!");
foundLine = true;
if (pos != -1) {
if (line.substring(0, pos).equals(Main.MLG_Current_Hash)) {
Main.MLG_Last_Modified_Long =
new Long(line.substring(pos + 1, end));
Main.MLG_Last_Modified_Date = new Date(Main.MLG_Last_Modified_Long);
Long highestModTime = Main.ZipGetModificationTime(Main.MLGFileName);
long tCalc = Main.MLG_Last_Modified_Long - highestModTime;
if (Main.testing) {
Main.outD("tCalc\tMLG_Last_Modified_Long\thighestModTime"
+ Main.newLine + tCalc + "\t"
+ Main.MLG_Last_Modified_Long + "\t" + highestModTime);
}
if (highestModTime == 0L) {
Main.err("Archive Intergrity Check Failed: .zip/.jar file Issue.");
Main.err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
} else {
if (tCalc < -15000L) {
//time is newer? (.zip file is newer than BuildID)
Main.err("Archive Intergrity Check Failed: .zip file is newer than BuildID. Offset: "
+ (tCalc / 1000) + "sec.");
Main.err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
}
if (tCalc < 15000L) {
//times are within 30 seconds (+/- 15 seconds) of each other. (typically 1-2 seconds, but left room for real-world error)
if (Main.testing | Main.flag_downloadedBuildID) {
Main.out("Archive Intergrity Check Passed. Offset: "
+ (tCalc / 1000) + "sec.");
}
} else {
//times dont match. (.zip file is older than specified BuildID)
Main.err("Archive Intergrity Check Failed: .zip file is older than BuildID. Offset: "
+ (tCalc / 1000) + "sec.");
Main.err("Archive Intergrity Check Failed: (MLG will still run. Just note that this may not be an official version.)");
}
}
//return;
}
}
}
}
in.close();
if (foundLine == false) {
// out("[DEBUG] FoundLine False");
buildID(false);
readBuildID(); // yes I'm calling the function from itself. potential infinite loop? possibly. I haven't encountered it yet!
return;
}
} catch (Exception e) {
Main.err("Cant Read " + Main.buildIDFile + "!");
Main.err(e.getLocalizedMessage());
Main.err("");
// e.printStackTrace();
buildID(false);
readBuildID();
return;
}
}
}
/**
* Updates MLG to the Latest Version
*
* @author Morlok8k
*
*/
public static void updateMLG() {
buildID(true); //get latest BuildID file.
Main.MLG_Last_Modified_Date = null;
readBuildID();
Iterator<String> e = Main.timeStamps.iterator();
String s;
int diff;
//boolean renameFailed = false;
while (e.hasNext()) {
s = e.next();
diff = Main.MLG_Last_Modified_Date.compareTo(new Date(new Long(s)));
//out(diff);
if (diff < 0) { // if this is less than 0, there is a new version of MLG on the Internet!
Main.out("There is a NEW VERSION Of " + Main.PROG_NAME + " available online!");
try {
File fileRename = new File(Main.MLG_JarFile);
fileRename.renameTo(new File(Main.MLG_JarFile + ".old"));
} catch (Exception e1) {
Main.out("Rename attempt #1 failed!");
e1.printStackTrace();
try {
Main.copyFile(new File(Main.MLG_JarFile), new File(Main.MLG_JarFile
+ ".old"));
File fileDelete = new File(Main.MLG_JarFile);
fileDelete.delete();
} catch (Exception e2) {
Main.out("Rename attempt #2 failed!");
e2.printStackTrace();
//renameFailed = true;
return;
}
}
boolean fileSuccess = MLG_DownloadFile.downloadFile(Main.github_MLG_jar_URL, true);
if (fileSuccess) {
Main.out(Main.MLG_JarFile + " downloaded.");
return;
}
}
}
}
/**
* This gets the filename of a .jar (typically this one!)
*
* @author Morlok8k
*/
public static String getClassLoader(Class<?> classFile) throws IOException {
ClassLoader loader = classFile.getClassLoader();
String filename = classFile.getName().replace('.', '/') + ".class";
URL resource =
(loader != null) ? loader.getResource(filename) : ClassLoader
.getSystemResource(filename);
filename = URLDecoder.decode(resource.toString(), "UTF-8");
// out(filename);
// START Garbage removal:
int bang = filename.indexOf("!"); // remove everything after xxxx.jar
if (bang == -1) { // a real example:
bang = filename.length(); // jar:file:/home/morlok8k/test.jar!/me/Morlok8k/test/Main.class
}
int file = filename.indexOf("file:"); // removes junk from the beginning of the path
file = file + 5;
if (file == -1) {
file = 0;
}
if (filename.contains("rsrc:")) {
Main.err("THIS WAS COMPILED USING \"org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader\"! ");
Main.err("DO NOT PACKAGE YOUR .JAR'S WITH THIS CLASSLOADER CODE!");
Main.err("(Your Libraries need to be extracted.)");
return Main.rsrcError;
}
if (filename.contains(".jar")) {
Main.isCompiledAsJar = true;
}
filename = filename.replace('/', File.separatorChar);
String returnString = filename.substring(file, bang);
// END Garbage removal
return returnString;
}
/**
* This gets the TimeStamp (last modified date) of a class file (typically this one!) <br>
* <br>
* Thanks to Roedy Green at <br>
* <a href="http://mindprod.com/jgloss/compiletimestamp.html">http://mindprod .com/jgloss/compiletimestamp.html</a>
*
* @author Morlok8k
*/
public static Date getCompileTimeStamp(Class<?> classFile) throws IOException {
ClassLoader loader = classFile.getClassLoader();
String filename = classFile.getName().replace('.', '/') + ".class";
// get the corresponding class file as a Resource.
URL resource =
(loader != null) ? loader.getResource(filename) : ClassLoader
.getSystemResource(filename);
URLConnection connection = resource.openConnection();
// Note, we are using Connection.getLastModified not File.lastModifed.
// This will then work both or members of jars or standalone class files.
// NOTE: NOT TRUE! IT READS THE JAR, NOT THE FILES INSIDE!
long time = connection.getLastModified();
return (time != 0L) ? new Date(time) : null;
}
/**
* <b>.zip file Get Modification Time</b><br>
*
* Takes a string of a path to a .zip file (or .jar), and and returns a Long of the latest "Last Time Modified". <br>
* <br>
*
* Thanks to the following:<br>
* <a href="http://www.java-examples.com/get-modification-time-zip-entry-example">http://www.java-examples.com/get-modification-time-zip-entry-example</a><br>
* <a href="http://www.java-examples.com/get-crc-32-checksum-zip-entry-example">http://www.java-examples.com/get-crc-32-checksum-zip-entry-example</a>
*
* @param zipFile
* @param timeBuildID
* @author Morlok8k
*/
public static Long ZipGetModificationTime(String zipFile) {
Long highestModTime = 0L;
try {
ZipFile zipF = new ZipFile(zipFile);
/*
* Get list of zip entries using entries method of ZipFile class.
*/
Enumeration<? extends ZipEntry> e = zipF.entries();
if (Main.testing) {
Main.outD("File Name\t\tCRC\t\tModification Time\n---------------------------------\n");
}
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
Long modTime = entry.getTime();
if (!(entry.getName().toUpperCase().contains(".CLASS"))) { //ignore highest timestamp for non .class files, as they can be injected into the .jar file much later after compiling.
modTime = 0L;
}
if (highestModTime < modTime) {
highestModTime = modTime;
}
if (Main.testing) {
String entryName = entry.getName();
Date modificationTime = new Date(modTime);
String CRC = Long.toHexString(entry.getCrc());
Main.outD(entryName + "\t" + CRC + "\t" + modificationTime + "\t"
+ modTime.toString());
}
}
zipF.close();
return highestModTime;
} catch (IOException ioe) {
Main.out("Error opening zip file" + ioe);
return 0L; //return Jan. 1, 1970 12:00 GMT for failures
}
}
}