org.pepsoft.worldpainter.tools.BiomesTileProvider Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.tools;
import org.pepsoft.util.ColourUtils;
import org.pepsoft.util.swing.TileListener;
import org.pepsoft.util.swing.TileProvider;
import org.pepsoft.worldpainter.BiomeScheme;
import org.pepsoft.worldpainter.ColourScheme;
import org.pepsoft.worldpainter.biomeschemes.BiomeSchemeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import static org.pepsoft.worldpainter.Constants.*;
import static org.pepsoft.worldpainter.biomeschemes.Minecraft1_17Biomes.*;
/**
*
* @author pepijn
*/
public class BiomesTileProvider implements TileProvider {
public BiomesTileProvider(BiomeScheme biomeScheme, ColourScheme colourScheme) {
this(biomeScheme, colourScheme, 2, false);
}
public BiomesTileProvider(BiomeScheme biomeScheme, ColourScheme colourScheme, int zoom, boolean fade) {
this.biomeScheme = biomeScheme;
this.colourScheme = colourScheme;
this.zoom = zoom;
this.fade = fade;
patternColour = fade ? 0xff808080 : 0xff000000;
init();
}
public BiomesTileProvider(int biomeAlgorithm, long minecraftSeed, ColourScheme colourScheme, int zoom, boolean fade) {
this.biomeAlgorithm = biomeAlgorithm;
this.colourScheme = colourScheme;
this.minecraftSeed = minecraftSeed;
this.zoom = zoom;
this.fade = fade;
patternColour = fade ? 0xff808080 : 0xff000000;
}
@Override
public int getTileSize() {
return TILE_SIZE;
}
@Override
public boolean isZoomSupported() {
return true;
}
@Override
public int getZoom() {
return zoom;
}
@Override
public void setZoom(int zoom) {
if (zoom != this.zoom) {
if (zoom > 0) {
throw new UnsupportedOperationException("Zooming in not supported");
}
this.zoom = zoom;
bufferRef = new ThreadLocal<>();
}
}
@Override
public boolean isTilePresent(int x, int y) {
return enabled;
}
@Override
public boolean paintTile(Image image, int tileX, int tileY, int imageX, int imageY) {
if (! enabled) {
return false;
}
try {
BiomeScheme biomeScheme = getBiomeScheme();
if (biomeScheme == null) {
return false;
}
final int scale = 1 << -zoom;
int[] buffer = bufferRef.get();
if (buffer == null) {
buffer = new int[TILE_SIZE * TILE_SIZE * scale * scale];
bufferRef.set(buffer);
}
biomeScheme.getBiomes(tileX * TILE_SIZE * scale, tileY * TILE_SIZE * scale, TILE_SIZE * scale, TILE_SIZE * scale, buffer);
BufferedImage tile = renderBufferRef.get();
int[][] biomeCounts = biomeCountsRef.get();
if (biomeCounts == null) {
biomeCounts = new int[][] {new int[256], new int[256], new int[256]};
biomeCountsRef.set(biomeCounts);
}
for (int x = 0; x < TILE_SIZE; x++) {
for (int y = 0; y < TILE_SIZE; y++) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < biomeCounts[i].length; j++) {
biomeCounts[i][j] = 0;
}
}
for (int dx = 0; dx < scale; dx++) {
for (int dz = 0; dz < scale; dz++) {
int biome = buffer[x * scale + dx + (y * scale + dz) * TILE_SIZE * scale];
biomeCounts[BIOME_PRIORITIES[biome]][biome]++;
}
}
int mostCommonBiome = -1;
for (int i = 2; i >= 0; i--) {
int mostCommonBiomeCount = 0;
for (int j = 0; j < biomeCounts[i].length; j++) {
if (biomeCounts[i][j] > mostCommonBiomeCount) {
mostCommonBiome = j;
mostCommonBiomeCount = biomeCounts[i][j];
}
}
if (mostCommonBiome != -1) {
break;
}
}
if ((biomePatterns[mostCommonBiome] != null) && (biomePatterns[mostCommonBiome][x % 16][y % 16])) {
tile.setRGB(x, y, patternColour);
} else {
tile.setRGB(x, y, biomeColours[mostCommonBiome]);
}
}
}
Graphics2D g2 = (Graphics2D) image.getGraphics();
try {
g2.drawImage(tile, imageX, imageY, null);
} finally {
g2.dispose();
}
} catch (Throwable t) {
logger.error("Exception while generating image for tile at {}, {}", tileX, tileY, t);
}
return true;
}
@Override
public int getTilePriority(int x, int y) {
return 0; // All tiles have equal priority
}
@Override
public Rectangle getExtent() {
return null;
}
@Override
public void addTileListener(TileListener tileListener) {
// Do nothing (tiles never change)
}
@Override
public void removeTileListener(TileListener tileListener) {
// Do nothing (tiles never change)
}
private synchronized BiomeScheme getBiomeScheme() {
if (biomeScheme == null) {
try {
biomeScheme = BiomeSchemeManager.getSharedBiomeScheme(biomeAlgorithm);
if (biomeScheme == null) {
switch (biomeAlgorithm) {
case BIOME_ALGORITHM_1_7_DEFAULT:
biomeScheme = BiomeSchemeManager.getSharedBiomeScheme(BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT);
break;
case BIOME_ALGORITHM_1_7_LARGE:
biomeScheme = BiomeSchemeManager.getSharedBiomeScheme(BIOME_ALGORITHM_1_3_LARGE);
break;
}
}
} catch (Exception e) {
// TODO: this seems to happen with the Minecraft 1.6 jar
// Why?
logger.error("An exception occurred while trying to load or initialize Minecraft jar; continuing without showing biomes", e);
} catch (Error e) {
// TODO: this seems to happen with the Minecraft 1.6 jar
// Why?
logger.error("An error occurred while trying to load or initialize Minecraft jar; continuing without showing biomes", e);
}
if (biomeScheme != null) {
biomeScheme.setSeed(minecraftSeed);
init();
} else {
enabled = false;
}
}
return biomeScheme;
}
private void init() {
int biomeCount = biomeScheme.getBiomeCount();
biomeColours = new int[biomeCount];
biomePatterns = new boolean[biomeCount][][];
for (int i = 0; i < biomeCount; i++) {
if (biomeScheme.isBiomePresent(i)) {
biomeColours[i] = 0xff000000 | (fade ? ColourUtils.mix(0xffffff, biomeScheme.getColour(i, colourScheme)) : biomeScheme.getColour(i, colourScheme));
biomePatterns[i] = biomeScheme.getPattern(i);
}
}
}
private final ColourScheme colourScheme;
private int biomeAlgorithm;
private long minecraftSeed;
private final ThreadLocal biomeCountsRef = new ThreadLocal<>();
private final int patternColour;
private final boolean fade;
private BiomeScheme biomeScheme;
private int zoom;
private volatile ThreadLocal bufferRef = new ThreadLocal<>();
private int[] biomeColours;
private boolean[][][] biomePatterns;
private volatile boolean enabled = true;
private static final ThreadLocal renderBufferRef = new ThreadLocal() {
@Override
protected BufferedImage initialValue() {
return new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_ARGB);
}
};
private static final Logger logger = LoggerFactory.getLogger(BiomesTileProvider.class);
private static final int[] BIOME_PRIORITIES = new int[256];
static {
// Every biome should have medium priority except the exceptions below
Arrays.fill(BIOME_PRIORITIES, 1);
// Ocean should have low priority:
BIOME_PRIORITIES[BIOME_OCEAN] = 0;
BIOME_PRIORITIES[BIOME_FROZEN_OCEAN] = 0;
BIOME_PRIORITIES[BIOME_DEEP_OCEAN] = 0;
// River should have high priority
BIOME_PRIORITIES[BIOME_RIVER] = 2;
BIOME_PRIORITIES[BIOME_FROZEN_RIVER] = 2;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy