A modern web interface for Luanti (Minetest) server management with ContentDB integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
125 lines
3.3 KiB
JavaScript
125 lines
3.3 KiB
JavaScript
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
|
|
class ConfigParser {
|
|
static async parseConfig(filePath) {
|
|
try {
|
|
const content = await fs.readFile(filePath, 'utf8');
|
|
const config = {};
|
|
|
|
const lines = content.split('\n');
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
|
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
|
|
const equalIndex = trimmed.indexOf('=');
|
|
if (equalIndex === -1) continue;
|
|
|
|
const key = trimmed.substring(0, equalIndex).trim();
|
|
const value = trimmed.substring(equalIndex + 1).trim();
|
|
|
|
config[key] = value;
|
|
}
|
|
|
|
return config;
|
|
} catch (error) {
|
|
if (error.code === 'ENOENT') {
|
|
return {};
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
static async writeConfig(filePath, config) {
|
|
const lines = [];
|
|
|
|
for (const [key, value] of Object.entries(config)) {
|
|
if (value !== undefined && value !== null) {
|
|
lines.push(`${key} = ${value}`);
|
|
}
|
|
}
|
|
|
|
await fs.writeFile(filePath, lines.join('\n') + '\n', 'utf8');
|
|
}
|
|
|
|
static async parseModConfig(filePath) {
|
|
const config = await this.parseConfig(filePath);
|
|
|
|
if (config.depends) {
|
|
config.depends = config.depends.split(',').map(dep => dep.trim()).filter(Boolean);
|
|
} else {
|
|
config.depends = [];
|
|
}
|
|
|
|
if (config.optional_depends) {
|
|
config.optional_depends = config.optional_depends.split(',').map(dep => dep.trim()).filter(Boolean);
|
|
} else {
|
|
config.optional_depends = [];
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
static async writeModConfig(filePath, config) {
|
|
const configCopy = { ...config };
|
|
|
|
if (Array.isArray(configCopy.depends)) {
|
|
configCopy.depends = configCopy.depends.join(', ');
|
|
}
|
|
|
|
if (Array.isArray(configCopy.optional_depends)) {
|
|
configCopy.optional_depends = configCopy.optional_depends.join(', ');
|
|
}
|
|
|
|
await this.writeConfig(filePath, configCopy);
|
|
}
|
|
|
|
static async parseWorldConfig(filePath) {
|
|
const config = await this.parseConfig(filePath);
|
|
|
|
const booleanFields = ['creative_mode', 'enable_damage', 'enable_pvp', 'server_announce'];
|
|
for (const field of booleanFields) {
|
|
if (config[field] !== undefined) {
|
|
config[field] = config[field] === 'true';
|
|
}
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
static async writeWorldConfig(filePath, config) {
|
|
const configCopy = { ...config };
|
|
|
|
const booleanFields = ['creative_mode', 'enable_damage', 'enable_pvp', 'server_announce'];
|
|
for (const field of booleanFields) {
|
|
if (typeof configCopy[field] === 'boolean') {
|
|
configCopy[field] = configCopy[field].toString();
|
|
}
|
|
}
|
|
|
|
await this.writeConfig(filePath, configCopy);
|
|
}
|
|
|
|
static async parseGameConfig(filePath) {
|
|
const config = await this.parseConfig(filePath);
|
|
|
|
// Parse common game config fields
|
|
if (config.name) {
|
|
config.name = config.name.trim();
|
|
}
|
|
if (config.title) {
|
|
config.title = config.title.trim();
|
|
}
|
|
if (config.description) {
|
|
config.description = config.description.trim();
|
|
}
|
|
if (config.author) {
|
|
config.author = config.author.trim();
|
|
}
|
|
|
|
return config;
|
|
}
|
|
}
|
|
|
|
module.exports = ConfigParser; |