yobberbyte commited on
Commit
5842b47
·
verified ·
1 Parent(s): a00861d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +276 -1
app.py CHANGED
@@ -1 +1,276 @@
1
- print("Hello World!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ print("STARTED")
2
+
3
+ # Imports
4
+ import gradio as gr
5
+ import spaces, requests, os, time, threading, subprocess, shutil, tarfile, urllib.request, json
6
+
7
+ from huggingface_hub import hf_hub_download, upload_file
8
+
9
+ # ========================
10
+ # PATH SETUP (FIXED)
11
+ # ========================
12
+ ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
13
+ BASE_DIR = os.path.join(ROOT_DIR, "minecraft_server")
14
+
15
+ WORLD_PATH = os.path.join(BASE_DIR, "world")
16
+ NETHER_PATH = os.path.join(BASE_DIR, "world_nether")
17
+ END_PATH = os.path.join(BASE_DIR, "world_the_end")
18
+
19
+ print("[DEBUG] ROOT:", ROOT_DIR)
20
+ print("[DEBUG] BASE:", BASE_DIR)
21
+
22
+ # ========================
23
+ # ENV VARIABLES
24
+ # ========================
25
+ ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "")
26
+ HF_TOKEN = os.environ.get("HF_TOKEN", "")
27
+ PLAYIT_AUTH_KEY = os.environ.get("PLAYIT_AUTH_KEY", "")
28
+
29
+ HF_REPO_ID = "Dalleon/McSaves"
30
+ WORLD_ID = "world_default"
31
+
32
+ # ========================
33
+ # GLOBALS
34
+ # ========================
35
+ SERVER_PROCESS = None
36
+ TCP_PROCESS = None
37
+ PUBLIC_TCP = None
38
+ SERVER_ONLINE = False
39
+
40
+ SERVER_OUTPUT_BUFFER = []
41
+
42
+ # ========================
43
+ # JAVA INSTALL (fallback)
44
+ # ========================
45
+ def install_java21_local():
46
+ jdk_url = "https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz"
47
+ download_path = os.path.join(BASE_DIR, "jdk21.tar.gz")
48
+
49
+ print("[JAVA] Downloading...")
50
+ urllib.request.urlretrieve(jdk_url, download_path)
51
+
52
+ extract_dir = os.path.join(BASE_DIR, "jdk21")
53
+ os.makedirs(extract_dir, exist_ok=True)
54
+
55
+ with tarfile.open(download_path, "r:gz") as tar:
56
+ tar.extractall(path=extract_dir)
57
+
58
+ for item in os.listdir(extract_dir):
59
+ if item.startswith("jdk-21"):
60
+ java_home = os.path.join(extract_dir, item)
61
+ os.environ["JAVA_HOME"] = java_home
62
+ os.environ["PATH"] = os.path.join(java_home, "bin") + ":" + os.environ["PATH"]
63
+ print("[JAVA] Installed:", java_home)
64
+ return
65
+
66
+ # ========================
67
+ # DOWNLOAD PAPER
68
+ # ========================
69
+ def download_paper():
70
+ jar_path = os.path.join(BASE_DIR, "paper.jar")
71
+ if os.path.exists(jar_path):
72
+ return
73
+
74
+ print("[PAPER] Downloading...")
75
+ url = "https://api.papermc.io/v2/projects/paper/versions/1.20.6/builds/latest/downloads/paper-1.20.6-latest.jar"
76
+ urllib.request.urlretrieve(url, jar_path)
77
+
78
+ # ========================
79
+ # SERVER OUTPUT READER
80
+ # ========================
81
+ def read_server_output():
82
+ global SERVER_PROCESS
83
+ while True:
84
+ if SERVER_PROCESS and SERVER_PROCESS.stdout:
85
+ line = SERVER_PROCESS.stdout.readline()
86
+ if line:
87
+ print("[MC]", line.strip())
88
+ SERVER_OUTPUT_BUFFER.append(line)
89
+ time.sleep(0.1)
90
+
91
+ # ========================
92
+ # SAVE WORLD
93
+ # ========================
94
+ def save_world():
95
+ global SERVER_PROCESS
96
+
97
+ print("[SAVE] Saving world...")
98
+
99
+ if SERVER_PROCESS:
100
+ SERVER_PROCESS.stdin.write("save-off\n")
101
+ SERVER_PROCESS.stdin.flush()
102
+
103
+ SERVER_PROCESS.stdin.write("save-all\n")
104
+ SERVER_PROCESS.stdin.flush()
105
+
106
+ time.sleep(10)
107
+
108
+ SERVER_PROCESS.stdin.write("save-on\n")
109
+ SERVER_PROCESS.stdin.flush()
110
+
111
+ tar_path = os.path.join(BASE_DIR, "world.tar.gz")
112
+
113
+ with tarfile.open(tar_path, "w:gz") as tar:
114
+ if os.path.exists(WORLD_PATH):
115
+ tar.add(WORLD_PATH, arcname="world")
116
+
117
+ if os.path.exists(NETHER_PATH):
118
+ tar.add(NETHER_PATH, arcname="world_nether")
119
+
120
+ if os.path.exists(END_PATH):
121
+ tar.add(END_PATH, arcname="world_the_end")
122
+
123
+ upload_file(
124
+ path_or_fileobj=tar_path,
125
+ path_in_repo="world.tar.gz",
126
+ repo_id=HF_REPO_ID,
127
+ token=HF_TOKEN,
128
+ repo_type="model"
129
+ )
130
+
131
+ print("[SAVE] Done.")
132
+
133
+ # ========================
134
+ # LOAD WORLD
135
+ # ========================
136
+ def load_world():
137
+ print("[LOAD] Loading world...")
138
+
139
+ try:
140
+ file_path = hf_hub_download(
141
+ repo_id=HF_REPO_ID,
142
+ filename="world.tar.gz",
143
+ token=HF_TOKEN
144
+ )
145
+ except:
146
+ print("[LOAD] No backup found.")
147
+ return
148
+
149
+ if os.path.exists(WORLD_PATH):
150
+ shutil.rmtree(WORLD_PATH)
151
+
152
+ with tarfile.open(file_path, "r:gz") as tar:
153
+ tar.extractall(BASE_DIR)
154
+
155
+ print("[LOAD] Done.")
156
+
157
+ # ========================
158
+ # PLAYIT TUNNEL (FIXED - NON-BLOCKING)
159
+ # ========================
160
+ def start_tcp():
161
+ global PUBLIC_TCP, SERVER_ONLINE, TCP_PROCESS
162
+
163
+ playit_path = os.path.join(BASE_DIR, "playit")
164
+
165
+ if not os.path.exists(playit_path):
166
+ print("[PLAYIT] Downloading...")
167
+ url = "https://github.com/playit-cloud/playit-agent/releases/latest/download/playit-linux-amd64"
168
+ urllib.request.urlretrieve(url, playit_path)
169
+ os.chmod(playit_path, 0o755)
170
+
171
+ if not PLAYIT_AUTH_KEY:
172
+ print("[PLAYIT] Missing auth key")
173
+ return
174
+
175
+ # ✅ FIX: fully detached process (NO PIPE, NO READLINE, NO FREEZE)
176
+ TCP_PROCESS = subprocess.Popen(
177
+ [playit_path, "--secret", PLAYIT_AUTH_KEY],
178
+ cwd=BASE_DIR,
179
+ stdin=subprocess.DEVNULL,
180
+ stdout=subprocess.DEVNULL,
181
+ stderr=subprocess.DEVNULL,
182
+ start_new_session=True
183
+ )
184
+
185
+ print("[PLAYIT] Agent started safely in background")
186
+
187
+ # small delay so it can initialize without blocking HF
188
+ time.sleep(5)
189
+
190
+ # ❗ IMPORTANT: no blocking log parsing anymore
191
+ PUBLIC_TCP = "Check Playit dashboard for address"
192
+ SERVER_ONLINE = True
193
+
194
+ print("[PLAYIT] Ready (no blocking, HF-safe)")
195
+ # ========================
196
+ # START SERVER
197
+ # ========================
198
+ def start_server():
199
+ global SERVER_PROCESS
200
+
201
+ load_world()
202
+
203
+ if shutil.which("java") is None:
204
+ install_java21_local()
205
+
206
+ if shutil.which("java") is None:
207
+ print("[ERROR] Java not found")
208
+ return
209
+
210
+ download_paper()
211
+
212
+ with open(os.path.join(BASE_DIR, "eula.txt"), "w") as f:
213
+ f.write("eula=true")
214
+
215
+ SERVER_PROCESS = subprocess.Popen(
216
+ [
217
+ shutil.which("java"),
218
+ "-Xms512M",
219
+ "-Xmx1G",
220
+ "-jar",
221
+ "paper.jar",
222
+ "--nogui"
223
+ ],
224
+ cwd=BASE_DIR,
225
+ stdin=subprocess.PIPE,
226
+ stdout=subprocess.PIPE,
227
+ stderr=subprocess.STDOUT,
228
+ text=True
229
+ )
230
+
231
+ threading.Thread(target=read_server_output, daemon=True).start()
232
+
233
+ time.sleep(5)
234
+ start_tcp()
235
+
236
+ # ========================
237
+ # COMMAND EXEC
238
+ # ========================
239
+ def execute_command(password, cmd):
240
+ if password != ADMIN_PASSWORD:
241
+ return "Wrong password"
242
+
243
+ if not SERVER_PROCESS:
244
+ return "Server not running"
245
+
246
+ SERVER_PROCESS.stdin.write(cmd + "\n")
247
+ SERVER_PROCESS.stdin.flush()
248
+
249
+ return "Executed"
250
+
251
+ # ========================
252
+ # GET ADDRESS
253
+ # ========================
254
+ def get_address():
255
+ if not SERVER_ONLINE:
256
+ return "Server starting..."
257
+
258
+ return PUBLIC_TCP or "No address yet"
259
+
260
+ # ========================
261
+ # INIT
262
+ # ========================
263
+ threading.Thread(target=start_server, daemon=True).start()
264
+
265
+ # ========================
266
+ # UI
267
+ # ========================
268
+ with gr.Blocks() as app:
269
+ gr.Markdown("## ⛏️ Minecraft Server")
270
+
271
+ address = gr.Textbox(label="Server Address")
272
+ btn = gr.Button("Get Address")
273
+
274
+ btn.click(fn=get_address, outputs=address)
275
+
276
+ app.launch()