amidstest/src/main/java/amidst/mojangapi/minecraftinterface/local/LocalMinecraftInterface.java

157 lines
6.2 KiB
Java

package amidst.mojangapi.minecraftinterface.local;
import java.lang.reflect.InvocationTargetException;
import amidst.clazz.symbolic.SymbolicClass;
import amidst.clazz.symbolic.SymbolicObject;
import amidst.clazz.translator.ClassTranslator;
import amidst.documentation.ThreadSafe;
import amidst.gameengineabstraction.GameEngineType;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.LauncherProfile;
import amidst.mojangapi.minecraftinterface.MinecraftInterface;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.minecraftinterface.RecognisedVersion;
import amidst.mojangapi.world.WorldType;
@ThreadSafe
public class LocalMinecraftInterface implements MinecraftInterface {
public static LocalMinecraftInterface create(ClassTranslator translator, LauncherProfile launcherProfile)
throws LocalMinecraftInterfaceCreationException {
return new LocalMinecraftInterfaceBuilder(translator).create(launcherProfile);
}
/**
* A GenLayer instance, at quarter scale to the final biome layer (i.e. both
* axis are divided by 4). Minecraft calculates biomes at
* quarter-resolution, then noisily interpolates the biome-map up to 1:1
* resolution when needed, this is the biome GenLayer before it is
* interpolated.
*/
private volatile SymbolicObject quarterResolutionBiomeGenerator;
/**
* A GenLayer instance, the biome layer. (1:1 scale) Minecraft calculates
* biomes at quarter-resolution, then noisily interpolates the biome-map up
* to 1:1 resolution when needed, this is the interpolated biome GenLayer.
*/
private volatile SymbolicObject fullResolutionBiomeGenerator;
private final SymbolicClass intCacheClass;
private final SymbolicClass blockInitClass;
private final SymbolicClass genLayerClass;
private final SymbolicClass worldTypeClass;
private final SymbolicClass genOptionsFactoryClass;
private final RecognisedVersion recognisedVersion;
LocalMinecraftInterface(
SymbolicClass intCacheClass,
SymbolicClass blockInitClass,
SymbolicClass genLayerClass,
SymbolicClass worldTypeClass,
SymbolicClass genOptionsFactoryClass,
RecognisedVersion recognisedVersion) {
this.intCacheClass = intCacheClass;
this.blockInitClass = blockInitClass;
this.genLayerClass = genLayerClass;
this.worldTypeClass = worldTypeClass;
this.genOptionsFactoryClass = genOptionsFactoryClass;
this.recognisedVersion = recognisedVersion;
}
@Override
public synchronized int[] getBiomeData(int x, int y, int width, int height, boolean useQuarterResolution)
throws MinecraftInterfaceException {
try {
intCacheClass.callStaticMethod(SymbolicNames.METHOD_INT_CACHE_RESET_INT_CACHE);
return (int[]) getBiomeGenerator(useQuarterResolution)
.callMethod(SymbolicNames.METHOD_GEN_LAYER_GET_INTS, x, y, width, height);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new MinecraftInterfaceException("unable to get biome data", e);
}
}
private SymbolicObject getBiomeGenerator(boolean useQuarterResolution) {
if (useQuarterResolution) {
return quarterResolutionBiomeGenerator;
} else {
return fullResolutionBiomeGenerator;
}
}
@Override
public synchronized void createWorld(long seed, WorldType worldType, String generatorOptions)
throws MinecraftInterfaceException {
try {
AmidstLogger.info("Creating world with seed '" + seed + "' and type '" + worldType.getName() + "'");
AmidstLogger.info("Using the following generator options: " + generatorOptions);
initializeBlock();
Object[] genLayers = getGenLayers(seed, worldType, generatorOptions);
quarterResolutionBiomeGenerator = new SymbolicObject(genLayerClass, genLayers[0]);
fullResolutionBiomeGenerator = new SymbolicObject(genLayerClass, genLayers[1]);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new MinecraftInterfaceException("unable to create world", e);
}
}
/**
* Minecraft 1.8 and higher require block initialization to be called before
* creating a biome generator.
*/
private void initializeBlock() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (blockInitClass != null) {
blockInitClass.callStaticMethod(SymbolicNames.METHOD_BLOCK_INIT_INITIALIZE);
}
}
private Object[] getGenLayers(long seed, WorldType worldType, String generatorOptions)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException {
if (worldTypeClass == null) {
return (Object[]) genLayerClass
.callStaticMethod(SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_1, seed);
} else if (genLayerClass.hasMethod(SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_4)) {
return (Object[]) genLayerClass.callStaticMethod(
SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_4,
seed,
getWorldType(worldType).getObject(),
getGeneratorOptions(generatorOptions).getObject());
} else if (genLayerClass.hasMethod(SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_3)) {
return (Object[]) genLayerClass.callStaticMethod(
SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_3,
seed,
getWorldType(worldType).getObject(),
generatorOptions);
} else {
return (Object[]) genLayerClass.callStaticMethod(
SymbolicNames.METHOD_GEN_LAYER_INITIALIZE_ALL_BIOME_GENERATORS_2,
seed,
getWorldType(worldType).getObject());
}
}
private SymbolicObject getGeneratorOptions(String generatorOptions)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException {
SymbolicObject factory = (SymbolicObject) genOptionsFactoryClass
.callStaticMethod(SymbolicNames.METHOD_GEN_OPTIONS_FACTORY_JSON_TO_FACTORY, generatorOptions);
return (SymbolicObject) factory.callMethod(SymbolicNames.METHOD_GEN_OPTIONS_FACTORY_BUILD);
}
private SymbolicObject getWorldType(WorldType worldType) throws IllegalArgumentException, IllegalAccessException {
return (SymbolicObject) worldTypeClass.getStaticFieldValue(worldType.getSymbolicFieldName());
}
@Override
public RecognisedVersion getRecognisedVersion() {
return recognisedVersion;
}
@Override
public GameEngineType getGameEngineType() {
return GameEngineType.MINECRAFT;
}
}