Skip to content

Commit a4e7fbd

Browse files
committed
fix: Soluciona bugs críticos y mejora la robustez
Este commit aborda varios problemas críticos para mejorar la estabilidad y la experiencia de usuario: - fix(operators): Corrige un bug donde el comando 'op list' aparecía como un operador en la GUI. Se ha separado la lógica de visualización de comandos de la de procesamiento de salida del servidor. - fix(resources): Soluciona el problema de la pestaña de Recursos, que no mostraba el uso de CPU/RAM. La nueva lógica ahora monitoriza el proceso hijo de Java en lugar del script de inicio, asegurando mediciones precisas. - fix(java): Actualiza la lógica de detección de la versión de Java requerida para que sea compatible con Minecraft 1.21 y versiones futuras, solucionando el error 'UnsupportedClassVersionError'. - fix(gui): Resuelve un 'TclError' que ocurría al refrescar la lista de jugadores. Se ha optimizado la creación de widgets para evitar referencias a elementos destruidos.
1 parent 5c82700 commit a4e7fbd

File tree

3 files changed

+58
-22
lines changed

3 files changed

+58
-22
lines changed

minecraft_server_gui.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def __init__(self, master):
5959
self.expecting_player_list_next_line = False
6060
self.player_count_line_prefix = "There are "
6161
self.player_count_line_suffix = " players online:"
62+
self.psutil_proc = None
6263

6364
# --- TK Variables ---
6465
self.master = master
@@ -1200,7 +1201,10 @@ def _create_resources_view_widgets(self, parent_frame):
12001201
self.cpu_percent_label.pack(side=tk.LEFT, expand=True)
12011202

12021203
def _update_resource_usage(self):
1203-
if not hasattr(self, 'server_handler') or not self.server_handler.is_running():
1204+
is_running = hasattr(self, 'server_handler') and self.server_handler.is_running()
1205+
1206+
if not is_running:
1207+
self.psutil_proc = None # Reset process cache when server is off
12041208
if matplotlib_available and hasattr(self, 'line_cpu'):
12051209
self.cpu_history = [0.0] * 50
12061210
self.ram_history = [0.0] * 50
@@ -1214,29 +1218,52 @@ def _update_resource_usage(self):
12141218

12151219
try:
12161220
pid = self.server_handler.get_pid()
1217-
if pid is None: return
1218-
proc = psutil.Process(pid)
1219-
cpu_percent = proc.cpu_percent(interval=None) / (psutil.cpu_count() or 1)
1220-
self.cpu_history.pop(0)
1221-
self.cpu_history.append(float(cpu_percent))
1222-
1223-
mem_info = proc.memory_info()
1221+
if pid is None:
1222+
self.psutil_proc = None
1223+
self.master.after(2000, self._update_resource_usage)
1224+
return
1225+
1226+
# If we don't have a process object or the PID has changed, find the correct process to monitor.
1227+
if self.psutil_proc is None or self.psutil_proc.pid != pid:
1228+
parent_proc = psutil.Process(pid)
1229+
1230+
# Search for a java child process, which is the actual server
1231+
java_proc = None
1232+
try:
1233+
children = parent_proc.children(recursive=True)
1234+
for child in children:
1235+
if child.name().lower() in ['java.exe', 'javaw.exe']:
1236+
java_proc = child
1237+
break
1238+
except psutil.NoSuchProcess:
1239+
pass # Parent process might have already died, which is fine.
1240+
1241+
self.psutil_proc = java_proc if java_proc else parent_proc
1242+
self.psutil_proc.cpu_percent(interval=None) # Prime the measurement
1243+
1244+
# Now, get the actual usage from the correct process
1245+
cpu_percent = self.psutil_proc.cpu_percent(interval=None) / (psutil.cpu_count() or 1)
1246+
mem_info = self.psutil_proc.memory_info()
12241247
ram_percent = (mem_info.rss / psutil.virtual_memory().total) * 100
1225-
self.ram_history.pop(0)
1226-
self.ram_history.append(ram_percent)
1248+
1249+
self.cpu_history.pop(0); self.cpu_history.append(float(cpu_percent))
1250+
self.ram_history.pop(0); self.ram_history.append(ram_percent)
12271251

