跳转到内容

打包计划

任务:把《原神》文字战斗模拟系统打成一个解压即用的 zip 包,内置免安装 MySQL,对方装了 JDK 就能跑。 源项目根目录:E:\C\cDownKeShe\(默认包原版);重构版:E:\AI\zcode\object\ke-she\refactored\。 打包工作目录:E:\AI\zcode\object\ke-she\dist\(新建)。


  • 数据库方案:随包带免安装 MySQL(不用 H2/SQLite,SQL 全不动)。
  • 打包形态:完整项目 zip(源码 + 依赖 jar + run.bat + README),对方装 JDK 解压即跑。

1. 核心问题:硬编码的 MySQL 路径

Section titled “1. 核心问题:硬编码的 MySQL 路径”

当前 DBConnector.java 硬编码:

File mysqlExe = new File("E:\\SQL\\mysql\\bin\\mysqld.exe");
File myIni = new File("E:\\SQL\\mysql\\my.ini");
pb.directory(new File("E:\\SQL"));

别人电脑没有 E:\SQL,程序连不上库就 System.exit(1) 退出。必须改成相对路径,让 MySQL 跟着项目走。


2. MySQL 瘦身清单(关键,决定包体积)

Section titled “2. MySQL 瘦身清单(关键,决定包体积)”

实测 E:\SQL\mysql1.1 GB,绝大部分可删。运行时只保留:

