Skip to content

Commit 68159da

Browse files
committed
v1.2.1: Console improvements, auto-restart, stability fixes - Auto-restart on server crash with Dashboard toggle and max 3 attempts - Console search/filter bar with level badges and export logs button - Console input always enabled with REST API fallback when WS disconnected - Dashboard & Console now stay mounted preserving logs across tab switches - Dashboard mini-console gets REST fallback for commands - WebSocket error logging added for easier debugging - Fixed polling fallback hardcoded to false, now uses actual isConnected
1 parent 49fa1a4 commit 68159da

11 files changed

Lines changed: 265 additions & 69 deletions

File tree

README.md

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,37 @@
2828

2929
---
3030

31-
## What's New in v1.2.0
31+
## What's New in v1.2.1
3232

33-
### Complete UI Redesign
34-
- **Pixel art icon system** — Custom 16x16 pixel icons throughout the entire UI for a cohesive Minecraft-inspired aesthetic
35-
- **Visual effects** — Mouse spotlight tracking, noise grain overlay, magnetic button hover effects, and animated abstract backgrounds
36-
- **Server Library** — Completely redesigned server selector with grid view, search, recently opened section, and engine type icons
37-
- **Refined dark theme** — Deeper blacks, improved contrast, and smoother glassmorphism panels
33+
### Auto-Restart on Crash
34+
- Server automatically restarts after unexpected shutdowns — toggle it on/off from the Dashboard header
35+
- Up to 3 restart attempts with a 3-second delay between retries
3836

39-
### NeoForge Support
40-
- Full support for **NeoForge** as a server engine alongside Vanilla, Paper, Spigot, Forge, and Fabric
41-
- NeoForge appears in the Setup Wizard, Mods browser, and server cards with its own icon
37+
### Console Improvements
38+
- **Export logs** — Download button saves the full console history as a `.txt` file
39+
- **Search & filter** — Search bar and level filter (All/CMD/INF/WRN/ERR) for quick log navigation
40+
- **Always usable input** — Console input stays enabled even when WebSocket is disconnected (REST API fallback)
4241

43-
### Modpacks
44-
- New **Modpacks** tab in the Mods section — browse and install modpacks directly from Modrinth
42+
### Stability Fixes
43+
- **Logs persist across tab switches** — No more losing console logs when navigating between panels
44+
- **Dashboard mini-console** — REST API fallback for sending commands when WebSocket is down
45+
- **Connection status** — Clear "Disconnected" indicator instead of misleading "Loading..." state
4546

46-
### Multi-Language (i18n)
47-
- Interface available in **English, Spanish, French, and Russian**
48-
- Language selector in the new App Settings panel
47+
---
4948

50-
### App Settings
51-
- New dedicated **Settings panel** with language, theme, notifications, and more options
49+
<details>
50+
<summary><strong>Earlier: v1.2.0 — UI Redesign & NeoForge</strong></summary>
5251

53-
### Other Improvements
54-
- **Error Boundary** — Graceful error handling across the UI
55-
- **WebSocket Context** — Centralized real-time communication layer
56-
- **Engine icons** — Each server type (Vanilla, Paper, Spigot, Forge, NeoForge, Fabric) now has its own visual icon in cards and selectors
57-
- **Improved Mods browser** — Filter by loader (Fabric, Forge, NeoForge, Quilt), version, category, and sort order
52+
### Complete UI Redesign
53+
- **Pixel art icon system** — Custom 16x16 pixel icons throughout the entire UI
54+
- **Visual effects** — Mouse spotlight, noise grain, magnetic buttons, abstract backgrounds
55+
- **Server Library** — Redesigned grid view with search, recently opened, engine type icons
56+
57+
### NeoForge Support & Modpacks
58+
- **NeoForge** as a new server engine + **Modpacks** tab for browsing and installing from Modrinth
59+
- **Multi-Language (i18n)** — English, Spanish, French, and Russian with language selector in App Settings
60+
61+
</details>
5862

5963
---
6064

@@ -80,7 +84,8 @@
8084
### Server Management
8185
- **One-click server creation** — Vanilla, Paper, Spigot, Forge, **NeoForge**, Fabric
8286
- **Multiple server profiles** — Switch between servers instantly
83-
- **Live console** with real-time logs and command input
87+
- **Live console** with real-time logs, search/filter, export, and command input
88+
- **Auto-restart on crash** — Detects and restarts server automatically after unexpected shutdowns
8489
- **Start/Stop controls** with visual status indicators
8590
- **Server Conflict Guard** — Prevents running multiple servers simultaneously
8691

@@ -100,10 +105,11 @@
100105

101106
### Dashboard
102107
- **Real-time stats** — CPU, RAM, and uptime monitoring with sparkline graphs
103-
- **Public Server** — Share your server globally via SSH tunnel (Pinggy)
108+
- **Auto-restart** — Toggle to automatically restart server on crash (max 3 attempts)
109+
- **Public Server** — Share your server globally via SSH tunnel (Pinggy/Playit)
104110
- **Region Selection** — EU, US, and Asia for best latency
105111
- **Local IP display** — Easy LAN connection for friends
106-
- **Quick command input** — Send commands from dashboard
112+
- **Quick command input** — Send commands from dashboard with WebSocket/REST fallback
107113

