├── proto ├── put all proto files here.txt ├── 请把您的proto文件放在此处.txt ├── FuckUmiHoMoRsp.proto └── FuckUmiHoMoReq.proto ├── Output ├── packetIds.json └── PacketOpcodes.java ├── start_zh-cn.bat ├── README_zh-cn.md ├── start.bat ├── getcmdids_pancake_zh-cn.js ├── getcmdids_pancake.js ├── getcmdids_grasscutter_zh-cn.js ├── getcmdids_grasscutter.js └── README.md /proto/put all proto files here.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /proto/请把您的proto文件放在此处.txt: -------------------------------------------------------------------------------- 1 | 请把您的proto文件放在此处 2 | -------------------------------------------------------------------------------- /Output/packetIds.json: -------------------------------------------------------------------------------- 1 | { 2 | "13371337": "PacketHead", 3 | "114514": "FuckUmiHoMoReq", 4 | "1919810": "FuckUmiHoMoRsp", 5 | } -------------------------------------------------------------------------------- /proto/FuckUmiHoMoRsp.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | 4 | message FuckUmiHoMoRsp { 5 | enum CmdId { 6 | option allow_alias = true; 7 | NONE = 0; 8 | ENET_CHANNEL_ID = 0; 9 | ENET_IS_RELIABLE = 1; 10 | CMD_ID = 1919810; 11 | } 12 | 13 | int32 retcode = 19; 14 | uint32 seq = 19; 15 | uint32 client_time = 810; 16 | } 17 | -------------------------------------------------------------------------------- /proto/FuckUmiHoMoReq.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | 4 | message FuckUmiHoMoReq { 5 | enum CmdId { 6 | option allow_alias = true; 7 | ENET_CHANNEL_ID = 0; 8 | NONE = 0; 9 | ENET_IS_RELIABLE = 1; 10 | IS_ALLOW_CLIENT = 1; 11 | CMD_ID = 114514; 12 | } 13 | 14 | uint32 seq = 11; 15 | uint32 client_time = 45; 16 | bytes sc_data = 1; 17 | float ue_time = 4; 18 | } 19 | -------------------------------------------------------------------------------- /Output/PacketOpcodes.java: -------------------------------------------------------------------------------- 1 | package emu.grasscutter.net.packet; 2 | 3 | import java.util.HashSet; 4 | 5 | public class PacketOpcodes { 6 | public static final int NONE = 0; 7 | 8 | public static final int FuckUmiHoMoReq = 114514; 9 | public static final int FuckUmiHoMoRsp = 1919810; 10 | 11 | public static final HashSet BANNED_PACKETS = new HashSet() {{ 12 | add(PacketOpcodes.WindSeedClientNotify); 13 | add(PacketOpcodes.PlayerLuaShellNotify); 14 | }}; 15 | } 16 | -------------------------------------------------------------------------------- /start_zh-cn.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title cmdid提取工具 1.0.3 3 | echo. 版本:1.0.3 4 | echo. 开发者:umaru 5 | echo. 构建日期:June 6, 2022 6 | echo. 欢迎使用cmdid提取工具。 7 | echo. 警告:请将所有欲提取的proto文件放在./proto/目录内,否则程序将无法运行。 8 | echo. 在开始前,请确定你已安装nodejs。如果未安装,请前往此处下载。 9 | echo. https://nodejs.org/ 10 | goto menu 11 | :menu 12 | echo.[1] Pancake 格式 (packetIds.json) 13 | echo.[2] Grasscutter 格式 (PacketOpcodes.java) 14 | set /p choose_format=请按1或2 15 | if %choose_format%==1 goto :pancake 16 | if %choose_format%==2 goto :grasscutter 17 | :pancake 18 | rem 19 | node getcmdids_pancake_zh-cn.js 20 | pause 21 | exit 22 | :grasscutter 23 | node getcmdids_grasscutter_zh-cn.js 24 | pause 25 | exit 26 | -------------------------------------------------------------------------------- /README_zh-cn.md: -------------------------------------------------------------------------------- 1 | [EN](README.MD)|中文 2 | 3 | # cmdid提取工具 4 | >这是 Genshin Impact 的 CMD IDs/Packet IDs 提取工具。 5 | 6 | ## 用法 7 | **开始之前,请确保已安装nodejs。如果尚未安装,可以在 [此处](https://nodejs.org/) 下载。** 8 | 9 | ### 步骤一.克隆/下载这个项目 10 | 11 | ### 步骤二.将所有proto文件置于 `./proto` 12 | 13 | ### 步骤三.运行 `start.bat` 或者 `node getcmdids_pancake.js` 14 | 15 | ### 步骤四.文件将在 `./Output` 中生成 16 | 17 | # 更新 18 | ### v1.0.3 19 | Sycamore0: 20 | - 改变文件的生成位置。 21 | - 不再在文件生成后打开文件。 22 | - 编辑控制台日志。 23 | 24 | JuliusPtolemy: 25 | - 修复了对2.7proto的cmdids提取异常的问题。 26 | - 批处理文件中包含的文件格式。 27 | - 使 `PacketOpcodes.java` 适配当前的Grasscutter。 28 | - 编辑控制台日志。 29 | 30 | ### v1.0.2 31 | Sycamore0: 32 | - 修复了选择 `pancake模式` 后依旧执行 `grasscutter模式` 的问题。 33 | - 选择 `pancake模式` 将生成packetIds.json。 34 | - 修改了 `grasscutter` 格式生成的文件名。 35 | - 在生成的文件中添加了一些文本。 36 | - 您可能依旧需要修改一下 `packetids.json` 的格式。 37 | - 在使用pancake格式时自动添加 `"13371337": "PacketHead",` 。 38 | -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title Cmdids Extraction Tool 1.0.3 3 | echo. Version:1.0.3 4 | echo. Developer:umaru 5 | echo. Build date:June 6, 2022 6 | echo. Welcome to use cmdids Extraction tool. 7 | echo. Warning: Please put all proto files in ./proto/ directory, otherwise the tool will not run. 8 | echo. Before you start, make sure nodejs is installed. If you haven't installed it, you can download it here. 9 | echo. https://nodejs.org/ 10 | goto menu 11 | :menu 12 | echo.[1] Pancake format (packetIds.json) 13 | echo.[2] Grasscutter format (PacketOpcodes.java) 14 | echo.[3] start_zh-cn 15 | set /p choose_format=Please press 1, 2 or 3 16 | if %choose_format%==1 goto :pancake 17 | if %choose_format%==2 goto :grasscutter 18 | if %choose_format%==3 goto :start_zh-cn 19 | :pancake 20 | rem 21 | node getcmdids_pancake.js 22 | pause 23 | exit 24 | :grasscutter 25 | node getcmdids_grasscutter.js 26 | pause 27 | exit 28 | :start_zh-cn 29 | cls 30 | start_zh-cn.bat 31 | exit 32 | -------------------------------------------------------------------------------- /getcmdids_pancake_zh-cn.js: -------------------------------------------------------------------------------- 1 | function getCmdids() { 2 | const fs = require('fs'); 3 | const protoPath = './proto/'; 4 | console.log('找到proto文件。请稍后。'); 5 | const protoFiles = fs.readdirSync(protoPath); 6 | let protoStr = ''; 7 | protoFiles.forEach(file => { 8 | const content = fs.readFileSync(protoPath + file, 'utf-8'); 9 | let cmdId = content.match(/CMD_ID = (\d+);/); 10 | if (cmdId === null) { 11 | let cmdId = content.match(/CmdId: (\d+)/); 12 | if (cmdId) { 13 | protoStr += ` "${cmdId[1]}": "${file.replace('.proto', '')}",\n`; 14 | } 15 | } 16 | else { 17 | protoStr += ` "${cmdId[1]}": "${file.replace('.proto', '')}",\n`; 18 | } 19 | }) 20 | fs.writeFileSync('./Output/packetIds.json', '{\n "13371337": "PacketHead",\n','utf-8'); 21 | fs.appendFileSync('./Output/packetIds.json', protoStr); 22 | const appendFileContent = '}'; 23 | fs.appendFileSync('./Output/packetIds.json', appendFileContent, 'utf-8'); 24 | } 25 | getCmdids(); 26 | console.log('操作成功完成。请查看./Output/packetIds.json。'); 27 | 28 | 29 | -------------------------------------------------------------------------------- /getcmdids_pancake.js: -------------------------------------------------------------------------------- 1 | function getCmdids() { 2 | const fs = require('fs'); 3 | const protoPath = './proto/'; 4 | console.log('Extracting CMDIDs...'); 5 | const protoFiles = fs.readdirSync(protoPath); 6 | let protoStr = ''; 7 | protoFiles.forEach(file => { 8 | const content = fs.readFileSync(protoPath + file, 'utf-8'); 9 | let cmdId = content.match(/CMD_ID = (\d+);/); 10 | if (cmdId === null) { 11 | let cmdId = content.match(/CmdId: (\d+)/); 12 | if (cmdId) { 13 | protoStr += ` "${cmdId[1]}": "${file.replace('.proto', '')}",\n`; 14 | } 15 | } 16 | else { 17 | protoStr += ` "${cmdId[1]}": "${file.replace('.proto', '')}",\n`; 18 | } 19 | }) 20 | fs.writeFileSync('./Output/packetIds.json', '{\n "13371337": "PacketHead",\n', 'utf-8'); 21 | fs.appendFileSync('./Output/packetIds.json', protoStr); 22 | const appendFileContent = '}'; 23 | fs.appendFileSync('./Output/packetIds.json', appendFileContent, 'utf-8'); 24 | } 25 | getCmdids(); 26 | console.log('Done! Please check ./Output/packetIds.json'); 27 | -------------------------------------------------------------------------------- /getcmdids_grasscutter_zh-cn.js: -------------------------------------------------------------------------------- 1 | function getCmdids() { 2 | const fs = require('fs'); 3 | const protoPath = './proto/'; 4 | console.log('找到proto文件。请稍后。'); 5 | const protoFiles = fs.readdirSync(protoPath); 6 | let protoStr = ''; 7 | protoFiles.forEach(file => { 8 | const content = fs.readFileSync(protoPath + file, 'utf-8'); 9 | let cmdId = content.match(/CMD_ID = (\d+);/); 10 | if (cmdId === null) { 11 | let cmdId = content.match(/CmdId: (\d+)/); 12 | if (cmdId) { 13 | protoStr += `public static final int ${file.replace('.proto', '')} = ${cmdId[1]};\n`; 14 | } 15 | } 16 | else { 17 | protoStr += `public static final int ${file.replace('.proto', '')} = ${cmdId[1]};\n`; 18 | } 19 | }) 20 | fs.writeFileSync('./Output/PacketOpcodes.java', 'package emu.grasscutter.net.packet;\n\nimport java.util.HashSet;\n\npublic class PacketOpcodes {\n public static final int NONE = 0;\n\n','utf-8'); 21 | fs.appendFileSync('./Output/PacketOpcodes.java', protoStr,'utf-8'); 22 | const appendFileContent = "\npublic static final HashSet BANNED_PACKETS = new HashSet() {{\n add(PacketOpcodes.WindSeedClientNotify);\n add(PacketOpcodes.PlayerLuaShellNotify);\n }};\n}\n"; 23 | fs.appendFileSync('./Output/PacketOpcodes.java', appendFileContent, 'utf-8'); 24 | } 25 | getCmdids(); 26 | console.log('操作成功完成。请查看./Output/PacketOpcodes.java。'); 27 | -------------------------------------------------------------------------------- /getcmdids_grasscutter.js: -------------------------------------------------------------------------------- 1 | function getCmdids() { 2 | const fs = require('fs'); 3 | const protoPath = './proto/'; 4 | console.log('Extracting CMDIDs...'); 5 | const protoFiles = fs.readdirSync(protoPath); 6 | let protoStr = ''; 7 | protoFiles.forEach(file => { 8 | const content = fs.readFileSync(protoPath + file, 'utf-8'); 9 | let cmdId = content.match(/CMD_ID = (\d+);/); 10 | if (cmdId === null) { 11 | let cmdId = content.match(/CmdId: (\d+)/); 12 | if (cmdId) { 13 | protoStr += `public static final int ${file.replace('.proto', '')} = ${cmdId[1]};\n`; 14 | } 15 | } 16 | else { 17 | protoStr += `public static final int ${file.replace('.proto', '')} = ${cmdId[1]};\n`; 18 | } 19 | }) 20 | fs.writeFileSync('./Output/PacketOpcodes.java', 'package emu.grasscutter.net.packet;\n\nimport java.util.HashSet;\n\npublic class PacketOpcodes {\n public static final int NONE = 0;\n\n','utf-8'); 21 | fs.appendFileSync('./Output/PacketOpcodes.java', protoStr,'utf-8'); 22 | const appendFileContent = "\npublic static final HashSet BANNED_PACKETS = new HashSet() {{\n add(PacketOpcodes.WindSeedClientNotify);\n add(PacketOpcodes.PlayerLuaShellNotify);\n }};\n}\n"; 23 | fs.appendFileSync('./Output/PacketOpcodes.java', appendFileContent, 'utf-8'); 24 | } 25 | getCmdids(); 26 | console.log('Done! Please check ./Output/PacketOpcodes.java'); 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EN|[中文](README_zh-cn.md) 2 | 3 | # CMD IDs Extraction Tool 4 | >An extraction tool to extract CMD IDs/Packet IDs from Genshin. 5 | 6 | ## Usage 7 | **Make sure Node.js is installed. If you haven't installed it, download it here: https://nodejs.org/** 8 | 9 | ### 1. Download the tool 10 | - Download the latest release from https://github.com/umaru-233/Cmdids-Extraction-Tool/releases, download the ZIP file, and extract it 11 | - or `git clone https://github.com/umaru-233/Cmdids-Extraction-Tool.git` 12 | 13 | ### 2.Put all proto files to `./proto` 14 | 15 | ### 3. Launch `start.bat` 16 | 17 | ### 4. The files will be in `./Output` folder 18 | 19 | # Update 20 | ### v1.0.3 21 | Sycamore0: 22 | - Changed the location of file generation. 23 | - No longer open file after file generation. 24 | - Edited console logs. 25 | 26 | JuliusPtolemy: 27 | - When using the tool to extract the 2.7 protos from the Grasscutter repository, CMD ID will be null. This fixes this issue. 28 | - Included file format in the batch file. 29 | - Edited `PacketOpcodes.java` to match with the current Grasscutter's `PacketOpcodes.java`. 30 | - Edited console logs. 31 | ### v1.0.2 32 | Sycamore0: 33 | - This version fixed an issue where some of the grasscutter instructions were still executed after selecting pancake. 34 | - PacketIds.json is generated when pancake mode is selected. 35 | - Modified the file name generated by `grasscutter` mode. 36 | - Added some content to the generated file. 37 | - Added `{}` `"13371337": "PacketHead", `to `packetids.json` File. 38 | - You may still need to check `packetids.json` file to make some format changes. 39 | - Automatically add ` "13371337": "packethead",` when using pancake format . 40 | --------------------------------------------------------------------------------