Fix server management issues and improve overall stability

Major server management fixes:
- Replace Flatpak-specific pkill with universal process tree termination using pstree + process.kill()
- Fix signal format errors (SIGTERM/SIGKILL instead of TERM/KILL strings)
- Add 5-second cooldown after server stop to prevent race conditions with external detection
- Enable Stop Server button for external servers in UI
- Implement proper timeout handling with process tree killing

ContentDB improvements:
- Fix download retry logic and "closed" error by preventing concurrent zip extraction
- Implement smart root directory detection and stripping during package extraction
- Add game-specific timeout handling (8s for VoxeLibre vs 3s for simple games)

World creation fixes:
- Make world creation asynchronous to prevent browser hangs
- Add WebSocket notifications for world creation completion status

Other improvements:
- Remove excessive debug logging
- Improve error handling and user feedback throughout the application
- Clean up temporary files and unnecessary logging

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nathan Schneider
2025-08-24 19:17:38 -06:00
parent 3aed09b60f
commit 2d3b1166fe
15 changed files with 851 additions and 536 deletions

View File

@@ -4,6 +4,7 @@ const fs = require('fs').promises;
const paths = require('../utils/paths');
const ConfigParser = require('../utils/config-parser');
const appConfig = require('../utils/app-config');
const PackageRegistry = require('../utils/package-registry');
const router = express.Router();
@@ -170,8 +171,11 @@ router.post('/update', async (req, res) => {
if (newDataDir && newDataDir !== appConfig.getDataDirectory()) {
try {
await appConfig.setDataDirectory(newDataDir);
// Update paths to use new directory
await paths.initialize();
// Force reload paths to use new directory
await paths.forceReload();
// Reinitialize package registry to use new directory
const packageRegistry = new PackageRegistry();
await packageRegistry.reinitialize();
} catch (error) {
throw new Error(`Failed to update data directory: ${error.message}`);
}
@@ -286,6 +290,53 @@ router.get('/api/schema', (req, res) => {
});
// Get current configuration (API)
// Change data directory only
router.post('/change-data-directory', async (req, res) => {
try {
const { newDataDirectory } = req.body;
if (!newDataDirectory || !newDataDirectory.trim()) {
return res.status(400).json({
success: false,
error: 'Data directory path is required'
});
}
const newDataDir = newDataDirectory.trim();
const currentDataDir = appConfig.getDataDirectory();
if (newDataDir === currentDataDir) {
return res.json({
success: true,
message: 'Data directory is already set to this path',
dataDirectory: currentDataDir
});
}
// Validate and set new data directory
await appConfig.load();
await appConfig.setDataDirectory(newDataDir);
await appConfig.save();
// Update paths to use new directory
await paths.initialize();
res.json({
success: true,
message: 'Data directory updated successfully. Please restart the application for all changes to take effect.',
dataDirectory: newDataDir,
previousDirectory: currentDataDir
});
} catch (error) {
console.error('Error changing data directory:', error);
res.status(500).json({
success: false,
error: `Failed to change data directory: ${error.message}`
});
}
});
router.get('/api/current', async (req, res) => {
try {
const config = await ConfigParser.parseConfig(paths.configFile);