I forget if I've tested all this

This commit is contained in:
BuildTools 2016-11-28 14:27:16 -05:00
parent 590b052e08
commit 845a0e56e5
5 changed files with 127 additions and 193 deletions

View file

@ -5,18 +5,18 @@ import org.bukkit.configuration.file.FileConfiguration;
public class ConfigProcess implements Runnable { public class ConfigProcess implements Runnable {
//STATIC static Main plugin; //initialized in Main onEnable()
static Main plugin; static FileConfiguration config;//
static FileConfiguration config;
final String name;
//================================STATIC================================
static final boolean isNew(String name) static final boolean isNew(String name)
{ {
return !config.contains(name); return !config.contains(name);
} }
static final void addNew(String name, WorldObject newWorld) static final void addNew(String name, WorldObj newWorld)
{ {
config.set(name + ".width", newWorld.width); config.set(name + ".total", newWorld.total);
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.x", newWorld.current[0]);
config.set(name + ".currentRegion.z", newWorld.current[1]); config.set(name + ".currentRegion.z", newWorld.current[1]);
config.set(name + ".n", 1); config.set(name + ".n", 1);
@ -26,16 +26,11 @@ public class ConfigProcess implements Runnable {
config.set(name + ".B", 0); config.set(name + ".B", 0);
plugin.saveConfig(); plugin.saveConfig();
} }
static final WorldObject getUnfinished(String name) static final WorldObj getUnfinished(String name)
{ {
return new WorldObject return new WorldObj
( (
config.getInt(name + ".width"), config.getInt(name + ".total"),
new int[]
{
config.getInt(name + ".lowerleft.x"),
config.getInt(name + ".lowerleft.z")
},
new int[] new int[]
{ {
config.getInt(name + ".currentRegion.x"), config.getInt(name + ".currentRegion.x"),
@ -57,36 +52,34 @@ public class ConfigProcess implements Runnable {
return config.getString("@ CRASH RESUME"); return config.getString("@ CRASH RESUME");
} }
//===============================INSTANCE===============================
//INSTANCE ConfigProcess(String name)
private final String name = TaskManager.loadProcess.worldname;
ConfigProcess()
{ {
this.name = name;
config.set("@ CRASH RESUME", name); config.set("@ CRASH RESUME", name);
} }
ConfigProcess(boolean b) ConfigProcess(boolean b)
{ {
//don't create crash resume name = config.getString("@ CRASH RESUME");
} }
public final void run() public final void run()
{ {
final int[] currentRegion = TaskManager.loadProcess.currentRegion; config.set(name + ".currentRegion.x", TaskManager.loadProcess.currentRegion[0]);
Bukkit.getLogger().info config.set(name + ".currentRegion.z", TaskManager.loadProcess.currentRegion[1]);
(
"Saving world-load progress: " + name
+ "["
+ currentRegion[0] + ","
+ currentRegion[1]
+ "]"
);
config.set(name + ".currentRegion.x", currentRegion[0]);
config.set(name + ".currentRegion.z", currentRegion[1]);
config.set(name + ".n", TaskManager.loadProcess.n); config.set(name + ".n", TaskManager.loadProcess.n);
config.set(name + ".c", TaskManager.loadProcess.c); config.set(name + ".c", TaskManager.loadProcess.c);
config.set(name + ".D", TaskManager.loadProcess.D); config.set(name + ".D", TaskManager.loadProcess.D);
config.set(name + ".d", TaskManager.loadProcess.d); config.set(name + ".d", TaskManager.loadProcess.d);
config.set(name + ".B", TaskManager.loadProcess.B ? 1 : 0); config.set(name + ".B", TaskManager.loadProcess.B ? 1 : 0);
plugin.saveConfig(); plugin.saveConfig();
Bukkit.getLogger().info
(
"Saving world-load progress: " + name
+ "["
+ TaskManager.loadProcess.currentRegion[0] + ","
+ TaskManager.loadProcess.currentRegion[1]
+ "]"
);
} }
final void finish() final void finish()
{ {
@ -100,7 +93,7 @@ public class ConfigProcess implements Runnable {
run(); run();
config.set("@ CRASH RESUME", null); config.set("@ CRASH RESUME", null);
plugin.saveConfig(); plugin.saveConfig();
Bukkit.getLogger().info("...stopping world-load"); Bukkit.getLogger()
.info("...stopping world-load");
} }
} }

View file

@ -7,38 +7,25 @@ public class LoadProcess implements Runnable
{ {
//=================================INIT================================= //=================================INIT=================================
final World world; private final World world;
final String worldname; final int totalRegions;
final int totalRegions; int[] currentRegion;
int[] currentRegion; LoadProcess(String name, WorldObj newWorld)
LoadProcess(String name, WorldObject newWorld)
{ {
ConfigProcess.addNew(name, newWorld); ConfigProcess.addNew(name, newWorld);
world = Bukkit.getWorld(name); world = Bukkit.getWorld(name);
worldname = name; totalRegions = newWorld.total;
totalRegions = newWorld.width * newWorld.width;
currentRegion = newWorld.current; currentRegion = newWorld.current;
lowerleft = newWorld.lowerleft;
allChunkCoords = generateAllChunkCoords(newWorld.width);
} }
LoadProcess(String name) LoadProcess(String name)
{ {
final WorldObject unfinished = ConfigProcess.getUnfinished(name); final WorldObj unfinished = ConfigProcess.getUnfinished(name);
world = Bukkit.getWorld(name); world = Bukkit.getWorld(name);
worldname = name; totalRegions = unfinished.total;
totalRegions = unfinished.width * unfinished.width;
currentRegion = unfinished.current; currentRegion = unfinished.current;
lowerleft = unfinished.lowerleft;
allChunkCoords = generateAllChunkCoords(unfinished.width);
n = unfinished.n; n = unfinished.n;
c = unfinished.c; c = unfinished.c;
D = unfinished.D; D = unfinished.D;
@ -75,15 +62,16 @@ public class LoadProcess implements Runnable
private final boolean setNextRegion() private final boolean setNextRegion()
{ {
n++;
if (n == totalRegions) return false; if (n == totalRegions) return false;
if (d != D) d++; if (d == D)
else
{ {
d = 0; if (B) D++; d = 1;
if (B) D++;
B = !B; B = !B;
c = c == 4 ? 1 : c + 1; c = c == 4 ? 1 : c + 1;
} }
else d++;
switch (c) switch (c)
{ {
case 1 : currentRegion[0]++; break; case 1 : currentRegion[0]++; break;
@ -91,60 +79,27 @@ 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;
} }
n++;
return true; return true;
} }
//===============================CHUNK MAP============================== //==============================GET CHUNKS==============================
private final int[][][] getChunksCurrentRegion()
private final int[] lowerleft;
private final int[][][][][] allChunkCoords;
private final int[][][][][] generateAllChunkCoords(int w)
{ {
int[][][][][] allChunkCoords = new int[w][w][32][32][2]; final int[][][] chunks = new int[32][32][2];
int z;
int regionX = lowerleft[0]; for (int x = 0; x < 32; x++)
int regionZ = lowerleft[1];
boolean negX = true;
boolean negZ = true;
int chunkX = 0;
int chunkZ = 0;
for (int[][][][] xRowRegions : allChunkCoords)
{ {
regionZ = lowerleft[1]; z = 0;
negZ = true; for (; z < 32; z++)
for (int[][][] region : xRowRegions)
{ {
chunkX = 0; chunks[x][z][0] = (currentRegion[0] * 32) + x;
for (int[][] xRowChunks : region) chunks[x][z][1] = (currentRegion[1] * 32) + z;
{
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; return chunks;
} }
private final int[][][] getChunksCurrentRegion(){
return
allChunkCoords
[ currentRegion[0] - lowerleft[0] ]
[ currentRegion[1] - lowerleft[1] ];
}
//==================================RUN================================= //==================================RUN=================================
private static volatile boolean ready = true; private static volatile boolean ready = true;
public final void run() public final void run()
@ -158,7 +113,7 @@ public class LoadProcess implements Runnable
for (int[] chunk : xRow) for (int[] chunk : xRow)
{ {
world.loadChunk(chunk[0], chunk[1], true); world.loadChunk(chunk[0], chunk[1], true);
world.unloadChunk(chunk[0], chunk[1]); world.unloadChunkRequest(chunk[0], chunk[1]);
} }
} }
if (!setNextRegion()) if (!setNextRegion())

View file

@ -4,21 +4,17 @@ 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 {
public void onEnable() public void onEnable()
{ {
saveDefaultConfig(); saveDefaultConfig();
getCommand("beginfullmapload").setExecutor(new TaskManager.StartCommand()); getCommand("beginfullmapload").setExecutor(new TaskManager.StartCommand());
getCommand("stopfullmapload").setExecutor(new TaskManager.StopCommand()); getCommand("stopfullmapload").setExecutor(new TaskManager.StopCommand());
TaskManager.plugin = this;
ConfigProcess.plugin = this; ConfigProcess.plugin = this;
ConfigProcess.config = getConfig(); ConfigProcess.config = getConfig();
if (TaskManager.crashResume()) if (TaskManager.crashResume())
{
Bukkit.getLogger().info("...resuming from crash"); Bukkit.getLogger().info("...resuming from crash");
}
} }
} }

View file

@ -8,35 +8,36 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
public class TaskManager { public class TaskManager {
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; private static BukkitTask loadTask;
static BukkitTask configTask; private static BukkitTask configTask;
//===================================CONTROLS===================================
private static final boolean start(String name, String[] args) //===================================CONTROLS==================================
private static final void schedule(long delay)
{
loadTask = Bukkit.getScheduler().runTaskTimer(ConfigProcess.plugin, loadProcess, delay, 100);
configTask = Bukkit.getScheduler().runTaskTimer(ConfigProcess.plugin, loadProcess, delay, 100);
}
//-----------------------------------------------------------------------------
private static final boolean start(String[] args, String name)
{ {
final boolean isNew;
if (ConfigProcess.isNew(name)) if (ConfigProcess.isNew(name))
{ {
loadProcess = new LoadProcess(name, WorldObject.generate(args)); loadProcess = new LoadProcess(name, WorldObj.generate(args));
isNew = true; configProcess = new ConfigProcess(name);
schedule(0);
return true;
} }
else loadProcess = new LoadProcess(name);
{ configProcess = new ConfigProcess(name);
loadProcess = new LoadProcess(name); schedule(0);
isNew = false; return false;
}
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() static final boolean crashResume()
{ {
@ -44,18 +45,15 @@ public class TaskManager {
{ {
loadProcess = new LoadProcess(ConfigProcess.getCrashResume()); loadProcess = new LoadProcess(ConfigProcess.getCrashResume());
configProcess = new ConfigProcess(false); configProcess = new ConfigProcess(false);
schedule(1200);
loadTask = Bukkit.getScheduler().runTaskTimer( plugin, loadProcess, 1200, 100 );
configTask = Bukkit.getScheduler().runTaskTimer( plugin, configProcess, 1200, 200 );
return true; return true;
} }
return false; return false;
} }
static final void finish() static final void stop_or_finish()
{ {
loadTask.cancel(); loadTask.cancel();
configTask.cancel(); configTask.cancel();
configProcess.finish();
loadProcess = null; loadProcess = null;
configProcess = null; configProcess = null;
@ -64,6 +62,11 @@ public class TaskManager {
inProgress = false; inProgress = false;
} }
static final void finish()
{
configProcess.finish();
}
static final boolean stop() static final boolean stop()
{ {
if (inProgress) if (inProgress)
@ -87,34 +90,10 @@ public class TaskManager {
return false; return false;
} }
//===================================COMMANDS=================================== //===================================COMMANDS===================================
static final class StartCommand implements CommandExecutor
{
@Override
public final boolean onCommand(CommandSender sender, Command label, String command, String[] args)
{
if (inProgress)
{
sender.sendMessage("a process is already running (" + loadProcess.worldname + "). /StopLoadSave to stop.");
return false;
}
else inProgress = true;
if (start(((Player)sender).getWorld().getName(),args))
{
sender.sendMessage("starting...");
}
else
{
sender.sendMessage("resuming...");
}
return true;
}
}
static final class StopCommand implements CommandExecutor static final class StopCommand implements CommandExecutor
{ {
@Override
public final boolean onCommand(CommandSender sender, Command label, String command, String[] args) public final boolean onCommand(CommandSender sender, Command label, String command, String[] args)
{ {
if (stop()) if (stop())
@ -126,4 +105,23 @@ public class TaskManager {
return false; return false;
} }
} }
static final class StartCommand implements CommandExecutor
{
public final boolean onCommand(CommandSender sender, Command label, String command, String[] args)
{
if (inProgress)
{
sender.sendMessage("a process is already running (" + configProcess.name + "). /StopLoadSave to stop.");
return false;
}
inProgress = true;
sender.sendMessage
(
start(args,((Player)sender).getWorld().getName()) ?
"starting..." :
"resuming..."
);
return true;
}
}
} }

View file

@ -1,9 +1,8 @@
package iieLoadSaveEntireWorld; package iieLoadSaveEntireWorld;
public class WorldObject { public class WorldObj {
final int width; final int total;
final int[] lowerleft;
int[] current; int[] current;
int n; int n;
int c; int c;
@ -11,25 +10,20 @@ public class WorldObject {
int d; int d;
boolean B; boolean B;
WorldObject() WorldObj()
{ {
width = 44; total = 1936; //44 * 44
lowerleft = new int[] { -22, -22 };
current = new int[] { -1, -1 }; current = new int[] { -1, -1 };
} }
WorldObject(int width, int[] lowerleft, int[] center) WorldObj(int total, int[] center)
{ {
this.width = width; this.total = total;
this.lowerleft = lowerleft;
this.current = center; this.current = center;
} }
WorldObject( WorldObj(int total, int[] current,
int width, int[] lowerleft, int[] current, int n, int c, int D, int d, boolean B)
int n, int c, int D, int d, boolean B
)
{ {
this.width = width; this.total = total;
this.lowerleft = lowerleft;
this.current = current; this.current = current;
this.n = n; this.n = n;
this.c = c; this.c = c;
@ -38,22 +32,22 @@ public class WorldObject {
this.B = B; this.B = B;
} }
static final WorldObject generate(String[] args) static final WorldObj generate(String[] args)
{ {
if (args.length == 0) if (args.length == 0) return new WorldObj();
{
return new WorldObject();
}
int[] bounds = regionBounds(new ParsedArgs(args)); int[] bounds = regionBounds(new ParsedArgs(args));
return new WorldObject
return new WorldObj
( (
bounds[2] - bounds[0],//----------------------------width (bounds[2] - bounds[0]) * (bounds[2] - bounds[0]),//width ^ 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 /* for even widths, the math above returns the
* minimum center not the maximum center. So: * minimum center not the maximum center. So:
* *
@ -118,14 +112,12 @@ public class WorldObject {
{ {
int[] bounds = new int[] 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[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 ),
Math.floorDiv( a.center[1] + a.radius, 512 ) Math.floorDiv( a.center[1] + a.radius, 512 )
}; };
//add margins---------------------------------------------------------------
//add margins------------
final int[] edges = new int[4]; final int[] edges = new int[4];
final int[] radii = new int[4]; final int[] radii = new int[4];
@ -143,7 +135,7 @@ public class WorldObject {
radii[2] = Math.abs(a.center[1] - edges[2]); radii[2] = Math.abs(a.center[1] - edges[2]);
radii[3] = Math.abs(a.center[1] - edges[3]); radii[3] = Math.abs(a.center[1] - edges[3]);
//compare to original block radius, if difference is < 4 chunks add a region width //compare to original block radius: if difference < 64 blocks add a region width
if (radii[0] - a.radius < 64) { bounds[0] -= 1; margin[0] = true; } 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[1] - a.radius < 64) { bounds[1] += 1; margin[1] = true; }
if (radii[2] - a.radius < 64) { bounds[2] -= 1; margin[2] = true; } if (radii[2] - a.radius < 64) { bounds[2] -= 1; margin[2] = true; }