批量提取游戏信息并插入数据库的自动化实践

本文介绍如何从 33 个子游戏项目中自动提取游戏配置信息,并批量插入到 MySQL 数据库的完整流程。通过 Python 脚本自动解析 C++ 头文件,生成 SQL 插入脚本,实现游戏配置信息的快速入库。

**关键词**:游戏开发;数据库;Python;SQL;自动化;MySQL


1. 项目背景

在一个大型游戏平台项目中,我们需要管理 33 个子游戏的配置信息。每个游戏都有一个 `CMD_Game.h` 头文件,其中定义了游戏 ID、游戏名称等关键信息。传统的手动录入方式效率低下且容易出错,因此我们需要一个自动化的解决方案。

1.1 数据结构

数据库表 `GameGameItem` 包含以下关键字段:

| 字段名 | 类型 | 说明 |

|--------|------|------|

| GameID | INT | 游戏唯一标识 |

| GameName | NVARCHAR | 游戏名称 |

| SuportType | INT | 支持类型 |

| DataBaseAddr | NVARCHAR | 数据库地址 |

| DataBaseName | NVARCHAR | 数据库名称 |

| ServerVersion | INT | 服务器版本号 |

| ClientVersion | INT | 客户端版本号 |

| ServerDLLName | NVARCHAR | 服务器 DLL 文件名 |

| ClientExeName | NVARCHAR | 客户端 EXE 文件名 |


2. 游戏信息源分析

2.1 项目结构

```

game/

├── 21 点/

│ └── 消息定义/

│ └── CMD_Game.h

├── 斗地主/

│ └── 消息定义/

│ └── CMD_Game.h

├── 捕鱼达人/

│ └── 消息定义/

│ └── CMD_Game.h

└── ... (共 33 个游戏)

```

2.2 CMD_Game.h 文件格式

每个游戏的 `CMD_Game.h` 文件包含类似以下定义:

```cpp

// 游戏属性

#define KIND_ID 200 // 游戏 ID

#define GAME_NAME TEXT("斗地主") // 游戏名字

```


3. 自动化提取脚本

3.1 Python 提取脚本

```python

-*- coding: utf-8 -*-

"""

从 CMD_*.h 文件中提取游戏 ID 和游戏名称

生成 SQL 插入脚本

"""

import os

import re

def parse_cmd_h_file(file_path):

"""解析 CMD_*.h 文件,提取游戏 ID 和名称"""

game_id = None

game_name = None

try:

with open(file_path, 'r', encoding='gbk', errors='ignore') as f:

content = f.read()

查找 KIND_ID 定义

kind_id_match = re.search(r'#define\s+KIND_ID\s+(\d+)', content)

if kind_id_match:

game_id = int(kind_id_match.group(1))

查找 GAME_NAME 定义

game_name_match = re.search(r'#define\s+GAME_NAME\s+TEXT\("([^"]+)"\)', content)

if game_name_match:

game_name = game_name_match.group(1)

return game_id, game_name

except:

return None, None

def main():

script_dir = os.path.dirname(os.path.abspath(file))

print("=" * 80)

print("从 CMD_*.h 文件提取游戏信息")

print("=" * 80)

print()

games = {}

files_checked = 0

遍历所有 CMD_*.h 文件

for root, dirs, files in os.walk(script_dir):

跳过编译输出目录和旗舰版(避免重复)

dirs[:] = [d for d in dirs if d not in ['bin', 'obj', 'Debug', 'Release',

'.vs', '中间目录', '运行', '编译日志', '旗舰版游戏']]

for file in files:

if file.upper().startswith('CMD_'):

file_path = os.path.join(root, file)

files_checked += 1

game_id, game_name = parse_cmd_h_file(file_path)

if game_id and game_name:

game_dir = os.path.basename(os.path.dirname(os.path.dirname(file_path)))

if game_id not in games:

games[game_id] = {'name': game_name, 'dir': game_dir, 'file': file}

print(f"GameID {game_id}: {game_name} (来自:{game_dir}/{file})")

print()

print("=" * 80)

print(f"检查了 {files_checked} 个文件")

print(f"找到 {len(games)} 个游戏")

print("=" * 80)

生成 SQL 脚本

sql_path = os.path.join(script_dir, 'insert_all_games.sql')

with open(sql_path, 'w', encoding='utf-8-sig') as f:

f.write("-- ============================================\n")

f.write("-- 游戏信息插入脚本 (从 CMD_*.h 自动生成)\n")

f.write("-- 数据库:WHQJPlatformDB\n")

f.write("-- 表名:GameGameItem\n")

f.write("-- ============================================\n\n")

f.write("USE WHQJPlatformDB;\n")

f.write("GO\n\n")

f.write("-- 删除旧数据\n")

f.write("DELETE FROM GameGameItem WHERE GameID >= 100\n")

f.write("GO\n\n")

按 GameID 排序

for game_id in sorted(games.keys()):

game_info = games[game_id]

game_name = game_info['name']

server_dll = f"Game{game_id}Server.dll"

client_exe = f"Game{game_id}.exe"

f.write(f"INSERT INTO GameGameItem (GameID, GameName, SuportType, DataBaseAddr, ")

f.write(f"DataBaseName, ServerVersion, ClientVersion, ServerDLLName, ClientExeName) ")

f.write(f"VALUES ({game_id}, N'{game_name}', 31, '127.0.0.1', 'WHQJPlatformDB', ")

f.write(f"101122049, 101122049, '{server_dll}', '{client_exe}')\n")

f.write("GO\n")

f.write("\n-- 验证\n")

f.write("SELECT GameID, GameName FROM GameGameItem ORDER BY GameID\n")

f.write("GO\n")

print(f"\nSQL 脚本已保存至:{sql_path}")

打印游戏列表

print("\n完整游戏列表:")

print("-" * 80)

for game_id in sorted(games.keys()):

game_info = games[game_id]

print(f" {game_id}: {game_info['name']} ({game_info['dir']})")

if name == "main":

import sys

sys.exit(main())

```

