diff --git a/.gitignore b/.gitignore
index 32858aa..70069c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,7 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+
+/bin/
+.classpath
+*.classpath
diff --git a/.project b/.project
new file mode 100644
index 0000000..6d94092
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ iieLoadSaveEntireWorld
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3a21537
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/src/iieLoadSaveEntireWorld/ChunkLoaderAPI.java b/src/iieLoadSaveEntireWorld/ChunkLoaderAPI.java
new file mode 100644
index 0000000..0a0fd58
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/ChunkLoaderAPI.java
@@ -0,0 +1,31 @@
+package iieLoadSaveEntireWorld;
+
+import org.bukkit.Location;
+
+public class ChunkLoaderAPI {
+ /**This method loads a chunk if the chunk isn't loaded already.
+ * @param locationToLoad
+ * @return True if chunk was already loaded, False if chunk wasn't already loaded
+ */
+ public static boolean loadChunk(Location locationToLoad){
+ if(!(locationToLoad.getBlock().getChunk().isLoaded())){
+ locationToLoad.getBlock().getChunk().load();
+ return true;
+ }
+ return false;
+ }
+
+
+ /**This method loads a chunk if the chunk isn't loaded already.
+ * @param locationToLoad
+ * @return True if chunk was already unloaded, False if chunk wasn't already unloaded
+ */
+ public static boolean unloadChunk(Location locationToUnload){
+ if (locationToUnload.getBlock().getChunk().isLoaded()){
+ locationToUnload.getBlock().getChunk().unload();
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/iieLoadSaveEntireWorld/ConfigProcess.java b/src/iieLoadSaveEntireWorld/ConfigProcess.java
new file mode 100644
index 0000000..104c2f1
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/ConfigProcess.java
@@ -0,0 +1,58 @@
+package iieLoadSaveEntireWorld;
+
+import org.bukkit.configuration.file.FileConfiguration;
+
+public class ConfigProcess implements Runnable {
+
+ //STATIC
+ private static final Main plugin = new Main();
+ private static final FileConfiguration config = plugin.getConfig();
+
+ static final boolean isNew(String name)
+ {
+ return !config.contains(name);
+ }
+ static final WorldObject getUnfinished(String name)
+ {
+ return new WorldObject
+ (
+ config.getInt(name + ".width"),
+ new int[]
+ {
+ config.getInt(name + ".currentRegion.x"),
+ config.getInt(name + ".currentRegion.z")
+ },
+ new int[]
+ {
+ config.getInt(name + ".lowerleft.x"),
+ config.getInt(name + ".lowerleft.z")
+ },
+ config.getInt(name + ".n"),
+ config.getInt(name + ".c"),
+ config.getInt(name + ".D"),
+ config.getInt(name + ".d"),
+ config.getInt(name + ".B") == 1
+ );
+ }
+
+
+ //INSTANCE
+ private final String name = TaskManager.loadProcess.worldname;
+ public final void run()
+ {
+ config.set(".currentRegion.x", TaskManager.loadProcess.currentRegion[0]);
+ config.set(".currentRegion.z", TaskManager.loadProcess.currentRegion[1]);
+ config.set(".n", TaskManager.loadProcess.n);
+ config.set(".c", TaskManager.loadProcess.c);
+ config.set(".D", TaskManager.loadProcess.D);
+ config.set(".d", TaskManager.loadProcess.d);
+ config.set(".B", TaskManager.loadProcess.B ? 1 : 0);
+ plugin.saveConfig();
+ }
+ final void finish()
+ {
+ config.set("finished", name);
+ config.set(name, null);
+ plugin.saveConfig();
+ }
+}
diff --git a/src/iieLoadSaveEntireWorld/LoadProcess.java b/src/iieLoadSaveEntireWorld/LoadProcess.java
new file mode 100644
index 0000000..c87ab31
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/LoadProcess.java
@@ -0,0 +1,170 @@
+package iieLoadSaveEntireWorld;
+
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+
+public class LoadProcess implements Runnable
+{
+ //=================================INIT=================================
+
+ final World world;
+ final String worldname;
+ final int totalRegions;
+ int[] currentRegion;
+
+
+ LoadProcess(String name, WorldObject newWorld)
+ {
+ world = Bukkit.getWorld(name);
+ worldname = name;
+
+ totalRegions = newWorld.width * newWorld.width;
+ currentRegion = newWorld.current;
+
+ this.lowerleft = newWorld.lowerleft;
+ allChunkCoords = generateAllChunkCoords(newWorld.width, newWorld.lowerleft);
+ }
+ LoadProcess(String name)
+ {
+ final WorldObject unfinished = ConfigProcess.getUnfinished(name);
+
+ world = Bukkit.getWorld(name);
+ worldname = name;
+
+ totalRegions = unfinished.width * unfinished.width;
+ currentRegion = unfinished.current;
+
+ this.lowerleft = unfinished.lowerleft;
+ allChunkCoords = generateAllChunkCoords(unfinished.width, unfinished.lowerleft);
+
+ this.n = unfinished.n;
+ this.c = unfinished.c;
+ this.D = unfinished.D;
+ this.d = unfinished.d;
+ this.B = unfinished.B;
+ }
+
+
+ //===============================PATTERN================================
+
+ /* The pattern:
+ *
+ * 3 | 36 35 34 33 32 31
+ * |
+ * 2 | 17 16 15 14 13 30
+ * |
+ * 1 | 18 05 04 03 12 29
+ * |
+ * Z | 19 06 01 02 11 28
+ * |
+ * -1 | 20 07 08 09 10 27
+ * |
+ * -2 | 21 22 23 24 25 26
+ * +-----------------------
+ * -2 -1 X 1 2 3
+ * etc.
+ */
+
+ int n = 1; //number
+ int c = 1; //direction of travel: E,N,W,S - 1,2,3,4
+ int D = 1; //distance to travel
+ int d = 0; //distance already traveled
+ boolean B = false; //OK to change direction?
+
+ private final void setNextRegion()
+ {
+ n++;
+ if (d != D) d++;
+ else
+ {
+ d = 0;
+ D++;
+ switch (c){
+ case 1 : currentRegion[0]++;
+ case 2 : currentRegion[1]++;
+ case 3 : currentRegion[0]--;
+ case 4 :
+ currentRegion[1]--;
+ c = B ? 1 : c + 1;
+ }
+ B = !B;
+ }
+ }
+ final boolean isFinished(){
+ return n == totalRegions;
+ }
+
+
+ //===============================CHUNK MAP==============================
+
+ private final int[] lowerleft;
+ private final int[][][][][] allChunkCoords;
+ private final int[][][][][] generateAllChunkCoords(int w,int[] lowerleft)
+ {
+ int[][][][][] allChunkCoords = new int[w][w][32][32][2];
+
+ int regionX = lowerleft[0];
+ int regionZ = lowerleft[1];
+ boolean negX = true;
+ boolean negZ = true;
+ int chunkX = 0;
+ int chunkZ = 0;
+ for (int[][][][] xRowRegions : allChunkCoords)
+ {
+ regionZ = lowerleft[1];
+ negZ = true;
+ for (int[][][] region : xRowRegions)
+ {
+ chunkX = 0;
+ for (int[][] xRowChunks : region)
+ {
+ chunkZ = 0;
+ for (int[] chunk : xRowChunks)
+ {
+ chunk[0] = (regionX * 32) + (negX ? 0 - chunkX : chunkX);
+ chunk[1] = (regionZ * 32) + (negZ ? 0 - chunkZ : chunkZ);
+ chunkZ++;
+ }
+ chunkX++;
+ }
+ regionZ++;
+ if (negZ)
+ negZ = regionZ < 0;
+ }
+ regionX++;
+ if (negX)
+ negX = regionX < 0;
+ }
+ return allChunkCoords;
+ }
+ private final int[][][] getChunksCurrentRegion(){
+ return
+ allChunkCoords
+ [ currentRegion[0] - lowerleft[0] ]
+ [ currentRegion[1] - lowerleft[1] ];
+ }
+
+
+ //==================================RUN=================================
+
+ boolean ready = true;
+ public final void run()
+ {
+ if (!ready) return;
+ else ready = false;
+
+ final int[][][] r = getChunksCurrentRegion();
+ for (int[][] xRow : r)
+ {
+ for (int[] chunk : xRow)
+ {
+ world.loadChunk(chunk[0], chunk[1], true);
+ world.unloadChunk(chunk[0], chunk[1]);
+ }
+ }
+ setNextRegion();
+
+ if (isFinished()) TaskManager.finish();
+ else ready = true;
+ }
+}
diff --git a/src/iieLoadSaveEntireWorld/Main.java b/src/iieLoadSaveEntireWorld/Main.java
new file mode 100644
index 0000000..fdcc8d7
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/Main.java
@@ -0,0 +1,13 @@
+package iieLoadSaveEntireWorld;
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class Main extends JavaPlugin {
+
+ public void onEnable()
+ {
+ saveDefaultConfig();
+ getCommand("beginfullmapload").setExecutor(new TaskManager.StartCommand());
+ getCommand("stopfullmapload").setExecutor(new TaskManager.StopCommand());
+ }
+}
diff --git a/src/iieLoadSaveEntireWorld/TaskManager.java b/src/iieLoadSaveEntireWorld/TaskManager.java
new file mode 100644
index 0000000..88bb32f
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/TaskManager.java
@@ -0,0 +1,107 @@
+package iieLoadSaveEntireWorld;
+
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitTask;
+
+public class TaskManager {
+
+ private static final Main plugin = new Main();
+
+ static boolean inProgress = false;
+ static LoadProcess loadProcess;
+ static ConfigProcess configProcess;
+ static BukkitTask loadTask;
+ static BukkitTask configTask;
+
+ //===================================CONTROLS===================================
+ private static final void start(LoadProcess loadProcess)
+ {
+ inProgress = true;
+ TaskManager.loadProcess = loadProcess;
+ TaskManager.loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 0, 10 );
+ TaskManager.configTask = Bukkit.getScheduler().runTaskTimer( plugin, new ConfigProcess(), 0, 200 );
+ }
+ static final void finish()
+ {
+ configProcess.finish();
+ loadTask.cancel();
+ configTask.cancel();
+
+ loadProcess = null;
+ configProcess = null;
+ loadTask = null;
+ configTask = null;
+
+ inProgress = false;
+ }
+ static final boolean stop()
+ {
+ if (inProgress)
+ {
+ if (loadProcess.isFinished()) finish();
+ else
+ {
+ loadTask.cancel();
+ configTask.cancel();
+ configProcess.run();
+
+ loadProcess = null;
+ configProcess = null;
+ loadTask = null;
+ configTask = null;
+
+ inProgress = false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ //===================================COMMANDS===================================
+
+ static final class StartCommand implements CommandExecutor
+ {
+ @Override
+ public final boolean onCommand(CommandSender sender, Command label, String command, String[] args)
+ {
+ String name = ((Player)sender).getWorld().getName();
+ if (inProgress)
+ {
+ sender.sendMessage("a process is already running (" + name + "). /StopLoadSave to stop.");
+ return false;
+ }
+ else inProgress = true;
+
+ if (ConfigProcess.isNew(name))
+ {
+ sender.sendMessage("starting...");
+ start(new LoadProcess(name, WorldObject.generate(args)));
+ }
+ else
+ {
+ sender.sendMessage("resuming...");
+ start(new LoadProcess(name));
+ }
+ return true;
+ }
+ }
+ static final class StopCommand implements CommandExecutor
+ {
+ @Override
+ public final boolean onCommand(CommandSender sender, Command label, String command, String[] args)
+ {
+ if (stop())
+ {
+ sender.sendMessage("stopped.");
+ return true;
+ }
+ sender.sendMessage("nothing to stop.");
+ return false;
+ }
+ }
+}
diff --git a/src/iieLoadSaveEntireWorld/WorldObject.java b/src/iieLoadSaveEntireWorld/WorldObject.java
new file mode 100644
index 0000000..9380c0c
--- /dev/null
+++ b/src/iieLoadSaveEntireWorld/WorldObject.java
@@ -0,0 +1,208 @@
+package iieLoadSaveEntireWorld;
+
+public class WorldObject {
+
+ final int width;
+ final int[] lowerleft;
+ int[] current;
+ int n;
+ int c;
+ int D;
+ int d;
+ boolean B;
+
+ WorldObject()
+ {
+ width = 44;
+ lowerleft = new int[] { -22, -22 };
+ current = new int[] { -1, -1 };
+ }
+ WorldObject(int width, int[] lowerleft, int[] center)
+ {
+ this.width = width;
+ this.lowerleft = lowerleft;
+ this.current = center;
+ }
+ WorldObject(
+ int width, int[] lowerleft, int[] current,
+ int n, int c, int D, int d, boolean B
+ )
+ {
+ this.width = width;
+ this.lowerleft = lowerleft;
+ this.current = current;
+ this.n = n;
+ this.c = c;
+ this.D = D;
+ this.D = d;
+ this.B = B;
+ }
+
+ static final WorldObject generate(String[] args)
+ {
+ if (args.length == 0)
+ {
+ return new WorldObject();
+ }
+ int[] bounds = regionBounds(new ParsedArgs(args));
+
+ return new WorldObject(
+ bounds[2] - bounds[0],
+ new int[]{ bounds[0], bounds[2] },
+ new int[]{
+ bounds[0] - 1 + (bounds[1]-bounds[0] + 1)/2,
+ bounds[2] - 1 + (bounds[3]-bounds[2] + 1)/2
+ }
+ );
+ }
+ //==============================================================================
+ private static final class ParsedArgs
+ {
+ private static final int defaultRadius = 11264;
+ private static final int[] defaultCenter = new int[]{0,0};
+
+ final int radius;
+ final int[] center;
+ ParsedArgs (String[] args)
+ {
+ if (isInt(args[0]) && args[0] != "0")
+ {
+ radius = Integer.parseInt(args[0]);
+ }
+ else
+ {
+ radius = defaultRadius;
+ }
+ if (args.length > 2 && isInt(args[1]) && isInt(args[2]))
+ {
+ center = new int[]{ Integer.parseInt(args[1]),
+ Integer.parseInt(args[2]) };
+ }
+ else
+ {
+ center = defaultCenter;
+ }
+ }
+ private static final boolean isInt(String arg)
+ {
+ int length = arg.length();
+ int i = 0;
+ if (arg.charAt(0) == '-')
+ {
+ if (length == 1) return false;
+ else i = 1;
+ }
+ for (; i < length; i++)
+ {
+ char c = arg.charAt(i);
+ if (c < '0' || c > '9')
+ return false;
+ }
+ return true;
+ }
+ }
+ //==============================================================================
+ private static final int[] regionBounds(ParsedArgs a)
+ {
+ int[] bounds = new int[]
+ {
+ // [ get region ] [ get block ]
+ Math.floorDiv( a.center[0] - a.radius, 512 ),
+ Math.floorDiv( a.center[0] + a.radius, 512 ),
+ Math.floorDiv( a.center[1] - a.radius, 512 ),
+ Math.floorDiv( a.center[1] + a.radius, 512 )
+ };
+
+ //add margins------------
+
+ final int[] edges = new int[4];
+ final int[] radii = new int[4];
+ final boolean[] margin = new boolean[4];
+
+ //get block edge farthest from center
+ edges[0] = bounds[0] *512;
+ edges[0] = (bounds[1]+1) *512 - 1;
+ edges[0] = bounds[2] *512;
+ edges[0] = (bounds[3]+1) *512 - 1;
+
+ //get radius from center to far block edge of region
+ radii[0] = Math.abs(a.center[0] - edges[0]);
+ radii[1] = Math.abs(a.center[0] - edges[1]);
+ radii[2] = Math.abs(a.center[1] - edges[2]);
+ radii[3] = Math.abs(a.center[1] - edges[3]);
+
+ //compare to original block radius, if difference is < 4 chunks add a region width
+ if (radii[0] - a.radius < 64) { bounds[0] -= 1; margin[0] = true; }
+ if (radii[1] - a.radius < 64) { bounds[1] += 1; margin[1] = true; }
+ if (radii[2] - a.radius < 64) { bounds[2] -= 1; margin[2] = true; }
+ if (radii[3] - a.radius < 64) { bounds[3] += 1; margin[3] = true; }
+
+ //resquare the selection
+ if (!margin[0])
+ if (!margin[1])
+ if (!margin[2])
+ if (!margin[3])//-----------0000
+ return bounds;
+ else//----------------------0001
+ if (radii[0] < radii[1])
+ bounds[0]++;
+ else
+ bounds[1]++;
+ else
+ if (!margin[3])//-----------0010
+ if (radii[0] < radii[1])
+ bounds[0]++;
+ else
+ bounds[1]++;
+ else//----------------------0011
+ {
+ bounds[0]++;
+ bounds[1]++;
+ }
+ else
+ if (!margin[2])
+ if (!margin[3])//-----------0100
+ if (radii[2] < radii[3])
+ bounds[2]++;
+ else
+ bounds[3]++;
+ else//----------------------0101
+ return bounds;
+ else
+ if (!margin[3])//-----------0110
+ return bounds;
+ else//----------------------0111
+ bounds[0]++;
+ else
+ if (margin[1])
+ if (margin[2])
+ if (margin[3])//------------1111
+ return bounds;
+ else//----------------------1110
+ bounds[3]++;
+ else
+ if (margin[3])//------------1101
+ bounds[2]++;
+ else//----------------------1100
+ {
+ bounds[2]++;
+ bounds[3]++;
+ }
+ else
+ if (margin[2])
+ if (margin[3])//------------1011
+ bounds[1]++;
+ else//----------------------1010
+ return bounds;
+ else
+ if (margin[3])//------------1001
+ return bounds;
+ else//----------------------1000
+ if (radii[2] == radii[3])
+ bounds[0]++;
+ else
+ bounds[1]++;
+
+ return bounds;
+ }
+}
diff --git a/src/unused/CacheOld.java b/src/unused/CacheOld.java
new file mode 100644
index 0000000..2267c14
--- /dev/null
+++ b/src/unused/CacheOld.java
@@ -0,0 +1,123 @@
+package unused;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import iieLoadSaveEntireWorld.Main;
+
+public class CacheOld
+{
+/*
+
+ private static int maxNameLength;
+ private static char[][] listUnfinished;
+ private static Map cacheUnfinished;
+ static void generate()
+ {
+ maxNameLength = Main.config.getInt("max name length");
+ Set set = Main.unfinished.getKeys(false);
+ populateList(set);
+ populateCache(set);
+ }
+ static void addWorld()
+ {
+
+ }
+ static void saveProgress()
+ {
+
+ }
+ static void finish(String name)
+ {
+ //TODO
+ }
+ static void addUnfinished(int width, int[] center, int[] lowerleft, String name)
+ {
+
+ }
+ static boolean isUnfinished(String name){
+ int i = 0;
+ boolean match = true;
+ for (char[] world : listUnfinished)
+ {
+ for (char c : name.toCharArray())
+ {
+ if (c != world[i]){ match = false; break; }
+ }
+ if (match) break;
+ i = 0;
+ match = true;
+ }
+ return match;
+ }
+ private static void populateList(Set set)
+ {
+ char[][] listUnfinished = new char[set.size()][maxNameLength];
+ int i = 0;
+ int ii = 0;
+ for (String name : set)
+ {
+ for (char c : name.toCharArray())
+ {
+ listUnfinished[i][ii] = c;
+ ii++;
+ }
+ i++;
+ ii = 0;
+ }
+ }
+ private static void populateCache(Set set)
+ {
+ String path;
+ for (String name : set){
+ path = "unfinishedWorlds." + name + ".";
+ cacheUnfinished.put(
+ name,
+ new WorldStatus(
+ Main.config.getInt(path + "width"),
+ new int[]{
+ Main.config.getInt(path + "lowerleft.x"),
+ Main.config.getInt(path + "lowerleft.z")},
+ new int[]{
+ Main.config.getInt(path + "currentRegion.x"),
+ Main.config.getInt(path + "currentRegion.z")},
+ Main.config.getInt(path + "n"),
+ Main.config.getInt(path + "c"),
+ Main.config.getInt(path + "D"),
+ Main.config.getInt(path + "d"),
+ Main.config.getBoolean(path + "B")));
+ }
+ }
+ static final class WorldStatus
+ {
+ final int width;
+ final int[] lowerleft;
+ int[] currentRegion;
+ int n = 1;
+ int c = 1;
+ int D = 1;
+ int d = 0;
+ boolean B = false;
+ WorldStatus(int width, int[] lowerleft, int[]center)
+ {
+ this.width = width;
+ this.lowerleft = lowerleft;
+ currentRegion = center;
+ }
+ WorldStatus(
+ int width, int[] lowerleft,
+ int[] current, int n, int c, int D, int d, boolean B)
+ {
+ this.width = width;
+ this.lowerleft = lowerleft;
+ currentRegion = current;
+ this.n = n;
+ this.c = c;
+ this.D = D;
+ this.d = d;
+ this.B = B;
+ }
+ }
+*/
+}
diff --git a/src/unused/LoadSaveProcessOld.java b/src/unused/LoadSaveProcessOld.java
new file mode 100644
index 0000000..c141df4
--- /dev/null
+++ b/src/unused/LoadSaveProcessOld.java
@@ -0,0 +1,236 @@
+package unused;
+
+import org.bukkit.scheduler.BukkitTask;
+
+public class LoadSaveProcessOld {
+
+ /* the contents of this class are static because
+ * loading and saving an entire world is an intensive process,
+ * and only one save process should be running at a time.
+ *
+ * so only one save process should be TRACKED at a time.
+ */
+
+ //=============================STATIC FIELDS============================
+
+ static BukkitTask task;
+
+ static int[] startRegion;
+
+ static int[] currentRegion;
+
+ static TranslatedCoordinates savedRegions;
+
+ static int[][][][][] allChunkCoords;
+
+ static RegionPattern regionPattern;
+
+ //INITIALIZE FIELDS
+ static void init(int width, int x, int z){
+ boolean even = width % 2 == 0;
+ int radius = Math.floorDiv(width,2);
+ if (even) radius -=1 ;
+ int lowX = x-radius;
+ int lowZ = z-radius;
+
+ startRegion = new int[] {x,z};
+ currentRegion = startRegion;
+ savedRegions = new TranslatedCoordinates(width,lowX,lowZ);
+ generateAllChunkCoords(width,lowX,lowZ);
+ if (even) regionPattern = new OutwardSpiralPattern();
+ else regionPattern = new CardinalPointsPattern();
+ }
+
+
+
+ //===============================PATTERNS===============================
+
+ //ABSTRACT PARENT CLASS
+ static abstract class RegionPattern {
+ static int n = 1; //iteration number
+ abstract void reset(); //reset fields
+ abstract void setNextRegion();
+ }
+
+ //EVEN DIAMETER: OUTWARD SPIRAL PATTERN
+ private static class OutwardSpiralPattern extends RegionPattern {
+
+ /* The pattern:
+ *
+ * 3 | 36 35 34 33 32 31
+ * |
+ * 2 | 17 16 15 14 13 30
+ * |
+ * 1 | 18 05 04 03 12 29
+ * |
+ * Z | 19 06 01 02 11 28
+ * |
+ * -1 | 20 07 08 09 10 27
+ * |
+ * -2 | 21 22 23 24 25 26
+ * +-----------------------
+ * -2 -1 X 1 2 3
+ * etc.
+ */
+
+ static int c; //direction of travel: E,N,W,S - 1,2,3,4
+ static int D; //distance to travel
+ static int d; //distance already traveled
+ static boolean B; //OK to change direction?
+
+ OutwardSpiralPattern(){
+ c = 1;
+ D = 1;
+ d = 0;
+ B = false;
+ }
+
+
+
+ //interface methods
+ public void reset() {
+
+ }
+ public void setNextRegion() {
+
+ }
+ }
+
+
+ //ODD DIAMETER: CARDINAL POINTS PATTERN
+ private static class CardinalPointsPattern extends RegionPattern {
+
+ /* The pattern:
+ *
+ * 2 | 23 18 10 14 22
+ * |
+ * 1 | 15 07 02 06 21
+ * |
+ * Z | 11 03 01 05 13
+ * |
+ * -1 | 19 08 04 09 17
+ * |
+ * -2 | 24 16 12 20 25
+ * +-------------------
+ * -2 -1 X 1 2
+ * etc.
+ */
+
+ private static int[] cardinalPoints; //midpoint of each side
+
+ private static int c; //side: N,W,S,E = 1,2,3,4
+ private static int r; //radius from square center
+
+ private static int d; //distance from cardinal point
+ private static boolean B; //direction from cardinal point
+
+ private static void expR(){ //expand radius, cardinal points
+ r++;
+ cardinalPoints[0]++;
+ cardinalPoints[1]--;
+ cardinalPoints[2]--;
+ cardinalPoints[4]++;
+ }
+
+ CardinalPointsPattern(){
+ reset();
+ }
+
+ //interface methods
+ void reset(){
+ cardinalPoints = new int[] { //each cardinal point contains
+ startRegion[1]+1, //only the dimension that moves
+ startRegion[0]-1,
+ startRegion[1]-1,
+ startRegion[0]+1
+ };
+ n = 1;
+ c = 1;
+ r = 1;
+ d = 0;
+ B = false;
+ }
+ void setNextRegion(){
+ n++;
+ switch (c){
+ case 1 :
+ if (B) currentRegion = new int[] {startRegion[0] + d, cardinalPoints[0]};
+ else; currentRegion = new int[] {startRegion[0] - d, cardinalPoints[0]};
+ case 2 :
+ if (B) currentRegion = new int[] {cardinalPoints[1], startRegion[0] + d};
+ else; currentRegion = new int[] {cardinalPoints[1], startRegion[0] - d};
+ case 3 :
+ if (B) currentRegion = new int[] {startRegion[0] - d, cardinalPoints[2]};
+ else; currentRegion = new int[] {startRegion[0] + d, cardinalPoints[2]};
+ case 4 :
+ if (B) currentRegion = new int[] {cardinalPoints[3], startRegion[0] - d};
+ else; currentRegion = new int[] {cardinalPoints[3], startRegion[0] + d};
+
+ if (r == d) { expR(); d = 0; c = 1; }
+ else { d++; c++; B = !B; }
+
+ }
+ }
+ }
+
+
+
+ //=================================UTIL=================================
+
+ //CUSTOM MAP CLASS FOR TRACKING SAVED REGIONS
+ static class TranslatedCoordinates {
+
+ int xAdjust;
+ int zAdjust;
+ boolean[][] savemap;
+ public TranslatedCoordinates(int w, int lowX, int lowZ)
+ {
+ xAdjust = 0 - lowX;
+ zAdjust = 0 - lowZ;
+ savemap = new boolean[w][w];
+ }
+ int x(int x){ return x + xAdjust; }
+ int z(int z){ return z + zAdjust; }
+
+ void save(int x, int z) { savemap[x(x)][z(z)] = true; }
+ boolean isSaved(int x, int z) { return savemap[x(x)][z(z)]; }
+
+ boolean allSaved(){
+ for (boolean[] xRow : savemap){
+ for (boolean region : xRow){
+ if (!region) return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ //GENERATE ALL CHUNK COORDINATES
+ private static void generateAllChunkCoords(int d, int lowX, int lowZ) {
+ allChunkCoords = new int[d][d][32][32][2];
+ int regionX = lowX;
+ boolean negX = true;
+ for (int[][][][] xRowRegions : allChunkCoords){
+ int regionZ = lowZ;
+ boolean negZ = true;
+ for (int[][][] region : xRowRegions){
+ int chunkX = 0;
+ for (int[][] xRowChunks : region){
+ int chunkZ = 0;
+ for (int[] chunk : xRowChunks){
+ chunk[0] = (regionX * 32) + (negX ? 0 - chunkX : chunkX);
+ chunk[1] = (regionZ * 32) + (negZ ? 0 - chunkZ : chunkZ);
+ chunkZ++;
+ }
+ chunkX++;
+ }
+ regionZ++;
+ if (negZ)
+ negZ = regionZ < 0;
+ }
+ regionX++;
+ if (negX)
+ negX = regionX < 0;
+ }
+ }
+}
diff --git a/target/config.yml b/target/config.yml
new file mode 100644
index 0000000..e69de29
diff --git a/target/plugin.yml b/target/plugin.yml
new file mode 100644
index 0000000..4d5b3c3
--- /dev/null
+++ b/target/plugin.yml
@@ -0,0 +1,6 @@
+ main: iieLoadSaveEntireWorld.Main
+ version: 1.0.0
+ name: LoadSaveEntireWorld
+ commands:
+ loadsaveentireworld:
+ description: loads and saves the entire map, in 32x32 chunk sections
\ No newline at end of file