路径体积用途
bin/mysqld.exe49M数据库服务主程序(唯一必需的可执行)
bin/*.dll(与 mysqld 同目录的运行时 DLL)~5MVC++ 运行时,通常已在系统,但保险保留
share/9.5M字符集、错误信息、时区表(mysqld 启动必需)
lib/libmysql.dll6.9M客户端库(连接器用,保留保险)
lib/plugin/存储引擎插件(InnoDB 等,mysqld 启动会加载
my.ini145B配置文件(路径要改成相对/自适应)
LICENSE README<1MGPL 协议,必须带(GPL 合规)
路径体积原因
bin/mysqld.pdb333M调试符号,运行完全不需要
bin/libprotobuf-debug.pdb*.pdb~30M全部 pdb 调试符号
bin/mysql.exe mysqladmin.exe mysqldump.exe mysqlcheck.exe mysqlimport.exe mysqlshow.exe mysqlslap.exe mysqlpump.exe mysqlbinlog.exe mysql_migrate_keyring.exe mysql_upgrade.exe mysql_secure_installation.exe perror.exe myisam*.exe各 6-7M客户端/维护工具,游戏运行不需要,保留 mysqld.exe 一个即可
lib/*.lib(libmysql.lib/mysqlclient.lib/mysqlservices.lib)53M开发链接库,运行不需要
lib/private/私有头,不需要
lib/mecab/日语分词(可选删,体积小可留)
include/412KC 开发头文件,不需要
docs/10K文档,不需要
data/binlog.*<1M二进制日志,初始化时会重生
data/*.err *.pid auto.cnf运行时生成

data 目录单独处理(见第 3 节)。

瘦身后预估:mysqld.exe(49) + share(9.5) + lib(~7) + bin/dll(~5) ≈ 70M,zip 压缩后约 30M


3. data 目录策略(最容易出错,重点)

Section titled “3. data 目录策略(最容易出错,重点)”

mysqld 需要 datadir 指向一个已初始化的数据目录(含 mysql 系统库、表结构)。两个方案:

方案 A(推荐):打包干净的 data 目录

Section titled “方案 A(推荐):打包干净的 data 目录”
  1. 把现有 E:\SQL\mysql\data 整个复制过来,但清理运行时产物:删 binlog.**.err*.pidauto.cnfib_logfile*ibdata1undo_*#innodb_tempmysql.sock
  2. 保留mysql/(系统库)、genshin_rpg/(游戏数据,900K)、sys/performance_schema/、各种 .pem(SSL 证书,初始化生成但保留可避免重新生成失败)、ib_buffer_pool
  3. 风险:InnoDB 数据文件(ibdata1)被删后,启动时可能报”系统表空间不存在”。更稳的做法是用 mysqld --initialize 重新生成 data(见方案 B)。

方案 B(最稳):data 目录不打包,首次启动自动初始化

Section titled “方案 B(最稳):data 目录不打包,首次启动自动初始化”
  1. zip 里不带 data 目录(或带一个空的 data/ 占位)。
  2. start_mysql.bat 启动前检测:若 data\mysql 不存在,执行:
    mysqld --defaults-file=my.ini --initialize-insecure --console
    --initialize-insecure = root 空密码,与代码里密码候选 ["","root","123456"] 匹配)。
  3. 初始化后再启动 mysqld,再跑 db\genshin_rpg.sql 建库建表。

本计划采用方案 B 的混合:打包里带一份预先 --initialize 过、并已导入 genshin_rpg.sql 的干净 data(让对方解压即有数据、零等待),同时在 start_mysql.bat 里加”检测 data 是否存在,否则自动初始化”的兜底。两全。

my.ini

[mysqld]
port=3306
basedir=E:\SQL\mysql
datadir=E:\SQL\mysql\data
character-set-server=utf8mb4
default-storage-engine=INNODB
secure-file-priv=""

问题:basedir/datadir 用了绝对路径,换机器就失效。MySQL 的 basedir/datadir 不支持相对路径写法(会相对 CURRENTDIR,行为不可靠)。

解决:不把 basedir/datadir 写死在 my.ini,改由启动脚本动态生成 my.ini(脚本知道自己所在目录)。详见第 5 节 start_mysql.bat


4. 代码改造(仅 DBConnector.java,最小改动)

Section titled “4. 代码改造(仅 DBConnector.java,最小改动)”

原代码用 E:\\SQL\\mysql\\bin\\mysqld.exe。改成:从 当前工作目录jar/类路径所在目录 推导 MySQL 路径。

采用约定:MySQL 子目录与启动脚本同级。即包内布局:

GenshinRPG/
├─ run.bat ← 双击启动入口
├─ start_mysql.bat ← 启动/初始化 MySQL(被 run.bat 调用)
├─ stop_mysql.bat ← 关闭 MySQL
├─ mysql/ ← 瘦身后的免安装 MySQL
│ ├─ bin/mysqld.exe
│ ├─ share/
│ ├─ lib/libmysql.dll, plugin/
│ ├─ data/ ← 干净 data(含 genshin_rpg)
│ └─ my.ini ← 由 start_mysql.bat 动态生成
├─ lib/
│ └─ mysql-connector-j-8.0.33.jar
├─ bin/ ← 编译产物(可预编译好,对方免编译)
├─ src/ ← 源码(分包重构版)
├─ db/
│ └─ genshin_rpg.sql ← 建库脚本(首次初始化兜底用)
├─ README.txt ← 使用说明
└─ .gitignore

4.2 DBConnector.java 改动点(精确到行)

Section titled “4.2 DBConnector.java 改动点(精确到行)”

定位(重构版 refactored/src/com/genshin/rpg/dao/DBConnector.java,约 50-65 行):

原代码

File mysqlExe = new File("E:\\SQL\\mysql\\bin\\mysqld.exe");
File myIni = new File("E:\\SQL\\mysql\\my.ini");
if (mysqlExe.exists() && myIni.exists()) {
ProcessBuilder pb = new ProcessBuilder(
mysqlExe.getAbsolutePath(),
"--defaults-file=" + myIni.getAbsolutePath()
);
pb.directory(new File("E:\\SQL"));
pb.start();
Thread.sleep(4000);
connected = tryConnect();
}

改为(用相对路径,基准 = 程序工作目录 = 包根目录):

// 内置 MySQL 子目录路径:相对当前工作目录
File mysqlDir = new File("mysql");
File mysqlExe = new File(mysqlDir, "bin/mysqld.exe");
File myIni = new File(mysqlDir, "my.ini");
if (mysqlExe.exists() && myIni.exists()) {
ProcessBuilder pb = new ProcessBuilder(
mysqlExe.getAbsolutePath(),
"--defaults-file=" + myIni.getAbsolutePath()
);
pb.directory(mysqlDir.getAbsoluteFile()); // 工作目录设为 mysql/,便于相对 data 路径
pb.redirectErrorStream(true);
pb.start();
Thread.sleep(4000);
connected = tryConnect();
}

⚠️ 红线:除路径外,其余逻辑一字不改——密码候选 ["","root","123456"]、连接串 jdbc:mysql://localhost:3306/...、库名 genshin_rpgThread.sleep(4000)、连不上则 JOptionPane + System.exit(1) 全部保留。

4.3 可选增强(推荐加,提升体验,不破坏功能)

Section titled “4.3 可选增强(推荐加,提升体验,不破坏功能)”

连不上时给更友好的提示,引导用户检查:

javax.swing.JOptionPane.showMessageDialog(null,
"无法连接 MySQL。\n请确认:\n1) 本机 3306 端口未被占用\n2) mysql\\data 目录存在且未损坏\n3) 已按 README 指示从 run.bat 启动",
"数据库连接错误", javax.swing.JOptionPane.ERROR_MESSAGE);

(原提示是”无法连接至 localhost:3306”,可保留原文不改,仅补几行说明。)


5.1 start_mysql.bat(核心,处理路径自适应 + 首次初始化)

Section titled “5.1 start_mysql.bat(核心,处理路径自适应 + 首次初始化)”
Terminal window
@echo off
chcp 65001 >nul
cd /d "%~dp0"
echo [MySQL] 检查数据库服务...
REM 若 3306 已通,说明 MySQL 已在跑(本机或其他),直接跳过启动
mysql\bin\mysql.exe -uroot -e "SELECT 1" >nul 2>&1
REM 注意:上面这行需要 mysql.exe,我们瘦身时删了。改用端口探测:
REM 用 powershell 探测端口(避免依赖 mysql.exe)
powershell -Command "try { $c=New-Object Net.Sockets.TcpClient; $c.Connect('localhost',3306); $c.Close(); exit 0 } catch { exit 1 }"
if %errorlevel%==0 (
echo [MySQL] 检测到 3306 端口已开放,跳过启动。
goto :eof
)
REM 端口未开,启动内置 MySQL
echo [MySQL] 正在启动内置免安装 MySQL...
REM 动态生成 my.ini(路径自适应本机)
set "BASE=%cd%\mysql"
set "DATA=%BASE%\data"
(
echo [mysqld]
echo port=3306
echo basedir=%BASE%
echo datadir=%DATA%
echo character-set-server=utf8mb4
echo default-storage-engine=INNODB
echo secure-file-priv=""
echo skip-grant-tables
) > mysql\my.ini
REM 若 data 未初始化,先初始化(首次运行)
if not exist "mysql\data\mysql" (
echo [MySQL] 首次运行,正在初始化数据目录(约 10 秒)...
mysql\bin\mysqld.exe --defaults-file=mysql\my.ini --initialize-insecure --console
)
REM 后台启动 mysqld
start "" /B mysql\bin\mysqld.exe --defaults-file=mysql\my.ini
REM 等待启动(最多 30 秒,每秒探测一次端口)
set /a wait=0
:waitloop
powershell -Command "try { $c=New-Object Net.Sockets.TcpClient; $c.Connect('localhost',3306); $c.Close(); exit 0 } catch { exit 1 }"
if %errorlevel%==0 goto :ready
set /a wait+=1
if %wait% geq 30 goto :timeout
timeout /t 1 /nobreak >nul
goto :waitloop
:ready
echo [MySQL] 启动成功。
goto :eof
:timeout
echo [MySQL] 启动超时!请检查 mysql\data 目录或 3306 端口占用。
exit /b 1

关键点:

  • skip-grant-tables 让 root 免密(与代码密码候选 "" 匹配)。
  • --initialize-insecure 首次初始化(root 空密码)。
  • 端口探测替代依赖 mysql.exe(瘦身已删)。
  • 用 PowerShell 探测端口兼容性好(Win7+/PS 自带)。
Terminal window
@echo off
chcp 65001 >nul
cd /d "%~dp0"
echo ========================================
echo 原神文字战斗模拟系统 - 启动中
echo ========================================
REM 1. 启动内置 MySQL
call start_mysql.bat
if %errorlevel% neq 0 (
echo [错误] MySQL 启动失败,程序无法继续。
pause
exit /b 1
)
REM 2. 启动 Java 程序
echo [应用] 正在启动...
set "CP=bin;lib\mysql-connector-j-8.0.33.jar"
java -cp "%CP%" com.genshin.rpg.Main
REM 3. 退出时关闭 MySQL(可选,避免残留进程)
echo.
echo [清理] 正在关闭数据库服务...
call stop_mysql.bat
pause
Terminal window
@echo off
cd /d "%~dp0"
REM 用 mysqladmin 关闭需要 mysqladmin.exe(已删)。改用任务管理方式:
REM 方案:存储 mysqld 的 PID 启动时记录,关闭时按 PID 杀进程。
REM 简化版:直接按进程名结束本目录启动的 mysqld(不影响系统服务)
REM 安全做法:记录 PID
if exist mysql\mysqld.pid (
for /f %%P in (mysql\mysqld.pid) do taskkill /PID %%P /F >nul 2>&1
del mysql\mysqld.pid
) else (
REM 兜底:提示用户手动关
echo [提示] 未找到 PID 记录。如需关闭,可在任务管理器结束 mysqld.exe。
)

(启动脚本里 start "" /B mysqld 改为先拿 PID:start "" /B cmd /c "mysqld ... & echo !PID! > mysql\mysqld.pid" 较复杂,执行 AI 可简化为”程序退出后留 MySQL 运行,下次启动更快”,在 README 里说明。)


《原神》文字战斗模拟系统 - 使用说明
====================================
【环境要求】
- Windows 10/11(64 位)
- 已安装 JDK 17 或以上(运行 java -version 能看到版本号即可)
【运行步骤】
1. 解压本 zip 到任意目录(路径尽量不要含中文或空格)。
2. 双击 run.bat。
3. 首次启动会自动初始化数据库(约 10 秒),请耐心等待。
4. 出现登录窗口即成功。
- 玩家:点"玩家注册"新建账号 → 切"玩家登录"登录。
- 管理员:点"管理员后台",密码 klee is comming
【常见问题】
Q: 提示"3306 端口被占用"?
A: 你电脑已装了 MySQL。双击 run.bat 会自动检测并复用,无需处理。
Q: 启动后白屏/闪退?
A: 确认 JDK 已装。命令行运行 java -version 验证。
Q: 想看源码?
A: 用 IntelliJ IDEA 打开本目录,src/ 下是全部源码。
【目录说明】
- run.bat 启动入口
- mysql/ 内置免安装 MySQL(请勿删除)
- lib/ JDBC 驱动
- bin/ 已编译的 class(可直接运行)
- src/ 源码
- db/genshin_rpg.sql 建库脚本(参考)
【卸载】直接删除整个文件夹即可。数据库数据存在 mysql\data 下,会一起删除。

7. 工作步骤(执行 AI 按序执行)

Section titled “7. 工作步骤(执行 AI 按序执行)”
  1. 创建打包工作目录 E:\AI\zcode\object\ke-she\dist\genshinrpg\
  2. 瘦身 MySQL:把 E:\SQL\mysql 复制到 GenshinRPG\mysql\,然后删除第 2 节列出的所有可删项(*.pdblib\*.lib、非 mysqld 的 bin\*.exeincludedocslib\privatedata\binlog.*data\*.errdata\*.piddata\auto.cnfdata\ib_logfile*data\ibdata1data\undo_*data\#innodb_temp)。
    • 保留:bin\mysqld.exebin\*.dllshare\lib\libmysql.dlllib\plugin\lib\mecab\(可选)、LICENSEREADMEdata\mysqldata\sysdata\performance_schemadata\genshin_rpgdata\*.pem
  3. 复制源码与依赖:把 refactored\src\ 复制到 GenshinRPG\src\mysql-connector-j-8.0.33.jar 复制到 GenshinRPG\lib\db\genshin_rpg.sql 复制到 GenshinRPG\db\
  4. 改 DBConnector.java:按第 4.2 节把绝对路径 E:\\SQL\\... 改为相对 mysql\...只改路径,其余不动
  5. 预编译 bin:在 GenshinRPG\ 下编译 javac -encoding UTF-8 -d bin @sources.txt,让对方免编译(README 也写”可双击 run.bat 直接跑”)。
  6. 写脚本:写 start_mysql.batrun.batstop_mysql.batREADME.txt.gitignore
  7. 本地验证(必须在 dist 上跑通):
    • 关掉本机已有的 MySQL 服务(net stop mysql 或任务管理器结束 mysqld),模拟”对方无 MySQL”环境。
    • GenshinRPG\mysql\data 重新初始化(验证首次初始化流程)。
    • 双击 run.bat,确认:① 端口探测 → ② 初始化 → ③ 程序启动 → ④ 能登录能玩。
    • 再次双击(复用已启动的 MySQL),确认不重复初始化。
  8. 打 zip:把整个 GenshinRPG\ 压成 GenshinRPG.zip,放 E:\AI\zcode\object\ke-she\dist\
  9. 体积核对:zip 应在 50MB 以内(目标 30MB 左右)。

  • GenshinRPG.zip 解压后,在不带 E:\SQL 的干净环境下双击 run.bat 能启动到登录窗。
  • 首次启动自动初始化 MySQL 并建好 genshin_rpg 库(程序能登录/注册/存档)。
  • DBConnector.java 除路径行外无其他改动(diff 自查)。
  • 所有功能与原版一致(登录/战斗/养成/管理员后台)。
  • zip 体积 < 50MB。
  • README 写清楚运行步骤。
  • 写一份 dist\PACK_NOTE.md:记录瘦身明细(删了什么、留了什么、最终体积)、首次初始化验证记录、复用启动验证记录。

风险对策
mysqld.exe 缺少 lib/plugin 无法启动保留 lib\plugin\(InnoDB 等引擎插件)
--initialize-insecure 在某些 MySQL 版本行为差异打包已初始化的 data 兜底(方案 B 混合)
对方机器已有 MySQL 占 3306start_mysql.bat 端口探测,已开则复用
路径含中文/空格导致 mysqld 报错README 提示解压到无中文空格路径
GPL 协议(MySQL 是 GPL)保留 LICENSE/README,分发说明注明”内含 MySQL Community Server (GPL)“
binlog 删除后启动失败--initialize 重生而非手动删

(计划书完。配合同目录《打包执行提示词.md》使用。)