182 lines
6.1 KiB
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);
|
|
}
|
|
}
|