108114
### Mods & Modpacks
109115
- **Mod search & install** — Browse and install mods from Modrinth

backend/api_server.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,11 @@ def get_status():
622622
and state.tunnel_process.poll() is None,
623623
"address": state.tunnel_address,
624624
},
625+
"auto_restart": {
626+
"enabled": state.server_handler.auto_restart,
627+
"attempt": state.server_handler._restart_count,
628+
"max_attempts": state.server_handler._max_restarts,
629+
},
625630
}
626631

627632

@@ -678,6 +683,26 @@ def cancel_stop_server():
678683
return {"message": message}
679684

680685

686+
@app.post("/server/auto-restart")
687+
def set_auto_restart(enabled: bool = True):
688+
if not state or not state.server_handler:
689+
raise HTTPException(status_code=400, detail="Server not configured")
690+
state.server_handler.auto_restart = enabled
691+
state.server_handler._restart_count = 0
692+
return {"message": f"Auto-restart {'enabled' if enabled else 'disabled'}"}
693+
694+
695+
@app.get("/server/auto-restart")
696+
def get_auto_restart():
697+
if not state or not state.server_handler:
698+
return {"enabled": False, "attempt": 0, "max_attempts": 3}
699+
return {
700+
"enabled": state.server_handler.auto_restart,
701+
"attempt": state.server_handler._restart_count,
702+
"max_attempts": state.server_handler._max_restarts,
703+
}
704+
705+
681706
@app.post("/command")
682707
def send_console_command(cmd: CommandRequest):
683708
if not state or not state.server_handler:

backend/server/server_handler.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ def __init__(
8282
None # Epoch time when shutdown will occur
8383
)
8484

85+
# Auto-restart on crash
86+
self.auto_restart = False
87+
self._restart_count = 0
88+
self._max_restarts = 3
89+
self._restart_delay = 3
90+
8591
# Statistics Cache for low-resource environments
8692
self._stats_cache = {"cpu": 0, "ram": "0/0 GB", "uptime": "0h 0m"}
8793
self._last_stats_time = 0
@@ -860,8 +866,30 @@ def _run_server(self, command, env):
860866
# 2. Enviar mensaje de log final
861867
if not was_stopping:
862868
self._log("Server stopped unexpectedly.\n", "error")
869+
# Auto-restart on crash
870+
if self.auto_restart and self._restart_count < self._max_restarts:
871+
self._restart_count += 1
872+
self._log(
873+
f"Auto-restarting in {self._restart_delay}s "
874+
f"(attempt {self._restart_count}/{self._max_restarts})...\n",
875+
"warning",
876+
)
877+
# Notify frontend about restart attempt
878+
if self.output_callback:
879+
self.output_callback(
880+
{
881+
"type": "auto_restart",
882+
"attempt": self._restart_count,
883+
"max_attempts": self._max_restarts,
884+
"server_id": self.server_id,
885+
}
886+
)
887+
time.sleep(self._restart_delay)
888+
self.start()
889+
return # Don't send offline status, start() will handle it
863890
else:
864891
self._log("Server stopped.\n", "info")
892+
self._restart_count = 0 # Reset on clean stop
865893

