import zipfile from textwrap import dedent as _ from utils import * from psutil import virtual_memory import platform import subprocess script_license() print("此向导将会自动为你生成启动脚本!") def detect_jar(): for i in os.listdir(os.getcwd()): if not os.path.isdir(i) and i.endswith(".jar"): print("找到服务端核心" + f"\033[32m{i}\033[0m!!\n") return i print("没有发现服务端核心,请将此脚本和服务端核心放在同一目录下再使用\n") return class VersionMeta: pufferfish: bool = False leaf: bool = False minecraft_version: int = 0 def detect_brand(jar_path): meta = VersionMeta() with zipfile.ZipFile(jar_path, 'r') as jar: if 'META-INF/versions.list' in jar.namelist(): manifest_data = jar.read('META-INF/versions.list').decode('utf-8') a = manifest_data.split('\t') meta.version = int(a[1].split('.')[1]) brand = a[2].split('/')[1].split('-')[0].lower() if brand == 'leaf': meta.leaf = True if brand in ["pufferfish", "purpur", "leaves", "gale", "leaf"]: meta.pufferfish = True return meta def ask(title): while True: select = input(title + "(y/n):") if select.lower().startswith("y"): print() return True elif select.lower().startswith("n"): print() return False else: print("\033[31m输入错误,请输入 y 或者 n\033[0m\n") def get_memory(): return int(virtual_memory().available / (1024 * 1024)) # to MB def get_java(path, check): try: result = subprocess.run([path, "-version"], capture_output=True, text=True) print("成功检测到java!版本为:") print(result.stderr) return True except FileNotFoundError or subprocess.CalledProcessError: if check: print("\033[31m警告,找不到java,请重新指定java路径,或者不自行指定java!\033[0m\n") else: print("\033[31m警告,找不到java,请检查java环境变量或手动指定java路径!\033[0m\n") return False def generate_command(server: str, meta: VersionMeta): while True: if ask("自行指定 java 路径?"): java = input("请输入 java 路径(应当以 java.exe 结尾, 如 D:/jdk/bin/java.exe):") if get_java(java, True): java = '"' + java + '"' break else: if get_java("java", False): java = "java" break if ask("自动检测使用内存?"): memory = get_memory() - 1000 # to MB if memory / 1024 > 20: memory = 20 * 1024 print(f"\033[32m自动使用内存{memory}MB\033[0m\n") else: memory = int(input("内存(至少1024MB,不建议为服务器分配少于2048MB的内存)(单位为MB,输入时不带单位):")) if memory / 1024 > 20: print("不建议为您的服务器分配超过 16-20GB 的内存,给 Java 太多的内存可能会损害服务器的性能") if not ask("使用优化参数(推荐使用)?"): return f"{java} -Xms{memory}M -Xmx{memory}M -jar {server}" base = ( f"{java} -Xms1024M -Xmx{memory}M -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+UseFMA " f"-XX:+UseVectorCmov -XX:+UseNewLongLShift -XX:+UseFastStosb -XX:+SegmentedCodeCache " f"-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+OmitStackTraceInFastThrow " f"-XX:+AlwaysActAsServerClassMachine -XX:+AlwaysPreTouch -XX:+DisableExplicitGC " f"-XX:NmethodSweepActivity=1 -XX:ReservedCodeCacheSize=400M -XX:NonNMethodCodeHeapSize=12M " f"-XX:ProfiledCodeHeapSize=194M -XX:NonProfiledCodeHeapSize=194M -XX:-DontCompileHugeMethods " f"-XX:MaxNodeLimit=240000 -XX:NodeLimitFudgeFactor=8000 -XX:+UseVectorCmov -XX:+PerfDisableSharedMem " f"-XX:+UseFastUnorderedTimeStamps -XX:+UseCriticalJavaThreadPriority -XX:ThreadPriorityPolicy=1 " f"-XX:AllocatePrefetchStyle=3 -XX:+UseG1GC -XX:MaxGCPauseMillis=37 -XX:+PerfDisableSharedMem " f"-XX:G1HeapRegionSize=16M -XX:G1NewSizePercent=23 -XX:G1ReservePercent=20 -XX:SurvivorRatio=32 " f"-XX:G1MixedGCCountTarget=3 -XX:G1HeapWastePercent=20 -XX:InitiatingHeapOccupancyPercent=10 " f"-XX:G1RSetUpdatingPauseTimePercent=0 -XX:MaxTenuringThreshold=1 " f"-XX:G1SATBBufferEnqueueingThresholdPercent=30 -XX:G1ConcMarkStepDurationMillis=5.0 -XX:GCTimeRatio=99 " f"-XX:G1ConcRefinementServiceIntervalMillis=150 -XX:G1ConcRSHotCardLimit=16 ") if meta.pufferfish and meta.minecraft_version >= 18: base += "--add-modules=jdk.incubator.vector " if meta.leaf: base += "-DLeaf.library-download-repo=https://maven.aliyun.com/repository/public " base += f"-jar {server} " if ask("关闭服务端自带GUI(GUI没啥用)(推荐关闭)"): base += "--nogui" return base def generate_batch(command, restart): os_name = platform.system() if os_name == "Windows": with open("start.bat", "w", encoding="utf8") as fp: if restart: fp.write(_(f""" @echo off chcp 65001 :start echo 开始启动MC服务器 {command} echo MC服务器已关闭 echo 服务器正在重新启动..。 echo 按 CTRL + C 停止。 goto :start """)) else: fp.write(_(f""" @echo off chcp 65001 echo 开始启动MC服务器 {command} echo MC服务器已关闭 pause """)) elif os_name == "Linux": with open("start.sh", "w", encoding="utf8") as fp: if restart: fp.write(_(f""" #!/bin/bash echo "开始启动MC服务器" {command} echo "MC服务器已关闭" while true; do echo "按 CTRL + C 停止。" {command} sleep 1 done """)) else: fp.write(_(f""" #!/bin/bash echo "开始启动MC服务器" {command} echo "MC服务器已关闭" """)) else: raise OSError("不支持的操作系统") if __name__ == "__main__": server = detect_jar() if server is None: exit_() command = generate_command(server, detect_brand(server)) generate_batch(command, ask("开启自动重启?")) print("生成完毕") exit_()