3.2 使用方法

  1. 将脚本保存为 `extract_all_games.py`

  2. 放置在游戏根目录下

  3. 运行脚本:`python extract_all_games.py`

  4. 生成的 SQL 文件:`insert_all_games.sql`


4. SQL 插入脚本

4.1 SQL Server 版本

```sql

-- ============================================

-- 游戏信息插入脚本 (从 CMD_*.h 自动生成)

-- 数据库:WHQJPlatformDB

-- 表名:GameGameItem

-- ============================================

USE WHQJPlatformDB

GO

-- 删除旧数据

DELETE FROM GameGameItem WHERE GameID >= 100

GO

-- 扑克类游戏(12 个)

INSERT INTO GameGameItem (GameID, GameName, SuportType, DataBaseAddr, DataBaseName,

ServerVersion, ClientVersion, ServerDLLName, ClientExeName)

VALUES (200, N'斗地主', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'Game200Server.dll', 'Game200.exe')

GO

-- ... 其他游戏

```

4.2 MySQL 版本

```sql

-- ============================================

-- 游戏信息插入脚本 (MySQL 版本)

-- 从 CMD_*.h 自动生成

-- 数据库:WHQJPlatformDB

-- 表名:GameGameItem

-- ============================================

USE WHQJPlatformDB;

-- 删除旧数据

DELETE FROM GameGameItem WHERE GameID >= 100;

-- 批量插入游戏数据

INSERT INTO GameGameItem (GameID, GameName, SuportType, DataBaseAddr, DataBaseName,

ServerVersion, ClientVersion, ServerDLLName, ClientExeName)

VALUES

(3, '德州扑克', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'DZShowHandServer.dll', 'DZShowHand.exe'),

(51, '浙江十三水', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'ThirteenZJServer.dll', 'ThirteenZJ.exe'),

(56, '疯狂三张', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'ThreeMadnessServer.dll', 'ThreeMadness.exe'),

(57, '八人牛牛', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'OxEightServer.dll', 'OxEight.exe'),

(104, '百人牛牛', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'OxBattleServer.dll', 'OxBattle.exe'),

(200, '斗地主', 31, '127.0.0.1', 'WHQJPlatformDB', 101122049, 101122049,

'LandServer.dll', 'Land.exe');

-- ... 其他游戏

-- 验证查询

SELECT GameID, GameName FROM GameGameItem ORDER BY GameID;

```


5. 执行结果

5.1 成功插入的游戏列表(33 个)

| GameID | 游戏名称 | ServerDLLName | ClientExeName |

