diff --git a/src/org/jnbt/ByteArrayTag.java b/src/com/sk89q/jnbt/ByteArrayTag.java
similarity index 94%
rename from src/org/jnbt/ByteArrayTag.java
rename to src/com/sk89q/jnbt/ByteArrayTag.java
index 3e84b294b..739203acc 100644
--- a/src/org/jnbt/ByteArrayTag.java
+++ b/src/com/sk89q/jnbt/ByteArrayTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/ByteTag.java b/src/com/sk89q/jnbt/ByteTag.java
similarity index 94%
rename from src/org/jnbt/ByteTag.java
rename to src/com/sk89q/jnbt/ByteTag.java
index b255cee70..358ec889b 100644
--- a/src/org/jnbt/ByteTag.java
+++ b/src/com/sk89q/jnbt/ByteTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/CompoundTag.java b/src/com/sk89q/jnbt/CompoundTag.java
similarity index 95%
rename from src/org/jnbt/CompoundTag.java
rename to src/com/sk89q/jnbt/CompoundTag.java
index ce9c07927..a7f6d833a 100644
--- a/src/org/jnbt/CompoundTag.java
+++ b/src/com/sk89q/jnbt/CompoundTag.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
/*
* JNBT License
@@ -35,6 +35,7 @@ package org.jnbt;
import java.util.Collections;
import java.util.Map;
+import com.sk89q.jnbt.Tag;
/**
* The TAG_Compound
tag.
diff --git a/src/org/jnbt/DoubleTag.java b/src/com/sk89q/jnbt/DoubleTag.java
similarity index 94%
rename from src/org/jnbt/DoubleTag.java
rename to src/com/sk89q/jnbt/DoubleTag.java
index 668e0fd02..ed74c14bc 100644
--- a/src/org/jnbt/DoubleTag.java
+++ b/src/com/sk89q/jnbt/DoubleTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/EndTag.java b/src/com/sk89q/jnbt/EndTag.java
similarity index 94%
rename from src/org/jnbt/EndTag.java
rename to src/com/sk89q/jnbt/EndTag.java
index 1f6b7f313..176c86ffc 100644
--- a/src/org/jnbt/EndTag.java
+++ b/src/com/sk89q/jnbt/EndTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/FloatTag.java b/src/com/sk89q/jnbt/FloatTag.java
similarity index 94%
rename from src/org/jnbt/FloatTag.java
rename to src/com/sk89q/jnbt/FloatTag.java
index 3921a6478..0d9055356 100644
--- a/src/org/jnbt/FloatTag.java
+++ b/src/com/sk89q/jnbt/FloatTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/IntTag.java b/src/com/sk89q/jnbt/IntTag.java
similarity index 94%
rename from src/org/jnbt/IntTag.java
rename to src/com/sk89q/jnbt/IntTag.java
index ad2e43361..b5187b197 100644
--- a/src/org/jnbt/IntTag.java
+++ b/src/com/sk89q/jnbt/IntTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/ListTag.java b/src/com/sk89q/jnbt/ListTag.java
similarity index 94%
rename from src/org/jnbt/ListTag.java
rename to src/com/sk89q/jnbt/ListTag.java
index 4d267033f..17e8096eb 100644
--- a/src/org/jnbt/ListTag.java
+++ b/src/com/sk89q/jnbt/ListTag.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
/*
* JNBT License
@@ -35,6 +35,8 @@ package org.jnbt;
import java.util.Collections;
import java.util.List;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.Tag;
/**
* The TAG_List
tag.
diff --git a/src/org/jnbt/LongTag.java b/src/com/sk89q/jnbt/LongTag.java
similarity index 94%
rename from src/org/jnbt/LongTag.java
rename to src/com/sk89q/jnbt/LongTag.java
index c337de889..66390f350 100644
--- a/src/org/jnbt/LongTag.java
+++ b/src/com/sk89q/jnbt/LongTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/NBTConstants.java b/src/com/sk89q/jnbt/NBTConstants.java
similarity index 95%
rename from src/org/jnbt/NBTConstants.java
rename to src/com/sk89q/jnbt/NBTConstants.java
index 5dced4fcb..7533d8574 100644
--- a/src/org/jnbt/NBTConstants.java
+++ b/src/com/sk89q/jnbt/NBTConstants.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
import java.nio.charset.Charset;
diff --git a/src/org/jnbt/NBTInputStream.java b/src/com/sk89q/jnbt/NBTInputStream.java
similarity index 88%
rename from src/org/jnbt/NBTInputStream.java
rename to src/com/sk89q/jnbt/NBTInputStream.java
index 4ba8c3c0a..69bd5abb6 100644
--- a/src/org/jnbt/NBTInputStream.java
+++ b/src/com/sk89q/jnbt/NBTInputStream.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
/*
* JNBT License
@@ -41,7 +41,20 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.zip.GZIPInputStream;
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.ByteTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.DoubleTag;
+import com.sk89q.jnbt.EndTag;
+import com.sk89q.jnbt.FloatTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.LongTag;
+import com.sk89q.jnbt.NBTConstants;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
/**
*
This class reads NBT, or
@@ -68,7 +81,7 @@ public final class NBTInputStream implements Closeable {
* @throws IOException if an I/O error occurs.
*/
public NBTInputStream(InputStream is) throws IOException {
- this.is = new DataInputStream(new GZIPInputStream(is));
+ this.is = new DataInputStream(is);
}
/**
diff --git a/src/org/jnbt/NBTOutputStream.java b/src/com/sk89q/jnbt/NBTOutputStream.java
similarity index 90%
rename from src/org/jnbt/NBTOutputStream.java
rename to src/com/sk89q/jnbt/NBTOutputStream.java
index a9a3c8956..41bea562e 100644
--- a/src/org/jnbt/NBTOutputStream.java
+++ b/src/com/sk89q/jnbt/NBTOutputStream.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
import java.io.Closeable;
import java.io.DataOutputStream;
@@ -6,6 +6,20 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.GZIPOutputStream;
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.ByteTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.DoubleTag;
+import com.sk89q.jnbt.EndTag;
+import com.sk89q.jnbt.FloatTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.LongTag;
+import com.sk89q.jnbt.NBTConstants;
+import com.sk89q.jnbt.NBTUtils;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/NBTUtils.java b/src/com/sk89q/jnbt/NBTUtils.java
similarity index 89%
rename from src/org/jnbt/NBTUtils.java
rename to src/com/sk89q/jnbt/NBTUtils.java
index 823b04ae6..1410453a4 100644
--- a/src/org/jnbt/NBTUtils.java
+++ b/src/com/sk89q/jnbt/NBTUtils.java
@@ -1,4 +1,18 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.ByteArrayTag;
+import com.sk89q.jnbt.ByteTag;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.DoubleTag;
+import com.sk89q.jnbt.EndTag;
+import com.sk89q.jnbt.FloatTag;
+import com.sk89q.jnbt.IntTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.LongTag;
+import com.sk89q.jnbt.NBTConstants;
+import com.sk89q.jnbt.ShortTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/ShortTag.java b/src/com/sk89q/jnbt/ShortTag.java
similarity index 94%
rename from src/org/jnbt/ShortTag.java
rename to src/com/sk89q/jnbt/ShortTag.java
index 11e2f3afd..559fd093f 100644
--- a/src/org/jnbt/ShortTag.java
+++ b/src/com/sk89q/jnbt/ShortTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/StringTag.java b/src/com/sk89q/jnbt/StringTag.java
similarity index 94%
rename from src/org/jnbt/StringTag.java
rename to src/com/sk89q/jnbt/StringTag.java
index 3bcb09265..57ee7d85d 100644
--- a/src/org/jnbt/StringTag.java
+++ b/src/com/sk89q/jnbt/StringTag.java
@@ -1,4 +1,6 @@
-package org.jnbt;
+package com.sk89q.jnbt;
+
+import com.sk89q.jnbt.Tag;
/*
* JNBT License
diff --git a/src/org/jnbt/Tag.java b/src/com/sk89q/jnbt/Tag.java
similarity index 95%
rename from src/org/jnbt/Tag.java
rename to src/com/sk89q/jnbt/Tag.java
index 384784697..79fa0ed20 100644
--- a/src/org/jnbt/Tag.java
+++ b/src/com/sk89q/jnbt/Tag.java
@@ -1,4 +1,4 @@
-package org.jnbt;
+package com.sk89q.jnbt;
/*
* JNBT License
diff --git a/src/com/sk89q/worldedit/CuboidClipboard.java b/src/com/sk89q/worldedit/CuboidClipboard.java
index 28f2f4cca..476436a7c 100644
--- a/src/com/sk89q/worldedit/CuboidClipboard.java
+++ b/src/com/sk89q/worldedit/CuboidClipboard.java
@@ -19,14 +19,15 @@
package com.sk89q.worldedit;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.blocks.*;
import com.sk89q.worldedit.data.*;
-import org.jnbt.*;
import java.io.*;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
+import java.util.zip.GZIPInputStream;
/**
* The clipboard remembers the state of a cuboid region.
@@ -381,7 +382,8 @@ public class CuboidClipboard {
public static CuboidClipboard loadSchematic(File path)
throws DataException, IOException {
FileInputStream stream = new FileInputStream(path);
- NBTInputStream nbtStream = new NBTInputStream(stream);
+ NBTInputStream nbtStream = new NBTInputStream(
+ new GZIPInputStream(stream));
Vector origin = new Vector();
Vector offset = new Vector();
diff --git a/src/com/sk89q/worldedit/EditSession.java b/src/com/sk89q/worldedit/EditSession.java
index 95a1bf4aa..c47e3fc53 100755
--- a/src/com/sk89q/worldedit/EditSession.java
+++ b/src/com/sk89q/worldedit/EditSession.java
@@ -2109,7 +2109,7 @@ public class EditSession {
/**
* Returns the highest solid 'terrain' block which can occur naturally.
- * Looks at: 1, 2, 3, 7, 12, 13, 14, 15, 16, 56, 73, 74, 87, 88, 89
+ * Looks at: 1, 2, 3, 7, 12, 13, 14, 15, 16, 56, 73, 74, 87, 88, 89, 82
*
* @param x
* @param z
@@ -2131,6 +2131,7 @@ public class EditSession {
|| id == 7 // bedrock
|| id == 12 // sand
|| id == 13 // gravel
+ || id == 82 // clay
// hell
|| id == 87 // netherstone
|| id == 88 // slowsand
diff --git a/src/com/sk89q/worldedit/blocks/ChestBlock.java b/src/com/sk89q/worldedit/blocks/ChestBlock.java
index 678bc618d..54e109ec6 100644
--- a/src/com/sk89q/worldedit/blocks/ChestBlock.java
+++ b/src/com/sk89q/worldedit/blocks/ChestBlock.java
@@ -19,12 +19,12 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
-import org.jnbt.*;
/**
* Represents chests.
diff --git a/src/com/sk89q/worldedit/blocks/DispenserBlock.java b/src/com/sk89q/worldedit/blocks/DispenserBlock.java
index f887c1edc..4504219b3 100644
--- a/src/com/sk89q/worldedit/blocks/DispenserBlock.java
+++ b/src/com/sk89q/worldedit/blocks/DispenserBlock.java
@@ -19,12 +19,12 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
-import org.jnbt.*;
/**
* Represents dispensers.
diff --git a/src/com/sk89q/worldedit/blocks/FurnaceBlock.java b/src/com/sk89q/worldedit/blocks/FurnaceBlock.java
index d72066407..c67180528 100644
--- a/src/com/sk89q/worldedit/blocks/FurnaceBlock.java
+++ b/src/com/sk89q/worldedit/blocks/FurnaceBlock.java
@@ -19,12 +19,12 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
-import org.jnbt.*;
/**
* Represents furnaces.
diff --git a/src/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/src/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
index 64d2e673f..5e2e2fab1 100644
--- a/src/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
+++ b/src/com/sk89q/worldedit/blocks/MobSpawnerBlock.java
@@ -19,10 +19,10 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
-import org.jnbt.*;
/**
* Represents chests.
diff --git a/src/com/sk89q/worldedit/blocks/NoteBlock.java b/src/com/sk89q/worldedit/blocks/NoteBlock.java
index 5a186127f..e25a86f36 100644
--- a/src/com/sk89q/worldedit/blocks/NoteBlock.java
+++ b/src/com/sk89q/worldedit/blocks/NoteBlock.java
@@ -19,10 +19,10 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
-import org.jnbt.*;
/**
*
diff --git a/src/com/sk89q/worldedit/blocks/SignBlock.java b/src/com/sk89q/worldedit/blocks/SignBlock.java
index d36146a13..4ae5a563e 100644
--- a/src/com/sk89q/worldedit/blocks/SignBlock.java
+++ b/src/com/sk89q/worldedit/blocks/SignBlock.java
@@ -19,10 +19,10 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.data.*;
import java.util.Map;
import java.util.HashMap;
-import org.jnbt.*;
/**
*
diff --git a/src/com/sk89q/worldedit/blocks/TileEntityBlock.java b/src/com/sk89q/worldedit/blocks/TileEntityBlock.java
index 4cf06ee84..f36b57fc2 100644
--- a/src/com/sk89q/worldedit/blocks/TileEntityBlock.java
+++ b/src/com/sk89q/worldedit/blocks/TileEntityBlock.java
@@ -19,9 +19,9 @@
package com.sk89q.worldedit.blocks;
+import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.data.*;
import java.util.Map;
-import org.jnbt.Tag;
/**
* A class implementing this interface has extra TileEntityBlock data to store.
diff --git a/src/com/sk89q/worldedit/commands/ChunkCommands.java b/src/com/sk89q/worldedit/commands/ChunkCommands.java
index 8354850a1..3dac26653 100644
--- a/src/com/sk89q/worldedit/commands/ChunkCommands.java
+++ b/src/com/sk89q/worldedit/commands/ChunkCommands.java
@@ -25,7 +25,7 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
-import com.sk89q.worldedit.data.NestedFileChunkStore;
+import com.sk89q.worldedit.data.LegacyChunkStore;
/**
* Chunk tools.
@@ -73,7 +73,7 @@ public class ChunkCommands {
Set chunks = session.getSelection(player.getWorld()).getChunks();
for (Vector2D chunk : chunks) {
- player.print(NestedFileChunkStore.getFilename(chunk));
+ player.print(LegacyChunkStore.getFilename(chunk));
}
}
@@ -109,7 +109,7 @@ public class ChunkCommands {
writer.write("PAUSE\r\n");
for (Vector2D chunk : chunks) {
- String filename = NestedFileChunkStore.getFilename(chunk);
+ String filename = LegacyChunkStore.getFilename(chunk);
writer.write("ECHO " + filename + "\r\n");
writer.write("DEL \"world/" + filename + "\"\r\n");
}
@@ -138,7 +138,7 @@ public class ChunkCommands {
writer.write("read -p \"Press any key to continue...\"\n");
for (Vector2D chunk : chunks) {
- String filename = NestedFileChunkStore.getFilename(chunk);
+ String filename = LegacyChunkStore.getFilename(chunk);
writer.write("echo " + filename + "\n");
writer.write("rm \"world/" + filename + "\"\n");
}
diff --git a/src/com/sk89q/worldedit/data/Chunk.java b/src/com/sk89q/worldedit/data/Chunk.java
index ae05e4f92..3c05cd4f7 100644
--- a/src/com/sk89q/worldedit/data/Chunk.java
+++ b/src/com/sk89q/worldedit/data/Chunk.java
@@ -23,9 +23,9 @@ package com.sk89q.worldedit.data;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.*;
-import org.jnbt.*;
/**
* Represents a chunk.
diff --git a/src/com/sk89q/worldedit/data/ChunkStore.java b/src/com/sk89q/worldedit/data/ChunkStore.java
index 99cca9949..ef0432b3b 100644
--- a/src/com/sk89q/worldedit/data/ChunkStore.java
+++ b/src/com/sk89q/worldedit/data/ChunkStore.java
@@ -20,8 +20,8 @@
package com.sk89q.worldedit.data;
import java.io.*;
+import com.sk89q.jnbt.*;
import com.sk89q.worldedit.*;
-import org.jnbt.*;
/**
* Represents chunk storage mechanisms.
diff --git a/src/com/sk89q/worldedit/data/AlphaChunkStore.java b/src/com/sk89q/worldedit/data/FileLegacyChunkStore.java
similarity index 94%
rename from src/com/sk89q/worldedit/data/AlphaChunkStore.java
rename to src/com/sk89q/worldedit/data/FileLegacyChunkStore.java
index 38da78f99..10c03c8f4 100644
--- a/src/com/sk89q/worldedit/data/AlphaChunkStore.java
+++ b/src/com/sk89q/worldedit/data/FileLegacyChunkStore.java
@@ -26,7 +26,7 @@ import java.io.*;
*
* @author sk89q
*/
-public class AlphaChunkStore extends NestedFileChunkStore {
+public class FileLegacyChunkStore extends LegacyChunkStore {
/**
* Folder to read from.
*/
@@ -38,7 +38,7 @@ public class AlphaChunkStore extends NestedFileChunkStore {
*
* @param path
*/
- public AlphaChunkStore(File path) {
+ public FileLegacyChunkStore(File path) {
this.path = path;
}
diff --git a/src/com/sk89q/worldedit/data/FileMcRegionChunkStore.java b/src/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
new file mode 100644
index 000000000..f9dabee69
--- /dev/null
+++ b/src/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
@@ -0,0 +1,57 @@
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010, 2011 sk89q
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+package com.sk89q.worldedit.data;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class FileMcRegionChunkStore extends McRegionChunkStore {
+ /**
+ * Folder to read from.
+ */
+ private File path;
+
+ /**
+ * Create an instance. The passed path is the folder to read the
+ * chunk files from.
+ *
+ * @param path
+ */
+ public FileMcRegionChunkStore(File path) {
+ this.path = path;
+ }
+
+ @Override
+ protected InputStream getInputStream(String name) throws IOException,
+ DataException {
+
+ String file = "region" + File.separator + name;
+
+ try {
+ return new FileInputStream(new File(path, file));
+ } catch (FileNotFoundException e) {
+ throw new MissingChunkException();
+ }
+ }
+
+}
diff --git a/src/com/sk89q/worldedit/data/ForwardSeekableInputStream.java b/src/com/sk89q/worldedit/data/ForwardSeekableInputStream.java
new file mode 100644
index 000000000..1ed26595b
--- /dev/null
+++ b/src/com/sk89q/worldedit/data/ForwardSeekableInputStream.java
@@ -0,0 +1,100 @@
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010, 2011 sk89q
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+package com.sk89q.worldedit.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ForwardSeekableInputStream extends InputStream {
+
+ protected InputStream parent;
+ protected long position = 0;
+
+ public ForwardSeekableInputStream(InputStream parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int ret = parent.read();
+ position++;
+ return ret;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return parent.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ parent.close();
+ }
+
+ @Override
+ public synchronized void mark(int readlimit) {
+ parent.mark(readlimit);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return parent.markSupported();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ throw new IOException("Offset not supported for read()");
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ int read = parent.read(b);
+ position += read;
+ return read;
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ parent.reset();
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ long skipped = parent.skip(n);
+ position += skipped;
+ return skipped;
+ }
+
+ public void seek(long n) throws IOException {
+ long diff = n - position;
+
+ if (diff < 0) {
+ throw new IOException("Can't seek backwards");
+ }
+
+ if (diff == 0) {
+ return;
+ }
+
+ if (skip(diff) < diff) {
+ throw new IOException("Failed to seek " + diff + " bytes");
+ }
+ }
+}
diff --git a/src/com/sk89q/worldedit/data/NestedFileChunkStore.java b/src/com/sk89q/worldedit/data/LegacyChunkStore.java
similarity index 93%
rename from src/com/sk89q/worldedit/data/NestedFileChunkStore.java
rename to src/com/sk89q/worldedit/data/LegacyChunkStore.java
index 9cd08fde2..7ae24c515 100644
--- a/src/com/sk89q/worldedit/data/NestedFileChunkStore.java
+++ b/src/com/sk89q/worldedit/data/LegacyChunkStore.java
@@ -19,10 +19,13 @@
package com.sk89q.worldedit.data;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.NBTInputStream;
+import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.*;
import java.io.*;
import java.util.Map;
-import org.jnbt.*;
+import java.util.zip.GZIPInputStream;
/**
* Represents chunk stores that use Alpha's file format for storing chunks.
@@ -31,7 +34,7 @@ import org.jnbt.*;
*
* @author sk89q
*/
-public abstract class NestedFileChunkStore extends ChunkStore {
+public abstract class LegacyChunkStore extends ChunkStore {
/**
* Get the filename of a chunk.
*
@@ -82,7 +85,8 @@ public abstract class NestedFileChunkStore extends ChunkStore {
+ "." + Integer.toString(z, 36) + ".dat";
InputStream stream = getInputStream(folder1, folder2, filename);
- NBTInputStream nbt = new NBTInputStream(stream);
+ NBTInputStream nbt = new NBTInputStream(
+ new GZIPInputStream(stream));
Tag tag;
try {
diff --git a/src/com/sk89q/worldedit/data/McRegionChunkStore.java b/src/com/sk89q/worldedit/data/McRegionChunkStore.java
new file mode 100644
index 000000000..69b0d5b8a
--- /dev/null
+++ b/src/com/sk89q/worldedit/data/McRegionChunkStore.java
@@ -0,0 +1,123 @@
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010, 2011 sk89q
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+package com.sk89q.worldedit.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.NBTInputStream;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.Vector2D;
+
+public abstract class McRegionChunkStore extends ChunkStore {
+ protected String curFilename = null;
+ protected McRegionReader cachedReader = null;
+
+ /**
+ * Get the filename of a region file.
+ *
+ * @param pos
+ * @return
+ */
+ public static String getFilename(Vector2D pos) {
+ int x = pos.getBlockX();
+ int z = pos.getBlockZ();
+
+ String filename = "r." + (x >> 5) + "." + (z >> 5) + ".mcr";
+
+ return filename;
+ }
+
+ protected McRegionReader getReader(Vector2D pos) throws DataException, IOException {
+ String filename = getFilename(pos);
+ if (curFilename.equals(filename)) {
+ return cachedReader;
+ }
+ InputStream stream = getInputStream(filename);
+ cachedReader = new McRegionReader(stream);
+ return cachedReader;
+ }
+
+ @Override
+ public CompoundTag getChunkTag(Vector2D pos) throws DataException,
+ IOException {
+
+ McRegionReader reader = getReader(pos);
+ InputStream stream = reader.getChunkInputStream(pos);
+ NBTInputStream nbt = new NBTInputStream(stream);
+ Tag tag;
+
+ try {
+ tag = nbt.readTag();
+ if (!(tag instanceof CompoundTag)) {
+ throw new ChunkStoreException("CompoundTag expected for chunk; got "
+ + tag.getClass().getName());
+ }
+
+ Map children = (Map)((CompoundTag)tag).getValue();
+ CompoundTag rootTag = null;
+
+ // Find Level tag
+ for (Map.Entry entry : children.entrySet()) {
+ if (entry.getKey().equals("Level")) {
+ if (entry.getValue() instanceof CompoundTag) {
+ rootTag = (CompoundTag)entry.getValue();
+ break;
+ } else {
+ throw new ChunkStoreException("CompoundTag expected for 'Level'; got "
+ + entry.getValue().getClass().getName());
+ }
+ }
+ }
+
+ if (rootTag == null) {
+ throw new ChunkStoreException("Missing root 'Level' tag");
+ }
+
+ return rootTag;
+ } finally {
+ stream.close();
+ }
+ }
+
+ /**
+ * Get the input stream for a chunk file.
+ *
+ * @param name
+ * @return
+ * @throws IOException
+ */
+ protected abstract InputStream getInputStream(String name)
+ throws IOException, DataException;
+
+
+ /**
+ * Close resources.
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException {
+ if (cachedReader != null) {
+ cachedReader.close();
+ }
+ }
+}
diff --git a/src/com/sk89q/worldedit/data/McRegionReader.java b/src/com/sk89q/worldedit/data/McRegionReader.java
new file mode 100644
index 000000000..d77e484e2
--- /dev/null
+++ b/src/com/sk89q/worldedit/data/McRegionReader.java
@@ -0,0 +1,197 @@
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010 sk89q
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+/*
+
+ Region File Format
+
+ Concept: The minimum unit of storage on hard drives is 4KB. 90% of Minecraft
+ chunks are smaller than 4KB. 99% are smaller than 8KB. Write a simple
+ container to store chunks in single files in runs of 4KB sectors.
+
+ Each region file represents a 32x32 group of chunks. The conversion from
+ chunk number to region number is floor(coord / 32): a chunk at (30, -3)
+ would be in region (0, -1), and one at (70, -30) would be at (3, -1).
+ Region files are named "r.x.z.data", where x and z are the region coordinates.
+
+ A region file begins with a 4KB header that describes where chunks are stored
+ in the file. A 4-byte big-endian integer represents sector offsets and sector
+ counts. The chunk offset for a chunk (x, z) begins at byte 4*(x+z*32) in the
+ file. The bottom byte of the chunk offset indicates the number of sectors the
+ chunk takes up, and the top 3 bytes represent the sector number of the chunk.
+ Given a chunk offset o, the chunk data begins at byte 4096*(o/256) and takes up
+ at most 4096*(o%256) bytes. A chunk cannot exceed 1MB in size. If a chunk
+ offset is 0, the corresponding chunk is not stored in the region file.
+
+ Chunk data begins with a 4-byte big-endian integer representing the chunk data
+ length in bytes, not counting the length field. The length must be smaller than
+ 4096 times the number of sectors. The next byte is a version field, to allow
+ backwards-compatible updates to how chunks are encoded.
+
+ A version of 1 represents a gzipped NBT file. The gzipped data is the chunk
+ length - 1.
+
+ A version of 2 represents a deflated (zlib compressed) NBT file. The deflated
+ data is the chunk length - 1.
+
+ */
+
+package com.sk89q.worldedit.data;
+
+import java.io.*;
+import java.util.zip.*;
+import com.sk89q.worldedit.Vector2D;
+
+/**
+ * Reader for a MCRegion file. This reader works on input streams, meaning
+ * that it can be used to read files from non-file based sources.
+ *
+ * @author sk89q
+ */
+public class McRegionReader {
+
+ protected static final int VERSION_GZIP = 1;
+ protected static final int VERSION_DEFLATE = 2;
+ protected static final int SECTOR_BYTES = 4096;
+ protected static final int SECTOR_INTS = SECTOR_BYTES / 4;
+ public static final int CHUNK_HEADER_SIZE = 5;
+
+ protected ForwardSeekableInputStream stream;
+ protected DataInputStream dataStream;
+
+ protected int offsets[];
+
+ /**
+ * Construct the reader.
+ *
+ * @param stream
+ * @throws DataException
+ * @throws IOException
+ */
+ public McRegionReader(InputStream stream) throws DataException, IOException {
+ this.stream = new ForwardSeekableInputStream(stream);
+ this.dataStream = new DataInputStream(this.stream);
+
+ readHeader();
+ }
+
+ /**
+ * Read the header.
+ *
+ * @throws DataException
+ * @throws IOException
+ */
+ private void readHeader() throws DataException, IOException {
+ offsets = new int[SECTOR_INTS];
+
+ for (int i = 0; i < SECTOR_INTS; ++i) {
+ int offset = dataStream.readInt();
+ offsets[i] = offset;
+ }
+ }
+
+ /**
+ * Gets the uncompressed data input stream for a chunk.
+ *
+ * @param pos
+ * @return
+ * @throws IOException
+ * @throws DataException
+ */
+ public synchronized InputStream getChunkInputStream(Vector2D pos)
+ throws IOException, DataException {
+
+ int x = pos.getBlockX();
+ int z = pos.getBlockZ();
+
+ if (x < 0 || x >= 32 || z < 0 || z >= 32) {
+ throw new DataException("MCRegion file does not contain " + x + "," + z);
+ }
+
+ int offset = getOffset(x, z);
+
+ // The chunk hasn't been generated
+ if (offset == 0) {
+ return null;
+ }
+
+ int sectorNumber = offset >> 8;
+ int numSectors = offset & 0xFF;
+
+ stream.seek(sectorNumber * SECTOR_BYTES);
+ int length = dataStream.readInt();
+
+ if (length > SECTOR_BYTES * numSectors) {
+ throw new DataException("MCRegion chunk at "
+ + x + "," + z + " has an invalid length of " + length);
+ }
+
+ byte version = dataStream.readByte();
+
+ if (version == VERSION_GZIP) {
+ byte[] data = new byte[length - 1];
+ if (dataStream.read(data) < length - 1) {
+ throw new DataException("MCRegion file does not contain "
+ + x + "," + z + " in full");
+ }
+ return new GZIPInputStream(new ByteArrayInputStream(data));
+ } else if (version == VERSION_DEFLATE) {
+ byte[] data = new byte[length - 1];
+ if (dataStream.read(data) < length - 1) {
+ throw new DataException("MCRegion file does not contain "
+ + x + "," + z + " in full");
+ }
+ return new InflaterInputStream(new ByteArrayInputStream(data));
+ } else {
+ throw new DataException("MCRegion chunk at "
+ + x + "," + z + " has an unsupported version of " + version);
+ }
+ }
+
+ /**
+ * Get the offset for a chunk. May return 0 if it doesn't exist.
+ *
+ * @param x
+ * @param z
+ * @return
+ */
+ private int getOffset(int x, int z) {
+ return offsets[x + z * 32];
+ }
+
+ /**
+ * Returns whether the file contains a chunk.
+ *
+ * @param x
+ * @param z
+ * @return
+ */
+ public boolean hasChunk(int x, int z) {
+ return getOffset(x, z) != 0;
+ }
+
+ /**
+ * Close the stream.
+ *
+ * @throws IOException
+ */
+ public void close() throws IOException {
+ stream.close();
+ }
+}
\ No newline at end of file
diff --git a/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java b/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java
deleted file mode 100644
index de521698b..000000000
--- a/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java
+++ /dev/null
@@ -1,157 +0,0 @@
-// $Id$
-/*
- * WorldEdit
- * Copyright (C) 2010 sk89q
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-
-package com.sk89q.worldedit.data;
-
-import de.schlichtherle.io.*;
-import de.schlichtherle.io.File;
-import de.schlichtherle.io.FileInputStream;
-import java.io.*;
-import java.util.regex.Pattern;
-
-/**
- * Represents the chunk store used by Minecraft alpha. This driver uses
- * TrueZip to read zip files, althoguh it currently does not work well.
- *
- * @author sk89q
- */
-public class TrueZipAlphaChunkStore extends NestedFileChunkStore {
- /**
- * Folder to read from.
- */
- private File path;
-
- /**
- * Create an instance. The passed path is the folder to read the
- * chunk files from.
- *
- * @param path
- */
- public TrueZipAlphaChunkStore(java.io.File path) {
- this.path = new File(path);
- File root = findWorldPath(this.path);
- if (root != null) {
- this.path = root;
- }
- }
-
- /**
- * Create an instance. The passed path is the folder to read the
- * chunk files from.
- *
- * @param path
- */
- public TrueZipAlphaChunkStore(File path) {
- this.path = path;
- File root = findWorldPath(path);
- if (root != null) {
- this.path = root;
- }
- }
-
- /**
- * Create an instance. The passed path is the folder to read the
- * chunk files from.
- *
- * @param path
- */
- public TrueZipAlphaChunkStore(String path) {
- this.path = new File(path);
- File root = findWorldPath(this.path);
- if (root != null) {
- this.path = root;
- }
- }
-
- /**
- * Get the input stream for a chunk file.
- *
- * @param f1
- * @param f2
- * @param name
- * @return
- * @throws DataException
- * @throws IOException
- */
- @Override
- protected InputStream getInputStream(String f1, String f2, String name)
- throws DataException, IOException {
- String file = f1 + File.separator + f2 + File.separator + name;
- File f = new File(path, file);
- try {
- return new FileInputStream(f.getAbsolutePath());
- } catch (FileNotFoundException e) {
- throw new MissingChunkException();
- }
- }
-
- /**
- * Find the root directory for the chunk files.
- *
- * @param path
- * @return
- */
- private File findWorldPath(File path) {
- File f = new File(path, "world");
-
- if (path.contains(f)) {
- return f;
- }
-
- return searchForPath(path);
- }
-
- /**
- * Find the root directory for the chunk files.
- *
- * @param path
- * @return
- */
- private File searchForPath(File path) {
- String[] children = path.list();
-
- Pattern pattern = Pattern.compile(".*[\\\\/]level\\.dat$");
-
- if (children == null) {
- return null;
- } else {
- for (String f : children) {
- if (pattern.matcher(f).matches()) {
- return (File)(new File(path, f)).getParentFile();
- }
- }
- }
-
- return null;
- }
-
- /**
- * Close the archive.
- *
- * @throws IOException
- */
- @Override
- public void close() throws IOException {
- try {
- File.umount(new File(path));
- } catch (ArchiveException e) {
- throw new IOException(e);
- }
- }
-}
diff --git a/src/com/sk89q/worldedit/data/TrueZipLegacyAlphaChunkStore.java b/src/com/sk89q/worldedit/data/TrueZipLegacyChunkStore.java
similarity index 92%
rename from src/com/sk89q/worldedit/data/TrueZipLegacyAlphaChunkStore.java
rename to src/com/sk89q/worldedit/data/TrueZipLegacyChunkStore.java
index e5372f147..736169fbe 100644
--- a/src/com/sk89q/worldedit/data/TrueZipLegacyAlphaChunkStore.java
+++ b/src/com/sk89q/worldedit/data/TrueZipLegacyChunkStore.java
@@ -1,167 +1,167 @@
-// $Id$
-/*
- * WorldEdit
- * Copyright (C) 2010 sk89q
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-
-package com.sk89q.worldedit.data;
-
-import java.io.*;
-import java.util.regex.Pattern;
-import java.util.zip.ZipException;
-import java.util.Enumeration;
-import de.schlichtherle.util.zip.*;
-
-/**
- * Represents the chunk store used by Minecraft alpha but zipped. Uses
- * the replacement classes for java.util.zip.* from TrueZip.
- *
- * @author sk89q
- */
-public class TrueZipLegacyAlphaChunkStore extends NestedFileChunkStore {
- /**
- * ZIP file.
- */
- @SuppressWarnings("unused")
- private File zipFile;
- /**
- * Actual ZIP.
- */
- private ZipFile zip;
- /**
- * Folder inside the ZIP file to read from, if any.
- */
- private String folder;
-
- /**
- * Create an instance. The folder argument lets you choose a folder or
- * path to look into in the ZIP for the files. Use a blank string for
- * the folder to not look into a subdirectory.
- *
- * @param zipFile
- * @param folder
- * @throws IOException
- * @throws ZipException
- */
- public TrueZipLegacyAlphaChunkStore(File zipFile, String folder)
- throws IOException, ZipException {
- this.zipFile = zipFile;
- this.folder = folder;
-
- zip = new ZipFile(zipFile);
- }
-
- /**
- * Create an instance. The subfolder containing the chunk data will
- * be detected.
- *
- * @param zipFile
- * @throws IOException
- * @throws ZipException
- */
- public TrueZipLegacyAlphaChunkStore(File zipFile)
- throws IOException, ZipException {
- this.zipFile = zipFile;
-
- zip = new ZipFile(zipFile);
- }
-
- /**
- * Get the input stream for a chunk file.
- *
- * @param f1
- * @param f2
- * @param name
- * @return
- * @throws IOException
- * @throws DataException
- */
- @Override
- @SuppressWarnings("unchecked")
- protected InputStream getInputStream(String f1, String f2, String name)
- throws IOException, DataException {
- String file = f1 + "/" + f2 + "/" + name;
-
- // Detect subfolder for the world's files
- if (folder != null) {
- if (!folder.equals("")) {
- file = folder + "/" + file;
- }
- } else {
- ZipEntry testEntry = zip.getEntry("level.dat");
-
- // So, the data is not in the root directory
- if (testEntry == null) {
- // Let's try a world/ sub-directory
- testEntry = getEntry("world/level.dat");
-
- Pattern pattern = Pattern.compile(".*[\\\\/]level\\.dat$");
-
- // So not there either...
- if (testEntry == null) {
- for (Enumeration extends ZipEntry> e = zip.entries();
- e.hasMoreElements(); ) {
-
- testEntry = (ZipEntry)e.nextElement();
-
- // Whoo, found level.dat!
- if (pattern.matcher(testEntry.getName()).matches()) {
- file = testEntry.getName().replaceAll("level\\.dat$", "")
- + file;
- break;
- }
- }
- } else {
- file = "world/" + file;
- }
- }
- }
-
- ZipEntry entry = getEntry(file);
- if (entry == null) {
- throw new MissingChunkException();
- }
- try {
- return zip.getInputStream(entry);
- } catch (ZipException e) {
- throw new IOException("Failed to read " + file + " in ZIP");
- }
- }
-
- /**
- * Get an entry from the ZIP, trying both types of slashes.
- *
- * @param file
- * @return
- */
- private ZipEntry getEntry(String file) {
- ZipEntry entry = zip.getEntry(file);
- if (entry != null) {
- return entry;
- }
- return zip.getEntry(file.replace("/", "\\"));
- }
-
- /**
- * Close resources.
- *
- * @throws IOException
- */
- @Override
- public void close() throws IOException {
- zip.close();
- }
-}
+// $Id$
+/*
+ * WorldEdit
+ * Copyright (C) 2010 sk89q
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+package com.sk89q.worldedit.data;
+
+import java.io.*;
+import java.util.regex.Pattern;
+import java.util.zip.ZipException;
+import java.util.Enumeration;
+import de.schlichtherle.util.zip.*;
+
+/**
+ * Represents the chunk store used by Minecraft alpha but zipped. Uses
+ * the replacement classes for java.util.zip.* from TrueZip.
+ *
+ * @author sk89q
+ */
+public class TrueZipLegacyChunkStore extends LegacyChunkStore {
+ /**
+ * ZIP file.
+ */
+ @SuppressWarnings("unused")
+ private File zipFile;
+ /**
+ * Actual ZIP.
+ */
+ private ZipFile zip;
+ /**
+ * Folder inside the ZIP file to read from, if any.
+ */
+ private String folder;
+
+ /**
+ * Create an instance. The folder argument lets you choose a folder or
+ * path to look into in the ZIP for the files. Use a blank string for
+ * the folder to not look into a subdirectory.
+ *
+ * @param zipFile
+ * @param folder
+ * @throws IOException
+ * @throws ZipException
+ */
+ public TrueZipLegacyChunkStore(File zipFile, String folder)
+ throws IOException, ZipException {
+ this.zipFile = zipFile;
+ this.folder = folder;
+
+ zip = new ZipFile(zipFile);
+ }
+
+ /**
+ * Create an instance. The subfolder containing the chunk data will
+ * be detected.
+ *
+ * @param zipFile
+ * @throws IOException
+ * @throws ZipException
+ */
+ public TrueZipLegacyChunkStore(File zipFile)
+ throws IOException, ZipException {
+ this.zipFile = zipFile;
+
+ zip = new ZipFile(zipFile);
+ }
+
+ /**
+ * Get the input stream for a chunk file.
+ *
+ * @param f1
+ * @param f2
+ * @param name
+ * @return
+ * @throws IOException
+ * @throws DataException
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected InputStream getInputStream(String f1, String f2, String name)
+ throws IOException, DataException {
+ String file = f1 + "/" + f2 + "/" + name;
+
+ // Detect subfolder for the world's files
+ if (folder != null) {
+ if (!folder.equals("")) {
+ file = folder + "/" + file;
+ }
+ } else {
+ ZipEntry testEntry = zip.getEntry("level.dat");
+
+ // So, the data is not in the root directory
+ if (testEntry == null) {
+ // Let's try a world/ sub-directory
+ testEntry = getEntry("world/level.dat");
+
+ Pattern pattern = Pattern.compile(".*[\\\\/]level\\.dat$");
+
+ // So not there either...
+ if (testEntry == null) {
+ for (Enumeration extends ZipEntry> e = zip.entries();
+ e.hasMoreElements(); ) {
+
+ testEntry = (ZipEntry)e.nextElement();
+
+ // Whoo, found level.dat!
+ if (pattern.matcher(testEntry.getName()).matches()) {
+ file = testEntry.getName().replaceAll("level\\.dat$", "")
+ + file;
+ break;
+ }
+ }
+ } else {
+ file = "world/" + file;
+ }
+ }
+ }
+
+ ZipEntry entry = getEntry(file);
+ if (entry == null) {
+ throw new MissingChunkException();
+ }
+ try {
+ return zip.getInputStream(entry);
+ } catch (ZipException e) {
+ throw new IOException("Failed to read " + file + " in ZIP");
+ }
+ }
+
+ /**
+ * Get an entry from the ZIP, trying both types of slashes.
+ *
+ * @param file
+ * @return
+ */
+ private ZipEntry getEntry(String file) {
+ ZipEntry entry = zip.getEntry(file);
+ if (entry != null) {
+ return entry;
+ }
+ return zip.getEntry(file.replace("/", "\\"));
+ }
+
+ /**
+ * Close resources.
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException {
+ zip.close();
+ }
+}
diff --git a/src/com/sk89q/worldedit/data/ZippedAlphaChunkStore.java b/src/com/sk89q/worldedit/data/ZippedAlphaChunkStore.java
index 65b783cfc..8823d6117 100644
--- a/src/com/sk89q/worldedit/data/ZippedAlphaChunkStore.java
+++ b/src/com/sk89q/worldedit/data/ZippedAlphaChunkStore.java
@@ -29,7 +29,7 @@ import java.util.Enumeration;
*
* @author sk89q
*/
-public class ZippedAlphaChunkStore extends NestedFileChunkStore {
+public class ZippedAlphaChunkStore extends LegacyChunkStore {
/**
* ZIP file.
*/
diff --git a/src/com/sk89q/worldedit/snapshots/Snapshot.java b/src/com/sk89q/worldedit/snapshots/Snapshot.java
index f653ea890..356ff353b 100644
--- a/src/com/sk89q/worldedit/snapshots/Snapshot.java
+++ b/src/com/sk89q/worldedit/snapshots/Snapshot.java
@@ -21,12 +21,15 @@ package com.sk89q.worldedit.snapshots;
import com.sk89q.worldedit.data.*;
import java.io.*;
+import java.util.logging.Logger;
/**
*
* @author sk89q
*/
public class Snapshot {
+ protected static Logger logger = Logger.getLogger("Minecraft.WorldEdit");
+
/**
* Stores snapshot file.
*/
@@ -57,7 +60,7 @@ public class Snapshot {
public ChunkStore getChunkStore() throws IOException, DataException {
if (file.getName().toLowerCase().endsWith(".zip")) {
try {
- return new TrueZipLegacyAlphaChunkStore(file);
+ return new TrueZipLegacyChunkStore(file);
} catch (NoClassDefFoundError e) {
return new ZippedAlphaChunkStore(file);
}
@@ -65,12 +68,12 @@ public class Snapshot {
|| file.getName().toLowerCase().endsWith(".tar.gz")
|| file.getName().toLowerCase().endsWith(".tar")) {
try {
- return new TrueZipAlphaChunkStore(file);
+ return new TrueZipLegacyChunkStore(file);
} catch (NoClassDefFoundError e) {
throw new DataException("TrueZIP is required for .tar support");
}
} else {
- return new AlphaChunkStore(file);
+ return new FileLegacyChunkStore(file);
}
}