12281252
if matplotlib_available and self.resource_canvas.get_tk_widget().winfo_exists():
12291253
self.line_cpu.set_ydata(self.cpu_history)
12301254
self.line_ram.set_ydata(self.ram_history)
1255+
self.ax_cpu.set_ylim(0, max(10, (max(self.cpu_history) // 10 + 2) * 10))
1256+
self.ax_ram.set_ylim(0, max(10, (max(self.ram_history) // 5 + 2) * 5))
12311257
self.resource_canvas.draw()
12321258
self.cpu_percent_label.configure(text=f"CPU: {cpu_percent:.1f}%")
12331259
self.ram_label.configure(text=f"RAM: {mem_info.rss / (1024**2):.0f}MB ({ram_percent:.1f}%)")
12341260

1235-
except (psutil.NoSuchProcess, psutil.AccessDenied): pass
1261+
except (psutil.NoSuchProcess, psutil.AccessDenied):
1262+
self.psutil_proc = None # Process died, clear the cache
12361263
finally:
12371264
self.master.after(2000, self._update_resource_usage)
12381265

1239-
def log_to_console(self, msg, level="info"):
1266+
def _write_to_console_widgets(self, msg, level="info"):
12401267
text_boxes = []
12411268
if hasattr(self, 'full_console_output_area') and self.full_console_output_area.winfo_exists():
12421269
text_boxes.append(self.full_console_output_area)
@@ -1247,6 +1274,8 @@ def log_to_console(self, msg, level="info"):
12471274
text_box.insert(tk.END, msg, level)
12481275
text_box.see(tk.END)
12491276

1277+
def log_to_console(self, msg, level="info"):
1278+
self._write_to_console_widgets(msg, level)
12501279
self.process_server_output(msg, level)
12511280

12521281
def start_server_thread(self):
@@ -1406,13 +1435,15 @@ def send_command_from_entry(self, event=None): self.send_command_from_button()
14061435
def send_command_from_button(self):
14071436
cmd = self.command_entry.get().strip()
14081437
if cmd:
1438+
self._write_to_console_widgets(f"> {cmd}\n", "info")
14091439
self.server_handler.send_command(cmd)
14101440
self.command_entry.delete(0, tk.END)
14111441

14121442
def send_command_from_console_entry(self, event=None): self.send_command_from_console_button()
14131443
def send_command_from_console_button(self):
14141444
cmd = self.console_command_entry.get().strip()
14151445
if cmd:
1446+
self._write_to_console_widgets(f"> {cmd}\n", "info")
14161447
self.server_handler.send_command(cmd)
14171448
self.console_command_entry.delete(0, tk.END)
14181449

@@ -1522,13 +1553,11 @@ def _refresh_players_display(self):
15221553

15231554
ctk.CTkButton(row, text="Ban", width=50, command=lambda p=player_name: self._context_ban_player(p)).pack(side=tk.RIGHT, padx=5, pady=5)
15241555
ctk.CTkButton(row, text="Kick", width=50, command=lambda p=player_name: self._context_kick_player(p)).pack(side=tk.RIGHT, padx=5, pady=5)
1525-
op_button = ctk.CTkButton(row, text="Op", width=50, command=lambda p=player_name: self._context_op_player(p, True))
1526-
deop_button = ctk.CTkButton(row, text="De-Op", width=50, command=lambda p=player_name: self._context_op_player(p, False))
15271556

15281557
if player_name in self.ops_list:
1529-
deop_button.pack(side=tk.RIGHT, padx=5, pady=5)
1558+
ctk.CTkButton(row, text="De-Op", width=50, command=lambda p=player_name: self._context_op_player(p, False)).pack(side=tk.RIGHT, padx=5, pady=5)
15301559
else:
1531-
op_button.pack(side=tk.RIGHT, padx=5, pady=5)
1560+
ctk.CTkButton(row, text="Op", width=50, command=lambda p=player_name: self._context_op_player(p, True)).pack(side=tk.RIGHT, padx=5, pady=5)
15321561

15331562
self._update_dashboard_info()
15341563

server/server_handler.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ def send_command(self, command):
213213
try:
214214
self.server_process.stdin.write(f"{command}\n")
215215
self.server_process.stdin.flush()
216-
self.output_callback(f"> {command}\n", "info")
217216
except (IOError, ValueError) as e:
218217
self.output_callback(f"Error sending command: {e}\n", "error")
219218
else:

utils/helpers.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,21 @@ def get_required_java_version(minecraft_version_str):
4545
if len(parts) >= 2:
4646
minor_version = int(parts[1])
4747

48-
if minor_version >= 20:
49-
# MC 1.20.5+ requires Java 21
48+
# Minecraft 1.21+ requires Java 21
49+
if minor_version >= 21:
50+
return 21
51+
52+
# Minecraft 1.20.5+ requires Java 21
53+
if minor_version == 20:
5054
if len(parts) > 2 and int(parts[2]) >= 5:
5155
return 21
52-
return 17 # MC 1.20 to 1.20.4
53-
elif minor_version >= 17:
54-
return 17 # MC 1.17 to 1.19
56+
# MC 1.20 to 1.20.4 use Java 17
57+
return 17
58+
59+
# Minecraft 1.17 to 1.19.4 use Java 17
60+
if minor_version >= 17:
61+
return 17
62+
5563
except (ValueError, IndexError):
5664
pass # Fallback to default if parsing fails
5765

0 commit comments

Comments
 (0)