/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.biomeschemes;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import org.pepsoft.util.Checksum;
import org.pepsoft.util.FileUtils;
import org.pepsoft.worldpainter.BiomeScheme;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An abstract base class for {@link BiomeScheme}s which can invoke Minecraft
* code from a Minecraft jar file for version 1.8 and later to calculate biomes.
*
* @author pepijn
*/
public abstract class Minecraft1_8JarBiomeScheme extends AbstractMinecraft1_7BiomeScheme {
public Minecraft1_8JarBiomeScheme(File minecraftJar, File libDir, Checksum md5Sum, Map<Checksum, String[]> hashesToClassNames) {
if (logger.isDebugEnabled()) {
logger.debug("Creating biome scheme using Minecraft jar {}", minecraftJar);
}
if (md5Sum == null) {
try {
md5Sum = FileUtils.getMD5(minecraftJar);
} catch (IOException e) {
throw new RuntimeException("I/O error calculating hash for " + minecraftJar, e);
}
}
try {
init(hashesToClassNames.get(md5Sum), getClassLoader(minecraftJar, libDir));
} catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException e) {
throw new RuntimeException("Not a valid minecraft.jar of the correct version", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Access denied while trying to initialise Minecraft", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Exception thrown while trying to initialise Minecraft", e);
}
}
@Override
public void setSeed(long seed) {
if ((landscape == null) || (seed != this.seed)) {
try {
landscape = ((Object[]) getLandscapesMethod.invoke(null, seed, null, null))[1];
this.seed = seed;
} catch (IllegalAccessException e) {
throw new RuntimeException("Access denied while trying to set the seed", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Exception thrown while trying to set the seed", e);
}
}
}
@Override
public final synchronized void getBiomes(int x, int y, int width, int height, int[] buffer) {
try {
int[] biomes = (int[]) getBiomesMethod.invoke(landscape, x, y, width, height);
clearBuffersMethod.invoke(null);
System.arraycopy(biomes, 0, buffer, 0, Math.min(biomes.length, buffer.length));
} catch (IllegalAccessException e) {
throw new RuntimeException("Access denied while trying to calculate biomes", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Exception thrown while trying to calculate biomes", e);
}
}
protected void init(String[] classNames, ClassLoader classLoader) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
String landscapeClassName = classNames[0];
String bufferManagerClassName = classNames[1];
String worldGeneratorClassName = classNames[2];
String initClassName = classNames[3];
Class<?> landscapeClass = classLoader.loadClass(landscapeClassName);
worldGeneratorClass = classLoader.loadClass(worldGeneratorClassName);
getLandscapesMethod = landscapeClass.getMethod("a", long.class, worldGeneratorClass, String.class);
getBiomesMethod = landscapeClass.getMethod("a", int.class, int.class, int.class, int.class);
Class<?> bufferManagerClass = classLoader.loadClass(bufferManagerClassName);
clearBuffersMethod = bufferManagerClass.getMethod("a");
// Initialise Minecraft
Class<?> initClass = classLoader.loadClass(initClassName);
Method initMethod = initClass.getMethod("c");
initMethod.invoke(null);
}
Class<?> worldGeneratorClass;
Method getLandscapesMethod, getBiomesMethod, clearBuffersMethod;
Object landscape;
long seed = Long.MIN_VALUE;
private static final Logger logger = LoggerFactory.getLogger(Minecraft1_8JarBiomeScheme.class);
}