package org.pepsoft.minecraft.mapexplorer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; /** * A <code>DirectoryNode</code> which is part of a Minecraft map and can contain * region files, NBT files and other special node types. * * <p>Created by Pepijn on 15-6-2016. */ public class MinecraftDirectoryNode extends DirectoryNode { public MinecraftDirectoryNode(File dir) { super(dir); } @Override protected Node[] loadChildren() { File[] contents = file.listFiles(); @SuppressWarnings("ConstantConditions") // Can't happen since this node is only created for existing directories List<Node> children = new ArrayList<>(contents.length); for (File file: contents) { if (file.isDirectory()) { children.add(new MinecraftDirectoryNode(file)); } else if (file.isFile()) { String name = file.getName(); if (regionFilenamePatternVersion1.matcher(name).matches() || regionFilenamePatternVersion2.matcher(name).matches()) { children.add(new RegionFileNode(file)); } else { String lowercaseName = name.toLowerCase(); if (lowercaseName.endsWith(".nbt") || lowercaseName.endsWith(".dat") || lowercaseName.endsWith(".dat_old")) { children.add(new NBTFileNode(file)); } else if (isGzip(file)) { // Gamble that any gzipped file is an NBT file children.add(new NBTFileNode(file)); } } } } children.sort((node1, node2) -> COLLATOR.compare(node1.getName(), node2.getName())); return children.toArray(new Node[children.size()]); } private boolean isGzip(File file) { if (file.length() >= 18) { try (FileInputStream in = new FileInputStream(file)) { return (in.read() == 0x1f) && (in.read() == 0x8b); } catch (IOException e) { throw new RuntimeException("I/O error while trying to determine whether " + file + " is a gzip file"); } } else { return false; } } private final Pattern regionFilenamePatternVersion1 = Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mcr"); private final Pattern regionFilenamePatternVersion2 = Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca"); }