import os import subprocess import threading import requests from fastapi import FastAPI from fastapi.responses import HTMLResponse import uvicorn app = FastAPI() MC_PATH = "/data/minecraft" PORT = 7860 MAX_RAM = "2G" MIN_RAM = "1G" SERVER_VERSION = "1.20.1" logs = [] mc_process = None def log(msg): print(msg) logs.append(msg) if len(logs) > 100: logs.pop(0) def setup(): os.makedirs(MC_PATH, exist_ok=True) with open(f"{MC_PATH}/eula.txt", "w") as f: f.write("eula=true\n") props = f"{MC_PATH}/server.properties" if not os.path.exists(props): with open(props, "w") as f: f.write( "online-mode=false\n" "server-port=25565\n" "motd=HF Fabric Server\n" ) def download_fabric(): jar = f"{MC_PATH}/fabric-server-launch.jar" if os.path.exists(jar): log("Fabric already exists") return log("Downloading Fabric...") loader = requests.get( "https://meta.fabricmc.net/v2/versions/loader" ).json()[0] loader_version = loader["loader"]["version"] installer_version = loader["installer"]["version"] installer_url = ( f"https://meta.fabricmc.net/v2/versions/installer/" f"{installer_version}" ) r = requests.get(installer_url) with open("/tmp/fabric-installer.jar", "wb") as f: f.write(r.content) cmd = [ "java", "-jar", "/tmp/fabric-installer.jar", "server", "-mcversion", SERVER_VERSION, "-loader", loader_version, "-downloadMinecraft" ] subprocess.run(cmd, cwd=MC_PATH) log("Fabric installed!") def start_mc(): global mc_process setup() download_fabric() jar = f"{MC_PATH}/fabric-server-launch.jar" cmd = [ "java", f"-Xms{MIN_RAM}", f"-Xmx{MAX_RAM}", "-jar", jar, "nogui" ] log("Starting Minecraft...") mc_process = subprocess.Popen( cmd, cwd=MC_PATH, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) def read_logs(): for line in mc_process.stdout: log(line.strip()) threading.Thread(target=read_logs, daemon=True).start() def start_playit(): log("Downloading Playit...") r = requests.get( "https://github.com/playit-cloud/playit-agent/releases/latest/download/playit-linux-amd64" ) with open("/tmp/playit", "wb") as f: f.write(r.content) os.chmod("/tmp/playit", 0o755) log("Starting Playit...") p = subprocess.Popen( ["/tmp/playit"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) def read_playit(): for line in p.stdout: log("[PLAYIT] " + line.strip()) threading.Thread(target=read_playit, daemon=True).start() @app.on_event("startup") async def startup(): threading.Thread(target=start_mc, daemon=True).start() @app.get("/", response_class=HTMLResponse) async def home(): text = "\n".join(logs[-50:]) return f"""
{text}
"""
@app.get("/start-playit")
async def playit_route():
threading.Thread(
target=start_playit,
daemon=True
).start()
return {"ok": True}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=PORT)