/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.pepsoft.worldpainter.biomeschemes; import org.pepsoft.util.Checksum; import org.pepsoft.util.FileUtils; import org.pepsoft.util.GUIUtils; import org.pepsoft.util.Version; import org.pepsoft.worldpainter.BiomeScheme; import org.pepsoft.worldpainter.ColourScheme; import org.pepsoft.worldpainter.Configuration; import org.pepsoft.worldpainter.util.MinecraftUtil; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.stream.Collectors; import static org.pepsoft.worldpainter.Constants.*; /** * * @author pepijn */ public class BiomeSchemeManager { public static BiomeScheme getNewBiomeScheme(final int biomeAlgorithm) { return getBiomeScheme(biomeAlgorithm, false); } public static BiomeScheme getSharedBiomeScheme(final int biomeAlgorithm) { return getBiomeScheme(biomeAlgorithm, true); } public static BiomeScheme getBiomeScheme(final int biomeAlgorithm, final boolean shared) { if (logger.isTraceEnabled()) { logger.trace("Thread {} requesting biome scheme {}", Thread.currentThread().getName(), biomeAlgorithm, new Throwable("Invoked from")); } synchronized (initialisationLock) { if (! initialised) { initialise(); } } if (shared && BIOME_SCHEMES.containsKey(biomeAlgorithm)) { // We already previously found and initialised a biome scheme for // this algorithm, so reuse it return BIOME_SCHEMES.get(biomeAlgorithm); } else { final String version; switch (biomeAlgorithm) { case BIOME_ALGORITHM_1_1: version = "1.1"; break; case BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT: version = "1.6.4 or 1.2.3 - 1.6.2"; break; case BIOME_ALGORITHM_1_3_LARGE: version = "1.6.4 or 1.3.1 - 1.6.2"; break; case BIOME_ALGORITHM_1_7_DEFAULT: version = "1.10.2 or 1.7.2 - 1.9"; break; case BIOME_ALGORITHM_1_7_LARGE: version = "1.10.2 or 1.7.2 - 1.9"; break; default: throw new IllegalArgumentException(); } SortedMap<Version, BiomeJar> biomeJars = BIOME_JARS.get(biomeAlgorithm); if ((biomeJars != null) && (! biomeJars.isEmpty())) { // We have a jar for this biome scheme final BiomeJar biomeJar = biomeJars.get(biomeJars.lastKey()); logger.info("Creating biome scheme " + version + " from " + biomeJar.file.getAbsolutePath()); BiomeScheme biomeScheme = biomeJar.descriptor.instantiate(biomeJar.file, minecraftDir, biomeJar.checksum); BIOME_SCHEMES.put(biomeAlgorithm, biomeScheme); return biomeScheme; } else { logger.info("Could not find compatible jar for biome scheme " + version); return null; } } } /** * Get all found Minecraft jars. * * @return All found Minecraft jars. */ public static SortedMap<Version, File> getAllMinecraftJars() { synchronized (initialisationLock) { if (! initialised) { initialise(); } } return Collections.unmodifiableSortedMap(ALL_JARS); } public static BufferedImage createImage(BiomeScheme biomeScheme, int biome, ColourScheme colourScheme) { int backgroundColour = biomeScheme.getColour(biome, colourScheme); boolean[][] pattern = biomeScheme.getPattern(biome); BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { if ((pattern != null) && pattern[x][y]) { image.setRGB(x, y, 0); } else { image.setRGB(x, y, backgroundColour); } } } return GUIUtils.scaleToUI(image); } public static List<Integer> getAvailableBiomeAlgorithms() { synchronized (initialisationLock) { if (! initialised) { initialise(); } } List<Integer> availableBiomeAlgorithms = new ArrayList<>(BIOME_JARS.keySet()); Collections.sort(availableBiomeAlgorithms, Comparator.reverseOrder()); return availableBiomeAlgorithms; } /** * Starts background initialisation of the biome scheme manager, so that * subsequent invocations of the <code>getSharedBiomeScheme</code> methods won't * have to wait for initialisation. */ public static void initialiseInBackground() { synchronized (initialisationLock) { if (initialised || initialising) { return; } initialising = true; new Thread(() -> { try { doInitialisation(); } catch (Throwable t) { logger.error(t.getClass().getSimpleName() + " while scanning for Minecraft jars", t); } }, "Biome Scheme Manager Initialiser").start(); } } private static void scanDir(File dir) { File[] files = dir.listFiles(pathname -> pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".jar")); // files can only be null if dir does not exist or is not a directory, // which really should not be possible, but we've had reports from the // wild that it does, so check for it if (files != null) { for (File file: files) { try { if (file.getName().toLowerCase().contains("optifine")) { // Skip anything OptiFine-related, as OptiFine creates Minecraft profiles with invalid json files. continue; } if (file.isDirectory()) { scanDir(file); } else { if (logger.isTraceEnabled()) { logger.trace("Scanning file {}", file); } Checksum hash = FileUtils.getMD5(file); if (DESCRIPTORS.containsKey(hash)) { for (BiomeSchemeDescriptor descriptor: DESCRIPTORS.get(hash)) { SortedMap<Version, BiomeJar> jars = BIOME_JARS.get(descriptor.biomeScheme); if (jars == null) { jars = new TreeMap<>(); BIOME_JARS.put(descriptor.biomeScheme, jars); } jars.put(descriptor.minecraftVersion, new BiomeJar(file, hash, descriptor)); // Also store it as a resources jar ALL_JARS.put(descriptor.minecraftVersion, file); } } else { // It's not a supported jar, but see if the filename is // just a version number so that we can assume it's a // Minecraft jar we can at least use for loading // resources try { Version version = Version.parse(file.getName().substring(0, file.getName().length() - 4)); ALL_JARS.put(version, file); } catch (NumberFormatException e) { // Skip silently } } } } catch (IOException e) { logger.error("I/O error while scanning potential Minecraft jar or directory " + file.getAbsolutePath() + "; skipping file", e); } } } } private static void initialise() { synchronized (initialisationLock) { if (initialised) { return; } else if (initialising) { if (logger.isDebugEnabled()) { logger.debug("Thread {} waiting for another thread to finish initialisation", Thread.currentThread().getName()); } // Another thread is initialising us; wait for it to finish while (initialising) { try { initialisationLock.wait(); } catch (InterruptedException e) { throw new RuntimeException("Thread interrupted while waiting for biome scheme manager initialisation", e); } } if (logger.isDebugEnabled()) { logger.debug("Thread {} continuing", Thread.currentThread().getName()); } return; } else { doInitialisation(); } } } private static void doInitialisation() { synchronized (initialisationLock) { if (logger.isDebugEnabled()) { logger.debug("Performing initialisation on thread {}", Thread.currentThread().getName()); } try { // Scan the Minecraft directory for supported jars minecraftDir = MinecraftUtil.findMinecraftDir(); if (minecraftDir != null) { scanDir(new File(minecraftDir, "bin")); scanDir(new File(minecraftDir, "versions")); } // Collect the names of the files we already looked at so we can skip // them below Set<File> processedFiles = new HashSet<>(); for (Map.Entry<Integer, SortedMap<Version, BiomeJar>> entry: BIOME_JARS.entrySet()) { processedFiles.addAll(entry.getValue().values().stream().map(biomeJar -> biomeJar.file).collect(Collectors.toList())); } // Check the jars stored in the configuration (if we haven't // encountered them above) Configuration config = Configuration.getInstance(); Map<Integer, File> minecraftJars = config.getMinecraftJars(); for (Iterator<Map.Entry<Integer, File>> i = minecraftJars.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Integer, File> entry = i.next(); File file = entry.getValue(); if (file.getAbsolutePath().toLowerCase().contains("optifine")) { // OptiFine-created files create problems, so filter // them out if the configuration somehow got polluted // with them i.remove(); continue; } else if (processedFiles.contains(file)) { continue; } else if ((! file.isFile()) || (! file.canRead())) { // The file is no longer there, or it's not accessible; // remove it from the configuration i.remove(); continue; } try { Checksum checksum = FileUtils.getMD5(file); if (DESCRIPTORS.containsKey(checksum)) { for (BiomeSchemeDescriptor descriptor: DESCRIPTORS.get(checksum)) { SortedMap<Version, BiomeJar> jars = BIOME_JARS.computeIfAbsent(descriptor.biomeScheme, key -> new TreeMap<>()); jars.put(descriptor.minecraftVersion, new BiomeJar(file, checksum, descriptor)); // Also store it as a resources jar ALL_JARS.put(descriptor.minecraftVersion, file); } } else { // It's not a supported jar, but see if the filename is // just a version number so that we can assume it's a // Minecraft jar we can at least use for loading // resources try { Version version = Version.parse(file.getName().substring(0, file.getName().length() - 4)); ALL_JARS.put(version, file); } catch (NumberFormatException e) { // We don't recognize this jar. Perhaps it has been // replaced with an unsupported version. In any // case, remove it from the configuration i.remove(); } } } catch (IOException e) { logger.error("I/O error while scanning Minecraft jar " + file.getAbsolutePath() + "; skipping file", e); } } } finally { // Done initialised = true; initialising = false; initialisationLock.notifyAll(); } if (logger.isDebugEnabled()) { logger.debug("Thread {} finished initialisation", Thread.currentThread().getName()); } } } private static final Map<Checksum, Set<BiomeSchemeDescriptor>> DESCRIPTORS = new HashMap<>(); private static final Map<Integer, BiomeScheme> BIOME_SCHEMES = new HashMap<>(); private static final Map<Integer, SortedMap<Version, BiomeJar>> BIOME_JARS = new HashMap<>(); private static final SortedMap<Version, File> ALL_JARS = new TreeMap<>(); private static final Object initialisationLock = new Object(); private static File minecraftDir; private static boolean initialised, initialising; static { addDescriptor(new Checksum(new byte[] {(byte) -23, (byte) 35, (byte) 2, (byte) -46, (byte) -84, (byte) -37, (byte) -89, (byte) -55, (byte) 126, (byte) 13, (byte) -115, (byte) -15, (byte) -31, (byte) 13, (byte) 32, (byte) 6}), new BiomeSchemeDescriptor(new Version(1, 1), BIOME_ALGORITHM_1_1, Minecraft1_1BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 18, (byte) -10, (byte) -60, (byte) -79, (byte) -67, (byte) -52, (byte) 99, (byte) -16, (byte) 41, (byte) -29, (byte) -64, (byte) -120, (byte) -93, (byte) 100, (byte) -72, (byte) -28}), new BiomeSchemeDescriptor(new Version(1, 2, 3), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); // guess addDescriptor(new Checksum(new byte[] {(byte) 37, (byte) 66, (byte) 62, (byte) -85, (byte) 109, (byte) -121, (byte) 7, (byte) -7, (byte) 108, (byte) -58, (byte) -83, (byte) -118, (byte) 33, (byte) -89, (byte) 37, (byte) 10}), new BiomeSchemeDescriptor(new Version(1, 2, 4), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); // guess addDescriptor(new Checksum(new byte[] {(byte) -114, (byte) -121, (byte) 120, (byte) 7, (byte) -118, (byte) 23, (byte) 90, (byte) 51, (byte) 96, (byte) 58, (byte) 88, (byte) 82, (byte) 87, (byte) -14, (byte) -123, (byte) 99}), new BiomeSchemeDescriptor(new Version(1, 2, 5), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); // guess addDescriptor(new Checksum(new byte[] {(byte) 38, (byte) 108, (byte) -53, (byte) -55, (byte) 121, (byte) -118, (byte) -3, (byte) 46, (byte) -83, (byte) -13, (byte) -42, (byte) -64, (byte) 27, (byte) 76, (byte) 86, (byte) 42}), new BiomeSchemeDescriptor(new Version(1, 3, 1), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); // guess addDescriptor(new Checksum(new byte[] {(byte) -106, (byte) -106, (byte) -103, (byte) -15, (byte) 62, (byte) 91, (byte) -66, (byte) 127, (byte) 18, (byte) -28, (byte) 10, (byte) -60, (byte) -13, (byte) 43, (byte) 125, (byte) -102}), new BiomeSchemeDescriptor(new Version(1, 3, 2), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 119, (byte) 17, (byte) 117, (byte) -64, (byte) 23, (byte) 120, (byte) -22, (byte) 103, (byte) 57, (byte) 91, (byte) -58, (byte) -111, (byte) -102, (byte) 90, (byte) -99, (byte) -59}), new BiomeSchemeDescriptor(new Version(1, 4, 2), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) -114, (byte) -128, (byte) -5, (byte) 1, (byte) -77, (byte) 33, (byte) -58, (byte) -77, (byte) -57, (byte) -17, (byte) -54, (byte) 57, (byte) 122, (byte) 62, (byte) -22, (byte) 53}), new BiomeSchemeDescriptor(new Version(1, 4, 7), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 92, (byte) 18, (byte) 25, (byte) -40, (byte) 105, (byte) -72, (byte) 125, (byte) 35, (byte) 61, (byte) -29, (byte) 3, (byte) 54, (byte) -120, (byte) -20, (byte) 117, (byte) 103}), new BiomeSchemeDescriptor(new Version(1, 5, 1), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 104, (byte) -105, (byte) -61, (byte) 40, (byte) 127, (byte) -71, (byte) 113, (byte) -55, (byte) -13, (byte) 98, (byte) -21, (byte) 58, (byte) -78, (byte) 15, (byte) 93, (byte) -35}), new BiomeSchemeDescriptor(new Version(1, 5, 2), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_2BiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) -106, (byte) -106, (byte) -103, (byte) -15, (byte) 62, (byte) 91, (byte) -66, (byte) 127, (byte) 18, (byte) -28, (byte) 10, (byte) -60, (byte) -13, (byte) 43, (byte) 125, (byte) -102}), new BiomeSchemeDescriptor(new Version(1, 3, 2), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_3LargeBiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 119, (byte) 17, (byte) 117, (byte) -64, (byte) 23, (byte) 120, (byte) -22, (byte) 103, (byte) 57, (byte) 91, (byte) -58, (byte) -111, (byte) -102, (byte) 90, (byte) -99, (byte) -59}), new BiomeSchemeDescriptor(new Version(1, 4, 2), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_3LargeBiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) -114, (byte) -128, (byte) -5, (byte) 1, (byte) -77, (byte) 33, (byte) -58, (byte) -77, (byte) -57, (byte) -17, (byte) -54, (byte) 57, (byte) 122, (byte) 62, (byte) -22, (byte) 53}), new BiomeSchemeDescriptor(new Version(1, 4, 7), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_3LargeBiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 92, (byte) 18, (byte) 25, (byte) -40, (byte) 105, (byte) -72, (byte) 125, (byte) 35, (byte) 61, (byte) -29, (byte) 3, (byte) 54, (byte) -120, (byte) -20, (byte) 117, (byte) 103}), new BiomeSchemeDescriptor(new Version(1, 5, 1), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_3LargeBiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 104, (byte) -105, (byte) -61, (byte) 40, (byte) 127, (byte) -71, (byte) 113, (byte) -55, (byte) -13, (byte) 98, (byte) -21, (byte) 58, (byte) -78, (byte) 15, (byte) 93, (byte) -35}), new BiomeSchemeDescriptor(new Version(1, 5, 2), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_3LargeBiomeScheme.class, false)); addDescriptor(new Checksum(new byte[] {(byte) 29, (byte) 67, (byte) -51, (byte) -70, (byte) -117, (byte) -105, (byte) 82, (byte) -41, (byte) -11, (byte) 87, (byte) -85, (byte) 125, (byte) 62, (byte) 54, (byte) 89, (byte) 100}), new BiomeSchemeDescriptor(new Version(1, 6, 2), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_6BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 46, (byte) 80, (byte) 68, (byte) -11, (byte) 53, (byte) -98, (byte) -126, (byte) 36, (byte) 85, (byte) 81, (byte) 22, (byte) 122, (byte) 35, (byte) 127, (byte) 49, (byte) 103}), new BiomeSchemeDescriptor(new Version(1, 6, 4), BIOME_ALGORITHM_1_2_AND_1_3_DEFAULT, Minecraft1_6BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 29, (byte) 67, (byte) -51, (byte) -70, (byte) -117, (byte) -105, (byte) 82, (byte) -41, (byte) -11, (byte) 87, (byte) -85, (byte) 125, (byte) 62, (byte) 54, (byte) 89, (byte) 100}), new BiomeSchemeDescriptor(new Version(1, 6, 2), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_6LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 46, (byte) 80, (byte) 68, (byte) -11, (byte) 53, (byte) -98, (byte) -126, (byte) 36, (byte) 85, (byte) 81, (byte) 22, (byte) 122, (byte) 35, (byte) 127, (byte) 49, (byte) 103}), new BiomeSchemeDescriptor(new Version(1, 6, 4), BIOME_ALGORITHM_1_3_LARGE, Minecraft1_6LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 122, (byte) 48, (byte) 69, (byte) 84, (byte) -3, (byte) -22, (byte) -121, (byte) -102, (byte) 121, (byte) -98, (byte) -2, (byte) 110, (byte) -82, (byte) -35, (byte) -116, (byte) -107}), new BiomeSchemeDescriptor(new Version(1, 7, 2), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_7BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 95, (byte) 124, (byte) -57, (byte) -21, (byte) 1, (byte) -53, (byte) -39, (byte) 53, (byte) -87, (byte) -105, (byte) 60, (byte) -74, (byte) -23, (byte) -60, (byte) -63, (byte) 14}), new BiomeSchemeDescriptor(new Version(1, 7, 9), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_7BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -122, (byte) 99, (byte) -95, (byte) 12, (byte) -20, (byte) -63, (byte) 14, (byte) -86, (byte) 104, (byte) 58, (byte) -110, (byte) 126, (byte) -11, (byte) 55, (byte) 24, (byte) 82}), new BiomeSchemeDescriptor(new Version(1, 8), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 92, (byte) -102, (byte) -81, (byte) 49, (byte) 25, (byte) -97, (byte) 118, (byte) 62, (byte) -7, (byte) 8, (byte) 92, (byte) -55, (byte) -74, (byte) -112, (byte) 43, (byte) 29}), new BiomeSchemeDescriptor(new Version(1, 8, 1), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -108, (byte) 55, (byte) -76, (byte) -114, (byte) 5, (byte) 27, (byte) 12, (byte) -24, (byte) -127, (byte) 124, (byte) -104, (byte) -98, (byte) 89, (byte) -25, (byte) -103, (byte) 79}), new BiomeSchemeDescriptor(new Version(1, 8, 3), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 101, (byte) -123, (byte) -119, (byte) 23, (byte) -111, (byte) -32, (byte) -41, (byte) 93, (byte) -59, (byte) 76, (byte) -5, (byte) 84, (byte) 122, (byte) -122, (byte) 109, (byte) -80}), new BiomeSchemeDescriptor(new Version(1, 8, 8), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 57, (byte) 96, (byte) -103, (byte) -30, (byte) 62, (byte) 88, (byte) 48, (byte) -99, (byte) 33, (byte) 113, (byte) 58, (byte) -75, (byte) -41, (byte) -63, (byte) -47, (byte) -88}), new BiomeSchemeDescriptor(new Version(1, 8, 9), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -66, (byte) 112, (byte) 66, (byte) 2, (byte) 51, (byte) 112, (byte) -101, (byte) 61, (byte) 119, (byte) -113, (byte) 118, (byte) 39, (byte) -35, (byte) 80, (byte) -34, (byte) 98}), new BiomeSchemeDescriptor(new Version(1, 9), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_8BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 55, (byte) -8, (byte) 13, (byte) 38, (byte) 104, (byte) 114, (byte) -20, (byte) 17, (byte) 86, (byte) 10, (byte) -80, (byte) -119, (byte) 95, (byte) 124, (byte) -10, (byte) 59}), new BiomeSchemeDescriptor(new Version(1, 10, 2), BIOME_ALGORITHM_1_7_DEFAULT, Minecraft1_10BiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 122, (byte) 48, (byte) 69, (byte) 84, (byte) -3, (byte) -22, (byte) -121, (byte) -102, (byte) 121, (byte) -98, (byte) -2, (byte) 110, (byte) -82, (byte) -35, (byte) -116, (byte) -107}), new BiomeSchemeDescriptor(new Version(1, 7, 2), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_7LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 95, (byte) 124, (byte) -57, (byte) -21, (byte) 1, (byte) -53, (byte) -39, (byte) 53, (byte) -87, (byte) -105, (byte) 60, (byte) -74, (byte) -23, (byte) -60, (byte) -63, (byte) 14}), new BiomeSchemeDescriptor(new Version(1, 7, 9), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_7LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -122, (byte) 99, (byte) -95, (byte) 12, (byte) -20, (byte) -63, (byte) 14, (byte) -86, (byte) 104, (byte) 58, (byte) -110, (byte) 126, (byte) -11, (byte) 55, (byte) 24, (byte) 82}), new BiomeSchemeDescriptor(new Version(1, 8), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 92, (byte) -102, (byte) -81, (byte) 49, (byte) 25, (byte) -97, (byte) 118, (byte) 62, (byte) -7, (byte) 8, (byte) 92, (byte) -55, (byte) -74, (byte) -112, (byte) 43, (byte) 29}), new BiomeSchemeDescriptor(new Version(1, 8, 1), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -108, (byte) 55, (byte) -76, (byte) -114, (byte) 5, (byte) 27, (byte) 12, (byte) -24, (byte) -127, (byte) 124, (byte) -104, (byte) -98, (byte) 89, (byte) -25, (byte) -103, (byte) 79}), new BiomeSchemeDescriptor(new Version(1, 8, 3), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 101, (byte) -123, (byte) -119, (byte) 23, (byte) -111, (byte) -32, (byte) -41, (byte) 93, (byte) -59, (byte) 76, (byte) -5, (byte) 84, (byte) 122, (byte) -122, (byte) 109, (byte) -80}), new BiomeSchemeDescriptor(new Version(1, 8, 8), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 57, (byte) 96, (byte) -103, (byte) -30, (byte) 62, (byte) 88, (byte) 48, (byte) -99, (byte) 33, (byte) 113, (byte) 58, (byte) -75, (byte) -41, (byte) -63, (byte) -47, (byte) -88}), new BiomeSchemeDescriptor(new Version(1, 8, 9), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) -66, (byte) 112, (byte) 66, (byte) 2, (byte) 51, (byte) 112, (byte) -101, (byte) 61, (byte) 119, (byte) -113, (byte) 118, (byte) 39, (byte) -35, (byte) 80, (byte) -34, (byte) 98}), new BiomeSchemeDescriptor(new Version(1, 9), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_8LargeBiomeScheme.class, true)); addDescriptor(new Checksum(new byte[] {(byte) 55, (byte) -8, (byte) 13, (byte) 38, (byte) 104, (byte) 114, (byte) -20, (byte) 17, (byte) 86, (byte) 10, (byte) -80, (byte) -119, (byte) 95, (byte) 124, (byte) -10, (byte) 59}), new BiomeSchemeDescriptor(new Version(1, 10, 2), BIOME_ALGORITHM_1_7_LARGE, Minecraft1_10LargeBiomeScheme.class, true)); } private static void addDescriptor(Checksum checksum, BiomeSchemeDescriptor descriptor) { Set<BiomeSchemeDescriptor> descriptors = DESCRIPTORS.computeIfAbsent(checksum, key -> new HashSet<>()); descriptors.add(descriptor); } private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(BiomeSchemeManager.class); static class BiomeSchemeDescriptor { BiomeSchemeDescriptor(Version minecraftVersion, int biomeScheme, Class<? extends BiomeScheme> _class, boolean addLibraries) { this.minecraftVersion = minecraftVersion; this.biomeScheme = biomeScheme; this._class = _class; this.addLibraries = addLibraries; try { constructor = addLibraries ? _class.getConstructor(File.class, File.class, Checksum.class) : _class.getConstructor(File.class, Checksum.class); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } public BiomeScheme instantiate(File jarFile, File minecraftDir, Checksum checksum) { try { if (addLibraries) { File libDir = new File(minecraftDir, "libraries"); return constructor.newInstance(jarFile, libDir, checksum); } else { return constructor.newInstance(jarFile, checksum); } } catch (InstantiationException e) { throw new RuntimeException("Could not instantiate biome scheme", e); } catch (IllegalAccessException e) { throw new RuntimeException("Access denied while instantiating biome scheme", e); } catch (InvocationTargetException e) { throw new RuntimeException("Exception thrown while instantiating biome scheme", e); } } final Version minecraftVersion; final int biomeScheme; final Class<? extends BiomeScheme> _class; final Constructor<? extends BiomeScheme> constructor; private final boolean addLibraries; } static class BiomeJar { BiomeJar(File file, Checksum checksum, BiomeSchemeDescriptor descriptor) { this.file = file; this.checksum = checksum; this.descriptor = descriptor; } final File file; final Checksum checksum; final BiomeSchemeDescriptor descriptor; } }