diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Configuration.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Configuration.java index 6690b46e..f6f01613 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Configuration.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Configuration.java @@ -38,9 +38,9 @@ import static org.pepsoft.minecraft.Material.DIRT; import static org.pepsoft.util.XDG.HOME; import static org.pepsoft.util.XDG.XDG_DATA_HOME; import static org.pepsoft.worldpainter.Configuration.DonationStatus.DONATED; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL_1_15; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.DEFAULT; import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES; import static org.pepsoft.worldpainter.Terrain.ROCK; @@ -843,7 +843,7 @@ public final class Configuration implements Serializable, EventLogger, Minecraft defaultMaxHeight = DEFAULT_MAX_HEIGHT_ANVIL; } if (defaultTerrainAndLayerSettings == null) { - defaultTerrainAndLayerSettings = new World2(JAVA_ANVIL_1_15, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), surface, JAVA_ANVIL_1_15.minZ, defaultMaxHeight, level, waterLevel, lava, beaches, 20, 1.0)).getDimension(DIM_NORMAL); + defaultTerrainAndLayerSettings = new World2(JAVA_ANVIL_1_15, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), surface, JAVA_ANVIL_1_15.minZ, defaultMaxHeight, level, waterLevel, lava, beaches, 20, 1.0)).getDimension(NORMAL_DETAIL); } // New legacy mechanism with version number @@ -1194,7 +1194,7 @@ public final class Configuration implements Serializable, EventLogger, Minecraft // Default view and world settings private boolean checkForUpdates = true, undoEnabled = true, defaultGridEnabled, defaultContoursEnabled = true, defaultViewDistanceEnabled, defaultWalkingDistanceEnabled; private int undoLevels = 100, defaultGridSize = 128, defaultContourSeparation = 10, defaultWidth = 5, defaultHeight = 5, defaultMaxHeight = World2.DEFAULT_MAX_HEIGHT; - private Dimension defaultTerrainAndLayerSettings = new World2(DEFAULT_PLATFORM, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), surface, DEFAULT_PLATFORM.minZ, defaultMaxHeight, level, waterLevel, lava, beaches, 20, 1.0)).getDimension(DIM_NORMAL); + private Dimension defaultTerrainAndLayerSettings = new World2(DEFAULT_PLATFORM, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), surface, DEFAULT_PLATFORM.minZ, defaultMaxHeight, level, waterLevel, lava, beaches, 20, 1.0)).getDimension(NORMAL_DETAIL); private boolean toolbarsLocked; private int version = CURRENT_VERSION, worldFileBackups = 3; private float defaultRange = 20, uiScale; diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Constants.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Constants.java index eb5c2a76..a069af73 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Constants.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Constants.java @@ -43,9 +43,6 @@ public final class Constants { */ public static final int UNKNOWN_MATERIAL_COLOUR = 0xFF00FF; - public static final int DIM_END_CEILING = -3; - public static final int DIM_NETHER_CEILING = -2; - public static final int DIM_NORMAL_CEILING = -1; public static final int DIM_NORMAL = 0; public static final int DIM_NETHER = 1; public static final int DIM_END = 2; diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Dimension.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Dimension.java index 1c2241f9..cf9998fb 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Dimension.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Dimension.java @@ -49,6 +49,8 @@ import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; import static org.pepsoft.minecraft.Material.*; import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; +import static org.pepsoft.worldpainter.Dimension.Role.DETAIL; import static org.pepsoft.worldpainter.Dimension.WallType.BEDROCK; import static org.pepsoft.worldpainter.Generator.*; import static org.pepsoft.worldpainter.biomeschemes.Minecraft1_19Biomes.*; @@ -58,11 +60,11 @@ import static org.pepsoft.worldpainter.biomeschemes.Minecraft1_19Biomes.*; * @author pepijn */ public class Dimension extends InstanceKeeper implements TileProvider, Serializable, Tile.Listener, Cloneable { - public Dimension(World2 world, long minecraftSeed, TileFactory tileFactory, int dim) { - this(world, minecraftSeed, tileFactory, dim, true); + public Dimension(World2 world, long minecraftSeed, TileFactory tileFactory, Anchor anchor) { + this(world, minecraftSeed, tileFactory, anchor, true); } - public Dimension(World2 world, long minecraftSeed, TileFactory tileFactory, int dim, boolean init) { + public Dimension(World2 world, long minecraftSeed, TileFactory tileFactory, Anchor anchor, boolean init) { if (world == null) { throw new NullPointerException("world"); } @@ -70,23 +72,25 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa this.seed = tileFactory.getSeed(); this.minecraftSeed = minecraftSeed; this.tileFactory = tileFactory; - this.dim = dim; + this.anchor = anchor; this.minHeight = tileFactory.getMinHeight(); this.maxHeight = tileFactory.getMaxHeight(); ceilingHeight = maxHeight; if (init) { - layerSettings.put(Resources.INSTANCE, ResourcesExporterSettings.defaultSettings(world.getPlatform(), dim, maxHeight)); + layerSettings.put(Resources.INSTANCE, ResourcesExporterSettings.defaultSettings(world.getPlatform(), anchor.dim, maxHeight)); topLayerDepthNoise = new PerlinNoise(seed + TOP_LAYER_DEPTH_SEED_OFFSET); - switch (dim) { - case DIM_NORMAL: - generator = new SeededGenerator(DEFAULT, minecraftSeed); - break; - case DIM_NETHER: - generator = new SeededGenerator(NETHER, minecraftSeed); - break; - case DIM_END: - generator = new SeededGenerator(END, minecraftSeed); - break; + if (anchor.role == DETAIL) { + switch (anchor.dim) { + case DIM_NORMAL: + generator = new SeededGenerator(DEFAULT, minecraftSeed); + break; + case DIM_NETHER: + generator = new SeededGenerator(NETHER, minecraftSeed); + break; + case DIM_END: + generator = new SeededGenerator(END, minecraftSeed); + break; + } } } } @@ -95,26 +99,36 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa return world; } - public int getDim() { - return dim; + public Anchor getAnchor() { + return anchor; } public String getName() { - switch (dim) { - case -3: - return "End Ceiling"; - case -2: - return "Nether Ceiling"; - case -1: - return "Surface Ceiling"; - case 0: - return "Surface"; - case 1: - return "Nether"; - case 2: - return "End"; + switch (anchor.role) { + case DETAIL: + switch (anchor.dim) { + case 0: + return "Surface" + (anchor.invert ? " Ceiling" : ""); + case 1: + return "Nether" + (anchor.invert ? " Ceiling" : ""); + case 2: + return "End" + (anchor.invert ? " Ceiling" : ""); + default: + return "Dimension " + anchor.dim + (anchor.invert ? " Ceiling" : ""); + } + case MASTER: + switch (anchor.dim) { + case 0: + return "Surface Master" + (anchor.invert ? " Ceiling" : ""); + case 1: + return "Nether Master" + (anchor.invert ? " Ceiling" : ""); + case 2: + return "End Master" + (anchor.invert ? " Ceiling" : ""); + default: + return "Master " + anchor.dim + (anchor.invert ? " Ceiling" : ""); + } default: - return "Dimension " + dim; + throw new InternalError("Unknown role " + anchor.role); } } @@ -1365,12 +1379,10 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa } public final int getAutoBiome(int x, int y) { - switch (dim) { + switch (anchor.dim) { case DIM_NETHER: - case DIM_NETHER_CEILING: return BIOME_HELL; case DIM_END: - case DIM_END_CEILING: return BIOME_SKY; default: Tile tile = getTile(x >> TILE_SIZE_BITS, y >> TILE_SIZE_BITS); @@ -1384,12 +1396,10 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa public final int getAutoBiome(Tile tile, int x, int y) { // TODO add platform support and Minecraft 1.18 biomes - switch (dim) { + switch (anchor.dim) { case DIM_NETHER: - case DIM_NETHER_CEILING: return BIOME_HELL; case DIM_END: - case DIM_END_CEILING: return BIOME_SKY; default: int biome; @@ -1942,6 +1952,28 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa bedrockWall = false; } } + if (wpVersion < 6) { + switch (dim) { + case -3: + anchor = END_DETAIL_CEILING; + break; + case -2: + anchor = NETHER_DETAIL_CEILING; + break; + case -1: + anchor = NORMAL_DETAIL_CEILING; + break; + case DIM_NORMAL: + anchor = NORMAL_DETAIL; + break; + case DIM_NETHER: + anchor = NETHER_DETAIL; + break; + case DIM_END: + anchor = END_DETAIL; + break; + } + } wpVersion = CURRENT_WP_VERSION; // Make sure that any custom layers which somehow ended up in the world @@ -1971,7 +2003,8 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa private final World2 world; private final long seed; - private final int dim; + @Deprecated + private final int dim = 0; final Map tiles = new HashMap<>(); private final TileFactory tileFactory; private int lowestX = Integer.MAX_VALUE, highestX = Integer.MIN_VALUE, lowestY = Integer.MAX_VALUE, highestY = Integer.MIN_VALUE; @@ -2002,6 +2035,7 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa private ExportSettings exportSettings; private MapGenerator generator; private WallType wallType, roofType; + private Anchor anchor; private transient List listeners = new ArrayList<>(); private transient boolean eventsInhibited; private transient Set dirtyTiles = new HashSet<>(); @@ -2022,7 +2056,7 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa private static final long TOP_LAYER_DEPTH_SEED_OFFSET = 180728193; private static final float ROOT_EIGHT = (float) Math.sqrt(8.0); - private static final int CURRENT_WP_VERSION = 5; + private static final int CURRENT_WP_VERSION = 6; private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Dimension.class); private static final long serialVersionUID = 2011062401L; @@ -2286,4 +2320,107 @@ public class Dimension extends InstanceKeeper implements TileProvider, Serializa private final HashSet activeTiles = new HashSet<>(); } + + public static final class Anchor implements Serializable { + public Anchor(int dim, Role role, boolean invert, int layer) { + if (role == null) { + throw new NullPointerException("role"); + } + this.dim = dim; + this.role = role; + this.invert = invert; + this.layer = layer; + } + + @Override + public String toString() { + return dim + + " " + role + + (invert ? " CEILING" : "") + + ((layer != 0) ? (" " + layer) : ""); + } + + @Override + public boolean equals(final Object o) { + return (o instanceof Anchor) + && (((Anchor) o).dim == dim) + && (((Anchor) o).role == role) + && (((Anchor) o).invert == invert) + && (((Anchor) o).layer == layer); + } + + @Override + public int hashCode() { + return 31 * (31 * (31 * dim + role.hashCode()) + (invert ? 1 : 0)) + layer; + } + + /** + * The game dimension to which this anchor refers. See {@link Constants#DIM_NORMAL}, + * {@link Constants#DIM_NETHER} and {@link Constants#DIM_END} for predefined values. Note that they don't + * correspond to the dimension numbers in Minecraft. + */ + public final int dim; + + /** + * The role this anchor plays in the specified game dimension. + */ + public final Role role; + + /** + * Whether this anchor should be exported inverted (e.g. as a ceiling). + */ + public final boolean invert; + + /** + * The layer this anchor occupies in the specified game dimension and role. + */ + public final int layer; + + /** + * Convenience constant for the default dimension (surface detail dimension, not inverted, layer zero). + */ + public static final Anchor NORMAL_DETAIL = new Anchor(DIM_NORMAL, DETAIL, false, 0); + + /** + * Convenience constant for the default Nether dimension (Nether detail dimension, not inverted, layer zero). + */ + public static final Anchor NETHER_DETAIL = new Anchor(DIM_NETHER, DETAIL, false, 0); + + /** + * Convenience constant for the default End dimension (End detail dimension, not inverted, layer zero). + */ + public static final Anchor END_DETAIL = new Anchor(DIM_END, DETAIL, false, 0); + + /** + * Convenience constant for the default dimension ceiling (surface detail dimension, inverted, layer zero). + */ + public static final Anchor NORMAL_DETAIL_CEILING = new Anchor(DIM_NORMAL, DETAIL, true, 0); + + /** + * Convenience constant for the default Nether dimension ceiling (Nether detail dimension, inverted, layer zero). + */ + public static final Anchor NETHER_DETAIL_CEILING = new Anchor(DIM_NETHER, DETAIL, true, 0); + + /** + * Convenience constant for the default End dimension ceiling (End detail dimension, inverted, layer zero). + */ + public static final Anchor END_DETAIL_CEILING = new Anchor(DIM_END, DETAIL, true, 0); + + private static final long serialVersionUID = 1L; + } + + /** + * A role of a {@link Dimension} within a game dimension. + */ + public enum Role { + /** + * A detail dimension. + */ + DETAIL, + + /** + * A master dimension that is exported where no detail dimension exists, at 1:16 scale. + */ + MASTER + } } \ No newline at end of file diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/DimensionSnapshot.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/DimensionSnapshot.java index a29a131e..46911edb 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/DimensionSnapshot.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/DimensionSnapshot.java @@ -19,7 +19,7 @@ import java.util.*; */ public final class DimensionSnapshot extends Dimension { // This cannot be an RODelegatingDimension because all the properties of the dimension need to be frozen public DimensionSnapshot(Dimension dimension, Snapshot snapshot) { - super(dimension.getWorld(), dimension.getMinecraftSeed(), dimension.getTileFactory(), dimension.getDim()); + super(dimension.getWorld(), dimension.getMinecraftSeed(), dimension.getTileFactory(), dimension.getAnchor()); this.dimension = dimension; this.snapshot = snapshot; super.setBorder(dimension.getBorder()); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Platform.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Platform.java index c1f05af8..8af75fce 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Platform.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/Platform.java @@ -67,7 +67,7 @@ public final class Platform implements Serializable { return false; } for (Dimension dimension: world.getDimensions()) { - if ((dimension.getDim() >= 0) && (! supportedDimensions.contains(dimension.getDim()))) { + if ((! dimension.getAnchor().invert) && (! supportedDimensions.contains(dimension.getAnchor().dim))) { return false; } } diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/RODelegatingDimension.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/RODelegatingDimension.java index d96fd261..8df2165e 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/RODelegatingDimension.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/RODelegatingDimension.java @@ -35,7 +35,7 @@ import java.util.*; */ public abstract class RODelegatingDimension extends Dimension { public RODelegatingDimension(Dimension dimension) { - super(dimension.getWorld(), dimension.getMinecraftSeed(), dimension.getTileFactory(), dimension.getDim()); + super(dimension.getWorld(), dimension.getMinecraftSeed(), dimension.getTileFactory(), dimension.getAnchor()); this.dimension = dimension; } @@ -45,8 +45,8 @@ public abstract class RODelegatingDimension extends Dimension { } @Override - public int getDim() { - return dimension.getDim(); + public Anchor getAnchor() { + return dimension.getAnchor(); } @Override diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/TileRenderer.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/TileRenderer.java index 6a4c1eb1..4dc204f4 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/TileRenderer.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/TileRenderer.java @@ -8,6 +8,7 @@ package org.pepsoft.worldpainter; import org.jetbrains.annotations.Contract; import org.pepsoft.util.ColourUtils; import org.pepsoft.util.IconUtils; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager; import org.pepsoft.worldpainter.layers.*; import org.pepsoft.worldpainter.layers.renderers.*; @@ -19,7 +20,8 @@ import java.util.List; import java.util.*; import static org.pepsoft.minecraft.Constants.*; -import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Constants.TILE_SIZE; +import static org.pepsoft.worldpainter.Constants.TILE_SIZE_BITS; /** * This class is not thread-safe! It keeps render state and should only be used to render one tile at a @@ -33,29 +35,8 @@ public final class TileRenderer { this.tileProvider = tileProvider; if ((tileProvider instanceof Dimension) && (((Dimension) tileProvider).getWorld() != null)) { platform = ((Dimension) tileProvider).getWorld().getPlatform(); - switch (((Dimension) tileProvider).getDim()) { - case DIM_NORMAL: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_NORMAL); - break; - case DIM_NETHER: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_NETHER); - break; - case DIM_END: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(DIM_END); - break; - default: - oppositeTileProvider = null; - break; - } + final Anchor anchor = ((Dimension) tileProvider).getAnchor(); + oppositeTileProvider = ((Dimension) tileProvider).getWorld().getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); } else { platform = Configuration.DEFAULT_PLATFORM; oppositeTileProvider = null; @@ -294,8 +275,8 @@ public final class TileRenderer { // } } - public static TileRenderer forWorld(World2 world, int dim, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, int zoom) { - Dimension dimension = world.getDimension(dim); + public static TileRenderer forWorld(World2 world, Anchor anchor, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, int zoom) { + Dimension dimension = world.getDimension(anchor); return new TileRenderer(dimension, colourScheme, customBiomeManager, zoom); } diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WPTileProvider.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WPTileProvider.java index dcde8ccd..a41d3d41 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WPTileProvider.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WPTileProvider.java @@ -10,11 +10,9 @@ import org.pepsoft.util.swing.TileListener; import org.pepsoft.util.swing.TiledImageViewer; import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager; import org.pepsoft.worldpainter.layers.Layer; -import org.pepsoft.worldpainter.layers.NotPresent; import org.pepsoft.worldpainter.layers.renderers.VoidRenderer; import java.awt.*; -import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -25,18 +23,17 @@ import static java.util.Collections.unmodifiableSet; import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.Constants.TILE_SIZE; +import static org.pepsoft.worldpainter.WPTileProvider.Effect.FADE_TO_WHITE; /** - * WorldPainter tile provider for - * {@link TiledImageViewer}s. Provides tiles based on a WorldPainter - * {@link Dimension} and optionally another tile provider which is used where - * the dimension has no tiles, or where chunks are marked {@link NotPresent}. + * WorldPainter tile provider for {@link TiledImageViewer}s. Provides tiles based on a {@link TileProvider}, e.g. a + * WorldPainter {@link Dimension}. * * @author pepijn */ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dimension.Listener, Tile.Listener { - public WPTileProvider(Dimension dimension, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, Set hiddenLayers, boolean contourLines, int contourSeparation, TileRenderer.LightOrigin lightOrigin, boolean showBorder, org.pepsoft.util.swing.TileProvider surroundingTileProvider, boolean active) { - tileProvider = dimension; + public WPTileProvider(TileProvider tileProvider, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, Set hiddenLayers, boolean contourLines, int contourSeparation, TileRenderer.LightOrigin lightOrigin, boolean showBorder, boolean active, Effect effect) { + this.tileProvider = tileProvider; this.colourScheme = colourScheme; this.hiddenLayers = (hiddenLayers != null) ? new HashSet<>(hiddenLayers) : null; this.contourLines = contourLines; @@ -44,33 +41,13 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime this.lightOrigin = lightOrigin; this.active = active; this.customBiomeManager = customBiomeManager; - this.surroundingTileProvider = surroundingTileProvider; - if (surroundingTileProvider != null) { - surroundingTileImageRef = createNewSurroundingTileImageRef(); - } else { - surroundingTileImageRef = null; - } this.showBorder = showBorder; tileRendererRef = createNewTileRendererRef(); + this.effect = effect; } - public WPTileProvider(TileProvider tileProvider, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, Set hiddenLayers, boolean contourLines, int contourSeparation, TileRenderer.LightOrigin lightOrigin, boolean showBorder, org.pepsoft.util.swing.TileProvider surroundingTileProvider) { - this.tileProvider = tileProvider; - this.colourScheme = colourScheme; - this.hiddenLayers = (hiddenLayers != null) ? new HashSet<>(hiddenLayers) : null; - this.contourLines = contourLines; - this.contourSeparation = contourSeparation; - this.lightOrigin = lightOrigin; - active = false; - this.customBiomeManager = customBiomeManager; - this.surroundingTileProvider = surroundingTileProvider; - if (surroundingTileProvider != null) { - surroundingTileImageRef = createNewSurroundingTileImageRef(); - } else { - surroundingTileImageRef = null; - } - this.showBorder = showBorder; - tileRendererRef = createNewTileRendererRef(); + public WPTileProvider(TileProvider tileProvider, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, Set hiddenLayers, boolean contourLines, int contourSeparation, TileRenderer.LightOrigin lightOrigin, boolean showBorder) { + this(tileProvider, colourScheme, customBiomeManager, hiddenLayers, contourLines, contourSeparation, lightOrigin, showBorder, false, null); } public synchronized void setHiddenLayers(Set hiddenLayers) { @@ -93,8 +70,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime @Override public boolean isTilePresent(int x, int y) { if (zoom == 0) { - return getUnzoomedTileType(x, y) != TileType.SURROUNDS - || ((surroundingTileProvider != null) && surroundingTileProvider.isTilePresent(x, y)); + return getUnzoomedTileType(x, y) != TileType.SURROUNDS; } else { final int scale = 1 << -zoom; for (int dx = 0; dx < scale; dx++) { @@ -105,11 +81,6 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime case BEDROCK_WALL: case BARRIER_WALL: return true; - case SURROUNDS: - if ((surroundingTileProvider != null) && surroundingTileProvider.isTilePresent(x, y)) { - return true; - } - break; } } } @@ -123,11 +94,9 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime if (zoom == 0) { return paintUnzoomedTile(tileImage, x, y, imageX, imageY); } else { - Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); + final Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); g2.setComposite(AlphaComposite.Src); try { - Boolean surroundingTileImageAvailable = null; - BufferedImage surroundingTileImage = null; final Color waterColour = new Color(colourScheme.getColour(BLK_WATER)); final Color lavaColour = new Color(colourScheme.getColour(BLK_LAVA)); final Color voidColour = new Color(0x00ffffff & VoidRenderer.getColour(), true); @@ -136,58 +105,15 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime final int subSize = TILE_SIZE / scale; for (int dx = 0; dx < scale; dx++) { for (int dy = 0; dy < scale; dy++) { - TileType tileType = getUnzoomedTileType(x * scale + dx, y * scale + dy); + final TileType tileType = getUnzoomedTileType(x * scale + dx, y * scale + dy); switch (tileType) { case WORLD: - Tile tile = tileProvider.getTile(x * scale + dx, y * scale + dy); - TileRenderer tileRenderer = tileRendererRef.get(); + final Tile tile = tileProvider.getTile(x * scale + dx, y * scale + dy); + final TileRenderer tileRenderer = tileRendererRef.get(); tileRenderer.renderTile(tile, tileImage, dx * subSize, dy * subSize); - - // If the tile has chunks that are marked "not present" and - // there is a surrounding tile provider, copy those chunks from - // there - if (tile.hasLayer(NotPresent.INSTANCE) && (surroundingTileProvider != null)) { - if (surroundingTileImageAvailable == null) { - surroundingTileImage = surroundingTileImageRef.get(); - surroundingTileImageAvailable = surroundingTileProvider.paintTile(surroundingTileImage, x, y, 0, 0); - } - if (surroundingTileImageAvailable) { - for (int chunkX = 0; chunkX < 8; chunkX++) { - final int xInTile = chunkX << 4; - // Copy entire vertical columns of chunks at - // once, if possible, as a performance - // optimisation - int runStart = -1; - boolean previousChunkNotPresent = false; - for (int chunkY = 0; chunkY < 8; chunkY++) { - final int yInTile = chunkY << 4; - if (tile.getBitLayerValue(NotPresent.INSTANCE, xInTile, yInTile) != previousChunkNotPresent) { - if (! previousChunkNotPresent) { - runStart = chunkY; - previousChunkNotPresent = true; - } else { - // Copy the previous run of not present chunks - g2.drawImage(surroundingTileImage, - imageX + dx * subSize + (chunkX << 4) / scale, imageY + dy * subSize + (runStart << 4) / scale, imageX + dx * subSize + ((chunkX + 1) << 4) / scale, imageY + dy * subSize + (chunkY << 4) / scale, - dx * subSize + (chunkX << 4) / scale, dy * subSize + (runStart << 4) / scale, dx * subSize + ((chunkX + 1) << 4) / scale, dy * subSize + (chunkY << 4) / scale, - null); - previousChunkNotPresent = false; - } - } - } - if (previousChunkNotPresent) { - // Copy the last run of not present chunks - g2.drawImage(surroundingTileImage, - imageX + dx * subSize + (chunkX << 4) / scale, imageY + dy * subSize + (runStart << 4) / scale, imageX + dx * subSize + ((chunkX + 1) << 4) / scale, imageY + dy * subSize + (8 << 4) / scale, - dx * subSize + (chunkX << 4) / scale, dy * subSize + (runStart << 4) / scale, dx * subSize + ((chunkX + 1) << 4) / scale, dy * subSize + (8 << 4) / scale, - null); - } - } - } - } break; case BORDER: - Paint paint; + final Paint paint; switch (((Dimension) tileProvider).getBorder()) { case WATER: case ENDLESS_WATER: @@ -203,7 +129,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime break; case BARRIER: case ENDLESS_BARRIER: - paint = BARRIER_PAINT; + paint = BARRIER_PAINT; // TODO apply effects break; default: throw new InternalError(); @@ -230,22 +156,8 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime case SURROUNDS: case BEDROCK_WALL: case BARRIER_WALL: - if (surroundingTileProvider != null) { - if (surroundingTileImageAvailable == null) { - surroundingTileImage = new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_ARGB); - surroundingTileImageAvailable = surroundingTileProvider.paintTile(surroundingTileImage, x, y, 0, 0); - } - if (surroundingTileImageAvailable) { - g2.drawImage(surroundingTileImage, - imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, - imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, - null); - } - } - if (! Boolean.TRUE.equals(surroundingTileImageAvailable)) { - g2.setColor(voidColour); - g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, subSize); - } + g2.setColor(voidColour); + g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, subSize); if ((tileType == TileType.BEDROCK_WALL) || (tileType == TileType.BARRIER_WALL)){ g2.setPaint((tileType == TileType.BEDROCK_WALL) ? bedrockColour : BARRIER_PAINT); TileType neighbourType = getUnzoomedTileType(x * scale + dx, y * scale + dy - 1); @@ -270,6 +182,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime } } } + applyEffects(g2); } finally { g2.dispose(); } @@ -300,17 +213,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime @Override public Rectangle getExtent() { - Rectangle tileProviderExtent = tileProvider.getExtent(); - Rectangle surroundingTileProviderExtent = (surroundingTileProvider != null) ? surroundingTileProvider.getExtent() : null; - if (tileProviderExtent != null) { - if (surroundingTileProviderExtent != null) { - return tileProviderExtent.union(surroundingTileProviderExtent); - } else { - return tileProviderExtent; - } - } else { - return surroundingTileProviderExtent; - } + return tileProvider.getExtent(); } @Override @@ -355,9 +258,6 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime } this.zoom = zoom; tileRendererRef = createNewTileRendererRef(); - if (surroundingTileProvider != null) { - surroundingTileProvider.setZoom(zoom); - } } } @@ -440,60 +340,21 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime } private boolean paintUnzoomedTile(final Image tileImage, final int x, final int y, final int dx, final int dy) { - TileType tileType = getUnzoomedTileType(x, y); + final TileType tileType = getUnzoomedTileType(x, y); switch (tileType) { case WORLD: - Tile tile = tileProvider.getTile(x, y); - TileRenderer tileRenderer = tileRendererRef.get(); - tileRenderer.renderTile(tile, tileImage, dx, dy); - - // If the tile has chunks that are marked "not present" and there is a surrounding tile provider, copy - // those chunks from there - if (tile.hasLayer(NotPresent.INSTANCE) && (surroundingTileProvider != null)) { - Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); + tileRendererRef.get().renderTile(tileProvider.getTile(x, y), tileImage, dx, dy); + if (effect != null) { + final Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); try { - BufferedImage surroundingTileImage = surroundingTileImageRef.get(); - if (surroundingTileProvider.paintTile(surroundingTileImage, x, y, 0, 0)) { - for (int chunkX = 0; chunkX < 8; chunkX++) { - final int xInTile = chunkX << 4; - // Copy entire vertical columns of chunks at once, if possible, as a performance - // optimisation - int runStart = -1; - boolean previousChunkNotPresent = false; - for (int chunkY = 0; chunkY < 8; chunkY++) { - final int yInTile = chunkY << 4; - if (tile.getBitLayerValue(NotPresent.INSTANCE, xInTile, yInTile) != previousChunkNotPresent) { - if (! previousChunkNotPresent) { - runStart = chunkY; - previousChunkNotPresent = true; - } else { - // Copy the previous run of not present chunks - final int runStartYInTile = runStart << 4; - g2.drawImage(surroundingTileImage, - dx + xInTile, dy + runStartYInTile, dx + xInTile + 16, dy + yInTile, - xInTile, runStartYInTile, xInTile + 16, yInTile, - null); - previousChunkNotPresent = false; - } - } - } - if (previousChunkNotPresent) { - // Copy the last run of not present chunks - final int runStartYInTile = runStart << 4; - g2.drawImage(surroundingTileImage, - dx + xInTile, dy + runStartYInTile, dx + xInTile + 16, dy + TILE_SIZE, - xInTile, runStartYInTile, xInTile + 16, TILE_SIZE, - null); - } - } - } + applyEffects(g2); } finally { g2.dispose(); } } return true; case BORDER: - Paint paint; + final Paint paint; switch (((Dimension) tileProvider).getBorder()) { case WATER: case ENDLESS_WATER: @@ -535,26 +396,18 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime if (tileProvider.isTilePresent(x - 1, y)) { g2.drawLine(dx + 1, dy + 1, dx + 1, dy + TILE_SIZE - 1); } + applyEffects(g2); } finally { g2.dispose(); } return true; case BEDROCK_WALL: case BARRIER_WALL: - boolean backgroundPainted = false; - if (surroundingTileProvider != null) { - backgroundPainted = surroundingTileProvider.paintTile(tileImage, x, y, dx, dy); - } g2 = (Graphics2D) tileImage.getGraphics(); try { - if (! backgroundPainted) { - // A surrounding tile provider would have completely - // filled the image, but if there isn't one or it didn't - // work we have to make sure of that ourselves - g2.setColor(new Color(0x00ffffff & VoidRenderer.getColour(), true)); - g2.setComposite(AlphaComposite.Src); - g2.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); - } + g2.setColor(new Color(0x00ffffff & VoidRenderer.getColour(), true)); + g2.setComposite(AlphaComposite.Src); + g2.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); if (tileType == TileType.BARRIER_WALL) { g2.setPaint(BARRIER_PAINT); } else { @@ -576,14 +429,12 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(dx, dy, 16, TILE_SIZE); } + applyEffects(g2); } finally { g2.dispose(); } return true; case SURROUNDS: - if (surroundingTileProvider != null) { - return surroundingTileProvider.paintTile(tileImage, x, y, dx, dy); - } return false; default: throw new InternalError(); @@ -600,7 +451,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime private void fireTilesChangedIncludeBorder(Set tiles) { if (showBorder && (tileProvider instanceof Dimension) - && (((Dimension) tileProvider).getDim() == DIM_NORMAL) + && (((Dimension) tileProvider).getAnchor().dim == DIM_NORMAL) && (((Dimension) tileProvider).getBorder() != null) && (! ((Dimension) tileProvider).getBorder().isEndless())) { final Set coordSet = new HashSet<>(); @@ -670,9 +521,12 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime }); } - @NotNull - private ThreadLocal createNewSurroundingTileImageRef() { - return ThreadLocal.withInitial(() -> new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_RGB)); + private void applyEffects(Graphics2D g2) { + if (effect == FADE_TO_WHITE) { + g2.setComposite(AlphaComposite.SrcOver.derive(0.5f)); + g2.setColor(Color.WHITE); + g2.fillRect(0, 0, TILE_SIZE, TILE_SIZE); + } } private final TileProvider tileProvider; @@ -683,8 +537,7 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime private final TileRenderer.LightOrigin lightOrigin; private final List listeners = new ArrayList<>(); private final CustomBiomeManager customBiomeManager; - private final org.pepsoft.util.swing.TileProvider surroundingTileProvider; - private final ThreadLocal surroundingTileImageRef; + private final Effect effect; private int zoom = 0; private volatile ThreadLocal tileRendererRef; @@ -714,4 +567,8 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime */ BARRIER_WALL } + + public enum Effect { + FADE_TO_WHITE + } } \ No newline at end of file diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/World2.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/World2.java index 6ee9fd61..1e5931cc 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/World2.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/World2.java @@ -13,6 +13,7 @@ import org.pepsoft.util.MemoryUtils; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.SubProgressReceiver; import org.pepsoft.util.undo.UndoManager; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.history.HistoryEntry; import org.pepsoft.worldpainter.layers.Biome; import org.pepsoft.worldpainter.layers.Layer; @@ -24,8 +25,10 @@ import java.io.*; import java.util.List; import java.util.*; +import static java.util.stream.Collectors.toSet; import static org.pepsoft.minecraft.Material.WOOL_MAGENTA; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.END; import static org.pepsoft.worldpainter.Generator.NETHER; import static org.pepsoft.worldpainter.World2.Warning.MISSING_CUSTOM_TERRAINS; @@ -54,13 +57,13 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { } this.platform = platform; this.maxheight = tileFactory.getMaxHeight(); - Dimension dim = new Dimension(this, minecraftSeed, tileFactory, 0); + Dimension dim = new Dimension(this, minecraftSeed, tileFactory, NORMAL_DETAIL); addDimension(dim); } public long getChangeNo() { long totalChangeNo = changeNo + borderSettings.getChangeNo(); - for (Dimension dimension: dimensions.values()) { + for (Dimension dimension: dimensionsByAnchor.values()) { totalChangeNo += dimension.getChangeNo(); } if (logger.isDebugEnabled()) { @@ -173,25 +176,33 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { propertyChangeSupport.removePropertyChangeListener(propertyName, listener); } - public Dimension getDimension(int dim) { - return dimensions.get(dim); + public Dimension getDimension(Anchor anchor) { + return dimensionsByAnchor.get(anchor); } - - public Dimension[] getDimensions() { - return dimensions.values().toArray(new Dimension[dimensions.size()]); + + public Set getDimensions() { + return new HashSet<>(dimensionsByAnchor.values()); } - + + public Set getDimensionsWithRole(Dimension.Role role, boolean inverted, int layer) { + return dimensionsByAnchor.values().stream() + .filter(dimension -> { + final Anchor anchor = dimension.getAnchor(); + return (anchor.role == role) && (anchor.invert == inverted) && (anchor.layer == layer); + }).collect(toSet()); + } + public final void addDimension(Dimension dimension) { - if (dimensions.containsKey(dimension.getDim())) { - throw new IllegalStateException("Dimension " + dimension.getDim() + " already exists"); + if (dimensionsByAnchor.containsKey(dimension.getAnchor())) { + throw new IllegalStateException("Dimension " + dimension.getAnchor() + " already exists"); } else if (dimension.getMaxHeight() > maxheight) { throw new IllegalStateException("Dimension has higher max height (" + dimension.getMaxHeight() + ") than world (" + maxheight + ")"); } else { if (dimension.getWorld() != this) { throw new IllegalArgumentException("Dimension belongs to another world"); } - dimensions.put(dimension.getDim(), dimension); - if (dimension.getDim() == 0) { + dimensionsByAnchor.put(dimension.getAnchor(), dimension); + if (dimension.getAnchor().dim == DIM_NORMAL) { TileFactory tileFactory = dimension.getTileFactory(); if (tileFactory instanceof HeightMapTileFactory) { if (((HeightMapTileFactory) tileFactory).getWaterHeight() < 32) { @@ -201,19 +212,19 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { } } } - if (dimension.getDim() != DIM_NORMAL) { + if (dimension.getAnchor().dim != DIM_NORMAL) { history.add(new HistoryEntry(HistoryEntry.WORLD_DIMENSION_ADDED, dimension.getName())); } } - public Dimension removeDimension(int dim) { - if (dimensions.containsKey(dim)) { + public Dimension removeDimension(Anchor anchor) { + if (dimensionsByAnchor.containsKey(anchor)) { changeNo++; - Dimension dimension = dimensions.remove(dim); + Dimension dimension = dimensionsByAnchor.remove(anchor); history.add(new HistoryEntry(HistoryEntry.WORLD_DIMENSION_REMOVED, dimension.getName())); return dimension; } else { - throw new IllegalStateException("Dimension " + dim + " does not exist"); + throw new IllegalStateException("Dimension " + anchor + " does not exist"); } } @@ -250,7 +261,7 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { */ @Deprecated public Generator getGenerator() { - return dimensions.get(DIM_NORMAL).getGenerator().getType(); + return dimensionsByAnchor.get(NORMAL_DETAIL).getGenerator().getType(); } public Platform getPlatform() { @@ -344,8 +355,8 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { */ @Deprecated public String getGeneratorOptions() { - return (dimensions.get(DIM_NORMAL).getGenerator() instanceof CustomGenerator) - ? ((CustomGenerator) dimensions.get(DIM_NORMAL).getGenerator()).getName() + return (dimensionsByAnchor.get(NORMAL_DETAIL).getGenerator() instanceof CustomGenerator) + ? ((CustomGenerator) dimensionsByAnchor.get(NORMAL_DETAIL).getGenerator()).getName() : null; } @@ -459,8 +470,8 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { * rotation progress. */ public void transform(CoordinateTransform transform, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled { - int dimCount = dimensions.size(), dim = 0; - for (Dimension dimension: dimensions.values()) { + int dimCount = dimensionsByAnchor.size(), dim = 0; + for (Dimension dimension: dimensionsByAnchor.values()) { dimension.transform(transform, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, (float) dim / dimCount, 1.0f / dimCount) : null); dim++; } @@ -478,14 +489,14 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { * transforms any surface-related metadata stored in the world. If an undo * manager is installed this operation will destroy all undo info. * - * @param dim The index of the dimension to transform. + * @param anchor The anchor of the dimension to transform. * @param transform The coordinate transform to apply. * @param progressReceiver A progress receiver which will be informed of * rotation progress. */ - public void transform(int dim, CoordinateTransform transform, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled { - dimensions.get(dim).transform(transform, progressReceiver); - if (dim == DIM_NORMAL) { + public void transform(Anchor anchor, CoordinateTransform transform, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled { + dimensionsByAnchor.get(anchor).transform(transform, progressReceiver); + if (anchor.equals(NORMAL_DETAIL)) { Point oldSpawnPoint = spawnPoint; spawnPoint = transform.transform(spawnPoint); propertyChangeSupport.firePropertyChange("spawnPoint", oldSpawnPoint, spawnPoint); @@ -497,14 +508,13 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { } public void clearLayerData(Layer layer) { - for (Dimension dimension: dimensions.values()) { + for (Dimension dimension: dimensionsByAnchor.values()) { dimension.clearLayerData(layer); } } - @SuppressWarnings("unchecked") public long measureSize() { - dimensions.values().forEach(org.pepsoft.worldpainter.Dimension::ensureAllReadable); + dimensionsByAnchor.values().forEach(org.pepsoft.worldpainter.Dimension::ensureAllReadable); return MemoryUtils.getSize(this, new HashSet<>(Arrays.asList(UndoManager.class, Dimension.Listener.class, PropertyChangeSupport.class, Layer.class, Terrain.class))); } @@ -708,7 +718,7 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { } if (wpVersion < 9) { dimensions.values().forEach(dimension -> { - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case DIM_NORMAL: MapGenerator generator = MapGenerator.fromLegacySettings(this.generator, dimension.getMinecraftSeed(), generatorName, generatorOptions, platform, this::addWarning); dimension.setGenerator(generator); @@ -725,6 +735,11 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { generatorName = null; generatorOptions = null; } + if (wpVersion < 10) { + dimensionsByAnchor = new HashMap<>(); + dimensions.values().forEach(dimension -> dimensionsByAnchor.put(dimension.getAnchor(), dimension)); + dimensions = null; + } wpVersion = CURRENT_WP_VERSION; // The number of custom terrains increases now and again; correct old @@ -738,7 +753,8 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { private boolean createGoodiesChest = true; private Point spawnPoint = new Point(0, 0); private File importedFrom; - private final SortedMap dimensions = new TreeMap<>(); + @Deprecated + private SortedMap dimensions; private boolean mapFeatures = true; @Deprecated private int gameType; @@ -777,6 +793,7 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { private Map attributes; @Deprecated private SuperflatPreset superflatPreset; + private Map dimensionsByAnchor = new HashMap<>(); private transient Set warnings; private transient Map metadata; private transient long changeNo; @@ -819,7 +836,7 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable { */ public static final String METADATA_KEY_PLUGINS = "org.pepsoft.worldpainter.plugins"; - private static final int CURRENT_WP_VERSION = 9; + private static final int CURRENT_WP_VERSION = 10; private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(World2.class); private static final long serialVersionUID = 2011062401L; diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WorldIO.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WorldIO.java index bdddc369..acd5747b 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WorldIO.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/WorldIO.java @@ -23,6 +23,7 @@ import java.util.zip.ZipException; import static org.pepsoft.minecraft.Material.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.DEFAULT; // TODO why this design again? Just make these utility methods, surely? @@ -131,7 +132,7 @@ public class WorldIO { newWorld.setImportedFrom(oldWorld.getImportedFrom()); newWorld.setName(oldWorld.getName()); newWorld.setSpawnPoint(oldWorld.getSpawnPoint()); - Dimension dim0 = newWorld.getDimension(0); + Dimension dim0 = newWorld.getDimension(NORMAL_DETAIL); newWorld.setAskToConvertToAnvil(true); newWorld.setUpIs(Direction.WEST); newWorld.setAskToRotate(true); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/AbstractWorldExporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/AbstractWorldExporter.java index 0ce441eb..a35e3110 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/AbstractWorldExporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/AbstractWorldExporter.java @@ -8,6 +8,7 @@ import org.pepsoft.util.ProgressReceiver.OperationCancelled; import org.pepsoft.util.SubProgressReceiver; import org.pepsoft.util.mdc.MDCThreadPoolExecutor; import org.pepsoft.worldpainter.Dimension; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.Platform; import org.pepsoft.worldpainter.Tile; import org.pepsoft.worldpainter.World2; @@ -40,7 +41,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.minecraft.Material.AIR; -import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.Platform.Capability.*; import static org.pepsoft.worldpainter.util.ThreadUtils.chooseThreadCount; @@ -100,20 +100,8 @@ public abstract class AbstractWorldExporter implements WorldExporter { 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 Anchor anchor = dimension.getAnchor(); + final Dimension ceiling = dimension.getWorld().getDimension(new Anchor(anchor.dim, anchor.role, true, 0)); final ChunkFactory.Stats collectedStats = new ChunkFactory.Stats(); dimension.rememberChanges(); @@ -129,7 +117,7 @@ public abstract class AbstractWorldExporter implements WorldExporter { if (tilesSelected) { // Sanity check assert world.getDimensionsToExport().size() == 1; - assert world.getDimensionsToExport().contains(dimension.getDim()); + assert world.getDimensionsToExport().contains(anchor.dim); selectedTiles = world.getTilesToExport(); for (Point tile: selectedTiles) { int regionX = tile.x >> 2; @@ -271,7 +259,7 @@ public abstract class AbstractWorldExporter implements WorldExporter { } finally { if ((exportResults != null) && exportResults.chunksGenerated) { long saveStart = System.currentTimeMillis(); - worldRegion.save(worldDir, dimension.getDim()); + worldRegion.save(worldDir, anchor.dim); if (logger.isDebugEnabled()) { logger.debug("Saving region took {} ms", System.currentTimeMillis() - saveStart); } @@ -568,7 +556,7 @@ public abstract class AbstractWorldExporter implements WorldExporter { // TODO: trying to do this for every region should work but is not very // elegant - if ((dimension.getDim() == 0) && world.isCreateGoodiesChest()) { + if ((dimension.getAnchor().dim == 0) && world.isCreateGoodiesChest()) { Point goodiesPoint = (Point) world.getSpawnPoint().clone(); goodiesPoint.translate(3, 3); int height = Math.min(dimension.getIntHeightAt(goodiesPoint) + 1, dimension.getMaxHeight() - 1); @@ -886,7 +874,7 @@ public abstract class AbstractWorldExporter implements WorldExporter { total += entry.getValue().size(); } // Make sure to honour the read-only layer: TODO: this means nothing at the moment. Is it still relevant? - try (CachingMinecraftWorld minecraftWorld = new CachingMinecraftWorld(worldDir, dimension.getDim(), dimension.getMaxHeight(), platform, false, 512)) { + try (CachingMinecraftWorld minecraftWorld = new CachingMinecraftWorld(worldDir, dimension.getAnchor().dim, dimension.getMaxHeight(), platform, false, 512)) { final ExportSettings exportSettings = (dimension.getExportSettings() != null) ? dimension.getExportSettings() : platformProvider.getDefaultExportSettings(platform); for (Entry> entry: fixups.entrySet()) { if (progressReceiver != null) { diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/BorderChunkFactory.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/BorderChunkFactory.java index 58e17c5f..5bc6b58e 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/BorderChunkFactory.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/BorderChunkFactory.java @@ -59,13 +59,11 @@ public class BorderChunkFactory { result.chunk = PlatformManager.getInstance().createChunk(platform, chunkX, chunkZ, maxHeight); final int maxY = maxHeight - 1; final int biome; - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case DIM_NETHER: - case DIM_NETHER_CEILING: biome = BIOME_HELL; break; case DIM_END: - case DIM_END_CEILING: biome = BIOME_THE_END; break; default: diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaMinecraftWorld.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaMinecraftWorld.java index e8b36931..68fce95b 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaMinecraftWorld.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaMinecraftWorld.java @@ -5,8 +5,8 @@ package org.pepsoft.worldpainter.exporting; -import org.pepsoft.worldpainter.Platform; import org.pepsoft.worldpainter.Dimension; +import org.pepsoft.worldpainter.Platform; import java.awt.*; import java.io.File; @@ -43,8 +43,8 @@ public class JavaMinecraftWorld extends CachingMinecraftWorld { } public JavaMinecraftWorld(File worldDir, Dimension dimension, Platform platform, boolean readOnly, int cacheSize) { - super(worldDir, dimension.getDim(), dimension.getMaxHeight(), platform, readOnly, cacheSize); - if ((dimension.getWorld().getTilesToExport() != null) && dimension.getWorld().getDimensionsToExport().contains(dimension.getDim())) { + super(worldDir, dimension.getAnchor().dim, dimension.getMaxHeight(), platform, readOnly, cacheSize); + if ((dimension.getWorld().getTilesToExport() != null) && dimension.getWorld().getDimensionsToExport().contains(dimension.getAnchor().dim)) { lowestX = Integer.MAX_VALUE; highestX = Integer.MIN_VALUE; lowestZ = Integer.MAX_VALUE; @@ -73,7 +73,7 @@ public class JavaMinecraftWorld extends CachingMinecraftWorld { lowestZ = northEastChunk.y >> 4; highestZ = southWestChunk.y >> 4; } - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case DIM_NORMAL: dimensionDir = worldDir; break; @@ -84,7 +84,7 @@ public class JavaMinecraftWorld extends CachingMinecraftWorld { dimensionDir = new File(worldDir, "DIM1"); break; default: - throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported"); + throw new IllegalArgumentException("Dimension " + dimension.getAnchor().dim + " not supported"); } if (! worldDir.isDirectory()) { throw new IllegalArgumentException(worldDir + " does not exist or is not a directory"); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaWorldExporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaWorldExporter.java index fcc27655..42004f20 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaWorldExporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/JavaWorldExporter.java @@ -11,6 +11,7 @@ import org.pepsoft.util.FileUtils; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.worldpainter.Dimension; import org.pepsoft.worldpainter.*; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.history.HistoryEntry; import org.pepsoft.worldpainter.platforms.JavaPlatformProvider; import org.pepsoft.worldpainter.util.FileInUseException; @@ -26,8 +27,10 @@ import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.minecraft.SuperflatPreset.Structure.*; import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.DefaultPlugin.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.Dimension.Border.ENDLESS_BARRIER; import static org.pepsoft.worldpainter.Dimension.Border.ENDLESS_WATER; +import static org.pepsoft.worldpainter.Dimension.Role.DETAIL; import static org.pepsoft.worldpainter.Platform.Capability.GENERATOR_PER_DIMENSION; import static org.pepsoft.worldpainter.biomeschemes.Minecraft1_19Biomes.*; @@ -81,7 +84,7 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this long start = System.currentTimeMillis(); // Export dimensions - Dimension dim0 = world.getDimension(0); + Dimension dim0 = world.getDimension(NORMAL_DETAIL); JavaLevel level = JavaLevel.create(platform, world.getMaxHeight()); level.setSeed(dim0.getMinecraftSeed()); level.setName(name); @@ -100,10 +103,10 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this level.setAllowCommands(world.isAllowCheats()); } for (Dimension dimension: world.getDimensions()) { - if (dimension.getDim() < 0) { + if (dimension.getAnchor().invert) { // Ceiling dimension continue; - } else if ((! platform.capabilities.contains(GENERATOR_PER_DIMENSION)) && (dimension.getDim() != DIM_NORMAL)) { + } else if ((! platform.capabilities.contains(GENERATOR_PER_DIMENSION)) && (dimension.getAnchor().dim != DIM_NORMAL)) { // This platform only supports generator settings for the surface dimension, and this is not the surface dimension continue; } @@ -112,7 +115,7 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this final SuperflatPreset.Builder superflatPresetBuilder; final int biome; final Structure[] structures; - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case DIM_NETHER: biome = BIOME_HELL; structures = null; // TODO are there Nether structures we could put here? @@ -184,9 +187,9 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this superflatPresetBuilder.addLayer(MC_AIR, dimension.getMaxHeight() - platform.minZ - totalDepth - 1); superflatPresetBuilder.addLayer((dimension.getRoofType() == Dimension.WallType.BEDROCK) ? MC_BEDROCK : MC_BARRIER, 1); } - level.setGenerator(dimension.getDim(), new SuperflatGenerator(superflatPresetBuilder.build())); + level.setGenerator(dimension.getAnchor().dim, new SuperflatGenerator(superflatPresetBuilder.build())); } else { - level.setGenerator(dimension.getDim(), dimension.getGenerator()); + level.setGenerator(dimension.getAnchor().dim, dimension.getGenerator()); } } level.setMapFeatures(world.isMapFeatures()); @@ -219,10 +222,9 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this if (selectedTiles == null) { selectedDimension = -1; boolean first = true; - for (Dimension dimension: world.getDimensions()) { - if ((dimension.getDim() < 0) || ((selectedDimensions != null) && (! selectedDimensions.contains(dimension.getDim())))) { - // This dimension will be exported as part of another dimension, or it has not been selected to - // be exported, so skip it + for (Dimension dimension: world.getDimensionsWithRole(DETAIL, false, 0)) { + if ((selectedDimensions != null) && (! selectedDimensions.contains(dimension.getAnchor().dim))) { + // This dimension has not been selected to be exported, so skip it continue; } if (first) { @@ -230,11 +232,11 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this } else if (progressReceiver != null) { progressReceiver.reset(); } - stats.put(dimension.getDim(), exportDimension(worldDir, dimension, progressReceiver)); + stats.put(dimension.getAnchor().dim, exportDimension(worldDir, dimension, progressReceiver)); } } else { selectedDimension = selectedDimensions.iterator().next(); - stats.put(selectedDimension, exportDimension(worldDir, world.getDimension(selectedDimension), progressReceiver)); + stats.put(selectedDimension, exportDimension(worldDir, world.getDimension(new Anchor(selectedDimension, DETAIL, false, 0)), progressReceiver)); } // Update the session.lock file, hopefully kicking out any Minecraft instances which may have tried to open the @@ -248,7 +250,7 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this if (selectedTiles == null) { world.addHistoryEntry(HistoryEntry.WORLD_EXPORTED_FULL, name, worldDir); } else { - world.addHistoryEntry(HistoryEntry.WORLD_EXPORTED_PARTIAL, name, worldDir, world.getDimension(selectedDimension).getName()); + world.addHistoryEntry(HistoryEntry.WORLD_EXPORTED_PARTIAL, name, worldDir, world.getDimension(new Anchor(selectedDimension, DETAIL, false, 0)).getName()); } // Log an event @@ -263,15 +265,15 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this event.setAttribute(ATTRIBUTE_KEY_GAME_TYPE_NAME, world.getGameType().name()); event.setAttribute(ATTRIBUTE_KEY_ALLOW_CHEATS, world.isAllowCheats()); event.setAttribute(ATTRIBUTE_KEY_GENERATOR, dim0.getGenerator().getType().name()); - Dimension dimension = world.getDimension(0); + Dimension dimension = world.getDimension(NORMAL_DETAIL); event.setAttribute(ATTRIBUTE_KEY_TILES, dimension.getTileCount()); logLayers(dimension, event, ""); - dimension = world.getDimension(1); + dimension = world.getDimension(NETHER_DETAIL); if (dimension != null) { event.setAttribute(ATTRIBUTE_KEY_NETHER_TILES, dimension.getTileCount()); logLayers(dimension, event, "nether."); } - dimension = world.getDimension(2); + dimension = world.getDimension(END_DETAIL); if (dimension != null) { event.setAttribute(ATTRIBUTE_KEY_END_TILES, dimension.getTileCount()); logLayers(dimension, event, "end."); @@ -293,24 +295,22 @@ public class JavaWorldExporter extends AbstractWorldExporter { // TODO can this } protected ChunkFactory.Stats exportDimension(File worldDir, Dimension dimension, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled { - File dimensionDir; - Dimension ceiling; - switch (dimension.getDim()) { + final Anchor anchor = dimension.getAnchor(); + final File dimensionDir; + switch (anchor.dim) { case DIM_NORMAL: dimensionDir = worldDir; - ceiling = dimension.getWorld().getDimension(DIM_NORMAL_CEILING); break; case DIM_NETHER: dimensionDir = new File(worldDir, "DIM-1"); - ceiling = dimension.getWorld().getDimension(DIM_NETHER_CEILING); break; case DIM_END: dimensionDir = new File(worldDir, "DIM1"); - ceiling = dimension.getWorld().getDimension(DIM_END_CEILING); break; default: - throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported"); + throw new IllegalArgumentException("Dimension " + anchor.dim + " not supported"); } + final Dimension ceiling = dimension.getWorld().getDimension(new Anchor(anchor.dim, DETAIL, true, 0)); for (DataType dataType: platformProvider.getDataTypes(platform)) { File regionDir = new File(dimensionDir, dataType.name().toLowerCase()); if (! regionDir.exists()) { diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/WorldPainterChunkFactory.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/WorldPainterChunkFactory.java index 329acfb8..b6e1dc66 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/WorldPainterChunkFactory.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/exporting/WorldPainterChunkFactory.java @@ -69,8 +69,8 @@ public class WorldPainterChunkFactory implements ChunkFactory { biomesSupported2D = platform.capabilities.contains(BIOMES); biomesSupported3D = platform.capabilities.contains(BIOMES_3D); biomesSupportedNamed = platform.capabilities.contains(NAMED_BIOMES); - copyBiomes = (biomesSupported2D || biomesSupported3D || biomesSupportedNamed) && (dimension.getDim() >= 0); - switch (dimension.getDim()) { + copyBiomes = (biomesSupported2D || biomesSupported3D || biomesSupportedNamed) && (! dimension.getAnchor().invert); + switch (dimension.getAnchor().dim) { case DIM_NORMAL: defaultBiome = BIOME_PLAINS; break; @@ -80,12 +80,6 @@ public class WorldPainterChunkFactory implements ChunkFactory { case DIM_END: defaultBiome = BIOME_SKY; break; - case DIM_NORMAL_CEILING: - case DIM_NETHER_CEILING: - case DIM_END_CEILING: - // Biome is ignored for ceilings - defaultBiome = 0; - break; default: throw new InternalError(); } diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/HeightMapImporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/HeightMapImporter.java index 19409090..fd62d4d6 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/HeightMapImporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/HeightMapImporter.java @@ -32,6 +32,7 @@ import java.util.Map; import static org.pepsoft.minecraft.Constants.DEFAULT_MAX_HEIGHT_ANVIL; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; /** * @@ -57,7 +58,7 @@ public class HeightMapImporter { final World2 world = new World2(platform, minecraftSeed, tileFactory); world.addHistoryEntry(HistoryEntry.WORLD_IMPORTED_FROM_HEIGHT_MAP, imageFile); world.setName(name); - final Dimension dimension = world.getDimension(DIM_NORMAL); + final Dimension dimension = world.getDimension(NORMAL_DETAIL); // Export settings final Configuration config = Configuration.getInstance(); @@ -220,7 +221,7 @@ public class HeightMapImporter { Theme theme = ((this.theme != null) ? this.theme : heightMapTileFactory.getTheme()).clone(); theme.setWaterHeight(worldWaterLevel); HeightMapTileFactory tileFactory = new PreviewTileFactory(1L, previewHeightMap, platform.minZ, maxHeight, heightMapTileFactory.isFloodWithLava(), theme, heightMap, voidBelowLevel); - return new WPTileProvider(tileFactory, colourScheme, null, null, contourLines, contourSeparation, lightOrigin, false, null); + return new WPTileProvider(tileFactory, colourScheme, null, null, contourLines, contourSeparation, lightOrigin, false); } else { return null; } diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/JavaMapImporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/JavaMapImporter.java index 44fbd9f1..758db783 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/JavaMapImporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/importing/JavaMapImporter.java @@ -36,6 +36,7 @@ import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.minecraft.Material.*; import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.Platform.Capability.*; import static org.pepsoft.worldpainter.biomeschemes.Minecraft1_19Biomes.*; import static org.pepsoft.worldpainter.importing.MapImporter.ReadOnlyOption.*; @@ -77,7 +78,7 @@ public class JavaMapImporter extends MapImporter { final World2 world = importWorld(level); final long minecraftSeed = world.getAttribute(SEED).orElse(new Random().nextLong()); tileFactory.setSeed(minecraftSeed); - Dimension dimension = new Dimension(world, minecraftSeed, tileFactory, DIM_NORMAL); + Dimension dimension = new Dimension(world, minecraftSeed, tileFactory, NORMAL_DETAIL); dimension.setEventsInhibited(true); try { dimension.setCoverSteepTerrain(false); @@ -129,7 +130,7 @@ public class JavaMapImporter extends MapImporter { terrainRanges.put(-1, Terrain.NETHERRACK); theme.setTerrainRanges(terrainRanges); theme.setLayerMap(null); - dimension = new Dimension(world, minecraftSeed + 1, netherTileFactory, DIM_NETHER); + dimension = new Dimension(world, minecraftSeed + 1, netherTileFactory, NETHER_DETAIL); dimension.setEventsInhibited(true); try { dimension.setCoverSteepTerrain(false); @@ -158,7 +159,7 @@ public class JavaMapImporter extends MapImporter { terrainRanges.put(-1, Terrain.END_STONE); theme.setTerrainRanges(terrainRanges); theme.setLayerMap(Collections.emptyMap()); - dimension = new Dimension(world, minecraftSeed + 2, endTileFactory, DIM_END); + dimension = new Dimension(world, minecraftSeed + 2, endTileFactory, END_DETAIL); dimension.setEventsInhibited(true); try { dimension.setCoverSteepTerrain(false); @@ -189,7 +190,7 @@ public class JavaMapImporter extends MapImporter { 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.getDimension(DIM_NORMAL).getGenerator().getType().name()); + event.setAttribute(ATTRIBUTE_KEY_GENERATOR, world.getDimension(NORMAL_DETAIL).getGenerator().getType().name()); event.setAttribute(ATTRIBUTE_KEY_TILES, dimension.getTileCount()); config.logEvent(event); } @@ -247,7 +248,7 @@ public class JavaMapImporter extends MapImporter { final AtomicInteger nextCustomBiomeId = new AtomicInteger(FIRST_UNALLOCATED_ID); final Set allBiomes = synchronizedSet(new HashSet<>()); final Set invalidBiomeIds = synchronizedSet(new HashSet<>()); - try (ChunkStore chunkStore = PlatformManager.getInstance().getChunkStore(platform, worldDir, dimension.getDim())) { + try (ChunkStore chunkStore = PlatformManager.getInstance().getChunkStore(platform, worldDir, dimension.getAnchor().dim)) { final int total = chunkStore.getChunkCount(); final AtomicInteger count = new AtomicInteger(); final StringBuffer reportBuilder = new StringBuffer(); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/ResourcesExporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/ResourcesExporter.java index 72f1835f..05a3018d 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/ResourcesExporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/ResourcesExporter.java @@ -35,7 +35,7 @@ import static org.pepsoft.worldpainter.layers.exporters.ResourcesExporter.Resour */ public class ResourcesExporter extends AbstractLayerExporter implements FirstPassLayerExporter { public ResourcesExporter(Dimension dimension, Platform platform, ExporterSettings settings) { - super(dimension, platform, (settings != null) ? settings : defaultSettings(platform, dimension.getDim(), dimension.getMaxHeight()), Resources.INSTANCE); + super(dimension, platform, (settings != null) ? settings : defaultSettings(platform, dimension.getAnchor().dim, dimension.getMaxHeight()), Resources.INSTANCE); final ResourcesExporterSettings resourcesSettings = (ResourcesExporterSettings) super.settings; final Set allMaterials = resourcesSettings.getMaterials(); final List activeMaterials = new ArrayList<>(allMaterials.size()); @@ -72,7 +72,7 @@ public class ResourcesExporter extends AbstractLayerExporter implemen final int minimumLevel = ((ResourcesExporterSettings) super.settings).getMinimumLevel(); final int xOffset = (chunk.getxPos() & 7) << 4; final int zOffset = (chunk.getzPos() & 7) << 4; - final boolean coverSteepTerrain = dimension.isCoverSteepTerrain(), nether = (dimension.getDim() == DIM_NETHER); + final boolean coverSteepTerrain = dimension.isCoverSteepTerrain(), nether = (dimension.getAnchor().dim == DIM_NETHER); // int[] counts = new int[256]; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { @@ -239,7 +239,6 @@ public class ResourcesExporter extends AbstractLayerExporter implemen final Map settings = new HashMap<>(); switch (dim) { case DIM_NORMAL: - case DIM_NORMAL_CEILING: // TODO make these normal distributions or something else more similar to Minecraft settings.put(DIRT, new ResourceSettings(DIRT, 0 , maxHeight - 1, 57, random.nextLong())); settings.put(GRAVEL, new ResourceSettings(GRAVEL, platform.minZ, maxHeight - 1, 28, random.nextLong())); @@ -260,7 +259,6 @@ public class ResourcesExporter extends AbstractLayerExporter implemen settings.put(ANCIENT_DEBRIS, new ResourceSettings(ANCIENT_DEBRIS, platform.minZ, maxHeight - 1, 0, random.nextLong())); break; case DIM_NETHER: - case DIM_NETHER_CEILING: settings.put(QUARTZ_ORE, new ResourceSettings(QUARTZ_ORE, platform.minZ, maxHeight - 1, (platform != JAVA_MCREGION) ? 7 : 0, random.nextLong())); settings.put(GOLD_ORE, new ResourceSettings(GOLD_ORE, platform.minZ, maxHeight - 1, ((platform == JAVA_ANVIL_1_15) || (platform == JAVA_ANVIL_1_17) || (platform == JAVA_ANVIL_1_18)) ? @@ -281,7 +279,6 @@ public class ResourcesExporter extends AbstractLayerExporter implemen settings.put(COPPER_ORE, new ResourceSettings(COPPER_ORE, 0, 88, 0, random.nextLong())); break; case DIM_END: - case DIM_END_CEILING: settings.put(DIRT, new ResourceSettings(DIRT, 0 , maxHeight - 1, 0, random.nextLong())); settings.put(GRAVEL, new ResourceSettings(GRAVEL, platform.minZ, maxHeight - 1, 0, random.nextLong())); settings.put(GOLD_ORE, new ResourceSettings(GOLD_ORE, platform.minZ, 31, 0, random.nextLong())); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/VoidExporter.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/VoidExporter.java index 52353538..bd52ca0d 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/VoidExporter.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/layers/exporters/VoidExporter.java @@ -76,7 +76,7 @@ public class VoidExporter extends AbstractLayerExporter= 0) { + if (! dimension.getAnchor().invert) { int highestNonAirBlock = Integer.MIN_VALUE; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/merging/JavaWorldMerger.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/merging/JavaWorldMerger.java index 2d34e097..e0f3ce79 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/merging/JavaWorldMerger.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/merging/JavaWorldMerger.java @@ -35,6 +35,7 @@ import static org.pepsoft.minecraft.Constants.*; import static org.pepsoft.minecraft.DataType.REGION; import static org.pepsoft.minecraft.Material.*; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.Platform.Capability.*; import static org.pepsoft.worldpainter.platforms.PlatformUtils.determineNativePlatforms; @@ -227,7 +228,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad // Dimension sanity checks for (Dimension dimension: world.getDimensions()) { - final int dim = dimension.getDim(); + final int dim = dimension.getAnchor().dim; if ((dim < 0) || ((world.getDimensionsToExport() != null) && (! world.getDimensionsToExport().contains(dim)))) { // Skip ceiling dimensions, or dimensions that are not going to be merged continue; @@ -281,7 +282,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad // Modify it if necessary and write it to the new level final Set selectedDimensions = world.getDimensionsToExport(); if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) { - Dimension surfaceDimension = world.getDimension(DIM_NORMAL); + Dimension surfaceDimension = world.getDimension(NORMAL_DETAIL); level.setSeed(surfaceDimension.getMinecraftSeed()); Point spawnPoint = world.getSpawnPoint(); level.setSpawnX(spawnPoint.x); @@ -317,14 +318,14 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad // instances which may have the map open: level.save(worldDir); - if ((selectedDimensions == null) ? (world.getDimension(DIM_NORMAL) != null) : selectedDimensions.contains(DIM_NORMAL)) { - mergeDimension(worldDir, backupDir, world.getDimension(DIM_NORMAL), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it + if ((selectedDimensions == null) ? (world.getDimension(NORMAL_DETAIL) != null) : selectedDimensions.contains(DIM_NORMAL)) { + mergeDimension(worldDir, backupDir, world.getDimension(NORMAL_DETAIL), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it } - if ((selectedDimensions == null) ? (world.getDimension(DIM_NETHER) != null) : selectedDimensions.contains(DIM_NETHER)) { - mergeDimension(worldDir, backupDir, world.getDimension(DIM_NETHER), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it + if ((selectedDimensions == null) ? (world.getDimension(NETHER_DETAIL) != null) : selectedDimensions.contains(DIM_NETHER)) { + mergeDimension(worldDir, backupDir, world.getDimension(NETHER_DETAIL), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it } - if ((selectedDimensions == null) ? (world.getDimension(DIM_END) != null) : selectedDimensions.contains(DIM_END)) { - mergeDimension(worldDir, backupDir, world.getDimension(DIM_END), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it + if ((selectedDimensions == null) ? (world.getDimension(END_DETAIL) != null) : selectedDimensions.contains(DIM_END)) { + mergeDimension(worldDir, backupDir, world.getDimension(END_DETAIL), progressReceiver); // TODO: this should be a SubProgressReceiver if we are exporting more than one dimension, or we should reset it } // TODO: move player positions if necessary @@ -370,9 +371,9 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad 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.getDimension(DIM_NORMAL).getGenerator().getType().name()); + event.setAttribute(ATTRIBUTE_KEY_GENERATOR, world.getDimension(NORMAL_DETAIL).getGenerator().getType().name()); if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) { - Dimension surfaceDimension = world.getDimension(0); + Dimension surfaceDimension = world.getDimension(NORMAL_DETAIL); event.setAttribute(ATTRIBUTE_KEY_TILES, surfaceDimension.getTileCount()); logLayers(surfaceDimension, event, ""); } @@ -399,7 +400,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad progressReceiver.setMessage("merging " + dimension.getName() + " dimension"); } final File dimensionDir, backupDimensionDir; - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case org.pepsoft.worldpainter.Constants.DIM_NORMAL: dimensionDir = worldDir; backupDimensionDir = backupWorldDir; @@ -413,7 +414,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad backupDimensionDir = new File(backupWorldDir, "DIM1"); break; default: - throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported"); + throw new IllegalArgumentException("Dimension " + dimension.getAnchor().dim + " not supported"); } final Set dataTypes = platformProvider.getDataTypes(platform); for (DataType dataType: dataTypes) { @@ -550,7 +551,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad logger.debug("Merged region " + regionCoords.x + "," + regionCoords.y); } } finally { - minecraftWorld.save(worldDir, dimension.getDim()); + minecraftWorld.save(worldDir, dimension.getAnchor().dim); } synchronized (fixups) { if (!regionFixups.isEmpty()) { @@ -628,7 +629,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad } } finally { if ((exportResults != null) && exportResults.chunksGenerated) { - minecraftWorld.save(worldDir, dimension.getDim()); + minecraftWorld.save(worldDir, dimension.getAnchor().dim); } } synchronized (fixups) { @@ -729,7 +730,7 @@ public class JavaWorldMerger extends JavaWorldExporter { // TODO can this be mad if (tileSelection) { // Sanity check assert world.getDimensionsToExport().size() == 1; - assert world.getDimensionsToExport().contains(dimension.getDim()); + assert world.getDimensionsToExport().contains(dimension.getAnchor().dim); for (Point tileCoords: selectedTiles) { Tile tile = dimension.getTile(tileCoords); boolean nonReadOnlyChunksFound = false; diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/DumpObject.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/DumpObject.java index b3fcb3bb..fefb3e19 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/DumpObject.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/DumpObject.java @@ -20,8 +20,8 @@ import java.security.cert.X509Certificate; import java.util.zip.GZIPInputStream; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL_1_15; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.plugins.WPPluginManager.DESCRIPTOR_PATH; /** @@ -124,7 +124,7 @@ public class DumpObject { static { TileFactory tileFactory = TileFactoryFactory.createNoiseTileFactory(0L, Terrain.GRASS, JAVA_ANVIL_1_15.minZ, JAVA_ANVIL_1_15.standardMaxHeight, 58, DEFAULT_WATER_LEVEL, false, true, 20.0f, 1.0); - FAKE_DIMENSION = new World2(JAVA_ANVIL_1_15, 0L, tileFactory).getDimension(DIM_NORMAL); + FAKE_DIMENSION = new World2(JAVA_ANVIL_1_15, 0L, tileFactory).getDimension(NORMAL_DETAIL); } private static final Logger logger = LoggerFactory.getLogger(DumpObject.class); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/RecoverWorld.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/RecoverWorld.java index 3200885c..e657d574 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/RecoverWorld.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/RecoverWorld.java @@ -194,7 +194,7 @@ public class RecoverWorld { System.err.println("Dimension " + dimension.getName() + " tile factory lost; creating default tile factory"); tileFactory = TileFactoryFactory.createNoiseTileFactory(dimension.getSeed(), Terrain.GRASS, minHeight, maxHeight, 58, DEFAULT_WATER_LEVEL, false, true, 20, 1.0); } - Dimension newDimension = new Dimension(newWorld, dimension.getMinecraftSeed(), tileFactory, dimension.getDim()); + Dimension newDimension = new Dimension(newWorld, dimension.getMinecraftSeed(), tileFactory, dimension.getAnchor()); try { for (Map.Entry settingsEntry: dimension.getAllLayerSettings().entrySet()) { if (settingsEntry.getValue() != null) { diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/ResetLava.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/ResetLava.java index 2d9d19a0..d9674267 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/ResetLava.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/ResetLava.java @@ -4,20 +4,18 @@ */ package org.pepsoft.worldpainter.tools; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; import org.pepsoft.worldpainter.Dimension; -import static org.pepsoft.worldpainter.Constants.*; import org.pepsoft.worldpainter.Tile; import org.pepsoft.worldpainter.World2; import org.pepsoft.worldpainter.layers.FloodWithLava; +import java.io.*; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import static org.pepsoft.worldpainter.Constants.TILE_SIZE; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; + /** * * @author pepijn @@ -32,7 +30,7 @@ public class ResetLava { world = (World2) in.readObject(); } System.out.println("World loaded"); - Dimension dim0 = world.getDimension(0); + Dimension dim0 = world.getDimension(NORMAL_DETAIL); for (Tile tile: dim0.getTiles()) { for (int x = 0; x < TILE_SIZE; x++) { for (int y = 0; y < TILE_SIZE; y++) { diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/TestTool.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/TestTool.java index 836a1bf3..c9464ba7 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/TestTool.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/TestTool.java @@ -17,6 +17,7 @@ import java.util.Random; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL_1_15; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; //import org.pepsoft.worldpainter.gardenofeden.Inn; /** @@ -33,7 +34,7 @@ public class TestTool { world.setName("TestWorld"); world.setSpawnPoint(new Point(64, 64)); world.setGameType(GameType.CREATIVE); - Dimension dimension = world.getDimension(0); + Dimension dimension = world.getDimension(NORMAL_DETAIL); dimension.addTile(tileFactory.createTile(0, 0)); Garden garden = dimension.getGarden(); // Inn inn = new Inn(garden, seed, null, new Point(64, 64), 1, 9, 9, EAST, 3, RandomOne.of(ThemeManager.getInstance().getThemes()), false, true, true, true, true, true, true, true, true, true, true, Inn.createName(seed)); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/Timings.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/Timings.java index 593be658..938eea60 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/Timings.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/Timings.java @@ -5,6 +5,13 @@ */ package org.pepsoft.worldpainter.tools; +import org.pepsoft.minecraft.Constants; +import org.pepsoft.util.FileUtils; +import org.pepsoft.util.ProgressReceiver; +import org.pepsoft.worldpainter.DefaultPlugin; +import org.pepsoft.worldpainter.World2; +import org.pepsoft.worldpainter.exporting.JavaWorldExporter; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -12,12 +19,8 @@ import java.io.ObjectInputStream; import java.security.SecureRandom; import java.util.Random; import java.util.zip.GZIPInputStream; -import org.pepsoft.minecraft.Constants; -import org.pepsoft.util.FileUtils; -import org.pepsoft.util.ProgressReceiver; -import org.pepsoft.worldpainter.DefaultPlugin; -import org.pepsoft.worldpainter.World2; -import org.pepsoft.worldpainter.exporting.JavaWorldExporter; + +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; /** * @@ -34,7 +37,7 @@ public class Timings { long totalDuration = 0; for (int i = 0; i < 5; i++) { // final World2 world = WorldFactory.createDefaultWorld(defaultConfig, random.nextLong()); - world.getDimension(0).getTileFactory().setSeed(random.nextLong()); + world.getDimension(NORMAL_DETAIL).getTileFactory().setSeed(random.nextLong()); if (world.getPlatform() == null) { if (world.getMaxHeight() == Constants.DEFAULT_MAX_HEIGHT_ANVIL) { world.setPlatform(DefaultPlugin.JAVA_ANVIL); @@ -43,7 +46,7 @@ public class Timings { } } final JavaWorldExporter exporter = new JavaWorldExporter(world); - System.out.println("Starting export of world " + world.getName() + " " + i + " (seed: " + world.getDimension(0).getSeed() + ")"); + System.out.println("Starting export of world " + world.getName() + " " + i + " (seed: " + world.getDimension(NORMAL_DETAIL).getSeed() + ")"); File baseDir = new File(System.getProperty("user.dir")); String name = world.getName() + ' ' + i; File worldDir = new File(baseDir, FileUtils.sanitiseName(name)); diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/scripts/MappingOp.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/scripts/MappingOp.java index 1fe97952..0d87d25f 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/scripts/MappingOp.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/tools/scripts/MappingOp.java @@ -25,6 +25,7 @@ package org.pepsoft.worldpainter.tools.scripts; import org.pepsoft.worldpainter.Dimension; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.HeightMap; import org.pepsoft.worldpainter.Terrain; import org.pepsoft.worldpainter.World2; @@ -41,6 +42,7 @@ import java.util.HashMap; import java.util.Map; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Role.DETAIL; /** * @@ -111,31 +113,37 @@ public class MappingOp extends AbstractOperation { public MappingOp applyToSurface() { this.dimIndex = DIM_NORMAL; + this.dimInverted = false; return this; } public MappingOp applyToNether() { this.dimIndex = DIM_NETHER; + this.dimInverted = false; return this; } public MappingOp applyToEnd() { this.dimIndex = DIM_END; + this.dimInverted = false; return this; } public MappingOp applyToSurfaceCeiling() { - this.dimIndex = DIM_NORMAL_CEILING; + this.dimIndex = DIM_NORMAL; + this.dimInverted = true; return this; } public MappingOp applyToNetherCeiling() { - this.dimIndex = DIM_NETHER_CEILING; + this.dimIndex = DIM_NETHER; + this.dimInverted = true; return this; } public MappingOp applyToEndCeiling() { - this.dimIndex = DIM_END_CEILING; + this.dimIndex = DIM_END; + this.dimInverted = true; return this; } @@ -324,7 +332,7 @@ public class MappingOp extends AbstractOperation { } } } - final Dimension dimension = world.getDimension(dimIndex); + final Dimension dimension = world.getDimension(new Anchor(dimIndex, DETAIL, dimInverted, 0)); if (dimension == null) { throw new ScriptException("Non existent dimension specified"); } @@ -459,6 +467,7 @@ public class MappingOp extends AbstractOperation { private long storedColour = -1L; private Mode mode = Mode.SET; private Filter filter; + private boolean dimInverted; enum Mode { SET, SET_WHEN_LOWER, SET_WHEN_HIGHER, SET_TERRAIN diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/MaterialUtils.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/MaterialUtils.java index 7f9a147b..6ade07b6 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/MaterialUtils.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/MaterialUtils.java @@ -97,7 +97,7 @@ public class MaterialUtils { if (settings.getChance(material) > 0) { if (material.blockType == -1) { nameOnlyMaterialsForLayer.add(material.name); - } else if ((material == GOLD_ORE) && (dimension.getDim() == DIM_NETHER)) { + } else if ((material == GOLD_ORE) && (dimension.getAnchor().dim == DIM_NETHER)) { nameOnlyMaterialsForLayer.add(NETHER_GOLD_ORE.name); } } diff --git a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/WorldUtils.java b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/WorldUtils.java index a6a30abd..b4f51883 100644 --- a/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/WorldUtils.java +++ b/WorldPainter/WPCore/src/main/java/org/pepsoft/worldpainter/util/WorldUtils.java @@ -14,9 +14,11 @@ import org.pepsoft.worldpainter.layers.exporters.ExporterSettings; import java.util.ArrayList; import java.util.List; +import java.util.Set; import static org.pepsoft.minecraft.Constants.*; -import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Constants.DIM_END; +import static org.pepsoft.worldpainter.Constants.DIM_NETHER; /** * Utility methods for working with WorldPainter worlds. @@ -31,9 +33,11 @@ public final class WorldUtils { */ public static void resizeWorld(final World2 world, final HeightTransform transform, final int newMinHeight, final int newMaxHeight, final boolean transformLayers, final ProgressReceiver progressReceiver) throws OperationCancelled { world.setMaxHeight(newMaxHeight); - final org.pepsoft.worldpainter.Dimension[] dimensions = world.getDimensions(); - for (int i = 0; i < dimensions.length; i++) { - resizeDimension(dimensions[i], newMinHeight, newMaxHeight, transform, transformLayers, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, (float) i / dimensions.length, 1f / dimensions.length) : null); + final Set dimensions = world.getDimensions(); + final int total = dimensions.size(); + int count = 0; + for (Dimension dimension: dimensions) { + resizeDimension(dimension, newMinHeight, newMaxHeight, transform, transformLayers, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, (float) count++ / total, 1f / total) : null); } } @@ -43,14 +47,12 @@ public final class WorldUtils { public static void resizeDimension(final Dimension dim, final int newMinHeight, final int newMaxHeight, final HeightTransform transform, final boolean transformLayers, final ProgressReceiver progressReceiver) throws OperationCancelled { final int oldMinHeight = dim.getMinHeight(), oldMaxHeight = dim.getMaxHeight(); final int dimNewMinHeight, dimNewMaxHeight; - switch (dim.getDim()) { + switch (dim.getAnchor().dim) { case DIM_NETHER: - case DIM_NETHER_CEILING: dimNewMinHeight = Math.max(newMinHeight, 0); dimNewMaxHeight = Math.min(newMaxHeight, DEFAULT_MAX_HEIGHT_NETHER); break; case DIM_END: - case DIM_END_CEILING: dimNewMinHeight = Math.max(newMinHeight, 0); dimNewMaxHeight = Math.min(newMaxHeight, DEFAULT_MAX_HEIGHT_END); break; @@ -90,7 +92,6 @@ public final class WorldUtils { final int raiseBy = oldMinHeight - dimNewMinHeight; final SuperflatPreset settings = ((SuperflatGenerator) dim.getGenerator()).getSettings(); final List layers = new ArrayList<>(settings.getLayers()); - final int currentHeight = layers.stream().mapToInt(SuperflatPreset.Layer::getThickness).sum(); if (raiseBy > 0) { // Insert deepslate to raise the Superflat terrain up. Skip the lowest layer // if that is bedrock, so that bedrock remains at the bottom. If the lowest diff --git a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/ExportTester.java b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/ExportTester.java index 0d7d7644..0be52ff0 100644 --- a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/ExportTester.java +++ b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/ExportTester.java @@ -15,13 +15,12 @@ import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.toSet; import static org.pepsoft.minecraft.Constants.DEFAULT_MAX_HEIGHT_ANVIL; import static org.pepsoft.worldpainter.DefaultPlugin.*; import static org.pepsoft.worldpainter.plugins.WPPluginManager.DESCRIPTOR_PATH; @@ -126,9 +125,11 @@ public class ExportTester extends RegressionIT { verifyJavaWorld(mapDir, (world.getPlatform() == JAVA_MCREGION)? Constants.VERSION_MCREGION : Constants.VERSION_ANVIL); final Collection dimensions; if (world.getDimensionsToExport() != null) { - dimensions = world.getDimensionsToExport().stream().map(world::getDimension).collect(Collectors.toSet()); + dimensions = world.getDimensions().stream() + .filter(dimension -> world.getDimensionsToExport().contains(dimension.getAnchor().dim)) + .collect(toSet()); } else { - dimensions = Arrays.asList(world.getDimensions()); + dimensions = world.getDimensions(); } for (Dimension dimension: dimensions) { // Gather some blocks which really should exist in the exported map. This is a bit of a gamble though diff --git a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/RegressionIT.java b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/RegressionIT.java index e29f9e17..1040d33d 100644 --- a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/RegressionIT.java +++ b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/RegressionIT.java @@ -77,8 +77,8 @@ public class RegressionIT { File anvil115worldDir = exportDimension(dimension, tmpBaseDir); logger.info("Comparing dimension " + dimension.getName()); Rectangle area = new Rectangle(dimension.getLowestX() << 5, dimension.getLowestY() << 5, dimension.getWidth() << 5, dimension.getHeight() << 5); - try (MinecraftWorld anvil12World = new JavaMinecraftWorld(anvil12worldDir, dimension.getDim(), dimension.getMaxHeight(), JAVA_ANVIL, true, 256); - MinecraftWorld anvil115World = new JavaMinecraftWorld(anvil115worldDir, dimension.getDim(), dimension.getMaxHeight(), JAVA_ANVIL_1_15, true, 256)) { + try (MinecraftWorld anvil12World = new JavaMinecraftWorld(anvil12worldDir, dimension.getAnchor().dim, dimension.getMaxHeight(), JAVA_ANVIL, true, 256); + MinecraftWorld anvil115World = new JavaMinecraftWorld(anvil115worldDir, dimension.getAnchor().dim, dimension.getMaxHeight(), JAVA_ANVIL_1_15, true, 256)) { MinecraftWorldUtils.assertEquals("Anvil 1.2", anvil12World, "Anvil 1.15", anvil115World, area); } } finally { @@ -114,7 +114,7 @@ public class RegressionIT { // Export logger.info("Exporting dimension {} of world {}", dimension.getName(), world.getName()); - world.setDimensionsToExport(singleton(dimension.getDim())); + world.setDimensionsToExport(singleton(dimension.getAnchor().dim)); JavaWorldExporter worldExporter = new JavaWorldExporter(world); String name = world.getName() + "-" + world.getPlatform().id; worldExporter.export(baseDir, name, null, null); @@ -178,7 +178,7 @@ public class RegressionIT { int[] lowestChunkX = {Integer.MAX_VALUE}, highestChunkX = {Integer.MIN_VALUE}; int[] lowestChunkZ = {Integer.MAX_VALUE}, highestChunkZ = {Integer.MIN_VALUE}; Set materials = new HashSet<>(); - ChunkStore chunkStore = platformProvider.getChunkStore(platform, worldDir, dimension.getDim()); + ChunkStore chunkStore = platformProvider.getChunkStore(platform, worldDir, dimension.getAnchor().dim); chunkStore.visitChunks(chunk -> { if (chunk.getxPos() < lowestChunkX[0]) { lowestChunkX[0] = chunk.getxPos(); diff --git a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/TestData.java b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/TestData.java index 9bf18b0e..c7868ae9 100644 --- a/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/TestData.java +++ b/WorldPainter/WPCore/src/test/java/org/pepsoft/worldpainter/TestData.java @@ -11,8 +11,8 @@ import org.pepsoft.worldpainter.themes.Theme; import java.awt.*; import static org.pepsoft.minecraft.Material.*; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.Constants.TILE_SIZE; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Terrain.GRASS; public final class TestData { @@ -26,7 +26,7 @@ public final class TestData { public static Dimension createDimension(Rectangle area, int terrainHeight) { final TileFactory tileFactory = createTileFactory(terrainHeight); - final Dimension dimension = new Dimension(WORLD, SEED, tileFactory, DIM_NORMAL); + final Dimension dimension = new Dimension(WORLD, SEED, tileFactory, NORMAL_DETAIL); final int tileX1 = area.x / TILE_SIZE, tileX2 = (area.x + area.width - 1) / TILE_SIZE, tileY1 = area.y / TILE_SIZE, tileY2 = (area.y + area.height - 1) / TILE_SIZE; for (int tileX = tileX1; tileX <= tileX2; tileX++) { for (int tileY = tileY1; tileY <= tileY2; tileY++) { diff --git a/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/DynMapPreviewer.java b/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/DynMapPreviewer.java index 59c87481..33c29b7f 100644 --- a/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/DynMapPreviewer.java +++ b/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/DynMapPreviewer.java @@ -28,8 +28,8 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL_1_15; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.plugins.WPPluginManager.DESCRIPTOR_PATH; /** @@ -117,12 +117,7 @@ public class DynMapPreviewer extends TiledImageViewer { tileProvider.setAzimuth(azimuth); tileProvider.setInclination(inclination); tileProvider.setCaves(caves); - if (getTileProviderCount() == 0) { - // First time - addTileProvider(tileProvider); - } else { - replaceTileProvider(0, tileProvider); - } + setTileProvider(tileProvider); } else { tileProvider = null; if (getTileProviderCount() > 0) { @@ -235,7 +230,7 @@ public class DynMapPreviewer extends TiledImageViewer { DynMapPreviewer viewer = new DynMapPreviewer(); WPObject object = CustomObjectManager.getInstance().loadObject(new File(args[0])); TileFactory tileFactory = TileFactoryFactory.createNoiseTileFactory(0L, Terrain.GRASS, JAVA_ANVIL_1_15.minZ, JAVA_ANVIL_1_15.standardMaxHeight, 58, DEFAULT_WATER_LEVEL, false, true, 20.0f, 1.0); - Dimension dimension = new World2(JAVA_ANVIL_1_15, 0L, tileFactory).getDimension(DIM_NORMAL); + Dimension dimension = new World2(JAVA_ANVIL_1_15, 0L, tileFactory).getDimension(NORMAL_DETAIL); viewer.setObject(object, dimension); frame.getContentPane().add(viewer, BorderLayout.CENTER); frame.setSize(800, 600); diff --git a/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/WPDynmapWorld.java b/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/WPDynmapWorld.java index 7f6e04e0..5dd7fcfe 100644 --- a/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/WPDynmapWorld.java +++ b/WorldPainter/WPDynmapPreviewer/src/main/java/org/pepsoft/worldpainter/dynmap/WPDynmapWorld.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.util.List; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; +import static org.pepsoft.worldpainter.Constants.DIM_NETHER; /** * A {@link DynmapWorld} implementation which wraps a {@link MinecraftWorld} for @@ -36,7 +37,7 @@ public class WPDynmapWorld extends DynmapWorld { @Override public boolean isNether() { - return dim == Constants.DIM_NETHER || dim == Constants.DIM_NETHER_CEILING; + return dim == DIM_NETHER; } @Override @@ -93,13 +94,10 @@ public class WPDynmapWorld extends DynmapWorld { public String getEnvironment() { switch (dim) { case Constants.DIM_NORMAL: - case Constants.DIM_NORMAL_CEILING: return "normal"; case Constants.DIM_END: - case Constants.DIM_END_CEILING: return "the_end"; - case Constants.DIM_NETHER: - case Constants.DIM_NETHER_CEILING: + case DIM_NETHER: return "nether"; default: throw new IllegalArgumentException("Dimension " + dim + " not supported"); @@ -121,7 +119,7 @@ public class WPDynmapWorld extends DynmapWorld { } World2 wpWorld = dimension.getWorld(); Point spawnPoint = wpWorld.getSpawnPoint(); - return forMinecraftWorld(minecraftWorld, wpWorld.getName() + " - " + dimension.getName(), dimension.getDim(), waterLevel, new Point3i(spawnPoint.x, spawnPoint.y, dimension.getIntHeightAt(spawnPoint.x, spawnPoint.y))); + return forMinecraftWorld(minecraftWorld, wpWorld.getName() + " - " + dimension.getName(), dimension.getAnchor().dim, waterLevel, new Point3i(spawnPoint.x, spawnPoint.y, dimension.getIntHeightAt(spawnPoint.x, spawnPoint.y))); } public static WPDynmapWorld forMinecraftMap(File worldDir, int dim) throws IOException { diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/App.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/App.java index a7c9d810..99372b1c 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/App.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/App.java @@ -19,6 +19,7 @@ import org.pepsoft.util.swing.ProgressTask; import org.pepsoft.util.swing.RemoteJCheckBox; import org.pepsoft.util.swing.TiledImageViewerContainer; import org.pepsoft.util.undo.UndoManager; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.biomeschemes.*; import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager.CustomBiomeListener; import org.pepsoft.worldpainter.brushes.BitmapBrush; @@ -109,6 +110,7 @@ import static org.pepsoft.util.swing.ProgressDialog.NOT_CANCELABLE; import static org.pepsoft.util.swing.ProgressDialog.NO_FOCUS_STEALING; import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES; import static org.pepsoft.worldpainter.Platform.Capability.*; import static org.pepsoft.worldpainter.Terrain.*; @@ -357,7 +359,7 @@ public final class App extends JFrame implements RadiusControl, // Reloading the same world; no need to do anything other than // to reload the dimension if (dimension != null) { - setDimension(world.getDimension(dimension.getDim())); + setDimension(world.getDimension(dimension.getAnchor())); } } else { this.world = world; @@ -383,7 +385,7 @@ public final class App extends JFrame implements RadiusControl, dockingManager.loadLayoutFrom(new ByteArrayInputStream(config.getJideLayoutData().get(world.getName()))); } - setDimension(world.getDimension(DIM_NORMAL)); + setDimension(world.getDimension(NORMAL_DETAIL)); if (config.isDefaultViewDistanceEnabled() != view.isDrawViewDistance()) { ACTION_VIEW_DISTANCE.actionPerformed(null); @@ -429,27 +431,8 @@ public final class App extends JFrame implements RadiusControl, // Keep the view position of the opposite dimension, if any, // in sync if (world != null) { - Dimension oppositeDimension = null; - switch (this.dimension.getDim()) { - case DIM_NORMAL: - oppositeDimension = world.getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - oppositeDimension = world.getDimension(DIM_NORMAL); - break; - case DIM_NETHER: - oppositeDimension = world.getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - oppositeDimension = world.getDimension(DIM_NETHER); - break; - case DIM_END: - oppositeDimension = world.getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - oppositeDimension = world.getDimension(DIM_END); - break; - } + final Anchor anchor = this.dimension.getAnchor(); + final Dimension oppositeDimension = world.getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); if (oppositeDimension != null) { oppositeDimension.setLastViewPosition(viewPosition); } @@ -496,12 +479,13 @@ public final class App extends JFrame implements RadiusControl, this.dimension = dimension; if (dimension != null) { setTitle("WorldPainter - " + world.getName() + " - " + dimension.getName()); // NOI18N - viewSurfaceMenuItem.setSelected(dimension.getDim() == DIM_NORMAL); - viewSurfaceCeilingMenuItem.setSelected(dimension.getDim() == DIM_NORMAL_CEILING); - viewNetherMenuItem.setSelected(dimension.getDim() == DIM_NETHER); - viewNetherCeilingMenuItem.setSelected(dimension.getDim() == DIM_NETHER_CEILING); - viewEndMenuItem.setSelected(dimension.getDim() == DIM_END); - viewEndCeilingMenuItem.setSelected(dimension.getDim() == DIM_END_CEILING); + final Anchor anchor = dimension.getAnchor(); + viewSurfaceMenuItem.setSelected((anchor.dim == DIM_NORMAL) && (! anchor.invert)); + viewSurfaceCeilingMenuItem.setSelected((anchor.dim == DIM_NORMAL) && anchor.invert); + viewNetherMenuItem.setSelected((anchor.dim == DIM_NETHER) && (! anchor.invert)); + viewNetherCeilingMenuItem.setSelected((anchor.dim == DIM_NETHER) && anchor.invert); + viewEndMenuItem.setSelected((anchor.dim == DIM_END) && (! anchor.invert)); + viewEndCeilingMenuItem.setSelected((anchor.dim == DIM_END) && anchor.invert); // Legacy: if this is an older world with an overlay enabled, ask // the user if we should fix the coordinates (ask because they might @@ -526,7 +510,7 @@ public final class App extends JFrame implements RadiusControl, view.moveTo(dimension.getLastViewPosition()); configureForPlatform(); - currentUndoManager = undoManagers.get(dimension.getDim()); + currentUndoManager = undoManagers.get(anchor.dim); if (currentUndoManager == null) { if ((! "true".equals(System.getProperty("org.pepsoft.worldpainter.disableUndo"))) && config.isUndoEnabled()) { currentUndoManager = new UndoManager(ACTION_UNDO, ACTION_REDO, Math.max(config.getUndoLevels() + 1, 2)); @@ -538,7 +522,7 @@ public final class App extends JFrame implements RadiusControl, ACTION_REDO.setEnabled(false); } currentUndoManager.setStopAtClasses(PropertyChangeListener.class, Tile.Listener.class, Biome.class, BetterAction.class); - undoManagers.put(dimension.getDim(), currentUndoManager); + undoManagers.put(anchor.dim, currentUndoManager); dimension.register(currentUndoManager); } else if ((!"true".equals(System.getProperty("org.pepsoft.worldpainter.disableUndo"))) && config.isUndoEnabled()) { currentUndoManager.registerActions(ACTION_UNDO, ACTION_REDO); @@ -936,15 +920,15 @@ public final class App extends JFrame implements RadiusControl, Configuration config = Configuration.getInstance(); EventVO event = new EventVO(EVENT_KEY_ACTION_OPEN_WORLD).addTimestamp(); event.setAttribute(ATTRIBUTE_KEY_MAX_HEIGHT, newWorld.getMaxHeight()); - Dimension loadedDimension = newWorld.getDimension(0); + Dimension loadedDimension = newWorld.getDimension(NORMAL_DETAIL); event.setAttribute(ATTRIBUTE_KEY_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, ""); - loadedDimension = newWorld.getDimension(1); + loadedDimension = newWorld.getDimension(NETHER_DETAIL); if (loadedDimension != null) { event.setAttribute(ATTRIBUTE_KEY_NETHER_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, "nether."); } - loadedDimension = newWorld.getDimension(2); + loadedDimension = newWorld.getDimension(END_DETAIL); if (loadedDimension != null) { event.setAttribute(ATTRIBUTE_KEY_END_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, "end."); @@ -1129,7 +1113,7 @@ public final class App extends JFrame implements RadiusControl, } view.setInhibitUpdates(true); try { - ShiftWorldDialog dialog = new ShiftWorldDialog(parent, world, dimension.getDim()); + ShiftWorldDialog dialog = new ShiftWorldDialog(parent, world, dimension.getAnchor()); dialog.setVisible(true); if (! dialog.isCancelled()) { currentUndoManager.armSavePoint(); @@ -1148,7 +1132,7 @@ public final class App extends JFrame implements RadiusControl, } view.setInhibitUpdates(true); try { - RotateWorldDialog dialog = new RotateWorldDialog(parent, world, dimension.getDim()); + RotateWorldDialog dialog = new RotateWorldDialog(parent, world, dimension.getAnchor()); dialog.setVisible(true); if (! dialog.isCancelled()) { currentUndoManager.armSavePoint(); @@ -1167,7 +1151,7 @@ public final class App extends JFrame implements RadiusControl, } view.setInhibitUpdates(true); try { - ScaleWorldDialog dialog = new ScaleWorldDialog(parent, world, dimension.getDim()); + ScaleWorldDialog dialog = new ScaleWorldDialog(parent, world, dimension.getAnchor()); dialog.setVisible(true); if (! dialog.isCancelled()) { currentUndoManager.armSavePoint(); @@ -1954,7 +1938,7 @@ public final class App extends JFrame implements RadiusControl, return; } Configuration config = Configuration.getInstance(); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, strings.getString("generated.world"), DEFAULT_OCEAN_SEED, config.getDefaultPlatform(), DIM_NORMAL, config.getDefaultMaxHeight(), null); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, strings.getString("generated.world"), DEFAULT_OCEAN_SEED, config.getDefaultPlatform(), NORMAL_DETAIL, config.getDefaultMaxHeight(), null); dialog.setVisible(true); if (! dialog.isCancelled()) { clearWorld(); // Free up memory of the world and the undo buffer @@ -1980,7 +1964,7 @@ public final class App extends JFrame implements RadiusControl, // Log an event EventVO event = new EventVO(EVENT_KEY_ACTION_NEW_WORLD).addTimestamp(); event.setAttribute(ATTRIBUTE_KEY_MAX_HEIGHT, newWorld.getMaxHeight()); - event.setAttribute(ATTRIBUTE_KEY_TILES, newWorld.getDimension(0).getTileCount()); + event.setAttribute(ATTRIBUTE_KEY_TILES, newWorld.getDimension(NORMAL_DETAIL).getTileCount()); config.logEvent(event); setWorld(newWorld, true); @@ -2246,15 +2230,15 @@ public final class App extends JFrame implements RadiusControl, // Log an event EventVO event = new EventVO(EVENT_KEY_ACTION_SAVE_WORLD).addTimestamp(); event.setAttribute(ATTRIBUTE_KEY_MAX_HEIGHT, world.getMaxHeight()); - Dimension loadedDimension = world.getDimension(0); + Dimension loadedDimension = world.getDimension(NORMAL_DETAIL); event.setAttribute(ATTRIBUTE_KEY_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, ""); - loadedDimension = world.getDimension(1); + loadedDimension = world.getDimension(NETHER_DETAIL); if (loadedDimension != null) { event.setAttribute(ATTRIBUTE_KEY_NETHER_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, "nether."); } - loadedDimension = world.getDimension(2); + loadedDimension = world.getDimension(END_DETAIL); if (loadedDimension != null) { event.setAttribute(ATTRIBUTE_KEY_END_TILES, loadedDimension.getTileCount()); logLayers(loadedDimension, event, "end."); @@ -4264,38 +4248,38 @@ public final class App extends JFrame implements RadiusControl, menu.addSeparator(); viewSurfaceMenuItem = new JCheckBoxMenuItem(strings.getString("view.surface"), true); - viewSurfaceMenuItem.addActionListener(e -> viewDimension(DIM_NORMAL)); + viewSurfaceMenuItem.addActionListener(e -> viewDimension(NORMAL_DETAIL)); viewSurfaceMenuItem.setMnemonic('s'); viewSurfaceMenuItem.setAccelerator(KeyStroke.getKeyStroke(VK_U, PLATFORM_COMMAND_MASK)); viewSurfaceMenuItem.setEnabled(false); menu.add(viewSurfaceMenuItem); viewSurfaceCeilingMenuItem = new JCheckBoxMenuItem("View Surface Ceiling", false); - viewSurfaceCeilingMenuItem.addActionListener(e -> viewDimension(DIM_NORMAL_CEILING)); + viewSurfaceCeilingMenuItem.addActionListener(e -> viewDimension(NORMAL_DETAIL_CEILING)); viewSurfaceCeilingMenuItem.setEnabled(false); menu.add(viewSurfaceCeilingMenuItem); viewNetherMenuItem = new JCheckBoxMenuItem(strings.getString("view.nether"), false); - viewNetherMenuItem.addActionListener(e -> viewDimension(DIM_NETHER)); + viewNetherMenuItem.addActionListener(e -> viewDimension(NETHER_DETAIL)); viewNetherMenuItem.setMnemonic('n'); viewNetherMenuItem.setAccelerator(KeyStroke.getKeyStroke(VK_H, PLATFORM_COMMAND_MASK)); viewNetherMenuItem.setEnabled(false); menu.add(viewNetherMenuItem); viewNetherCeilingMenuItem = new JCheckBoxMenuItem("View Nether Ceiling", false); - viewNetherCeilingMenuItem.addActionListener(e -> viewDimension(DIM_NETHER_CEILING)); + viewNetherCeilingMenuItem.addActionListener(e -> viewDimension(NETHER_DETAIL_CEILING)); viewNetherCeilingMenuItem.setEnabled(false); menu.add(viewNetherCeilingMenuItem); viewEndMenuItem = new JCheckBoxMenuItem(strings.getString("view.end"), false); - viewEndMenuItem.addActionListener(e -> viewDimension(DIM_END)); + viewEndMenuItem.addActionListener(e -> viewDimension(END_DETAIL)); viewEndMenuItem.setMnemonic('e'); viewEndMenuItem.setAccelerator(KeyStroke.getKeyStroke(VK_D, PLATFORM_COMMAND_MASK)); viewEndMenuItem.setEnabled(false); menu.add(viewEndMenuItem); viewEndCeilingMenuItem = new JCheckBoxMenuItem("View End Ceiling", false); - viewEndCeilingMenuItem.addActionListener(e -> viewDimension(DIM_END_CEILING)); + viewEndCeilingMenuItem.addActionListener(e -> viewDimension(END_DETAIL_CEILING)); viewEndCeilingMenuItem.setEnabled(false); menu.add(viewEndCeilingMenuItem); @@ -4466,7 +4450,7 @@ public final class App extends JFrame implements RadiusControl, biomesViewerFrame.requestFocus(); } else { int preferredAlgorithm = -1; - if ((dimension != null) && (dimension.getDim() == DIM_NORMAL) && (dimension.getMaxHeight() == DEFAULT_MAX_HEIGHT_ANVIL)) { + if ((dimension != null) && (dimension.getAnchor().dim == DIM_NORMAL) && (dimension.getMaxHeight() == DEFAULT_MAX_HEIGHT_ANVIL)) { if (dimension.getGenerator().getType() == LARGE_BIOMES) { preferredAlgorithm = BIOME_ALGORITHM_1_7_LARGE; } else { @@ -4582,8 +4566,8 @@ public final class App extends JFrame implements RadiusControl, } private void addSurfaceCeiling() { - final Dimension surface = world.getDimension(DIM_NORMAL); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 3, world.getPlatform(), DIM_NORMAL_CEILING, surface.getMaxHeight(), surface, surface.getTileCoords()); + final Dimension surface = world.getDimension(NORMAL_DETAIL); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 3, world.getPlatform(), NORMAL_DETAIL_CEILING, surface.getMaxHeight(), surface, surface.getTileCoords()); dialog.setVisible(true); if (! dialog.isCancelled()) { if (! dialog.checkMemoryRequirements(this)) { @@ -4611,12 +4595,12 @@ public final class App extends JFrame implements RadiusControl, private void removeSurfaceCeiling() { if (showConfirmDialog(this, "Are you sure you want to completely remove the Surface ceiling?\nThis action cannot be undone!", "Confirm Surface Ceiling Deletion", YES_NO_OPTION) == YES_OPTION) { - world.removeDimension(DIM_NORMAL_CEILING); - if ((dimension != null) && (dimension.getDim() == DIM_NORMAL_CEILING)) { - viewDimension(DIM_NORMAL); + world.removeDimension(NORMAL_DETAIL_CEILING); + if ((dimension != null) && (dimension.getAnchor().equals(NORMAL_DETAIL_CEILING))) { + viewDimension(NORMAL_DETAIL); } else { configureForPlatform(); - if (dimension.getDim() == DIM_NORMAL) { + if (dimension.getAnchor().dim == DIM_NORMAL) { view.refreshTiles(); } } @@ -4625,8 +4609,8 @@ public final class App extends JFrame implements RadiusControl, } private void addNetherCeiling() { - final Dimension nether = world.getDimension(DIM_NETHER); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), nether.getSeed() + 1, world.getPlatform(), DIM_NETHER_CEILING, nether.getMaxHeight(), nether, nether.getTileCoords()); + final Dimension nether = world.getDimension(NETHER_DETAIL); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), nether.getSeed() + 1, world.getPlatform(), NETHER_DETAIL_CEILING, nether.getMaxHeight(), nether, nether.getTileCoords()); dialog.setVisible(true); if (! dialog.isCancelled()) { if (! dialog.checkMemoryRequirements(this)) { @@ -4654,12 +4638,12 @@ public final class App extends JFrame implements RadiusControl, private void removeNetherCeiling() { if (showConfirmDialog(this, "Are you sure you want to completely remove the Nether ceiling?\nThis action cannot be undone!", "Confirm Nether Ceiling Deletion", YES_NO_OPTION) == YES_OPTION) { - world.removeDimension(DIM_NETHER_CEILING); - if ((dimension != null) && (dimension.getDim() == DIM_NETHER_CEILING)) { - viewDimension(DIM_NETHER); + world.removeDimension(NETHER_DETAIL_CEILING); + if ((dimension != null) && (dimension.getAnchor().equals(NETHER_DETAIL_CEILING))) { + viewDimension(NETHER_DETAIL); } else { configureForPlatform(); - if (dimension.getDim() == DIM_NETHER) { + if (dimension.getAnchor().dim == DIM_NETHER) { view.refreshTiles(); } } @@ -4668,8 +4652,8 @@ public final class App extends JFrame implements RadiusControl, } private void addEndCeiling() { - final Dimension end = world.getDimension(DIM_END); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), end.getSeed() + 1, world.getPlatform(), DIM_END_CEILING, end.getMaxHeight(), end, end.getTileCoords()); + final Dimension end = world.getDimension(END_DETAIL); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), end.getSeed() + 1, world.getPlatform(), END_DETAIL_CEILING, end.getMaxHeight(), end, end.getTileCoords()); dialog.setVisible(true); if (! dialog.isCancelled()) { if (! dialog.checkMemoryRequirements(this)) { @@ -4697,12 +4681,12 @@ public final class App extends JFrame implements RadiusControl, private void removeEndCeiling() { if (showConfirmDialog(this, "Are you sure you want to completely remove the End ceiling?\nThis action cannot be undone!", "Confirm End Ceiling Deletion", YES_NO_OPTION) == YES_OPTION) { - world.removeDimension(DIM_END_CEILING); - if ((dimension != null) && (dimension.getDim() == DIM_END_CEILING)) { - viewDimension(DIM_END); + world.removeDimension(END_DETAIL_CEILING); + if ((dimension != null) && (dimension.getAnchor().equals(END_DETAIL_CEILING))) { + viewDimension(END_DETAIL); } else { configureForPlatform(); - if (dimension.getDim() == DIM_END) { + if (dimension.getAnchor().dim == DIM_END) { view.refreshTiles(); } } @@ -4845,8 +4829,8 @@ public final class App extends JFrame implements RadiusControl, } private void addNether() { - final Dimension surface = world.getDimension(DIM_NORMAL); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 1, world.getPlatform(), DIM_NETHER, Math.min(world.getMaxHeight(), DEFAULT_MAX_HEIGHT_NETHER), surface); + final Dimension surface = world.getDimension(NORMAL_DETAIL); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 1, world.getPlatform(), NETHER_DETAIL, Math.min(world.getMaxHeight(), DEFAULT_MAX_HEIGHT_NETHER), surface); dialog.setVisible(true); if (! dialog.isCancelled()) { if (! dialog.checkMemoryRequirements(this)) { @@ -4876,12 +4860,12 @@ public final class App extends JFrame implements RadiusControl, private void removeNether() { if (showConfirmDialog(this, "Are you sure you want to completely remove the Nether dimension?\nThis action cannot be undone!", "Confirm Nether Deletion", YES_NO_OPTION) == YES_OPTION) { - world.removeDimension(DIM_NETHER); - if (world.getDimension(DIM_NETHER_CEILING) != null) { - world.removeDimension(DIM_NETHER_CEILING); + world.removeDimension(NETHER_DETAIL); + if (world.getDimension(NETHER_DETAIL_CEILING) != null) { + world.removeDimension(NETHER_DETAIL_CEILING); } - if ((dimension != null) && ((dimension.getDim() == DIM_NETHER) || (dimension.getDim() == DIM_NETHER_CEILING))) { - viewDimension(DIM_NORMAL); + if ((dimension != null) && (dimension.getAnchor().dim == DIM_NETHER)) { + viewDimension(NORMAL_DETAIL); } else { configureForPlatform(); } @@ -4890,8 +4874,8 @@ public final class App extends JFrame implements RadiusControl, } private void addEnd() { - final Dimension surface = world.getDimension(DIM_NORMAL); - final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 2, world.getPlatform(), DIM_END, Math.min(world.getMaxHeight(), DEFAULT_MAX_HEIGHT_END), surface); + final Dimension surface = world.getDimension(NORMAL_DETAIL); + final NewWorldDialog dialog = new NewWorldDialog(this, selectedColourScheme, world.getName(), surface.getSeed() + 2, world.getPlatform(), END_DETAIL, Math.min(world.getMaxHeight(), DEFAULT_MAX_HEIGHT_END), surface); dialog.setVisible(true); if (! dialog.isCancelled()) { if (! dialog.checkMemoryRequirements(this)) { @@ -4919,12 +4903,12 @@ public final class App extends JFrame implements RadiusControl, private void removeEnd() { if (showConfirmDialog(this, "Are you sure you want to completely remove the End dimension?\nThis action cannot be undone!", "Confirm End Deletion", YES_NO_OPTION) == YES_OPTION) { - world.removeDimension(DIM_END); - if (world.getDimension(DIM_END_CEILING) != null) { - world.removeDimension(DIM_END_CEILING); + world.removeDimension(END_DETAIL); + if (world.getDimension(END_DETAIL_CEILING) != null) { + world.removeDimension(END_DETAIL_CEILING); } - if ((dimension != null) && ((dimension.getDim() == DIM_END) || (dimension.getDim() == DIM_END_CEILING))) { - viewDimension(DIM_NORMAL); + if ((dimension != null) && (dimension.getAnchor().dim == DIM_END)) { + viewDimension(NORMAL_DETAIL); } else { configureForPlatform(); } @@ -4932,9 +4916,9 @@ public final class App extends JFrame implements RadiusControl, } } - private void viewDimension(int dim) { - if (dim != dimension.getDim()) { - setDimension(world.getDimension(dim)); + private void viewDimension(Anchor anchor) { + if (! anchor.equals(dimension.getAnchor())) { + setDimension(world.getDimension(anchor)); } } @@ -5372,11 +5356,11 @@ public final class App extends JFrame implements RadiusControl, private void configureForPlatform() { final Platform platform = world.getPlatform(); boolean imported = (world != null) && (world.getImportedFrom() != null); - boolean nether = (world != null) && (world.getDimension(DIM_NETHER) != null); - boolean end = (world != null) && (world.getDimension(DIM_END) != null); - boolean surfaceCeiling = (world != null) && (world.getDimension(DIM_NORMAL_CEILING) != null); - boolean netherCeiling = (world != null) && (world.getDimension(DIM_NETHER_CEILING) != null); - boolean endCeiling = (world != null) && (world.getDimension(DIM_END_CEILING) != null); + boolean nether = (world != null) && (world.getDimension(NETHER_DETAIL) != null); + boolean end = (world != null) && (world.getDimension(END_DETAIL) != null); + boolean surfaceCeiling = (world != null) && (world.getDimension(NORMAL_DETAIL_CEILING) != null); + boolean netherCeiling = (world != null) && (world.getDimension(NETHER_DETAIL_CEILING) != null); + boolean endCeiling = (world != null) && (world.getDimension(END_DETAIL_CEILING) != null); biomeHelper = new BiomeHelper(selectedColourScheme, customBiomeManager, platform); addNetherMenuItem.setEnabled(platform.supportedDimensions.contains(DIM_NETHER) && (! imported) && (! nether)); removeNetherMenuItem.setEnabled(nether); @@ -5395,16 +5379,15 @@ public final class App extends JFrame implements RadiusControl, addEndCeilingMenuItem.setEnabled(platform.supportedDimensions.contains(DIM_END) && end && (! endCeiling)); removeEndCeilingMenuItem.setEnabled(endCeiling); if (dimension != null) { - final boolean biomesSupported = (dimension.getDim() >= 0) && platform.capabilities.contains(BIOMES) || platform.capabilities.contains(BIOMES_3D) || platform.capabilities.contains(NAMED_BIOMES); + final boolean biomesSupported = (! dimension.getAnchor().invert) && platform.capabilities.contains(BIOMES) || platform.capabilities.contains(BIOMES_3D) || platform.capabilities.contains(NAMED_BIOMES); if ((! biomesSupported) && (paint instanceof DiscreteLayerPaint) && (((DiscreteLayerPaint) paint).getLayer() == Biome.INSTANCE)) { deselectPaint(); } biomesPanelFrame.setEnabled(biomesSupported); // TODO deselect biomes panel if it was selected layerControls.get(Biome.INSTANCE).setEnabled(biomesSupported); - switch (dimension.getDim()) { + switch (dimension.getAnchor().dim) { case DIM_NORMAL: - case DIM_NORMAL_CEILING: setSpawnPointToggleButton.setEnabled(platform.capabilities.contains(SET_SPAWN_POINT)); ACTION_MOVE_TO_SPAWN.setEnabled(platform.capabilities.contains(SET_SPAWN_POINT)); break; @@ -5499,7 +5482,7 @@ public final class App extends JFrame implements RadiusControl, Terrain customTerrain = Terrain.getCustomTerrain(index); MixedMaterial mixedMaterial = getCustomMaterial(index); String name = mixedMaterial.getName(); - Set allTerrains = ProgressDialog.executeTask(this, "Checking whether terrain is in use", () -> Arrays.stream(world.getDimensions()) + Set allTerrains = ProgressDialog.executeTask(this, "Checking whether terrain is in use", () -> world.getDimensions().stream() .parallel() .flatMap(dim -> dim.getAllTerrains().parallelStream()) .collect(toSet()), NOT_CANCELABLE); @@ -5635,7 +5618,7 @@ public final class App extends JFrame implements RadiusControl, } sb.append(')'); final String description = sb.toString(); - String defaultname = world.getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getDim() == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + ".png"; // NOI18N + String defaultname = world.getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getAnchor().dim == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + ".png"; // NOI18N File selectedFile = FileUtils.selectFileForSave(App.this, "Export as image file", new File(defaultname), new FileFilter() { @Override public boolean accept(File f) { @@ -5714,7 +5697,7 @@ public final class App extends JFrame implements RadiusControl, sb.append(')'); final String description = sb.toString(); final String defaultExtension = extensions.get(0); - String defaultname = world.getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getDim() == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + (highRes ? "_high-res-heightmap." + defaultExtension : "_heightmap." + defaultExtension); // NOI18N + String defaultname = world.getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getAnchor().dim == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + (highRes ? "_high-res-heightmap." + defaultExtension : "_heightmap." + defaultExtension); // NOI18N Configuration config = Configuration.getInstance(); File dir = config.getHeightMapsDirectory(); if ((dir == null) || (! dir.isDirectory())) { @@ -6983,27 +6966,8 @@ public final class App extends JFrame implements RadiusControl, @Override public void performAction(ActionEvent e) { if ((dimension != null) && (world != null)) { - Dimension oppositeDimension = null; - switch (dimension.getDim()) { - case DIM_NORMAL: - oppositeDimension = world.getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - oppositeDimension = world.getDimension(DIM_NORMAL); - break; - case DIM_NETHER: - oppositeDimension = world.getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - oppositeDimension = world.getDimension(DIM_NETHER); - break; - case DIM_END: - oppositeDimension = world.getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - oppositeDimension = world.getDimension(DIM_END); - break; - } + final Anchor anchor = dimension.getAnchor(); + final Dimension oppositeDimension = world.getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); if (oppositeDimension != null) { setDimension(oppositeDimension); return; diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ChangeHeightDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ChangeHeightDialog.java index df92b9bf..3d3a3e7c 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ChangeHeightDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ChangeHeightDialog.java @@ -41,8 +41,8 @@ public class ChangeHeightDialog extends WorldPainterDialog { public ChangeHeightDialog(Window parent, World2 world) { super(parent); this.world = world; - lowestHeight = stream(world.getDimensions()).mapToInt(Dimension::getLowestIntHeight).min().getAsInt(); - highestHeight = stream(world.getDimensions()).mapToInt(Dimension::getHightestIntHeight).max().getAsInt(); + lowestHeight = world.getDimensions().stream().mapToInt(Dimension::getLowestIntHeight).min().getAsInt(); + highestHeight = world.getDimensions().stream().mapToInt(Dimension::getHightestIntHeight).max().getAsInt(); initComponents(); labelOldExtents.setText(lowestHeight + " - " + highestHeight); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/DimensionPropertiesEditor.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/DimensionPropertiesEditor.java index d4ae5ea9..69c0f1b9 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/DimensionPropertiesEditor.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/DimensionPropertiesEditor.java @@ -482,7 +482,7 @@ public class DimensionPropertiesEditor extends javax.swing.JPanel { // resources ResourcesExporterSettings resourcesSettings = (ResourcesExporterSettings) dimension.getLayerSettings(Resources.INSTANCE); if (resourcesSettings == null) { - resourcesSettings = ResourcesExporterSettings.defaultSettings(platform, dimension.getDim(), dimension.getMaxHeight()); + resourcesSettings = ResourcesExporterSettings.defaultSettings(platform, dimension.getAnchor().dim, dimension.getMaxHeight()); } if (jCheckBox8.isSelected()) { int minimumLevel = jSlider4.getValue(); @@ -904,7 +904,7 @@ public class DimensionPropertiesEditor extends javax.swing.JPanel { // resources ResourcesExporterSettings resourcesSettings = (ResourcesExporterSettings) dimension.getLayerSettings(Resources.INSTANCE); if (resourcesSettings == null) { - resourcesSettings = ResourcesExporterSettings.defaultSettings(platform, dimension.getDim(), dimension.getMaxHeight()); + resourcesSettings = ResourcesExporterSettings.defaultSettings(platform, dimension.getAnchor().dim, dimension.getMaxHeight()); resourcesSettings.setMinimumLevel(0); } jCheckBox8.setSelected(resourcesSettings.isApplyEverywhere()); @@ -1068,8 +1068,8 @@ public class DimensionPropertiesEditor extends javax.swing.JPanel { private void setControlStates() { final boolean enabled = isEnabled(); - final boolean dim0 = (dimension != null) && (dimension.getDim() == Constants.DIM_NORMAL); - final boolean ceiling = (dimension != null) && (dimension.getDim() < 0); + final boolean dim0 = (dimension != null) && (dimension.getAnchor().dim == Constants.DIM_NORMAL); + final boolean ceiling = (dimension != null) && dimension.getAnchor().invert; final boolean decorations = checkBoxDecorateCaverns.isSelected() || checkBoxDecorateCaves.isSelected() || checkBoxDecorateChasms.isSelected(); setEnabled(radioButtonLavaBorder, enabled && (! ceiling)); setEnabled(radioButtonNoBorder, enabled && (! ceiling)); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportTileSelectionDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportTileSelectionDialog.java index 968e4ed2..f9d241ae 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportTileSelectionDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportTileSelectionDialog.java @@ -10,6 +10,7 @@ */ package org.pepsoft.worldpainter; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager; import org.pepsoft.worldpainter.layers.Layer; @@ -24,6 +25,7 @@ import java.util.List; import java.util.Set; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Role.DETAIL; /** * @@ -38,11 +40,11 @@ public class ExportTileSelectionDialog extends javax.swing.JDialog implements Wi List dimensions = new ArrayList<>(); for (Dimension dimension: world.getDimensions()) { - if (dimension.getDim() < 0) { + if (dimension.getAnchor().invert) { // Ceiling dimensions shouldn't be separately selectable continue; } - dimensions.add(dimension.getDim()); + dimensions.add(dimension.getAnchor().dim); } jComboBox1.setModel(new DefaultComboBoxModel(dimensions.toArray())); programmaticChange = true; @@ -89,7 +91,7 @@ public class ExportTileSelectionDialog extends javax.swing.JDialog implements Wi tileSelector1.setContourLines(contourLines); tileSelector1.setContourSeparation(contourSeparation); tileSelector1.setLightOrigin(lightOrigin); - tileSelector1.setDimension(world.getDimension(selectedDimension)); + tileSelector1.setDimension(world.getDimension(new Anchor(selectedDimension, DETAIL, false, 0))); tileSelector1.setCustomBiomeManager(customBiomeManager); if (selectedTiles != null) { tileSelector1.setSelectedTiles(selectedTiles); @@ -214,7 +216,7 @@ public class ExportTileSelectionDialog extends javax.swing.JDialog implements Wi private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed if (! programmaticChange) { int selectedDimension = getSelectedDimension(); - tileSelector1.setDimension(world.getDimension(selectedDimension)); + tileSelector1.setDimension(world.getDimension(new Anchor(selectedDimension, DETAIL, false, 0))); tileSelector1.moveToCentre(); tileSelector1.clearSelection(); buttonSetSpawn.setEnabled(selectedDimension == DIM_NORMAL); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportWorldDialog.java index 00ea9e7b..d0289f61 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ExportWorldDialog.java @@ -12,6 +12,7 @@ package org.pepsoft.worldpainter; import org.pepsoft.util.DesktopUtils; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager; import org.pepsoft.worldpainter.layers.CustomLayer; import org.pepsoft.worldpainter.layers.Layer; @@ -33,6 +34,7 @@ import static org.pepsoft.minecraft.Constants.DIFFICULTY_HARD; import static org.pepsoft.minecraft.Constants.DIFFICULTY_PEACEFUL; import static org.pepsoft.worldpainter.Constants.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.GameType.*; import static org.pepsoft.worldpainter.Platform.Capability.NAME_BASED; import static org.pepsoft.worldpainter.Platform.Capability.POPULATE; @@ -51,7 +53,7 @@ public class ExportWorldDialog extends WorldPainterDialog { this.world = world; selectedTiles = world.getTilesToExport(); selectedDimension = (selectedTiles != null) ? world.getDimensionsToExport().iterator().next() : DIM_NORMAL; - final Dimension dim0 = world.getDimension(0); + final Dimension dim0 = world.getDimension(NORMAL_DETAIL); this.colourScheme = colourScheme; this.hiddenLayers = hiddenLayers; this.contourLines = contourLines; @@ -90,44 +92,44 @@ public class ExportWorldDialog extends WorldPainterDialog { surfacePropertiesEditor.setColourScheme(colourScheme); surfacePropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); surfacePropertiesEditor.setDimension(dim0); - dimensionPropertiesEditors.put(DIM_NORMAL, surfacePropertiesEditor); - if (world.getDimension(DIM_NETHER) != null) { + dimensionPropertiesEditors.put(NORMAL_DETAIL, surfacePropertiesEditor); + if (world.getDimension(NETHER_DETAIL) != null) { netherPropertiesEditor.setColourScheme(colourScheme); netherPropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); - netherPropertiesEditor.setDimension(world.getDimension(DIM_NETHER)); - dimensionPropertiesEditors.put(DIM_NETHER, netherPropertiesEditor); + netherPropertiesEditor.setDimension(world.getDimension(NETHER_DETAIL)); + dimensionPropertiesEditors.put(NETHER_DETAIL, netherPropertiesEditor); } else { jTabbedPane1.setEnabledAt(2, false); } - if (world.getDimension(DIM_END) != null) { + if (world.getDimension(END_DETAIL) != null) { endPropertiesEditor.setColourScheme(colourScheme); endPropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); - endPropertiesEditor.setDimension(world.getDimension(DIM_END)); - dimensionPropertiesEditors.put(DIM_END, endPropertiesEditor); + endPropertiesEditor.setDimension(world.getDimension(END_DETAIL)); + dimensionPropertiesEditors.put(END_DETAIL, endPropertiesEditor); } else { jTabbedPane1.setEnabledAt(4, false); } - if (world.getDimension(DIM_NORMAL_CEILING) != null) { + if (world.getDimension(NORMAL_DETAIL_CEILING) != null) { surfaceCeilingPropertiesEditor.setColourScheme(colourScheme); surfaceCeilingPropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); - surfaceCeilingPropertiesEditor.setDimension(world.getDimension(DIM_NORMAL_CEILING)); - dimensionPropertiesEditors.put(DIM_NORMAL_CEILING, surfaceCeilingPropertiesEditor); + surfaceCeilingPropertiesEditor.setDimension(world.getDimension(NORMAL_DETAIL_CEILING)); + dimensionPropertiesEditors.put(NORMAL_DETAIL_CEILING, surfaceCeilingPropertiesEditor); } else { jTabbedPane1.setEnabledAt(1, false); } - if (world.getDimension(DIM_NETHER_CEILING) != null) { + if (world.getDimension(NETHER_DETAIL_CEILING) != null) { netherCeilingPropertiesEditor.setColourScheme(colourScheme); netherCeilingPropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); - netherCeilingPropertiesEditor.setDimension(world.getDimension(DIM_NETHER_CEILING)); - dimensionPropertiesEditors.put(DIM_NETHER_CEILING, netherCeilingPropertiesEditor); + netherCeilingPropertiesEditor.setDimension(world.getDimension(NETHER_DETAIL_CEILING)); + dimensionPropertiesEditors.put(NETHER_DETAIL_CEILING, netherCeilingPropertiesEditor); } else { jTabbedPane1.setEnabledAt(3, false); } - if (world.getDimension(DIM_END_CEILING) != null) { + if (world.getDimension(END_DETAIL_CEILING) != null) { endCeilingPropertiesEditor.setColourScheme(colourScheme); endCeilingPropertiesEditor.setMode(DimensionPropertiesEditor.Mode.EXPORT); - endCeilingPropertiesEditor.setDimension(world.getDimension(DIM_END_CEILING)); - dimensionPropertiesEditors.put(DIM_END_CEILING, endCeilingPropertiesEditor); + endCeilingPropertiesEditor.setDimension(world.getDimension(END_DETAIL_CEILING)); + dimensionPropertiesEditors.put(END_DETAIL_CEILING, endCeilingPropertiesEditor); } else { jTabbedPane1.setEnabledAt(5, false); } @@ -248,16 +250,16 @@ public class ExportWorldDialog extends WorldPainterDialog { StringBuilder sb = new StringBuilder("Please confirm that you want to export the world
notwithstanding the following warnings:
    "); boolean showWarning = false; for (Dimension dimension: world.getDimensions()) { - if (dimension.getDim() < 0) { + if (dimension.getAnchor().invert) { // Skip ceilings continue; } - final DimensionPropertiesEditor editor = dimensionPropertiesEditors.get(dimension.getDim()); + final DimensionPropertiesEditor editor = dimensionPropertiesEditors.get(dimension.getAnchor()); final Generator generatorType = editor.getSelectedGeneratorType(); if ((editor.isPopulateSelected() || dimension.getAllLayers(true).contains(Populate.INSTANCE)) && (! platform.capabilities.contains(POPULATE))) { sb.append("
  • Population not supported for
    map format " + platform.displayName + "; it will not have an effect"); showWarning = true; - } else if ((! radioButtonExportSelection.isSelected()) || (selectedDimension == dimension.getDim())) { + } else if ((! radioButtonExportSelection.isSelected()) || (selectedDimension == dimension.getAnchor().dim)) { // The dimension is going to be exported if ((generatorType == Generator.FLAT) && (editor.isPopulateSelected() || dimension.getAllLayers(true).contains(Populate.INSTANCE))) { sb.append("
  • The Superflat world type is selected and Populate is in use.
    Minecraft will not populate generated chunks for Superflat maps."); @@ -394,31 +396,31 @@ public class ExportWorldDialog extends WorldPainterDialog { jTabbedPane1.setSelectedIndex(0); return false; } - if (world.getDimension(DIM_NETHER) != null) { + if (world.getDimension(NETHER_DETAIL) != null) { if (! netherPropertiesEditor.saveSettings()) { jTabbedPane1.setSelectedIndex(2); return false; } } - if (world.getDimension(DIM_END) != null) { + if (world.getDimension(END_DETAIL) != null) { if (! endPropertiesEditor.saveSettings()) { jTabbedPane1.setSelectedIndex(4); return false; } } - if (world.getDimension(DIM_NORMAL_CEILING) != null) { + if (world.getDimension(NORMAL_DETAIL_CEILING) != null) { if (! surfaceCeilingPropertiesEditor.saveSettings()) { jTabbedPane1.setSelectedIndex(1); return false; } } - if (world.getDimension(DIM_NETHER_CEILING) != null) { + if (world.getDimension(NETHER_DETAIL_CEILING) != null) { if (! netherCeilingPropertiesEditor.saveSettings()) { jTabbedPane1.setSelectedIndex(3); return false; } } - if (world.getDimension(DIM_END_CEILING) != null) { + if (world.getDimension(END_DETAIL_CEILING) != null) { if (! endCeilingPropertiesEditor.saveSettings()) { jTabbedPane1.setSelectedIndex(5); return false; @@ -479,7 +481,7 @@ public class ExportWorldDialog extends WorldPainterDialog { return; } if (App.getInstance().changeWorldHeight(this)) { - dimensionPropertiesEditors.forEach((dim, editor) -> editor.setDimension(world.getDimension(dim))); + dimensionPropertiesEditors.forEach((anchor, editor) -> editor.setDimension(world.getDimension(anchor))); platformChanged(); } } @@ -788,7 +790,7 @@ public class ExportWorldDialog extends WorldPainterDialog { checkBoxGoodies.setSelected(world.isCreateGoodiesChest()); - dimensionPropertiesEditors.forEach((dim, editor) -> editor.setPlatform(newPlatform)); + dimensionPropertiesEditors.forEach((anchor, editor) -> editor.setPlatform(newPlatform)); pack(); setControlStates(); @@ -849,7 +851,7 @@ public class ExportWorldDialog extends WorldPainterDialog { private final TileRenderer.LightOrigin lightOrigin; private final CustomBiomeManager customBiomeManager; private final WorldPainter view; - private final Map dimensionPropertiesEditors = new HashMap<>(); + private final Map dimensionPropertiesEditors = new HashMap<>(); private final List supportedPlatforms = new ArrayList<>(); private int selectedDimension; private Set selectedTiles; diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ImportHeightMapDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ImportHeightMapDialog.java index 5aa04c86..7a295523 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ImportHeightMapDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ImportHeightMapDialog.java @@ -571,11 +571,7 @@ public class ImportHeightMapDialog extends WorldPainterDialog implements Documen if (image != null) { TileProvider previewProvider = createImporter().getPreviewProvider(colourScheme, contourLines, contourSeparation, lightOrigin); if (previewProvider != null) { - if (tiledImageViewer2.getTileProviderCount() == 0) { - tiledImageViewer2.addTileProvider(previewProvider); - } else { - tiledImageViewer2.replaceTileProvider(0, previewProvider); - } + tiledImageViewer2.setTileProvider(previewProvider); if (recentre) { tiledImageViewer2.moveTo(image.getWidth() / 2, image.getHeight() / 2); } diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/MergeWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/MergeWorldDialog.java index 2586599d..ae65c1ea 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/MergeWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/MergeWorldDialog.java @@ -38,6 +38,7 @@ import java.util.Set; import static org.pepsoft.worldpainter.App.MERGE_WARNING_KEY; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.*; import static org.pepsoft.worldpainter.Platform.Capability.*; import static org.pepsoft.worldpainter.util.BackupUtils.cleanUpBackups; @@ -46,6 +47,7 @@ import static org.pepsoft.worldpainter.util.BackupUtils.cleanUpBackups; * @author pepijn */ // TODO: add support for multiple dimensions +@SuppressWarnings({"unused", "FieldCanBeLocal", "Convert2Lambda", "Anonymous2MethodRef", "ConstantConditions"}) // Managed by NetBeans public class MergeWorldDialog extends WorldPainterDialog { /** Creates new form ExportWorldDialog */ public MergeWorldDialog(Window parent, World2 world, ColourScheme colourScheme, CustomBiomeManager customBiomeManager, Set hiddenLayers, boolean contourLines, int contourSeparation, TileRenderer.LightOrigin lightOrigin, WorldPainter view) { @@ -90,9 +92,9 @@ public class MergeWorldDialog extends WorldPainterDialog { checkBoxNether.setSelected(world.getDimensionsToExport().contains(DIM_NETHER)); checkBoxEnd.setSelected(world.getDimensionsToExport().contains(DIM_END)); } else { - checkBoxSurface.setSelected(world.getDimension(DIM_NORMAL) != null); - checkBoxNether.setSelected(world.getDimension(DIM_NETHER) != null); - checkBoxEnd.setSelected(world.getDimension(DIM_END) != null); + checkBoxSurface.setSelected(world.getDimension(NORMAL_DETAIL) != null); + checkBoxNether.setSelected(world.getDimension(NETHER_DETAIL) != null); + checkBoxEnd.setSelected(world.getDimension(END_DETAIL) != null); } world.getAttribute(ATTRIBUTE_MERGE_SETTINGS).ifPresent(mergeSettings -> { if (mergeSettings.replaceChunks) { @@ -183,7 +185,7 @@ public class MergeWorldDialog extends WorldPainterDialog { } boolean allDimensionsSelected = true; for (Dimension dimension: world.getDimensions()) { - if (! dimensionsToExport.contains(dimension.getDim())) { + if (! dimensionsToExport.contains(dimension.getAnchor().dim)) { allDimensionsSelected = false; break; } @@ -333,10 +335,10 @@ public class MergeWorldDialog extends WorldPainterDialog { private void setControlStates() { final boolean mergeAll = radioButtonAll.isSelected(); final boolean mergeEverything = radioButtonExportEverything.isSelected(); - final boolean surfacePresent = world.getDimension(DIM_NORMAL) != null; - final boolean netherPresent = world.getDimension(DIM_NETHER) != null; - final boolean endPresent = world.getDimension(DIM_END) != null; - final boolean oneDimensionPresent = world.getDimensions().length == 1; + final boolean surfacePresent = world.getDimension(NORMAL_DETAIL) != null; + final boolean netherPresent = world.getDimension(NETHER_DETAIL) != null; + final boolean endPresent = world.getDimension(END_DETAIL) != null; + final boolean oneDimensionPresent = world.getDimensions().size() == 1; boolean biomesSupported = false, threeDeeBiomesSupported = false; final File mapDir = new File(fieldSelectedMapDir.getText().trim()); if (mapDir.isDirectory()) { @@ -446,7 +448,6 @@ public class MergeWorldDialog extends WorldPainterDialog { * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ - @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog.java index 25fb36d0..d4f5ccac 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog.java @@ -17,6 +17,7 @@ import org.pepsoft.minecraft.SeededGenerator; import org.pepsoft.util.MathUtils; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.mdc.MDCThreadPoolExecutor; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.Dimension.Border; import org.pepsoft.worldpainter.biomeschemes.Minecraft1_2BiomeScheme; import org.pepsoft.worldpainter.history.HistoryEntry; @@ -58,16 +59,16 @@ import static org.pepsoft.worldpainter.util.MinecraftUtil.blocksToWalkingTime; */ public class NewWorldDialog extends WorldPainterDialog { /** Creates new form NewWorldDialog */ - public NewWorldDialog(App app, ColourScheme colourScheme, String name, long seed, Platform platform, int dim, int defaultMaxHeight, Dimension baseDimension) { - this(app, colourScheme, name, seed, platform, dim, defaultMaxHeight, baseDimension, null); + public NewWorldDialog(App app, ColourScheme colourScheme, String name, long seed, Platform platform, Anchor anchor, int defaultMaxHeight, Dimension baseDimension) { + this(app, colourScheme, name, seed, platform, anchor, defaultMaxHeight, baseDimension, null); } /** Creates new form NewWorldDialog */ - public NewWorldDialog(App app, ColourScheme colourScheme, String name, long seed, Platform platform, int dim, int defaultMaxHeight, Dimension baseDimension, Set tiles) { + public NewWorldDialog(App app, ColourScheme colourScheme, String name, long seed, Platform platform, Anchor anchor, int defaultMaxHeight, Dimension baseDimension, Set tiles) { super(app); this.app = app; this.colourScheme = colourScheme; - this.dim = dim; + this.anchor = anchor; this.tiles = tiles; this.baseDimension = baseDimension; @@ -93,7 +94,7 @@ public class NewWorldDialog extends WorldPainterDialog { comboBoxMaxHeight.setSelectedItem(defaultMaxHeight); Configuration config = Configuration.getInstance(); - if (dim == DIM_NORMAL) { + if ((anchor.dim == DIM_NORMAL) && (! anchor.invert)) { if (! config.isHilly()) { radioButtonFlat.setSelected(true); spinnerRange.setEnabled(false); @@ -115,7 +116,7 @@ public class NewWorldDialog extends WorldPainterDialog { ((DefaultEditor) spinnerWidth.getEditor()).getTextField().setColumns(4); ((DefaultEditor) spinnerLength.getEditor()).getTextField().setColumns(4); - if (dim == DIM_NORMAL_CEILING) { + if ((anchor.dim == DIM_NORMAL) && anchor.invert) { setTitle("Add Surface Ceiling"); fieldName.setEnabled(false); comboBoxTarget.setEnabled(false); @@ -124,41 +125,40 @@ public class NewWorldDialog extends WorldPainterDialog { spinnerWaterLevel.setValue(0); checkBoxBeaches.setSelected(false); comboBoxMaxHeight.setEnabled(false); - } else if (dim == DIM_NETHER) { - setTitle("Add Nether"); - fieldName.setEnabled(false); - comboBoxTarget.setEnabled(false); - comboBoxSurfaceMaterial.setSelectedItem(NETHERLIKE); - int lavaLevel = defaultMaxHeight * 3 / 4; - spinnerTerrainLevel.setValue(lavaLevel - 4); - spinnerWaterLevel.setValue(lavaLevel); - checkBoxLava.setSelected(true); + } else if (anchor.dim == DIM_NETHER) { + if (! anchor.invert) { + setTitle("Add Nether"); + fieldName.setEnabled(false); + comboBoxTarget.setEnabled(false); + comboBoxSurfaceMaterial.setSelectedItem(NETHERLIKE); + int lavaLevel = defaultMaxHeight * 3 / 4; + spinnerTerrainLevel.setValue(lavaLevel - 4); + spinnerWaterLevel.setValue(lavaLevel); + checkBoxLava.setSelected(true); + } else { + setTitle("Add Nether Ceiling"); + fieldName.setEnabled(false); + comboBoxTarget.setEnabled(false); + comboBoxSurfaceMaterial.setSelectedItem(NETHERLIKE); + spinnerTerrainLevel.setValue(58); + spinnerWaterLevel.setValue(0); + } checkBoxBeaches.setSelected(false); comboBoxMaxHeight.setEnabled(false); - } else if (dim == DIM_NETHER_CEILING) { - setTitle("Add Nether Ceiling"); - fieldName.setEnabled(false); - comboBoxTarget.setEnabled(false); - comboBoxSurfaceMaterial.setSelectedItem(NETHERLIKE); - spinnerTerrainLevel.setValue(58); - spinnerWaterLevel.setValue(0); - checkBoxBeaches.setSelected(false); - comboBoxMaxHeight.setEnabled(false); - } else if (dim == DIM_END) { - setTitle("Add End"); - fieldName.setEnabled(false); - comboBoxTarget.setEnabled(false); - comboBoxSurfaceMaterial.setSelectedItem(END_STONE); - spinnerTerrainLevel.setValue(32); - spinnerWaterLevel.setValue(0); - checkBoxBeaches.setSelected(false); - comboBoxMaxHeight.setEnabled(false); - } else if (dim == DIM_END_CEILING) { - setTitle("Add End Ceiling"); - fieldName.setEnabled(false); - comboBoxTarget.setEnabled(false); - comboBoxSurfaceMaterial.setSelectedItem(END_STONE); - spinnerTerrainLevel.setValue(58); + } else if (anchor.dim == DIM_END) { + if (! anchor.invert) { + setTitle("Add End"); + fieldName.setEnabled(false); + comboBoxTarget.setEnabled(false); + comboBoxSurfaceMaterial.setSelectedItem(END_STONE); + spinnerTerrainLevel.setValue(32); + } else { + setTitle("Add End Ceiling"); + fieldName.setEnabled(false); + comboBoxTarget.setEnabled(false); + comboBoxSurfaceMaterial.setSelectedItem(END_STONE); + spinnerTerrainLevel.setValue(58); + } spinnerWaterLevel.setValue(0); checkBoxBeaches.setSelected(false); comboBoxMaxHeight.setEnabled(false); @@ -316,7 +316,7 @@ public class NewWorldDialog extends WorldPainterDialog { } if (mostCenteredTileCoords != null) { world.setSpawnPoint(new Point(mostCenteredTileCoords.x * TILE_SIZE + TILE_SIZE / 2, mostCenteredTileCoords.y * TILE_SIZE + TILE_SIZE / 2)); - if (dimension.getDim() == DIM_NORMAL) { + if (dimension.getAnchor().dim == DIM_NORMAL) { dimension.setLastViewPosition(world.getSpawnPoint()); } } @@ -345,7 +345,7 @@ public class NewWorldDialog extends WorldPainterDialog { final TileFactory tileFactory = createTileFactory(worldpainterSeed); final Dimension dimension; - dimension = new Dimension(world, minecraftSeed, tileFactory, dim); + dimension = new Dimension(world, minecraftSeed, tileFactory, anchor); dimension.setEventsInhibited(true); try { ExecutorService executorService = MDCThreadPoolExecutor.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); @@ -477,7 +477,7 @@ public class NewWorldDialog extends WorldPainterDialog { } final ResourcesExporterSettings resourcesSettings = (ResourcesExporterSettings) dimension.getLayerSettings(Resources.INSTANCE); - if (dim < 0) { + if (anchor.invert) { // Ceiling dimension; invert min and max levels: final int maxZ = dimension.getMaxHeight() + dimension.getMinHeight() - 1; for (Material material: resourcesSettings.getMaterials()) { @@ -486,24 +486,26 @@ public class NewWorldDialog extends WorldPainterDialog { resourcesSettings.setMaxLevel(material, maxZ - oldMinLevel); } } - if (dim == DIM_NETHER) { - dimension.setSubsurfaceMaterial(NETHERLIKE); + if (anchor.dim == DIM_NETHER) { + if (! anchor.invert) { + dimension.setSubsurfaceMaterial(NETHERLIKE); - final CavernsSettings cavernsSettings = new CavernsSettings(); - cavernsSettings.setCavernsEverywhereLevel(16); - cavernsSettings.setSurfaceBreaking(true); - cavernsSettings.setFloodWithLava(true); - cavernsSettings.setWaterLevel(16); - dimension.setLayerSettings(Caverns.INSTANCE, cavernsSettings); - } else if (dim == DIM_NETHER_CEILING) { - dimension.setSubsurfaceMaterial(NETHERLIKE); - } else if ((dim == DIM_END) || (dim == DIM_END_CEILING)) { + final CavernsSettings cavernsSettings = new CavernsSettings(); + cavernsSettings.setCavernsEverywhereLevel(16); + cavernsSettings.setSurfaceBreaking(true); + cavernsSettings.setFloodWithLava(true); + cavernsSettings.setWaterLevel(16); + dimension.setLayerSettings(Caverns.INSTANCE, cavernsSettings); + } else { + dimension.setSubsurfaceMaterial(NETHERLIKE); + } + } else if (anchor.dim == DIM_END) { dimension.setSubsurfaceMaterial(END_STONE); } final Configuration config = Configuration.getInstance(); final Dimension defaults = config.getDefaultTerrainAndLayerSettings(); - if (dim == DIM_NORMAL) { + if ((anchor.dim == DIM_NORMAL) && (! anchor.invert)) { if (! checkBoxCircular.isSelected()) { dimension.setBorder(defaults.getBorder()); dimension.setBorderSize(defaults.getBorderSize()); @@ -546,7 +548,7 @@ public class NewWorldDialog extends WorldPainterDialog { } private void setControlStates() { - boolean surfaceDimension = dim == DIM_NORMAL; + boolean surfaceDimension = (anchor.dim == DIM_NORMAL) && (! anchor.invert); checkBoxExtendedBlockIds.setEnabled(platform.capabilities.contains(BLOCK_BASED) && (! platform.capabilities.contains(NAME_BASED)) && (platform != JAVA_MCREGION)); boolean hilly = radioButtonHilly.isSelected(); spinnerRange.setEnabled(hilly); @@ -607,7 +609,7 @@ public class NewWorldDialog extends WorldPainterDialog { private final Map cache = new HashMap<>(); }; Configuration config = Configuration.getInstance(); - tiledImageViewer1.setTileProvider(new WPTileProvider(tileProvider, colourScheme, app.getCustomBiomeManager(), Collections.singleton(Biome.INSTANCE), config.isDefaultContoursEnabled(), config.getDefaultContourSeparation(), config.getDefaultLightOrigin(), false, null)); + tiledImageViewer1.setTileProvider(new WPTileProvider(tileProvider, colourScheme, app.getCustomBiomeManager(), Collections.singleton(Biome.INSTANCE), config.isDefaultContoursEnabled(), config.getDefaultContourSeparation(), config.getDefaultLightOrigin(), false)); } private TileFactory createTileFactory(long seed) { @@ -620,14 +622,12 @@ public class NewWorldDialog extends WorldPainterDialog { final boolean beaches = checkBoxBeaches.isSelected(); final int minHeight; int maxHeight = (Integer) comboBoxMaxHeight.getSelectedItem(); - switch (dim) { + switch (anchor.dim) { case DIM_NETHER: - case DIM_NETHER_CEILING: minHeight = Math.max(platform.minZ, 0); maxHeight = Math.min(maxHeight, DEFAULT_MAX_HEIGHT_NETHER); break; case DIM_END: - case DIM_END_CEILING: minHeight = Math.max(platform.minZ, 0); maxHeight = Math.min(maxHeight, DEFAULT_MAX_HEIGHT_END); break; @@ -653,7 +653,7 @@ public class NewWorldDialog extends WorldPainterDialog { } Configuration config = Configuration.getInstance(); Dimension defaults = config.getDefaultTerrainAndLayerSettings(); - if ((dim == DIM_NORMAL) + if ((anchor.dim == DIM_NORMAL) && (! anchor.invert) && (defaults.getTileFactory() instanceof HeightMapTileFactory) && (((HeightMapTileFactory) defaults.getTileFactory()).getTheme() instanceof SimpleTheme) && (((SimpleTheme) ((HeightMapTileFactory) defaults.getTileFactory()).getTheme()).getTerrainRanges() != null) @@ -667,7 +667,7 @@ public class NewWorldDialog extends WorldPainterDialog { final SimpleTheme theme = (SimpleTheme) tileFactory.getTheme(); theme.setTerrainRanges(terrainRanges); theme.setRandomise(defaultTheme.isRandomise()); - } else if ((dim != DIM_NORMAL) && radioButtonSimpleTerrain.isSelected()) { + } else if (((anchor.dim != DIM_NORMAL) || anchor.invert) && radioButtonSimpleTerrain.isSelected()) { // Override the default terrain map: SortedMap terrainMap = new TreeMap<>(); terrainMap.put(-1, terrain); @@ -1535,8 +1535,9 @@ public class NewWorldDialog extends WorldPainterDialog { private final Set tiles; private final ColourScheme colourScheme; private final Dimension baseDimension; + private final Anchor anchor; private Platform platform; - private int previousExp = -1, dim, savedTerrainLevel; + private int previousExp = -1, savedTerrainLevel; private long worldpainterSeed; private SimpleTheme theme; private boolean programmaticChange = true; diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog2.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog2.java index a01b6f2a..65d5f037 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog2.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/NewWorldDialog2.java @@ -59,7 +59,7 @@ public class NewWorldDialog2 extends javax.swing.JDialog { private final Map cache = new HashMap<>(); }; Configuration config = Configuration.getInstance(); - tiledImageViewer1.setTileProvider(new WPTileProvider(tileProvider, ColourScheme.DEFAULT, app.getCustomBiomeManager(), Collections.singleton(Biome.INSTANCE), config.isDefaultContoursEnabled(), config.getDefaultContourSeparation(), config.getDefaultLightOrigin(), false, null)); + tiledImageViewer1.setTileProvider(new WPTileProvider(tileProvider, ColourScheme.DEFAULT, app.getCustomBiomeManager(), Collections.singleton(Biome.INSTANCE), config.isDefaultContoursEnabled(), config.getDefaultContourSeparation(), config.getDefaultLightOrigin(), false)); } private TileFactory createTileFactory() { diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/PreferencesDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/PreferencesDialog.java index a69a4910..0f200c2d 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/PreferencesDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/PreferencesDialog.java @@ -42,8 +42,8 @@ import static java.util.Arrays.asList; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.DefaultPlugin.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.*; import static org.pepsoft.worldpainter.HeightTransform.IDENTITY; import static org.pepsoft.worldpainter.Platform.Capability.BLOCK_BASED; @@ -1715,7 +1715,7 @@ public class PreferencesDialog extends WorldPainterDialog { checkBoxBeaches.setSelected(true); comboBoxSurfaceMaterial.setSelectedItem(GRASS); checkBoxResourcesEverywhere.setSelected(true); - defaultTerrainAndLayerSettings = new World2(defaultPlatform, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), GRASS, defaultPlatform.minZ, defaultPlatform.standardMaxHeight, 58, DEFAULT_WATER_LEVEL, false, true, 20, 1.0)).getDimension(DIM_NORMAL); + defaultTerrainAndLayerSettings = new World2(defaultPlatform, World2.DEFAULT_OCEAN_SEED, TileFactoryFactory.createNoiseTileFactory(new Random().nextLong(), GRASS, defaultPlatform.minZ, defaultPlatform.standardMaxHeight, 58, DEFAULT_WATER_LEVEL, false, true, 20, 1.0)).getDimension(NORMAL_DETAIL); config.setDefaultTerrainAndLayerSettings(defaultTerrainAndLayerSettings); defaultExportSettings = null; } diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/RotateWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/RotateWorldDialog.java index b0943bc1..4f96ad7f 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/RotateWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/RotateWorldDialog.java @@ -12,12 +12,12 @@ package org.pepsoft.worldpainter; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.SubProgressReceiver; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.history.HistoryEntry; import java.awt.*; import static org.pepsoft.util.AwtUtils.doOnEventThread; -import static org.pepsoft.worldpainter.Constants.*; /** * @@ -25,39 +25,19 @@ import static org.pepsoft.worldpainter.Constants.*; */ public class RotateWorldDialog extends WorldPainterDialog implements ProgressReceiver { /** Creates new form RotateWorldDialog */ - public RotateWorldDialog(Window parent, World2 world, int dim) { + public RotateWorldDialog(Window parent, World2 world, Anchor anchor) { super(parent); this.world = world; - this.dim = dim; - Dimension opposite = null; - switch (dim) { - case DIM_NORMAL: - opposite = world.getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - opposite = world.getDimension(DIM_NORMAL); - break; - case DIM_END: - opposite = world.getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - opposite = world.getDimension(DIM_END); - break; - case DIM_NETHER: - opposite = world.getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - opposite = world.getDimension(DIM_NETHER); - break; - } + this.anchor = anchor; + final Dimension opposite = world.getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); if (opposite != null) { - oppositeDim = opposite.getDim(); + oppositeAnchor = opposite.getAnchor(); } else { - oppositeDim = Integer.MIN_VALUE; + oppositeAnchor = null; } initComponents(); - jCheckBox1.setEnabled(oppositeDim != Integer.MIN_VALUE); + jCheckBox1.setEnabled(oppositeAnchor != null); getRootPane().setDefaultButton(buttonRotate); @@ -126,14 +106,14 @@ public class RotateWorldDialog extends WorldPainterDialog implements ProgressRec @Override public void run() { try { - if ((oppositeDim == Integer.MIN_VALUE) || (! jCheckBox1.isSelected())) { - world.transform(dim, transform, RotateWorldDialog.this); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(dim).getName(), degrees); + if ((oppositeAnchor == null) || (! jCheckBox1.isSelected())) { + world.transform(anchor, transform, RotateWorldDialog.this); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(anchor).getName(), degrees); } else { - world.transform(dim, transform, new SubProgressReceiver(RotateWorldDialog.this, 0.0f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(dim).getName(), degrees); - world.transform(oppositeDim, transform, new SubProgressReceiver(RotateWorldDialog.this, 0.5f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(oppositeDim).getName(), degrees); + world.transform(anchor, transform, new SubProgressReceiver(RotateWorldDialog.this, 0.0f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(anchor).getName(), degrees); + world.transform(oppositeAnchor, transform, new SubProgressReceiver(RotateWorldDialog.this, 0.5f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_ROTATED, world.getDimension(oppositeAnchor).getName(), degrees); } done(); } catch (Throwable t) { @@ -269,7 +249,7 @@ public class RotateWorldDialog extends WorldPainterDialog implements ProgressRec // End of variables declaration//GEN-END:variables private final World2 world; - private final int dim, oppositeDim; + private final Anchor anchor, oppositeAnchor; private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ScaleWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ScaleWorldDialog.java index b18ebf04..d38464f1 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ScaleWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ScaleWorldDialog.java @@ -9,6 +9,7 @@ import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.SubProgressReceiver; import org.pepsoft.util.swing.ProgressDialog; import org.pepsoft.util.swing.ProgressTask; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.history.HistoryEntry; import javax.swing.*; @@ -18,7 +19,7 @@ import static java.lang.String.format; import static javax.swing.JOptionPane.OK_OPTION; import static javax.swing.JOptionPane.YES_NO_OPTION; import static org.pepsoft.util.swing.ProgressDialog.NOT_CANCELABLE; -import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Constants.TILE_SIZE; import static org.pepsoft.worldpainter.util.MinecraftUtil.blocksToWalkingTime; /** @@ -30,40 +31,20 @@ public class ScaleWorldDialog extends WorldPainterDialog { /** * Creates new form ScaleWorldDialog */ - public ScaleWorldDialog(Window parent, World2 world, int dim) { + public ScaleWorldDialog(Window parent, World2 world, Anchor anchor) { super(parent); this.world = world; - this.dim = dim; - final Dimension dimension = world.getDimension(dim); - Dimension opposite = null; - switch (dim) { - case DIM_NORMAL: - opposite = world.getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - opposite = world.getDimension(DIM_NORMAL); - break; - case DIM_END: - opposite = world.getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - opposite = world.getDimension(DIM_END); - break; - case DIM_NETHER: - opposite = world.getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - opposite = world.getDimension(DIM_NETHER); - break; - } + this.anchor = anchor; + final Dimension dimension = world.getDimension(anchor); + final Dimension opposite = world.getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); if (opposite != null) { - oppositeDim = opposite.getDim(); + oppositeAnchor = opposite.getAnchor(); } else { - oppositeDim = Integer.MIN_VALUE; + oppositeAnchor = null; } initComponents(); - checkBoxIncludeCeiling.setEnabled(oppositeDim != Integer.MIN_VALUE); + checkBoxIncludeCeiling.setEnabled(oppositeAnchor != null); final int width = dimension.getWidth() * TILE_SIZE, height = dimension.getHeight() * TILE_SIZE; labelCurrentSize.setText(format("%d x %d blocks", width, height)); labelCurrentWalkingTime.setText(getWalkingTime(width, height)); @@ -92,14 +73,14 @@ public class ScaleWorldDialog extends WorldPainterDialog { @Override public Void execute(ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled { - if ((oppositeDim == Integer.MIN_VALUE) || (! checkBoxIncludeCeiling.isSelected())) { - world.transform(dim, transform, progressReceiver); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(dim).getName(), percentage); + if ((oppositeAnchor == null) || (! checkBoxIncludeCeiling.isSelected())) { + world.transform(anchor, transform, progressReceiver); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(anchor).getName(), percentage); } else { - world.transform(dim, transform, new SubProgressReceiver(progressReceiver, 0.0f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(dim).getName(), percentage); - world.transform(oppositeDim, transform, new SubProgressReceiver(progressReceiver, 0.5f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(oppositeDim).getName(), percentage); + world.transform(anchor, transform, new SubProgressReceiver(progressReceiver, 0.0f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(anchor).getName(), percentage); + world.transform(oppositeAnchor, transform, new SubProgressReceiver(progressReceiver, 0.5f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SCALED, world.getDimension(oppositeAnchor).getName(), percentage); } return null; } @@ -108,7 +89,7 @@ public class ScaleWorldDialog extends WorldPainterDialog { } private void updateNewSize() { - final Dimension dimension = world.getDimension(dim); + final Dimension dimension = world.getDimension(anchor); final float scale = (int) spinnerScaleFactor.getValue() / 100f; final int newWidth = Math.round(dimension.getWidth() * TILE_SIZE * scale), newHeight = Math.round(dimension.getHeight() * TILE_SIZE * scale); labelNewSize.setText(format("%d x %d blocks", newWidth, newHeight)); @@ -336,5 +317,5 @@ public class ScaleWorldDialog extends WorldPainterDialog { // End of variables declaration//GEN-END:variables private final World2 world; - private final int dim, oppositeDim; + private final Anchor anchor, oppositeAnchor; } \ No newline at end of file diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ShiftWorldDialog.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ShiftWorldDialog.java index 0a990c1b..e9f8d45b 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ShiftWorldDialog.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/ShiftWorldDialog.java @@ -12,12 +12,12 @@ package org.pepsoft.worldpainter; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.SubProgressReceiver; +import org.pepsoft.worldpainter.Dimension.Anchor; import org.pepsoft.worldpainter.history.HistoryEntry; import java.awt.*; import static org.pepsoft.util.AwtUtils.doOnEventThread; -import static org.pepsoft.worldpainter.Constants.*; /** * @@ -25,39 +25,19 @@ import static org.pepsoft.worldpainter.Constants.*; */ public class ShiftWorldDialog extends WorldPainterDialog implements ProgressReceiver { /** Creates new form RotateWorldDialog */ - public ShiftWorldDialog(Window parent, World2 world, int dim) { + public ShiftWorldDialog(Window parent, World2 world, Anchor anchor) { super(parent); this.world = world; - this.dim = dim; - Dimension opposite = null; - switch (dim) { - case DIM_NORMAL: - opposite = world.getDimension(DIM_NORMAL_CEILING); - break; - case DIM_NORMAL_CEILING: - opposite = world.getDimension(DIM_NORMAL); - break; - case DIM_END: - opposite = world.getDimension(DIM_END_CEILING); - break; - case DIM_END_CEILING: - opposite = world.getDimension(DIM_END); - break; - case DIM_NETHER: - opposite = world.getDimension(DIM_NETHER_CEILING); - break; - case DIM_NETHER_CEILING: - opposite = world.getDimension(DIM_NETHER); - break; - } + this.anchor = anchor; + final Dimension opposite = world.getDimension(new Anchor(anchor.dim, anchor.role, ! anchor.invert, 0)); if (opposite != null) { - oppositeDim = opposite.getDim(); + oppositeAnchor = opposite.getAnchor(); } else { - oppositeDim = Integer.MIN_VALUE; + oppositeAnchor = null; } initComponents(); - jCheckBox1.setEnabled(oppositeDim != Integer.MIN_VALUE); + jCheckBox1.setEnabled(oppositeAnchor != null); getRootPane().setDefaultButton(buttonShift); @@ -116,14 +96,14 @@ public class ShiftWorldDialog extends WorldPainterDialog implements ProgressRece @Override public void run() { try { - if ((oppositeDim == Integer.MIN_VALUE) || (! jCheckBox1.isSelected())) { - world.transform(dim, transform, ShiftWorldDialog.this); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(dim).getName(), east, south); + if ((oppositeAnchor == null) || (! jCheckBox1.isSelected())) { + world.transform(anchor, transform, ShiftWorldDialog.this); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(anchor).getName(), east, south); } else { - world.transform(dim, transform, new SubProgressReceiver(ShiftWorldDialog.this, 0.0f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(dim).getName(), east, south); - world.transform(oppositeDim, transform, new SubProgressReceiver(ShiftWorldDialog.this, 0.5f, 0.5f)); - world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(oppositeDim).getName(), east, south); + world.transform(anchor, transform, new SubProgressReceiver(ShiftWorldDialog.this, 0.0f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(anchor).getName(), east, south); + world.transform(oppositeAnchor, transform, new SubProgressReceiver(ShiftWorldDialog.this, 0.5f, 0.5f)); + world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_HORIZONTALLY, world.getDimension(oppositeAnchor).getName(), east, south); } done(); } catch (Throwable t) { @@ -306,7 +286,7 @@ public class ShiftWorldDialog extends WorldPainterDialog implements ProgressRece // End of variables declaration//GEN-END:variables private final World2 world; - private final int dim, oppositeDim; + private final Anchor anchor, oppositeAnchor; private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/TileSelector.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/TileSelector.java index 6ead196d..2014c344 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/TileSelector.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/TileSelector.java @@ -222,10 +222,10 @@ public class TileSelector extends javax.swing.JPanel { public void setDimension(Dimension dimension) { this.dimension = dimension; if (dimension != null) { - int biomeAlgorithm = -1; - if ((dimension.getDim() == DIM_NORMAL) && ((dimension.getBorder() == null) || (! dimension.getBorder().isEndless()))) { + if ((dimension.getAnchor().dim == DIM_NORMAL) && ((dimension.getBorder() == null) || (! dimension.getBorder().isEndless()))) { World2 world = dimension.getWorld(); if (world != null) { + int biomeAlgorithm = -1; Platform platform = world.getPlatform(); if (platform == JAVA_MCREGION) { biomeAlgorithm = BIOME_ALGORITHM_1_1; @@ -236,12 +236,17 @@ public class TileSelector extends javax.swing.JPanel { biomeAlgorithm = BIOME_ALGORITHM_1_7_LARGE; } } + if (biomeAlgorithm != -1) { + viewer.setTileProvider(-1, new BiomesTileProvider(biomeAlgorithm, dimension.getMinecraftSeed(), colourScheme, 0, true)); + } } } - WPTileProvider tileProvider = new WPTileProvider(dimension, colourScheme, customBiomeManager, hiddenLayers, contourLines, contourSeparation, lightOrigin, true, (biomeAlgorithm != -1) ? new BiomesTileProvider(biomeAlgorithm, dimension.getMinecraftSeed(), colourScheme, 0, true) : null); + + WPTileProvider tileProvider = new WPTileProvider(dimension, colourScheme, customBiomeManager, hiddenLayers, contourLines, contourSeparation, lightOrigin, true); // tileProvider.setZoom(zoom); viewer.setTileProvider(tileProvider); - viewer.setMarkerCoords(((dimension.getDim() == DIM_NORMAL) || (dimension.getDim() == DIM_NORMAL_CEILING)) ? dimension.getWorld().getSpawnPoint() : null); + + viewer.setMarkerCoords((dimension.getAnchor().dim == DIM_NORMAL) ? dimension.getWorld().getSpawnPoint() : null); buttonSpawn.setEnabled(true); // moveToCentre(); } else { @@ -254,7 +259,7 @@ public class TileSelector extends javax.swing.JPanel { } public void refresh() { - if ((dimension != null) && ((dimension.getDim() == DIM_NORMAL) || (dimension.getDim() == DIM_NORMAL_CEILING))) { + if ((dimension != null) && (dimension.getAnchor().dim == DIM_NORMAL)) { viewer.setMarkerCoords(dimension.getWorld().getSpawnPoint()); } viewer.refresh(); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldFactory.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldFactory.java index 991fac83..c37ebf9e 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldFactory.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldFactory.java @@ -28,6 +28,7 @@ import java.util.TreeMap; import static org.pepsoft.minecraft.Constants.DEFAULT_MAX_HEIGHT_ANVIL; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; import static org.pepsoft.worldpainter.Constants.TILE_SIZE; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES; import static org.pepsoft.worldpainter.World2.DEFAULT_OCEAN_SEED; import static org.pepsoft.worldpainter.util.MathUtils.getLargestDistanceFromOrigin; @@ -53,7 +54,7 @@ public final class WorldFactory { final int radius = config.getDefaultWidth() * 64; // final boolean circularWorld = true; // final int radius = 750; - final Dimension dim0 = world.getDimension(0); + final Dimension dim0 = world.getDimension(NORMAL_DETAIL); final TileFactory tileFactory = dim0.getTileFactory(); dim0.setEventsInhibited(true); try { @@ -145,7 +146,7 @@ public final class WorldFactory { world.setGameType(config.getDefaultGameType()); world.setAllowCheats(config.isDefaultAllowCheats()); - final Dimension dim0 = world.getDimension(0); + final Dimension dim0 = world.getDimension(NORMAL_DETAIL); dim0.setEventsInhibited(true); try { dim0.setBorder(defaults.getBorder()); @@ -185,7 +186,7 @@ public final class WorldFactory { world.setMixedMaterial(1, new MixedMaterial("Stone/Gravel", new Row[] {new Row(Material.STONE, 750, 1.0f), new Row(Material.GRAVEL, 250, 1.0f)}, Minecraft1_2BiomeScheme.BIOME_PLAINS, null, 1.0f)); final ResourceBundle strings = ResourceBundle.getBundle("org.pepsoft.worldpainter.resources.strings"); world.setName(strings.getString("generated.world")); - final Dimension dim0 = world.getDimension(0); + final Dimension dim0 = world.getDimension(NORMAL_DETAIL); if (config.getDefaultMaxHeight() == DEFAULT_MAX_HEIGHT_ANVIL) { dim0.setGenerator(new SeededGenerator(LARGE_BIOMES, DEFAULT_OCEAN_SEED)); } diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldPainter.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldPainter.java index 2ca0287e..e30c3577 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldPainter.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/WorldPainter.java @@ -38,6 +38,7 @@ import static org.pepsoft.worldpainter.Generator.DEFAULT; import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES; import static org.pepsoft.worldpainter.TileRenderer.FLUIDS_AS_LAYER; import static org.pepsoft.worldpainter.TileRenderer.TERRAIN_AS_LAYER; +import static org.pepsoft.worldpainter.WPTileProvider.Effect.FADE_TO_WHITE; /** * @@ -66,14 +67,14 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene @Override public final void setDimension(Dimension dimension) { Dimension oldDimension = this.dimension; - if ((oldDimension != null) && ((oldDimension.getDim() == DIM_NORMAL) || (oldDimension.getDim() == DIM_NORMAL_CEILING))) { + if ((oldDimension != null) && (oldDimension.getAnchor().dim == DIM_NORMAL)) { oldDimension.getWorld().removePropertyChangeListener("spawnPoint", this); } this.dimension = dimension; if (dimension != null) { drawContours = dimension.isContoursEnabled(); contourSeparation = dimension.getContourSeparation(); - if ((dimension.getDim() == DIM_NORMAL) || (dimension.getDim() == DIM_NORMAL_CEILING)) { + if (dimension.getAnchor().dim == DIM_NORMAL) { dimension.getWorld().addPropertyChangeListener("spawnPoint", this); } @@ -90,7 +91,7 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene setOverlayOffsetY(dimension.getOverlayOffsetY()); setOverlay(null); setDrawOverlay(dimension.isOverlayEnabled()); - setMarkerCoords(((dimension.getDim() == DIM_NORMAL) || (dimension.getDim() == DIM_NORMAL_CEILING)) ? dimension.getWorld().getSpawnPoint() : null); + setMarkerCoords((dimension.getAnchor().dim == DIM_NORMAL) ? dimension.getWorld().getSpawnPoint() : null); } else { setOverlay(null); setMarkerCoords(null); @@ -351,12 +352,12 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene public void refreshTiles() { if (dimension != null) { - int biomeAlgorithm = -1; if (drawBiomes - && (dimension.getDim() == DIM_NORMAL) + && (dimension.getAnchor().dim == DIM_NORMAL) && ((dimension.getBorder() == null) || (! dimension.getBorder().isEndless()))) { World2 world = dimension.getWorld(); if (world != null) { + int biomeAlgorithm = -1; Platform platform = world.getPlatform(); if (platform == JAVA_MCREGION) { biomeAlgorithm = BIOME_ALGORITHM_1_1; @@ -367,17 +368,17 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene biomeAlgorithm = BIOME_ALGORITHM_1_7_LARGE; } } + if (biomeAlgorithm != -1) { + setTileProvider(LAYER_BIOMES, new BiomesTileProvider(biomeAlgorithm, dimension.getMinecraftSeed(), colourScheme, 0, true)); + } } } - tileProvider = new WPTileProvider(dimension, colourScheme, customBiomeManager, hiddenLayers, drawContours, contourSeparation, lightOrigin, drawBorders, (biomeAlgorithm != -1) ? new BiomesTileProvider(biomeAlgorithm, dimension.getMinecraftSeed(), colourScheme, 0, true) : null, true); - if (getTileProviderCount() == 0) { - addTileProvider(tileProvider); - } else { - replaceTileProvider(0, tileProvider); - } + + tileProvider = new WPTileProvider(dimension, colourScheme, customBiomeManager, hiddenLayers, drawContours, contourSeparation, lightOrigin, drawBorders, true, null); + setTileProvider(LAYER_DETAILS, tileProvider); } else { if (getTileProviderCount() > 0) { - removeTileProvider(0); + removeAllTileProviders(); } tileProvider = null; } @@ -468,7 +469,7 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene } public void moveToSpawn() { - if ((dimension != null) && (dimension.getDim() == DIM_NORMAL)) { + if ((dimension != null) && (dimension.getAnchor().dim == DIM_NORMAL)) { moveToMarker(); } } @@ -536,7 +537,7 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene public void setDrawBiomes(boolean drawBiomes) { if (drawBiomes != this.drawBiomes) { this.drawBiomes = drawBiomes; - if ((dimension != null) && (dimension.getDim() == DIM_NORMAL)) { + if ((dimension != null) && (dimension.getAnchor().dim == DIM_NORMAL)) { refreshTiles(); } firePropertyChange("drawBiomes", ! drawBiomes, drawBiomes); @@ -915,4 +916,8 @@ public class WorldPainter extends WorldPainterView implements MouseMotionListene private static final Font NORMAL_FONT = new Font("SansSerif", Font.PLAIN, 10); private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(WorldPainter.class); private static final long serialVersionUID = 1L; + + private static final int LAYER_BIOMES = -2; + private static final int LAYER_MASTER = -1; + private static final int LAYER_DETAILS = 0; } \ No newline at end of file diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/layers/LayerPreviewCreator.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/layers/LayerPreviewCreator.java index 7664d1d7..fafb0a8c 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/layers/LayerPreviewCreator.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/layers/LayerPreviewCreator.java @@ -33,8 +33,8 @@ import java.util.List; import java.util.*; import static org.pepsoft.minecraft.Constants.DEFAULT_WATER_LEVEL; -import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_ANVIL_1_17; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; /** * A utility class for generating previews of layers. It renders a layer to a @@ -52,7 +52,7 @@ public class LayerPreviewCreator { final TileFactory tileFactory = subterranean ? TileFactoryFactory.createNoiseTileFactory(seed, Terrain.BARE_GRASS, JAVA_ANVIL_1_17.minZ, previewHeight, 56, DEFAULT_WATER_LEVEL, false, true, 20f, 0.5) : TileFactoryFactory.createNoiseTileFactory(seed, Terrain.BARE_GRASS, JAVA_ANVIL_1_17.minZ, previewHeight, 8, 14, false, true, 20f, 0.5); - final Dimension dimension = new World2(DefaultPlugin.JAVA_MCREGION, seed, tileFactory).getDimension(DIM_NORMAL); + final Dimension dimension = new World2(DefaultPlugin.JAVA_MCREGION, seed, tileFactory).getDimension(NORMAL_DETAIL); dimension.setSubsurfaceMaterial(Terrain.STONE); final MinecraftWorldObject minecraftWorldObject = new MinecraftWorldObject(layer.getName() + " Preview", new Box(-8, 136, -8, 136, 0, previewHeight), previewHeight, null, new Point3i(-64, -64, 0)); long now = System.currentTimeMillis(); @@ -291,7 +291,7 @@ public class LayerPreviewCreator { } Configuration.setInstance(config); WPPluginManager.initialise(config.getUuid()); - Dimension dimension = WorldFactory.createDefaultWorldWithoutTiles(config, 0L).getDimension(DIM_NORMAL); + Dimension dimension = WorldFactory.createDefaultWorldWithoutTiles(config, 0L).getDimension(NORMAL_DETAIL); for (Layer layer: LayerManager.getInstance().getLayers()) { // Layer layer = Caverns.INSTANCE; diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/operations/SetSpawnPoint.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/operations/SetSpawnPoint.java index 42adffc9..d11da0e8 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/operations/SetSpawnPoint.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/operations/SetSpawnPoint.java @@ -4,7 +4,6 @@ */ package org.pepsoft.worldpainter.operations; -import org.pepsoft.worldpainter.Constants; import org.pepsoft.worldpainter.Dimension; import org.pepsoft.worldpainter.World2; import org.pepsoft.worldpainter.WorldPainter; @@ -12,6 +11,8 @@ import org.pepsoft.worldpainter.WorldPainter; import javax.swing.*; import java.awt.*; +import static org.pepsoft.worldpainter.Constants.DIM_NORMAL; + /** * * @author pepijn @@ -25,8 +26,8 @@ public class SetSpawnPoint extends MouseOrTabletOperation { protected void tick(int centreX, int centreY, boolean inverse, boolean first, float dynamicLevel) { if (first) { Dimension dimension = getDimension(); - if ((dimension.getDim() != Constants.DIM_NORMAL) && (dimension.getDim() != Constants.DIM_NORMAL_CEILING)) { - throw new IllegalArgumentException("Cannot set spawn point on dimensions other than 0"); + if (dimension.getAnchor().dim != DIM_NORMAL) { + throw new IllegalArgumentException("Cannot set spawn point on dimensions other than DIM_NORMAL"); } World2 world = dimension.getWorld(); int spawnHeight = dimension.getIntHeightAt(centreX, centreY); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeFrame.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeFrame.java index 6820acfb..afbf817a 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeFrame.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeFrame.java @@ -156,8 +156,8 @@ public class ThreeDeeFrame extends JFrame implements WindowListener { if (dimension != null) { threeDeeView = new ThreeDeeView(dimension, colourScheme, customBiomeManager, rotation, zoom); scrollPane.setViewportView(threeDeeView); - MOVE_TO_SPAWN_ACTION.setEnabled(dimension.getDim() == DIM_NORMAL); - glassPane.setRotation(DIRECTIONS[rotation], dimension.getDim() < 0); + MOVE_TO_SPAWN_ACTION.setEnabled(dimension.getAnchor().dim == DIM_NORMAL); + glassPane.setRotation(DIRECTIONS[rotation], dimension.getAnchor().invert); } } @@ -202,7 +202,7 @@ public class ThreeDeeFrame extends JFrame implements WindowListener { scrollPane.setViewportView(threeDeeView); // scrollPane.getViewport().setViewPosition(new Point((threeDeeView.getWidth() - scrollPane.getWidth()) / 2, (threeDeeView.getHeight() - scrollPane.getHeight()) / 2)); threeDeeView.moveToTile(centreMostTile); - glassPane.setRotation(DIRECTIONS[rotation], dimension.getDim() < 0); + glassPane.setRotation(DIRECTIONS[rotation], dimension.getAnchor().invert); } private static final long serialVersionUID = 1L; @@ -224,7 +224,7 @@ public class ThreeDeeFrame extends JFrame implements WindowListener { scrollPane.setViewportView(threeDeeView); // scrollPane.getViewport().setViewPosition(new Point((threeDeeView.getWidth() - scrollPane.getWidth()) / 2, (threeDeeView.getHeight() - scrollPane.getHeight()) / 2)); threeDeeView.moveToTile(centreMostTile); - glassPane.setRotation(DIRECTIONS[rotation], dimension.getDim() < 0); + glassPane.setRotation(DIRECTIONS[rotation], dimension.getAnchor().invert); } private static final long serialVersionUID = 1L; @@ -251,7 +251,7 @@ public class ThreeDeeFrame extends JFrame implements WindowListener { } sb.append(')'); final String description = sb.toString(); - String defaultname = dimension.getWorld().getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getDim() == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + "_3d.png"; + String defaultname = dimension.getWorld().getName().replaceAll("\\s", "").toLowerCase() + ((dimension.getAnchor().dim == DIM_NORMAL) ? "" : ("_" + dimension.getName().toLowerCase())) + "_3d.png"; File selectedFile = FileUtils.selectFileForSave(ThreeDeeFrame.this, "Export as image file", new File(defaultname), new FileFilter() { @Override public boolean accept(File f) { @@ -319,7 +319,7 @@ public class ThreeDeeFrame extends JFrame implements WindowListener { @Override public void performAction(ActionEvent e) { - if (dimension.getDim() == DIM_NORMAL) { + if (dimension.getAnchor().dim == DIM_NORMAL) { Point spawn = dimension.getWorld().getSpawnPoint(); threeDeeView.moveTo(spawn.x, spawn.y); } diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeView.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeView.java index db1ae443..fbd4d1e3 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeView.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/threedeeview/ThreeDeeView.java @@ -48,7 +48,7 @@ public class ThreeDeeView extends JComponent implements Dimension.Listener, Tile } else { waterLevel = DEFAULT_WATER_LEVEL; } - upsideDown = dimension.getDim() < 0; // Ceiling dimension + upsideDown = dimension.getAnchor().invert; // Ceiling dimension zSortedTiles = new TreeMap<>(); for (Tile tile: dimension.getTiles()) { final Rectangle tileBaseBounds = getTileBounds(tile.getX(), tile.getY(), 0, 0, 0); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/BiomesViewerFrame.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/BiomesViewerFrame.java index a2cc48be..1aabeef8 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/BiomesViewerFrame.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/BiomesViewerFrame.java @@ -28,6 +28,7 @@ import java.util.List; import static org.pepsoft.util.GUIUtils.scaleToUI; import static org.pepsoft.worldpainter.Constants.*; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; import static org.pepsoft.worldpainter.Generator.DEFAULT; import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES; @@ -269,7 +270,7 @@ public class BiomesViewerFrame extends JFrame { "Generated World", ((Number) seedSpinner.getValue()).longValue(), ((Integer) schemeChooser.getSelectedItem() == BIOME_ALGORITHM_1_1) ? DefaultPlugin.JAVA_MCREGION : DefaultPlugin.JAVA_ANVIL, - DIM_NORMAL, + NORMAL_DETAIL, Configuration.getInstance().getDefaultMaxHeight(), null, imageViewer.getSelectedTiles()); @@ -291,7 +292,7 @@ public class BiomesViewerFrame extends JFrame { } }); if (newWorld != null) { - final Dimension dimension = newWorld.getDimension(DIM_NORMAL); + final Dimension dimension = newWorld.getDimension(NORMAL_DETAIL); switch ((Integer) schemeChooser.getSelectedItem()) { case BIOME_ALGORITHM_1_1: case BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT: diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/DumpWorld.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/DumpWorld.java index 1d69e7f5..b5b5b9dd 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/DumpWorld.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/DumpWorld.java @@ -57,7 +57,7 @@ public class DumpWorld { } private static void dumpDimension(Dimension dimension) { - System.out.println("Dimension: " + dimension.getName() + " (index: " + dimension.getDim() + ")"); + System.out.println("Dimension: " + dimension.getName() + " (index: " + dimension.getAnchor().dim + ")"); System.out.println(" Size: " + dimension.getWidth() + "x" + dimension.getHeight() + " tiles"); System.out.println(" Westernmost tile: " + dimension.getLowestX() + "; easternmost tile: " + dimension.getHighestX()); System.out.println(" Northernmost tile: " + dimension.getLowestY() + "; southernmost tile: " + dimension.getHighestY()); @@ -89,7 +89,7 @@ public class DumpWorld { } else { System.out.println(" Border: none"); } - if ((dimension.getDim() == Constants.DIM_NORMAL_CEILING) || (dimension.getDim() == Constants.DIM_NETHER_CEILING) || (dimension.getDim() == Constants.DIM_END_CEILING)) { + if (dimension.getAnchor().invert) { System.out.println(" Ceiling height: " + dimension.getCeilingHeight()); } System.out.println(" Max height: " + dimension.getMaxHeight()); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/HeightMapEditor.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/HeightMapEditor.java index 14410543..3b03e65d 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/HeightMapEditor.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/HeightMapEditor.java @@ -348,11 +348,7 @@ public class HeightMapEditor extends javax.swing.JFrame implements HeightMapProp private void installHeightMap(boolean updateTreeModel) { switch (viewMode) { case HEIGHT_MAP: - if (tiledImageViewer1.getTileProviderCount() == 0) { - tiledImageViewer1.setTileProvider(new HeightMapTileProvider(focusHeightMap)); - } else { - tiledImageViewer1.replaceTileProvider(0, new HeightMapTileProvider(focusHeightMap)); - } + tiledImageViewer1.setTileProvider(new HeightMapTileProvider(focusHeightMap)); tiledImageViewer1.setGridColour(Color.GRAY); break; case TERRAIN: @@ -401,11 +397,7 @@ public class HeightMapEditor extends javax.swing.JFrame implements HeightMapProp return tile; } }; - if (tiledImageViewer1.getTileProviderCount() == 0) { - tiledImageViewer1.setTileProvider(0, new WPTileProvider(tileProvider, ColourScheme.DEFAULT, null, Collections.singleton(Biome.INSTANCE), false, 10, TileRenderer.LightOrigin.NORTHWEST, false, null)); - } else { - tiledImageViewer1.replaceTileProvider(0, new WPTileProvider(tileProvider, ColourScheme.DEFAULT, null, Collections.singleton(Biome.INSTANCE), false, 10, TileRenderer.LightOrigin.NORTHWEST, false, null)); - } + tiledImageViewer1.setTileProvider(new WPTileProvider(tileProvider, ColourScheme.DEFAULT, null, Collections.singleton(Biome.INSTANCE), false, 10, TileRenderer.LightOrigin.NORTHWEST, false)); tiledImageViewer1.setGridColour(Color.BLACK); break; } diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/TileFactoryPreviewer.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/TileFactoryPreviewer.java index ea0abf19..8955baa6 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/TileFactoryPreviewer.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/TileFactoryPreviewer.java @@ -98,7 +98,7 @@ public class TileFactoryPreviewer { Terrain.setCustomMaterial(1, new MixedMaterial("Stone/Gravel", new Row[] {new Row(Material.STONE, 750, 1.0f), new Row(Material.GRAVEL, 250, 1.0f)}, Minecraft1_2BiomeScheme.BIOME_PLAINS, null, 1.0f)); TiledImageViewer viewer = new TiledImageViewer(); JFrame frame = new JFrame("TileFactory Previewer"); - viewer.setTileProvider(new WPTileProvider(tileProvider, ColourScheme.DEFAULT, null, Collections.singleton(Biome.INSTANCE), true, 10, TileRenderer.LightOrigin.NORTHWEST, false, null)); + viewer.setTileProvider(new WPTileProvider(tileProvider, ColourScheme.DEFAULT, null, Collections.singleton(Biome.INSTANCE), true, 10, TileRenderer.LightOrigin.NORTHWEST, false)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(viewer, BorderLayout.CENTER); frame.setSize(1000, 800); diff --git a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/WorldMorph.java b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/WorldMorph.java index cf925b47..bae50375 100644 --- a/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/WorldMorph.java +++ b/WorldPainter/WPGUI/src/main/java/org/pepsoft/worldpainter/tools/WorldMorph.java @@ -12,6 +12,7 @@ import javax.swing.*; import java.awt.*; import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; +import static org.pepsoft.worldpainter.Dimension.Anchor.NORMAL_DETAIL; /** * @@ -20,14 +21,14 @@ import static org.pepsoft.worldpainter.DefaultPlugin.JAVA_MCREGION; public class WorldMorph { public static void main(String[] args) { SwingUtilities.invokeLater(() -> { - final WorldPainter view = new WorldPainter(createNewWorld().getDimension(0), ColourScheme.DEFAULT, null); + final WorldPainter view = new WorldPainter(createNewWorld().getDimension(NORMAL_DETAIL), ColourScheme.DEFAULT, null); JFrame frame = new JFrame("WorldMorph"); frame.getContentPane().add(view, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); - Timer timer = new Timer(2000, e -> view.setDimension(createNewWorld().getDimension(0))); + Timer timer = new Timer(2000, e -> view.setDimension(createNewWorld().getDimension(NORMAL_DETAIL))); timer.start(); }); } @@ -36,7 +37,7 @@ public class WorldMorph { long seed = System.currentTimeMillis(); TileFactory tileFactory = TileFactoryFactory.createNoiseTileFactory(seed, Terrain.GRASS, JAVA_MCREGION.minZ, JAVA_MCREGION.standardMaxHeight, 16, 24, false, true, 20, 1.0); World2 world = new World2(JAVA_MCREGION, seed, tileFactory); - Dimension dim0 = world.getDimension(0); + Dimension dim0 = world.getDimension(NORMAL_DETAIL); for (int x = -2; x <= 2; x++) { for (int y = -2; y <= 2; y++) { dim0.addTile(tileFactory.createTile(x, y)); diff --git a/WorldPainter/WPUtils/src/main/java/org/pepsoft/util/swing/TiledImageViewer.java b/WorldPainter/WPUtils/src/main/java/org/pepsoft/util/swing/TiledImageViewer.java index 5a0f8ad0..b9b5bd5a 100644 --- a/WorldPainter/WPUtils/src/main/java/org/pepsoft/util/swing/TiledImageViewer.java +++ b/WorldPainter/WPUtils/src/main/java/org/pepsoft/util/swing/TiledImageViewer.java @@ -15,7 +15,6 @@ import java.awt.image.ImageObserver; import java.awt.image.VolatileImage; import java.lang.ref.Reference; import java.lang.ref.SoftReference; -import java.util.List; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; @@ -24,23 +23,21 @@ import static org.pepsoft.util.GUIUtils.getUIScale; import static org.pepsoft.util.GUIUtils.getUIScaleInt; /** - * A generic visual component which can display one or more layers of large or - * even endless tile-based images, with support for scrolling and scaling the - * images. + * A generic visual component which can display one or more layers of large or even endless tile-based images, with + * support for scrolling and scaling the images. * - *

    The tiles are provided by {@link TileProvider tile providers}. The tiles - * are requested asynchronously on multiple threads and are cached. This means - * that tile providers have to do no caching themselves and are free to - * calculate or generate each tile on request, even if that is relatively slow. - * - *

    When zooming in, this viewer performs all the scaling itself. When zooming - * out, for tile providers which indicate that they support zooming, the scaling - * is delegated to the tile providers. + *

    The tiles are provided by {@link TileProvider tile providers}. The tiles are requested asynchronously on multiple + * threads and are cached. This means that tile providers have to do no caching themselves and are free to calculate or + * generate each tile on request, even if that is relatively slow. * - *

    This class does not provide scrollbars, however it can be encapsulated in - * a {@link TiledImageViewerContainer} which will surround it with scrollbars, - * with support for the tile providers' - * {@link TileProvider#getExtent() extents}. + *

    The tile providers are ordered on numbered layers. The numbering does not have to be continuous, and only one tile + * provider can be configured per layer. Lower numbered layers are rendered below higher numbered layers. + * + *

    When zooming in, this viewer performs all the scaling itself. When zooming out, for tile providers which indicate + * that they support zooming, the scaling is delegated to the tile providers. + * + *

    This class does not provide scrollbars, however it can be encapsulated in a {@link TiledImageViewerContainer} + * which will surround it with scrollbars, with support for the tile providers' {@link TileProvider#getExtent() extents}. * * @author pepijn */ @@ -86,17 +83,8 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL * @return An unmodifyable view of the currently configured list of tile * providers. */ - public List getTileProviders() { - return Collections.unmodifiableList(tileProviders); - } - - /** - * Add a new tile provider to the end of the list of tile providers. - * - * @param tileProvider The tile provider to add. - */ - public void addTileProvider(TileProvider tileProvider) { - addTileProvider(tileProviders.size(), tileProvider); + public Collection getTileProviders() { + return Collections.unmodifiableCollection(tileProviders.values()); } /** @@ -109,94 +97,67 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL } /** - * Set the first tile provider. Mainly meant as a convenience method for - * clients that will only ever use one tile provider at a time. Will add the - * tile provider if there are none yet configured, or replace the first tile - * provider on the list if one or more tile providers are already set. + * Set or replace a tile provider on layer 0 and reuse the existing provider's cached tile images as stale tile + * images for the new provider. Mainly meant as a convenience method for clients that will only ever use one tile + * provider at a time. * - * @param tileProvider The tile provider to set. + * @param tileProvider The tile provider to place at the specified layer. */ public void setTileProvider(TileProvider tileProvider) { - if (tileProviders.isEmpty()) { - addTileProvider(tileProvider); - } else { - setTileProvider(0, tileProvider); - } + setTileProvider(0, tileProvider); } /** - * Replace a tile provider and remove all cached tile images for the - * existing provider. + * Set or replace a tile provider on a specific layer and reuse the existing provider's cached tile images as stale + * tile images for the new provider. * - * @param index The index of the tile provider to replace. - * @param tileProvider The tile provider with which to replace the existing - * provider at the specified index. + * @param layer The layer at which to place the tile provider. + * @param tileProvider The tile provider to place at the specified layer. */ - public void setTileProvider(int index, TileProvider tileProvider) { - removeTileProvider(index); - addTileProvider(index, tileProvider); - } - - /** - * Replace a tile provider and reuse the existing provider's cached tile - * images as stale tile images for the new provider. - * - * @param oldTileProvider The tile provider to replace. - * @param newTileProvider The tile provider with which to replace it. - */ - public void replaceTileProvider(TileProvider oldTileProvider, TileProvider newTileProvider) { - replaceTileProvider(tileProviders.indexOf(oldTileProvider), newTileProvider); - } - - /** - * Replace a tile provider and reuse the existing provider's cached tile - * images as stale tile images for the new provider. - * - * @param index The index of the tile provider to replace. - * @param newTileProvider The tile provider with which to replace it. - */ - public void replaceTileProvider(int index, TileProvider newTileProvider) { + public void setTileProvider(int layer, TileProvider tileProvider) { synchronized (TILE_CACHE_LOCK) { - TileProvider tileProvider = tileProviders.remove(index); - Point offset = offsets.remove(tileProvider); - tileProvider.removeTileListener(this); - Map> dirtyTileCache = dirtyTileCaches.remove(tileProvider); - Map> tileCache = tileCaches.remove(tileProvider); - // Add all live tile images from the tile cache to the dirty tile - // cache, for use as dirty tile for the new tile provider - for (Map.Entry> entry: tileCache.entrySet()) { - Reference tileImageRef = entry.getValue(); - if (tileImageRef != RENDERING) { - Image tileImage = tileImageRef.get(); - if (tileImage != null) { - dirtyTileCache.put(entry.getKey(), tileImageRef); + final TileProvider oldTileProvider = tileProviders.remove(layer); + Point offset = new Point(); + Map> dirtyTileCache = new HashMap<>(); + if (oldTileProvider != null) { + offset = offsets.remove(oldTileProvider); + oldTileProvider.removeTileListener(this); + dirtyTileCache = dirtyTileCaches.remove(oldTileProvider); + Map> tileCache = tileCaches.remove(oldTileProvider); + // Add all live tile images from the tile cache to the dirty tile cache, for use as dirty tile for the + // new tile provider + for (Map.Entry> entry: tileCache.entrySet()) { + Reference tileImageRef = entry.getValue(); + if (tileImageRef != RENDERING) { + Image tileImage = tileImageRef.get(); + if (tileImage != null) { + dirtyTileCache.put(entry.getKey(), tileImageRef); + } } } - } - // We're not completely sure how, but sometimes we reach here - // without the renderers having been started, so check whether there - // actually is a queue - if (queue != null) { - // Prune the queue of jobs related to this tile provider - for (Iterator i = queue.iterator(); i.hasNext(); ) { - if (((TileRenderJob) i.next()).tileProvider == tileProvider) { - i.remove(); + // We're not completely sure how, but sometimes we reach here without the renderers having been started, + // so check whether there actually is a queue + if (queue != null) { + // Prune the queue of jobs related to this tile provider + for (Iterator i = queue.iterator(); i.hasNext(); ) { + if (((TileRenderJob) i.next()).tileProvider == oldTileProvider) { + i.remove(); + } } } } - if (newTileProvider.isZoomSupported()) { - newTileProvider.setZoom((zoom <= 0) ? zoom : 0); + if (tileProvider.isZoomSupported()) { + tileProvider.setZoom((zoom <= 0) ? zoom : 0); } - newTileProvider.addTileListener(this); - tileProviders.add(index, newTileProvider); - offsets.put(newTileProvider, offset); - tileCaches.put(newTileProvider, new HashMap<>()); - dirtyTileCaches.put(newTileProvider, dirtyTileCache); + tileProvider.addTileListener(this); + tileProviders.put(layer, tileProvider); + offsets.put(tileProvider, offset); + tileCaches.put(tileProvider, new HashMap<>()); + dirtyTileCaches.put(tileProvider, dirtyTileCache); - // We're not completely sure how, but sometimes we reach here - // without the renderers having been started, so start them now (if - // we're visible of course) + // We're not completely sure how, but sometimes we reach here without the renderers having been started, so + // start them now (if we're visible of course) startRenderersIfApplicable(); } fireViewChangedEvent(); @@ -206,38 +167,35 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL /** * Remove a tile provider. * - * @param tileProvider The tile provider to remove. + * @param layer The layer on the tile provider to remove is placed. */ - public void removeTileProvider(TileProvider tileProvider) { - removeTileProvider(tileProviders.indexOf(tileProvider)); - } - - /** - * Remove a tile provider. - * - * @param index The index of the tile provider to remove. - */ - public void removeTileProvider(int index) { + public void removeTileProvider(int layer) { + boolean providerRemoved = false; synchronized (TILE_CACHE_LOCK) { - TileProvider tileProvider = tileProviders.remove(index); - offsets.remove(tileProvider); - tileProvider.removeTileListener(this); - tileCaches.remove(tileProvider); - dirtyTileCaches.remove(tileProvider); - // We're not completely sure how, but sometimes we reach here - // without the renderers having been started, so check whether there - // actually is a queue - if (queue != null) { - // Prune the queue of jobs related to this tile provider - for (Iterator i = queue.iterator(); i.hasNext(); ) { - if (((TileRenderJob) i.next()).tileProvider == tileProvider) { - i.remove(); + final TileProvider tileProvider = tileProviders.remove(layer); + if (tileProvider != null) { + offsets.remove(tileProvider); + tileProvider.removeTileListener(this); + tileCaches.remove(tileProvider); + dirtyTileCaches.remove(tileProvider); + // We're not completely sure how, but sometimes we reach here + // without the renderers having been started, so check whether there + // actually is a queue + if (queue != null) { + // Prune the queue of jobs related to this tile provider + for (Iterator i = queue.iterator(); i.hasNext(); ) { + if (((TileRenderJob) i.next()).tileProvider == tileProvider) { + i.remove(); + } } } + providerRemoved = true; } } - fireViewChangedEvent(); - repaint(); + if (providerRemoved) { + fireViewChangedEvent(); + repaint(); + } } /** @@ -245,7 +203,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL */ public void removeAllTileProviders() { synchronized (TILE_CACHE_LOCK) { - for (TileProvider tileProvider: tileProviders) { + for (TileProvider tileProvider: tileProviders.values()) { tileProvider.removeTileListener(this); } tileProviders.clear(); @@ -260,31 +218,6 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL repaint(); } - /** - * Add or insert a new tile provider at a specific index in the list. - * - * @param index The index at which to add or insert the new tile provider. - * @param tileProvider The tile provider to add or insert. - */ - public void addTileProvider(int index, TileProvider tileProvider) { - if (tileProvider == null) { - throw new NullPointerException(); - } - tileProviders.add(index, tileProvider); - offsets.put(tileProvider, new Point()); - synchronized (TILE_CACHE_LOCK) { - if (tileProvider.isZoomSupported()) { - tileProvider.setZoom((zoom <= 0) ? zoom : 0); - } - tileProvider.addTileListener(this); - tileCaches.put(tileProvider, new HashMap<>()); - dirtyTileCaches.put(tileProvider, new HashMap<>()); - startRenderersIfApplicable(); - } - fireViewChangedEvent(); - repaint(); - } - /** * Get the X coordinate in image coordinates of the centre of the view. * @@ -326,7 +259,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL */ public Rectangle getExtent() { Rectangle extent = null; - for (TileProvider tileProvider: tileProviders) { + for (TileProvider tileProvider: tileProviders.values()) { Rectangle providerExtent = tileProvider.getExtent(); if (providerExtent != null) { providerExtent = getTileBounds(tileProvider, providerExtent.x, providerExtent.y, providerExtent.width, providerExtent.height, zoom); @@ -394,11 +327,11 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL queue.clear(); } synchronized (TILE_CACHE_LOCK) { - for (TileProvider tileProvider: tileProviders) { + for (TileProvider tileProvider: tileProviders.values()) { if (tileProvider.isZoomSupported()) { // Only use the tile provider's own zoom support for // zooming out: - tileProvider.setZoom((zoom <= 0) ? zoom : 0); + tileProvider.setZoom(((zoom + providerZoom.getOrDefault(tileProvider, 0)) <= 0) ? (zoom + providerZoom.getOrDefault(tileProvider, 0)) : 0); } dirtyTileCaches.put(tileProvider, new HashMap<>()); tileCaches.put(tileProvider, new HashMap<>()); @@ -575,7 +508,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL public void refresh(boolean keepDirtyTiles) { queue.clear(); synchronized (TILE_CACHE_LOCK) { - for (TileProvider tileProvider: tileProviders) { + for (TileProvider tileProvider: tileProviders.values()) { if (keepDirtyTiles) { Map> dirtyTileCache = tileCaches.get(tileProvider); // Remove all dirty tiles which don't exist any more @@ -1010,6 +943,10 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL } } + public void setProviderZoom(TileProvider tileProvider, int zoom) { + providerZoom.put(tileProvider, zoom); + } + /** * Determine whether a tile is currently visible in the viewport. * @@ -1291,8 +1228,8 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); GraphicsConfiguration gc = getGraphicsConfiguration(); - for (TileProvider tileProvider: tileProviders) { - final int effectiveZoom = (tileProvider.isZoomSupported() && (zoom < 0)) ? 0 : zoom; + for (TileProvider tileProvider: tileProviders.values()) { + final int effectiveZoom = (tileProvider.isZoomSupported() && ((zoom + providerZoom.getOrDefault(tileProvider, 0)) < 0)) ? 0 : (zoom + providerZoom.getOrDefault(tileProvider, 0)); final Point topLeftTileCoords = viewToWorld(tileProvider, clipBounds.getLocation(), effectiveZoom); final int leftTile = topLeftTileCoords.x >> TILE_SIZE_BITS; final int topTile = topLeftTileCoords.y >> TILE_SIZE_BITS; @@ -1482,7 +1419,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL Rectangle tileBounds = getTileBounds(tileProvider, x, y, effectiveZoom); Image tile = getTile(tileProvider, x, y, effectiveZoom, gc); if (tile != null) { - if (zoom > 0) { + if ((zoom + providerZoom.getOrDefault(tileProvider, 0)) > 0) { g2.drawImage(tile, tileBounds.x, tileBounds.y, tileBounds.width, tileBounds.height, this); } else { g2.drawImage(tile, tileBounds.x, tileBounds.y, this); @@ -1799,7 +1736,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL /** * The currently configured tile providers. */ - private final List tileProviders = new ArrayList<>(); + private final SortedMap tileProviders = new TreeMap<>(); /** * The fresh and stale tile caches for each tile provider. */ @@ -1878,6 +1815,7 @@ public class TiledImageViewer extends JComponent implements TileListener, MouseL private BufferedImage backgroundImage; private BackgroundImageMode backgroundImageMode = BackgroundImageMode.CENTRE_REPEAT; private volatile boolean inhibitUpdates; + private Map providerZoom = new WeakHashMap<>(); public static final int TILE_SIZE = 128, TILE_SIZE_BITS = 7, TILE_SIZE_MASK = 0x7f; public static final IntegerAttributeKey ADVANCED_SETTING_MAX_TILE_RENDER_THREADS = new IntegerAttributeKey("display.maxTileRenderThreads", 8);