2015-02-23 06:29:45 +01:00
|
|
|
package com.intellectualcrafters.plot.util;
|
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
import java.io.File;
|
2015-07-25 20:12:35 +02:00
|
|
|
import java.util.ArrayList;
|
2015-10-07 08:33:33 +02:00
|
|
|
import java.util.HashSet;
|
2015-02-23 06:29:45 +01:00
|
|
|
import java.util.List;
|
2015-09-22 15:23:28 +02:00
|
|
|
import java.util.Set;
|
2015-02-23 06:29:45 +01:00
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
import com.intellectualcrafters.plot.PS;
|
2015-07-30 16:25:16 +02:00
|
|
|
import com.intellectualcrafters.plot.object.ChunkLoc;
|
2015-10-19 08:27:51 +02:00
|
|
|
import com.intellectualcrafters.plot.object.ConsolePlayer;
|
2015-07-30 16:25:16 +02:00
|
|
|
import com.intellectualcrafters.plot.object.Location;
|
|
|
|
import com.intellectualcrafters.plot.object.Plot;
|
|
|
|
import com.intellectualcrafters.plot.object.RegionWrapper;
|
|
|
|
import com.intellectualcrafters.plot.object.RunnableVal;
|
2016-02-10 19:59:51 +01:00
|
|
|
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
|
2015-07-30 16:25:16 +02:00
|
|
|
|
2015-09-13 06:04:31 +02:00
|
|
|
public abstract class ChunkManager {
|
|
|
|
|
2015-02-23 06:29:45 +01:00
|
|
|
public static ChunkManager manager = null;
|
2015-09-13 06:04:31 +02:00
|
|
|
|
|
|
|
public static ChunkLoc getChunkChunk(final Location loc) {
|
2015-02-23 06:29:45 +01:00
|
|
|
final int x = loc.getX() >> 9;
|
|
|
|
final int z = loc.getZ() >> 9;
|
|
|
|
return new ChunkLoc(x, z);
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2016-02-10 19:59:51 +01:00
|
|
|
private static RunnableVal<PlotChunk<?>> CURRENT_FORCE_CHUNK;
|
|
|
|
private static RunnableVal<PlotChunk<?>> CURRENT_ADD_CHUNK;
|
|
|
|
|
|
|
|
public static void setChunkInPlotArea(RunnableVal<PlotChunk<?>> force, RunnableVal<PlotChunk<?>> add, String world, ChunkLoc loc) {
|
|
|
|
if (PS.get().isAugmented(world)) {
|
|
|
|
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
|
|
|
|
PlotChunk<?> chunk = SetQueue.IMP.queue.getChunk(wrap);
|
|
|
|
if (force != null) {
|
|
|
|
force.run(chunk);
|
|
|
|
}
|
|
|
|
manager.regenerateChunk(world, loc);
|
|
|
|
if (add != null) {
|
|
|
|
add.run(chunk);
|
|
|
|
}
|
|
|
|
chunk.addToQueue();
|
|
|
|
chunk.flush(true);
|
|
|
|
} else {
|
|
|
|
CURRENT_FORCE_CHUNK = force;
|
|
|
|
CURRENT_ADD_CHUNK = add;
|
|
|
|
manager.regenerateChunk(world, loc);
|
|
|
|
CURRENT_FORCE_CHUNK = null;
|
|
|
|
CURRENT_ADD_CHUNK = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void preProcessChunk(PlotChunk<?> chunk) {
|
|
|
|
if (CURRENT_FORCE_CHUNK != null) {
|
|
|
|
CURRENT_FORCE_CHUNK.run(chunk);
|
|
|
|
CURRENT_FORCE_CHUNK = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void postProcessChunk(PlotChunk<?> chunk) {
|
|
|
|
if (CURRENT_ADD_CHUNK != null) {
|
|
|
|
CURRENT_ADD_CHUNK.run(chunk);
|
|
|
|
CURRENT_ADD_CHUNK = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 17:25:04 +01:00
|
|
|
public static void largeRegionTask(final String world, final RegionWrapper region, final RunnableVal<ChunkLoc> task, final Runnable whenDone) {
|
2016-02-10 19:59:51 +01:00
|
|
|
TaskManager.runTaskAsync(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
HashSet<ChunkLoc> chunks = new HashSet<>();
|
|
|
|
final Set<ChunkLoc> mcrs = manager.getChunkChunks(world);
|
|
|
|
for (ChunkLoc mcr : mcrs) {
|
|
|
|
int bx = mcr.x << 9;
|
|
|
|
int bz = mcr.z << 9;
|
|
|
|
int tx = bx + 511;
|
|
|
|
int tz = bz + 511;
|
|
|
|
if (bx <= region.maxX && tx >= region.minX && bz <= region.maxZ && tz >= region.minZ) {
|
2016-02-13 12:01:22 +01:00
|
|
|
for (int x = (bx >> 4); x <= (tx >> 4); x++) {
|
2016-02-10 19:59:51 +01:00
|
|
|
int cbx = x << 4;
|
|
|
|
int ctx = cbx + 15;
|
|
|
|
if (cbx <= region.maxX && ctx >= region.minX) {
|
2016-02-13 12:01:22 +01:00
|
|
|
for (int z = (bz >> 4); z <= (tz >> 4); z++) {
|
2016-02-10 19:59:51 +01:00
|
|
|
int cbz = z << 4;
|
|
|
|
int ctz = cbz + 15;
|
|
|
|
if (cbz <= region.maxZ && ctz >= region.minZ) {
|
|
|
|
chunks.add(new ChunkLoc(x, z));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-13 12:01:22 +01:00
|
|
|
TaskManager.objectTask(chunks, new RunnableVal<ChunkLoc>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run(ChunkLoc value) {
|
|
|
|
if (manager.loadChunk(world, value, false)) {
|
|
|
|
task.run(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, whenDone);
|
2016-02-10 19:59:51 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-07-25 20:12:35 +02:00
|
|
|
/**
|
|
|
|
* The int[] will be in the form: [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge] and will represent the bottom and top parts of the chunk
|
|
|
|
* @param pos1
|
|
|
|
* @param pos2
|
|
|
|
* @param task
|
|
|
|
* @param whenDone
|
|
|
|
*/
|
2015-09-13 06:04:31 +02:00
|
|
|
public static void chunkTask(final Location pos1, final Location pos2, final RunnableVal<int[]> task, final Runnable whenDone, final int allocate) {
|
2015-07-25 20:12:35 +02:00
|
|
|
final int p1x = pos1.getX();
|
|
|
|
final int p1z = pos1.getZ();
|
|
|
|
final int p2x = pos2.getX();
|
|
|
|
final int p2z = pos2.getZ();
|
|
|
|
final int bcx = p1x >> 4;
|
|
|
|
final int bcz = p1z >> 4;
|
|
|
|
final int tcx = p2x >> 4;
|
|
|
|
final int tcz = p2z >> 4;
|
|
|
|
final ArrayList<ChunkLoc> chunks = new ArrayList<ChunkLoc>();
|
2015-09-13 06:04:31 +02:00
|
|
|
|
|
|
|
for (int x = bcx; x <= tcx; x++) {
|
|
|
|
for (int z = bcz; z <= tcz; z++) {
|
2015-07-25 20:12:35 +02:00
|
|
|
chunks.add(new ChunkLoc(x, z));
|
|
|
|
}
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
TaskManager.runTask(new Runnable() {
|
2015-07-25 20:12:35 +02:00
|
|
|
@Override
|
2015-09-13 06:04:31 +02:00
|
|
|
public void run() {
|
2015-09-11 12:09:22 +02:00
|
|
|
final long start = System.currentTimeMillis();
|
2015-09-13 06:04:31 +02:00
|
|
|
while ((chunks.size() > 0) && ((System.currentTimeMillis() - start) < allocate)) {
|
2015-09-11 12:09:22 +02:00
|
|
|
final ChunkLoc chunk = chunks.remove(0);
|
2015-07-25 20:12:35 +02:00
|
|
|
task.value = new int[7];
|
|
|
|
task.value[0] = chunk.x;
|
|
|
|
task.value[1] = chunk.z;
|
|
|
|
task.value[2] = task.value[0] << 4;
|
|
|
|
task.value[3] = task.value[1] << 4;
|
|
|
|
task.value[4] = task.value[2] + 15;
|
|
|
|
task.value[5] = task.value[3] + 15;
|
2015-09-13 06:04:31 +02:00
|
|
|
if (task.value[0] == bcx) {
|
2015-09-11 12:09:22 +02:00
|
|
|
task.value[2] = p1x;
|
2015-07-25 20:12:35 +02:00
|
|
|
task.value[6] = 1;
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
if (task.value[0] == tcx) {
|
2015-07-25 20:12:35 +02:00
|
|
|
task.value[4] = p2x;
|
|
|
|
task.value[6] = 1;
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
if (task.value[1] == bcz) {
|
2015-07-25 20:12:35 +02:00
|
|
|
task.value[3] = p1z;
|
|
|
|
task.value[6] = 1;
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
if (task.value[1] == tcz) {
|
2015-07-25 20:12:35 +02:00
|
|
|
task.value[5] = p2z;
|
|
|
|
task.value[6] = 1;
|
|
|
|
}
|
|
|
|
task.run();
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
if (chunks.size() != 0) {
|
2015-07-25 20:12:35 +02:00
|
|
|
TaskManager.runTaskLater(this, 1);
|
2015-09-13 06:04:31 +02:00
|
|
|
} else {
|
2015-07-25 20:12:35 +02:00
|
|
|
TaskManager.runTask(whenDone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-12-14 17:15:30 +01:00
|
|
|
/**
|
|
|
|
* 0 = Entity
|
|
|
|
* 1 = Animal
|
|
|
|
* 2 = Monster
|
|
|
|
* 3 = Mob
|
|
|
|
* 4 = Boat
|
|
|
|
* 5 = Misc
|
|
|
|
* @param plot
|
|
|
|
* @return
|
|
|
|
*/
|
2015-09-11 12:09:22 +02:00
|
|
|
public abstract int[] countEntities(final Plot plot);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-09-11 12:09:22 +02:00
|
|
|
public abstract boolean loadChunk(final String world, final ChunkLoc loc, final boolean force);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-09-27 08:43:11 +02:00
|
|
|
public abstract void unloadChunk(final String world, final ChunkLoc loc, final boolean save, final boolean safe);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
public Set<ChunkLoc> getChunkChunks(final String world) {
|
2015-11-15 03:30:52 +01:00
|
|
|
final File folder = new File(PS.get().IMP.getWorldContainer(), world + File.separator + "region");
|
2015-10-07 08:33:33 +02:00
|
|
|
final File[] regionFiles = folder.listFiles();
|
|
|
|
final HashSet<ChunkLoc> chunks = new HashSet<>();
|
|
|
|
if (regionFiles == null) {
|
2015-11-15 03:30:52 +01:00
|
|
|
throw new RuntimeException("Could not find worlds folder: " + folder + " ? (no read access?)");
|
2015-10-07 08:33:33 +02:00
|
|
|
}
|
|
|
|
for (final File file : regionFiles) {
|
|
|
|
final String name = file.getName();
|
|
|
|
if (name.endsWith("mca")) {
|
|
|
|
final String[] split = name.split("\\.");
|
|
|
|
try {
|
|
|
|
final int x = Integer.parseInt(split[1]);
|
|
|
|
final int z = Integer.parseInt(split[2]);
|
|
|
|
final ChunkLoc loc = new ChunkLoc(x, z);
|
|
|
|
chunks.add(loc);
|
|
|
|
} catch (final Exception e) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return chunks;
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-09-11 12:09:22 +02:00
|
|
|
public abstract void regenerateChunk(final String world, final ChunkLoc loc);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
public void deleteRegionFiles(String world, List<ChunkLoc> chunks) {
|
|
|
|
deleteRegionFiles(world, chunks, null);
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
public void deleteRegionFiles(final String world, final List<ChunkLoc> chunks, final Runnable whenDone) {
|
|
|
|
TaskManager.runTaskAsync(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
for (final ChunkLoc loc : chunks) {
|
|
|
|
final String directory = world + File.separator + "region" + File.separator + "r." + loc.x + "." + loc.z + ".mca";
|
|
|
|
final File file = new File(PS.get().IMP.getWorldContainer(), directory);
|
2015-10-19 08:27:51 +02:00
|
|
|
ConsolePlayer.getConsole().sendMessage("&6 - Deleting file: " + file.getName() + " (max 1024 chunks)");
|
2015-10-07 08:33:33 +02:00
|
|
|
if (file.exists()) {
|
|
|
|
file.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (whenDone != null) {
|
|
|
|
whenDone.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-10-07 08:33:33 +02:00
|
|
|
public Plot hasPlot(String world, ChunkLoc chunk) {
|
|
|
|
final int x1 = chunk.x << 4;
|
|
|
|
final int z1 = chunk.z << 4;
|
|
|
|
final int x2 = x1 + 15;
|
|
|
|
final int z2 = z1 + 15;
|
|
|
|
final Location bot = new Location(world, x1, 0, z1);
|
2016-02-10 19:59:51 +01:00
|
|
|
Plot plot = bot.getOwnedPlotAbs();
|
|
|
|
if (plot != null) {
|
2015-10-07 08:33:33 +02:00
|
|
|
return plot;
|
|
|
|
}
|
|
|
|
final Location top = new Location(world, x2, 0, z2);
|
2016-02-10 19:59:51 +01:00
|
|
|
plot = top.getOwnedPlotAbs();
|
|
|
|
if (plot != null) {
|
2015-10-07 08:33:33 +02:00
|
|
|
return plot;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-09-22 15:23:28 +02:00
|
|
|
/**
|
|
|
|
* Copy a region to a new location (in the same world)
|
|
|
|
*/
|
2015-02-23 06:29:45 +01:00
|
|
|
public abstract boolean copyRegion(final Location pos1, final Location pos2, final Location newPos, final Runnable whenDone);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-07-25 16:43:19 +02:00
|
|
|
/**
|
|
|
|
* Assumptions:<br>
|
|
|
|
* - pos1 and pos2 are in the same plot<br>
|
|
|
|
* It can be harmful to the world if parameters outside this scope are provided
|
|
|
|
* @param pos1
|
|
|
|
* @param pos2
|
|
|
|
* @param whenDone
|
|
|
|
* @return
|
|
|
|
*/
|
2016-02-10 19:59:51 +01:00
|
|
|
public abstract boolean regenerateRegion(final Location pos1, final Location pos2, boolean ignoreAugment, final Runnable whenDone);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-08-04 14:21:12 +02:00
|
|
|
public abstract void clearAllEntities(final Location pos1, final Location pos2);
|
2015-09-13 06:04:31 +02:00
|
|
|
|
2015-09-22 15:23:28 +02:00
|
|
|
public abstract void swap(final Location bot1, final Location top1, final Location bot2, final Location top2, Runnable whenDone);
|
2015-02-23 06:29:45 +01:00
|
|
|
}
|