print("STARTED") import gradio as gr import requests, os, time, threading, subprocess, shutil, tarfile, urllib.request from huggingface_hub import hf_hub_download, upload_file # ======================== # PATHS # ======================== ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.join(ROOT_DIR, "minecraft_server") os.makedirs(BASE_DIR, exist_ok=True) WORLD_PATH = os.path.join(BASE_DIR, "world") NETHER_PATH = os.path.join(BASE_DIR, "world_nether") END_PATH = os.path.join(BASE_DIR, "world_the_end") # ======================== # ENV # ======================== HF_TOKEN = os.environ.get("HF_TOKEN", "") PLAYIT_AUTH_KEY = os.environ.get("PLAYIT_AUTH_KEY", "") HF_REPO_ID = "Dalleon/McSaves" # ======================== # GLOBALS # ======================== SERVER_PROCESS = None TCP_PROCESS = None PUBLIC_TCP = None SERVER_ONLINE = False # ======================== # DOWNLOAD PAPER (1.20.6) # ======================== def download_paper(): jar_path = os.path.join(BASE_DIR, "server.jar") if os.path.exists(jar_path): print("[PAPER] already exists") return print("[PAPER] downloading 1.20.6...") url = "https://api.papermc.io/v2/projects/paper/versions/1.20.6/builds/latest/downloads/paper-1.20.6-latest.jar" urllib.request.urlretrieve(url, jar_path) # ======================== # READ OUTPUT # ======================== def read_output(): global SERVER_PROCESS while True: if SERVER_PROCESS and SERVER_PROCESS.stdout: line = SERVER_PROCESS.stdout.readline() if line: print("[MC]", line.strip()) time.sleep(0.1) # ======================== # LOAD WORLD # ======================== def load_world(): try: file_path = hf_hub_download( repo_id=HF_REPO_ID, filename="world.tar.gz", token=HF_TOKEN ) except: print("[LOAD] no backup") return if os.path.exists(WORLD_PATH): shutil.rmtree(WORLD_PATH) with tarfile.open(file_path, "r:gz") as tar: tar.extractall(BASE_DIR) # ======================== # PLAYIT # ======================== def start_tcp(): global PUBLIC_TCP, SERVER_ONLINE, TCP_PROCESS path = os.path.join(BASE_DIR, "playit") if not os.path.exists(path): print("[PLAYIT] downloading...") urllib.request.urlretrieve( "https://github.com/playit-cloud/playit-agent/releases/latest/download/playit-linux-amd64", path ) os.chmod(path, 0o755) TCP_PROCESS = subprocess.Popen( [path, "--secret", PLAYIT_AUTH_KEY], cwd=BASE_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) timeout = time.time() + 20 while time.time() < timeout: line = TCP_PROCESS.stdout.readline() if line: print("[PLAYIT]", line.strip()) if "playit.gg" in line: for part in line.split(): if "playit.gg" in part: PUBLIC_TCP = part break if PUBLIC_TCP: break SERVER_ONLINE = True print("[PLAYIT] address:", PUBLIC_TCP) # ======================== # START SERVER # ======================== def start_server(): global SERVER_PROCESS print("[SERVER] starting...") load_world() download_paper() # accept eula with open(os.path.join(BASE_DIR, "eula.txt"), "w") as f: f.write("eula=true") SERVER_PROCESS = subprocess.Popen( [ "java", "-Xms512M", "-Xmx1G", "-jar", "server.jar", "--nogui" ], cwd=BASE_DIR, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) threading.Thread(target=read_output, daemon=True).start() time.sleep(5) start_tcp() # ======================== # START BUTTON HANDLER # ======================== def start_background(): threading.Thread(target=start_server, daemon=True).start() return "Starting server..." # ======================== # GET ADDRESS # ======================== def get_address(): if not SERVER_ONLINE: return "Starting..." return PUBLIC_TCP or "No address yet" # ======================== # UI # ======================== with gr.Blocks() as app: gr.Markdown("## ⛏️ Minecraft Server") start_btn = gr.Button("Start Server") status = gr.Textbox(label="Status") addr_btn = gr.Button("Get Address") address = gr.Textbox(label="Server Address") start_btn.click(fn=start_background, outputs=status) addr_btn.click(fn=get_address, outputs=address) app.launch()