use of org.pepsoft.worldpainter.Dimension in project WorldPainter by Captain-Chaos.
the class MouseOrTabletOperation method mousePressed.
// MouseListener (these methods are only invoked in legacy mode)
@Override
public void mousePressed(MouseEvent me) {
x = me.getX();
y = me.getY();
altDown = me.isAltDown() || me.isAltGraphDown();
undo = (me.getButton() == MouseEvent.BUTTON3) || altDown;
ctrlDown = me.isControlDown() || me.isMetaDown();
shiftDown = me.isShiftDown();
first = true;
if (!oneShot) {
if (timer == null) {
timer = new Timer(delay, e -> {
Point worldCoords = view.viewToWorld((int) x, (int) y);
tick(worldCoords.x, worldCoords.y, undo, first, 1.0f);
view.updateStatusBar(worldCoords.x, worldCoords.y);
first = false;
});
timer.setInitialDelay(0);
timer.start();
// start = System.currentTimeMillis();
}
} else {
Point worldCoords = view.viewToWorld((int) x, (int) y);
tick(worldCoords.x, worldCoords.y, undo, true, 1.0f);
view.updateStatusBar(worldCoords.x, worldCoords.y);
Dimension dimension = getDimension();
if (dimension != null) {
dimension.armSavePoint();
}
logOperation(undo ? statisticsKeyUndo : statisticsKey);
}
}
use of org.pepsoft.worldpainter.Dimension in project WorldPainter by Captain-Chaos.
the class AbstractWorldExporter method secondPass.
protected List<Fixup> secondPass(List<Layer> secondaryPassLayers, Dimension dimension, MinecraftWorld minecraftWorld, Map<Layer, LayerExporter> exporters, Collection<Tile> tiles, Point regionCoords, ProgressReceiver progressReceiver) throws OperationCancelled {
// Apply other secondary pass layers
if (logger.isDebugEnabled()) {
logger.debug("Start of second pass for region {},{}", regionCoords.x, regionCoords.y);
}
int layerCount = secondaryPassLayers.size(), counter = 0;
Rectangle area = new Rectangle((regionCoords.x << 9) - 16, (regionCoords.y << 9) - 16, 544, 544);
Rectangle exportedArea = new Rectangle((regionCoords.x << 9), (regionCoords.y << 9), 512, 512);
List<Fixup> fixups = new ArrayList<>();
// boolean frost = false;
for (Layer layer : secondaryPassLayers) {
// if (layer instanceof Frost) {
// frost = true;
// continue;
// }
@SuppressWarnings("unchecked") SecondPassLayerExporter exporter = (SecondPassLayerExporter) exporters.get(layer);
if (logger.isDebugEnabled()) {
logger.debug("Exporting layer {} for region {},{}", layer, regionCoords.x, regionCoords.y);
}
if (progressReceiver != null) {
if (minecraftWorld instanceof InvertedWorld) {
progressReceiver.setMessage("Exporting layer " + layer + " for ceiling");
} else {
progressReceiver.setMessage("Exporting layer " + layer);
}
}
List<Fixup> layerFixups = exporter.render(dimension, area, exportedArea, minecraftWorld);
if (layerFixups != null) {
fixups.addAll(layerFixups);
}
if (progressReceiver != null) {
counter++;
progressReceiver.setProgress((float) counter / layerCount);
}
}
// Garden / seeds first and second pass
GardenExporter gardenExporter = new GardenExporter();
Set<Seed> firstPassProcessedSeeds = new HashSet<>();
Set<Seed> secondPassProcessedSeeds = new HashSet<>();
tiles.stream().filter(tile -> tile.getLayers().contains(GardenCategory.INSTANCE)).forEach(tile -> {
gardenExporter.firstPass(dimension, tile, minecraftWorld, firstPassProcessedSeeds);
gardenExporter.secondPass(dimension, tile, minecraftWorld, secondPassProcessedSeeds);
});
// elegant
if ((dimension.getDim() == 0) && world.isCreateGoodiesChest()) {
Point goodiesPoint = (Point) world.getSpawnPoint().clone();
goodiesPoint.translate(3, 3);
int height = Math.min(dimension.getIntHeightAt(goodiesPoint) + 1, dimension.getMaxHeight() - 1);
minecraftWorld.setMaterialAt(goodiesPoint.x, goodiesPoint.y, height, Material.CHEST_NORTH);
Chunk chunk = minecraftWorld.getChunk(goodiesPoint.x >> 4, goodiesPoint.y >> 4);
if ((chunk != null) && (chunk.getTileEntities() != null)) {
Chest goodiesChest = createGoodiesChest();
goodiesChest.setX(goodiesPoint.x);
goodiesChest.setY(height);
goodiesChest.setZ(goodiesPoint.y);
chunk.getTileEntities().add(goodiesChest);
}
}
if (logger.isDebugEnabled()) {
logger.debug("End of second pass for region {},{}", regionCoords.x, regionCoords.y);
}
return fixups;
}
use of org.pepsoft.worldpainter.Dimension in project WorldPainter by Captain-Chaos.
the class JavaWorldMerger method mergeBiomes.
/**
* Merge only the biomes, leave everything else the same.
*/
public void mergeBiomes(File backupDir, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
// Read existing level.dat file and perform sanity checks
Level level = performSanityChecks(true);
// Backup existing level
File worldDir = levelDatFile.getParentFile();
if (!worldDir.renameTo(backupDir)) {
throw new FileInUseException("Could not move " + worldDir + " to " + backupDir);
}
if (!worldDir.mkdirs()) {
throw new IOException("Could not create " + worldDir);
}
// Copy everything that we are not going to generate (this includes the
// Nether and End dimensions)
File[] files = backupDir.listFiles();
// noinspection ConstantConditions // Cannot happen because we previously loaded level.dat from it
for (File file : files) {
if ((!file.getName().equalsIgnoreCase("session.lock")) && (!file.getName().equalsIgnoreCase("region"))) {
if (file.isFile()) {
FileUtils.copyFileToDir(file, worldDir);
} else if (file.isDirectory()) {
FileUtils.copyDir(file, new File(worldDir, file.getName()));
} else {
logger.warn("Not copying " + file + "; not a regular file or directory");
}
}
}
// Write session.lock file
File sessionLockFile = new File(worldDir, "session.lock");
try (DataOutputStream sessionOut = new DataOutputStream(new FileOutputStream(sessionLockFile))) {
sessionOut.writeLong(System.currentTimeMillis());
}
// Process all chunks and copy just the biomes
if (progressReceiver != null) {
progressReceiver.setMessage("Merging biomes");
}
// Find all the region files of the existing level
File oldRegionDir = new File(backupDir, "region");
final Pattern regionFilePattern = Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca");
File[] oldRegionFiles = oldRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
// Process each region file, copying every chunk unmodified, except
// for the biomes
// Can only happen for corrupted maps
@SuppressWarnings("ConstantConditions") int totalChunkCount = oldRegionFiles.length * 32 * 32, chunkCount = 0;
File newRegionDir = new File(worldDir, "region");
newRegionDir.mkdirs();
Dimension dimension = world.getDimension(DIM_NORMAL);
for (File file : oldRegionFiles) {
try (RegionFile oldRegion = new RegionFile(file)) {
String[] parts = file.getName().split("\\.");
int regionX = Integer.parseInt(parts[1]);
int regionZ = Integer.parseInt(parts[2]);
File newRegionFile = new File(newRegionDir, "r." + regionX + "." + regionZ + ".mca");
try (RegionFile newRegion = new RegionFile(newRegionFile)) {
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
if (oldRegion.containsChunk(x, z)) {
ChunkImpl2 chunk;
try (NBTInputStream in = new NBTInputStream(oldRegion.getChunkDataInputStream(x, z))) {
CompoundTag tag = (CompoundTag) in.readTag();
chunk = new ChunkImpl2(tag, level.getMaxHeight());
}
int chunkX = chunk.getxPos(), chunkZ = chunk.getzPos();
for (int xx = 0; xx < 16; xx++) {
for (int zz = 0; zz < 16; zz++) {
chunk.setBiome(xx, zz, dimension.getLayerValueAt(Biome.INSTANCE, (chunkX << 4) | xx, (chunkZ << 4) | zz));
}
}
try (NBTOutputStream out = new NBTOutputStream(newRegion.getChunkDataOutputStream(x, z))) {
out.writeTag(chunk.toNBT());
}
}
chunkCount++;
if (progressReceiver != null) {
progressReceiver.setProgress((float) chunkCount / totalChunkCount);
}
}
}
}
}
}
// Rewrite session.lock file
try (DataOutputStream sessionOut = new DataOutputStream(new FileOutputStream(sessionLockFile))) {
sessionOut.writeLong(System.currentTimeMillis());
}
}
use of org.pepsoft.worldpainter.Dimension in project WorldPainter by Captain-Chaos.
the class JavaWorldMerger method merge.
public void merge(File backupDir, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
logger.info("Merging world " + world.getName() + " with map at " + levelDatFile.getParentFile());
// Read existing level.dat file and perform sanity checks
Level level = performSanityChecks(false);
// Record start of export
long start = System.currentTimeMillis();
// Backup existing level
File worldDir = levelDatFile.getParentFile();
if (!worldDir.renameTo(backupDir)) {
throw new FileInUseException("Could not move " + worldDir + " to " + backupDir);
}
if (!worldDir.mkdirs()) {
throw new IOException("Could not create " + worldDir);
}
// Set the world to the same Minecraft version as the existing map, in
// case it has changed. This affects the type of chunks created in the
// first pass
int version = level.getVersion();
Platform platform = (version == SUPPORTED_VERSION_1) ? DefaultPlugin.JAVA_MCREGION : DefaultPlugin.JAVA_ANVIL;
world.setPlatform(platform);
// Modify it if necessary and write it to the the new level
if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) {
Dimension surfaceDimension = world.getDimension(DIM_NORMAL);
level.setSeed(surfaceDimension.getMinecraftSeed());
Point spawnPoint = world.getSpawnPoint();
level.setSpawnX(spawnPoint.x);
level.setSpawnY(Math.max(surfaceDimension.getIntHeightAt(spawnPoint), surfaceDimension.getWaterLevelAt(spawnPoint)));
level.setSpawnZ(spawnPoint.y);
}
// Save the level.dat file. This will also create a session.lock file, hopefully kicking out any Minecraft
// instances which may have the map open:
level.save(worldDir);
// Copy everything that we are not going to generate
File[] files = backupDir.listFiles();
// noinspection ConstantConditions // Cannot happen because we previously loaded level.dat from it
for (File file : files) {
if ((!file.getName().equalsIgnoreCase("level.dat")) && (!file.getName().equalsIgnoreCase("level.dat_old")) && (!file.getName().equalsIgnoreCase("session.lock")) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_NORMAL))) || (!file.getName().equalsIgnoreCase("region"))) && (!file.getName().equalsIgnoreCase("maxheight.txt")) && (!file.getName().equalsIgnoreCase("Height.txt")) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_NETHER))) || (!file.getName().equalsIgnoreCase("DIM-1"))) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_END))) || (!file.getName().equalsIgnoreCase("DIM1")))) {
if (file.isFile()) {
FileUtils.copyFileToDir(file, worldDir);
} else if (file.isDirectory()) {
FileUtils.copyDir(file, new File(worldDir, file.getName()));
} else {
logger.warn("Not copying " + file + "; not a regular file or directory");
}
}
}
if ((selectedDimensions == null) ? (world.getDimension(DIM_NORMAL) != null) : selectedDimensions.contains(DIM_NORMAL)) {
mergeDimension(worldDir, backupDir, world.getDimension(DIM_NORMAL), platform, progressReceiver);
}
if ((selectedDimensions == null) ? (world.getDimension(DIM_NETHER) != null) : selectedDimensions.contains(DIM_NETHER)) {
mergeDimension(worldDir, backupDir, world.getDimension(DIM_NETHER), platform, progressReceiver);
}
if ((selectedDimensions == null) ? (world.getDimension(DIM_END) != null) : selectedDimensions.contains(DIM_END)) {
mergeDimension(worldDir, backupDir, world.getDimension(DIM_END), platform, progressReceiver);
}
// Update the session.lock file, hopefully kicking out any Minecraft instances which may have tried to open the
// map in the mean time:
File sessionLockFile = new File(worldDir, "session.lock");
try (DataOutputStream sessionOut = new DataOutputStream(new FileOutputStream(sessionLockFile))) {
sessionOut.writeLong(System.currentTimeMillis());
}
// Record the merge in the world history
if (selectedDimensions == null) {
world.addHistoryEntry(HistoryEntry.WORLD_MERGED_FULL, level.getName(), worldDir);
} else {
String dimNames = selectedDimensions.stream().map(dim -> {
switch(dim) {
case DIM_NORMAL:
return "Surface";
case DIM_NETHER:
return "Nether";
case DIM_END:
return "End";
default:
return Integer.toString(dim);
}
}).collect(Collectors.joining(", "));
world.addHistoryEntry(HistoryEntry.WORLD_MERGED_PARTIAL, level.getName(), worldDir, dimNames);
}
if (!levelDatFile.equals(world.getMergedWith())) {
world.setMergedWith(levelDatFile);
}
// Log an event
Configuration config = Configuration.getInstance();
if (config != null) {
EventVO event = new EventVO(EVENT_KEY_ACTION_MERGE_WORLD).duration(System.currentTimeMillis() - start);
event.setAttribute(EventVO.ATTRIBUTE_TIMESTAMP, new Date(start));
event.setAttribute(ATTRIBUTE_KEY_MAX_HEIGHT, world.getMaxHeight());
event.setAttribute(ATTRIBUTE_KEY_PLATFORM, world.getPlatform().displayName);
event.setAttribute(ATTRIBUTE_KEY_MAP_FEATURES, world.isMapFeatures());
event.setAttribute(ATTRIBUTE_KEY_GAME_TYPE_NAME, world.getGameType().name());
event.setAttribute(ATTRIBUTE_KEY_ALLOW_CHEATS, world.isAllowCheats());
event.setAttribute(ATTRIBUTE_KEY_GENERATOR, world.getGenerator().name());
if (world.getPlatform().equals(DefaultPlugin.JAVA_ANVIL) && (world.getGenerator() == Generator.FLAT)) {
event.setAttribute(ATTRIBUTE_KEY_GENERATOR_OPTIONS, world.getGeneratorOptions());
}
if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) {
Dimension surfaceDimension = world.getDimension(0);
event.setAttribute(ATTRIBUTE_KEY_TILES, surfaceDimension.getTiles().size());
logLayers(surfaceDimension, event, "");
}
if (world.getImportedFrom() == null) {
event.setAttribute(ATTRIBUTE_KEY_IMPORTED_WORLD, false);
}
config.logEvent(event);
}
}
use of org.pepsoft.worldpainter.Dimension in project WorldPainter by Captain-Chaos.
the class AbstractWorldExporter method parallelExportRegions.
protected final ChunkFactory.Stats parallelExportRegions(Dimension dimension, Platform platform, File worldDir, ProgressReceiver progressReceiver) throws OperationCancelled {
if (progressReceiver != null) {
progressReceiver.setMessage("Exporting " + dimension.getName() + " dimension");
}
long start = System.currentTimeMillis();
final Dimension ceiling;
switch(dimension.getDim()) {
case DIM_NORMAL:
ceiling = dimension.getWorld().getDimension(DIM_NORMAL_CEILING);
break;
case DIM_NETHER:
ceiling = dimension.getWorld().getDimension(DIM_NETHER_CEILING);
break;
case DIM_END:
ceiling = dimension.getWorld().getDimension(DIM_END_CEILING);
break;
default:
throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported");
}
final ChunkFactory.Stats collectedStats = new ChunkFactory.Stats();
boolean wasDirty = dimension.isDirty(), ceilingWasDirty = (ceiling != null) && ceiling.isDirty();
dimension.rememberChanges();
if (ceiling != null) {
ceiling.rememberChanges();
}
try {
final Map<Layer, LayerExporter> exporters = setupDimensionForExport(dimension);
final Map<Layer, LayerExporter> ceilingExporters = (ceiling != null) ? setupDimensionForExport(ceiling) : null;
// Determine regions to export
int lowestRegionX = Integer.MAX_VALUE, highestRegionX = Integer.MIN_VALUE, lowestRegionZ = Integer.MAX_VALUE, highestRegionZ = Integer.MIN_VALUE;
final Set<Point> regions = new HashSet<>(), exportedRegions = new HashSet<>();
final boolean tileSelection = selectedTiles != null;
if (tileSelection) {
// Sanity check
assert selectedDimensions.size() == 1;
assert selectedDimensions.contains(dimension.getDim());
for (Point tile : selectedTiles) {
int regionX = tile.x >> 2;
int regionZ = tile.y >> 2;
regions.add(new Point(regionX, regionZ));
if (regionX < lowestRegionX) {
lowestRegionX = regionX;
}
if (regionX > highestRegionX) {
highestRegionX = regionX;
}
if (regionZ < lowestRegionZ) {
lowestRegionZ = regionZ;
}
if (regionZ > highestRegionZ) {
highestRegionZ = regionZ;
}
}
} else {
for (Tile tile : dimension.getTiles()) {
// Also add regions for any bedrock wall and/or border
// tiles, if present
int r = (((dimension.getBorder() != null) && (!dimension.getBorder().isEndless())) ? dimension.getBorderSize() : 0) + (((dimension.getBorder() == null) || (!dimension.getBorder().isEndless())) && dimension.isBedrockWall() ? 1 : 0);
for (int dx = -r; dx <= r; dx++) {
for (int dy = -r; dy <= r; dy++) {
int regionX = (tile.getX() + dx) >> 2;
int regionZ = (tile.getY() + dy) >> 2;
regions.add(new Point(regionX, regionZ));
if (regionX < lowestRegionX) {
lowestRegionX = regionX;
}
if (regionX > highestRegionX) {
highestRegionX = regionX;
}
if (regionZ < lowestRegionZ) {
lowestRegionZ = regionZ;
}
if (regionZ > highestRegionZ) {
highestRegionZ = regionZ;
}
}
}
}
if (ceiling != null) {
for (Tile tile : ceiling.getTiles()) {
int regionX = tile.getX() >> 2;
int regionZ = tile.getY() >> 2;
regions.add(new Point(regionX, regionZ));
if (regionX < lowestRegionX) {
lowestRegionX = regionX;
}
if (regionX > highestRegionX) {
highestRegionX = regionX;
}
if (regionZ < lowestRegionZ) {
lowestRegionZ = regionZ;
}
if (regionZ > highestRegionZ) {
highestRegionZ = regionZ;
}
}
}
}
// Sort the regions to export the first two rows together, and then
// row by row, to get the optimum tempo of performing fixups
java.util.List<Point> sortedRegions = new ArrayList<>(regions.size());
if (lowestRegionZ == highestRegionZ) {
// No point in sorting it
sortedRegions.addAll(regions);
} else {
for (int x = lowestRegionX; x <= highestRegionX; x++) {
for (int z = lowestRegionZ; z <= (lowestRegionZ + 1); z++) {
Point regionCoords = new Point(x, z);
if (regions.contains(regionCoords)) {
sortedRegions.add(regionCoords);
}
}
}
for (int z = lowestRegionZ + 2; z <= highestRegionZ; z++) {
for (int x = lowestRegionX; x <= highestRegionX; x++) {
Point regionCoords = new Point(x, z);
if (regions.contains(regionCoords)) {
sortedRegions.add(regionCoords);
}
}
}
}
final WorldPainterChunkFactory chunkFactory = new WorldPainterChunkFactory(dimension, exporters, platform, world.getMaxHeight());
final WorldPainterChunkFactory ceilingChunkFactory = (ceiling != null) ? new WorldPainterChunkFactory(ceiling, ceilingExporters, platform, world.getMaxHeight()) : null;
Runtime runtime = Runtime.getRuntime();
runtime.gc();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long memoryInUse = totalMemory - freeMemory;
long maxMemory = runtime.maxMemory();
long maxMemoryAvailable = maxMemory - memoryInUse;
int maxThreadsByMem = (int) (maxMemoryAvailable / 250000000L);
int threads;
if (System.getProperty("org.pepsoft.worldpainter.threads") != null) {
threads = Math.max(Math.min(Integer.parseInt(System.getProperty("org.pepsoft.worldpainter.threads")), sortedRegions.size()), 1);
} else {
threads = Math.max(Math.min(Math.min(maxThreadsByMem, runtime.availableProcessors()), sortedRegions.size()), 1);
}
logger.info("Using " + threads + " thread(s) for export (cores: " + runtime.availableProcessors() + ", available memory: " + (maxMemoryAvailable / 1048576L) + " MB)");
final Map<Point, List<Fixup>> fixups = new HashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(threads, new ThreadFactory() {
@Override
public synchronized Thread newThread(Runnable r) {
Thread thread = new Thread(threadGroup, r, "Exporter-" + nextID++);
thread.setPriority(Thread.MIN_PRIORITY);
return thread;
}
private final ThreadGroup threadGroup = new ThreadGroup("Exporters");
private int nextID = 1;
});
final ParallelProgressManager parallelProgressManager = (progressReceiver != null) ? new ParallelProgressManager(progressReceiver, regions.size()) : null;
try {
// Export each individual region
for (Point region : sortedRegions) {
final Point regionCoords = region;
executor.execute(() -> {
ProgressReceiver progressReceiver1 = (parallelProgressManager != null) ? parallelProgressManager.createProgressReceiver() : null;
if (progressReceiver1 != null) {
try {
progressReceiver1.checkForCancellation();
} catch (OperationCancelled e) {
return;
}
}
try {
WorldRegion worldRegion = new WorldRegion(regionCoords.x, regionCoords.y, dimension.getMaxHeight(), platform);
ExportResults exportResults = null;
try {
exportResults = exportRegion(worldRegion, dimension, ceiling, platform, regionCoords, tileSelection, exporters, ceilingExporters, chunkFactory, ceilingChunkFactory, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.0f, 0.9f) : null);
if (logger.isDebugEnabled()) {
logger.debug("Generated region " + regionCoords.x + "," + regionCoords.y);
}
if (exportResults.chunksGenerated) {
synchronized (collectedStats) {
collectedStats.landArea += exportResults.stats.landArea;
collectedStats.surfaceArea += exportResults.stats.surfaceArea;
collectedStats.waterArea += exportResults.stats.waterArea;
}
}
} finally {
if ((exportResults != null) && exportResults.chunksGenerated) {
long saveStart = System.currentTimeMillis();
worldRegion.save(worldDir, dimension.getDim());
if (logger.isDebugEnabled()) {
logger.debug("Saving region took {} ms", System.currentTimeMillis() - saveStart);
}
}
}
synchronized (fixups) {
if ((exportResults.fixups != null) && (!exportResults.fixups.isEmpty())) {
fixups.put(new Point(regionCoords.x, regionCoords.y), exportResults.fixups);
}
exportedRegions.add(regionCoords);
}
// thread is not already doing it
if (performingFixups.tryAcquire()) {
try {
Map<Point, List<Fixup>> myFixups = new HashMap<>();
synchronized (fixups) {
for (Iterator<Map.Entry<Point, List<Fixup>>> i = fixups.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<Point, List<Fixup>> entry = i.next();
Point fixupRegionCoords = entry.getKey();
if (isReadyForFixups(regions, exportedRegions, fixupRegionCoords)) {
myFixups.put(fixupRegionCoords, entry.getValue());
i.remove();
}
}
}
if (!myFixups.isEmpty()) {
performFixups(worldDir, dimension, platform, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.9f, 0.1f) : null, myFixups);
}
} finally {
performingFixups.release();
}
}
} catch (Throwable t) {
if (progressReceiver1 != null) {
progressReceiver1.exceptionThrown(t);
} else {
logger.error("Exception while exporting region", t);
}
}
});
}
} finally {
executor.shutdown();
try {
executor.awaitTermination(366, TimeUnit.DAYS);
} catch (InterruptedException e) {
throw new RuntimeException("Thread interrupted while waiting for all tasks to finish", e);
}
}
// performing fixups and thread B added new ones and then quit
synchronized (fixups) {
if (!fixups.isEmpty()) {
if (progressReceiver != null) {
progressReceiver.setMessage("Doing remaining fixups for " + dimension.getName());
progressReceiver.reset();
}
performFixups(worldDir, dimension, platform, progressReceiver, fixups);
}
}
// Calculate total size of dimension
collectedStats.time = System.currentTimeMillis() - start;
if (progressReceiver != null) {
progressReceiver.setProgress(1.0f);
}
} finally {
// Undo any changes we made (such as applying any combined layers)
if (dimension.undoChanges()) {
// TODO: some kind of cleverer undo mechanism (undo history
// cloning?) so we don't mess up the user's redo history
dimension.clearRedo();
dimension.armSavePoint();
}
// If the dimension wasn't dirty make sure it still isn't
dimension.setDirty(wasDirty);
if (ceiling != null) {
// Undo any changes we made (such as applying any combined layers)
if (ceiling.undoChanges()) {
// TODO: some kind of cleverer undo mechanism (undo history
// cloning?) so we don't mess up the user's redo history
ceiling.clearRedo();
ceiling.armSavePoint();
}
// If the dimension wasn't dirty make sure it still isn't
ceiling.setDirty(ceilingWasDirty);
}
}
return collectedStats;
}
Aggregations