global findInChain def findInChain(versionsPath,version,path): versionPath = p(versionsPath,version) clientJson = readJsonFile(p(versionPath,version + ".json")) curPath = copy.deepcopy(clientJson) success = True for dir in path: if dir in curPath: curPath = curPath[dir] else: success = False break if success == False: return findInChain(versionsPath,clientJson["inheritsFrom"],path) return curPath global findInChainDeepest def findInChainDeepest(versionsPath,version,path): found = False while True: versionPath = p(versionsPath,version) clientJson = readJsonFile(p(versionPath,version + ".json")) curPath = copy.deepcopy(clientJson) for dir in path: if dir in curPath: curPath = curPath[dir] else: if "inheritsFrom" in clientJson: version = clientJson["inheritsFrom"] continue else: curPath = False break found = curPath if "inheritsFrom" in clientJson: version = clientJson["inheritsFrom"] continue else: break if found == False: raise return found global parseJavaLibraryName def parseJavaLibraryName(libName): libSplit = libName.split(":",2) libPackage = libSplit[0] libName = libSplit[1] libVersion = libSplit[2] libFilePath = libPackage.replace(".","/") + "/" +libName+ "/" +libVersion+ "/" +libName+ "-" +libVersion+ ".jar" return libPackage,libName,libVersion,libFilePath global re import re global checkRules def checkRules(ruleList): action = "disallow" for rule in ruleList: if "os" in rule: if "name" in rule["os"]: rule["os"]["name"] = rule["os"]["name"].replace("osx","macos") if not re.search(rule["os"]["name"],lv["osName"]): continue if "arch" in rule["os"]: if not re.search(rule["os"]["arch"],lv["jvmArch"]): continue if "version" in rule["os"]: if not re.search(rule["os"]["version"],lv["osVersion"]): continue action = rule["action"] else: action = rule["action"] return action global getLibraryPrettyName def getLibraryPrettyName(library): libraryName = library["package"]+ ":" +library["name"]+ ":" +library["version"] if library["type"] == "native": libraryName += " (" +library["nativeOS"]+ ")" return libraryName global getFileHash def getFileHash(file): with open(file,"rb") as fileh: return hashlib.sha1(fileh.read()).hexdigest() global checkLibraryHash def checkLibraryHash(library): hash = False if library["dumb"] == False: if library["type"] == "library": hash = library["data"]["downloads"]["artifact"]["sha1"] else: hash = library["data"]["downloads"]["classifiers"]["natives-" +library["nativeOS"]]["sha1"] else: if not os.path.isfile(library["filePathOS"] + ".sha1"): print(colored(colorama.fore.RED,"No .sha1 file found, can't verify."),file=sys.stderr) return False else: with open(library["filePathOS"] + ".sha1","r") as fileh: hash = fileh.read() match = (hash == getFileHash(library["filePathOS"])) if not match: print(colored(colorama.Fore.RED,library["filePathOS"]+ " is corrupt!"),file=sys.stderr) return match global processVersion def processVersion(versionsPath,libraryPath,nativePath,version): versionPath = p(versionsPath,version) clientJson = readJsonFile(p(versionPath,version + ".json")) libraries = [] arguments = [] jvmArguments = [] if "inheritsFrom" in clientJson: _,libraries,_,_= processVersion(versionsPath,libraryPath,nativePath,clientJson["inheritsFrom"]) for library in clientJson["libraries"]: lBase = {} lBase["package"],lBase["name"],lBase["version"],lBase["filePath"] = parseJavaLibraryName(library["name"]) lBase["type"] = "library" lBase["data"] = library lBase["dumb"] = False if "downloads" in library: # not dumb if "classifiers" in library["downloads"]: # classifiers (usually for natives, their sources and their documentation) for classifier in library["downloads"]["classifiers"]: l = copy.deepcopy(lBase) native = library["downloads"]["classifiers"][classifier] if classifier.startswith("natives-"): l["type"] = "native" l["nativeOS"] = classifier.replace("natives-","",1) else: continue # TODO: add source and javadoc handling l["filePathOS"] = p(nativePath,native["path"].replace("/",os.path.sep)) if "url" in native and native["url"] != "": l["url"] = native["url"] libraries.append(l) if "artifact" in library["downloads"]: # artifact (usually for libraries) l = copy.deepcopy(lBase) if "path" in library["downloads"]["artifact"]: l["filePathOS"] = p(libraryPath,library["downloads"]["artifact"]["path"].replace("/",os.path.sep)) if "url" in library["downloads"]["artifact"] and library["downloads"]["artifact"]["url"] != "": l["url"] = library["downloads"]["artifact"]["url"] libraries.append(l) else: # dumb lBase["dumb"] = True if "natives" in library: # natives lBaseTwo = copy.deepcopy(lBase) lBaseTwo["type"] = "native" if not "url" in library: lBaseTwo["url"] = "https://libraries.minecraft.net" else: lBaseTwo["url"] = library["url"] while len(lBaseTwo["url"]) > 0 and lBaseTwo["url"][-1] == "/": lBaseTwo["url"] = lBaseTwo["url"][:-1] lBaseTwo["url"] = lBaseTwo["url"] + "/" + lBaseTwo["filePath"] for native in library["natives"]: l = copy.deepcopy(lBaseTwo) l["nativeOS"] = native native = "natives-" + native l["filePath"] = l["filePath"][:-4] + "-" + native + ".jar" l["url"] = l["url"][:-4] + "-" + native + ".jar" l["filePathOS"] = p(nativePath,l["filePath"].replace("/",os.path.sep)) libraries.append(l) else: # libraries l = copy.deepcopy(lBase) if not "url" in library: l["url"] = "https://libraries.minecraft.net" else: l["url"] = library["url"] while len(l["url"]) > 0 and l["url"][-1] == "/": l["url"] = l["url"][:-1] l["url"] = l["url"] + "/" + l["filePath"] l["filePathOS"] = p(libraryPath,l["filePath"].replace("/",os.path.sep)) libraries.append(l) libraries.append({"type":"client","filePathOS":p(versionPath,version + ".jar")}) if "arguments" in clientJson: if "game" in clientJson["arguments"]: for arg in clientJson["arguments"]["game"]: if type(arg) != str: continue arguments.append(arg) if "jvm" in clientJson["arguments"]: for arg in clientJson["arguments"]["jvm"]: if type(arg) != str: if "value" in arg: if type(arg["value"]) != list: arg["value"] = [arg["value"]] if "rules" in arg: if checkRules(arg["rules"]) == "allow": for value in arg["value"]: jvmArguments.append(value) else: for value in arg["value"]: jvmArguments.append(value) else: jvmArguments.append(arg) elif "minecraftArguments" in clientJson: margs = clientJson["minecraftArguments"].replace('"',"").split(" ") for arg in margs: if type(arg) != str: continue arguments.append(arg) return clientJson,libraries,arguments,jvmArguments global findArgument def findArgument(args,searchFor): for arg in args: if arg.startswith(searchFor): return True return False