157 lines
6.2 KiB
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;
|
|
}
|
|
}
|