mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 17:57:38 +00:00
Added McRegion reader classes (incomplete), moved some com.sk89q.worldedit.data classes around and moved org.jnbt com.sk89q.jnbt to coincide with some modifications to make the JNBT library a bit more generic by accepting uncompressed input streams.
This commit is contained in:
parent
488f841d69
commit
5e7d9c7f7d
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
||||||
@ -35,6 +35,7 @@ package org.jnbt;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>TAG_Compound</code> tag.
|
* The <code>TAG_Compound</code> tag.
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
||||||
@ -35,6 +35,8 @@ package org.jnbt;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.sk89q.jnbt.NBTUtils;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>TAG_List</code> tag.
|
* The <code>TAG_List</code> tag.
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
||||||
@ -41,7 +41,20 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This class reads <strong>NBT</strong>, or
|
* <p>This class reads <strong>NBT</strong>, or
|
||||||
@ -68,7 +81,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public NBTInputStream(InputStream is) throws IOException {
|
public NBTInputStream(InputStream is) throws IOException {
|
||||||
this.is = new DataInputStream(new GZIPInputStream(is));
|
this.is = new DataInputStream(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@ -6,6 +6,20 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.zip.GZIPOutputStream;
|
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
|
* JNBT License
|
@ -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
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,6 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -1,4 +1,4 @@
|
|||||||
package org.jnbt;
|
package com.sk89q.jnbt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNBT License
|
* JNBT License
|
@ -19,14 +19,15 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit;
|
package com.sk89q.worldedit;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.blocks.*;
|
import com.sk89q.worldedit.blocks.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import org.jnbt.*;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The clipboard remembers the state of a cuboid region.
|
* The clipboard remembers the state of a cuboid region.
|
||||||
@ -381,7 +382,8 @@ public class CuboidClipboard {
|
|||||||
public static CuboidClipboard loadSchematic(File path)
|
public static CuboidClipboard loadSchematic(File path)
|
||||||
throws DataException, IOException {
|
throws DataException, IOException {
|
||||||
FileInputStream stream = new FileInputStream(path);
|
FileInputStream stream = new FileInputStream(path);
|
||||||
NBTInputStream nbtStream = new NBTInputStream(stream);
|
NBTInputStream nbtStream = new NBTInputStream(
|
||||||
|
new GZIPInputStream(stream));
|
||||||
|
|
||||||
Vector origin = new Vector();
|
Vector origin = new Vector();
|
||||||
Vector offset = new Vector();
|
Vector offset = new Vector();
|
||||||
|
@ -2109,7 +2109,7 @@ public class EditSession {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the highest solid 'terrain' block which can occur naturally.
|
* 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 x
|
||||||
* @param z
|
* @param z
|
||||||
@ -2131,6 +2131,7 @@ public class EditSession {
|
|||||||
|| id == 7 // bedrock
|
|| id == 7 // bedrock
|
||||||
|| id == 12 // sand
|
|| id == 12 // sand
|
||||||
|| id == 13 // gravel
|
|| id == 13 // gravel
|
||||||
|
|| id == 82 // clay
|
||||||
// hell
|
// hell
|
||||||
|| id == 87 // netherstone
|
|| id == 87 // netherstone
|
||||||
|| id == 88 // slowsand
|
|| id == 88 // slowsand
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents chests.
|
* Represents chests.
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents dispensers.
|
* Represents dispensers.
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents furnaces.
|
* Represents furnaces.
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents chests.
|
* Represents chests.
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.blocks;
|
package com.sk89q.worldedit.blocks;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.jnbt.Tag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class implementing this interface has extra TileEntityBlock data to store.
|
* A class implementing this interface has extra TileEntityBlock data to store.
|
||||||
|
@ -25,7 +25,7 @@ import com.sk89q.minecraft.util.commands.Command;
|
|||||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.data.NestedFileChunkStore;
|
import com.sk89q.worldedit.data.LegacyChunkStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chunk tools.
|
* Chunk tools.
|
||||||
@ -73,7 +73,7 @@ public class ChunkCommands {
|
|||||||
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||||
|
|
||||||
for (Vector2D chunk : chunks) {
|
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");
|
writer.write("PAUSE\r\n");
|
||||||
|
|
||||||
for (Vector2D chunk : chunks) {
|
for (Vector2D chunk : chunks) {
|
||||||
String filename = NestedFileChunkStore.getFilename(chunk);
|
String filename = LegacyChunkStore.getFilename(chunk);
|
||||||
writer.write("ECHO " + filename + "\r\n");
|
writer.write("ECHO " + filename + "\r\n");
|
||||||
writer.write("DEL \"world/" + 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");
|
writer.write("read -p \"Press any key to continue...\"\n");
|
||||||
|
|
||||||
for (Vector2D chunk : chunks) {
|
for (Vector2D chunk : chunks) {
|
||||||
String filename = NestedFileChunkStore.getFilename(chunk);
|
String filename = LegacyChunkStore.getFilename(chunk);
|
||||||
writer.write("echo " + filename + "\n");
|
writer.write("echo " + filename + "\n");
|
||||||
writer.write("rm \"world/" + filename + "\"\n");
|
writer.write("rm \"world/" + filename + "\"\n");
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ package com.sk89q.worldedit.data;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.blocks.*;
|
import com.sk89q.worldedit.blocks.*;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a chunk.
|
* Represents a chunk.
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
package com.sk89q.worldedit.data;
|
package com.sk89q.worldedit.data;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import com.sk89q.jnbt.*;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import org.jnbt.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents chunk storage mechanisms.
|
* Represents chunk storage mechanisms.
|
||||||
|
@ -26,7 +26,7 @@ import java.io.*;
|
|||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public class AlphaChunkStore extends NestedFileChunkStore {
|
public class FileLegacyChunkStore extends LegacyChunkStore {
|
||||||
/**
|
/**
|
||||||
* Folder to read from.
|
* Folder to read from.
|
||||||
*/
|
*/
|
||||||
@ -38,7 +38,7 @@ public class AlphaChunkStore extends NestedFileChunkStore {
|
|||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
public AlphaChunkStore(File path) {
|
public FileLegacyChunkStore(File path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
57
src/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
Normal file
57
src/com/sk89q/worldedit/data/FileMcRegionChunkStore.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
100
src/com/sk89q/worldedit/data/ForwardSeekableInputStream.java
Normal file
100
src/com/sk89q/worldedit/data/ForwardSeekableInputStream.java
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,10 +19,13 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.data;
|
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 com.sk89q.worldedit.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.jnbt.*;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents chunk stores that use Alpha's file format for storing chunks.
|
* Represents chunk stores that use Alpha's file format for storing chunks.
|
||||||
@ -31,7 +34,7 @@ import org.jnbt.*;
|
|||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public abstract class NestedFileChunkStore extends ChunkStore {
|
public abstract class LegacyChunkStore extends ChunkStore {
|
||||||
/**
|
/**
|
||||||
* Get the filename of a chunk.
|
* Get the filename of a chunk.
|
||||||
*
|
*
|
||||||
@ -82,7 +85,8 @@ public abstract class NestedFileChunkStore extends ChunkStore {
|
|||||||
+ "." + Integer.toString(z, 36) + ".dat";
|
+ "." + Integer.toString(z, 36) + ".dat";
|
||||||
|
|
||||||
InputStream stream = getInputStream(folder1, folder2, filename);
|
InputStream stream = getInputStream(folder1, folder2, filename);
|
||||||
NBTInputStream nbt = new NBTInputStream(stream);
|
NBTInputStream nbt = new NBTInputStream(
|
||||||
|
new GZIPInputStream(stream));
|
||||||
Tag tag;
|
Tag tag;
|
||||||
|
|
||||||
try {
|
try {
|
123
src/com/sk89q/worldedit/data/McRegionChunkStore.java
Normal file
123
src/com/sk89q/worldedit/data/McRegionChunkStore.java
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String,Tag> children = (Map<String,Tag>)((CompoundTag)tag).getValue();
|
||||||
|
CompoundTag rootTag = null;
|
||||||
|
|
||||||
|
// Find Level tag
|
||||||
|
for (Map.Entry<String,Tag> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
197
src/com/sk89q/worldedit/data/McRegionReader.java
Normal file
197
src/com/sk89q/worldedit/data/McRegionReader.java
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
// $Id$
|
||||||
|
/*
|
||||||
|
* WorldEdit
|
||||||
|
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,157 +0,0 @@
|
|||||||
// $Id$
|
|
||||||
/*
|
|
||||||
* WorldEdit
|
|
||||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,167 +1,167 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
/*
|
/*
|
||||||
* WorldEdit
|
* WorldEdit
|
||||||
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.data;
|
package com.sk89q.worldedit.data;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.ZipException;
|
import java.util.zip.ZipException;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import de.schlichtherle.util.zip.*;
|
import de.schlichtherle.util.zip.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the chunk store used by Minecraft alpha but zipped. Uses
|
* Represents the chunk store used by Minecraft alpha but zipped. Uses
|
||||||
* the replacement classes for java.util.zip.* from TrueZip.
|
* the replacement classes for java.util.zip.* from TrueZip.
|
||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public class TrueZipLegacyAlphaChunkStore extends NestedFileChunkStore {
|
public class TrueZipLegacyChunkStore extends LegacyChunkStore {
|
||||||
/**
|
/**
|
||||||
* ZIP file.
|
* ZIP file.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private File zipFile;
|
private File zipFile;
|
||||||
/**
|
/**
|
||||||
* Actual ZIP.
|
* Actual ZIP.
|
||||||
*/
|
*/
|
||||||
private ZipFile zip;
|
private ZipFile zip;
|
||||||
/**
|
/**
|
||||||
* Folder inside the ZIP file to read from, if any.
|
* Folder inside the ZIP file to read from, if any.
|
||||||
*/
|
*/
|
||||||
private String folder;
|
private String folder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance. The folder argument lets you choose a folder or
|
* 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
|
* path to look into in the ZIP for the files. Use a blank string for
|
||||||
* the folder to not look into a subdirectory.
|
* the folder to not look into a subdirectory.
|
||||||
*
|
*
|
||||||
* @param zipFile
|
* @param zipFile
|
||||||
* @param folder
|
* @param folder
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws ZipException
|
* @throws ZipException
|
||||||
*/
|
*/
|
||||||
public TrueZipLegacyAlphaChunkStore(File zipFile, String folder)
|
public TrueZipLegacyChunkStore(File zipFile, String folder)
|
||||||
throws IOException, ZipException {
|
throws IOException, ZipException {
|
||||||
this.zipFile = zipFile;
|
this.zipFile = zipFile;
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
|
|
||||||
zip = new ZipFile(zipFile);
|
zip = new ZipFile(zipFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance. The subfolder containing the chunk data will
|
* Create an instance. The subfolder containing the chunk data will
|
||||||
* be detected.
|
* be detected.
|
||||||
*
|
*
|
||||||
* @param zipFile
|
* @param zipFile
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws ZipException
|
* @throws ZipException
|
||||||
*/
|
*/
|
||||||
public TrueZipLegacyAlphaChunkStore(File zipFile)
|
public TrueZipLegacyChunkStore(File zipFile)
|
||||||
throws IOException, ZipException {
|
throws IOException, ZipException {
|
||||||
this.zipFile = zipFile;
|
this.zipFile = zipFile;
|
||||||
|
|
||||||
zip = new ZipFile(zipFile);
|
zip = new ZipFile(zipFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the input stream for a chunk file.
|
* Get the input stream for a chunk file.
|
||||||
*
|
*
|
||||||
* @param f1
|
* @param f1
|
||||||
* @param f2
|
* @param f2
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws DataException
|
* @throws DataException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected InputStream getInputStream(String f1, String f2, String name)
|
protected InputStream getInputStream(String f1, String f2, String name)
|
||||||
throws IOException, DataException {
|
throws IOException, DataException {
|
||||||
String file = f1 + "/" + f2 + "/" + name;
|
String file = f1 + "/" + f2 + "/" + name;
|
||||||
|
|
||||||
// Detect subfolder for the world's files
|
// Detect subfolder for the world's files
|
||||||
if (folder != null) {
|
if (folder != null) {
|
||||||
if (!folder.equals("")) {
|
if (!folder.equals("")) {
|
||||||
file = folder + "/" + file;
|
file = folder + "/" + file;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ZipEntry testEntry = zip.getEntry("level.dat");
|
ZipEntry testEntry = zip.getEntry("level.dat");
|
||||||
|
|
||||||
// So, the data is not in the root directory
|
// So, the data is not in the root directory
|
||||||
if (testEntry == null) {
|
if (testEntry == null) {
|
||||||
// Let's try a world/ sub-directory
|
// Let's try a world/ sub-directory
|
||||||
testEntry = getEntry("world/level.dat");
|
testEntry = getEntry("world/level.dat");
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile(".*[\\\\/]level\\.dat$");
|
Pattern pattern = Pattern.compile(".*[\\\\/]level\\.dat$");
|
||||||
|
|
||||||
// So not there either...
|
// So not there either...
|
||||||
if (testEntry == null) {
|
if (testEntry == null) {
|
||||||
for (Enumeration<? extends ZipEntry> e = zip.entries();
|
for (Enumeration<? extends ZipEntry> e = zip.entries();
|
||||||
e.hasMoreElements(); ) {
|
e.hasMoreElements(); ) {
|
||||||
|
|
||||||
testEntry = (ZipEntry)e.nextElement();
|
testEntry = (ZipEntry)e.nextElement();
|
||||||
|
|
||||||
// Whoo, found level.dat!
|
// Whoo, found level.dat!
|
||||||
if (pattern.matcher(testEntry.getName()).matches()) {
|
if (pattern.matcher(testEntry.getName()).matches()) {
|
||||||
file = testEntry.getName().replaceAll("level\\.dat$", "")
|
file = testEntry.getName().replaceAll("level\\.dat$", "")
|
||||||
+ file;
|
+ file;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file = "world/" + file;
|
file = "world/" + file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZipEntry entry = getEntry(file);
|
ZipEntry entry = getEntry(file);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
throw new MissingChunkException();
|
throw new MissingChunkException();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return zip.getInputStream(entry);
|
return zip.getInputStream(entry);
|
||||||
} catch (ZipException e) {
|
} catch (ZipException e) {
|
||||||
throw new IOException("Failed to read " + file + " in ZIP");
|
throw new IOException("Failed to read " + file + " in ZIP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an entry from the ZIP, trying both types of slashes.
|
* Get an entry from the ZIP, trying both types of slashes.
|
||||||
*
|
*
|
||||||
* @param file
|
* @param file
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private ZipEntry getEntry(String file) {
|
private ZipEntry getEntry(String file) {
|
||||||
ZipEntry entry = zip.getEntry(file);
|
ZipEntry entry = zip.getEntry(file);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
return zip.getEntry(file.replace("/", "\\"));
|
return zip.getEntry(file.replace("/", "\\"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close resources.
|
* Close resources.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
zip.close();
|
zip.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ import java.util.Enumeration;
|
|||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public class ZippedAlphaChunkStore extends NestedFileChunkStore {
|
public class ZippedAlphaChunkStore extends LegacyChunkStore {
|
||||||
/**
|
/**
|
||||||
* ZIP file.
|
* ZIP file.
|
||||||
*/
|
*/
|
||||||
|
@ -21,12 +21,15 @@ package com.sk89q.worldedit.snapshots;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.data.*;
|
import com.sk89q.worldedit.data.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author sk89q
|
* @author sk89q
|
||||||
*/
|
*/
|
||||||
public class Snapshot {
|
public class Snapshot {
|
||||||
|
protected static Logger logger = Logger.getLogger("Minecraft.WorldEdit");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores snapshot file.
|
* Stores snapshot file.
|
||||||
*/
|
*/
|
||||||
@ -57,7 +60,7 @@ public class Snapshot {
|
|||||||
public ChunkStore getChunkStore() throws IOException, DataException {
|
public ChunkStore getChunkStore() throws IOException, DataException {
|
||||||
if (file.getName().toLowerCase().endsWith(".zip")) {
|
if (file.getName().toLowerCase().endsWith(".zip")) {
|
||||||
try {
|
try {
|
||||||
return new TrueZipLegacyAlphaChunkStore(file);
|
return new TrueZipLegacyChunkStore(file);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
return new ZippedAlphaChunkStore(file);
|
return new ZippedAlphaChunkStore(file);
|
||||||
}
|
}
|
||||||
@ -65,12 +68,12 @@ public class Snapshot {
|
|||||||
|| file.getName().toLowerCase().endsWith(".tar.gz")
|
|| file.getName().toLowerCase().endsWith(".tar.gz")
|
||||||
|| file.getName().toLowerCase().endsWith(".tar")) {
|
|| file.getName().toLowerCase().endsWith(".tar")) {
|
||||||
try {
|
try {
|
||||||
return new TrueZipAlphaChunkStore(file);
|
return new TrueZipLegacyChunkStore(file);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
throw new DataException("TrueZIP is required for .tar support");
|
throw new DataException("TrueZIP is required for .tar support");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new AlphaChunkStore(file);
|
return new FileLegacyChunkStore(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user