Text color, file checking, errors to stdout, small enhancements
This commit is contained in:
parent
fb2fdadf18
commit
13e7140112
@ -25,6 +25,56 @@ import platform
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
class coloramaFallback:
|
||||||
|
class Fore:
|
||||||
|
BLACK = ""
|
||||||
|
RED = ""
|
||||||
|
GREEN = ""
|
||||||
|
YELLOW = ""
|
||||||
|
BLUE = ""
|
||||||
|
MAGENTA = ""
|
||||||
|
CYAN = ""
|
||||||
|
WHITE = ""
|
||||||
|
RESET = ""
|
||||||
|
|
||||||
|
class Back:
|
||||||
|
BLACK = ""
|
||||||
|
RED = ""
|
||||||
|
GREEN = ""
|
||||||
|
YELLOW = ""
|
||||||
|
BLUE = ""
|
||||||
|
MAGENTA = ""
|
||||||
|
CYAN = ""
|
||||||
|
WHITE = ""
|
||||||
|
RESET = ""
|
||||||
|
|
||||||
|
class Style:
|
||||||
|
DIM = ""
|
||||||
|
NORMAL = ""
|
||||||
|
BRIGHT = ""
|
||||||
|
RESET_ALL = ""
|
||||||
|
|
||||||
|
def coloramaInit():
|
||||||
|
global colorama
|
||||||
|
coloramaSuccess = False
|
||||||
|
if not "-nocolor" in sys.argv:
|
||||||
|
try:
|
||||||
|
import colorama
|
||||||
|
colorama.init()
|
||||||
|
coloramaSuccess = True
|
||||||
|
except Exception as e:
|
||||||
|
print("Could not import/init colorama: " +str(e),file=sys.stderr)
|
||||||
|
print("Colors deactivated.\n",file=sys.stderr)
|
||||||
|
|
||||||
|
if not coloramaSuccess:
|
||||||
|
colorama = coloramaFallback
|
||||||
|
|
||||||
|
def colored(color,st,bright = True):
|
||||||
|
if bright:
|
||||||
|
st = colorama.Style.BRIGHT + st
|
||||||
|
|
||||||
|
return color + st + colorama.Style.RESET_ALL
|
||||||
|
|
||||||
def download(url,decode = "utf-8"):
|
def download(url,decode = "utf-8"):
|
||||||
request = urllib.request.Request(url,headers={"User-Agent":"Mozilla/5.0"})
|
request = urllib.request.Request(url,headers={"User-Agent":"Mozilla/5.0"})
|
||||||
response = urllib.request.urlopen(request)
|
response = urllib.request.urlopen(request)
|
||||||
@ -46,7 +96,7 @@ def fileDl(url,file,read = True,decode = "utf-8"):
|
|||||||
return readFile(file,decode)
|
return readFile(file,decode)
|
||||||
return
|
return
|
||||||
|
|
||||||
print(url)
|
#print(url)
|
||||||
data = download(url,False)
|
data = download(url,False)
|
||||||
fileh = open(tmpFile,"wb")
|
fileh = open(tmpFile,"wb")
|
||||||
fileh.write(data)
|
fileh.write(data)
|
||||||
@ -139,6 +189,37 @@ def checkRules(ruleList):
|
|||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
|
def getLibraryPrettyName(library):
|
||||||
|
libraryName = library["package"]+ ":" +library["name"]+ ":" +library["version"]
|
||||||
|
if library["type"] == "native":
|
||||||
|
libraryName += " (" +library["nativeOS"]+ ")"
|
||||||
|
return libraryName
|
||||||
|
|
||||||
|
def getFileHash(file):
|
||||||
|
with open(file,"rb") as fileh:
|
||||||
|
return hashlib.sha1(fileh.read()).hexdigest()
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
def processVersion(versionsPath,libraryPath,nativePath,version):
|
def processVersion(versionsPath,libraryPath,nativePath,version):
|
||||||
versionPath = p(versionsPath,version)
|
versionPath = p(versionsPath,version)
|
||||||
clientJson = readJsonFile(p(versionPath,version + ".json"))
|
clientJson = readJsonFile(p(versionPath,version + ".json"))
|
||||||
@ -154,7 +235,7 @@ def processVersion(versionsPath,libraryPath,nativePath,version):
|
|||||||
lBase["package"],lBase["name"],lBase["version"],lBase["filePath"] = parseJavaLibraryName(library["name"])
|
lBase["package"],lBase["name"],lBase["version"],lBase["filePath"] = parseJavaLibraryName(library["name"])
|
||||||
lBase["type"] = "library"
|
lBase["type"] = "library"
|
||||||
lBase["data"] = library
|
lBase["data"] = library
|
||||||
lBase["dumb"] = True
|
lBase["dumb"] = False
|
||||||
|
|
||||||
if "downloads" in library: # not dumb
|
if "downloads" in library: # not dumb
|
||||||
if "classifiers" in library["downloads"]: # classifiers (usually for natives, their sources and their documentation)
|
if "classifiers" in library["downloads"]: # classifiers (usually for natives, their sources and their documentation)
|
||||||
@ -183,6 +264,7 @@ def processVersion(versionsPath,libraryPath,nativePath,version):
|
|||||||
|
|
||||||
libraries.append(l)
|
libraries.append(l)
|
||||||
else: # dumb
|
else: # dumb
|
||||||
|
lBase["dumb"] = True
|
||||||
if "natives" in library: # natives
|
if "natives" in library: # natives
|
||||||
lBaseTwo = lBase.copy()
|
lBaseTwo = lBase.copy()
|
||||||
lBaseTwo["type"] = "native"
|
lBaseTwo["type"] = "native"
|
||||||
@ -247,7 +329,8 @@ def processVersion(versionsPath,libraryPath,nativePath,version):
|
|||||||
return clientJson,libraries,arguments,jvmArguments
|
return clientJson,libraries,arguments,jvmArguments
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("Reading config...")
|
coloramaInit()
|
||||||
|
print(colored(colorama.Fore.GREEN,"Reading config..."))
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.optionxform = str
|
config.optionxform = str
|
||||||
config.read(os.path.splitext(s)[0] + ".ini")
|
config.read(os.path.splitext(s)[0] + ".ini")
|
||||||
@ -279,7 +362,7 @@ def main():
|
|||||||
|
|
||||||
print("")
|
print("")
|
||||||
for setting in lv:
|
for setting in lv:
|
||||||
print(setting+ "=" +str(lv[setting]))
|
print(colored(colorama.Fore.BLACK,setting+ "=" +str(lv[setting])))
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
@ -293,8 +376,8 @@ def main():
|
|||||||
json.loads(lv["jvmArguments"])
|
json.loads(lv["jvmArguments"])
|
||||||
|
|
||||||
if not lv["osName"] in ["windows","linux","macos"]:
|
if not lv["osName"] in ["windows","linux","macos"]:
|
||||||
print("\nWarning, unsupported OS detected: '" +lv["osName"]+ "'")
|
print(colored(colorama.Fore.YELLOW,"\nWarning, unsupported OS detected: '" +lv["osName"]+ "'"),file=sys.stderr)
|
||||||
print("Needs to be either windows, linux or macos. Define it with osName=name in the config.")
|
print("Needs to be either windows, linux or macos. Define it with osName=name in the config.",file=sys.stderr)
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
if not "version" in lv: lv["version"] = input("Version ID: ")
|
if not "version" in lv: lv["version"] = input("Version ID: ")
|
||||||
@ -304,6 +387,7 @@ def main():
|
|||||||
tmpFile = p(lv["gamePath"],"file.tmp")
|
tmpFile = p(lv["gamePath"],"file.tmp")
|
||||||
if os.path.isfile(tmpFile): os.remove(tmpFile)
|
if os.path.isfile(tmpFile): os.remove(tmpFile)
|
||||||
|
|
||||||
|
launcherVariables = {}
|
||||||
versionsPath = p(lv["gamePath"],"versions")
|
versionsPath = p(lv["gamePath"],"versions")
|
||||||
libraryPath = p(lv["gamePath"],"libraries")
|
libraryPath = p(lv["gamePath"],"libraries")
|
||||||
nativePath = p(lv["gamePath"],"natives")
|
nativePath = p(lv["gamePath"],"natives")
|
||||||
@ -311,32 +395,62 @@ def main():
|
|||||||
nativesOutPath = p(lv["gamePath"],"natives-extracted",lv["version"],lv["osName"]+ "." +lv["jvmArch"])
|
nativesOutPath = p(lv["gamePath"],"natives-extracted",lv["version"],lv["osName"]+ "." +lv["jvmArch"])
|
||||||
assetsPath = p(lv["gamePath"],"assets")
|
assetsPath = p(lv["gamePath"],"assets")
|
||||||
|
|
||||||
print("Scanning .json(s)...")
|
print(colored(colorama.Fore.GREEN,"Scanning .json(s)..."))
|
||||||
clientJson,libraries,arguments,jvmArguments = processVersion(versionsPath,libraryPath,nativePath,lv["version"])
|
clientJson,libraries,arguments,jvmArguments = processVersion(versionsPath,libraryPath,nativePath,lv["version"])
|
||||||
|
|
||||||
print("\nDownloading libraries...")
|
try:
|
||||||
|
launcherVariables["assets_index_name"] = findInChain(versionsPath,lv["version"],["assets"])
|
||||||
|
except:
|
||||||
|
print(colored(colorama.Fore.YELLOW,"> Could not find assets_index_name, assuming pre-1.6"),file=sys.stderr)
|
||||||
|
launcherVariables["assets_index_name"] = "pre-1.6"
|
||||||
|
input()
|
||||||
|
|
||||||
|
print(colored(colorama.Fore.GREEN,"\nDownloading libraries..."))
|
||||||
for library in libraries:
|
for library in libraries:
|
||||||
if "url" in library:
|
if "url" in library:
|
||||||
|
print(colored(colorama.Fore.BLACK,getLibraryPrettyName(library)))
|
||||||
try:
|
try:
|
||||||
fileDl(library["url"],library["filePathOS"],read = False)
|
fileDl(library["url"],library["filePathOS"],read = False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Could not download: " +str(e))
|
print(colored(colorama.Fore.RED,"> Could not download: ") +str(e),file=sys.stderr)
|
||||||
|
else:
|
||||||
|
if library["dumb"] == True:
|
||||||
|
try:
|
||||||
|
fileDl(library["url"] + ".sha1",library["filePathOS"] + ".sha1",read = False)
|
||||||
|
except Exception as e:
|
||||||
|
print(colored(colorama.Fore.RED,"> Could not download sha1 hash: ") +str(e),file=sys.stderr)
|
||||||
|
|
||||||
|
if "-verifydata" in sys.argv: checkLibraryHash(library)
|
||||||
|
|
||||||
|
if "-verifydata" in sys.argv: # assets
|
||||||
|
print(colored(colorama.Fore.GREEN,"\nVerifying assets..."))
|
||||||
|
assetJson = False
|
||||||
|
with open(p(assetsPath,"indexes",launcherVariables["assets_index_name"] + ".json"),"r") as fileh: assetJson = json.loads(fileh.read())
|
||||||
|
|
||||||
|
for asset in assetJson["objects"]:
|
||||||
|
hash = assetJson["objects"][asset]["hash"]
|
||||||
|
assetp = p(assetsPath,"objects",hash[:2],hash)
|
||||||
|
if not os.path.isfile(assetp):
|
||||||
|
print(colored(colorama.Fore.RED,assetp+ " is missing!"),file=sys.stderr)
|
||||||
|
continue
|
||||||
|
if hash != getFileHash(assetp):
|
||||||
|
print(colored(colorama.Fore.RED,assetp+ " is corrupt!"),file=sys.stderr)
|
||||||
|
|
||||||
if "-downloadonly" in sys.argv:
|
if "-downloadonly" in sys.argv:
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
loadLibraries = {}
|
loadLibraries = {}
|
||||||
for library in libraries:
|
for library in libraries:
|
||||||
|
if "data" in library and "rules" in library["data"] and checkRules(library["data"]["rules"]) == "disallow": continue
|
||||||
if library["type"] == "client":
|
if library["type"] == "client":
|
||||||
loadLibraries["client:" +library["filePathOS"]] = library
|
loadLibraries["client:" +library["filePathOS"]] = library
|
||||||
elif library["type"] == "library":
|
elif library["type"] == "library":
|
||||||
if "rules" in library["data"] and checkRules(library["data"]["rules"]) == "disallow": continue
|
|
||||||
loadLibraries[library["package"] + ":" +library["name"]] = library
|
loadLibraries[library["package"] + ":" +library["name"]] = library
|
||||||
|
|
||||||
separator = ";"
|
separator = ";"
|
||||||
libraryList = ""
|
libraryList = ""
|
||||||
if lv["osName"] != "windows": separator = ":"
|
if lv["osName"] != "windows": separator = ":"
|
||||||
print("\nLoaded libraries:")
|
print(colored(colorama.Fore.GREEN,"\nLoaded libraries:"))
|
||||||
clientJar = ""
|
clientJar = ""
|
||||||
for libraryID in loadLibraries:
|
for libraryID in loadLibraries:
|
||||||
library = loadLibraries[libraryID]
|
library = loadLibraries[libraryID]
|
||||||
@ -345,15 +459,15 @@ def main():
|
|||||||
print("Client: " +library["filePathOS"])
|
print("Client: " +library["filePathOS"])
|
||||||
clientJar = library["filePathOS"]
|
clientJar = library["filePathOS"]
|
||||||
else:
|
else:
|
||||||
print("- " +library["package"]+ ":" +library["name"]+ ":" +library["version"])
|
print(colored(colorama.Fore.BLACK,getLibraryPrettyName(library)))
|
||||||
else:
|
else:
|
||||||
print("Lib not found: " +library["package"]+ ":" + +library["name"]+ ":" +library["version"])
|
print(colored(colorama.Fore.RED,"> Lib not found: ") +getLibraryPrettyName(library),file=sys.stderr)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
libraryList += library["filePathOS"] + separator
|
libraryList += library["filePathOS"] + separator
|
||||||
libraryList = libraryList[:-1]
|
libraryList = libraryList[:-1]
|
||||||
|
|
||||||
print("\nExtracting natives...")
|
print(colored(colorama.Fore.GREEN,"\nExtracting natives..."))
|
||||||
if not os.path.isdir(nativesOutPath): os.makedirs(nativesOutPath)
|
if not os.path.isdir(nativesOutPath): os.makedirs(nativesOutPath)
|
||||||
for library in libraries:
|
for library in libraries:
|
||||||
if library["type"] == "native":
|
if library["type"] == "native":
|
||||||
@ -364,23 +478,20 @@ def main():
|
|||||||
if not library["nativeOS"] in ["macos","osx"]: continue
|
if not library["nativeOS"] in ["macos","osx"]: continue
|
||||||
|
|
||||||
if not os.path.isfile(library["filePathOS"]):
|
if not os.path.isfile(library["filePathOS"]):
|
||||||
print("Native not found: " +library["package"]+ ":" +library["name"]+ ":" +library["version"])
|
print(colored(colorama.Fore.RED,"> Native not found: ") +getLibraryPrettyName(library),file=sys.stderr)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
print(colored(colorama.Fore.BLACK,getLibraryPrettyName(library)))
|
||||||
proc = subprocess.Popen(["7z","x",library["filePathOS"],"-o" +nativesOutPath,"-aos"],stdout=subprocess.DEVNULL)
|
proc = subprocess.Popen(["7z","x",library["filePathOS"],"-o" +nativesOutPath,"-aos"],stdout=subprocess.DEVNULL)
|
||||||
rtn = proc.wait()
|
rtn = proc.wait()
|
||||||
if rtn != 0: raise Exception("process","return code isn't 0")
|
if rtn != 0:
|
||||||
|
print(colored(colorama.Fore.RED,"> Native could not be extracted: ") +getLibraryPrettyName(library),file=sys.stderr)
|
||||||
|
|
||||||
print("\nSetting up launcher variables...")
|
print(colored(colorama.Fore.GREEN,"\nSetting up launcher variables..."))
|
||||||
launcherVariables = {}
|
|
||||||
launcherVariables["auth_player_name"] = lv["name"]
|
launcherVariables["auth_player_name"] = lv["name"]
|
||||||
launcherVariables["version_name"] = findInChainDeepest(versionsPath,lv["version"],["id"])
|
launcherVariables["version_name"] = findInChainDeepest(versionsPath,lv["version"],["id"])
|
||||||
launcherVariables["game_directory"] = lv["gamePath"]
|
launcherVariables["game_directory"] = lv["gamePath"]
|
||||||
launcherVariables["assets_root"] = assetsPath
|
launcherVariables["assets_root"] = assetsPath
|
||||||
try:
|
|
||||||
launcherVariables["assets_index_name"] = findInChain(versionsPath,lv["version"],["assets"])
|
|
||||||
except:
|
|
||||||
print("> Could not find assets_index_name, assuming pre-1.6")
|
|
||||||
launcherVariables["assets_index_name"] = "pre-1.6"
|
|
||||||
launcherVariables["auth_access_token"] = "-"
|
launcherVariables["auth_access_token"] = "-"
|
||||||
launcherVariables["auth_uuid"] = hashlib.md5(lv["name"].encode('utf-8')).hexdigest()
|
launcherVariables["auth_uuid"] = hashlib.md5(lv["name"].encode('utf-8')).hexdigest()
|
||||||
launcherVariables["user_type"] = "offline"
|
launcherVariables["user_type"] = "offline"
|
||||||
@ -400,7 +511,7 @@ def main():
|
|||||||
os.chdir(launcherVariables["game_directory"])
|
os.chdir(launcherVariables["game_directory"])
|
||||||
|
|
||||||
if launcherVariables["game_directory"].replace(pUp(launcherVariables["game_directory"]) + os.sep,"",1) == ".minecraft":
|
if launcherVariables["game_directory"].replace(pUp(launcherVariables["game_directory"]) + os.sep,"",1) == ".minecraft":
|
||||||
print("> game_directory is called .minecraft, setting APPDATA/HOME environment variables to parent directory.")
|
print(colored(colorama.Fore.MAGENTA,"> game_directory is called .minecraft, setting APPDATA/HOME environment variables to parent directory."))
|
||||||
os.environ["APPDATA"] = pUp(launcherVariables["game_directory"])
|
os.environ["APPDATA"] = pUp(launcherVariables["game_directory"])
|
||||||
os.environ["HOME"] = os.environ["APPDATA"]
|
os.environ["HOME"] = os.environ["APPDATA"]
|
||||||
|
|
||||||
@ -442,11 +553,11 @@ def main():
|
|||||||
args.append("--assetsDir")
|
args.append("--assetsDir")
|
||||||
args.append(launcherVariables["assets_root"])
|
args.append(launcherVariables["assets_root"])
|
||||||
|
|
||||||
print("\nLaunching Minecraft...")
|
print(colored(colorama.Fore.GREEN,"\nLaunching Minecraft..."))
|
||||||
if lv["console"] == "1":
|
if lv["console"] == "1":
|
||||||
proc = subprocess.Popen([lv["java"]] + args)
|
proc = subprocess.Popen([lv["java"]] + args)
|
||||||
rtn = proc.wait()
|
rtn = proc.wait()
|
||||||
if rtn != 0: raise Exception("process","return code isn't 0")
|
if rtn != 0: print(colored(colorama.Fore.RED,"> Launch failed: ") +"return isn't 0",file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
pkwargs = {
|
pkwargs = {
|
||||||
"stdout": subprocess.DEVNULL,
|
"stdout": subprocess.DEVNULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user