diff --git a/manifest.mf b/manifest.mf index c6ce47339..6ba946608 100644 --- a/manifest.mf +++ b/manifest.mf @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Class-Path: jnbt.jar +Class-Path: jnbt.jar truezip.jar ant.jar diff --git a/src/WorldEdit.java b/src/WorldEdit.java index 2623d5542..6f3fca111 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -953,7 +953,7 @@ public class WorldEdit { Region region = session.getRegion(); Snapshot snapshot = session.getSnapshot(); - ChunkStore chunkStore; + ChunkStore chunkStore = null; // No snapshot set? if (snapshot == null) { @@ -974,19 +974,26 @@ public class WorldEdit { return true; } - // Restore snapshot - SnapshotRestore restore = new SnapshotRestore(chunkStore, region); - //player.print(restore.getChunksAffected() + " chunk(s) will be loaded."); + try { + // Restore snapshot + SnapshotRestore restore = new SnapshotRestore(chunkStore, region); + //player.print(restore.getChunksAffected() + " chunk(s) will be loaded."); - restore.restore(editSession); + restore.restore(editSession); - if (restore.hadTotalFailure()) { - player.printError("No blocks could be restored. (Bad backup?)"); - } else { - player.print(String.format("Restored; %d " - + "missing chunks and %d other errors.", - restore.getMissingChunks().size(), - restore.getErrorChunks().size())); + if (restore.hadTotalFailure()) { + player.printError("No blocks could be restored. (Bad backup?)"); + } else { + player.print(String.format("Restored; %d " + + "missing chunks and %d other errors.", + restore.getMissingChunks().size(), + restore.getErrorChunks().size())); + } + } finally { + try { + chunkStore.close(); + } catch (IOException e) { + } } return true; diff --git a/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java b/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java new file mode 100644 index 000000000..48236ec38 --- /dev/null +++ b/src/com/sk89q/worldedit/data/TrueZipAlphaChunkStore.java @@ -0,0 +1,158 @@ +// $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 de.schlichtherle.io.FileOutputStream; +import java.io.*; + +/** + * Represents the chunk store used by Minecraft alpha. + * + * @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 + */ + protected InputStream getInputStream(String f1, String f2, String name) + throws DataException, IOException { + String file = f1 + File.separator + f2 + File.separator + name; + try { + return new FileInputStream(new File(path.getAbsolutePath(), file)); + } catch (FileNotFoundException e) { + throw new MissingChunkException(); + } + } + + /** + * Find the root directory for the chunk files. + * + * @param path + * @return + */ + private File findWorldPath(File path) { + if ((new File(path, "world")).exists()) { + return new File(path, "world"); + } + + return searchForPath(path); + } + + /** + * Find the root directory for the chunk files. + * + * @param path + * @return + */ + private File searchForPath(File path) { + String[] children = path.list(); + // listFiles() returns java.io.File[] + + if (children == null) { + return null; + } else { + for (String child : children) { + File f = new File(path, child); + + if (f.isFile() && f.getName().equals("level.dat")) { + return path; + } else if (f.isDirectory()) { + File res = findWorldPath(f); + if (res != null) { + return res; + } + } + } + } + + return null; + } + + /** + * Close the archive. + * + * @throws IOException + */ + @Override + public void close() throws IOException { + try { + path.umount(); + } catch (ArchiveException e) { + throw new IOException(e); + } + } +} diff --git a/src/com/sk89q/worldedit/snapshots/Snapshot.java b/src/com/sk89q/worldedit/snapshots/Snapshot.java index 795f73966..916d0856b 100644 --- a/src/com/sk89q/worldedit/snapshots/Snapshot.java +++ b/src/com/sk89q/worldedit/snapshots/Snapshot.java @@ -56,7 +56,11 @@ public class Snapshot { */ public ChunkStore getChunkStore() throws IOException { if (file.getName().toLowerCase().endsWith(".zip")) { - return new ZippedAlphaChunkStore(file); + try { + return new TrueZipAlphaChunkStore(file); + } catch (NoClassDefFoundError e) { + return new ZippedAlphaChunkStore(file); + } } else { return new AlphaChunkStore(file); }