866894
# 3. NOTIFICAR AL FRONTEND VIA WEBSOCKET (Explicit event)
867895
# Esto asegura que el frontend limpie cualquier estado 'stopping' residual.
@@ -906,6 +934,7 @@ def _process_log_line(
906934
)
907935
self.server_fully_started = True
908936
self.server_stopping = False
937+
self._restart_count = 0 # Reset restart counter on successful start
909938
# Broadcast explicit status change to online
910939
if self.output_callback:
911940
self.output_callback(

changelog.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Minecraft Server GUI - Changelog
22

3+
## Version 1.2.1 - 2026-05-27 CONSOLE & STABILITY UPDATE
4+
5+
### NEW FEATURES:
6+
- **Auto-restart on crash** — Server automatically restarts after unexpected shutdown (toggle in Dashboard header, max 3 attempts)
7+
- **Export console logs** — Download button in Console tab saves logs as .txt file
8+
- **Search & filter in console** — Search bar and level filter (All/CMD/INF/WRN/ERR) for quick log navigation
9+
10+
### BUG FIXES:
11+
- **Fixed console tab loading forever** — Input no longer disabled when WebSocket is disconnected; REST API fallback works now
12+
- **Fixed logs disappearing on tab switch** — Dashboard and Console components stay mounted; log state preserved across panel navigation
13+
- **Fixed Dashboard mini-console input** — REST API fallback added when WebSocket is disconnected
14+
- **Fixed polling fallback** — No longer hardcoded to always use polling; now correctly checks WebSocket connection state
15+
16+
### IMPROVEMENTS:
17+
- Console connection status now shows "Disconnected" (yellow) instead of "Loading..." (gray) when WebSocket is down
18+
- WebSocket errors now logged to console for easier debugging
19+
- Improved input usability in Console tab (always enabled, falls back to REST API)
20+
21+
---
22+
323
## Version 1.2.0 - 2026-04-30 UI REDESIGN & NEOFORGE
424

525
### UI REDESIGN:

electron-app/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

electron-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "minecraft-server-gui",
33
"private": true,
4-
"version": "1.2.0",
4+
"version": "1.2.1",
55
"repository": {
66
"type": "git",
77
"url": "https://github.com/CalaKuad1/Minecraft-Local-Server-GUI.git"

electron-app/src/App.jsx

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -266,34 +266,40 @@ function App() {
266266
<main className="flex-1 overflow-hidden relative flex flex-col bg-[#050505]/70 backdrop-blur-md w-full">
267267
<div className="flex-1 overflow-y-auto p-8 relative z-10 flex flex-col scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent w-full">
268268
<div className="mx-auto w-full flex-1 flex flex-col">
269+
{/* Dashboard - always mounted to preserve log state */}
270+
<div style={{ display: activeTab !== 'dashboard' ? 'none' : undefined }} className={activeTab === 'dashboard' ? 'flex-1 flex flex-col' : ''}>
271+
<Dashboard status={serverStatus} onRefresh={triggerRefresh} />
272+
</div>
273+
274+
{/* Console - always mounted to preserve log state */}
275+
<div style={{ display: activeTab !== 'console' ? 'none' : undefined }}>
276+
<Console key={selectedServer?.id} />
277+
</div>
278+
279+
{/* Animated transitions for other tabs */}
269280
<AnimatePresence mode="wait">
281+
{activeTab !== 'dashboard' && activeTab !== 'console' && (
270282
<motion.div
271-
key={`${activeTab}-${selectedServer?.id}`}
272-
initial={{ opacity: 0, scale: 0.99, y: 10, filter: 'blur(4px)' }}
273-
animate={{ opacity: 1, scale: 1, y: 0, filter: 'blur(0px)' }}
274-
exit={{ opacity: 0, scale: 0.99, y: -10, filter: 'blur(4px)' }}
275-
transition={{ duration: 0.25, ease: "easeOut" }}
276-
className={activeTab === 'dashboard' ? 'flex-1 flex flex-col' : ''}
277-
style={activeTab === 'console' ? { display: 'none' } : undefined}
278-
>
279-
{activeTab === 'dashboard' && <Dashboard status={serverStatus} onRefresh={triggerRefresh} />}
280-
{activeTab === 'players' && <Players status={serverStatus} />}
281-
{activeTab === 'worlds' && <Worlds />}
282-
{activeTab === 'mods' && <Mods status={serverStatus} onOpenWizard={() => setShowWizard(true)} />}
283-
{activeTab === 'plugins' && <Plugins status={serverStatus} />}
284-
{activeTab === 'settings' && <Settings />}
285-
</motion.div>
286-
</AnimatePresence>
287-
288-
<AnimatePresence>
289-
{showAppSettings && (
290-
<AppSettings isOpen={true} onClose={() => setShowAppSettings(false)} />
291-
)}
292-
</AnimatePresence>
283+
key={`${activeTab}-${selectedServer?.id}`}
284+
initial={{ opacity: 0, scale: 0.99, y: 10, filter: 'blur(4px)' }}
285+
animate={{ opacity: 1, scale: 1, y: 0, filter: 'blur(0px)' }}
286+
exit={{ opacity: 0, scale: 0.99, y: -10, filter: 'blur(4px)' }}
287+
transition={{ duration: 0.25, ease: "easeOut" }}
288+
>
289+
{activeTab === 'players' && <Players status={serverStatus} />}
290+
{activeTab === 'worlds' && <Worlds />}
291+
{activeTab === 'mods' && <Mods status={serverStatus} onOpenWizard={() => setShowWizard(true)} />}
292+
{activeTab === 'plugins' && <Plugins status={serverStatus} />}
293+
{activeTab === 'settings' && <Settings />}
294+
</motion.div>
295+
)}
296+
</AnimatePresence>
293297

294-
{activeTab === 'console' && (
295-
<Console key={selectedServer?.id} />
296-
)}
298+
<AnimatePresence>
299+
{showAppSettings && (
300+
<AppSettings isOpen={true} onClose={() => setShowAppSettings(false)} />
301+
)}
302+
</AnimatePresence>
297303
</div>
298304
</div>
299305
</main>

electron-app/src/api.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ export const api = {
5858
body: JSON.stringify({ command })
5959
});
6060
},
61+
setAutoRestart: async (enabled) => {
62+
await fetchJson(`${API_URL}/server/auto-restart?enabled=${enabled}`, { method: 'POST' });
63+
},
64+
getAutoRestart: async () => {
65+
return await fetchJson(`${API_URL}/server/auto-restart`);
66+
},
6167
scheduleStop: async (minutes) => {
6268
return await fetchJson(`${API_URL}/server/schedule-stop`, {
6369
method: 'POST',

0 commit comments

Comments
 (0)