use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.
the class FindOutliers method main.
public static void main(String[] args) throws IOException {
File[] worldDirs = new File(args[0]).listFiles();
for (File worldDir : worldDirs) {
System.out.println("Scanning " + worldDir);
File[] regionFiles = new File(worldDir, "region").listFiles();
if ((regionFiles == null) || (regionFiles.length == 0)) {
System.out.println(" No regions found");
continue;
}
int regionCount = 0, chunkCount = 0;
int lowestChunkX = Integer.MAX_VALUE, highestChunkX = Integer.MIN_VALUE, lowestChunkZ = Integer.MAX_VALUE, highestChunkZ = Integer.MIN_VALUE;
List<Integer> xValues = new ArrayList<>(), zValues = new ArrayList<>();
List<Point> chunks = new ArrayList<>();
for (File file : regionFiles) {
String[] nameFrags = file.getName().split("\\.");
int regionX = Integer.parseInt(nameFrags[1]);
int regionZ = Integer.parseInt(nameFrags[2]);
regionCount++;
RegionFile regionFile = new RegionFile(file);
try {
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
if (regionFile.containsChunk(x, z)) {
chunkCount++;
int chunkX = regionX * 32 + x, chunkZ = regionZ * 32 + z;
if (chunkX < lowestChunkX) {
lowestChunkX = chunkX;
}
if (chunkX > highestChunkX) {
highestChunkX = chunkX;
}
if (chunkZ < lowestChunkZ) {
lowestChunkZ = chunkZ;
}
if (chunkZ > highestChunkZ) {
highestChunkZ = chunkZ;
}
xValues.add(chunkX);
zValues.add(chunkZ);
chunks.add(new Point(chunkX, chunkZ));
}
}
}
} finally {
regionFile.close();
}
}
// System.out.println(args[0]);
// System.out.println("Region count: " + regionCount);
// System.out.println("Chunk count: " + chunkCount);
// System.out.println("Size in chunks: " + (highestChunkX - lowestChunkX + 1) + " by " + (highestChunkZ - lowestChunkZ + 1));
// System.out.println("Lowest chunk x: " + lowestChunkX + ", highest chunk x: " + highestChunkX);
// System.out.println("Lowest chunk z: " + lowestChunkZ + ", highest chunk z: " + highestChunkZ);
Collections.sort(xValues);
int p1 = xValues.size() / 4;
float q1 = xValues.get(p1) * 0.75f + xValues.get(p1 + 1) * 0.25f;
int p2 = xValues.size() / 2;
float q2 = (xValues.get(p2) + xValues.get(p2 + 1)) / 2f;
int p3 = xValues.size() * 3 / 4;
float q3 = xValues.get(p3) * 0.25f + xValues.get(p3 + 1) * 0.75f;
float iqr = q3 - q1;
int lowerLimit = (int) (q2 - iqr * 1.5f);
int upperLimit = (int) (q2 + iqr * 1.5f);
Set<Point> outlyingChunks = new HashSet<>();
for (Point chunk : chunks) {
if ((chunk.x < lowerLimit) || (chunk.x > upperLimit)) {
outlyingChunks.add(chunk);
}
}
Collections.sort(zValues);
p1 = zValues.size() / 4;
q1 = zValues.get(p1) * 0.75f + zValues.get(p1 + 1) * 0.25f;
p2 = zValues.size() / 2;
q2 = (zValues.get(p2) + zValues.get(p2 + 1)) / 2f;
p3 = zValues.size() * 3 / 4;
q3 = zValues.get(p3) * 0.25f + zValues.get(p3 + 1) * 0.75f;
iqr = q3 - q1;
lowerLimit = (int) (q2 - iqr * 1.5f);
upperLimit = (int) (q2 + iqr * 1.5f);
for (Point chunk : chunks) {
if ((chunk.y < lowerLimit) || (chunk.y > upperLimit)) {
outlyingChunks.add(chunk);
}
}
if (!outlyingChunks.isEmpty()) {
System.out.println(" Outlying chunk count: " + outlyingChunks.size());
// for (Point outlyingChunk: outlyingChunks) {
// System.out.println(outlyingChunk);
// }
} else {
System.out.println(" No outlying chunks found: " + outlyingChunks.size());
}
}
}
use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.
the class MapImportDialog method analyseMap.
private void analyseMap() {
mapStatistics = null;
resetStats();
File levelDatFile = new File(fieldFilename.getText());
final File worldDir = levelDatFile.getParentFile();
// Check if it's a valid level.dat file before we commit
int version;
try {
Level testLevel = Level.load(levelDatFile);
version = testLevel.getVersion();
} catch (IOException e) {
logger.error("IOException while analysing map " + levelDatFile, e);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
return;
} catch (IllegalArgumentException e) {
logger.error("IllegalArgumentException while analysing map " + levelDatFile, e);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
return;
} catch (NullPointerException e) {
logger.error("NullPointerException while analysing map " + levelDatFile, e);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
return;
}
// Other sanity checks
if ((version != SUPPORTED_VERSION_1) && (version != SUPPORTED_VERSION_2)) {
logger.error("Unsupported Minecraft version while analysing map " + levelDatFile);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("unsupported.minecraft.version"), strings.getString("unsupported.version"), JOptionPane.ERROR_MESSAGE);
return;
}
File regionDir = new File(worldDir, "region");
if (!regionDir.isDirectory()) {
logger.error("Region directory missing while analysing map " + levelDatFile);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("the.region.folder.is.missing"), strings.getString("region.folder.missing"), JOptionPane.ERROR_MESSAGE);
return;
}
final Pattern regionFilePattern = (version == SUPPORTED_VERSION_1) ? Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mcr") : Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca");
final File[] regionFiles = regionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
if ((regionFiles == null) || (regionFiles.length == 0)) {
logger.error("Region files missing while analysing map " + levelDatFile);
JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("the.region.folder.contains.no.region.files"), strings.getString("region.files.missing"), JOptionPane.ERROR_MESSAGE);
return;
}
// Check for Nether and End
boolean netherPresent = false, endPresent = false;
File netherRegionDir = new File(worldDir, "DIM-1/region");
if (netherRegionDir.isDirectory()) {
File[] netherRegionFiles = netherRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
if ((netherRegionFiles != null) && (netherRegionFiles.length > 0)) {
netherPresent = true;
}
}
File endRegionDir = new File(worldDir, "DIM1/region");
if (endRegionDir.isDirectory()) {
File[] endRegionFiles = endRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
if ((endRegionFiles != null) && (endRegionFiles.length > 0)) {
endPresent = true;
}
}
checkBoxImportNether.setEnabled(netherPresent);
checkBoxImportNether.setSelected(netherPresent);
checkBoxImportEnd.setEnabled(endPresent);
checkBoxImportEnd.setSelected(endPresent);
mapStatistics = ProgressDialog.executeTask(this, new ProgressTask<MapStatistics>() {
@Override
public String getName() {
return "Analyzing map...";
}
@Override
public MapStatistics execute(ProgressReceiver progressReceiver) throws OperationCancelled {
MapStatistics stats = new MapStatistics();
int chunkCount = 0;
List<Integer> xValues = new ArrayList<>(), zValues = new ArrayList<>();
List<Point> chunks = new ArrayList<>();
int count = 0;
for (File file : regionFiles) {
String[] nameFrags = file.getName().split("\\.");
int regionX = Integer.parseInt(nameFrags[1]);
int regionZ = Integer.parseInt(nameFrags[2]);
try {
RegionFile regionFile = new RegionFile(file);
try {
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
if (regionFile.containsChunk(x, z)) {
chunkCount++;
int chunkX = regionX * 32 + x, chunkZ = regionZ * 32 + z;
if (chunkX < stats.lowestChunkX) {
stats.lowestChunkX = chunkX;
}
if (chunkX > stats.highestChunkX) {
stats.highestChunkX = chunkX;
}
if (chunkZ < stats.lowestChunkZ) {
stats.lowestChunkZ = chunkZ;
}
if (chunkZ > stats.highestChunkZ) {
stats.highestChunkZ = chunkZ;
}
xValues.add(chunkX);
zValues.add(chunkZ);
chunks.add(new Point(chunkX, chunkZ));
}
}
}
} finally {
regionFile.close();
}
} catch (IOException e) {
throw new RuntimeException("I/O error while analyzing map " + worldDir, e);
}
count++;
progressReceiver.setProgress((float) count / (regionFiles.length + 1));
}
stats.chunkCount = chunkCount;
if (chunkCount == 0) {
// Completely empty map (wrong region file format)?
progressReceiver.setProgress(1.0f);
return stats;
}
Collections.sort(xValues);
int p1 = xValues.size() / 4;
float q1 = xValues.get(p1) * 0.75f + xValues.get(p1 + 1) * 0.25f;
int p2 = xValues.size() / 2;
float q2 = (xValues.get(p2) + xValues.get(p2 + 1)) / 2f;
int p3 = xValues.size() * 3 / 4;
float q3 = xValues.get(p3) * 0.25f + xValues.get(p3 + 1) * 0.75f;
float iqr = q3 - q1;
int lowerLimit = (int) (q2 - iqr * 1.5f);
int upperLimit = (int) (q2 + iqr * 1.5f);
for (Point chunk : chunks) {
if ((chunk.x < lowerLimit) || (chunk.x > upperLimit)) {
stats.outlyingChunks.add(chunk);
}
}
Collections.sort(zValues);
p1 = zValues.size() / 4;
q1 = zValues.get(p1) * 0.75f + zValues.get(p1 + 1) * 0.25f;
p2 = zValues.size() / 2;
q2 = (zValues.get(p2) + zValues.get(p2 + 1)) / 2f;
p3 = zValues.size() * 3 / 4;
q3 = zValues.get(p3) * 0.25f + zValues.get(p3 + 1) * 0.75f;
iqr = q3 - q1;
lowerLimit = (int) (q2 - iqr * 1.5f);
upperLimit = (int) (q2 + iqr * 1.5f);
for (Point chunk : chunks) {
if ((chunk.y < lowerLimit) || (chunk.y > upperLimit)) {
stats.outlyingChunks.add(chunk);
}
}
if (!stats.outlyingChunks.isEmpty()) {
chunks.stream().filter(chunk -> !stats.outlyingChunks.contains(chunk)).forEach(chunk -> {
if (chunk.x < stats.lowestChunkXNoOutliers) {
stats.lowestChunkXNoOutliers = chunk.x;
}
if (chunk.x > stats.highestChunkXNoOutliers) {
stats.highestChunkXNoOutliers = chunk.x;
}
if (chunk.y < stats.lowestChunkZNoOutliers) {
stats.lowestChunkZNoOutliers = chunk.y;
}
if (chunk.y > stats.highestChunkZNoOutliers) {
stats.highestChunkZNoOutliers = chunk.y;
}
});
} else {
stats.lowestChunkXNoOutliers = stats.lowestChunkX;
stats.highestChunkXNoOutliers = stats.highestChunkX;
stats.lowestChunkZNoOutliers = stats.lowestChunkZ;
stats.highestChunkZNoOutliers = stats.highestChunkZ;
}
progressReceiver.setProgress(1.0f);
return stats;
}
}, true);
if ((mapStatistics != null) && (mapStatistics.chunkCount > 0)) {
int width = mapStatistics.highestChunkXNoOutliers - mapStatistics.lowestChunkXNoOutliers + 1;
int length = mapStatistics.highestChunkZNoOutliers - mapStatistics.lowestChunkZNoOutliers + 1;
int area = (mapStatistics.chunkCount - mapStatistics.outlyingChunks.size());
labelWidth.setText(FORMATTER.format(width * 16) + " blocks (from " + FORMATTER.format(mapStatistics.lowestChunkXNoOutliers << 4) + " to " + FORMATTER.format((mapStatistics.highestChunkXNoOutliers << 4) + 15) + "; " + FORMATTER.format(width) + " chunks)");
labelLength.setText(FORMATTER.format(length * 16) + " blocks (from " + FORMATTER.format(mapStatistics.lowestChunkZNoOutliers << 4) + " to " + FORMATTER.format((mapStatistics.highestChunkZNoOutliers << 4) + 15) + "; " + FORMATTER.format(length) + " chunks)");
labelArea.setText(FORMATTER.format(area * 256L) + " blocksĀ² (" + FORMATTER.format(area) + " chunks)");
if (!mapStatistics.outlyingChunks.isEmpty()) {
// There are outlying chunks
int widthWithOutliers = mapStatistics.highestChunkX - mapStatistics.lowestChunkX + 1;
int lengthWithOutliers = mapStatistics.highestChunkZ - mapStatistics.lowestChunkZ + 1;
int areaOfOutliers = mapStatistics.outlyingChunks.size();
labelOutliers1.setVisible(true);
labelOutliers2.setVisible(true);
labelWidthWithOutliers.setText(FORMATTER.format(widthWithOutliers * 16) + " blocks (" + FORMATTER.format(widthWithOutliers) + " chunks)");
labelWidthWithOutliers.setVisible(true);
labelOutliers3.setVisible(true);
labelLengthWithOutliers.setText(FORMATTER.format(lengthWithOutliers * 16) + " blocks (" + FORMATTER.format(lengthWithOutliers) + " chunks)");
labelLengthWithOutliers.setVisible(true);
labelOutliers4.setVisible(true);
labelAreaOutliers.setText(FORMATTER.format(areaOfOutliers * 256L) + " blocksĀ² (" + FORMATTER.format(areaOfOutliers) + " chunks)");
labelAreaOutliers.setVisible(true);
checkBoxImportOutliers.setVisible(true);
// The dialog may need to become bigger:
pack();
}
}
}
use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.
the class DumpEntities method main.
public static void main(String[] args) throws IOException {
File worldDir = new File(args[0]);
File[] regionFiles = new File(worldDir, "region").listFiles();
for (File file : regionFiles) {
RegionFile regionFile = new RegionFile(file);
try {
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
if (regionFile.containsChunk(x, z)) {
CompoundTag tag;
try (NBTInputStream in = new NBTInputStream(regionFile.getChunkDataInputStream(x, z))) {
tag = (CompoundTag) in.readTag();
}
ChunkImpl2 chunk = new ChunkImpl2(tag, 256);
/*&& (((Painting) entity).getTileX() == 40) && (((Painting) entity).getTileZ() == 31)*/
chunk.getEntities().stream().filter(entity -> (entity instanceof Painting)).forEach(System.out::println);
}
}
}
} finally {
regionFile.close();
}
}
}
use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.
the class RegionFileNode method loadChildren.
@Override
protected Node[] loadChildren() {
try {
List<Node> chunks = new ArrayList<>();
RegionFile regionFile = new RegionFile(file);
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (regionFile.containsChunk(chunkX, chunkZ)) {
chunks.add(new ChunkNode(regionFile, chunkX, chunkZ));
}
}
}
return chunks.toArray(new Node[chunks.size()]);
} catch (IOException e) {
throw new RuntimeException("I/O error while reading region file", e);
}
}
use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.
the class Mapper method map.
private static void map(final File worldDir, final int dim, final ColourScheme colourScheme, File output) throws IOException, InterruptedException {
File levelDatFile = new File(worldDir, "level.dat");
Level level = Level.load(levelDatFile);
final Platform platform = level.getVersion() == SUPPORTED_VERSION_1 ? DefaultPlugin.JAVA_MCREGION : DefaultPlugin.JAVA_ANVIL;
maxHeight = level.getMaxHeight();
File dimensionDir;
switch(dim) {
case 0:
dimensionDir = worldDir;
break;
case 1:
dimensionDir = new File(worldDir, "DIM-1");
break;
case 2:
dimensionDir = new File(worldDir, "DIM1");
break;
default:
throw new IllegalArgumentException(Integer.toString(dim));
}
final File regionDir = new File(dimensionDir, "region");
if (!regionDir.exists()) {
error("Map does not have dimension " + dim);
}
System.out.println("Mapping " + worldDir);
System.out.println("Name: " + level.getName());
System.out.println("Seed: " + level.getSeed());
if (level.getGeneratorName() != null) {
System.out.println("Generator: " + level.getGeneratorName() + " (version " + level.getGeneratorVersion() + ")");
}
System.out.println("Map height: " + maxHeight);
System.out.println("Storage format: " + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? "McRegion (Minecraft 1.1 or earlier)" : "Anvil (Minecraft 1.2 or later)"));
// Determine size
File[] regionFiles = regionDir.listFiles(platform.equals(DefaultPlugin.JAVA_MCREGION) ? (dir, name) -> name.toLowerCase().endsWith(".mcr") : (FilenameFilter) (dir, name) -> name.toLowerCase().endsWith(".mca"));
int tmpLowestRegionX = Integer.MAX_VALUE, tmpHighestRegionX = Integer.MIN_VALUE;
int tmpLowestRegionZ = Integer.MAX_VALUE, tmpHighestRegionZ = Integer.MIN_VALUE;
for (File regionFile : regionFiles) {
String[] parts = regionFile.getName().split("\\.");
int regionX = Integer.parseInt(parts[1]);
int regionZ = Integer.parseInt(parts[2]);
if (regionX < tmpLowestRegionX) {
tmpLowestRegionX = regionX;
}
if (regionX > tmpHighestRegionX) {
tmpHighestRegionX = regionX;
}
if (regionZ < tmpLowestRegionZ) {
tmpLowestRegionZ = regionZ;
}
if (regionZ > tmpHighestRegionZ) {
tmpHighestRegionZ = regionZ;
}
}
final int lowestRegionX = tmpLowestRegionX, highestRegionX = tmpHighestRegionX;
final int lowestRegionZ = tmpLowestRegionZ, highestRegionZ = tmpHighestRegionZ;
int tmpLowestChunkX = Integer.MAX_VALUE, tmpHighestChunkX = Integer.MIN_VALUE;
int tmpLowestChunkZ = Integer.MAX_VALUE, tmpHighestChunkZ = Integer.MIN_VALUE;
for (int regionX = lowestRegionX; regionX <= highestRegionX; regionX++) {
File file = new File(regionDir, "r." + regionX + "." + lowestRegionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
if (file.exists()) {
int regionChunkX = regionX << 5;
int regionChunkZ = lowestRegionZ << 5;
RegionFile region = new RegionFile(file);
try {
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (region.containsChunk(chunkX, chunkZ)) {
int x = regionChunkX + chunkX;
int z = regionChunkZ + chunkZ;
if (x < tmpLowestChunkX) {
tmpLowestChunkX = x;
}
if (x > tmpHighestChunkX) {
tmpHighestChunkX = x;
}
if (z < tmpLowestChunkZ) {
tmpLowestChunkZ = z;
}
if (z > tmpHighestChunkZ) {
tmpHighestChunkZ = z;
}
}
}
}
} finally {
region.close();
}
}
file = new File(regionDir, "r." + regionX + "." + highestRegionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
if (file.exists()) {
int regionChunkX = regionX << 5;
int regionChunkZ = highestRegionZ << 5;
RegionFile region = new RegionFile(file);
try {
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (region.containsChunk(chunkX, chunkZ)) {
int x = regionChunkX + chunkX;
int z = regionChunkZ + chunkZ;
if (x < tmpLowestChunkX) {
tmpLowestChunkX = x;
}
if (x > tmpHighestChunkX) {
tmpHighestChunkX = x;
}
if (z < tmpLowestChunkZ) {
tmpLowestChunkZ = z;
}
if (z > tmpHighestChunkZ) {
tmpHighestChunkZ = z;
}
}
}
}
} finally {
region.close();
}
}
}
for (int regionZ = lowestRegionZ + 1; regionZ <= highestRegionZ - 1; regionZ++) {
File file = new File(regionDir, "r." + lowestRegionX + "." + regionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
if (file.exists()) {
int regionChunkX = lowestRegionX << 5;
int regionChunkZ = regionZ << 5;
RegionFile region = new RegionFile(file);
try {
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (region.containsChunk(chunkX, chunkZ)) {
int x = regionChunkX + chunkX;
int z = regionChunkZ + chunkZ;
if (x < tmpLowestChunkX) {
tmpLowestChunkX = x;
}
if (x > tmpHighestChunkX) {
tmpHighestChunkX = x;
}
if (z < tmpLowestChunkZ) {
tmpLowestChunkZ = z;
}
if (z > tmpHighestChunkZ) {
tmpHighestChunkZ = z;
}
}
}
}
} finally {
region.close();
}
}
file = new File(regionDir, "r." + highestRegionX + "." + regionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
if (file.exists()) {
int regionChunkX = highestRegionX << 5;
int regionChunkZ = regionZ << 5;
RegionFile region = new RegionFile(file);
try {
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (region.containsChunk(chunkX, chunkZ)) {
int x = regionChunkX + chunkX;
int z = regionChunkZ + chunkZ;
if (x < tmpLowestChunkX) {
tmpLowestChunkX = x;
}
if (x > tmpHighestChunkX) {
tmpHighestChunkX = x;
}
if (z < tmpLowestChunkZ) {
tmpLowestChunkZ = z;
}
if (z > tmpHighestChunkZ) {
tmpHighestChunkZ = z;
}
}
}
}
} finally {
region.close();
}
}
}
final int lowestChunkX = tmpLowestChunkX;
final int lowestChunkZ = tmpLowestChunkZ;
int widthChunks = (tmpHighestChunkX - tmpLowestChunkX + 1);
int heightChunks = (tmpHighestChunkZ - tmpLowestChunkZ + 1);
System.out.println("Width: " + (widthChunks << 4));
System.out.println("Height: " + (heightChunks << 4));
final BufferedImage image = new BufferedImage(widthChunks << 4, heightChunks << 4, BufferedImage.TYPE_INT_ARGB);
final int imageOffsetX = lowestChunkX << 4;
final int imageOffsetY = lowestChunkZ << 4;
final int waterColour = colourScheme.getColour(Material.WATER);
final int lavaColour = colourScheme.getColour(Material.LAVA);
final int snowColour = colourScheme.getColour(Material.SNOW);
int threads = Runtime.getRuntime().availableProcessors();
System.out.print("Mapping");
ExecutorService executorService = Executors.newFixedThreadPool(threads);
for (File file : regionFiles) {
final File finalFile = file;
executorService.submit(() -> {
try {
String[] parts = finalFile.getName().split("\\.");
int regionX = Integer.parseInt(parts[1]);
int regionY = Integer.parseInt(parts[2]);
WorldRegion world = new WorldRegion(worldDir, dim, regionX, regionY, maxHeight, platform);
int[][] heightCache = new int[544][544];
for (int i = 0; i < 544; i++) {
Arrays.fill(heightCache[i], -1);
}
for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkY = 0; chunkY < 32; chunkY++) {
int worldChunkX = (regionX << 5) | chunkX;
int worldChunkY = (regionY << 5) | chunkY;
if (world.isChunkPresent(worldChunkX, worldChunkY)) {
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
int worldX = (worldChunkX << 4) | x;
int worldY = (worldChunkY << 4) | y;
boolean snow = false, water = false, lava = false;
int waterLevel = 0;
for (int height = maxHeight - 1; height >= 0; height--) {
int blockType = world.getBlockTypeAt(worldX, worldY, height);
if (blockType != BLK_AIR) {
if (blockType == BLK_SNOW) {
snow = true;
} else if ((blockType == BLK_STATIONARY_WATER) || (blockType == BLK_WATER) || (blockType == BLK_STATIONARY_LAVA) || (blockType == BLK_LAVA)) {
if ((world.getDataAt(worldX, worldY, height) == 0) && (waterLevel == 0)) {
waterLevel = height;
if ((blockType == BLK_LAVA) || (blockType == BLK_STATIONARY_LAVA)) {
lava = true;
} else {
water = true;
}
}
} else if (TERRAIN_BLOCKS.contains(blockType)) {
// Terrain found
int data = world.getDataAt(worldX, worldY, height);
int depth = waterLevel - height;
int fluidAlpha = 0xff >> Math.min(depth, 3);
int colour = colourScheme.getColour(blockType, data);
if (depth > 0) {
colour = ColourUtils.multiply(colour, getBrightenAmount(world, heightCache, ((chunkX + 1) << 4) | x, ((chunkY + 1) << 4) | y, regionX, regionY));
}
if (water) {
colour = ColourUtils.mix(colour, waterColour, fluidAlpha);
} else if (lava) {
colour = ColourUtils.mix(colour, lavaColour, fluidAlpha);
}
if (snow) {
colour = ColourUtils.mix(colour, snowColour, 64);
}
if (depth <= 0) {
colour = ColourUtils.multiply(colour, getBrightenAmount(world, heightCache, ((chunkX + 1) << 4) | x, ((chunkY + 1) << 4) | y, regionX, regionY));
}
image.setRGB(worldX - imageOffsetX, worldY - imageOffsetY, 0xff000000 | colour);
break;
} else {
// Non-terrain block found (not shaded)
int data = world.getDataAt(worldX, worldY, height);
int depth = waterLevel - height;
int fluidAlpha = 0xff >> Math.min(depth, 3);
int colour = colourScheme.getColour(blockType, data);
if (water) {
colour = ColourUtils.mix(colour, waterColour, fluidAlpha);
} else if (lava) {
colour = ColourUtils.mix(colour, lavaColour, fluidAlpha);
}
if (snow) {
colour = ColourUtils.mix(colour, snowColour);
}
image.setRGB(worldX - imageOffsetX, worldY - imageOffsetY, 0xff000000 | colour);
break;
}
}
}
}
}
}
}
}
System.out.print('.');
System.out.flush();
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
});
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
System.out.println();
// Save image
System.out.println("Saving image to " + output + "...");
ImageIO.write(image, "PNG", output);
System.out.println("Finished");
}
Aggregations