package com.boydti.fawe.regions.general.plot; import com.boydti.fawe.Fawe; import com.boydti.fawe.example.NullFaweChunk; import com.boydti.fawe.jnbt.anvil.MCAChunk; import com.boydti.fawe.jnbt.anvil.MCAQueue; import com.boydti.fawe.jnbt.anvil.MCAWriter; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.SetQueue; import com.intellectualcrafters.configuration.ConfigurationSection; import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.commands.CommandCategory; import com.intellectualcrafters.plot.commands.MainCommand; import com.intellectualcrafters.plot.commands.RequiredType; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.SQLManager; import com.intellectualcrafters.plot.generator.HybridPlotWorld; import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.RunnableVal2; import com.intellectualcrafters.plot.object.RunnableVal3; import com.intellectualcrafters.plot.object.SetupObject; import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.WorldUtil; import com.plotsquared.general.commands.Command; import com.plotsquared.general.commands.CommandDeclaration; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; @CommandDeclaration( command = "moveto512", permission = "plots.moveto512", category = CommandCategory.DEBUG, requiredType = RequiredType.CONSOLE, description = "Move plots to a 512 sized region", usage = "/plots moveto512 [world]" ) public class MoveTo512 extends Command { public MoveTo512() { super(MainCommand.getInstance(), true); } private MCAChunk emptyPlot(MCAChunk chunk, HybridPlotWorld hpw) { int maxLayer = (hpw.PLOT_HEIGHT) >> 4; for (int i = maxLayer + 1; i < chunk.ids.length; i++) { chunk.ids[i] = null; chunk.data[i] = null; } for (int layer = 0; layer <= maxLayer; layer++) { byte[] ids = chunk.ids[layer]; if (ids == null) { ids = chunk.ids[layer] = new byte[4096]; chunk.data[layer] = new byte[2048]; chunk.skyLight[layer] = new byte[2048]; chunk.blockLight[layer] = new byte[2048]; } else { Arrays.fill(ids, (byte) 0); Arrays.fill(chunk.data[layer], (byte) 0); Arrays.fill(chunk.skyLight[layer], (byte) 0); Arrays.fill(chunk.blockLight[layer], (byte) 0); } if (layer == maxLayer) { int yMax = hpw.PLOT_HEIGHT & 15; for (int y = yMax + 1; y < 15; y++) { Arrays.fill(chunk.skyLight[layer], y << 7, (y << 7) + 128, (byte) 255); } if (layer == 0) { Arrays.fill(ids, 0, 256, (byte) 7); for (int y = 1; y < yMax; y++) { int y8 = y << 8; Arrays.fill(ids, y8, y8 + 256, (byte) 3); } } else { for (int y = 0; y < yMax; y++) { int y8 = y << 8; Arrays.fill(ids, y8, y8 + 256, (byte) 3); } } int yMax15 = yMax & 15; int yMax158 = yMax15 << 8; Arrays.fill(ids, yMax158, yMax158 + 256, (byte) 2); if (yMax != 15) { Arrays.fill(ids, yMax158 + 256, 4096, (byte) 0); } } else if (layer == 0){ Arrays.fill(ids, 256, 4096, (byte) 3); Arrays.fill(ids, 0, 256, (byte) 7); } else { Arrays.fill(ids, (byte) 3); } } return chunk; } private MCAChunk emptyRoad(MCAChunk chunk, HybridPlotWorld hpw) { int maxLayer = (hpw.ROAD_HEIGHT) >> 4; for (int i = maxLayer + 1; i < chunk.ids.length; i++) { chunk.ids[i] = null; chunk.data[i] = null; } for (int layer = 0; layer <= maxLayer; layer++) { byte[] ids = chunk.ids[layer]; if (ids == null) { ids = chunk.ids[layer] = new byte[4096]; chunk.data[layer] = new byte[2048]; chunk.skyLight[layer] = new byte[2048]; chunk.blockLight[layer] = new byte[2048]; } else { Arrays.fill(ids, (byte) 0); Arrays.fill(chunk.data[layer], (byte) 0); Arrays.fill(chunk.skyLight[layer], (byte) 0); Arrays.fill(chunk.blockLight[layer], (byte) 0); } if (layer == maxLayer) { int yMax = hpw.ROAD_HEIGHT & 15; for (int y = yMax + 1; y < 15; y++) { Arrays.fill(chunk.skyLight[layer], y << 7, (y << 7) + 128, (byte) 255); } if (layer == 0) { Arrays.fill(ids, 0, 256, (byte) 7); for (int y = 1; y <= yMax; y++) { int y8 = y << 8; Arrays.fill(ids, y8, y8 + 256, (byte) hpw.ROAD_BLOCK.id); } } else { for (int y = 0; y <= yMax; y++) { int y8 = y << 8; Arrays.fill(ids, y8, y8 + 256, (byte) hpw.ROAD_BLOCK.id); } } if (yMax != 15) { int yMax15 = yMax & 15; int yMax158 = yMax15 << 8; Arrays.fill(ids, yMax158 + 256, 4096, (byte) 0); } } else if (layer == 0){ Arrays.fill(ids, 256, 4096, (byte) hpw.ROAD_BLOCK.id); Arrays.fill(ids, 0, 256, (byte) 7); } else { Arrays.fill(ids, (byte) hpw.ROAD_BLOCK.id); } } return chunk; } @Override public void execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { checkTrue(args.length == 1, C.COMMAND_SYNTAX, getUsage()); PlotArea area = player.getPlotAreaAbs(); check(area, C.COMMAND_SYNTAX, getUsage()); checkTrue(area instanceof HybridPlotWorld, C.NOT_VALID_HYBRID_PLOT_WORLD); WorldUtil.IMP.saveWorld(area.worldname); FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(area.worldname, true, false); MCAQueue queueFrom = new MCAQueue(area.worldname, defaultQueue.getSaveFolder(), defaultQueue.hasSky()); String world = args[0]; File folder = new File(PS.imp().getWorldContainer(), world + File.separator + "region"); checkTrue(!folder.exists(), C.SETUP_WORLD_TAKEN, world); HybridPlotWorld hpw = (HybridPlotWorld) area; int minRoad = 7; int pLen = Math.min(hpw.PLOT_WIDTH, 512 - minRoad); int roadWidth = 512 - pLen; int roadPosLower; if ((roadWidth & 1) == 0) { roadPosLower = (short) (Math.floor(roadWidth / 2) - 1); } else { roadPosLower = (short) Math.floor(roadWidth / 2); } int roadPosUpper = 512 - roadWidth + roadPosLower + 1; final ThreadLocal roadCache = new ThreadLocal() { @Override protected boolean[] initialValue() { return new boolean[64]; } }; MCAChunk reference = new MCAChunk(null, 0, 0); { reference.fillCuboid(0, 15, 0, 0, 0, 15, 7, (byte) 0); reference.fillCuboid(0, 15, 1, hpw.PLOT_HEIGHT - 1, 0, 15, 3, (byte) 0); reference.fillCuboid(0, 15, hpw.PLOT_HEIGHT, hpw.PLOT_HEIGHT, 0, 15, 2, (byte) 0); } Map rawPlots = area.getPlotsRaw(); ArrayList plots = new ArrayList(rawPlots.values()); int size = plots.size(); PlotId nextId = new PlotId(0, 0); long start = System.currentTimeMillis(); int percent = 0; for (Plot plot : plots) { Fawe.debug(((percent += 100) / size) + "% complete!"); Location bot = plot.getBottomAbs(); Location top = plot.getTopAbs(); int oX = roadPosLower - bot.getX() + 1; int oZ = roadPosLower - bot.getZ() + 1; { // Move PlotId id = plot.getId(); Fawe.debug("Moving " + plot.getId() + " to " + nextId); id.x = nextId.x; id.y = nextId.y; id.recalculateHash(); } MCAWriter writer = new MCAWriter(512, 512, folder) { @Override public boolean shouldWrite(int chunkX, int chunkZ) { int bx = chunkX << 4; int bz = chunkZ << 4; int tx = bx + 15; int tz = bz + 15; return !(tx < roadPosLower || tz < roadPosLower || bx > roadPosUpper || bz > roadPosUpper); } @Override public MCAChunk write(MCAChunk newChunk, int bx, int tx, int bz, int tz) { Arrays.fill(newChunk.biomes, (byte) 4); if (!newChunk.tiles.isEmpty()) newChunk.tiles.clear(); if (tx < roadPosLower || tz < roadPosLower || bx > roadPosUpper || bz > roadPosUpper) { return emptyRoad(newChunk, hpw); } else { boolean partRoad = (bx <= roadPosLower || bz <= roadPosLower || tx >= roadPosUpper || tz >= roadPosUpper); boolean changed = false; emptyPlot(newChunk, hpw); int obx = bx - oX; int obz = bz - oZ; int otx = tx - oX; int otz = tz - oZ; int otherBCX = (obx) >> 4; int otherBCZ = (obz) >> 4; int otherTCX = (otx) >> 4; int otherTCZ = (otz) >> 4; int cx = newChunk.getX(); int cz = newChunk.getZ(); int cbx = (cx << 4) - oX; int cbz = (cz << 4) - oZ; for (int otherCZ = otherBCZ; otherCZ <= otherTCZ; otherCZ++) { for (int otherCX = otherBCX; otherCX <= otherTCX; otherCX++) { FaweChunk chunk; synchronized (queueFrom) { chunk = queueFrom.getFaweChunk(otherCX, otherCZ); } if (!(chunk instanceof NullFaweChunk)) { changed = true; MCAChunk other = (MCAChunk) chunk; int ocbx = otherCX << 4; int ocbz = otherCZ << 4; int octx = ocbx + 15; int octz = ocbz + 15; int offsetY = 0; int minX = obx > ocbx ? (obx - ocbx) & 15 : 0; int maxX = otx < octx ? (otx - ocbx) : 15; int minZ = obz > ocbz ? (obz - ocbz) & 15 : 0; int maxZ = otz < octz ? (otz - ocbz) : 15; int offsetX = ocbx - cbx; int offsetZ = ocbz - cbz; newChunk.copyFrom(other, minX, maxX, 0, 255, minZ, maxZ, offsetX, offsetY, offsetZ); } } } if (!changed || reference.idsEqual(newChunk, false)) { return null; } if (partRoad) { boolean[] rwp = roadCache.get(); for (short i = 0; i < 16; i++) { int vx = bx + i; int vz = bz + i; rwp[i] = vx < roadPosLower || vx > roadPosUpper; rwp[i + 32] = vx == roadPosLower || vx == roadPosUpper; rwp[i + 16] = vz < roadPosLower || vz > roadPosUpper; rwp[i + 48] = vz == roadPosLower || vz == roadPosUpper; } for (int z = 0; z < 16; z++) { final boolean rwpz16 = rwp[z + 16]; final boolean rwpz48 = rwp[z + 48]; for (int x = 0; x < 16; x++) { if (rwpz16 || rwp[x]) { for (int y = 1; y <= hpw.ROAD_HEIGHT; y++) { newChunk.setBlock(x, y, z, hpw.ROAD_BLOCK.id, hpw.ROAD_BLOCK.data); } for (int y = hpw.ROAD_HEIGHT + 1; y < 256; y++) { newChunk.setBlock(x, y, z, 0, 0); } } else if (rwpz48 || rwp[x + 32]) { for (int y = 1; y <= hpw.WALL_HEIGHT; y++) { newChunk.setBlock(x, y, z, hpw.WALL_FILLING.id, hpw.WALL_FILLING.data); } for (int y = hpw.WALL_HEIGHT + 2; y < 256; y++) { newChunk.setBlock(x, y, z, 0, 0); } newChunk.setBlock(x, hpw.WALL_HEIGHT + 1, z, hpw.CLAIMED_WALL_BLOCK.id, hpw.CLAIMED_WALL_BLOCK.data); } } } } } return newChunk; } }; writer.setMCAOffset(nextId.x - 1, nextId.y - 1); try { writer.generate(); System.gc(); } catch (IOException e) { e.printStackTrace(); return; } queueFrom.clear(); nextId = nextId.getNextId(1); } Fawe.debug("Anvil copy completed in " + ((System.currentTimeMillis() - start) / 1000d) + "s"); Fawe.debug("Updating database, please wait..."); rawPlots.clear(); for (Plot plot : plots) { rawPlots.put(plot.getId(), plot); DBFunc.movePlot(plot, plot); } SQLManager db = (SQLManager) DBFunc.dbManager; db.addNotifyTask(new Runnable() { @Override public void run() { Fawe.debug("Instructions"); Fawe.debug(" - Stop the server"); Fawe.debug(" - Rename the folder for the new world to the current world"); Fawe.debug(" - Change the plot size to " + pLen); Fawe.debug(" - Change the road size to " + roadWidth); Fawe.debug(" - Start the server"); } }); ConfigurationSection section = PS.get().worlds.getConfigurationSection("worlds." + world); if (section == null) section = PS.get().worlds.createSection("worlds." + world); area.saveConfiguration(section); section.set("plot.size", pLen); section.set("road.width", roadWidth); try { PS.get().worlds.save(PS.get().worldsFile); } catch (IOException e) { e.printStackTrace(); } final SetupObject object = new SetupObject(); object.world = world; object.plotManager = PS.imp().getPluginName(); object.setupGenerator = PS.imp().getPluginName(); String created = SetupUtils.manager.setupWorld(object); } }