Added /listchunks and /delchunks.

This commit is contained in:
sk89q 2010-10-28 10:27:30 -07:00
parent c525ebe760
commit 6173c6c78e
5 changed files with 178 additions and 2 deletions

View File

@ -92,6 +92,9 @@ public class SMWorldEdit extends Plugin {
worldEdit.setSnapshotRepository(new SnapshotRepository(snapshotsDir)); worldEdit.setSnapshotRepository(new SnapshotRepository(snapshotsDir));
} }
String shellSaveType = properties.getString("shell-save-type", "").trim();
worldEdit.setShellSaveType(shellSaveType.equals("") ? null : shellSaveType);
for (Map.Entry<String,String> entry : worldEdit.getCommands().entrySet()) { for (Map.Entry<String,String> entry : worldEdit.getCommands().entrySet()) {
etc.getInstance().addCommand(entry.getKey(), entry.getValue()); etc.getInstance().addCommand(entry.getKey(), entry.getValue());
} }

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.data.*;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.snapshots.InvalidSnapshotException; import com.sk89q.worldedit.snapshots.InvalidSnapshotException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Arrays; import java.util.Arrays;
import java.util.logging.Level; import java.util.logging.Level;
@ -77,6 +78,10 @@ public class WorldEdit {
* Default block change limit. -1 for no limit. * Default block change limit. -1 for no limit.
*/ */
private int defaultChangeLimit = -1; private int defaultChangeLimit = -1;
/**
* Shell script save type.
*/
private String shellSaveType;
/** /**
* Stores the snapshot repository. May be null; * Stores the snapshot repository. May be null;
*/ */
@ -169,6 +174,8 @@ public class WorldEdit {
commands.put("/thru", "Go through the wall that you are looking at"); commands.put("/thru", "Go through the wall that you are looking at");
commands.put("/ceil", "<Clearance> - Get to the ceiling"); commands.put("/ceil", "<Clearance> - Get to the ceiling");
commands.put("/chunkinfo", "Get the filename of the chunk that you are in"); commands.put("/chunkinfo", "Get the filename of the chunk that you are in");
commands.put("/listchunks", "Print a list of used chunks");
commands.put("/delchunks", "Generate a shell script to delete chunks");
commands.put("/listsnapshots", "List the 5 newest snapshots"); commands.put("/listsnapshots", "List the 5 newest snapshots");
commands.put("//use", "[SnapshotID] - Use a particular snapshot"); commands.put("//use", "[SnapshotID] - Use a particular snapshot");
commands.put("//restore", "Restore a particular snapshot"); commands.put("//restore", "Restore a particular snapshot");
@ -888,6 +895,92 @@ public class WorldEdit {
return true; return true;
// Dump a list of involved chunks
} else if (split[0].equalsIgnoreCase("/listchunks")) {
checkArgs(split, 0, 0, split[0]);
Set<Vector2D> chunks = session.getRegion().getChunks();
for (Vector2D chunk : chunks) {
player.print(NestedFileChunkStore.getFilename(chunk));
}
return true;
// Dump a list of involved chunks
} else if (split[0].equalsIgnoreCase("/delchunks")) {
checkArgs(split, 0, 0, split[0]);
Set<Vector2D> chunks = session.getRegion().getChunks();
FileOutputStream out = null;
if (shellSaveType == null) {
player.printError("shell-save-type has to be configured in worldedit.properties");
} else if (shellSaveType.equalsIgnoreCase("bat")) {
try {
out = new FileOutputStream("worldedit-delchunks.bat");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("@ECHO off\r\n");
writer.write("ECHO This batch file was generated by WorldEdit.\r\n");
writer.write("ECHO It contains a list of chunks that were in the selected region\r\n");
writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n");
writer.write("ECHO in order to delete the chunk files listed in this file.\r\n");
writer.write("ECHO.\r\n");
writer.write("PAUSE\r\n");
for (Vector2D chunk : chunks) {
String filename = NestedFileChunkStore.getFilename(chunk);
writer.write("ECHO " + filename + "\r\n");
writer.write("DEL \"world/" + filename + "\"\r\n");
}
writer.write("ECHO Complete.\r\n");
writer.write("PAUSE\r\n");
writer.close();
player.print("worldedit-delchunks.bat written. Run it when no one is near the region.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try { out.close(); } catch (IOException ie) {}
}
}
} else if (shellSaveType.equalsIgnoreCase("bash")) {
try {
out = new FileOutputStream("worldedit-delchunks.sh");
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
writer.write("#!/bin/bash\n");
writer.write("echo This shell file was generated by WorldEdit.\n");
writer.write("echo It contains a list of chunks that were in the selected region\n");
writer.write("echo at the time that the /delchunks command was used. Run this file\n");
writer.write("echo in order to delete the chunk files listed in this file.\n");
writer.write("echo\n");
writer.write("read -p \"Press any key to continue...\"\n");
for (Vector2D chunk : chunks) {
String filename = NestedFileChunkStore.getFilename(chunk);
writer.write("echo " + filename + "\n");
writer.write("rm \"world/" + filename + "\"\n");
}
writer.write("echo Complete.\n");
writer.write("read -p \"Press any key to continue...\"\n");
writer.close();
player.print("worldedit-delchunks.sh written. Run it when no one is near the region.");
player.print("You will have to chmod it to be executable.");
} catch (IOException e) {
player.printError("Error occurred: " + e.getMessage());
} finally {
if (out != null) {
try { out.close(); } catch (IOException ie) {}
}
}
} else {
player.printError("Unknown shell script save type. 'bat' or 'bash' expected.");
}
return true;
// List snapshots // List snapshots
} else if (split[0].equalsIgnoreCase("/listsnapshots")) { } else if (split[0].equalsIgnoreCase("/listsnapshots")) {
checkArgs(split, 0, 0, split[0]); checkArgs(split, 0, 0, split[0]);
@ -1128,4 +1221,18 @@ public class WorldEdit {
public void setSnapshotRepository(SnapshotRepository snapshotRepo) { public void setSnapshotRepository(SnapshotRepository snapshotRepo) {
this.snapshotRepo = snapshotRepo; this.snapshotRepo = snapshotRepo;
} }
/**
* @return the shellSaveType
*/
public String getShellSaveType() {
return shellSaveType;
}
/**
* @param shellSaveType the shellSaveType to set
*/
public void setShellSaveType(String shellSaveType) {
this.shellSaveType = shellSaveType;
}
} }

View File

@ -19,9 +19,9 @@
package com.sk89q.worldedit.data; package com.sk89q.worldedit.data;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.Map;
import org.jnbt.*; import org.jnbt.*;
/** /**
@ -32,6 +32,37 @@ import org.jnbt.*;
* @author sk89q * @author sk89q
*/ */
public abstract class NestedFileChunkStore extends ChunkStore { public abstract class NestedFileChunkStore extends ChunkStore {
/**
* Get the filename of a chunk.
*
* @param pos
* @param separator
* @return
*/
public static String getFilename(Vector2D pos, String separator) {
int x = pos.getBlockX();
int z = pos.getBlockZ();
String folder1 = Integer.toString(divisorMod(x, 64), 36);
String folder2 = Integer.toString(divisorMod(z, 64), 36);
String filename = "c." + Integer.toString(x, 36)
+ "." + Integer.toString(z, 36) + ".dat";
return folder1 + separator + folder2 + separator + filename;
}
/**
* Get the filename of a chunk, using the system's default path
* separator.
*
* @param pos
* @param separator
* @return
*/
public static String getFilename(Vector2D pos) {
return getFilename(pos, File.separator);
}
/** /**
* Get the tag for a chunk. * Get the tag for a chunk.
* *

View File

@ -20,7 +20,11 @@
package com.sk89q.worldedit.regions; package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.data.ChunkStore;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
/** /**
* *
@ -261,6 +265,29 @@ public class CuboidRegion implements Region {
this.pos2 = pos2; this.pos2 = pos2;
} }
/**
* Get a list of chunks that this region is within.
*
* @return
*/
public Set<Vector2D> getChunks() {
Set<Vector2D> chunks = new HashSet<Vector2D>();
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
Vector pt = new Vector(x, y, z);
chunks.add(ChunkStore.toChunk(pt));
}
}
}
return chunks;
}
/** /**
* Get the iterator. * Get the iterator.
* *

View File

@ -20,6 +20,8 @@
package com.sk89q.worldedit.regions; package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import java.util.Set;
/** /**
* *
@ -74,4 +76,10 @@ public interface Region extends Iterable<Vector> {
* @param change * @param change
*/ */
public void contract(Vector change); public void contract(Vector change);
/**
* Get a list of chunks.
*
* @return
*/
public Set<Vector2D> getChunks();
} }