|--------|----------|---------------|---------------|

| 3 | 德州扑克 | DZShowHandServer.dll | DZShowHand.exe |

| 33 | 六人三公 | OxBattleServer.dll | OxBattle.exe |

| 51 | 浙江十三水 | ThirteenZJServer.dll | ThirteenZJ.exe |

| 56 | 疯狂三张 | ThreeMadnessServer.dll | ThreeMadness.exe |

| 57 | 八人牛牛 | OxEightServer.dll | OxEight.exe |

| 104 | 百人牛牛 | OxBattleServer.dll | OxBattle.exe |

| 118 | 百人骰宝 | Game118Server.dll | Game118.exe |

| 122 | 欢乐 30 秒 | BaccaratNewServer.dll | BaccaratNew.exe |

| 123 | 飞禽走兽 | AnimalBattleServer.dll | AnimalBattle.exe |

| 127 | 金鲨银鲨 | SharkBattleServer.dll | SharkBattle.exe |

| 140 | 豪车俱乐部 | LuxuryCarServer.dll | LuxuryCar.exe |

| 143 | 百人推筒子 | 28GangBattleServer.dll | 28GangBattle.exe |

| 144 | 红黑大战 | RedBlackBattleServer.dll | RedBlackBattle.exe |

| 145 | 龙虎斗 | DragonTigerBattleServer.dll | DragonTigerBattle.exe |

| 147 | 五星宏辉 | FiveStarServer.dll | FiveStar.exe |

| 148 | 红包扫雷 | HBSLServer.dll | HBSL.exe |

| 200 | 斗地主 | LandServer.dll | Land.exe |

| 238 | 510K(定制版) | 510KEXServer.dll | 510KEX.exe |

| 240 | 跑得快 | RunFastServer.dll | RunFast.exe |

| 241 | 21 点 | BlackJackServer.dll | BlackJack.exe |

| 302 | 血战麻将 | SparrowXZServer.dll | SparrowXZ.exe |

| 389 | 红中麻将 | SparrowHZHServer.dll | SparrowHZH.exe |

| 391 | 新广东麻将 | SparrowGDEXServer.dll | SparrowGDEX.exe |

| 401 | 五子棋 | Game401Server.dll | Game401.exe |

| 510 | 李逵劈鱼 | FishLKServer.dll | FishLK.exe |

| 511 | 摇钱树 | FishYQSServer.dll | FishYQS.exe |

| 516 | 水浒传 | WaterMarginServer.dll | WaterMargin.exe |

| 520 | 足球连线 | Line39Server.dll | Line39.exe |

| 522 | 超级水果连线 | SuperFruitServer.dll | SuperFruit.exe |

| 527 | 捕鱼达人 | FishDRServer.dll | FishDR.exe |

| 532 | ATT 连环炮 | ATTServer.dll | ATT.exe |

| 614 | 3D 森林王国 | Server_3DSLWG.dll | 3DSLWG.exe |

| 707 | 襄阳卡五星 | SparrowXYKWXServer.dll | SparrowXYKWX.exe |

5.2 游戏分类统计

| 游戏类型 | 数量 | 代表游戏 |

|----------|------|----------|

| 扑克类 | 12 | 斗地主、德州扑克、牛牛 |

| 麻将类 | 5 | 红中麻将、血战麻将 |

| 街机类 | 7 | 飞禽走兽、金鲨银鲨 |

| 捕鱼类 | 4 | 捕鱼达人、李逵劈鱼 |

| 老虎机 | 4 | 超级水果连线、豪车俱乐部 |

| 其他 | 1 | 五子棋 |


6. 数据库操作命令

6.1 MySQL 执行命令

```bash

执行插入脚本

mysql -u root -p WHQJPlatformDB < insert_all_games_mysql.sql

验证数据

mysql -u root -p WHQJPlatformDB -e "SELECT COUNT(*) FROM GameGameItem"

导出游戏列表

mysql -u root -p WHQJPlatformDB -e "SELECT GameID, GameName FROM GameGameItem ORDER BY GameID"

```

6.2 SQL Server 执行命令

```bash

使用 sqlcmd 执行

sqlcmd -S 127.0.0.1 -d WHQJPlatformDB -i insert_all_games.sql

验证数据

sqlcmd -S 127.0.0.1 -d WHQJPlatformDB -Q "SELECT COUNT(*) FROM GameGameItem"

```


