Added purge command to delete chunks

This commit is contained in:
Justin Aquadro 2011-03-13 09:57:45 +00:00
parent 45839d2416
commit 77f0764013
7 changed files with 202 additions and 2 deletions

View file

@ -99,6 +99,28 @@ namespace NBToolkit
{
return _regionMan;
}
public bool DeleteChunk (int cx, int cz)
{
Region r = GetRegion(cx, cz);
if (r == null) {
return false;
}
if (!r.DeleteChunk(cx & REGION_XMASK, cz & REGION_ZMASK)) {
return false;
}
ChunkKey k = new ChunkKey(cx, cz);
_cache.Remove(k);
_dirty.Remove(k);
if (r.ChunkCount() == 0) {
_regionMan.DeleteRegion(r.X, r.Z);
}
return true;
}
}
public class MissingChunkException : Exception

View file

@ -66,6 +66,7 @@
<Compile Include="NDesk\Options.cs" />
<Compile Include="NibbleArray.cs" />
<Compile Include="Oregen.cs" />
<Compile Include="Purge.cs" />
<Compile Include="Region.cs" />
<Compile Include="RegionEnumerator.cs" />
<Compile Include="RegionKey.cs" />

View file

@ -28,6 +28,12 @@ namespace NBToolkit
options.SetDefaults();
filter.Run();
}
else if (args[0] == "purge") {
PurgeOptions options = new PurgeOptions(args);
Purge filter = new Purge(options);
options.SetDefaults();
filter.Run();
}
else if (args[0] == "help") {
if (args.Length < 2) {
args = new string[2] { "help", "help" };
@ -52,6 +58,13 @@ namespace NBToolkit
Console.WriteLine();
options.PrintUsage();
}
else if (args[1] == "purge") {
options = new PurgeOptions(args);
WriteBlock("Deletes all chunks matching the chunk filtering options. If no options are specified, all world chunks will be deleted. Region files that have all of their chunks purged will also be deleted from the world directory.");
Console.WriteLine();
options.PrintUsage();
}
else {
WriteBlock("Prints help and usage information for another command. Available commands are 'oregen' and 'replace'.");
Console.WriteLine();

View file

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Text;
using NDesk.Options;
using NBT;
namespace NBToolkit
{
public class PurgeOptions : TKOptions, IChunkFilterable
{
private OptionSet _filterOpt = null;
private ChunkFilter _chunkFilter = null;
public PurgeOptions ()
: base()
{
_filterOpt = new OptionSet();
_chunkFilter = new ChunkFilter();
}
public PurgeOptions (string[] args)
: this()
{
Parse(args);
}
public override void Parse (string[] args)
{
base.Parse(args);
_filterOpt.Parse(args);
_chunkFilter.Parse(args);
}
public override void PrintUsage ()
{
Console.WriteLine("Usage: nbtoolkit purge [options]");
Console.WriteLine();
Console.WriteLine("Options for command 'purge':");
_filterOpt.WriteOptionDescriptions(Console.Out);
Console.WriteLine();
_chunkFilter.PrintUsage();
Console.WriteLine();
base.PrintUsage();
}
public override void SetDefaults ()
{
base.SetDefaults();
}
public IChunkFilter GetChunkFilter ()
{
return _chunkFilter;
}
}
class Purge : TKFilter
{
private PurgeOptions opt;
private static Random rand = new Random();
public Purge (PurgeOptions o)
{
opt = o;
}
public override void Run ()
{
World world = new World(opt.OPT_WORLD);
int affectedChunks = 0;
foreach (Chunk chunk in new FilteredChunkList(world.GetChunkManager(), opt.GetChunkFilter())) {
affectedChunks++;
world.GetChunkManager().DeleteChunk(chunk.X, chunk.Z);
}
Console.WriteLine("Purged Chunks: " + affectedChunks);
}
}
}

View file

@ -7,10 +7,11 @@ using NBT;
namespace NBToolkit
{
public class Region
public class Region : IDisposable
{
protected int _rx;
protected int _rz;
protected bool _disposed = false;
protected RegionManager _regionMan;
@ -58,6 +59,34 @@ namespace NBToolkit
}
}
~Region ()
{
Dispose(false);
}
public void Dispose ()
{
Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose (bool disposing)
{
if (!_disposed) {
if (disposing) {
// Cleanup managed resources
RegionFile rf = _regionFile.Target as RegionFile;
if (rf != null) {
rf.Dispose();
rf = null;
}
}
// Cleanup unmanaged resources
}
_disposed = true;
}
public string GetFileName ()
{
return "r." + _rx + "." + _rz + ".mcr";
@ -151,5 +180,16 @@ namespace NBToolkit
return count;
}
public bool DeleteChunk (int lcx, int lcz)
{
RegionFile rf = GetRegionFile();
if (!rf.HasChunk(lcx, lcz)) {
return false;
}
rf.DeleteChunk(lcx, lcz);
return true;
}
}
}

View file

@ -371,8 +371,24 @@ namespace NBToolkit
file.Write(data, 0, length); // chunk data
}
public void DeleteChunk (int x, int z)
{
int offset = GetOffset(x, z);
int sectorNumber = offset >> 8;
int sectorsAllocated = offset & 0xFF;
file.Seek(sectorNumber * SECTOR_BYTES, SeekOrigin.Begin);
for (int i = 0; i < sectorsAllocated; i++) {
file.Write(emptySector, 0, SECTOR_BYTES);
}
SetOffset(x, z, 0);
SetTimestamp(x, z, 0);
}
/* is this an invalid chunk coordinate? */
private bool OutOfBounds(int x, int z) {
private bool OutOfBounds (int x, int z)
{
return x < 0 || x >= 32 || z < 0 || z >= 32;
}

View file

@ -49,5 +49,28 @@ namespace NBToolkit
{
return _regionPath;
}
public bool DeleteRegion (int rx, int rz)
{
Region r = GetRegion(rx, rz);
if (r == null) {
return false;
}
RegionKey k = new RegionKey(rx, rz);
_cache.Remove(k);
r.Dispose();
try {
File.Delete(r.GetFilePath());
}
catch (Exception e) {
Console.WriteLine("NOTICE: " + e.Message);
return false;
}
return true;
}
}
}