161 lines
6.5 KiB
Python
161 lines
6.5 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
#
|
||
|
# ________ _____ _________ .____ _________
|
||
|
# / _____/ / \ \_ ___ \| | \_ ___ \ ___________ ____
|
||
|
# / \ ___ / \ / \/ \ \/| | / \ \/ / _ \_ __ _/ __ \
|
||
|
# \ \_\ / Y \ \___| |__\ \___( <_> | | \\ ___/
|
||
|
# \______ \____|__ /\______ |_______ \______ /\____/|__| \___ >
|
||
|
# \/ \/ \/ \/ \/ \/
|
||
|
#
|
||
|
# Ghink Minecraft Launcher
|
||
|
# Copyleft Ghink Network Studio
|
||
|
# Bigsk (https://www.xiaxinzhe.cn)
|
||
|
# See the LICENSE
|
||
|
#
|
||
|
|
||
|
# Standard
|
||
|
import os, platform, hashlib, requests
|
||
|
import urllib.request, urllib.parse
|
||
|
from threading import Thread
|
||
|
# Extend
|
||
|
import psutil
|
||
|
# Self
|
||
|
import GMCLCore.log4py as log4py
|
||
|
from GMCLCore.config import *
|
||
|
|
||
|
class Core(object):
|
||
|
|
||
|
# Define constant
|
||
|
ARIA = "ARIA"
|
||
|
|
||
|
OFFICIAL = "OFFICIAL"
|
||
|
BMCLAPI = "BMCLAPI"
|
||
|
|
||
|
OFFLINE = "OFFLINE"
|
||
|
MOJANG = "MOJANG"
|
||
|
MICROSOFT = "MICROSOFT"
|
||
|
|
||
|
def __init__(self, workDir = ".gmclcore"):
|
||
|
# Define constant
|
||
|
self.ENV_SOURCE = "https://resource.ghink.net/application/rely"
|
||
|
|
||
|
# Define launcher vars
|
||
|
self.__name= "GMCLCore"
|
||
|
self.__version = "{} {}".format(VERSION[0], ".".join(str(c) for c in VERSION[1]))
|
||
|
self.__workDir = workDir
|
||
|
self.__system = platform.system()
|
||
|
self.parallel = psutil.cpu_count()
|
||
|
self.parallelType = self.ARIA
|
||
|
self.useragent = "{}/{}".format(self.__name, self.__version)
|
||
|
|
||
|
# Create workdir
|
||
|
os.makedirs(self.__workDir, exist_ok = True)
|
||
|
if self.__system == "Windows":
|
||
|
import win32api, win32con
|
||
|
win32api.SetFileAttributes(self.__workDir, win32con.FILE_ATTRIBUTE_HIDDEN)
|
||
|
|
||
|
# Init log object
|
||
|
self.l = log4py.log(self.__workDir)
|
||
|
|
||
|
# Define default game vars
|
||
|
self.gameDir = os.path.join(os.path.dirname(__file__), ".minecraft")
|
||
|
self.javaPath = self.searchJava()
|
||
|
self.gameMem = self.autoMemory()
|
||
|
self.authType = self.OFFLINE
|
||
|
self.id = "Steve"
|
||
|
self.uuid = self.generateUUID(self.id)
|
||
|
|
||
|
# Prepare running env
|
||
|
self.l.info("Initing running env...")
|
||
|
self.initEnv()
|
||
|
|
||
|
# Create daemon thread
|
||
|
self.l.info("Creating daemon thread...")
|
||
|
self.__daemonThread = Thread(target = self.__daemon)
|
||
|
self.__daemonThread.daemon = True
|
||
|
self.__daemonThread.start()
|
||
|
|
||
|
def initEnv(self):
|
||
|
os.makedirs(os.path.join(self.__workDir, "env"), exist_ok = True)
|
||
|
if self.networkTest():
|
||
|
source = self.urljoin(self.ENV_SOURCE, "aria2c")
|
||
|
if self.__system == "Windows":
|
||
|
if "64" in platform.machine():
|
||
|
self.__ariaPath = os.path.join(self.__workDir, "env", "aria2c64.exe")
|
||
|
source = self.urljoin(source, "win64")
|
||
|
elif "32" in platform.machine() or "86" in platform.machine():
|
||
|
self.__ariaPath = os.path.join(self.__workDir, "env", "aria2c32.exe")
|
||
|
source = self.urljoin(source, "win32")
|
||
|
else:
|
||
|
self.l.fatal("Unsupported processor architecture! ")
|
||
|
if not os.path.exists(self.__ariaPath):
|
||
|
with open(self.__ariaPath, "wb") as fb:
|
||
|
try:
|
||
|
content = requests.get(self.urljoin(source, "aria2c.exe"), headers = {"user-agent": self.useragent}).content
|
||
|
fb.write(content)
|
||
|
except Exception as e:
|
||
|
self.l.warn("Failed to install running env aria2c! System return: {}".format(e))
|
||
|
elif self.__system == "Linux":
|
||
|
self.__ariaPath = self.urljoin(self.__workDir, "env", "aria2c")
|
||
|
source = self.urljoin(source, "linux")
|
||
|
if not os.path.exists(self.__ariaPath):
|
||
|
with open(self.__ariaPath, "wb") as fb:
|
||
|
try:
|
||
|
content = requests.get(self.urljoin(source, "aria2c"), headers = {"user-agent": self.useragent}).content
|
||
|
fb.write(content)
|
||
|
except Exception as e:
|
||
|
self.l.warn("Failed to install running env aria2c! System return: {}".format(e))
|
||
|
elif self.__system == "Darwin":
|
||
|
self.__ariaPath = self.urljoin(self.__workDir, "env", "aria2c")
|
||
|
source = self.urljoin(source, "darwin")
|
||
|
if not os.path.exists(self.__ariaPath):
|
||
|
with open(self.__ariaPath, "wb") as fb:
|
||
|
try:
|
||
|
content = requests.get(self.urljoin(source, "aria2c"), headers = {"user-agent": self.useragent}).content
|
||
|
fb.write(content)
|
||
|
except Exception as e:
|
||
|
self.l.warn("Failed to install running env aria2c! System return: {}".format(e))
|
||
|
|
||
|
def __daemon(self):
|
||
|
while True:
|
||
|
pass
|
||
|
|
||
|
def urljoin(self, *args: str):
|
||
|
result = os.path.join(*args)
|
||
|
for i in range(result.count("\\")):
|
||
|
result = result.replace("\\", "/")
|
||
|
return result
|
||
|
|
||
|
def networkTest(self, source = r"https://www.baidu.com", retry = 3):
|
||
|
flag = False
|
||
|
for i in range(retry):
|
||
|
try:
|
||
|
fp = urllib.request.urlopen(source)
|
||
|
fp.read(100).decode()
|
||
|
fp.close()
|
||
|
except:
|
||
|
pass
|
||
|
else:
|
||
|
flag = True
|
||
|
return flag
|
||
|
|
||
|
def searchJava(self):
|
||
|
javaEnv = os.environ.get("Path", None) if self.__system == "Windows" else os.environ.get("PATH", None)
|
||
|
if javaEnv:
|
||
|
javaEnv = javaEnv.split(";") if self.__system == "Windows" else javaEnv.split(":")
|
||
|
for j in javaEnv:
|
||
|
for name in ("Java", "java", "JAVA", "Jre", "jre", "JRE"):
|
||
|
if name in j:
|
||
|
java = j
|
||
|
merge = os.path.join(java, "javaw.exe" if self.__system == "Windows" else "java")
|
||
|
if os.path.exists(merge):
|
||
|
return merge
|
||
|
|
||
|
def autoMemory(self):
|
||
|
return 0.8 * (psutil.virtual_memory().free / 1024 ** 2)
|
||
|
|
||
|
def generateUUID(self, id):
|
||
|
result = hashlib.md5()
|
||
|
result.update("".join(('OfflinePlayer:', id)).encode())
|
||
|
result = result.hexdigest()
|
||
|
return result
|