amidstest/src/main/java/amidst/mojangapi/world/oracle/BiomeDataOracle.java

182 lines
6.1 KiB
Java

package amidst.mojangapi.world.oracle;
import java.util.List;
import java.util.Random;
import amidst.documentation.ThreadSafe;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.minecraftinterface.MinecraftInterface;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.biome.UnknownBiomeIndexException;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
import amidst.mojangapi.world.coordinates.Resolution;
import amidst.fragment.IBiomeDataOracle;
@ThreadSafe
public class BiomeDataOracle implements IBiomeDataOracle {
private final MinecraftInterface minecraftInterface;
public BiomeDataOracle(MinecraftInterface minecraftInterface) {
this.minecraftInterface = minecraftInterface;
}
public short populateArray(CoordinatesInWorld corner, short[][] result, boolean useQuarterResolution) {
Resolution resolution = Resolution.from(useQuarterResolution);
int width = result.length;
if (width > 0) {
int height = result[0].length;
int left = (int) corner.getXAs(resolution);
int top = (int) corner.getYAs(resolution);
try {
copyToResult(result, width, height, getBiomeData(left, top, width, height, useQuarterResolution));
} catch (MinecraftInterfaceException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
}
}
return (short)0xffff;
}
public static void copyToResult(short[][] result, int width, int height, int[] biomeData) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
result[x][y] = (short) biomeData[getBiomeDataIndex(x, y, width)];
}
}
}
public static int getBiomeDataIndex(int x, int y, int width) {
return x + y * width;
}
public boolean isValidBiomeAtMiddleOfChunk(int chunkX, int chunkY, List<Biome> validBiomes) {
return isValidBiome(getMiddleOfChunk(chunkX), getMiddleOfChunk(chunkY), validBiomes);
}
private boolean isValidBiome(int x, int y, List<Biome> validBiomes) {
try {
return validBiomes.contains(getBiomeAt(x, y));
} catch (UnknownBiomeIndexException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
} catch (MinecraftInterfaceException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
}
}
public boolean isValidBiomeForStructureAtMiddleOfChunk(int chunkX, int chunkY, int size, List<Biome> validBiomes) {
return isValidBiomeForStructure(getMiddleOfChunk(chunkX), getMiddleOfChunk(chunkY), size, validBiomes);
}
public boolean isValidBiomeForStructure(int x, int y, int size, List<Biome> validBiomes) {
int left = x - size >> 2;
int top = y - size >> 2;
int right = x + size >> 2;
int bottom = y + size >> 2;
int width = right - left + 1;
int height = bottom - top + 1;
try {
int[] biomeData = getQuarterResolutionBiomeData(left, top, width, height);
for (int i = 0; i < width * height; i++) {
if (!validBiomes.contains(Biome.getByIndex(biomeData[i]))) {
return false;
}
}
return true;
} catch (UnknownBiomeIndexException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
} catch (MinecraftInterfaceException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
}
}
public CoordinatesInWorld findValidLocationAtMiddleOfChunk(
int chunkX,
int chunkY,
int size,
List<Biome> validBiomes,
Random random) {
return findValidLocation(getMiddleOfChunk(chunkX), getMiddleOfChunk(chunkY), size, validBiomes, random);
}
// TODO: Find out if we should useQuarterResolution or not
public CoordinatesInWorld findValidLocation(int x, int y, int size, List<Biome> validBiomes, Random random) {
int left = x - size >> 2;
int top = y - size >> 2;
int right = x + size >> 2;
int bottom = y + size >> 2;
int width = right - left + 1;
int height = bottom - top + 1;
try {
int[] biomeData = getQuarterResolutionBiomeData(left, top, width, height);
CoordinatesInWorld result = null;
int numberOfValidLocations = 0;
for (int i = 0; i < width * height; i++) {
if (validBiomes.contains(Biome.getByIndex(biomeData[i]))
&& (result == null || random.nextInt(numberOfValidLocations + 1) == 0)) {
result = createCoordinates(left, top, width, i);
numberOfValidLocations++;
}
}
return result;
} catch (UnknownBiomeIndexException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
} catch (MinecraftInterfaceException e) {
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
}
}
private CoordinatesInWorld createCoordinates(int left, int top, int width, int i) {
int x = left + i % width << 2;
int y = top + i / width << 2;
return CoordinatesInWorld.from(x, y);
}
private int getMiddleOfChunk(int coordinate) {
return coordinate * 16 + 8;
}
public Biome getBiomeAtMiddleOfChunk(int chunkX, int chunkY)
throws UnknownBiomeIndexException,
MinecraftInterfaceException {
return getBiomeAt(getMiddleOfChunk(chunkX), getMiddleOfChunk(chunkY));
}
/**
* Gets the biome located at the block-coordinates. This is not a fast
* routine, it was added for rare things like accurately testing structures.
* (uses the 1:1 scale biome-map)
*/
private Biome getBiomeAt(int x, int y) throws UnknownBiomeIndexException, MinecraftInterfaceException {
int[] biomeData = getFullResolutionBiomeData(x, y, 1, 1);
return Biome.getByIndex(biomeData[0]);
}
private int[] getQuarterResolutionBiomeData(int x, int y, int width, int height)
throws MinecraftInterfaceException {
return getBiomeData(x, y, width, height, true);
}
private int[] getFullResolutionBiomeData(int x, int y, int width, int height) throws MinecraftInterfaceException {
return getBiomeData(x, y, width, height, false);
}
private int[] getBiomeData(int x, int y, int width, int height, boolean useQuarterResolution)
throws MinecraftInterfaceException {
return minecraftInterface.getBiomeData(x, y, width, height, useQuarterResolution);
}
}