diff --git a/src/iieLoadSaveEntireWorld/ConfigProcess.java b/src/iieLoadSaveEntireWorld/ConfigProcess.java index 6a9de41..44838fb 100644 --- a/src/iieLoadSaveEntireWorld/ConfigProcess.java +++ b/src/iieLoadSaveEntireWorld/ConfigProcess.java @@ -12,13 +12,13 @@ public class ConfigProcess implements Runnable { { return !config.contains(name); } - static final void addNew(String name, int width, int[] lowerleft, int[] center) + static final void addNew(String name, WorldObject newWorld) { - config.set(name + ".width", width); - config.set(name + ".lowerleft.x", lowerleft[0]); - config.set(name + ".lowerleft.z", lowerleft[1]); - config.set(name + ".currentRegion.x", center[0]); - config.set(name + ".currentRegion.z", center[1]); + config.set(name + ".width", newWorld.width); + config.set(name + ".lowerleft.x", newWorld.lowerleft[0]); + config.set(name + ".lowerleft.z", newWorld.lowerleft[1]); + config.set(name + ".currentRegion.x", newWorld.current[0]); + config.set(name + ".currentRegion.z", newWorld.current[1]); config.set(name + ".n", 1); config.set(name + ".c", 1); config.set(name + ".D", 1); @@ -48,10 +48,26 @@ public class ConfigProcess implements Runnable { config.getInt(name + ".B") == 1 ); } + static final boolean crashResume() + { + return config.contains("@ CRASH RESUME"); + } + static final String getCrashResume() + { + return config.getString("@ CRASH RESUME"); + } //INSTANCE private final String name = TaskManager.loadProcess.worldname; + ConfigProcess() + { + config.set("@ CRASH RESUME", name); + } + ConfigProcess(boolean b) + { + //don't create crash resume + } public final void run() { final int[] currentRegion = TaskManager.loadProcess.currentRegion; @@ -74,8 +90,17 @@ public class ConfigProcess implements Runnable { } final void finish() { - config.set("finished worlds, fully saved", name); + config.set("@ FINISHED WORLDS", name); + config.set("@ CRASH RESUME", null); config.set(name, null); plugin.saveConfig(); } + final void stop() + { + run(); + config.set("@ CRASH RESUME", null); + plugin.saveConfig(); + Bukkit.getLogger().info("...stopping world-load"); + + } } diff --git a/src/iieLoadSaveEntireWorld/LoadProcess.java b/src/iieLoadSaveEntireWorld/LoadProcess.java index 6fb0531..9b66c56 100644 --- a/src/iieLoadSaveEntireWorld/LoadProcess.java +++ b/src/iieLoadSaveEntireWorld/LoadProcess.java @@ -7,22 +7,24 @@ public class LoadProcess implements Runnable { //=================================INIT================================= - final World world; - final String worldname; - final int totalRegions; - int[] currentRegion; + final World world; + final String worldname; + final int totalRegions; + int[] currentRegion; LoadProcess(String name, WorldObject newWorld) { + ConfigProcess.addNew(name, 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); + lowerleft = newWorld.lowerleft; + allChunkCoords = generateAllChunkCoords(newWorld.width); } LoadProcess(String name) { @@ -34,14 +36,14 @@ public class LoadProcess implements Runnable totalRegions = unfinished.width * unfinished.width; currentRegion = unfinished.current; - this.lowerleft = unfinished.lowerleft; - allChunkCoords = generateAllChunkCoords(unfinished.width, unfinished.lowerleft); + lowerleft = unfinished.lowerleft; + allChunkCoords = generateAllChunkCoords(unfinished.width); - this.n = unfinished.n; - this.c = unfinished.c; - this.D = unfinished.D; - this.d = unfinished.d; - this.B = unfinished.B; + n = unfinished.n; + c = unfinished.c; + D = unfinished.D; + d = unfinished.d; + B = unfinished.B; } @@ -71,14 +73,15 @@ public class LoadProcess implements Runnable int d = 0; //distance already traveled boolean B = false; //OK to increase distance? - private final void setNextRegion() + private final boolean setNextRegion() { n++; + if (n == totalRegions) return false; if (d != D) d++; else { - d = 0; if (B) D++; B = !B; - + d = 0; if (B) D++; + B = !B; c = c == 4 ? 1 : c + 1; } switch (c) @@ -88,9 +91,7 @@ public class LoadProcess implements Runnable case 3 : currentRegion[0]--; break; case 4 : currentRegion[1]--; break; } - } - final boolean isFinished(){ - return n == totalRegions; + return true; } @@ -98,7 +99,7 @@ public class LoadProcess implements Runnable private final int[] lowerleft; private final int[][][][][] allChunkCoords; - private final int[][][][][] generateAllChunkCoords(int w,int[] lowerleft) + private final int[][][][][] generateAllChunkCoords(int w) { int[][][][][] allChunkCoords = new int[w][w][32][32][2]; @@ -145,8 +146,7 @@ public class LoadProcess implements Runnable //==================================RUN================================= - - private boolean ready = true; + private static volatile boolean ready = true; public final void run() { if (!ready) return; @@ -161,9 +161,10 @@ public class LoadProcess implements Runnable world.unloadChunk(chunk[0], chunk[1]); } } - setNextRegion(); - - if (isFinished()) TaskManager.finish(); - else ready = true; + if (!setNextRegion()) + { + TaskManager.finish(); + } + ready = true; } } diff --git a/src/iieLoadSaveEntireWorld/Main.java b/src/iieLoadSaveEntireWorld/Main.java index c669844..c026b17 100644 --- a/src/iieLoadSaveEntireWorld/Main.java +++ b/src/iieLoadSaveEntireWorld/Main.java @@ -1,5 +1,6 @@ package iieLoadSaveEntireWorld; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; public class Main extends JavaPlugin { @@ -14,5 +15,10 @@ public class Main extends JavaPlugin { TaskManager.plugin = this; ConfigProcess.plugin = this; ConfigProcess.config = getConfig(); + + if (TaskManager.crashResume()) + { + Bukkit.getLogger().info("...resuming from crash"); + } } } diff --git a/src/iieLoadSaveEntireWorld/TaskManager.java b/src/iieLoadSaveEntireWorld/TaskManager.java index ddf7b07..fa5089c 100644 --- a/src/iieLoadSaveEntireWorld/TaskManager.java +++ b/src/iieLoadSaveEntireWorld/TaskManager.java @@ -11,7 +11,9 @@ public class TaskManager { static Main plugin; - static boolean inProgress = false; + static boolean inProgress = false; + static boolean canRun = true; + static LoadProcess loadProcess; static ConfigProcess configProcess; static BukkitTask loadTask; @@ -31,11 +33,24 @@ public class TaskManager { loadProcess = new LoadProcess(name); isNew = false; } - TaskManager.configProcess = new ConfigProcess(); - TaskManager.loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 0, 10 ); - TaskManager.configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 0, 200 ); + configProcess = new ConfigProcess(); + loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 0, 100 ); + configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 0, 200 ); return isNew; } + static final boolean crashResume() + { + if (ConfigProcess.crashResume()) + { + loadProcess = new LoadProcess(ConfigProcess.getCrashResume()); + configProcess = new ConfigProcess(false); + + loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 1200, 100 ); + configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 1200, 200 ); + return true; + } + return false; + } static final void finish() { loadTask.cancel(); @@ -53,12 +68,12 @@ public class TaskManager { { if (inProgress) { - if (loadProcess.isFinished()) finish(); + if (loadProcess.n == loadProcess.totalRegions) finish(); else { loadTask.cancel(); configTask.cancel(); - configProcess.run(); + configProcess.stop(); loadProcess = null; configProcess = null; diff --git a/src/iieLoadSaveEntireWorld/WorldObject.java b/src/iieLoadSaveEntireWorld/WorldObject.java index 01465f5..31f54e3 100644 --- a/src/iieLoadSaveEntireWorld/WorldObject.java +++ b/src/iieLoadSaveEntireWorld/WorldObject.java @@ -45,15 +45,27 @@ public class WorldObject { 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 - } - ); + return new WorldObject + ( + bounds[2] - bounds[0],//----------------------------width + new int[] { bounds[0], bounds[2] },//---------------lowerleft + new int[] { //--------------------------------------center + bounds[0] - 1 + (bounds[1]-bounds[0] + 1)/2, + bounds[2] - 1 + (bounds[3]-bounds[2] + 1)/2 + } + ); + /* for even widths, the math above returns the + * minimum center not the maximum center. So: + * + * * * * * + * * X X * + * * O X * + * * * * * + * + * the spiral pattern used in LoadProcess rotates + * counter-clockwise, so it must begin at minimum + * center. + */ } //============================================================================== private static final class ParsedArgs diff --git a/src/unused/CacheOld.java b/src/unused/CacheOld.java deleted file mode 100644 index 2267c14..0000000 --- a/src/unused/CacheOld.java +++ /dev/null @@ -1,123 +0,0 @@ -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/ChunkLoaderAPI.java b/src/unused/ChunkLoaderAPI.java deleted file mode 100644 index 24182f3..0000000 --- a/src/unused/ChunkLoaderAPI.java +++ /dev/null @@ -1,31 +0,0 @@ -package unused; - -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/unused/LoadSaveProcessOld.java b/src/unused/LoadSaveProcessOld.java deleted file mode 100644 index c141df4..0000000 --- a/src/unused/LoadSaveProcessOld.java +++ /dev/null @@ -1,236 +0,0 @@ -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; - } - } -}