207 lines
7.0 KiB
Java
207 lines
7.0 KiB
Java
package com.boydti.fawe.regions.general.plot;
|
|
|
|
import com.boydti.fawe.jnbt.anvil.MCAChunk;
|
|
import com.boydti.fawe.jnbt.anvil.MCAFile;
|
|
import com.boydti.fawe.jnbt.anvil.MCAFilter;
|
|
import com.boydti.fawe.jnbt.anvil.MCAQueue;
|
|
import com.boydti.fawe.object.FaweQueue;
|
|
import com.boydti.fawe.util.MainUtil;
|
|
import com.boydti.fawe.util.MathMan;
|
|
import com.boydti.fawe.util.SetQueue;
|
|
import com.intellectualcrafters.plot.PS;
|
|
import com.intellectualcrafters.plot.object.ChunkLoc;
|
|
import com.intellectualcrafters.plot.object.Location;
|
|
import com.intellectualcrafters.plot.object.Plot;
|
|
import com.intellectualcrafters.plot.object.PlotArea;
|
|
import com.intellectualcrafters.plot.object.PlotPlayer;
|
|
import com.intellectualcrafters.plot.util.expiry.ExpireManager;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
public class PlotTrim {
|
|
private final MCAQueue queue;
|
|
private final PlotArea area;
|
|
private final PlotPlayer player;
|
|
private final MCAQueue originalQueue;
|
|
private final File root;
|
|
private final File originalRoot;
|
|
private byte[][] ids;
|
|
private boolean deleteUnowned = true;
|
|
|
|
public PlotTrim(PlotPlayer player, PlotArea area, String worldName, boolean deleteUnowned) {
|
|
FaweQueue tmpQueue = SetQueue.IMP.getNewQueue(worldName, true, false);
|
|
File saveFolder = tmpQueue.getSaveFolder();
|
|
this.root = new File(saveFolder.getParentFile().getParentFile(), worldName + "-Copy" + File.separator + "region");
|
|
this.originalRoot = saveFolder;
|
|
this.originalQueue = new MCAQueue(worldName, originalRoot, true);
|
|
this.queue = new MCAQueue(worldName + "-Copy", root, true);
|
|
this.area = area;
|
|
this.player = player;
|
|
this.deleteUnowned = deleteUnowned;
|
|
}
|
|
|
|
public void setChunk(byte[][] ids) {
|
|
checkNotNull(ids);
|
|
this.ids = ids;
|
|
}
|
|
|
|
public void setChunk(int x, int z) {
|
|
this.ids = ((MCAChunk) originalQueue.getFaweChunk(x, z)).ids;
|
|
}
|
|
|
|
private Map<Long, Object> chunks = new ConcurrentHashMap<>();
|
|
private Object PRESENT = new Object();
|
|
|
|
private void removeChunks(Plot plot) {
|
|
Location pos1 = plot.getBottom();
|
|
Location pos2 = plot.getTop();
|
|
int ccx1 = pos1.getX() >> 4;
|
|
int ccz1 = pos1.getZ() >> 4;
|
|
int ccx2 = pos2.getX() >> 4;
|
|
int ccz2 = pos2.getZ() >> 4;
|
|
for (int x = ccx1; x <= ccx2; x++) {
|
|
for (int z = ccz1; z <= ccz2; z++) {
|
|
long pair = MathMan.pairInt(x, z);
|
|
chunks.remove(pair);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void run() {
|
|
final Set<ChunkLoc> mcas = new HashSet<>();
|
|
if (deleteUnowned && area != null) {
|
|
originalQueue.filterWorld(new MCAFilter() {
|
|
@Override
|
|
public boolean appliesFile(int mcaX, int mcaZ) {
|
|
mcas.add(new ChunkLoc(mcaX, mcaZ));
|
|
return false;
|
|
}
|
|
});
|
|
ArrayList<Plot> plots = new ArrayList<>();
|
|
plots.addAll(PS.get().getPlots(area));
|
|
if (ExpireManager.IMP != null) {
|
|
plots.removeAll(ExpireManager.IMP.getPendingExpired());
|
|
}
|
|
for (Plot plot : plots) {
|
|
Location pos1 = plot.getBottom();
|
|
Location pos2 = plot.getTop();
|
|
int ccx1 = pos1.getX() >> 9;
|
|
int ccz1 = pos1.getZ() >> 9;
|
|
int ccx2 = pos2.getX() >> 9;
|
|
int ccz2 = pos2.getZ() >> 9;
|
|
for (int x = ccx1; x <= ccx2; x++) {
|
|
for (int z = ccz1; z <= ccz2; z++) {
|
|
ChunkLoc loc = new ChunkLoc(x, z);
|
|
mcas.remove(loc);
|
|
}
|
|
}
|
|
}
|
|
for (ChunkLoc mca : mcas) {
|
|
int bx = mca.x << 5;
|
|
int bz = mca.z << 5;
|
|
for (int x = 0; x < 32; x++) {
|
|
for (int z = 0; z < 32; z++) {
|
|
long pair = MathMan.pairInt(bx + x, bz + z);
|
|
chunks.put(pair, PRESENT);
|
|
}
|
|
}
|
|
}
|
|
for (Plot plot : plots) {
|
|
removeChunks(plot);
|
|
}
|
|
}
|
|
originalQueue.filterWorld(new MCAFilter() {
|
|
@Override
|
|
public boolean appliesFile(int mcaX, int mcaZ) {
|
|
ChunkLoc loc = new ChunkLoc(mcaX, mcaZ);
|
|
if (mcas.contains(loc)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public MCAFile applyFile(MCAFile mca) {
|
|
int mcaX = mca.getX();
|
|
int mcaZ = mca.getZ();
|
|
ChunkLoc loc = new ChunkLoc(mcaX, mcaZ);
|
|
if (mcas.contains(loc)) {
|
|
player.sendMessage("Delete MCA " + mca);
|
|
mca.setDeleted(true);
|
|
return null;
|
|
}
|
|
try {
|
|
File copy = new File(root, mca.getFile().getName());
|
|
if (!copy.exists()) {
|
|
copy = MainUtil.copyFile(mca.getFile(), copy);
|
|
player.sendMessage("Filter copy -> " + copy);
|
|
} else {
|
|
player.sendMessage("Filter existing: " + mcaX + "," + mcaZ);
|
|
}
|
|
return new MCAFile(mca.getParent(), copy);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean appliesChunk(int cx, int cz) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public MCAChunk applyChunk(MCAChunk chunk, Object ignore) {
|
|
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
|
if (chunks.containsKey(pair)) {
|
|
chunk.setDeleted(true);
|
|
return null;
|
|
}
|
|
if (ids != null) {
|
|
for (int i = 0; i < ids.length; i++) {
|
|
if (!isEqual(ids[i], chunk.ids[i])) {
|
|
return null;
|
|
}
|
|
}
|
|
chunk.setDeleted(true);
|
|
}
|
|
return null;
|
|
}
|
|
});
|
|
player.sendMessage("Done!");
|
|
}
|
|
|
|
private int count = 0;
|
|
|
|
private boolean isEqual(byte[] a, byte[] b) {
|
|
if (a == b) {
|
|
return true;
|
|
}
|
|
if (a != null) {
|
|
if (b != null) {
|
|
return Arrays.equals(a, b);
|
|
}
|
|
return isEmpty(a);
|
|
}
|
|
return isEmpty(b);
|
|
}
|
|
|
|
private boolean isEmpty(byte[] a) {
|
|
for (byte b : a) {
|
|
if (b != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|