package com.intellectualcrafters.plot.generator;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.commands.Template;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.FileBytes;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashSet;
public class HybridPlotManager extends ClassicPlotManager {
public static boolean REGENERATIVE_CLEAR = true;
@Override
public void exportTemplate(PlotArea plotArea) throws IOException {
HashSet<FileBytes> files = new HashSet<>(
Collections.singletonList(new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml", Template.getBytes(plotArea))));
String dir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plotArea.worldname + File.separator;
String newDir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + "__TEMP_DIR__" + File.separator;
try {
File sideroad = MainUtil.getFile(PS.get().IMP.getDirectory(), dir + "sideroad.schematic");
if (sideroad.exists()) {
files.add(new FileBytes(newDir + "sideroad.schematic", Files.readAllBytes(sideroad.toPath())));
}
File intersection = MainUtil.getFile(PS.get().IMP.getDirectory(), "intersection.schematic");
if (intersection.exists()) {
files.add(new FileBytes(newDir + "intersection.schematic", Files.readAllBytes(intersection.toPath())));
}
File plot = MainUtil.getFile(PS.get().IMP.getDirectory(), dir + "plot.schematic");
if (plot.exists()) {
files.add(new FileBytes(newDir + "plot.schematic", Files.readAllBytes(plot.toPath())));
}
} catch (IOException e) {
e.printStackTrace();
}
Template.zipAll(plotArea.worldname, files);
}
@Override
public boolean createRoadEast(PlotArea plotArea, Plot plot) {
super.createRoadEast(plotArea, plot);
HybridPlotWorld hpw = (HybridPlotWorld) plotArea;
PlotId id = plot.getId();
PlotId id2 = new PlotId(id.x + 1, id.y);
Location bot = getPlotBottomLocAbs(hpw, id2);
Location top = getPlotTopLocAbs(hpw, id);
Location pos1 = new Location(plotArea.worldname, top.getX() + 1, 0, bot.getZ() - 1);
Location pos2 = new Location(plotArea.worldname, bot.getX(), Math.min(getWorldHeight(), 255), top.getZ() + 1);
MainUtil.resetBiome(plotArea, pos1, pos2);
if (!hpw.ROAD_SCHEMATIC_ENABLED) {
return true;
}
LocalBlockQueue queue = hpw.getQueue(false);
createSchemAbs(hpw, queue, pos1, pos2, true);
queue.enqueue();
return true;
}
private void createSchemAbs(HybridPlotWorld hpw, LocalBlockQueue queue, Location pos1, Location pos2, boolean clear) {
int size = hpw.SIZE;
int minY = Math.min(hpw.PLOT_HEIGHT, hpw.ROAD_HEIGHT);
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
short absX = (short) ((x - hpw.ROAD_OFFSET_X) % size);
if (absX < 0) {
absX += size;
}
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
short absZ = (short) ((z - hpw.ROAD_OFFSET_Z) % size);
if (absZ < 0) {
absZ += size;
}
char[] blocks = hpw.G_SCH.get(MathMan.pair(absX, absZ));
if (blocks != null) {
for (int y = 0; y < blocks.length; y++) {
PlotBlock block = PlotBlock.get(blocks[y]);
if (block != null) {
queue.setBlock(x, minY + y, z, block);
}
}
}
}
}
}
@Override
public boolean createRoadSouth(PlotArea plotArea, Plot plot) {
super.createRoadSouth(plotArea, plot);
HybridPlotWorld hpw = (HybridPlotWorld) plotArea;
PlotId id = plot.getId();
PlotId id2 = new PlotId(id.x, id.y + 1);
Location bot = getPlotBottomLocAbs(hpw, id2);
Location top = getPlotTopLocAbs(hpw, id);
Location pos1 = new Location(plotArea.worldname, bot.getX() - 1, 0, top.getZ() + 1);
Location pos2 = new Location(plotArea.worldname, top.getX() + 1, Math.min(getWorldHeight(), 255), bot.getZ());
MainUtil.resetBiome(plotArea, pos1, pos2);
if (!hpw.ROAD_SCHEMATIC_ENABLED) {
return true;
}
LocalBlockQueue queue = hpw.getQueue(false);
createSchemAbs(hpw, queue, pos1, pos2, true);
queue.enqueue();
return true;
}
@Override
public boolean createRoadSouthEast(PlotArea plotArea, Plot plot) {
super.createRoadSouthEast(plotArea, plot);
HybridPlotWorld hpw = (HybridPlotWorld) plotArea;
PlotId id = plot.getId();
PlotId id2 = new PlotId(id.x + 1, id.y + 1);
Location pos1 = getPlotTopLocAbs(hpw, id).add(1, 0, 1);
Location pos2 = getPlotBottomLocAbs(hpw, id2);
pos1.setY(0);
pos2.setY(Math.min(getWorldHeight(), 255));
LocalBlockQueue queue = hpw.getQueue(false);
createSchemAbs(hpw, queue, pos1, pos2, true);
if (hpw.ROAD_SCHEMATIC_ENABLED) {
createSchemAbs(hpw, queue, pos1, pos2, true);
}
queue.enqueue();
return true;
}
/**
* <p>Clearing the plot needs to only consider removing the blocks - This implementation has used the setCuboidAsync
* function, as it is fast, and uses NMS code - It also makes use of the fact that deleting chunks is a lot faster
* than block updates This code is very messy, but you don't need to do something quite as complex unless you happen
* to have 512x512 sized plots. </p>
*/
@Override
public boolean clearPlot(final PlotArea plotArea, Plot plot, final Runnable whenDone) {
final String world = plotArea.worldname;
final HybridPlotWorld dpw = (HybridPlotWorld) plotArea;
Location pos1 = plot.getBottomAbs();
Location pos2 = plot.getExtendedTopAbs();
// If augmented
final boolean canRegen = (plotArea.TYPE == 0) && (plotArea.TERRAIN == 0) && REGENERATIVE_CLEAR;
// The component blocks
final PlotBlock[] plotfloor = dpw.TOP_BLOCK;
final PlotBlock[] filling = dpw.MAIN_BLOCK;
final PlotBlock bedrock;
if (dpw.PLOT_BEDROCK) {
bedrock = PlotBlock.get((short) 7, (byte) 0);
} else {
bedrock = PlotBlock.get((short) 0, (byte) 0);
}
final PlotBlock air = PlotBlock.get((short) 0, (byte) 0);
final String biome = dpw.PLOT_BIOME;
final LocalBlockQueue queue = plotArea.getQueue(false);
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
// If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk
if (canRegen && (value[6] == 0)) {
queue.regenChunk(value[0], value[1]);
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Otherwise we need to set each component, as we don't want to regenerate the road or other plots that share the same chunk //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the biome
MainUtil.setBiome(world, value[2], value[3], value[4], value[5], biome);
// These two locations are for each component (e.g. bedrock, main block, floor, air)
Location bot = new Location(world, value[2], 0, value[3]);
Location top = new Location(world, value[4], 1, value[5]);
queue.setCuboid(bot, top, bedrock);
// Each component has a different layer
bot.setY(1);
top.setY(dpw.PLOT_HEIGHT);
queue.setCuboid(bot, top, filling);
bot.setY(dpw.PLOT_HEIGHT);
top.setY(dpw.PLOT_HEIGHT + 1);
queue.setCuboid(bot, top, plotfloor);
bot.setY(dpw.PLOT_HEIGHT + 1);
top.setY(getWorldHeight());
queue.setCuboid(bot, top, air);
// And finally set the schematic, the y value is unimportant for this function
pastePlotSchematic(dpw, queue, bot, top);
}
}, new Runnable() {
@Override
public void run() {
queue.enqueue();
// And notify whatever called this when plot clearing is done
GlobalBlockQueue.IMP.addTask(whenDone);
}
}, 10);
return true;
}
public void pastePlotSchematic(HybridPlotWorld plotWorld, LocalBlockQueue queue, Location l1, Location l2) {
if (!plotWorld.PLOT_SCHEMATIC) {
return;
}
createSchemAbs(plotWorld, queue, l1, l2, false);
}
}