package sk.tomsik68.mclauncher.impl.versions.mcdownload; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import sk.tomsik68.mclauncher.api.common.IOperatingSystem; import sk.tomsik68.mclauncher.api.common.MCLauncherAPI; import sk.tomsik68.mclauncher.impl.common.Platform; import sk.tomsik68.mclauncher.impl.versions.mcdownload.Rule.Action; import sk.tomsik68.mclauncher.util.IExtractRules; import sk.tomsik68.mclauncher.util.StringSubstitutor; import java.util.ArrayList; import java.util.HashMap; /** * Represents a library that is needed to run minecraft. */ final class Library { private final StringSubstitutor libraryPathSubstitutor = new StringSubstitutor("${%s}"); private final String name; private final HashMap<String, String> natives = new HashMap<String, String>(); private final ArrayList<Rule> rules = new ArrayList<Rule>(); private LibraryExtractRules extractRules; private final static String LIBRARY_BASE_URL = "https://libraries.minecraft.net/"; private String url = LIBRARY_BASE_URL; public Library(JSONObject json) { name = json.get("name").toString(); if (json.containsKey("natives")) { JSONObject nativesObj = (JSONObject) json.get("natives"); for (String nativeKey : nativesObj.keySet()) { String key = nativeKey; String value = nativesObj.get(nativeKey).toString(); natives.put(key, value); } } if (json.containsKey("rules")) { JSONArray rulz = (JSONArray) json.get("rules"); for (int i = 0; i < rulz.size(); ++i) { rules.add(new Rule((JSONObject) rulz.get(i))); } } if (json.containsKey("extract")) { extractRules = new LibraryExtractRules((JSONObject) json.get("extract")); } if (json.containsKey("url")) { url = json.get("url").toString(); } } public String getName() { return name; } /** * Returns name of library that holds natives for given operating system * @param os - IOperatingSystem to check * @return Name of library which holds natives for given OS */ public String getNatives(IOperatingSystem os) { if (!natives.containsKey(os.getMinecraftName())) return natives.get(Platform.wrapName(os.getMinecraftName())).replace("${arch}", System.getProperty("sun.arch.data.model")); return natives.get(os.getMinecraftName()).replace("${arch}", os.getArchitecture()); } /** * Returns relative path of library as string. Relative path is used in URLs, file paths. * You can read more about this on wiki... * @return Relative path of library. */ public String getPath() { libraryPathSubstitutor.setVariable("arch", Platform.getCurrentPlatform().getArchitecture()); String[] split = name.split(":"); StringBuilder result = new StringBuilder(); result = result.append(split[0].replace('.', '/'));// net/sf/jopt-simple result = result.append('/').append(split[1]).append('/').append(split[2]).append('/'); // /jopt-simple/4.4/ result = result.append(split[1]).append('-').append(split[2]); // jopt-simple-4.4 if (!natives.isEmpty()) { IOperatingSystem os = Platform.getCurrentPlatform(); String osName = os.getMinecraftName(); if(!natives.containsKey(osName)) osName = Platform.wrapName(osName); result = result.append('-').append(natives.get(osName)); } result = result.append(".jar"); return libraryPathSubstitutor.substitute(result.toString()); } /** * * @return True if this library is compatible with the current operating system */ boolean isCompatible() { Action action = Action.DISALLOW; for (Rule rule : rules) { // rule may only change resulting action if it's effective... if (rule.applies()) { action = rule.getAction(); System.out.println("Rule: " + rule.toString()); } } // the following condition is very important and can brackets can be ignored while reading(they're just to increase readability) // library is compatible if: // (there are no rules) OR ((action is allow) AND (there are EITHER ((no natives) OR (natives for this platform are available)))) return rules.isEmpty() || (action == Action.ALLOW && (!hasNatives() || natives.containsKey(Platform.getCurrentPlatform().getMinecraftName()) || natives.containsKey(Platform.wrapName(Platform.getCurrentPlatform().getMinecraftName())) )); } /** * * @return True if there are natives for any platform */ public boolean hasNatives() { return !natives.isEmpty(); } /** * * @return IExtractRules that apply to this library */ public IExtractRules getExtractRules() { return extractRules; } /** * * @return String which contains URL where this library can be downloaded */ public String getDownloadURL() { return url.concat(getPath()); } }