7. 技术要点

7.1 编码处理

  • 源文件使用 GBK 编码读取

  • SQL 文件使用 UTF-8 with BOM 编码保存

  • 避免中文乱码问题

7.2 正则表达式

```python

匹配 KIND_ID

r'#define\s+KIND_ID\s+(\d+)'

匹配 GAME_NAME

r'#define\s+GAME_NAME\s+TEXT\("([^"]+)"\)'

```

7.3 批量插入优化

  • 使用批量 INSERT 语句减少数据库交互

  • 先删除旧数据避免主键冲突

  • 添加事务保证数据一致性


8. 扩展应用

8.1 更新服务器 DLL 名称

从实际编译的项目文件中提取真实的服务器 DLL 名称:

```python

def parse_vcxproj(file_path):

"""解析.vcxproj 文件,提取目标文件名"""

with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:

content = f.read()

提取目标文件名

target_name_match = re.search(r'<TargetName>([^<]+)</TargetName>', content)

target_name = target_name_match.group(1) if target_name_match else None

return target_name

```

8.2 生成更新脚本

```sql

-- 更新 ServerDLLName 字段

UPDATE GameGameItem

SET ServerDLLName = 'LandServer.dll'

WHERE GameID = 200;

-- 更新 ClientExeName 字段(去掉 Server 和.dll,加上.exe)

UPDATE GameGameItem

SET ClientExeName = CONCAT(REPLACE(REPLACE(ServerDLLName, 'Server', ''), '.dll', ''), '.exe')

WHERE GameID >= 100;

```


9. 总结

本文介绍了一种从游戏项目头文件中自动提取配置信息并批量插入数据库的方法。主要优势包括:

  1. **自动化**:无需手动录入,减少人为错误

  2. **可维护**:脚本可重复使用,适应项目变化

  3. **高效率**:33 个游戏配置信息,几秒钟完成入库

  4. **跨平台**:支持 MySQL 和 SQL Server 两种数据库

该方法可推广到任何需要从源代码中提取配置信息的场景,具有很高的实用价值。


附录:完整代码

A.1 提取脚本(extract_all_games.py)

见第 3 节

A.2 MySQL 插入脚本(insert_all_games_mysql.sql)

见第 4.2 节

A.3 更新脚本(update_server_dll.sql)

```sql

-- 更新 ServerDLLName 字段为目标文件名

UPDATE GameGameItem SET ServerDLLName = 'DZShowHandServer.dll' WHERE GameID = 3;

UPDATE GameGameItem SET ServerDLLName = 'OxBattleServer.dll' WHERE GameID = 33;

-- ... 其他更新

-- 验证更新结果

SELECT GameID, GameName, ServerDLLName FROM GameGameItem ORDER BY GameID;

```


**作者简介**:林宏权,游戏后端开发工程师,专注于游戏服务器架构和自动化运维工具开发。

**版权声明**:本文为原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

相关推荐
Bin努力加餐饭1 小时前
MongoDB
数据库·mongodb
白藏y2 小时前
【MySQL】CentOS 7 环境下 MySQL 5.7 完整安装与配置
数据库·mysql
小箌2 小时前
JavaWeb_02
java·数据库·maven·mybatis
数据知道2 小时前
详解MongoDB混合部署策略:复制集与分片集群的组合应用
数据库·mongodb
沙振宇2 小时前
【Web】使用Vue3+PlayCanvas开发3D游戏(四)3D障碍物躲避游戏2-模型加载
游戏·3d·vue3·vite·playcanvas
海棠AI实验室2 小时前
OpenClaw 落地指南:在 Windows 本地零基础部署 OpenClaw 与自动化强化学习 (RL) 系统
运维·windows·自动化·openclaw
溜达的大象2 小时前
后端常用技术全方位分析:从核心标配到淘汰弃用,一文理清技术选型逻辑
网络·数据库
da_vinci_x2 小时前
告别“塑料机甲”:Plasticity的次世代硬表面磨损与自定义贴花工作流
游戏·3d·aigc·材质·技术美术·游戏策划·游戏美术
InfiSight智睿视界2 小时前
执行型AI落地巡店场景:从流程自动化到管理闭环
大数据·人工智能·自动化