Add command to delete unoccupied chunks

This commit is contained in:
Jesse Boyd 2017-04-10 23:42:51 +10:00
parent e6edcd0739
commit ecedd05651
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
2 changed files with 49 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.jnbt.anvil.MCAChunk; import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.jnbt.anvil.MCAClipboard; import com.boydti.fawe.jnbt.anvil.MCAClipboard;
import com.boydti.fawe.jnbt.anvil.MCAFile;
import com.boydti.fawe.jnbt.anvil.MCAFilter; import com.boydti.fawe.jnbt.anvil.MCAFilter;
import com.boydti.fawe.jnbt.anvil.MCAFilterCounter; import com.boydti.fawe.jnbt.anvil.MCAFilterCounter;
import com.boydti.fawe.jnbt.anvil.MCAQueue; import com.boydti.fawe.jnbt.anvil.MCAQueue;
@ -35,6 +36,9 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -89,6 +93,45 @@ public class AnvilCommands {
player.print(BBC.getPrefix() + BBC.VISITOR_BLOCK.format(counter.getTotal())); player.print(BBC.getPrefix() + BBC.VISITOR_BLOCK.format(counter.getTotal()));
} }
@Command(
aliases = {"deleteallold"},
usage = "<folder> <age-ticks> [file-age=60000]",
desc = "Delete all chunks which haven't been occupied for `age-ticks` and have been accessed since `file-age` (ms) after creation",
min = 2,
max = 3
)
@CommandPermissions("worldedit.anvil.deleteallold")
public void deleteAllOld(Player player, EditSession editSession, String folder, int inhabitedTicks, @Optional("60000") int fileAgeMillis) throws WorldEditException {
FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(folder, true, false);
MCAQueue queue = new MCAQueue(folder, defaultQueue.getSaveFolder(), defaultQueue.hasSky());
MCAFilterCounter result = queue.filterWorld(new MCAFilterCounter() {
@Override
public MCAFile applyFile(MCAFile mca) {
File file = mca.getFile();
try {
BasicFileAttributes attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
long creation = attr.creationTime().toMillis();
long modified = attr.lastModifiedTime().toMillis();
if (modified - creation < fileAgeMillis) {
mca.setDeleted(true);
get().add(512 * 512 * 256);
}
} catch (IOException | UnsupportedOperationException ignore) {}
return mca;
}
@Override
public MCAChunk applyChunk(MCAChunk chunk, MutableLong count) {
if (chunk.getInhabitedTime() <= inhabitedTicks) {
count.add(16 * 16 * 256);
chunk.setDeleted(true);
}
return null;
}
});
player.print(BBC.getPrefix() + BBC.VISITOR_BLOCK.format(result.getTotal()));
}
@Command( @Command(
aliases = {"replaceallpattern", "reap", "repallpat"}, aliases = {"replaceallpattern", "reap", "repallpat"},
usage = "<folder> [from-block] <to-pattern>", usage = "<folder> [from-block] <to-pattern>",

View File

@ -384,6 +384,7 @@ public class MCAFile {
} }
public void close(ForkJoinPool pool) { public void close(ForkJoinPool pool) {
if (raf == null) return;
synchronized (raf) { synchronized (raf) {
if (raf != null) { if (raf != null) {
flush(pool); flush(pool);
@ -411,7 +412,7 @@ public class MCAFile {
final Int2ObjectOpenHashMap<byte[]> append = new Int2ObjectOpenHashMap<>(); final Int2ObjectOpenHashMap<byte[]> append = new Int2ObjectOpenHashMap<>();
boolean modified = false; boolean modified = false;
for (MCAChunk chunk : getCachedChunks()) { for (MCAChunk chunk : getCachedChunks()) {
if (chunk.isModified()) { if (chunk.isModified() || chunk.isDeleted()) {
modified = true; modified = true;
if (!chunk.isDeleted()) { if (!chunk.isDeleted()) {
pool.submit(new Runnable() { pool.submit(new Runnable() {
@ -468,8 +469,8 @@ public class MCAFile {
int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31)); int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31));
byte[] newBytes = relocate.get(pair); byte[] newBytes = relocate.get(pair);
if (newBytes == null) { if (newBytes == null) {
MCAChunk cached = getCachedChunk(cx, cz);
if (offset == start) { if (offset == start) {
MCAChunk cached = getCachedChunk(cx, cz);
if (cached == null || !cached.isModified()) { if (cached == null || !cached.isModified()) {
writeHeader(raf, cx, cz, start >> 12, size >> 12, true); writeHeader(raf, cx, cz, start >> 12, size >> 12, true);
start += size; start += size;
@ -481,7 +482,9 @@ public class MCAFile {
} else { } else {
newBytes = compressedMap.get(pair); newBytes = compressedMap.get(pair);
if (newBytes == null) { if (newBytes == null) {
newBytes = getChunkCompressedBytes(getOffset(cx, cz)); if (cached == null || !cached.isDeleted()) {
newBytes = getChunkCompressedBytes(getOffset(cx, cz));
}
} }
} }
} }