added crashResume and some other changes

This commit is contained in:
BuildTools 2016-11-27 10:48:15 -05:00
parent 19b4a31775
commit 590b052e08
8 changed files with 107 additions and 438 deletions

View file

@ -12,13 +12,13 @@ public class ConfigProcess implements Runnable {
{ {
return !config.contains(name); 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 + ".width", newWorld.width);
config.set(name + ".lowerleft.x", lowerleft[0]); config.set(name + ".lowerleft.x", newWorld.lowerleft[0]);
config.set(name + ".lowerleft.z", lowerleft[1]); config.set(name + ".lowerleft.z", newWorld.lowerleft[1]);
config.set(name + ".currentRegion.x", center[0]); config.set(name + ".currentRegion.x", newWorld.current[0]);
config.set(name + ".currentRegion.z", center[1]); config.set(name + ".currentRegion.z", newWorld.current[1]);
config.set(name + ".n", 1); config.set(name + ".n", 1);
config.set(name + ".c", 1); config.set(name + ".c", 1);
config.set(name + ".D", 1); config.set(name + ".D", 1);
@ -48,10 +48,26 @@ public class ConfigProcess implements Runnable {
config.getInt(name + ".B") == 1 config.getInt(name + ".B") == 1
); );
} }
static final boolean crashResume()
{
return config.contains("@ CRASH RESUME");
}
static final String getCrashResume()
{
return config.getString("@ CRASH RESUME");
}
//INSTANCE //INSTANCE
private final String name = TaskManager.loadProcess.worldname; 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() public final void run()
{ {
final int[] currentRegion = TaskManager.loadProcess.currentRegion; final int[] currentRegion = TaskManager.loadProcess.currentRegion;
@ -74,8 +90,17 @@ public class ConfigProcess implements Runnable {
} }
final void finish() final void finish()
{ {
config.set("finished worlds, fully saved", name); config.set("@ FINISHED WORLDS", name);
config.set("@ CRASH RESUME", null);
config.set(name, null); config.set(name, null);
plugin.saveConfig(); plugin.saveConfig();
} }
final void stop()
{
run();
config.set("@ CRASH RESUME", null);
plugin.saveConfig();
Bukkit.getLogger().info("...stopping world-load");
}
} }

View file

@ -7,22 +7,24 @@ public class LoadProcess implements Runnable
{ {
//=================================INIT================================= //=================================INIT=================================
final World world; final World world;
final String worldname; final String worldname;
final int totalRegions; final int totalRegions;
int[] currentRegion; int[] currentRegion;
LoadProcess(String name, WorldObject newWorld) LoadProcess(String name, WorldObject newWorld)
{ {
ConfigProcess.addNew(name, newWorld);
world = Bukkit.getWorld(name); world = Bukkit.getWorld(name);
worldname = name; worldname = name;
totalRegions = newWorld.width * newWorld.width; totalRegions = newWorld.width * newWorld.width;
currentRegion = newWorld.current; currentRegion = newWorld.current;
this.lowerleft = newWorld.lowerleft; lowerleft = newWorld.lowerleft;
allChunkCoords = generateAllChunkCoords(newWorld.width, newWorld.lowerleft); allChunkCoords = generateAllChunkCoords(newWorld.width);
} }
LoadProcess(String name) LoadProcess(String name)
{ {
@ -34,14 +36,14 @@ public class LoadProcess implements Runnable
totalRegions = unfinished.width * unfinished.width; totalRegions = unfinished.width * unfinished.width;
currentRegion = unfinished.current; currentRegion = unfinished.current;
this.lowerleft = unfinished.lowerleft; lowerleft = unfinished.lowerleft;
allChunkCoords = generateAllChunkCoords(unfinished.width, unfinished.lowerleft); allChunkCoords = generateAllChunkCoords(unfinished.width);
this.n = unfinished.n; n = unfinished.n;
this.c = unfinished.c; c = unfinished.c;
this.D = unfinished.D; D = unfinished.D;
this.d = unfinished.d; d = unfinished.d;
this.B = unfinished.B; B = unfinished.B;
} }
@ -71,14 +73,15 @@ public class LoadProcess implements Runnable
int d = 0; //distance already traveled int d = 0; //distance already traveled
boolean B = false; //OK to increase distance? boolean B = false; //OK to increase distance?
private final void setNextRegion() private final boolean setNextRegion()
{ {
n++; n++;
if (n == totalRegions) return false;
if (d != D) d++; if (d != D) d++;
else else
{ {
d = 0; if (B) D++; B = !B; d = 0; if (B) D++;
B = !B;
c = c == 4 ? 1 : c + 1; c = c == 4 ? 1 : c + 1;
} }
switch (c) switch (c)
@ -88,9 +91,7 @@ public class LoadProcess implements Runnable
case 3 : currentRegion[0]--; break; case 3 : currentRegion[0]--; break;
case 4 : currentRegion[1]--; break; case 4 : currentRegion[1]--; break;
} }
} return true;
final boolean isFinished(){
return n == totalRegions;
} }
@ -98,7 +99,7 @@ public class LoadProcess implements Runnable
private final int[] lowerleft; private final int[] lowerleft;
private final int[][][][][] allChunkCoords; 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]; int[][][][][] allChunkCoords = new int[w][w][32][32][2];
@ -145,8 +146,7 @@ public class LoadProcess implements Runnable
//==================================RUN================================= //==================================RUN=================================
private static volatile boolean ready = true;
private boolean ready = true;
public final void run() public final void run()
{ {
if (!ready) return; if (!ready) return;
@ -161,9 +161,10 @@ public class LoadProcess implements Runnable
world.unloadChunk(chunk[0], chunk[1]); world.unloadChunk(chunk[0], chunk[1]);
} }
} }
setNextRegion(); if (!setNextRegion())
{
if (isFinished()) TaskManager.finish(); TaskManager.finish();
else ready = true; }
ready = true;
} }
} }

