/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.pepsoft.worldpainter.importing; import org.pepsoft.minecraft.Level; import org.pepsoft.minecraft.RegionFile; import org.pepsoft.util.FileUtils; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.ProgressReceiver.OperationCancelled; import org.pepsoft.util.swing.ProgressDialog; import org.pepsoft.util.swing.ProgressTask; import org.pepsoft.worldpainter.*; import org.pepsoft.worldpainter.util.MinecraftUtil; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.filechooser.FileFilter; import java.awt.*; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.text.NumberFormat; import java.util.*; import java.util.List; import java.util.regex.Pattern; import static org.pepsoft.minecraft.Constants.SUPPORTED_VERSION_1; import static org.pepsoft.minecraft.Constants.SUPPORTED_VERSION_2; /** * * @author SchmitzP */ public class MapImportDialog extends WorldPainterDialog { /** * Creates new form MapImportDialog */ public MapImportDialog(App app) { super(app); this.app = app; initComponents(); resetStats(); fieldFilename.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { checkSelection(); setControlStates(); } @Override public void removeUpdate(DocumentEvent e) { checkSelection(); setControlStates(); } @Override public void changedUpdate(DocumentEvent e) { checkSelection(); setControlStates(); } }); getRootPane().setDefaultButton(buttonOK); setLocationRelativeTo(app); } public World2 getImportedWorld() { return importedWorld; } private void checkSelection() { String fileStr = fieldFilename.getText(); if (fileStr.endsWith("level.dat")) { File file = new File(fileStr); if (file.isFile() && (! file.equals(previouslySelectedFile))) { previouslySelectedFile = file; 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(); } } } private void setControlStates() { String fileStr = fieldFilename.getText().trim(); File file = (! fileStr.isEmpty()) ? new File(fileStr) : null; if ((mapStatistics == null) || (mapStatistics.chunkCount == 0) || (file == null) || (! file.isFile())) { buttonOK.setEnabled(false); } else { buttonOK.setEnabled(true); } } private void resetStats() { labelWidth.setText("0 blocks (from ? to ?; 0 chunks)"); labelLength.setText("0 blocks (from ? to ?; 0 chunks)"); labelArea.setText("0 blocks² (0 chunks)"); labelOutliers1.setVisible(false); labelOutliers2.setVisible(false); labelWidthWithOutliers.setVisible(false); labelOutliers3.setVisible(false); labelLengthWithOutliers.setVisible(false); labelOutliers4.setVisible(false); labelAreaOutliers.setVisible(false); checkBoxImportOutliers.setSelected(false); checkBoxImportOutliers.setVisible(false); } private void selectFile() { File mySavesDir = Configuration.getInstance().getSavesDirectory(); if ((mySavesDir == null) && (MinecraftUtil.findMinecraftDir() != null)) { mySavesDir = new File(MinecraftUtil.findMinecraftDir(), "saves"); } File selectedFile = FileUtils.selectFileForOpen(this, "Select Minecraft map level.dat file", mySavesDir, new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || f.getName().equalsIgnoreCase("level.dat"); } @Override public String getDescription() { return strings.getString("minecraft.level.dat.file"); } }); if (selectedFile != null) { fieldFilename.setText(selectedFile.getAbsolutePath()); } } private void importWorld() { final File levelDatFile = new File(fieldFilename.getText()); final Set<Point> chunksToSkip = checkBoxImportOutliers.isSelected() ? null : mapStatistics.outlyingChunks; final MapImporter.ReadOnlyOption readOnlyOption; if (radioButtonReadOnlyAll.isSelected()) { readOnlyOption = MapImporter.ReadOnlyOption.ALL; } else if (radioButtonReadOnlyManMade.isSelected()) { readOnlyOption = MapImporter.ReadOnlyOption.MAN_MADE; } else if (radioButtonReadOnlyManMadeAboveGround.isSelected()) { readOnlyOption = MapImporter.ReadOnlyOption.MAN_MADE_ABOVE_GROUND; } else { readOnlyOption = MapImporter.ReadOnlyOption.NONE; } app.setWorld(null); importedWorld = ProgressDialog.executeTask(this, new ProgressTask<World2>() { @Override public String getName() { return strings.getString("importing.world"); } @Override public World2 execute(ProgressReceiver progressReceiver) throws OperationCancelled { try { Level level = Level.load(levelDatFile); int maxHeight = level.getMaxHeight(); int waterLevel; if (level.getVersion() == SUPPORTED_VERSION_1) { waterLevel = maxHeight / 2 - 2; } else { waterLevel = 62; } int terrainLevel = waterLevel - 4; TileFactory tileFactory = TileFactoryFactory.createNoiseTileFactory(0, Terrain.GRASS, maxHeight, terrainLevel, waterLevel, false, true, 20, 1.0); Set<Integer> dimensionsToImport = new HashSet<>(3); dimensionsToImport.add(Constants.DIM_NORMAL); if (checkBoxImportNether.isSelected()) { dimensionsToImport.add(Constants.DIM_NETHER); } if (checkBoxImportEnd.isSelected()) { dimensionsToImport.add(Constants.DIM_END); } final MapImporter importer = new MapImporter(tileFactory, levelDatFile, false, chunksToSkip, readOnlyOption, dimensionsToImport); World2 world = importer.doImport(progressReceiver); if (importer.getWarnings() != null) { try { SwingUtilities.invokeAndWait(() -> { Icon warningIcon = UIManager.getIcon("OptionPane.warningIcon"); Toolkit.getDefaultToolkit().beep(); int selectedOption = JOptionPane.showOptionDialog(MapImportDialog.this, strings.getString("the.import.process.generated.warnings"), strings.getString("import.warnings"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, warningIcon, new Object[] {strings.getString("review.warnings"), strings.getString("ok")}, null); if (selectedOption == 0) { ImportWarningsDialog warningsDialog = new ImportWarningsDialog(MapImportDialog.this, strings.getString("import.warnings")); warningsDialog.setWarnings(importer.getWarnings()); warningsDialog.setVisible(true); } }); } catch (InterruptedException | InvocationTargetException e) { throw new RuntimeException(e); } } return world; } catch (IOException e) { throw new RuntimeException("I/O error while importing world", e); } } }, true); if (importedWorld == null) { // The import was cancelled cancel(); return; } importedWorld.setDirty(false); Configuration config = Configuration.getInstance(); config.setSavesDirectory(levelDatFile.getParentFile().getParentFile()); ok(); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { buttonGroup1 = new javax.swing.ButtonGroup(); jLabel1 = new javax.swing.JLabel(); fieldFilename = new javax.swing.JTextField(); buttonSelectFile = new javax.swing.JButton(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); labelWidth = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); labelLength = new javax.swing.JLabel(); jLabel7 = new javax.swing.JLabel(); labelArea = new javax.swing.JLabel(); labelOutliers3 = new javax.swing.JLabel(); labelOutliers2 = new javax.swing.JLabel(); labelOutliers1 = new javax.swing.JLabel(); labelWidthWithOutliers = new javax.swing.JLabel(); labelLengthWithOutliers = new javax.swing.JLabel(); labelOutliers4 = new javax.swing.JLabel(); labelAreaOutliers = new javax.swing.JLabel(); buttonCancel = new javax.swing.JButton(); buttonOK = new javax.swing.JButton(); checkBoxImportOutliers = new javax.swing.JCheckBox(); jLabel5 = new javax.swing.JLabel(); radioButtonReadOnlyNone = new javax.swing.JRadioButton(); radioButtonReadOnlyManMade = new javax.swing.JRadioButton(); radioButtonReadOnlyAll = new javax.swing.JRadioButton(); radioButtonReadOnlyManMadeAboveGround = new javax.swing.JRadioButton(); checkBoxImportSurface = new javax.swing.JCheckBox(); checkBoxImportNether = new javax.swing.JCheckBox(); checkBoxImportEnd = new javax.swing.JCheckBox(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Import Existing Minecraft Map"); jLabel1.setText("Select the level.dat file of an existing Minecraft map:"); buttonSelectFile.setText("..."); buttonSelectFile.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonSelectFileActionPerformed(evt); } }); jLabel2.setText("Statistics for surface:"); jLabel3.setText("Width:"); labelWidth.setText("0"); jLabel4.setText("Length:"); labelLength.setText("0"); jLabel7.setText("Area:"); labelArea.setText("0"); labelOutliers3.setText("Length including outliers:"); labelOutliers2.setText("Width including outliers:"); labelOutliers1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/pepsoft/worldpainter/icons/error.png"))); // NOI18N labelOutliers1.setText("This map has rogue outlying chunks!"); labelWidthWithOutliers.setText("0"); labelLengthWithOutliers.setText("0"); labelOutliers4.setText("Area of outlying chunks:"); labelAreaOutliers.setText("0"); buttonCancel.setText("Cancel"); buttonCancel.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonCancelActionPerformed(evt); } }); buttonOK.setText("OK"); buttonOK.setEnabled(false); buttonOK.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonOKActionPerformed(evt); } }); checkBoxImportOutliers.setText("include outlying chunks in import"); jLabel5.setText("Options:"); buttonGroup1.add(radioButtonReadOnlyNone); radioButtonReadOnlyNone.setText("do not mark any chunks read-only"); buttonGroup1.add(radioButtonReadOnlyManMade); radioButtonReadOnlyManMade.setText("mark chunks containing man-made blocks read-only"); buttonGroup1.add(radioButtonReadOnlyAll); radioButtonReadOnlyAll.setText("mark all chunks read-only"); buttonGroup1.add(radioButtonReadOnlyManMadeAboveGround); radioButtonReadOnlyManMadeAboveGround.setSelected(true); radioButtonReadOnlyManMadeAboveGround.setText("<html>mark chunks containing man-made blocks <i>above ground</i> read-only</html>"); checkBoxImportSurface.setSelected(true); checkBoxImportSurface.setText("Import Surface"); checkBoxImportSurface.setEnabled(false); checkBoxImportNether.setText("Import Nether"); checkBoxImportNether.setEnabled(false); checkBoxImportEnd.setText("Import End"); checkBoxImportEnd.setEnabled(false); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(fieldFilename) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonSelectFile)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(buttonOK) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonCancel)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(radioButtonReadOnlyManMadeAboveGround, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(radioButtonReadOnlyAll) .addComponent(radioButtonReadOnlyManMade) .addComponent(radioButtonReadOnlyNone) .addComponent(jLabel1) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelLength)) .addGroup(layout.createSequentialGroup() .addComponent(jLabel3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelWidth)) .addGroup(layout.createSequentialGroup() .addComponent(jLabel7) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelArea))) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(labelOutliers4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelAreaOutliers)) .addGroup(layout.createSequentialGroup() .addComponent(labelOutliers2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelWidthWithOutliers)) .addGroup(layout.createSequentialGroup() .addComponent(labelOutliers3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(labelLengthWithOutliers)) .addComponent(checkBoxImportOutliers))) .addComponent(jLabel5) .addGroup(layout.createSequentialGroup() .addComponent(jLabel2) .addGap(18, 18, 18) .addComponent(labelOutliers1)) .addGroup(layout.createSequentialGroup() .addComponent(checkBoxImportSurface) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(checkBoxImportNether) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(checkBoxImportEnd))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fieldFilename, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(buttonSelectFile)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(labelOutliers1)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(labelWidth) .addComponent(labelOutliers2) .addComponent(labelWidthWithOutliers)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(labelLength) .addComponent(labelOutliers3) .addComponent(labelLengthWithOutliers)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel7) .addComponent(labelArea) .addComponent(labelOutliers4) .addComponent(labelAreaOutliers)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(checkBoxImportOutliers) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(checkBoxImportSurface) .addComponent(checkBoxImportNether) .addComponent(checkBoxImportEnd)) .addGap(18, 18, 18) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(radioButtonReadOnlyNone) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(radioButtonReadOnlyManMadeAboveGround, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(radioButtonReadOnlyManMade) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(radioButtonReadOnlyAll) .addGap(18, 18, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(buttonCancel) .addComponent(buttonOK)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void buttonSelectFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSelectFileActionPerformed selectFile(); }//GEN-LAST:event_buttonSelectFileActionPerformed private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed importWorld(); }//GEN-LAST:event_buttonOKActionPerformed private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed cancel(); }//GEN-LAST:event_buttonCancelActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonCancel; private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JButton buttonOK; private javax.swing.JButton buttonSelectFile; private javax.swing.JCheckBox checkBoxImportEnd; private javax.swing.JCheckBox checkBoxImportNether; private javax.swing.JCheckBox checkBoxImportOutliers; private javax.swing.JCheckBox checkBoxImportSurface; private javax.swing.JTextField fieldFilename; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel7; private javax.swing.JLabel labelArea; private javax.swing.JLabel labelAreaOutliers; private javax.swing.JLabel labelLength; private javax.swing.JLabel labelLengthWithOutliers; private javax.swing.JLabel labelOutliers1; private javax.swing.JLabel labelOutliers2; private javax.swing.JLabel labelOutliers3; private javax.swing.JLabel labelOutliers4; private javax.swing.JLabel labelWidth; private javax.swing.JLabel labelWidthWithOutliers; private javax.swing.JRadioButton radioButtonReadOnlyAll; private javax.swing.JRadioButton radioButtonReadOnlyManMade; private javax.swing.JRadioButton radioButtonReadOnlyManMadeAboveGround; private javax.swing.JRadioButton radioButtonReadOnlyNone; // End of variables declaration//GEN-END:variables private final App app; private File previouslySelectedFile; private MapStatistics mapStatistics; private World2 importedWorld; private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MapImportDialog.class); private static final ResourceBundle strings = ResourceBundle.getBundle("org.pepsoft.worldpainter.resources.strings"); // NOI18N private static final NumberFormat FORMATTER = NumberFormat.getIntegerInstance(); private static final long serialVersionUID = 1L; static class MapStatistics { int lowestChunkX = Integer.MAX_VALUE, lowestChunkZ = Integer.MAX_VALUE, highestChunkX = Integer.MIN_VALUE, highestChunkZ = Integer.MIN_VALUE; int lowestChunkXNoOutliers = Integer.MAX_VALUE, lowestChunkZNoOutliers = Integer.MAX_VALUE, highestChunkXNoOutliers = Integer.MIN_VALUE, highestChunkZNoOutliers = Integer.MIN_VALUE; int chunkCount; final Set<Point> outlyingChunks = new HashSet<>(); String errorMessage; } }