| package net.glowstone.generator.biomegrid; |
| |
| import static org.bukkit.block.Biome.BADLANDS; |
| import static org.bukkit.block.Biome.BADLANDS_PLATEAU; |
| import static org.bukkit.block.Biome.BIRCH_FOREST; |
| import static org.bukkit.block.Biome.BIRCH_FOREST_HILLS; |
| import static org.bukkit.block.Biome.DARK_FOREST; |
| import static org.bukkit.block.Biome.DEEP_OCEAN; |
| import static org.bukkit.block.Biome.DESERT; |
| import static org.bukkit.block.Biome.DESERT_HILLS; |
| import static org.bukkit.block.Biome.FOREST; |
| import static org.bukkit.block.Biome.GIANT_TREE_TAIGA; |
| import static org.bukkit.block.Biome.GIANT_TREE_TAIGA_HILLS; |
| import static org.bukkit.block.Biome.JUNGLE; |
| import static org.bukkit.block.Biome.JUNGLE_HILLS; |
| import static org.bukkit.block.Biome.MOUNTAINS; |
| import static org.bukkit.block.Biome.OCEAN; |
| import static org.bukkit.block.Biome.PLAINS; |
| import static org.bukkit.block.Biome.SAVANNA; |
| import static org.bukkit.block.Biome.SAVANNA_PLATEAU; |
| import static org.bukkit.block.Biome.SNOWY_MOUNTAINS; |
| import static org.bukkit.block.Biome.SNOWY_TAIGA; |
| import static org.bukkit.block.Biome.SNOWY_TAIGA_HILLS; |
| import static org.bukkit.block.Biome.SNOWY_TUNDRA; |
| import static org.bukkit.block.Biome.TAIGA; |
| import static org.bukkit.block.Biome.TAIGA_HILLS; |
| import static org.bukkit.block.Biome.WOODED_BADLANDS_PLATEAU; |
| import static org.bukkit.block.Biome.WOODED_HILLS; |
| import static org.bukkit.block.Biome.WOODED_MOUNTAINS; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import net.glowstone.constants.GlowBiome; |
| |
| public class BiomeVariationMapLayer extends MapLayer { |
| |
| private static final int[] ISLANDS = new int[]{GlowBiome.getId(PLAINS), |
| GlowBiome.getId(FOREST)}; |
| private static final Map<Integer, int[]> VARIATIONS = new HashMap<>(); |
| |
| static { |
| VARIATIONS.put(GlowBiome.getId(DESERT), new int[]{GlowBiome.getId(DESERT_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(FOREST), new int[]{GlowBiome.getId(WOODED_HILLS)}); |
| VARIATIONS |
| .put(GlowBiome.getId(BIRCH_FOREST), new int[]{GlowBiome.getId(BIRCH_FOREST_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(DARK_FOREST), new int[]{GlowBiome.getId(PLAINS)}); |
| VARIATIONS.put(GlowBiome.getId(TAIGA), new int[]{GlowBiome.getId(TAIGA_HILLS)}); |
| VARIATIONS |
| .put(GlowBiome.getId(GIANT_TREE_TAIGA), new int[]{GlowBiome.getId(GIANT_TREE_TAIGA_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(SNOWY_TAIGA), new int[]{GlowBiome.getId(SNOWY_TAIGA_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(PLAINS), |
| new int[]{GlowBiome.getId(FOREST), GlowBiome.getId(FOREST), |
| GlowBiome.getId(WOODED_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(SNOWY_TUNDRA), new int[]{GlowBiome.getId(SNOWY_MOUNTAINS)}); |
| VARIATIONS.put(GlowBiome.getId(JUNGLE), new int[]{GlowBiome.getId(JUNGLE_HILLS)}); |
| VARIATIONS.put(GlowBiome.getId(OCEAN), new int[]{GlowBiome.getId(DEEP_OCEAN)}); |
| VARIATIONS.put(GlowBiome.getId(MOUNTAINS), |
| new int[]{GlowBiome.getId(WOODED_MOUNTAINS)}); |
| VARIATIONS.put(GlowBiome.getId(SAVANNA), new int[]{GlowBiome.getId(SAVANNA_PLATEAU)}); |
| VARIATIONS.put(GlowBiome.getId(WOODED_BADLANDS_PLATEAU), new int[]{GlowBiome.getId(BADLANDS)}); |
| VARIATIONS.put(GlowBiome.getId(BADLANDS_PLATEAU), new int[]{GlowBiome.getId(BADLANDS)}); |
| VARIATIONS.put(GlowBiome.getId(BADLANDS), new int[]{GlowBiome.getId(BADLANDS)}); |
| } |
| |
| private final MapLayer belowLayer; |
| private final MapLayer variationLayer; |
| |
| /** |
| * Creates an instance with no variation layer. |
| * @param seed the PRNG seed |
| * @param belowLayer the layer below this one |
| */ |
| public BiomeVariationMapLayer(long seed, MapLayer belowLayer) { |
| this(seed, belowLayer, null); |
| } |
| |
| /** |
| * Creates an instance with the given variation layer. |
| * @param seed the PRNG seed |
| * @param belowLayer the layer below this one |
| * @param variationLayer the variation layer, or null to use no variation layer |
| */ |
| public BiomeVariationMapLayer(long seed, MapLayer belowLayer, MapLayer variationLayer) { |
| super(seed); |
| this.belowLayer = belowLayer; |
| this.variationLayer = variationLayer; |
| } |
| |
| @Override |
| public int[] generateValues(int x, int z, int sizeX, int sizeZ) { |
| if (variationLayer == null) { |
| return generateRandomValues(x, z, sizeX, sizeZ); |
| } |
| return mergeValues(x, z, sizeX, sizeZ); |
| } |
| |
| /** |
| * Generates a rectangle, replacing all the positive values in the previous layer with random |
| * values from 2 to 31 while leaving zero and negative values unchanged. |
| * |
| * @param x the lowest x coordinate |
| * @param z the lowest z coordinate |
| * @param sizeX the x coordinate range |
| * @param sizeZ the z coordinate range |
| * @return a flattened array of generated values |
| */ |
| public int[] generateRandomValues(int x, int z, int sizeX, int sizeZ) { |
| int[] values = belowLayer.generateValues(x, z, sizeX, sizeZ); |
| |
| int[] finalValues = new int[sizeX * sizeZ]; |
| for (int i = 0; i < sizeZ; i++) { |
| for (int j = 0; j < sizeX; j++) { |
| int val = values[j + i * sizeX]; |
| if (val > 0) { |
| setCoordsSeed(x + j, z + i); |
| val = nextInt(30) + 2; |
| } |
| finalValues[j + i * sizeX] = val; |
| } |
| } |
| return finalValues; |
| } |
| |
| /** |
| * Generates a rectangle using the previous layer and the variation layer. |
| * |
| * @param x the lowest x coordinate |
| * @param z the lowest z coordinate |
| * @param sizeX the x coordinate range |
| * @param sizeZ the z coordinate range |
| * @return a flattened array of generated values |
| */ |
| public int[] mergeValues(int x, int z, int sizeX, int sizeZ) { |
| int gridX = x - 1; |
| int gridZ = z - 1; |
| int gridSizeX = sizeX + 2; |
| int gridSizeZ = sizeZ + 2; |
| |
| int[] values = belowLayer.generateValues(gridX, gridZ, gridSizeX, gridSizeZ); |
| int[] variationValues = variationLayer.generateValues(gridX, gridZ, gridSizeX, gridSizeZ); |
| |
| int[] finalValues = new int[sizeX * sizeZ]; |
| for (int i = 0; i < sizeZ; i++) { |
| for (int j = 0; j < sizeX; j++) { |
| setCoordsSeed(x + j, z + i); |
| int centerValue = values[j + 1 + (i + 1) * gridSizeX]; |
| int variationValue = variationValues[j + 1 + (i + 1) * gridSizeX]; |
| if (centerValue != 0 && variationValue == 3 && centerValue < 128) { |
| finalValues[j + i * sizeX] = |
| GlowBiome.getBiome(centerValue + 128) != null ? centerValue + 128 |
| : centerValue; |
| } else if (variationValue == 2 || nextInt(3) == 0) { |
| int val = centerValue; |
| if (VARIATIONS.containsKey(centerValue)) { |
| val = VARIATIONS.get(centerValue)[nextInt( |
| VARIATIONS.get(centerValue).length)]; |
| } else if (centerValue == GlowBiome.getId(DEEP_OCEAN) && nextInt(3) == 0) { |
| val = ISLANDS[nextInt(ISLANDS.length)]; |
| } |
| if (variationValue == 2 && val != centerValue) { |
| val = GlowBiome.getBiome(val + 128) != null ? val + 128 : centerValue; |
| } |
| if (val != centerValue) { |
| int count = 0; |
| if (values[j + 1 + i * gridSizeX] == centerValue) { // upper value |
| count++; |
| } |
| if (values[j + 1 + (i + 2) * gridSizeX] == centerValue) { // lower value |
| count++; |
| } |
| if (values[j + (i + 1) * gridSizeX] == centerValue) { // left value |
| count++; |
| } |
| if (values[j + 2 + (i + 1) * gridSizeX] == centerValue) { // right value |
| count++; |
| } |
| // spread mountains if not too close from an edge |
| finalValues[j + i * sizeX] = count < 3 ? centerValue : val; |
| } else { |
| finalValues[j + i * sizeX] = val; |
| } |
| } else { |
| finalValues[j + i * sizeX] = centerValue; |
| } |
| } |
| } |
| return finalValues; |
| } |
| } |