Package morlok8k.MinecraftLandGenerator

Source Code of morlok8k.MinecraftLandGenerator.Main

/*
#######################################################################
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE              #
#                    Version 2, December 2004                         #
#                                                                     #
# Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>                    #
#                                                                     #
# Everyone is permitted to copy and distribute verbatim or modified   #
# copies of this license document, and changing it is allowed as long #
# as the name is changed.                                             #
#                                                                     #
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE              #
#   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION   #
#                                                                     #
#  0. You just DO WHAT THE FUCK YOU WANT TO.                          #
#                                                                     #
#######################################################################
*/

/*
* The Computer Programmer's Lament:
* Program complexity grows until it exceeds the capability of the programmer who must maintain it.
*/

package morlok8k.MinecraftLandGenerator;

import java.awt.EventQueue;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import morlok8k.MinecraftLandGenerator.GUI.MLG_GUI;

/**
*
* @author Corrodias, Morlok8k, pr0f1x
*
*/
public class Main {

  //////////////////////////////////////////////////////////
  // REMINDER: Because I always forget/mix up languages:  //
  // "static" in java means "global" to this class    //
  // "final" means "constant"                //
  // public/private shows/hides between classes      //
  //////////////////////////////////////////////////////////

  /**
   * @param args
   *            the command line arguments
   */
  public static void main(String[] args) {
    var.startTime = System.currentTimeMillis();

    var.originalArgs = args;  // we may potentially remove some args later, but we keep a record of the original for the log file.

    // This is really just here for debugging...
    // I plan on adding more asserts later, but for now, this will do.
    // to enable this, run:
    // java -enableassertions -jar MinecraftLandGenerator.jar
    assert var.assertsEnabled = true// Intentional side-effect!!!  (This may cause a Warning, which is safe to ignore: "Possible accidental assignment in place of a comparison. A condition expression should not be reduced to an assignment")
    if (var.assertsEnabled) {
      Out.outD("assertsEnabled: " + var.assertsEnabled);
      var.verbose = true;
      Out.outD("Verbose mode forced!");
      var.testing = true;
      Out.outD("Debug mode forced!");
      var.dontWait = true;
      Out.outD("-nowait mode forced!");
      Out.outD("");
    }

    boolean GUI = false;      // GUI needs to be true to run in graphical mode
    boolean NOGUI = false;      // NOGUI is a flag that finds reasons to not use a graphical mode.

    if (args.length != 0) {      // if args are present, then we assume we want NOGUI
      NOGUI = true;        // if no args are present, we will attempt GUI
    }

    String[] argsNOGUI = new String[args.length];
    argsNOGUI = args;
    argsNOGUI = 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;
    }

    //MLG_GUI Choosing code...
    if ((!NOGUI) && (!java.awt.GraphicsEnvironment.isHeadless())) {
      GUI = true;
      if (var.testing) {
        Out.outD("MLG_GUI: This is a graphical enviroment.");
      }

      //////
      GUI = false;        // forcing GUI to be false for now, because I don't have the MLG_GUI code ready yet!
      //////

    } else {
      GUI = false;        // No GUI for us today...
      if (var.testing) {
        Out.outD("MLG_GUI: Command Line Only!");
      }
    }

    if (GUI) {  //GUI
      // Launch MLG_GUI

      EventQueue.invokeLater(new Runnable() {

        @SuppressWarnings("static-access")
        @Override
        public void run() {

          try {
            final MLG_GUI window = new MLG_GUI();
            window.frmMLG_GUI.setVisible(true);
          } catch (final Exception e) {
            e.printStackTrace();
          }
        }
      });

    } else //No GUI
      // Finally, Lets Start MLG!

      var.UsingGUI = false;
      var.args = args;
      Main.runCLI();
    }

  }

  /**
   * Start MinecraftLandGenerator (Command Line Interface)
   *
   * @author Corrodias, Morlok8k
   * @param args
   *
   */
  private static void runCLI() {

    // Basic Program Initialization
    Startup.initialStart();
    boolean quit = false;
    quit = Startup.programArguments();
    if (quit) { return; }
    quit = Startup.confFile();
    if (quit) { return; }

    WorldVerify.verifyWorld();

    {
      final File backupLevel =
          new File(var.worldPath + var.fileSeparator + "level_backup.dat");
      if (backupLevel.exists()) {
        //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!");
        //Time.waitTenSec(false);

        Out.err("There is a level_backup.dat file left over from a previous attempt that failed.");
        Out.out("Resuming...");

        //use resume data
        final File serverLevel = new File(var.worldPath + var.fileSeparator + "level.dat");
        try {
          Misc.copyFile(backupLevel, serverLevel);
        } catch (final IOException e) {
          e.printStackTrace();
        }
        backupLevel.delete();

        //return;

        FileRead.readArrayListCoordLog(var.worldPath + var.fileSeparator + var.logFile);    // we read the .log just for any resume data, if any.

        System.gc();    //run the garbage collector - hopefully free up some memory!

        var.xRange = var.resumeX;
        var.zRange = var.resumeZ;

      }
    }

    // =====================================================================
    //                              PROCESSING
    // =====================================================================

    Out.out("Processing world \"" + var.worldPath + "\", in " + var.increment
        + " block increments, with: " + var.javaLine);
    // out( MLG + "Processing \"" + worldName + "\"...");

    Out.out("");

    // prepare our two ProcessBuilders
    // minecraft = new ProcessBuilder(javaLine, "-Xms1024m", "-Xmx1024m", "-jar", jarFile, "nogui");
    var.minecraft = new ProcessBuilder(var.javaLine.split("\\s")); // is this always going to work? i don't know.  (most likely yes)
    var.minecraft.directory(new File(var.serverPath));
    var.minecraft.redirectErrorStream(true);

    try {
      Out.out("Launching server once to make sure there is a world.");

      final long generationStartTimeTracking = System.currentTimeMillis();    //Start of time remaining calculations.

      final boolean serverLaunch = Server.runMinecraft();

      if (!(serverLaunch)) {
        System.exit(1);        // we got a warning or severe error
      }

      if ((var.xRange == 0) & (var.zRange == 0)) {  //If the server is launched with an X and a Z of zero, then we just shutdown MLG after the initial launch.
        return;
      }

      FileWrite.AppendTxtFile(var.worldPath + var.fileSeparator + var.logFile,
          "# " + var.PROG_NAME + " " + var.VERSION + " - " + SelfAware.JVMinfo()
              + var.newLine + "# " + var.MC_Server_Version + var.newLine
              + "# Started: " + var.dateFormat.format(generationStartTimeTracking)
              + var.newLine + "##Size: X" + var.xRange + "Z" + var.zRange
              + var.newLine);

      Out.out("");

      final File serverLevel = new File(var.worldPath + var.fileSeparator + "level.dat");
      final File backupLevel =
          new File(var.worldPath + var.fileSeparator + "level_backup.dat");

      Out.out("Backing up level.dat to level_backup.dat.");
      Misc.copyFile(serverLevel, backupLevel);
      Out.out("");

      final Coordinates spawn = SpawnPoint.getSpawn(serverLevel);
      Out.out("Spawn point detected: [X,Y,Z] " + spawn);

      FileWrite.AppendTxtFile(var.worldPath + var.fileSeparator + var.logFile, "# Seed: "
          + var.randomSeed + var.newLine + "# Spawn: " + spawn.toString() + var.newLine);

      boolean overridden = false;
      if (var.xOffset == null) {
        var.xOffset = spawn.getX();
      } else {
        overridden = true;
      }
      if (var.zOffset == null) {
        var.zOffset = spawn.getZ();
      } else {
        overridden = true;
      }

      if (var.useChunks) {    // use Chunks or Regions
        var.xRange = (int) (Math.ceil(((double) var.xRange) / ((double) 16))) * 16;      //say xRange was entered as 1000.  this changes it to be 1008, a multiple of 16. (the size of a chunk)
        var.zRange = (int) (Math.ceil(((double) var.zRange) / ((double) 16))) * 16;      //say zRange was entered as 2000.  there is no change, as it already is a multiple of 16.
        var.xOffset = (int) (Math.ceil(((double) var.xOffset) / ((double) 16))) * 16;
        var.zOffset = (int) (Math.ceil(((double) var.zOffset) / ((double) 16))) * 16;
      } else {
        var.xRange = (int) (Math.ceil(((double) var.xRange) / ((double) 512))) * 512;      //say xRange was entered as 1000.  this changes it to be 1024, a multiple of 512. (the size of a region)
        var.zRange = (int) (Math.ceil(((double) var.zRange) / ((double) 512))) * 512;      //say zRange was entered as 2048.  there is no change, as it already is a multiple of 512.
        var.xOffset = (int) (Math.ceil(((double) var.xOffset) / ((double) 512))) * 512;
        var.zOffset = (int) (Math.ceil(((double) var.zOffset) / ((double) 512))) * 512;
      }

      if (overridden) {
        Out.out("Centering land generation on [" + var.xOffset + ", " + var.zOffset
            + "] due to switches.");
      }

      Out.out("");

      double xLoops, zLoops;
      int curXloops = 0;
      int curZloops = 0;
      int xRangeAdj = 0;
      int zRangeAdj = 0;

      // 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
      xLoops = ((double) var.xRange / (double) var.increment);    //How many loops do we need?
      xLoops = Math.ceil(xLoops);                //round up to find out!
      xRangeAdj = (int) (xLoops * var.increment);
      xLoops = xLoops + 1;

      // Z
      zLoops = ((double) var.zRange / (double) var.increment);    //How many loops do we need?
      zLoops = Math.ceil(zLoops);                //round up to find out!
      zRangeAdj = (int) (zLoops * var.increment);
      zLoops = zLoops + 1;

      Out.out("Calculating Spawn Points...");

      // Perfect Squares Code:

      int totalIterations = (int) (xLoops * zLoops);
      int currentIteration = 0;

      long differenceTime = System.currentTimeMillis();

      Long timeTracking = 0L;

      final ArrayList<Coordinates> launchList = new ArrayList<Coordinates>(totalIterations);

      for (int currentX = 0; currentX <= (xRangeAdj / 2); currentX += var.increment) {
        curXloops++;
        boolean eastEdgeReached = false;

        if (curXloops == 1) {
          currentX = (((0 - var.xRange) / 2) + (var.incrementFull / 2));    // West Edge of map

        } else if (currentX >= ((xRangeAdj / 2) - (var.increment / 2))) {
          currentX = ((var.xRange / 2) - (var.incrementFull / 2));      // East Edge of map
          eastEdgeReached = true;
        }

        for (int currentZ = 0; currentZ <= (zRangeAdj / 2); currentZ += var.increment) {
          currentIteration++;

          curZloops++;
          boolean southEdgeReached = false;
          if (curZloops == 1) {
            currentZ = (((0 - var.zRange) / 2) + (var.incrementFull / 2))// North Edge of map
          } else if (currentZ >= ((zRangeAdj / 2) - (var.increment / 2))) {
            currentZ = ((var.zRange / 2) - (var.incrementFull / 2));    // South Edge of map
            southEdgeReached = true;
          }

          {
            // add Coordinates to arraylist here
            final Coordinates tempCoords =
                new Coordinates(currentX + var.xOffset, 64, currentZ + var.zOffset);
            launchList.add(tempCoords);

            if (var.testing) {
              System.out.println(tempCoords);
            }
          }

          if (curZloops == 1) {      // We are at the North edge.  We have special code for the North edge, so we need to change currentZ to be normal again.
            currentZ =
                (int) ((Math.ceil((((0 - zRangeAdj) / 2) / var.increment))) * var.increment);
          }
          if (southEdgeReached) {
            currentZ = zRangeAdj;    // We reached the South edge, so we make sure that we exit the "for loop", bypassing the "1152 bug"
          }

        }
        curZloops = 0;
        if (curXloops == 1) {      // We are at the West edge.  We have special code for the West edge, so we need to change currentX to be normal again.
          currentX =
              (int) ((Math.ceil((((0 - xRangeAdj) / 2) / var.increment))) * var.increment);
        }
        if (eastEdgeReached) {
          currentX = xRangeAdj;    // We reached the East edge, so we make sure that we exit the "for loop", bypassing the "1152 bug"
        }

      }

      //get existing list, and remove this list from launchList
      final ArrayList<Coordinates> removeList =
          FileRead.readArrayListCoordLog(var.worldPath + var.fileSeparator + var.logFile);

      if (!(removeList.isEmpty())) {
        Arraylist.arrayListRemove(launchList, removeList);
      }

      removeList.clear();    // we are done with this now.

      System.gc();    //run the garbage collector - hopefully free up some memory!

      currentIteration = 0;
      totalIterations = launchList.size();
      Coordinates xyz = null;
      final Iterator<Coordinates> coordArrayIterator = launchList.iterator();
      while (coordArrayIterator.hasNext()) {
        currentIteration++;
        xyz = coordArrayIterator.next();

        //////// Start server launch code

        String percentDone =
            Double.toString((((double) currentIteration - 1) / totalIterations) * 100);
        final int percentIndex =
            ((percentDone.indexOf(".") + 3) > percentDone.length()) ? percentDone
                .length() : (percentDone.indexOf(".") + 3);    //fix index on numbers like 12.3
        percentDone =
            percentDone.substring(0,
                (percentDone.indexOf(".") == -1 ? percentDone.length()
                    : percentIndex));      //Trim output, unless whole number

        Out.out("Setting spawn to [X,Y,Z]: " + xyz + " (" + currentIteration + " of "
            + totalIterations + ") " + percentDone + "% Done"); // Time Remaining estimate

        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.out("Estimated time remaining: " + Time.displayTime(differenceTime));            // I've noticed it gets pretty accurate after about 8 launches!

        // Set the spawn point
        SpawnPoint.setSpawn(serverLevel, xyz);

        // Launch the server
        boolean serverSuccess = false;

        serverSuccess = Server.runMinecraft();
        Out.out("");

        //////// End server launch code

        if (serverSuccess) {
          // Write the current Coordinates to log file!
          FileWrite.AppendTxtFile(var.worldPath + var.fileSeparator + var.logFile,
              xyz.toString() + var.newLine);
        } else {
          System.exit(1);        // we got a warning or severe error
        }

      }

      if (currentIteration == 0) {
        Out.out("Nothing to generate!");
      } else {
        Out.out("Finished generating chunks.");
      }

      Misc.copyFile(backupLevel, serverLevel);
      backupLevel.delete();
      Out.out("Restored original level.dat.");

      Out.out("Generation complete in: "
          + Time.displayTime(var.startTime, System.currentTimeMillis()));
      Time.waitTenSec(false);

      //TODO: add if's

      if (var.webLaunch) {    //if webLaunch is already false, don't check for these things
        if (java.awt.GraphicsEnvironment.isHeadless()) {
          var.webLaunch = false;          //headless enviroment - cant bring up webpage!
        }
        final File web1 = new File("web");
        final File web2 = new File("web.txt");    //user has put in the magical file to not launch the webpage
        final File web3 = new File("web.txt.txt");
        if (web2.exists() || (web1.exists() || web3.exists())) {  //check for "web.txt", if not found, check for "web", and if still not found, check for "web.txt.txt"
          var.webLaunch = false;
        }
      }

      if (var.webLaunch && java.awt.Desktop.isDesktopSupported()) {
        final URI splashPage = URI.create("http://adf.ly/520855/splashbanner");
        try {
          java.awt.Desktop.getDesktop().browse(splashPage);
        } catch (final IOException e) {
          Out.err("Error displaying webpage... " + e.getLocalizedMessage());
        }
      } else {
        Out.out("Please Visit: http://adf.ly/520855/mlg");
        Out.out("Or: " + var.WEBSITE);
        Out.out("Thanks!");
      }

    } catch (final IOException ex) {
      Logger.getLogger(Main.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
    }
  }
}
TOP

Related Classes of morlok8k.MinecraftLandGenerator.Main

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.