diff --git a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index fcf7000b2..72594630b 100644 --- a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java +++ b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java @@ -223,7 +223,7 @@ public abstract class CommandsManager { String previous = helpMessages.put(key, helpMessage); if (previous != null && !previous.replaceAll("^/[^ ]+ ", "").equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) { - helpMessages.put(key, previous+"\n\n"+helpMessage); + helpMessages.put(key, previous + "\n\n" + helpMessage); } } diff --git a/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java b/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java index 2a5aa9e53..0bf5aa11c 100644 --- a/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/SchematicCommands.java @@ -47,9 +47,9 @@ public class SchematicCommands { @Command( aliases = { "load" }, - usage = " ", + usage = "[format] ", desc = "Load a schematic into your clipboard", - min = 2, + min = 1, max = 2 ) @CommandPermissions("worldedit.clipboard.load") @@ -57,15 +57,28 @@ public class SchematicCommands { EditSession editSession) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); - SchematicFormat format = SchematicFormat.getFormat(args.getString(0)); + String fileName; + String formatName; + + if (args.argsLength() == 1) { + formatName = null; + fileName = args.getString(0); + } else { + formatName = args.getString(0); + fileName = args.getString(1); + } + File dir = we.getWorkingDirectoryFile(config.saveDir); + File f = we.getSafeOpenFile(player, dir, fileName, "schematic", "schematic"); + + SchematicFormat format = formatName == null ? null : SchematicFormat.getFormat(formatName); if (format == null) { - player.printError("Unknown schematic format: " + args.getString(0)); - return; + format = SchematicFormat.getFormat(f); } - String filename = args.getString(1); - File dir = we.getWorkingDirectoryFile(config.saveDir); - File f = we.getSafeOpenFile(player, dir, filename, "schematic", "schematic"); + if (format == null) { + player.printError("Unknown schematic format: " + formatName); + return; + } try { String filePath = f.getCanonicalPath(); @@ -76,7 +89,7 @@ public class SchematicCommands { } else { session.setClipboard(format.load(f)); WorldEdit.logger.info(player.getName() + " loaded " + filePath); - player.print(filename + " loaded. Paste it with //paste"); + player.print(fileName + " loaded. Paste it with //paste"); } } catch (DataException e) { player.printError("Load error: " + e.getMessage()); @@ -156,4 +169,28 @@ public class SchematicCommands { player.print(builder.toString()); } } + + @Command( + aliases = {"list", "all"}, + desc = "List available schematics", + max = 0 + ) + public void list(CommandContext args, LocalSession session, LocalPlayer player, + EditSession editSession) throws WorldEditException { + File dir = we.getWorkingDirectoryFile(we.getConfiguration().saveDir); + player.print("Available schematics (Filename - Format)"); + StringBuilder builder; + for (File file : dir.listFiles()) { + if (!file.isFile()) { + continue; + } + + SchematicFormat format = SchematicFormat.getFormat(file); + if (format == null) { + continue; + } + + player.print(file.getName() + ": " + format.getName()); + } + } } diff --git a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java index 787ec9c30..96766dc2a 100644 --- a/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java +++ b/src/main/java/com/sk89q/worldedit/schematic/MCEditSchematicFormat.java @@ -22,6 +22,7 @@ import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.ShortTag; @@ -34,6 +35,7 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.data.DataException; +import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -244,6 +246,31 @@ public class MCEditSchematicFormat extends SchematicFormat { stream.close(); } + @Override + public boolean isOfFormat(File file) { + DataInputStream str = null; + try { + str = new DataInputStream(new GZIPInputStream(new FileInputStream(file))); + if ((str.readByte() & 0xFF) != NBTConstants.TYPE_COMPOUND) { + return false; + } + byte[] nameBytes = new byte[str.readShort() & 0xFFFF]; + str.readFully(nameBytes); + String name = new String(nameBytes, NBTConstants.CHARSET); + return name.equals("Schematic"); + } catch (IOException e) { + return false; + } finally { + if (str != null) { + try { + str.close(); + } catch (IOException ignore) { + // blargh + } + } + } + } + /** * Get child tag of a NBT structure. * diff --git a/src/main/java/com/sk89q/worldedit/schematic/SchematicFormat.java b/src/main/java/com/sk89q/worldedit/schematic/SchematicFormat.java index f9ff9717f..e589723a7 100644 --- a/src/main/java/com/sk89q/worldedit/schematic/SchematicFormat.java +++ b/src/main/java/com/sk89q/worldedit/schematic/SchematicFormat.java @@ -45,6 +45,8 @@ import java.util.Set; */ public abstract class SchematicFormat { private static final Map SCHEMATIC_FORMATS = new HashMap(); + + // Built-in schematic formats public static final SchematicFormat MCEDIT = new MCEditSchematicFormat(); public static Set getFormats() { @@ -55,6 +57,19 @@ public abstract class SchematicFormat { return SCHEMATIC_FORMATS.get(lookupName.toLowerCase()); } + public static SchematicFormat getFormat(File file) { + if (!file.isFile()) { + return null; + } + + for (SchematicFormat format : SCHEMATIC_FORMATS.values()) { + if (format.isOfFormat(file)) { + return format; + } + } + return null; + } + private final String name; private final String[] lookupNames; @@ -137,4 +152,6 @@ public abstract class SchematicFormat { * @throws DataException If the clipboard has data which cannot be stored */ public abstract void save(CuboidClipboard clipboard, File file) throws IOException, DataException; + + public abstract boolean isOfFormat(File file); } diff --git a/src/main/java/com/sk89q/worldedit/spout/SpoutBiomeType.java b/src/main/java/com/sk89q/worldedit/spout/SpoutBiomeType.java index 2ad39464d..ccde1c637 100644 --- a/src/main/java/com/sk89q/worldedit/spout/SpoutBiomeType.java +++ b/src/main/java/com/sk89q/worldedit/spout/SpoutBiomeType.java @@ -34,4 +34,14 @@ public class SpoutBiomeType extends com.sk89q.worldedit.BiomeType { public BiomeType getSpoutBiome() { return type; } + + @Override + public boolean equals(Object other) { + return other instanceof SpoutBiomeType && ((SpoutBiomeType)other).type.equals(this.type); + } + + @Override + public int hashCode() { + return 31 + type.hashCode(); + } }