GameServerManager/server/data/gameconfig/可视化配置文件.md
2025-09-08 23:14:40 +08:00

454 lines
No EOL
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 可视化配置文件
order: 2
---
## 概述
本系统提供了一套完整的游戏配置文件可视化编辑解决方案,支持多种配置文件格式的解析、编辑和保存。系统由**后端解析器**、**前端可视化组件**和**配置模板**三部分组成。
## 系统架构
::: tabs
@tab 后端解析器
- 负责配置文件的读取、解析和保存,基于 TypeScript 实现。
- 支持多种解析器:
- **configobj**INI 格式,默认)
- **yaml/ruamel.yaml**YAML 格式)
- **properties**Java Properties 格式)
- **json**JSON 格式)
- ⚠️ 当前不支持 HOCON 和 TOML如需支持需自行扩展。
@tab 前端组件
- 提供用户友好的可视化编辑界面。
- 支持双列布局(左侧说明,右侧输入控件)、多种输入类型、嵌套字段、表单验证和类型转换。
@tab 配置模板
- 使用 `.yml` 文件定义配置结构、字段类型和默认值。
- 模板自动检测路径:
1. `data/gameconfig/`(打包路径)
2. `server/data/gameconfig/`(开发环境)
3. `../server/data/gameconfig/`(其他情况)
:::
## 核心类与接口
### GameConfigManager 主要方法
- `getAvailableGameConfigs()`:获取所有可用的游戏配置模板
- `getGameConfigSchema(gameName: string)`:获取指定游戏的配置模板
- `readGameConfig(serverPath: string, configSchema: GameConfigSchema)`:读取配置文件
- `saveGameConfig(serverPath: string, configSchema: GameConfigSchema, configData: ParsedConfigData)`:保存配置文件
- `getDefaultValues(configSchema: GameConfigSchema)`:获取默认值
### 主要接口定义
```typescript
interface GameConfigField {
name: string
display: string
default: any
type: 'string' | 'number' | 'boolean' | 'select' | 'nested'
description?: string
options?: Array<{ value: any; label: string }>
nested_fields?: GameConfigField[]
}
interface GameConfigSection {
key: string
fields: GameConfigField[]
}
interface GameConfigMeta {
game_name: string
config_file: string
parser?: string
}
interface GameConfigSchema {
meta: GameConfigMeta
sections: GameConfigSection[]
}
```
## 添加新游戏配置支持
### 1. 创建配置模板文件
`server/data/gameconfig/` 目录下创建新的 YAML 模板文件,命名格式:`游戏名称.yml`
::: tip
系统会自动扫描该目录下所有 `.yml``.yaml` 文件,并缓存模板以提升性能。
:::
#### 模板文件结构示例
```yaml
meta:
game_name: "游戏显示名称"
config_file: "相对于服务器根目录的配置文件路径"
parser: "解析器类型" # 可选,默认为 configobj
sections:
- key: "配置文件中的 section 名称"
fields:
- name: "字段名称"
display: "显示名称"
default: 默认值
type: "字段类型"
description: "字段描述"
options: # 仅 type 为 select 时需要
- value: "选项值"
label: "选项显示名称"
```
#### 支持的字段类型
- `string`:文本输入框
- `number`:数字输入框
- `boolean`:开关控件
- `select`:下拉选择框(需配置 options
- `nested`:嵌套字段,包含多个子字段
#### 嵌套字段示例
```yaml
- name: "OptionSettings"
display: "选项设置"
type: "nested"
description: "嵌套的选项设置"
nested_fields:
- name: "Difficulty"
display: "游戏难度"
default: "None"
type: "select"
options:
- value: "None"
label: "默认"
- value: "Easy"
label: "简单"
- name: "ExpRate"
display: "经验倍率"
default: 1.0
type: "number"
description: "玩家获得经验的倍率"
```
### 2. 配置解析器选择
根据目标游戏配置文件格式选择解析器:
- INI 格式(推荐,默认):
```yaml
meta:
parser: "configobj"
```
- YAML 格式:
```yaml
meta:
parser: "yaml"
# 或
meta:
parser: "ruamel.yaml"
```
- Properties 格式:
```yaml
meta:
parser: "properties"
```
- JSON 格式:
```yaml
meta:
parser: "json"
```
::: warning
如未指定 `parser` 字段,系统默认使用 configobj。
:::
### 3. 测试配置
1. 重启后端服务
2. 前端界面选择新添加的游戏配置
3. 测试读取、编辑和保存功能
## 特殊配置处理
### 嵌套字段的数据格式
- 读取时:将括号格式字符串解析为键值对对象
- 保存时:将表单数据组合为原始格式
- 显示时:每个子字段独立显示和编辑
```typescript
// 示例:将 "(Difficulty=None,ExpRate=1.0)" 解析为对象
{
"Difficulty": "None",
"ExpRate": 1.0
}
```
### JSON 格式特殊处理
- 读取:直接解析 JSON 对象结构,保持原有类型
- 保存:格式化为 JSON 字符串2 空格缩进
```json
{
"server": {
"port": 8080,
"name": "My Game Server",
"options": {
"difficulty": "normal",
"max_players": 20,
"pvp": true
}
}
}
```
### 数据类型转换
- 布尔值:`"true"/"false"` 或 `"1"/"0"` → `true/false`
- 数字:字符串 → 数值类型(失败返回 0
- 字符串:保持原样
## 前端组件扩展
### 新增输入控件类型
在 `GameConfigManager.tsx` 的 `renderInputComponent` 函数中扩展:
```typescript
else if (fieldType === 'custom_type') {
inputComponent = <CustomComponent style={{ textAlign: 'center' }} />;
}
```
### 自定义样式
采用双列布局,可通过样式自定义:
```typescript
// 左侧信息列
<Col span={12} style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center'
}}>
// 右侧输入列
<Col span={12} style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}}>
```
## 后端解析器扩展
### 添加新解析器
1. 在 `GameConfigManager` 构造函数注册:
```typescript
this.supportedParsers = new Map([
['properties', this.parseWithProperties.bind(this)],
['configobj', this.parseWithConfigObj.bind(this)],
['yaml', this.parseWithYaml.bind(this)],
['ruamel.yaml', this.parseWithYaml.bind(this)],
['json', this.parseWithJson.bind(this)],
['new_parser', this.parseWithNewParser.bind(this)] // 新增解析器
])
```
2. 实现解析方法:
```typescript
private async parseWithNewParser(configPath: string, configSchema: GameConfigSchema): Promise<ParsedConfigData> {
try {
// 实现解析逻辑
const content = await fs.readFile(configPath, 'utf-8')
// ... 解析逻辑
return result
} catch (error) {
logger.error('新解析器解析失败:', error)
throw error
}
}
```
3. 在 `saveGameConfig` 方法添加保存逻辑:
```typescript
switch (parserType) {
case 'properties':
await this.saveWithProperties(fullConfigPath, configData, configSchema)
break
// ... 其他 case
case 'new_parser':
await this.saveWithNewParser(fullConfigPath, configData, configSchema)
break
default:
throw new Error(`不支持的解析器类型: ${parserType}`)
}
```
4. 实现保存方法:
```typescript
private async saveWithNewParser(configPath: string, configData: ParsedConfigData, configSchema: GameConfigSchema): Promise<void> {
// 实现保存逻辑
const content = this.formatConfigData(configData, configSchema)
await fs.writeFile(configPath, content, 'utf-8')
}
```
## 错误处理与日志
- 配置文件不存在、解析器不支持、文件解析失败、保存失败均有详细报错
- 日志记录 INFO/WARN/ERROR/DEBUG便于排查
- 配置模板缓存机制,提升性能
## 常见问题与解决方案
::: details 配置文件读取失败
- 路径不正确、文件不存在、权限问题、解析器不匹配
- 检查路径、权限、解析器类型,查看日志
:::
::: details 嵌套字段显示异常
- 模板 `nested_fields` 配置不正确、数据格式异常、类型定义错误
- 检查模板结构和字段类型
:::
::: details 保存后配置无效
- 数据格式不符、类型转换错误、权限问题
- 检查保存格式、类型转换、写入权限
:::
::: details 配置模板加载失败
- YAML 格式错误、路径不对、编码问题
- 使用 YAML 校验工具,检查目录和编码
:::
## 最佳实践
- 字段描述清晰、默认值合理、数值字段标注范围、显示名称友好
- 优先用成熟解析器,匹配格式,关注性能
- 模板提供 fallback 默认值,优雅降级,详细日志
- 前端表单验证、显示说明、支持重置
- TypeScript 类型定义、统一代码风格、详细注释、依赖常更新
- 缓存机制、异步文件操作、内存优化
## 示例Minecraft 配置模板
```yaml
meta:
game_name: "Minecraft服务器"
config_file: "server.properties"
parser: "properties"
sections:
- key: "server"
fields:
- name: "server-port"
display: "服务器端口"
default: 25565
type: "number"
description: "服务器监听端口范围1024-65535"
- name: "max-players"
display: "最大玩家数"
default: 20
type: "number"
description: "服务器最大同时在线玩家数"
- name: "gamemode"
display: "游戏模式"
default: "survival"
type: "select"
options:
- value: "survival"
label: "生存模式"
- value: "creative"
label: "创造模式"
- value: "adventure"
label: "冒险模式"
- value: "spectator"
label: "观察者模式"
description: "默认游戏模式"
- name: "pvp"
display: "PVP模式"
default: true
type: "boolean"
description: "是否启用玩家对战"
```
## 示例JSON 格式游戏配置
```yaml
meta:
game_name: "示例JSON游戏"
config_file: "config.json"
parser: "json"
sections:
- key: "server"
fields:
- name: "port"
display: "服务器端口"
default: 8080
type: "number"
description: "服务器监听端口"
- name: "name"
display: "服务器名称"
default: "My Game Server"
type: "string"
description: "服务器显示名称"
- name: "settings"
display: "游戏设置"
type: "nested"
description: "嵌套的游戏设置"
nested_fields:
- name: "difficulty"
display: "难度"
default: "normal"
type: "select"
options:
- value: "easy"
label: "简单"
- value: "normal"
label: "普通"
- value: "hard"
label: "困难"
- name: "max_players"
display: "最大玩家数"
default: 10
type: "number"
```
对应 JSON 配置文件:
```json
{
"server": {
"port": 8080,
"name": "My Game Server",
"settings": {
"difficulty": "normal",
"max_players": 10
}
}
}
```
## 依赖库说明
- **yaml**YAML 文件解析与生成
- **properties-reader**Java Properties 文件解析
- **fs/promises**:异步文件系统操作
如需添加新解析器,请在 `package.json` 添加依赖。
---
通过本页文档,开发者可快速为新游戏添加配置文件可视化支持。模块化设计便于扩展解析器和模板,正确配置模板、选择解析器并遵循最佳实践可保障系统稳定与体验。