| print("STARTED") |
|
|
| import gradio as gr |
| import spaces, requests, os, time, threading, subprocess, shutil, tarfile, urllib.request |
| from huggingface_hub import hf_hub_download, upload_file |
|
|
| |
| |
| |
| ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| BASE_DIR = os.path.join(ROOT_DIR, "minecraft_server") |
|
|
| 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") |
|
|
| |
| |
| |
| ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "") |
| HF_TOKEN = os.environ.get("HF_TOKEN", "") |
| PLAYIT_AUTH_KEY = os.environ.get("PLAYIT_AUTH_KEY", "") |
|
|
| HF_REPO_ID = "Dalleon/McSaves" |
|
|
| |
| |
| |
| SERVER_PROCESS = None |
| TCP_PROCESS = None |
| PUBLIC_TCP = None |
| SERVER_ONLINE = False |
|
|
| |
| |
| |
| def keep_alive(): |
| while True: |
| try: |
| requests.get("http://127.0.0.1:7860") |
| print("[KEEPALIVE]") |
| except: |
| pass |
| time.sleep(240) |
|
|
| |
| |
| |
| def install_java(): |
| print("[JAVA] Installing...") |
| url = "https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz" |
| path = os.path.join(BASE_DIR, "java.tar.gz") |
|
|
| urllib.request.urlretrieve(url, path) |
|
|
| extract = os.path.join(BASE_DIR, "java") |
| os.makedirs(extract, exist_ok=True) |
|
|
| with tarfile.open(path, "r:gz") as tar: |
| tar.extractall(extract) |
|
|
| for f in os.listdir(extract): |
| if f.startswith("jdk"): |
| java_home = os.path.join(extract, f) |
| os.environ["JAVA_HOME"] = java_home |
| os.environ["PATH"] = os.path.join(java_home, "bin") + ":" + os.environ["PATH"] |
| print("[JAVA] Ready") |
|
|
| |
| |
| |
| 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) |
|
|
| |
| |
| |
| def save_world(): |
| global SERVER_PROCESS |
|
|
| print("[SAVE] Saving...") |
|
|
| if SERVER_PROCESS: |
| SERVER_PROCESS.stdin.write("save-all\n") |
| SERVER_PROCESS.stdin.flush() |
| time.sleep(10) |
|
|
| tar_path = os.path.join(BASE_DIR, "world.tar.gz") |
|
|
| with tarfile.open(tar_path, "w:gz") as tar: |
| if os.path.exists(WORLD_PATH): |
| tar.add(WORLD_PATH, arcname="world") |
| if os.path.exists(NETHER_PATH): |
| tar.add(NETHER_PATH, arcname="world_nether") |
| if os.path.exists(END_PATH): |
| tar.add(END_PATH, arcname="world_the_end") |
|
|
| try: |
| upload_file( |
| path_or_fileobj=tar_path, |
| path_in_repo="world.tar.gz", |
| repo_id=HF_REPO_ID, |
| token=HF_TOKEN, |
| repo_type="model" |
| ) |
| print("[SAVE] Uploaded") |
| except Exception as e: |
| print("[SAVE ERROR]", e) |
|
|
| |
| |
| |
| def load_world(): |
| print("[LOAD] Loading...") |
|
|
| 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) |
|
|
| |
| |
| |
| 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) |
|
|
| |
| |
| |
| def start_server(): |
| global SERVER_PROCESS |
|
|
| print("[SERVER] Booting...") |
|
|
| time.sleep(5) |
|
|
| load_world() |
|
|
| if shutil.which("java") is None: |
| install_java() |
|
|
| if shutil.which("java") is None: |
| print("[ERROR] Java missing") |
| return |
|
|
| with open(os.path.join(BASE_DIR, "eula.txt"), "w") as f: |
| f.write("eula=true") |
|
|
| SERVER_PROCESS = subprocess.Popen( |
| [ |
| shutil.which("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() |
|
|
| |
| |
| |
| def watchdog(): |
| global SERVER_PROCESS |
| while True: |
| if SERVER_PROCESS and SERVER_PROCESS.poll() is not None: |
| print("[WATCHDOG] Restarting...") |
| start_server() |
| time.sleep(10) |
|
|
| |
| |
| |
| def start_background(): |
| threading.Thread(target=start_server, daemon=True).start() |
| threading.Thread(target=keep_alive, daemon=True).start() |
| threading.Thread(target=watchdog, daemon=True).start() |
|
|
| |
| |
| |
| def get_address(): |
| if not SERVER_ONLINE: |
| return "Starting..." |
| return PUBLIC_TCP or "No address yet" |
|
|
| |
| |
| |
| with gr.Blocks() as app: |
| gr.Markdown("## ⛏️ Minecraft Server") |
|
|
| address = gr.Textbox(label="Server Address") |
| btn = gr.Button("Get Address") |
| start_btn = gr.Button("Start Server (if not running)") |
|
|
| btn.click(fn=get_address, outputs=address) |
| start_btn.click(fn=start_background) |
|
|
| |
| |
|
|
| app.launch() |