/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter;
import org.pepsoft.minecraft.Direction;
import org.pepsoft.minecraft.Material;
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.history.HistoryEntry;
import org.pepsoft.worldpainter.layers.Biome;
import org.pepsoft.worldpainter.layers.Layer;
import java.awt.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.*;
import java.util.List;
import static org.pepsoft.worldpainter.Constants.DIM_NORMAL;
import static org.pepsoft.worldpainter.Constants.TILE_SIZE;
/**
*
* @author pepijn
*/
public class World2 extends InstanceKeeper implements Serializable, Cloneable {
public World2(int maxHeight) {
this.maxheight = maxHeight;
}
public World2(long minecraftSeed, TileFactory tileFactory, int maxHeight) {
this.maxheight = maxHeight;
Dimension dim = new Dimension(minecraftSeed, tileFactory, 0, maxHeight);
addDimension(dim);
}
public boolean isDirty() {
if (dirty || borderSettings.isDirty()) {
return true;
} else {
for (Dimension dimension: dimensions.values()) {
if (dimension.isDirty()) {
return true;
}
}
return false;
}
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
if (! dirty) {
borderSettings.setDirty(false);
for (Dimension dimension: dimensions.values()) {
dimension.setDirty(false);
}
}
}
public String getName() {
return name;
}
public void setName(String name) {
if (! (name.equals(this.name))) {
String oldName = this.name;
this.name = name;
dirty = true;
propertyChangeSupport.firePropertyChange("name", oldName, name);
}
}
public boolean isCreateGoodiesChest() {
return createGoodiesChest;
}
public void setCreateGoodiesChest(boolean createGoodiesChest) {
if (createGoodiesChest != this.createGoodiesChest) {
this.createGoodiesChest = createGoodiesChest;
dirty = true;
propertyChangeSupport.firePropertyChange("createGoodiesChest", ! createGoodiesChest, createGoodiesChest);
}
}
public Point getTileCoordinates(int worldX, int worldY) {
int tileX = (int) Math.floor((double) worldX / TILE_SIZE);
int tileY = (int) Math.floor((double) worldY / TILE_SIZE);
return new Point(tileX, tileY);
}
public Point getTileCoordinates(Point worldCoords) {
return getTileCoordinates(worldCoords.x, worldCoords.y);
}
public Point getSpawnPoint() {
return spawnPoint;
}
public void setSpawnPoint(Point spawnPoint) {
if (! spawnPoint.equals(this.spawnPoint)) {
Point oldSpawnPoint = this.spawnPoint;
this.spawnPoint = spawnPoint;
dirty = true;
propertyChangeSupport.firePropertyChange("spawnPoint", oldSpawnPoint, spawnPoint);
}
}
public File getImportedFrom() {
return importedFrom;
}
public void setImportedFrom(File importedFrom) {
if ((importedFrom == null) ? (this.importedFrom != null) : (! importedFrom.equals(this.importedFrom))) {
File oldImportedFrom = this.importedFrom;
this.importedFrom = importedFrom;
propertyChangeSupport.firePropertyChange("importedFrom", oldImportedFrom, importedFrom);
}
}
public boolean isMapFeatures() {
return mapFeatures;
}
public void setMapFeatures(boolean mapFeatures) {
if (mapFeatures != this.mapFeatures) {
this.mapFeatures = mapFeatures;
dirty = true;
propertyChangeSupport.firePropertyChange("mapFeatures", ! mapFeatures, mapFeatures);
}
}
public int getGameType() {
return gameType;
}
public void setGameType(int gameType) {
if (gameType != this.gameType) {
int oldGameType = this.gameType;
this.gameType = gameType;
dirty = true;
propertyChangeSupport.firePropertyChange("gameType", oldGameType, gameType);
}
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
public Dimension getDimension(int dim) {
return dimensions.get(dim);
}
public Dimension[] getDimensions() {
return dimensions.values().toArray(new Dimension[dimensions.size()]);
}
public final void addDimension(Dimension dimension) {
if (dimensions.containsKey(dimension.getDim())) {
throw new IllegalStateException("Dimension " + dimension.getDim() + " already exists");
} else if (dimension.getMaxHeight() != maxheight) {
throw new IllegalStateException("Dimension has different max height (" + dimension.getMaxHeight() + ") than world (" + maxheight + ")");
} else {
dimension.setWorld(this);
dimensions.put(dimension.getDim(), dimension);
if (dimension.getDim() == 0) {
TileFactory tileFactory = dimension.getTileFactory();
if (tileFactory instanceof HeightMapTileFactory) {
if (((HeightMapTileFactory) tileFactory).getWaterHeight() < 32) {
// Low level
generator = Generator.FLAT;
}
}
}
}
if (dimension.getDim() != DIM_NORMAL) {
history.add(new HistoryEntry(HistoryEntry.WORLD_DIMENSION_ADDED, dimension.getName()));
}
}
public Dimension removeDimension(int dim) {
if (dimensions.containsKey(dim)) {
dirty = true;
Dimension dimension = dimensions.remove(dim);
history.add(new HistoryEntry(HistoryEntry.WORLD_DIMENSION_REMOVED, dimension.getName()));
return dimension;
} else {
throw new IllegalStateException("Dimension " + dim + " does not exist");
}
}
public MixedMaterial getMixedMaterial(int index) {
return mixedMaterials[index];
}
public void setMixedMaterial(int index, MixedMaterial material) {
if ((material == null) ? (mixedMaterials[index] != null) : (! material.equals(mixedMaterials[index]))) {
MixedMaterial oldMaterial = mixedMaterials[index];
mixedMaterials[index] = material;
dirty = true;
propertyChangeSupport.fireIndexedPropertyChange("mixedMaterial", index, oldMaterial, material);
}
}
public int getMaxHeight() {
return maxheight;
}
public void setMaxHeight(int maxHeight) {
if (maxHeight != this.maxheight) {
int oldMaxHeight = this.maxheight;
this.maxheight = maxHeight;
dirty = true;
propertyChangeSupport.firePropertyChange("maxHeight", oldMaxHeight, maxHeight);
}
}
public Generator getGenerator() {
return generator;
}
public void setGenerator(Generator generator) {
if (generator != this.generator) {
Generator oldGenerator = this.generator;
this.generator = generator;
dirty = true;
propertyChangeSupport.firePropertyChange("generator", oldGenerator, generator);
}
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
if (version != this.version) {
int oldVersion = this.version;
this.version = version;
dirty = true;
propertyChangeSupport.firePropertyChange("version", oldVersion, version);
}
}
public boolean isAskToConvertToAnvil() {
// Inverted so that legacy worlds have the correct setting
return !dontAskToConvertToAnvil;
}
public void setAskToConvertToAnvil(boolean askToConvertToAnvil) {
// Inverted so that legacy worlds have the correct setting
if (askToConvertToAnvil == dontAskToConvertToAnvil) {
dontAskToConvertToAnvil = !askToConvertToAnvil;
dirty = true;
propertyChangeSupport.firePropertyChange("askToConvertToAnvil", askToConvertToAnvil, !askToConvertToAnvil);
}
}
public Set<Point> getTilesToExport() {
return tilesToExport;
}
public void setTilesToExport(Set<Point> tilesToExport) {
this.tilesToExport = tilesToExport;
}
public boolean isAskToRotate() {
return askToRotate;
}
public void setAskToRotate(boolean askToRotate) {
if (askToRotate != this.askToRotate) {
this.askToRotate = askToRotate;
dirty = true;
propertyChangeSupport.firePropertyChange("askToRotate", !askToRotate, askToRotate);
}
}
public Direction getUpIs() {
return upIs;
}
public void setUpIs(Direction upIs) {
if (upIs != this.upIs) {
Direction oldUpIs = this.upIs;
this.upIs = upIs;
dirty = true;
propertyChangeSupport.firePropertyChange("upIs", oldUpIs, upIs);
}
}
public boolean isAllowMerging() {
return allowMerging;
}
public void setAllowMerging(boolean allowMerging) {
this.allowMerging = allowMerging;
}
public boolean isAllowCheats() {
return allowCheats;
}
public void setAllowCheats(boolean allowCheats) {
if (allowCheats != this.allowCheats) {
this.allowCheats = allowCheats;
dirty = true;
propertyChangeSupport.firePropertyChange("allowCheats", !allowCheats, allowCheats);
}
}
public String getGeneratorOptions() {
return generatorOptions;
}
public void setGeneratorOptions(String generatorOptions) {
if ((generatorOptions != null) ? (! generatorOptions.equals(this.generatorOptions)) : (this.generatorOptions != null)) {
String oldGeneratorOptions = this.generatorOptions;
this.generatorOptions = generatorOptions;
dirty = true;
propertyChangeSupport.firePropertyChange("generatorOptions", oldGeneratorOptions, generatorOptions);
}
}
public boolean isExtendedBlockIds() {
return extendedBlockIds;
}
public void setExtendedBlockIds(boolean extendedBlockIds) {
if (extendedBlockIds != this.extendedBlockIds) {
this.extendedBlockIds = extendedBlockIds;
dirty = true;
propertyChangeSupport.firePropertyChange("extendedBlockIds", !extendedBlockIds, extendedBlockIds);
}
}
public int getDifficulty() {
return difficulty;
}
public void setDifficulty(int difficulty) {
if (difficulty != this.difficulty) {
int oldDifficulty = this.difficulty;
this.difficulty = difficulty;
dirty = true;
propertyChangeSupport.firePropertyChange("difficulty", oldDifficulty, difficulty);
}
}
public List<HistoryEntry> getHistory() {
synchronized (history) {
return history;
}
}
public void addHistoryEntry(int key, Serializable... args) {
synchronized (history) {
history.add(new HistoryEntry(key, args));
}
}
public Map<String, Object> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
}
public BorderSettings getBorderSettings() {
return borderSettings;
}
public File getMergedWith() {
return mergedWith;
}
public void setMergedWith(File mergedWith) {
if ((mergedWith == null) ? (this.mergedWith != null) : (! mergedWith.equals(this.mergedWith))) {
File oldMergedWith = this.mergedWith;
this.mergedWith = mergedWith;
dirty = true;
propertyChangeSupport.firePropertyChange("mergedWith", oldMergedWith, mergedWith);
}
}
public Set<Integer> getDimensionsToExport() {
return dimensionsToExport;
}
public void setDimensionsToExport(Set<Integer> dimensionsToExport) {
if ((dimensionsToExport == null) ? (this.dimensionsToExport != null) : (! dimensionsToExport.equals(this.dimensionsToExport))) {
Set<Integer> oldMergedDimensions = this.dimensionsToExport;
this.dimensionsToExport = dimensionsToExport;
dirty = true;
propertyChangeSupport.firePropertyChange("mergedDimensions", oldMergedDimensions, dimensionsToExport);
}
}
/**
* Transforms all dimensions of this world horizontally. If an undo manager
* is installed this operation will destroy all undo info.
*
* @param transform The coordinate transform to apply.
* @param progressReceiver A progress receiver which will be informed of
* rotation progress.
*/
public void transform(CoordinateTransform transform, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled {
int dimCount = dimensions.size(), dim = 0;
for (Dimension dimension: dimensions.values()) {
dimension.transform(transform, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, (float) dim / dimCount, 1.0f / dimCount) : null);
dim++;
}
Point oldSpawnPoint = spawnPoint;
spawnPoint = transform.transform(spawnPoint);
propertyChangeSupport.firePropertyChange("spawnPoint", oldSpawnPoint, spawnPoint);
Direction oldUpIs = upIs;
upIs = transform.inverseTransform(upIs);
propertyChangeSupport.firePropertyChange("upIs", oldUpIs, upIs);
dirty = true;
}
/**
* Transforms one dimension horizontally. If it's the surface dimension also
* 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 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) {
Point oldSpawnPoint = spawnPoint;
spawnPoint = transform.transform(spawnPoint);
propertyChangeSupport.firePropertyChange("spawnPoint", oldSpawnPoint, spawnPoint);
Direction oldUpIs = upIs;
upIs = transform.inverseTransform(upIs);
propertyChangeSupport.firePropertyChange("upIs", oldUpIs, upIs);
}
dirty = true;
}
public void clearLayerData(Layer layer) {
for (Dimension dimension: dimensions.values()) {
dimension.clearLayerData(layer);
}
}
@SuppressWarnings("unchecked")
public int measureSize() {
dimensions.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)));
}
/**
* Get the set of warning generated during loading, if any.
*
* @return The set of warning generated during loading, if any. May be
* <code>null</code>.
*/
Set<Warning> getWarnings() {
return warnings;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
propertyChangeSupport = new PropertyChangeSupport(this);
if (wpVersion < 1) {
// Legacy maps
if (maxheight == 0) {
maxheight = 128;
}
if (generator == null) {
generator = Generator.DEFAULT;
if ((generatorName != null) && generatorName.equals("FLAT")) {
generator = Generator.FLAT;
} else {
TileFactory tileFactory = dimensions.containsKey(0) ? dimensions.get(0).getTileFactory() : null;
if (tileFactory instanceof HeightMapTileFactory) {
if (((HeightMapTileFactory) tileFactory).getWaterHeight() < 32) {
// Low level
generator = Generator.FLAT;
}
}
}
}
if (biomeAlgorithm == BIOME_ALGORITHM_CUSTOM_BIOMES) {
customBiomes = true;
}
if (upIs == null) {
upIs = Direction.WEST;
askToRotate = true;
}
if ((! allowMerging) && (biomeAlgorithm != BIOME_ALGORITHM_NONE)) {
customBiomes = false;
}
if (mixedMaterials == null) {
mixedMaterials = new MixedMaterial[Terrain.CUSTOM_TERRAIN_COUNT];
if (customMaterials != null) {
for (int i = 0; i < customMaterials.length; i++) {
if (customMaterials[i] != null) {
mixedMaterials[i] = MixedMaterial.create(customMaterials[i]);
}
}
customMaterials = null;
}
}
Dimension dim = dimensions.get(DIM_NORMAL);
if (dim != null) {
// Migrate to refactored automatic biomes
if (biomeAlgorithm == BIOME_ALGORITHM_AUTO_BIOMES) {
// Automatic biomes was enabled; biome information should
// be present throughout; no need to do anything. Schedule a
// warning to warn the user about the change though
warnings = EnumSet.of(Warning.AUTO_BIOMES_DISABLED);
} else if (customBiomes) {
// Custom biomes was enabled; a mix of initialised and
// uninitialised tiles may be present which would be
// problematic, as the initialised tiles would have been
// initialised to zero and the default is now 255. Check what
// the situation is and take appropriate steps
boolean tilesWithBiomesFound = false, tilesWithoutBiomesFound = false;
for (Tile tile: dim.getTiles()) {
if (tile.hasLayer(Biome.INSTANCE)) {
tilesWithBiomesFound = true;
} else {
tilesWithoutBiomesFound = true;
}
}
if (tilesWithBiomesFound) {
if (tilesWithoutBiomesFound) {
// There is a mix of initialised and uninitialiased
// tiles. Initialise the uninitialised ones to zero.
// No need to warn the user as there is no change in
// behaviour
for (Tile tile: dim.getTiles()) {
if (! tile.hasLayer(Biome.INSTANCE)) {
for (int x = 0; x < TILE_SIZE; x++) {
for (int y = 0; y < TILE_SIZE; y++) {
tile.setLayerValue(Biome.INSTANCE, x, y, 0);
}
}
}
}
} else {
// There are only initialised tiles. Good, we can leave
// it like that, and don't have to warn the user, as the
// behaviour will not change
}
} else if (tilesWithoutBiomesFound) {
// There are only uninitialised tiles. Leave it like that,
// but warn the user that automatic biomes is now active
warnings = EnumSet.of(Warning.AUTO_BIOMES_ENABLED);
}
} else {
// Neither custom nor automatic biomes was enabled; all
// tiles *should* be uninitialised, but clear the layer data
// anyway just to make sure. Schedule a warning to warn the user
// that automatic biomes are now active
dim.clearLayerData(Biome.INSTANCE);
warnings = EnumSet.of(Warning.AUTO_BIOMES_ENABLED);
}
}
}
if (wpVersion < 2) {
if (gameType == GAME_TYPE_HARDCORE) {
difficulty = org.pepsoft.minecraft.Constants.DIFFICULTY_HARD;
} else {
difficulty = org.pepsoft.minecraft.Constants.DIFFICULTY_NORMAL;
}
}
if (wpVersion < 3) {
history = new ArrayList<>();
history.add(new HistoryEntry(HistoryEntry.WORLD_LEGACY_PRE_2_0_0));
}
if (wpVersion < 4) {
borderSettings = new BorderSettings();
}
if (wpVersion < 5) {
if (tilesToExport != null) {
dimensionsToExport = Collections.singleton(dimensionToExport);
} else {
dimensionsToExport = null;
}
dimensionToExport = -1;
}
wpVersion = CURRENT_WP_VERSION;
// Bug fix: fix the maxHeight of the dimensions, which somehow is not
// always correctly set (possibly only on imported worlds from
// non-standard height maps due to a bug which should be fixed).
dimensions.values().stream()
.filter(dimension -> dimension.getMaxHeight() != maxheight)
.forEach(dimension -> {
logger.warn("Fixing maxHeight of dimension " + dimension.getDim() + " (was " + dimension.getMaxHeight() + ", should be " + maxheight + ")");
dimension.setMaxHeight(maxheight);
dimension.setDirty(false);
});
// The number of custom terrains increases now and again; correct old
// worlds for it
if (mixedMaterials.length != Terrain.CUSTOM_TERRAIN_COUNT) {
mixedMaterials = Arrays.copyOf(mixedMaterials, Terrain.CUSTOM_TERRAIN_COUNT);
}
}
private String name = "Generated World";
private boolean createGoodiesChest = true;
private Point spawnPoint = new Point(0, 0);
private File importedFrom;
private final SortedMap<Integer, Dimension> dimensions = new TreeMap<>();
private boolean mapFeatures = true;
private int gameType = GAME_TYPE_SURVIVAL;
@Deprecated
private Material[] customMaterials;
@Deprecated
private int biomeAlgorithm = -1;
private int maxheight = DEFAULT_MAX_HEIGHT; // Typo, but there are already worlds in the wild with this, so leave it
private transient boolean dirty;
private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
@Deprecated
private String generatorName;
/**
* The map format version number with which this world was last exported.
*/
private int version;
/**
* The type of terrain generator to choose.
*/
private Generator generator = Generator.DEFAULT;
private boolean dontAskToConvertToAnvil = true;
private boolean customBiomes;
@Deprecated
private int dimensionToExport;
private Set<Point> tilesToExport;
private boolean askToRotate, allowMerging = true;
private Direction upIs = Direction.NORTH;
private boolean allowCheats;
private String generatorOptions;
private MixedMaterial[] mixedMaterials = new MixedMaterial[Terrain.CUSTOM_TERRAIN_COUNT];
private boolean extendedBlockIds;
private int wpVersion = CURRENT_WP_VERSION;
private int difficulty = org.pepsoft.minecraft.Constants.DIFFICULTY_NORMAL;
private List<HistoryEntry> history = new ArrayList<>();
private BorderSettings borderSettings = new BorderSettings();
private File mergedWith;
private Set<Integer> dimensionsToExport;
private transient Set<Warning> warnings;
private transient Map<String, Object> metadata;
@Deprecated
public static final int BIOME_ALGORITHM_NONE = -1;
@Deprecated
public static final int BIOME_ALGORITHM_CUSTOM_BIOMES = 6;
@Deprecated
public static final int BIOME_ALGORITHM_AUTO_BIOMES = 7;
public static final int DEFAULT_MAX_HEIGHT = org.pepsoft.minecraft.Constants.DEFAULT_MAX_HEIGHT_2;
public static final long DEFAULT_OCEAN_SEED = 27594263L; // A seed with a large ocean around the origin, and not many mushroom islands nearby. Should be used with Large Biomes
public static final long DEFAULT_LAND_SEED = 227290L; // A seed with a huge continent around the origin. Should be used with Large Biomes
// These do NOT correspond to actual Minecraft game types, since hardcore
// is encoded as survival
public static final int GAME_TYPE_SURVIVAL = 0;
public static final int GAME_TYPE_CREATIVE = 1;
public static final int GAME_TYPE_ADVENTURE = 2;
public static final int GAME_TYPE_HARDCORE = 3;
/**
* A {@link String} containing the WorldPainter version with which this file
* was saved.
*/
public static final String METADATA_KEY_WP_VERSION = "org.pepsoft.worldpainter.wp.version";
/**
* A {@link String} containing the WorldPainter build with which this file
* was saved.
*/
public static final String METADATA_KEY_WP_BUILD = "org.pepsoft.worldpainter.wp.build";
/**
* A {@link Date} containing the time at which this file was saved.
*/
public static final String METADATA_KEY_TIMESTAMP = "org.pepsoft.worldpainter.timestamp";
/**
* An optional two dimensional {@link String}[][2] array containing the
* plugins installed in the WorldPainter instance which saved the file. One
* row per plugin, which each row containing two elements, the first being
* the plugin name, the second being the plugin version.
*
* <p>May be <code>null</code> if no non-standard plugins were present.
*/
public static final String METADATA_KEY_PLUGINS = "org.pepsoft.worldpainter.plugins";
private static final int CURRENT_WP_VERSION = 5;
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(World2.class);
private static final long serialVersionUID = 2011062401L;
enum Warning {AUTO_BIOMES_ENABLED, AUTO_BIOMES_DISABLED}
public static class BorderSettings implements Serializable, org.pepsoft.util.undo.Cloneable<BorderSettings> {
public int getCentreX() {
return centreX;
}
public void setCentreX(int centreX) {
if (centreX != this.centreX) {
this.centreX = centreX;
dirty = true;
}
}
public int getCentreY() {
return centreY;
}
public void setCentreY(int centreY) {
if (centreY != this.centreY) {
this.centreY = centreY;
dirty = true;
}
}
public int getSize() {
return size;
}
public void setSize(int size) {
if (size != this.size) {
this.size = size;
dirty = true;
}
}
public int getSafeZone() {
return safeZone;
}
public void setSafeZone(int safeZone) {
if (safeZone != this.safeZone) {
this.safeZone = safeZone;
dirty = true;
}
}
public int getWarningBlocks() {
return warningBlocks;
}
public void setWarningBlocks(int warningBlocks) {
if (warningBlocks != this.warningBlocks) {
this.warningBlocks = warningBlocks;
dirty = true;
}
}
public int getWarningTime() {
return warningTime;
}
public void setWarningTime(int warningTime) {
if (warningTime != this.warningTime) {
this.warningTime = warningTime;
dirty = true;
}
}
public int getSizeLerpTarget() {
return sizeLerpTarget;
}
public void setSizeLerpTarget(int sizeLerpTarget) {
if (sizeLerpTarget != this.sizeLerpTarget) {
this.sizeLerpTarget = sizeLerpTarget;
dirty = true;
}
}
public int getSizeLerpTime() {
return sizeLerpTime;
}
public void setSizeLerpTime(int sizeLerpTime) {
if (sizeLerpTime != this.sizeLerpTime) {
this.sizeLerpTime = sizeLerpTime;
dirty = true;
}
dirty = true;
}
public float getDamagePerBlock() {
return damagePerBlock;
}
public void setDamagePerBlock(float damagePerBlock) {
if (damagePerBlock != this.damagePerBlock) {
this.damagePerBlock = damagePerBlock;
dirty = true;
}
dirty = true;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BorderSettings that = (BorderSettings) o;
if (centreX != that.centreX) return false;
if (centreY != that.centreY) return false;
if (size != that.size) return false;
if (safeZone != that.safeZone) return false;
if (warningBlocks != that.warningBlocks) return false;
if (warningTime != that.warningTime) return false;
if (sizeLerpTarget != that.sizeLerpTarget) return false;
if (sizeLerpTime != that.sizeLerpTime) return false;
return Float.compare(that.damagePerBlock, damagePerBlock) == 0;
}
@Override
public int hashCode() {
int result = centreX;
result = 31 * result + centreY;
result = 31 * result + size;
result = 31 * result + safeZone;
result = 31 * result + warningBlocks;
result = 31 * result + warningTime;
result = 31 * result + sizeLerpTarget;
result = 31 * result + sizeLerpTime;
result = 31 * result + (damagePerBlock != +0.0f ? Float.floatToIntBits(damagePerBlock) : 0);
return result;
}
@Override
public BorderSettings clone() {
try {
return (BorderSettings) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
private int centreX, centreY, size = 60000000, safeZone = 5, warningBlocks = 5, warningTime = 15, sizeLerpTarget = 60000000, sizeLerpTime;
private float damagePerBlock = 0.2f;
private boolean dirty;
private static final long serialVersionUID = 1L;
}
}