View file

@ -1,5 +1,6 @@
package iieLoadSaveEntireWorld; package iieLoadSaveEntireWorld;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin { public class Main extends JavaPlugin {
@ -14,5 +15,10 @@ public class Main extends JavaPlugin {
TaskManager.plugin = this; TaskManager.plugin = this;
ConfigProcess.plugin = this; ConfigProcess.plugin = this;
ConfigProcess.config = getConfig(); ConfigProcess.config = getConfig();
if (TaskManager.crashResume())
{
Bukkit.getLogger().info("...resuming from crash");
}
} }
} }

View file

@ -11,7 +11,9 @@ public class TaskManager {
static Main plugin; static Main plugin;
static boolean inProgress = false; static boolean inProgress = false;
static boolean canRun = true;
static LoadProcess loadProcess; static LoadProcess loadProcess;
static ConfigProcess configProcess; static ConfigProcess configProcess;
static BukkitTask loadTask; static BukkitTask loadTask;
@ -31,11 +33,24 @@ public class TaskManager {
loadProcess = new LoadProcess(name); loadProcess = new LoadProcess(name);
isNew = false; isNew = false;
} }
TaskManager.configProcess = new ConfigProcess(); configProcess = new ConfigProcess();
TaskManager.loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 0, 10 ); loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 0, 100 );
TaskManager.configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 0, 200 ); configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 0, 200 );
return isNew; 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() static final void finish()
{ {
loadTask.cancel(); loadTask.cancel();
@ -53,12 +68,12 @@ public class TaskManager {
{ {
if (inProgress) if (inProgress)
{ {
if (loadProcess.isFinished()) finish(); if (loadProcess.n == loadProcess.totalRegions) finish();
else else
{ {
loadTask.cancel(); loadTask.cancel();
configTask.cancel(); configTask.cancel();
configProcess.run(); configProcess.stop();
loadProcess = null; loadProcess = null;
configProcess = null; configProcess = null;

View file

@ -45,15 +45,27 @@ public class WorldObject {
return new WorldObject(); return new WorldObject();
} }
int[] bounds = regionBounds(new ParsedArgs(args)); int[] bounds = regionBounds(new ParsedArgs(args));
return new WorldObject
return new WorldObject( (
bounds[2] - bounds[0], bounds[2] - bounds[0],//----------------------------width
new int[]{ bounds[0], bounds[2] }, new int[] { bounds[0], bounds[2] },//---------------lowerleft
new int[]{ new int[] { //--------------------------------------center
bounds[0] - 1 + (bounds[1]-bounds[0] + 1)/2, bounds[0] - 1 + (bounds[1]-bounds[0] + 1)/2,
bounds[2] - 1 + (bounds[3]-bounds[2] + 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 private static final class ParsedArgs

View file

@ -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<String,WorldStatus> cacheUnfinished;
static void generate()
{
maxNameLength = Main.config.getInt("max name length");
Set<String> 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<String> 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<String> 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;
}
}
*/
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}