Refactor Dimension identity/layering in preparation of master/multiple layer support

master
Captain Chaos 2022-08-15 14:24:00 +02:00
parent b4004645eb
commit 2bae92287c
59 changed files with 817 additions and 990 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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<Point, Tile> 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<Listener> listeners = new ArrayList<>();
private transient boolean eventsInhibited;
private transient Set<Tile> 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<Point> 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
}
}

View File

@ -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());

View File

@ -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;
}
}

View File

@ -35,7 +35,7 @@ import java.util.*;
*/
public abstract class RODelegatingDimension<T extends Tile> 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<T extends Tile> extends Dimension {
}
@Override
public int getDim() {
return dimension.getDim();
public Anchor getAnchor() {
return dimension.getAnchor();
}
@Override

View File

@ -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 <strong>not</strong> 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);
}

View File

@ -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<Layer> 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<Layer> 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<Layer> 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<Layer> 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<Layer> 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<Tile> 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<Point> coordSet = new HashSet<>();
@ -670,9 +521,12 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime
});
}
@NotNull
private ThreadLocal<BufferedImage> 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<TileListener> listeners = new ArrayList<>();
private final CustomBiomeManager customBiomeManager;
private final org.pepsoft.util.swing.TileProvider surroundingTileProvider;
private final ThreadLocal<BufferedImage> surroundingTileImageRef;
private final Effect effect;
private int zoom = 0;
private volatile ThreadLocal<TileRenderer> tileRendererRef;
@ -714,4 +567,8 @@ public class WPTileProvider implements org.pepsoft.util.swing.TileProvider, Dime
*/
BARRIER_WALL
}
public enum Effect {
FADE_TO_WHITE
}
}

View File

@ -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<Dimension> getDimensions() {
return new HashSet<>(dimensionsByAnchor.values());
}
public Set<Dimension> 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<Integer, Dimension> dimensions = new TreeMap<>();
@Deprecated
private SortedMap<Integer, Dimension> dimensions;
private boolean mapFeatures = true;
@Deprecated
private int gameType;
@ -777,6 +793,7 @@ public class World2 extends InstanceKeeper implements Serializable, Cloneable {
private Map<String, Object> attributes;
@Deprecated
private SuperflatPreset superflatPreset;
private Map<Anchor, Dimension> dimensionsByAnchor = new HashMap<>();
private transient Set<Warning> warnings;
private transient Map<String, Object> 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;

View File

@ -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);

View File

@ -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<Point, List<Fixup>> entry: fixups.entrySet()) {
if (progressReceiver != null) {

View File

@ -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:

View File

@ -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");

View File

@ -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()) {

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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<String> allBiomes = synchronizedSet(new HashSet<>());
final Set<Integer> 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();

View File

@ -35,7 +35,7 @@ import static org.pepsoft.worldpainter.layers.exporters.ResourcesExporter.Resour
*/
public class ResourcesExporter extends AbstractLayerExporter<Resources> 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<Material> allMaterials = resourcesSettings.getMaterials();
final List<Material> activeMaterials = new ArrayList<>(allMaterials.size());
@ -72,7 +72,7 @@ public class ResourcesExporter extends AbstractLayerExporter<Resources> 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<Resources> implemen
final Map<Material, ResourceSettings> 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<Resources> 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<Resources> 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()));

View File

@ -76,7 +76,7 @@ public class VoidExporter extends AbstractLayerExporter<org.pepsoft.worldpainter
// Check for water surrounding the column; pre-render the falling water
// column to avoid long pauses in Minecraft when the chunks are loaded
// (but not for ceiling dimensions)
if (dimension.getDim() >= 0) {
if (! dimension.getAnchor().invert) {
int highestNonAirBlock = Integer.MIN_VALUE;
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {

View File

@ -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<Integer> 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<DataType> 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;

View File

@ -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);

View File

@ -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<Layer, ExporterSettings> settingsEntry: dimension.getAllLayerSettings().entrySet()) {
if (settingsEntry.getValue() != null) {

View File

@ -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++) {

View File

@ -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));

View File

@ -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));

View File

@ -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<Void> {
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<Void> {
}
}
}
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<Void> {
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

View File

@ -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);
}
}

View File

@ -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<Dimension> 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<SuperflatPreset.Layer> 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

View File

@ -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<Dimension> 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

View File

@ -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<Material> 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();

View File

@ -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++) {

View File

@ -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);

View File

@ -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 {

View File

@ -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<Terrain> allTerrains = ProgressDialog.executeTask(this, "Checking whether terrain is in use", () -> Arrays.stream(world.getDimensions())
Set<Terrain> 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;

View File

@ -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);

View File

@ -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));

View File

@ -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<Integer> 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);

View File

@ -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("<html>Please confirm that you want to export the world<br>notwithstanding the following warnings:<br><ul>");
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("<li>Population not supported for<br>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("<li>The Superflat world type is selected and Populate is in use.<br>Minecraft will <em>not</em> 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<Integer, DimensionPropertiesEditor> dimensionPropertiesEditors = new HashMap<>();
private final Map<Anchor, DimensionPropertiesEditor> dimensionPropertiesEditors = new HashMap<>();
private final List<Platform> supportedPlatforms = new ArrayList<>();
private int selectedDimension;
private Set<Point> selectedTiles;

View File

@ -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);
}

View File

@ -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<Layer> 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")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {

View File

@ -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<Point> tiles) {
public NewWorldDialog(App app, ColourScheme colourScheme, String name, long seed, Platform platform, Anchor anchor, int defaultMaxHeight, Dimension baseDimension, Set<Point> 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<Point, Tile> 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<Integer, Terrain> terrainMap = new TreeMap<>();
terrainMap.put(-1, terrain);
@ -1535,8 +1535,9 @@ public class NewWorldDialog extends WorldPainterDialog {
private final Set<Point> 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;

View File

@ -59,7 +59,7 @@ public class NewWorldDialog2 extends javax.swing.JDialog {
private final Map<Point, Tile> 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() {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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:

View File

@ -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());

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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.
*
* <p>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.
*
* <p>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.
* <p>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.
*
* <p>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}.
* <p>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.
*
* <p>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.
*
* <p>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<TileProvider> 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<TileProvider> 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<Point, Reference<? extends Image>> dirtyTileCache = dirtyTileCaches.remove(tileProvider);
Map<Point, Reference<? extends Image>> 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<Point, Reference<? extends Image>> entry: tileCache.entrySet()) {
Reference<? extends Image> 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<Point, Reference<? extends Image>> dirtyTileCache = new HashMap<>();
if (oldTileProvider != null) {
offset = offsets.remove(oldTileProvider);
oldTileProvider.removeTileListener(this);
dirtyTileCache = dirtyTileCaches.remove(oldTileProvider);
Map<Point, Reference<? extends Image>> 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<Point, Reference<? extends Image>> entry: tileCache.entrySet()) {
Reference<? extends Image> 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<Runnable> 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<Runnable> 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<Runnable> 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<Runnable> 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<Point, Reference<? extends Image>> 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<TileProvider> tileProviders = new ArrayList<>();
private final SortedMap<Integer, TileProvider> 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<TileProvider, Integer> 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);