diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d14ebf3e0..89d029f19 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,16 @@ jobs: with: distribution: temurin java-version: '17' + - name: Cache gradle files + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ./.gradle/loom-cache + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle', 'gradle.properties', '**/*.accesswidener') }} + restore-keys: | + ${{ runner.os }}-gradle- - name: Run Gradle run: ./gradlew && ./gradlew jar - name: Upload build diff --git a/.gitignore b/.gitignore index 35ee889c5..ede33151b 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ *.nar *.ear *.zip -*.tar.gz +*.gz *.rar # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml @@ -52,20 +52,30 @@ tmp/ .vscode # Grasscutter -resources/ -logs/ -plugins/ -data/AbilityEmbryos.json -data/OpenConfig.json +/resources +/logs +/plugins +/data +/keys +/language +/languages +/src/generated + +/*.jar +/*.sh + GM Handbook.txt config.json mitmdump.exe -*.jar -!lib/*.jar mongod.exe -/src/generated/ -/*.sh -language/ -languages/ + gacha-mapping.js -data/gacha_mappings.js +mappings.js +BuildConfig.java + +# lombok +/.apt_generated/ + +# macOS +.DS_Store +data/hk4e/announcement/ diff --git a/README.md b/README.md index 99d80c65b..f9b4b53da 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ EN | [中文](README_zh-CN.md) 2. Set network proxy to `127.0.0.1:8080` or the proxy port you specified. -**you can also use `start.cmd` to start servers and proxy daemons automatically** +**you can also use `start.cmd` to start servers and proxy daemons automatically, but you have to set up JAVA_HOME enviroment** ### Building @@ -98,61 +98,11 @@ chmod +x gradlew You can find the output jar in the root of the project folder. -## Commands - -You might want to use this command (`java -jar grasscutter.jar -handbook`) in a cmd that is in the grasscutter folder. It will create a handbook file (GM Handbook.txt) where you can find the item IDs for stuff you want. - -You may want to use this command (`java -jar grasscutter.jar -gachamap`) to generate a mapping file for the gacha record subsystem. The file will be generated to `GRASSCUTTER_RESOURCE/gcstatic` folder. Otherwise you may only see number IDs in the gacha record page. - -There is a dummy user named "Server" in every player's friends list that you can message to use commands. Commands also work in other chat rooms, such as private/team chats. to run commands ingame, you need to add prefix `/` or `!` such as `/pos` - -| Commands | Usage | Permission node | Availability | description | Alias | -| -------------- | ------------------------------------------------- | ------------------------- | ------------ | ------------------------------------------------------------ | ----------------------------------------------- | -| account | account \ [UID] | | Server only | Creates an account with the specified username and the in-game UID for that account. The UID will be auto generated if not set. | | -| broadcast | broadcast \ | server.broadcast | Both side | Sends a message to all the players. | b | -| coop | coop \ \ | server.coop | Both side | Forces someone to join the world of others. | | -| changescene | changescene \ | player.changescene | Client only | Switch scenes by scene ID. | scene | -| clear | clear [UID] | player.clearinv | Client only | Deletes all unequipped and unlocked level 0 artifacts(art)/weapons(wp)/material(all) or all, including 5-star rarity ones from your inventory. | clear | -| drop | drop [amount] | server.drop | Client only | Drops an item around you. | `d` `dropitem` | -| enterdungeon | enterdungeon \ | player.enterdungeon | Client only | Enter a dungeon by dungeon ID | | -| give | give [player] [amount] [level] [finement] | player.give | Both side | Gives item(s) to you or the specified player. (finement option only weapon.) | `g` `item` `giveitem` | -| givechar | givechar \ \ | player.givechar | Both side | Gives the player a specified character. | givec | -| giveart | giveart [player] \ \ [\[,\]]... [level] | player.giveart | Both side | Gives the player a specified artifact. | gart | -| giveall | giveall [uid] [amount] | player.giveall | Both side | Gives all items. | givea | -| godmode | godmode [uid] | player.godmode | Client only | Prevents you from taking damage. | | -| heal | heal | player.heal | Client only | Heals all characters in your current team. | h | -| help | help [command] | | Both side | Sends the help message or shows information about a specified command. | | -| kick | kick \ | server.kick | Both side | Kicks the specified player from the server. (WIP) | k | -| killall | killall [playerUid] [sceneId] | server.killall | Both side | Kills all entities in the current scene or specified scene of the corresponding player. | | -| list | list | | Both side | Lists online players. | | -| permission | permission \ \ | * | Both side | Grants or removes a permission for a user. | | -| position | position | | Client only | Sends your current coordinates. | pos | -| reload | reload | server.reload | Both side | Reloads the server config | | -| resetconst | resetconst [all] | player.resetconstellation | Client only | Resets the constellation level on your currently selected character, will need to relog after using the command to see any changes. | resetconstellation | -| restart | | | Both side | Restarts the current session | | -| say | say \ \ | server.sendmessage | Both side | Sends a message to a player as the server | `sendservmsg` `sendservermessage` `sendmessage` | -| setfetterlevel | setfetterlevel \ | player.setfetterlevel | Client only | Sets the friendship level for your currently selected character | setfetterlvl | -| setstats | setstats \ \ | player.setstats | Client only | Sets a stat for your currently selected character | stats | -| setworldlevel | setworldlevel \ | player.setworldlevel | Client only | Sets your world level (Relog to see proper effects) | setworldlvl | -| spawn | spawn \ [amount] [level(monster only)] | server.spawn | Client only | Spawns some entities around you | | -| stop | stop | server.stop | Both side | Stops the server | | -| talent | talent \ \ | player.settalent | Client only | Sets talent level for your currently selected character | | -| teleport | teleport [@playerUid] \ \ \ [sceneId] | player.teleport | Both side | Change the player's position. | tp | -| tpall | | player.tpall | Client only | Teleports all players in your world to your position | | -| weather | weather \ \ | player.weather | Client only | Changes the weather | w | - -### Bonus - -- Teleporting - - When you want to teleport somewhere, use the in-game marking function on the map. - - Mark a point on the map using the fish hook marking (the last one.) - - (Optional) rename the map marker to a number to override the default Y coordinate (height, default 300.) - - Confirm and close the map. - - You will see your character falling from a very high destination, exact location that you marked. +### Commands have moved to the [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)! # Quick Troubleshooting * If compiling wasn't successful, please check your JDK installation (JDK 17 and validated JDK's bin PATH variable) -* My client doesn't connect, doesn't login, 4206, etc... - Your proxy daemon setup is most likely *the issue*, if you are using Fiddler, make sure it running on another port other than 8888 - -* Startup sequence: Mongodb > Grasscutter > Proxy daemon (mitmdump, fiddler, etc.) > Game +* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is *the issue*, if using + Fiddler make sure it running on another port except 8888 +* Startup sequence: MongoDB > Grasscutter > Proxy daemon (mitmdump, fiddler, etc.) > Game diff --git a/README_zh-CN.md b/README_zh-CN.md index 66878b4f4..4c1705e93 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -123,11 +123,13 @@ chmod +x gradlew | godmode | godmode [uid] | player.godmode | 仅客户端 | 保护你不受到任何伤害(依然会被击退) | | | heal | heal | player.heal | 仅客户端 | 治疗队伍中所有角色 | h | | help | help [命令] | | 均可使用 | 显示帮助或展示指定命令的帮助 | | +| join | join [多个角色id] | player.join | 仅客户端 | 强制入队角色,跟config.json中的avatarLimits有关(跟队内角色数量上限有关)。用法:`join 10000021 10000022` | | | kick | kick \ | server.kick | 均可使用 | 从服务器中踢出指定玩家 (WIP) | k | | killall | killall [uid] [场景ID] | server.killall | 均可使用 | 杀死指定玩家世界中所在或指定场景的全部生物 | | | list | list | | 均可使用 | 列出在线玩家 | | | permission | permission <权限节点> | * | 均可使用 | 添加或移除玩家的权限 | | | position | position | | 仅客户端 | 获取当前坐标 | pos | +| remove | remove [多个角色在队伍中的序号] | player.remove | 仅客户端 | 强制将某个角色从当前队伍中移除。例如`remove 1 2`表示将1号和2号角色移除 | | | reload | reload | server.reload | 均可使用 | 重载服务器配置 | | | resetconst | resetconst [all] | player.resetconstellation | 仅客户端 | 重置当前角色的命座,重新登录即可生效 | resetconstellation | | restart | restart | | 均可使用 | 重启服务端 | | @@ -140,6 +142,7 @@ chmod +x gradlew | talent | talent <天赋ID> <等级> | player.settalent | 仅客户端 | 设置当前角色的天赋等级 | | | teleport | teleport [@playerUid] \ \ \ [sceneId] | player.teleport | 均可使用 | 传送玩家到指定坐标 | tp | | tpall | | player.tpall | 仅客户端 | 传送多人世界中所有的玩家到自身地点 | | +| unlocktower | | player.tower | 仅客户端 | 解锁深渊全部层 | ut | | weather | weather <天气ID> <气候ID> | player.weather | 仅客户端 | 改变天气 | w | ### 额外功能 diff --git a/build.gradle b/build.gradle index dd8fa9fa0..7beb3a816 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,8 @@ sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 group = 'xyz.grasscutters' -version = '1.1.0' +version = '1.1.2-dev' + sourceCompatibility = 17 targetCompatibility = 17 @@ -86,6 +87,9 @@ dependencies { implementation group: 'org.luaj', name: 'luaj-jse', version: '3.0.1' protobuf files('proto/') + + compileOnly 'org.projectlombok:lombok:1.18.24' + annotationProcessor 'org.projectlombok:lombok:1.18.24' } configurations.all { @@ -97,12 +101,14 @@ application { mainClassName = 'emu.grasscutter.Grasscutter' } + jar { manifest { attributes 'Main-Class': 'emu.grasscutter.Grasscutter' } jar.baseName = 'grasscutter' + jar.archiveName = project.hasProperty('jarFilename') ? "${jarFilename}.${extension}" : archiveName from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } @@ -226,6 +232,23 @@ javadoc { } } +task injectGitHash { + def gitCommitHash = { + try { + return 'git rev-parse --verify --short HEAD'.execute().text.trim() + } catch (e) { + return "GIT_NOT_FOUND" + } + } + new File(projectDir, "src/main/java/emu/grasscutter/BuildConfig.java").text = """ + package emu.grasscutter; + public class BuildConfig { + public static final String VERSION = \"${version}\"; + public static final String GIT_HASH = \"${gitCommitHash()}\"; + } + """ +} + processResources { dependsOn "generateProto" } diff --git a/data/Banners.json b/data/Banners.json deleted file mode 100644 index a4f724ac9..000000000 --- a/data/Banners.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "gachaType": 200, - "scheduleId": 893, - "bannerType": "STANDARD", - "prefabPath": "GachaShowPanel_A022", - "previewPrefabPath": "UI_Tab_GachaShowPanel_A022", - "titlePath": "UI_GACHA_SHOW_PANEL_A022_TITLE", - "costItem": 224, - "beginTime": 0, - "endTime": 1924992000, - "sortId": 1000, - "rateUpItems1": [], - "rateUpItems2": [] - }, - { - "gachaType": 301, - "scheduleId": 903, - "bannerType": "EVENT", - "prefabPath": "GachaShowPanel_A079", - "previewPrefabPath": "UI_Tab_GachaShowPanel_A079", - "titlePath": "UI_GACHA_SHOW_PANEL_A048_TITLE", - "costItem": 223, - "beginTime": 0, - "endTime": 1924992000, - "sortId": 9998, - "maxItemType": 1, - "rateUpItems1": [1002], - "rateUpItems2": [1053, 1020, 1045] - }, - { - "gachaType": 302, - "scheduleId": 913, - "bannerType": "WEAPON", - "prefabPath": "GachaShowPanel_A080", - "previewPrefabPath": "UI_Tab_GachaShowPanel_A080", - "titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE", - "costItem": 223, - "beginTime": 0, - "endTime": 1924992000, - "sortId": 9997, - "minItemType": 2, - "eventChance": 75, - "softPity": 80, - "hardPity": 80, - "rateUpItems1": [11509, 12504], - "rateUpItems2": [11401, 12402, 13407, 14401, 15401] - } -] diff --git a/data/GameAnnouncement.json b/data/GameAnnouncement.json deleted file mode 100644 index 2bce06fdb..000000000 --- a/data/GameAnnouncement.json +++ /dev/null @@ -1,29 +0,0 @@ -{ -"list": [ - { - "ann_id": 1, - "title": "Welcome to Grasscutter!", - "subtitle": "Welcome", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/17/f4aa42d505822805eebf4a55d72a78d8_2755691727027973637.jpg", - "content": "Hi there!
First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! Check out our:
", - "lang": "es-es" - }, - { - "ann_id": 2, - "title": "How to use announcements", - "subtitle": "How to use", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/17/f4aa42d505822805eebf4a55d72a78d8_2755691727027973637.jpg", - "content": "Tips
>How to use announcements

>Announcement content can use HTML

>The specific content of the announcement is stored in the program directorydata/GameAnnouncement.json, whileGameAnnouncementList.json stores the announcement list data

How to use
>In GameAnnouncement
ParametersDescription
ann_IdAnnouncement unique id
titleShow at the top of the content
subtitletitle shown on the left
bannerDisplay between content and title
contentas u see
langdisplay language
totalAnnouncement quantity


>In GameAnnouncementList
If you want to add an annouement, please add the list data in the announcement type corresponding to GameAnnouncementList, and finally add the announcement content in GameAnnouncement", - "lang": "es-es" - }, - { - "ann_id": 3, - "title": "ǻ--This is the event announcement", - "subtitle": "Welcome", - "banner":"https://uploadstatic-sea.mihoyo.com/announcement/2020/09/22/7d85f19b152d218e73224d7c138a0fd0_5818585260283672899.jpg", - "content": "Welcome", - "lang": "es-es" - } -], -"total": 3 -} \ No newline at end of file diff --git a/data/GameAnnouncementList.json b/data/GameAnnouncementList.json deleted file mode 100644 index ea3091fc7..000000000 --- a/data/GameAnnouncementList.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "t": "System.currentTimeMillis()", - "list": [ - { - "list": [ - { - "ann_id": 1, - "title": "Welcome to Grasscutter!", - "subtitle": "Welcome", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/22/7d85f19b152d218e73224d7c138a0fd0_5818585260283672899.jpg", - "content": "", - "type_label": "Juego", - "tag_label": "1", - "tag_icon": "https://uploadstatic-sea.mihoyo.com/announcement/2020/03/05/a2588f1a51faee9fa8dfe9aead649dd6_7237021399135895303.png", - "login_alert": 1, - "lang": "es-es", - "start_time": "2020-09-25 04:05:30", - "end_time": "2023-10-30 11:00:00", - "type": 2, - "remind": 0, - "alert": 0, - "tag_start_time": "2000-01-02 15:04:05", - "tag_end_time": "2030-01-02 15:04:05", - "remind_ver": 1, - "has_content": true, - "extra_remind": 0 - }, - { - "ann_id": 2, - "title": "Ϸ -- This is the game announcement", - "subtitle": "This is the game announcement", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/17/85b7163c95745a76d49b3d163d893592_6487108933004985049.jpg", - "content": "", - "type_label": "Juego", - "tag_label": "1", - "tag_icon": "https://uploadstatic-sea.mihoyo.com/announcement/2020/03/05/a2588f1a51faee9fa8dfe9aead649dd6_7237021399135895303.png", - "login_alert": 1, - "lang": "es-es", - "start_time": "2020-09-25 15:12:09", - "end_time": "2030-10-30 11:00:00", - "type": 2, - "remind": 0, - "alert": 0, - "tag_start_time": "2000-01-02 08:04:05", - "tag_end_time": "2030-01-02 08:04:05", - "remind_ver": 1, - "has_content": true, - "extra_remind": 0 - } - ], - "type_id": 2, - "type_label": "Juego" - }, - { - "list": [ - { - "ann_id": 3, - "title": "ǻ--This is the event announcement", - "subtitle": "Welcome", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/22/7d85f19b152d218e73224d7c138a0fd0_5818585260283672899.jpg", - "content": "", - "type_label": "Eventos", - "tag_label": "1", - "tag_icon": "https://uploadstatic-sea.mihoyo.com/announcement/2020/03/05/a2588f1a51faee9fa8dfe9aead649dd6_7237021399135895303.png", - "login_alert": 1, - "lang": "es-es", - "start_time": "2020-09-25 04:05:30", - "end_time": "2022-05-02 00:51:00", - "type": 2, - "remind": 0, - "alert": 0, - "tag_start_time": "2000-01-02 15:04:05", - "tag_end_time": "2022-05-02 00:51:00", - "remind_ver": 1, - "has_content": true, - "extra_remind": 0 - } - ], - "type_id": 1, - "type_label": "Eventos" - }, - { - "list": [ - {} - ], - "type_id": 3, - "type_label": "Others" - } - ], - "total": 3, - "type_list": [ - { - "id": 2, - "name": "Ϸϵͳ", - "mi18n_name": "Juego" - }, - { - "id": 1, - "name": "", - "mi18n_name": "Eventos" - }, - { - "id": 3, - "name": "", - "mi18n_name": "Others" - } - ], - "alert": true, - "alert_id": 2, - "timezone": -5, - "pic_list": [ - ], - "pic_total": 0, - "pic_type_list": [ - ], - "pic_alert": false, - "pic_alert_id": 0, - "static_sign": "" -} \ No newline at end of file diff --git a/data/query_cur_region.txt b/data/query_cur_region.txt deleted file mode 100644 index ddef1aff6..000000000 --- a/data/query_cur_region.txt +++ /dev/null @@ -1 +0,0 @@ -GpgdCgo4LjIwOS42Ni4xENWsARosaHR0cHM6Ly9vc2V1cm9vYXNlcnZlci55dWFuc2hlbi5jb20vcmVjaGFyZ2U6BGV1cm9COWh0dHBzOi8vYXV0b3BhdGNoaGsueXVhbnNoZW4uY29tL2NsaWVudF9nYW1lX3Jlcy8yLjZfbGl2ZUo8aHR0cHM6Ly9hdXRvcGF0Y2hoay55dWFuc2hlbi5jb20vY2xpZW50X2Rlc2lnbl9kYXRhLzIuNl9saXZlUpIBaHR0cHM6Ly93ZWJzdGF0aWMtc2VhLmhveW92ZXJzZS5jb20veXMvZXZlbnQvaW0tc2VydmljZS9pbmRleC5odG1sP2ltX291dD1mYWxzZSZzaWduX3R5cGU9MiZhdXRoX2FwcGlkPWltX2NjcyZhdXRoa2V5X3Zlcj0xJndpbl9kaXJlY3Rpb249cG9ydHJhaXRiCDIuNl9saXZlcNnsmgOQAdnsmgOaAVx7InJlbW90ZU5hbWUiOiAiZGF0YV92ZXJzaW9ucyIsICJtZDUiOiAiMWE0NDVhZTQ4ZmJkYmUwMzgzMTJiZTg2OGYyODEzZDIiLCAiZmlsZVNpemUiOiA0NDE1faIBW3sicmVtb3RlTmFtZSI6ICJkYXRhX3ZlcnNpb25zIiwgIm1kNSI6ICIxNzU0MmM3YmJhYzQ5YjkxMWRlMjlhOTYyNzU0YmQ2MSIsICJmaWxlU2l6ZSI6IDUxNH2yAYEGCL23mQMa4AV7InJlbW90ZU5hbWUiOiAicmVzX3ZlcnNpb25zX2V4dGVybmFsIiwgIm1kNSI6ICI5ZjA5MmNhMTMwNjdjYWU0MzEzNDkzZWVkM2QzZTlhZSIsICJmaWxlU2l6ZSI6IDUyNjk2Nn0NCnsicmVtb3RlTmFtZSI6ICJyZXNfdmVyc2lvbnNfbWVkaXVtIiwgIm1kNSI6ICI3Yzk0MmU3MDRhODA0YzIxMjJmYzYzZWU5MjhlNzE0OCIsICJmaWxlU2l6ZSI6IDI4NTU1MH0NCnsicmVtb3RlTmFtZSI6ICJyZXNfdmVyc2lvbnNfc3RyZWFtaW5nIiwgIm1kNSI6ICJlMzVmNmQ4NTNkMDRjZTAyMmFjN2MzNmQ0M2Y0MGU3YyIsICJmaWxlU2l6ZSI6IDEyMjAzNn0NCnsicmVtb3RlTmFtZSI6ICJyZWxlYXNlX3Jlc192ZXJzaW9uc19leHRlcm5hbCIsICJtZDUiOiAiODc2NGIwZjJlZDgxNWNkNDQzMGUwODVjNDYxYTZmNGQiLCAiZmlsZVNpemUiOiA1MjY5NjZ9DQp7InJlbW90ZU5hbWUiOiAicmVsZWFzZV9yZXNfdmVyc2lvbnNfbWVkaXVtIiwgIm1kNSI6ICIxYmJlMzc0YzE2YmZmNDU5MTU5OWMyMTk3MzQyMDM0OCIsICJmaWxlU2l6ZSI6IDI4NTU1MH0NCnsicmVtb3RlTmFtZSI6ICJyZWxlYXNlX3Jlc192ZXJzaW9uc19zdHJlYW1pbmciLCAibWQ1IjogIjcyZmE3ZmY2NmQ1MTRmY2JhMzRhZjAwN2YyYjljMmY4IiwgImZpbGVTaXplIjogMTIyMDM2fQ0KeyJyZW1vdGVOYW1lIjogImJhc2VfcmV2aXNpb24iLCAibWQ1IjogImZiZmE2ZDZlMDcwMmQxYzc5ZTA1NjRmYjI4NjdlNzM4IiwgImZpbGVTaXplIjogMTh9IgEwKgo3YTM0YTM2YTZlMggyLjZfbGl2ZboBnBBFYzJiEAAAAJNvNOvzlkCCDSqpQ6a141IACAAA6gq2poqqrhWr1LS/wULjaiSPJIGsouCxUfY40ezmGoMU5SZZLwQ97KrlkCLKvTVycxteFwEPDxFrKxiHE1oigrAAkjc0NU12JqcQBFL8ExWeR+3QfCPnh7MWo424stJoHPADl9E6R/n3YDXAtq1gUzZu5Y4aGtd9XDyVjozcbIrtVVTGVpvRIuwGYoOCRCwDeRKphu9MoJfbi9mawLh5XSq+KLsAksjM90JJ/DEUzP2XCB/QILsiSiwbET5LUrl65OXCN4sLxZg+86qmeU28cdz4tWDewXYFO+Y7AnJAt7JfpgR/8Os7A9CDPD8WA6GBdqyplmoKRtnjjZG9ZGZIk1YF7AdGUhE8672XlWW3clJaNMBpHFkON+t7Utgu6prY/uJJLFZlGm5KMSend8u8GTMYOE5/AJsVkX/5eS8V2F6Dt6mZJgPtGAlX7Rp1a1R57FMKQLS+9nIzKDMclWFs7ebbnv+lcqckuqln19/JMrYQg9E4IiDVn5akaHZbnYBw0+HDR5kfT2xWfWVo8CJu4mPSpVR1kI4HhZXTURnHa7ezObuwHQm3NS7wHK7VO0E+qgnUgb+vK9M0cHTQE6FsCi/bk0VaHZtDxpMCTfKluJiOsxhvRePOjEVyNyLwLJaoxwwSukMfSH9G+q62ygFmmErAQfKKWLreb72UegOgmhD8T8aytvWXHkWk07QCttqgPhax8BAW2OvRJluvorBUIeHDeO6QeBaZns4EXIYUcIQlfi3yGsLKhhGLb2OgN6a6B3ElxdgXRRYMGAdDoAxEnCcWmdZx874vEvf2KFUP6aU8l4lh0XV6RU/D7A+eqWN5bH4ffS4QBQq2MU6CNA5XumMsD4zUfC6od5T7Tt7uQsgbqtIMgXKpO8lRk4pRgnpPsqM1Ou8kTb1UdQSc4yREuJlrL2Tmtf35cAw7W290LIO/GaO9Rj1CPhATMn7jbUTA6+QN7rTxIzbVl66k95wQth81TYuvw1DlGOpVDTbcCB0uvfmcAAGhj57jVBlyVIu+KJzrrx8z9Uh6scsMCgrMPJn7nsCHSXD6yElTgLrF7FVwgqsxDjgcquqkrSnknP92jb+11IJbw05Ass4hcMRGJxdAefSWDIgdi7l4GnppPdUvLkG5uvBlO85AiT2NpqNmShebfst8rQLFc1B7hAcvh9EpM9Sii0/XXfe9tEf7AwKj2SWmS79PsjEiAiv18tJ6gDlaJ0WFSchXNBRPu8ESvKlE8q7myuc2t5nnxv/hctkez5+nh9SgQ3beL34chSL4RPTH32Jqzs5p7s2n87Bv4vfQccYFAF+kKMUZzKnWKl0LCrStSd3+s+4KF/tZXEKue5KoVobNhaQrD33HjWf9Rvw0ULd4ho4A6wj/uga9o7rZ2C2v1YEDNNqZ5/v/udN3hl7tXrWv5UXcUyTtooa66sJ8oITE8+4aDWimtX6dy0CdFQj2mHppbbvRF66flDd/gFA35xQOXfYdOud3NJogglHXofOoB0LEdbao9C6Nt2v+z7C4S0l3cAMXp/yiI9qxJT9b0mQ2zp2GN5i4gvrp+6iKjqxf+IA++oB/JzbbpSVOFJmFSysv4v3Al2AVbmFycYqv0GaoiZ22wiu8Ok3+LCyKJTITtaJLAtgbpwRfa9SUkdpRwMK1vMN1s6jZU9gdejY3oLVKjFpg66c9bagpmvIG1/gfgY9yT++Y8img4aB/JDJMAS2MVGxGlyrRFGaXBWLq3SkhqDqGD5klbvYv2IFMr4BAHP2uwLb92qEhtlksiVQYk8HGxLWlU2Fo+Pxee8L1xvQOgPdY4/cb33BuJXvtyW5ea5EmVtBPo4MU1ws9BvAzLs13Nisl+/FBvBn8ktkZmE5e6nsdpGEtq4/d7MfCLXGRI5L730mIieeAvtQcb0NMWGcubHPgjY58Pv4MSdRpOQakzM2rA5UD5O57rGH5q6p3HZfZk2iPUcJRsebMKJ4l1omr5JeD95DKDKy7Cts3RajufslekL3/wHwUZbAdEWyux2w1zbiukmhTfh0nbenm8Q8KOASCDo0SWO3e9FpOz5o+phHBVYgmfxRt11OonnLt1qKB7j/a7YdufvkFSsFm4UdgsJMPIHzeBjbSSDlLeCdmdKGQtFLC73npe6efYGUupMIV9EYup1D/OoCNlz2r/FhJ7aLRtj6Q6cb161MLp+rmjbSzN+RVFwf7wAVpLQMrHwTvUzB/8M7cTjN5VFE583uhy4KKf+W3iTxzdyX2SAD9QVu6EXv4KaEFBy8Vo0sga907Fi7imkwgjY2cdnEtPMMeO2Jqj3yWPdqrlVtfAn1jd14oix7YObsJ8mVBeueiplG9d7dxcA1GV+7xX9wOyPDcfH5FBAIlglBIEhjSyNQErH+JYRbOUotXMBQa1tlRRtBSLLDCRgEpG8F+Dv5Oao9ZBnKAi0GRjPKo+OjsehWzrNXGDcoTQsGD/bmKpCdaUOuEa6rLA7tbYwqT2SPdCJzBx2J+kI1bwDWhFF9ROrh9MvmwvMBE9dH5mbQj78p2P5gar2BUcNNbSVvSgxtCa1NHsf/GwrPmTQLPxCrEBcDucxIpsqfINp48iCJGZ4NvlRIZolmaVBWlxjVl/XYcb2YOl3K48e+LsfblTU6tyneZimrS+Y0qt7lncte6NZGPnf98wNLxY39IX8gATezGXoZ03TOhy1jX3epf4Bfw5ZyvU8/XJ2BvbPpw+b8LgS0y0DkeQG4mQGlHidnCAU9odHRwczovL3dlYnN0YXRpYy1zZWEuaG95b3ZlcnNlLmNvbS95cy9ldmVudC9lMjAyMDA0MTBnb19jb21tdW5pdHkvaW5kZXguaHRtbCMv0gEKYWRmZWI4YmU3MdoBCmFkZmViOGJlNzH6AR1odHRwczovL2FjY291bnQuaG95b3ZlcnNlLmNvbYICcWh0dHBzOi8vaGs0ZS1hcGktb3MuaG95b3ZlcnNlLmNvbS9jb21tb24vYXBpY2RrZXkvYXBpL2V4Y2hhbmdlQ2RrZXk/c2lnbl90eXBlPTImYXV0aF9hcHBpZD1hcGljZGtleSZhdXRoa2V5X3Zlcj0xigJMaHR0cHM6Ly9hY2NvdW50LmhveW92ZXJzZS5jb20vIy9hYm91dC9wcml2YWN5SW5HYW1lP2FwcF9pZD00JmJpej1oazRlX2dsb2JhbFqcEEVjMmIQAAAAk2806/OWQIINKqlDprXjUgAIAADqCramiqquFavUtL/BQuNqJI8kgayi4LFR9jjR7OYagxTlJlkvBD3squWQIsq9NXJzG14XAQ8PEWsrGIcTWiKCsACSNzQ1TXYmpxAEUvwTFZ5H7dB8I+eHsxajjbiy0mgc8AOX0TpH+fdgNcC2rWBTNm7ljhoa131cPJWOjNxsiu1VVMZWm9Ei7AZig4JELAN5EqmG70ygl9uL2ZrAuHldKr4ouwCSyMz3Qkn8MRTM/ZcIH9AguyJKLBsRPktSuXrk5cI3iwvFmD7zqqZ5Tbxx3Pi1YN7BdgU75jsCckC3sl+mBH/w6zsD0IM8PxYDoYF2rKmWagpG2eONkb1kZkiTVgXsB0ZSETzrvZeVZbdyUlo0wGkcWQ4363tS2C7qmtj+4kksVmUabkoxJ6d3y7wZMxg4Tn8AmxWRf/l5LxXYXoO3qZkmA+0YCVftGnVrVHnsUwpAtL72cjMoMxyVYWzt5tue/6VypyS6qWfX38kythCD0TgiINWflqRodludgHDT4cNHmR9PbFZ9ZWjwIm7iY9KlVHWQjgeFldNRGcdrt7M5u7AdCbc1LvAcrtU7QT6qCdSBv68r0zRwdNAToWwKL9uTRVodm0PGkwJN8qW4mI6zGG9F486MRXI3IvAslqjHDBK6Qx9If0b6rrbKAWaYSsBB8opYut5vvZR6A6CaEPxPxrK29ZceRaTTtAK22qA+FrHwEBbY69EmW6+isFQh4cN47pB4FpmezgRchhRwhCV+LfIawsqGEYtvY6A3proHcSXF2BdFFgwYB0OgDEScJxaZ1nHzvi8S9/YoVQ/ppTyXiWHRdXpFT8PsD56pY3lsfh99LhAFCrYxToI0Dle6YywPjNR8Lqh3lPtO3u5CyBuq0gyBcqk7yVGTilGCek+yozU67yRNvVR1BJzjJES4mWsvZOa1/flwDDtbb3Qsg78Zo71GPUI+EBMyfuNtRMDr5A3utPEjNtWXrqT3nBC2HzVNi6/DUOUY6lUNNtwIHS69+ZwAAaGPnuNUGXJUi74onOuvHzP1SHqxywwKCsw8mfuewIdJcPrISVOAusXsVXCCqzEOOByq6qStKeSc/3aNv7XUglvDTkCyziFwxEYnF0B59JYMiB2LuXgaemk91S8uQbm68GU7zkCJPY2mo2ZKF5t+y3ytAsVzUHuEBy+H0Skz1KKLT9dd9720R/sDAqPZJaZLv0+yMSICK/Xy0nqAOVonRYVJyFc0FE+7wRK8qUTyrubK5za3mefG/+Fy2R7Pn6eH1KBDdt4vfhyFIvhE9MffYmrOzmnuzafzsG/i99BxxgUAX6QoxRnMqdYqXQsKtK1J3f6z7goX+1lcQq57kqhWhs2FpCsPfceNZ/1G/DRQt3iGjgDrCP+6Br2jutnYLa/VgQM02pnn+/+503eGXu1eta/lRdxTJO2ihrrqwnyghMTz7hoNaKa1fp3LQJ0VCPaYemltu9EXrp+UN3+AUDfnFA5d9h0653c0miCCUdeh86gHQsR1tqj0Lo23a/7PsLhLSXdwAxen/KIj2rElP1vSZDbOnYY3mLiC+un7qIqOrF/4gD76gH8nNtulJU4UmYVLKy/i/cCXYBVuYXJxiq/QZqiJnbbCK7w6Tf4sLIolMhO1oksC2BunBF9r1JSR2lHAwrW8w3WzqNlT2B16NjegtUqMWmDrpz1tqCma8gbX+B+Bj3JP75jyKaDhoH8kMkwBLYxUbEaXKtEUZpcFYurdKSGoOoYPmSVu9i/YgUyvgEAc/a7Atv3aoSG2WSyJVBiTwcbEtaVTYWj4/F57wvXG9A6A91jj9xvfcG4le+3Jbl5rkSZW0E+jgxTXCz0G8DMuzXc2KyX78UG8GfyS2RmYTl7qex2kYS2rj93sx8ItcZEjkvvfSYiJ54C+1BxvQ0xYZy5sc+CNjnw+/gxJ1Gk5BqTMzasDlQPk7nusYfmrqncdl9mTaI9RwlGx5swoniXWiavkl4P3kMoMrLsK2zdFqO5+yV6Qvf/AfBRlsB0RbK7HbDXNuK6SaFN+HSdt6ebxDwo4BIIOjRJY7d70Wk7Pmj6mEcFViCZ/FG3XU6iecu3WooHuP9rth25++QVKwWbhR2Cwkw8gfN4GNtJIOUt4J2Z0oZC0UsLveel7p59gZS6kwhX0Ri6nUP86gI2XPav8WEntotG2PpDpxvXrUwun6uaNtLM35FUXB/vABWktAysfBO9TMH/wztxOM3lUUTnze6HLgop/5beJPHN3JfZIAP1BW7oRe/gpoQUHLxWjSyBr3TsWLuKaTCCNjZx2cS08wx47YmqPfJY92quVW18CfWN3XiiLHtg5uwnyZUF656KmUb13t3FwDUZX7vFf3A7I8Nx8fkUEAiWCUEgSGNLI1ASsf4lhFs5Si1cwFBrW2VFG0FIssMJGASkbwX4O/k5qj1kGcoCLQZGM8qj46Ox6FbOs1cYNyhNCwYP9uYqkJ1pQ64RrqssDu1tjCpPZI90InMHHYn6QjVvANaEUX1E6uH0y+bC8wET10fmZtCPvynY/mBqvYFRw01tJW9KDG0JrU0ex/8bCs+ZNAs/EKsQFwO5zEimyp8g2njyIIkZng2+VEhmiWZpUFaXGNWX9dhxvZg6Xcrjx74ux9uVNTq3Kd5mKatL5jSq3uWdy17o1kY+d/3zA0vFjf0hfyABN7MZehnTdM6HLWNfd6l/gF/DlnK9Tz9cnYG9s+nD5vwuBLTLQOR5AbiZAaUeJ2WLVAtaPymwUgxn8nMUMGk2pDMbkJNLgHPcao2F2HLBdC2W3r1Qs5PtDbMuMCIPSYscVx1x66qcJw19SiQyNLxCY9ErLGDY4mChY/X5NX7Pc2ricYE7EzCSZMYQmtUVZoqn1RPGz1P9Gj65Edm70zFOfRWfR+sTboONM7W3oNk1mkI2M5GwQrQpkAiyb5zwdxpsOwtQ0s0Sin4IOonpW9KcRv8yB8rMOMu6+C6m4h2MwRPj6QrVPWd8PV22qB4iAwfV3UYpjo91Mw/V5xT1DRSrb65vYtu8E4lR3HMv37at4aV6v8RluqeAIHHDJBANaUN3eLCSHewfEb+osQ5BV7XQT5Dwdy/LLFo+hdCBp0Retgtiwsq3+EgRs9i/d9tmghRqEdD/6re752aRiyTsf7CkWY6O7cCGfvmOLE0XhNQra+tLnlJCR1y4m1LOTB3ulQnZrA2E7Mmk7 \ No newline at end of file diff --git a/data/query_region_list.txt b/data/query_region_list.txt deleted file mode 100644 index b4681aaa7..000000000 --- a/data/query_region_list.txt +++ /dev/null @@ -1 +0,0 @@ -ElIKBm9zX3VzYRIHQW1lcmljYRoKREVWX1BVQkxJQyIzaHR0cHM6Ly9vc3VzYWRpc3BhdGNoLnl1YW5zaGVuLmNvbS9xdWVyeV9jdXJfcmVnaW9uElMKB29zX2V1cm8SBkV1cm9wZRoKREVWX1BVQkxJQyI0aHR0cHM6Ly9vc2V1cm9kaXNwYXRjaC55dWFuc2hlbi5jb20vcXVlcnlfY3VyX3JlZ2lvbhJRCgdvc19hc2lhEgRBc2lhGgpERVZfUFVCTElDIjRodHRwczovL29zYXNpYWRpc3BhdGNoLnl1YW5zaGVuLmNvbS9xdWVyeV9jdXJfcmVnaW9uElUKBm9zX2NodBIKVFcsIEhLLCBNTxoKREVWX1BVQkxJQyIzaHR0cHM6Ly9vc2NodGRpc3BhdGNoLnl1YW5zaGVuLmNvbS9xdWVyeV9jdXJfcmVnaW9uKpwQRWMyYhAAAABbrAvbhfIRHfaSCN24qQyVAAgAAMs68ZiMdPfEj41O2wBCYqGiC/WdovvJvaw4t3/m1zIYDrt3/ftK9GKFb7C+2E8FmaHqOnwjJYBg2wI1sXpGmuSxkeWw8Avr36wlNtQjhXNV9zoNKstuZYuheyLlpbPRbYZ3UA6/BzTVsjIhjR1lcqFrigQnpV6MgRR9KqxakCaffK6qIzMlodx4ZPKlqseQhCiyVAvLWQSRqCRcZipzotXsmgLQbpDFtRzhgukXPjfW5dAlzMwswPuu7ZQsf1AKipI34dVQLu6gtXthGgbjn89h/79VR5AokLCPGqIV7/2s+gHfykrjDtyp5rwCcmGQqwV3gHy5LGrHl8Zm12jNd7Qcng51ydqtX4xzet6J2iMF6Dw5nPd/hTyxn+i3Ttk6fop9rbCq3iNgEw3+0cSDal1I1ThYdVnMgPhZgQkZc5/SpTaR+8vfDzRIKbSSrrPSEgLnQvWZOOugXhNdyuiaBc8rJveno7vvktmnhDUF3xWi6osj75j2KghRrdHfDR3Zuh4COrGZDRBSKHft2AvfrxaMT9O8hPzzzYk0U2iicVCDlNP/8wqaT9Vqt1kHmruLxqh377iyp0mxKfNt0+SNRzLyRoyvOar/z3AT6TU9LRoCFrkcJpVsUN+2MVeT52PfMbv5O/Nw9sqsFDlofCJJ/EknY0wDc+tNarYOhDM67/ojn/p6W3ZPBJxb2wcF1TOh9dpAeZdCGJusqhMIj5lpoW8nENTFhkEgMUv2Lh5Z6WpeOAKAu9eDpBMhlRNCccDaNYUgo6TdVDtWxtPrS3NRYqtkvb2I2SEFP0apht954oKdG3ncxyOgHRUkwgtxbCMAngzWo9+VWV3H3OlqeEOv7DdO2o0y95EvlHYb/qtosXPI2jC+6FPa+yl4xmLqcENRTUrU23dsmX3SyBEmZvML4dNeyC53B+mh7DUFtPFJFndxj2tGO9mTSDgy8eCmKG90AiJOMoxaLB2HpnDXN1sTiIcd3WraiE6ZCt4E54hKXvXHPyN52CHkxq1y/TeXHEq4X4MyHyDSRLHmzVs9pnwHM0ZLthKFNyvGfTvjiYokAWtNEuh74syt+m6Wietb6JvgibnnDj6uFKI3BbH4GUT9blsnMgug323bJ6bFvV4iESvz1fNnnUSokWQy5+fWzxPDohULgFzhDCpwov78Bp0E3t6DXSWnrUdNqpLbYKmXO1Hdbn+QH4B90p85UB1V5eSZgxPpUvZbIO4GPScil8K+dkDLdsFa1zypWNmlUN0Ns5H/iuzMuJql2QFYz+SnV1R1T+qywwqCNP9oswcLiAR3XnSacs52vd3PI9+0PZuoF6tVMWlvutsQ34IFZaAwIkdKigZcHumLBt/0KyFASBfN674n8FnHrHOQHU6oCeXkQA9kC8MtkvMb7fOLdzbTsD6SVojzZ64i9mDXxF+iLR9o52OxjIFzwLGRy/ivT/aAnHLZ3AsbnvslDjlQl2ADBFvf7xjmvFu0xlfK58TUpfVEkScFFapWJyKVybB4CRz1wKKz6n/a9581LpCVOWRsJa5p+j0zYcS2PfhmRf3RzwsDHeBjEVlIARbhxNKvmjdZyIidSdMMcsJHDRLE3bvo9kKfag0vRVKmuPLPc9FrACsz3vlkApcVQvzieHWoiP+foEvfj9+7Ti2tLfKdzVkMUmugZiZ46+7PKvIciiiuBPlyld0CCPTtTFHUOMO5dUfrUblX8K3awWiaNQFBS0J3iK08t1bgWfLhsKzsS32fRWugaqecwO9Rji9oHn+UuN8Nz9SgNxodroq9q7y/KHFxbqjCl62g25HN9zUa/s5wnIRwVAiWgTuOe3qGqjwp5m/GR8YVSSK/8mV9EL4AaF8d1uifdVA6wWSH1e/1UB8vcdU83P8ne3u1ho+Y/57WB7KnQaGaiD/108+wiAxNqMb2ex8on01VxdLKV1makXV3gzsvWaRevW8t/K11ZwYfo9g+guWADsA0JO0jWooiaupq1kNWrEheBdSRXBO7Jnb+56cTjPGwLpp7ZOHe/bSCJ4MGzPF3lK66LXhVo+rxvNjhoKVRjhGYxN4T8+AiRo3r+1KwdIGSrtODp3ri3JWAy6Eajp1Ukp9GaCbHSJFnYml84nKew7zLLe//ExQpjd4QAjMTvnbm+Ff6a1jf69QEVo0I33gI7/buwqgjiuvjeL6EYaMolKrKlHZHf/HwWbFbdID8T9aoyZJuCUd6YHaMPRAS6n5nvTwkRLlJ/f6wgyypUGZ22Bb1qGIb9SoPgSgIJkifUoewQW2EexqfoAsHXJVABLy+jp/SC4xzHZOSh42zU1k80HIgrnSOmu6T56F6gqy4Y2cZuZU8LXbO/01u8ifEz8yaXfEFSFdxE0TWl92OLKFtJZr9nNOBQQQr5FDGf6zB1/0CziG/5+PrUDgG3irzho6+7wXkc2CpxlBKOLWdjs3V/Lab6cURz1QZY4HYgUkJtm4U5OKUeO2+murlhC7SrnwyUtGrsD8NbCmI4SRHKPoeLBJQO/m3dRze5Ltr8N9IS7/ukPeOYe1O2agrmhH/JjYfz/l8Gmq8PGY+oavYp8I+2yKvGLD9kCxEgKcTeRh9AW/xPTLGsacrGKQCY+M76DfyLKxCZDiDY9xkBIKchxsMsn7FqZvRMMyJBHbqa3AKQyAN73NCSuFF5f1qDjARU/xqJFhOaKoR64c78oqh1GqOqEFbfNQIRw6WeFCGyW6v6p10uLdR7KXnR7+wub9aG992MpIBk0+gru74yO/WcA0vLdDEQIBwc+M0lmLB53ylsPtde3nliaC5ROHR1IS4LO8Q+3o0BHMr0my0bqFwwCAvZVXOFBHxXyUgrrmUTnZYVSQXNV6+MALBmmRU5yOzhhyHoEdj9YHZeyPpZkYc6DkJWCRYbFfmczNIs133KB9rlfug40w/hHa8pXyRyLaKQUMIUYEvt3Y4AQ== \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100644 index 000000000..08a31b51d --- /dev/null +++ b/install.sh @@ -0,0 +1,295 @@ +#!/usr/bin/env bash + +# Grasscutter install script for linux +# Made by TurtleIdiot + +# Stops the installer if any command has a non-zero exit status +set -e + +# Checks for root +if [ $EUID != 0 ]; then + echo "Please run the installer as root!" + exit +fi + +is_command() { + # Checks if a given command is available + local check_command="$1" + command -v "${check_command}" > /dev/null 2>&1 +} + +# IP validation +valid_ip() { + local ip=$1 + local stat=1 + + if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + OIFS=$IFS + IFS="." + ip=($ip) + IFS=$OIFS + [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ + && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] + stat=$? + fi + return $stat +} + +# Checks for supported installer(s) (only apt-get and pacman right now, might add more in the future) +if is_command apt-get ; then + echo -e "Supported package manager found (apt-get)\n" + + GC_DEPS="mongodb openjdk-17-jre" + INSTALLER_DEPS="wget openssl unzip git" + SYSTEM="deb" # Debian-based (debian, ubuntu) +elif is_command pacman ; then + echo -e "supported package manager found (pacman)\n" + + GC_DEPS="jre17-openjdk" + INSTALLER_DEPS="curl wget openssl unzip git base-devel" # curl is still a dependency here in order to successfully build mongodb + SYSTEM="arch" # Arch for the elitists :P +else + echo "No supported package manager found" + exit +fi + +BRANCH="stable" # Stable by default +# Allows choice between stable and dev branch +echo "Please select the branch you wish to install" +echo -e "!!NOTE!!: stable is the recommended branch.\nDo *NOT* use development unless you have a reason to and know what you're doing" +select branch in "stable" "development" ; do + case $branch in + stable ) + BRANCH="stable" + break;; + development ) + BRANCH="development" + break;; + esac +done + +echo "The following packages will have to be installed in order to INSTALL grasscutter:" +echo -e "$INSTALLER_DEPS \n" +echo "The following packages will have to be installed to RUN grasscutter:" +echo -e "$GC_DEPS \n" + +echo "Do you wish to proceed and install grasscutter?" +select yn in "Yes" "No" ; do + case $yn in + Yes ) break;; + No ) exit;; + esac +done + +echo "Updating package cache..." +case $SYSTEM in # More concise than if + deb ) apt-get update -qq;; + arch ) pacman -Syy;; +esac + +# Starts installing dependencies +echo "Installing setup dependencies..." +case $SYSTEM in # These are one-liners anyways + deb ) apt-get -qq install $INSTALLER_DEPS -y;; + arch ) pacman -Sq --noconfirm --needed $INSTALLER_DEPS > /dev/null;; +esac +echo "Done" + +echo "Installing grasscutter dependencies..." +case $SYSTEM in + deb) apt-get -qq install $GC_DEPS -y > /dev/null;; + arch ) pacman -Sq --noconfirm --needed $GC_DEPS > /dev/null;; +esac +# *sighs* here we go... +INST_ARCH_MONGO="no" +if [ $SYSTEM = "arch" ]; then + echo -e "-=-=-=-=-=--- !! IMPORTANT !! ---=-=-=-=-=-\n" + echo -e " Due to licensing issues with mongodb,\n it is no longer available on the official arch repositiries." + echo -e " In order to install mongodb,\n it needs to be fetched from the Arch User Repository.\n" + echo -e " As this script is running as root,\n a temporary user will need to be created to run makepkg." + echo -e " The temporary user will be deleted once\n makepkg has finished.\n" + echo -e " This will be handled automatically.\n" + echo -e "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n" + echo -e "!!NOTE!!: Only select \"Skip\" if mongodb is already installed on this system" + echo "Do you want to continue?" + select yn in "Yes" "Skip" "No" ; do + case $yn in + Yes ) + INST_ARCH_MONGO="yes" + break;; + No ) exit;; + Skip ) + INST_ARCH_MONGO="no" + break;; + esac + done +fi + +if [ $INST_ARCH_MONGO = "yes" ]; then + DIR=$(pwd) + # Make temp user + echo "Creating temporary user..." + TEMPUSER="gctempuser" + TEMPHOME="/home/$TEMPUSER" + useradd -m $TEMPUSER + cd $TEMPHOME + + # Do the actual makepkg shenanigans + echo "Building mongodb... (this will take a moment)" + su $TEMPUSER< /dev/null + exit +EOF + mv "$(find -name "mongodb-bin*.pkg.tar.zst" -type f)" ./mongodb-bin.pkg.tar.zst + cd $DIR + + # Snatch the file to current working directory + mv "$TEMPHOME/mongodb-bin.pkg.tar.zst" ./mongodb-bin.pkg.tar.zst + chown root ./mongodb-bin.pkg.tar.zst + chgrp root ./mongodb-bin.pkg.tar.zst + chmod 775 ./mongodb-bin.pkg.tar.zst + + echo "Installing mongodb..." + pacman -U mongodb-bin.pkg.tar.zst --noconfirm > /dev/null + rm mongodb-bin.pkg.tar.zst + + echo "Starting mongodb..." + systemctl enable mongodb + systemctl start mongodb + + echo "Removing temporary account..." + userdel -r $TEMPUSER +fi +echo "Done" + +echo "Getting grasscutter..." + +# Download and rename jar +wget -q --show-progress "https://nightly.link/Grasscutters/Grasscutter/workflows/build/$BRANCH/Grasscutter.zip" +echo "unzipping" +unzip -qq Grasscutter.zip +mv $(find -name "grasscutter*.jar" -type f) grasscutter.jar + +# Download resources +echo "Downloading resources... (this will take a moment)" +wget -q --show-progress https://github.com/Koko-boya/Grasscutter_Resources/archive/refs/heads/main.zip -O resources.zip +echo "Extracting..." +unzip -qq resources.zip +mv ./Grasscutter_Resources-main/Resources ./resources + +# Here we do a sparse checkout to only pull /data and /keys +echo "Downloading keys and data..." +mkdir repo +cd repo +git init -q +git remote add origin https://github.com/Grasscutters/Grasscutter.git +git fetch -q +git config core.sparseCheckout true +echo "data/" >> .git/info/sparse-checkout +echo "keys/" >> .git/info/sparse-checkout +git pull origin stable -q +cd ../ +mv ./repo/data ./data +mv ./repo/keys ./keys + +# Generate handbook/config +echo "Please enter language when *NEXT* prompted (press enter/return to continue to language select)" +read +java -jar grasscutter.jar -handbook + +# Prompt IP address for config.json and for generating new keystore.p12 file +echo "Please enter the IP address that will be used to connect to the server" +echo "This can be a local or a public IP address" +echo "This IP address will be used to generate SSL certificates so it is important it is correct" + +while : ; do + read -p "Enter IP: " SERVER_IP + if valid_ip $SERVER_IP; then + break; + else + echo "Invalid IP address. Try again." + fi +done + +# Replaces "127.0.0.1" with given IP +sed -i "s/127.0.0.1/$SERVER_IP/g" config.json + +# Generates new keystore.p12 with the server's IP address +# This is done to prevent a "Connection Timed Out" error from appearing +# after clicking to enter the door in the main menu/title screen +# This issue only exists when connecting to a server *other* than localhost +# since the default keystore.p12 has only been made for localhost + +mkdir certs +cd certs +echo "Generating CA key and certificate pair..." +openssl req -x509 -nodes -days 25202 -newkey rsa:2048 -subj "/C=GB/ST=Essex/L=London/O=Grasscutters/OU=Grasscutters/CN=$SERVER_IP" -keyout CAkey.key -out CAcert.crt +echo "Generating SSL key and certificate pair..." + +openssl genpkey -out ssl.key -algorithm rsa + +# Creates a conf file in order to generate a csr +cat > csr.conf < cert.conf < AGKPABKOHDA = 30; + /*oneof detail { + SeaLampActivityDetailInfo sam_lamp_info = 11; + CrucibleActivityDetailInfo crucible_info = 12; + SalesmanActivityDetailInfo salesman_info = 13; + TrialAvatarActivityDetailInfo trial_avatar_info = 14; + DeliveryActivityDetailInfo delivery_info = 16; + AsterActivityDetailInfo aster_info = 21; + FlightActivityDetailInfo flight_info = 25; + DragonSpineActivityDetailInfo dragon_spine_info = 31; + EffigyActivityDetailInfo effigy_info = 32; + TreasureMapActivityDetailInfo treasure_map_info = 35; + BlessingActivityDetailInfo blessing_info = 41; + SeaLampActivityInfo sea_lamp_info = 42; + ExpeditionActivityDetailInfo expedition_info = 43; + ArenaChallengeActivityDetailInfo arena_challenge_info = 44; + FleurFairActivityDetailInfo fleur_fair_info = 51; + WaterSpiritActivityDetailInfo water_spirit_info = 52; + ChannelerSlabActivityDetailInfo challneler_slab_info = 61; + MistTrialActivityDetailInfo mist_trial_activity_info = 62; + HideAndSeekActivityDetailInfo hide_and_seek_info = 63; + FindHilichurlDetailInfo find_hilichurl_info = 64; + SummerTimeDetailInfo summer_time_info = 65; + BuoyantCombatDetailInfo buoyant_combat_info = 66; + EchoShellDetailInfo echo_shell_info = 67; + BounceConjuringActivityDetailInfo bounce_conjuring_info = 68; + BlitzRushActivityDetailInfo blitz_rush_info = 69; + ChessActivityDetailInfo chess_info = 70; + SumoActivityDetailInfo sumo_info = 71; + MoonfinTrialActivityDetailInfo moonfin_trial_info = 72; + LunaRiteDetailInfo luna_rite_info = 73; + PlantFlowerActivityDetailInfo plant_flower_info = 74; + MusicGameActivityDetailInfo music_game_info = 75; + RoguelikeDungeonActivityDetailInfo roguelike_dungoen_info = 76; + DigActivityDetailInfo dig_info = 77; + DOCNGBMKEID hachi_info = 78; + DLHPBNNDGFI winter_camp_info = 79; + IFACCKLEJCC potion_info = 80; + PFMCPMIMGLM tanuki_travel_activity_info = 81; + JEIAODKGIBD lantern_rite_activity_info = 82; + EPDOGGKOCAP michiae_matsuri_info = 83; + NHMFHLIGAKL bartender_info = 84; + EAGKNMCLJDI ugc_info = 85; + ADPBMLFDHJD crystal_link_info = 86; + JACDNLEIDOO irodori_info = 87; + EHDKFDJEEGP photo_info = 88; + BEPFLAKHNHL spice_info = 89; + MMNEJBFMAEA gacha_info = 90; + JLMHDDHOGGD luminance_stone_challenge_info = 91; + IGBMCJOPGIL rogue_diary_info = 92; + }*/ } diff --git a/proto/ActivityWatcherInfo.proto b/proto/ActivityWatcherInfo.proto index fa82861c8..6a2293b29 100755 --- a/proto/ActivityWatcherInfo.proto +++ b/proto/ActivityWatcherInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ActivityWatcherInfo { uint32 watcher_id = 1; uint32 cur_progress = 2; diff --git a/proto/AiSkillCdInfo.proto b/proto/AiSkillCdInfo.proto index e0e205730..b03331b15 100755 --- a/proto/AiSkillCdInfo.proto +++ b/proto/AiSkillCdInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AiSkillCdInfo { map skill_cd_map = 1; map skill_group_cd_map = 2; diff --git a/proto/AiSyncInfo.proto b/proto/AiSyncInfo.proto index b279f2021..42784191f 100755 --- a/proto/AiSyncInfo.proto +++ b/proto/AiSyncInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AiSyncInfo { uint32 entity_id = 1; bool has_path_to_target = 2; diff --git a/proto/AiThreatInfo.proto b/proto/AiThreatInfo.proto index 24e2083d0..828d1ff66 100755 --- a/proto/AiThreatInfo.proto +++ b/proto/AiThreatInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AiThreatInfo { map ai_threat_map = 1; } diff --git a/proto/AllWidgetDataNotify.proto b/proto/AllWidgetDataNotify.proto new file mode 100644 index 000000000..8b0eaf34a --- /dev/null +++ b/proto/AllWidgetDataNotify.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "AnchorPointData.proto"; +// import "CCEOEOHLAPK.proto"; +import "ClientCollectorData.proto"; +import "LunchBoxData.proto"; +import "OneoffGatherPointDetectorData.proto"; +import "WidgetCoolDownData.proto"; +import "WidgetSlotData.proto"; + +// CmdId: 4273 +// EnetChannelId: 0 +// EnetIsReliable: true +message AllWidgetDataNotify { + repeated AnchorPointData anchor_point_list = 13; + uint32 next_anchor_point_usable_time = 10; + LunchBoxData lunch_box_data = 11; + repeated OneoffGatherPointDetectorData oneoff_gather_point_detector_data_list = 5; + repeated ClientCollectorData client_collector_data_list = 6; + repeated WidgetCoolDownData cool_down_group_data_list = 2; + repeated WidgetCoolDownData normal_cool_down_data_list = 4; + repeated WidgetSlotData slot_list = 3; + // CCEOEOHLAPK KNPDHPEGCHI = 12; +} diff --git a/proto/AnchorPointData.proto b/proto/AnchorPointData.proto new file mode 100644 index 000000000..9ad591363 --- /dev/null +++ b/proto/AnchorPointData.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +message AnchorPointData { + uint32 anchor_point_id = 1; + Vector pos = 2; + Vector rot = 3; + uint32 end_time = 4; + uint32 scene_id = 5; +} diff --git a/proto/AnchorPointDataNotify.proto b/proto/AnchorPointDataNotify.proto new file mode 100644 index 000000000..eee610963 --- /dev/null +++ b/proto/AnchorPointDataNotify.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "AnchorPointData.proto"; + +// CmdId: 4268 +// EnetChannelId: 0 +// EnetIsReliable: true +message AnchorPointDataNotify { + repeated AnchorPointData anchor_point_list = 14; + uint32 next_usable_time = 6; +} diff --git a/proto/AnchorPointOpReq.proto b/proto/AnchorPointOpReq.proto new file mode 100644 index 000000000..f9882e626 --- /dev/null +++ b/proto/AnchorPointOpReq.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4254 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message AnchorPointOpReq { + uint32 anchor_point_op_type = 6; + uint32 anchor_point_id = 1; + + enum AnchorPointOpType { + ANCHOR_POINT_OP_TYPE_NONE = 0; + ANCHOR_POINT_OP_TYPE_TELEPORT = 1; + ANCHOR_POINT_OP_TYPE_REMOVE = 2; + } +} diff --git a/proto/AnchorPointOpRsp.proto b/proto/AnchorPointOpRsp.proto new file mode 100644 index 000000000..db8852b07 --- /dev/null +++ b/proto/AnchorPointOpRsp.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4278 +// EnetChannelId: 0 +// EnetIsReliable: true +message AnchorPointOpRsp { + int32 retcode = 13; + uint32 anchor_point_op_type = 3; + uint32 anchor_point_id = 2; +} diff --git a/proto/AnimatorParameterValueInfo.proto b/proto/AnimatorParameterValueInfo.proto index fd74b7e42..8c1b5a2c0 100755 --- a/proto/AnimatorParameterValueInfo.proto +++ b/proto/AnimatorParameterValueInfo.proto @@ -2,12 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AnimatorParameterValueInfo { - oneof ParaVal { + uint32 para_type = 1; + oneof para_val { int32 int_val = 2; float float_val = 3; bool bool_val = 4; } - uint32 para_type = 1; } diff --git a/proto/AskAddFriendNotify.proto b/proto/AskAddFriendNotify.proto index 647ca561e..736bca43c 100755 --- a/proto/AskAddFriendNotify.proto +++ b/proto/AskAddFriendNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "FriendBrief.proto"; +// CmdId: 4038 +// EnetChannelId: 0 +// EnetIsReliable: true message AskAddFriendNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4006; - } - - uint32 target_uid = 1; - FriendBrief target_friend_brief = 2; + uint32 target_uid = 13; + FriendBrief target_friend_brief = 10; } diff --git a/proto/AskAddFriendReq.proto b/proto/AskAddFriendReq.proto index 65c89ea21..75b74678a 100755 --- a/proto/AskAddFriendReq.proto +++ b/proto/AskAddFriendReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4032 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AskAddFriendReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4100; - } - - uint32 target_uid = 1; + uint32 target_uid = 8; } diff --git a/proto/AskAddFriendRsp.proto b/proto/AskAddFriendRsp.proto index 12493c5bd..2643456f1 100755 --- a/proto/AskAddFriendRsp.proto +++ b/proto/AskAddFriendRsp.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4017 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AskAddFriendRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4001; - } - - int32 retcode = 1; - uint32 target_uid = 2; - uint32 param = 3; + int32 retcode = 11; + uint32 target_uid = 14; + uint32 param = 13; } diff --git a/proto/AttackHitEffectResult.proto b/proto/AttackHitEffectResult.proto index b3e0ec3d4..918d23a7e 100755 --- a/proto/AttackHitEffectResult.proto +++ b/proto/AttackHitEffectResult.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AttackHitEffectResult { uint32 hit_eff_level = 1; float retreat_strength = 2; diff --git a/proto/AttackResult.proto b/proto/AttackResult.proto index 6b55dd587..458188ba0 100755 --- a/proto/AttackResult.proto +++ b/proto/AttackResult.proto @@ -3,9 +3,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "AbilityIdentifier.proto"; +import "AttackHitEffectResult.proto"; import "HitCollision.proto"; import "Vector.proto"; -import "AttackHitEffectResult.proto"; message AttackResult { uint32 attacker_id = 1; @@ -37,4 +37,5 @@ message AttackResult { float endure_delta = 37; uint32 target_type = 38; float element_durability_attenuation = 39; + uint32 EGPFEACDCLP = 40; } diff --git a/proto/AvatarAddNotify.proto b/proto/AvatarAddNotify.proto index 72375aa8f..afdf42043 100755 --- a/proto/AvatarAddNotify.proto +++ b/proto/AvatarAddNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarInfo.proto"; +// CmdId: 1757 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarAddNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1795; - } - - AvatarInfo avatar = 1; - bool is_in_team = 2; + AvatarInfo avatar = 11; + bool is_in_team = 15; } diff --git a/proto/AvatarChangeCostumeNotify.proto b/proto/AvatarChangeCostumeNotify.proto index cb4c611a4..814bd3fd7 100755 --- a/proto/AvatarChangeCostumeNotify.proto +++ b/proto/AvatarChangeCostumeNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "SceneEntityInfo.proto"; +// CmdId: 1780 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarChangeCostumeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1724; - } - SceneEntityInfo entity_info = 1; } diff --git a/proto/AvatarChangeCostumeReq.proto b/proto/AvatarChangeCostumeReq.proto index 5da0ffd94..a3a7b4fee 100755 --- a/proto/AvatarChangeCostumeReq.proto +++ b/proto/AvatarChangeCostumeReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1734 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarChangeCostumeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1606; - } - - uint64 avatar_guid = 1; - uint32 costume_id = 2; + uint64 avatar_guid = 7; + uint32 costume_id = 8; } diff --git a/proto/AvatarChangeCostumeRsp.proto b/proto/AvatarChangeCostumeRsp.proto index e4e60bc94..e72ca326d 100755 --- a/proto/AvatarChangeCostumeRsp.proto +++ b/proto/AvatarChangeCostumeRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1723 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarChangeCostumeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1748; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 costume_id = 3; + int32 retcode = 15; + uint64 avatar_guid = 3; + uint32 costume_id = 1; } diff --git a/proto/AvatarDataNotify.proto b/proto/AvatarDataNotify.proto index dd93c8c35..cd344ab13 100755 --- a/proto/AvatarDataNotify.proto +++ b/proto/AvatarDataNotify.proto @@ -5,20 +5,15 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarInfo.proto"; import "AvatarTeam.proto"; +// CmdId: 1695 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1694; - } - - repeated AvatarInfo avatar_list = 1; - map avatar_team_map = 2; - uint32 cur_avatar_team_id = 3; - fixed64 choose_avatar_guid = 4; - repeated uint64 temp_avatar_guid_list = 5; - repeated uint32 owned_flycloak_list = 6; + repeated AvatarInfo avatar_list = 15; + map avatar_team_map = 6; + uint32 cur_avatar_team_id = 2; + fixed64 choose_avatar_guid = 11; + repeated uint64 temp_avatar_guid_list = 14; + repeated uint32 owned_flycloak_list = 8; repeated uint32 owned_costume_list = 7; } diff --git a/proto/AvatarDieAnimationEndReq.proto b/proto/AvatarDieAnimationEndReq.proto index de301fc9f..28cd9d59d 100755 --- a/proto/AvatarDieAnimationEndReq.proto +++ b/proto/AvatarDieAnimationEndReq.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 1616 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarDieAnimationEndReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1737; - } - - uint64 die_guid = 1; - uint32 skill_id = 2; - Vector reborn_pos = 3; + uint64 die_guid = 14; + uint32 skill_id = 4; + Vector reborn_pos = 13; } diff --git a/proto/AvatarDieAnimationEndRsp.proto b/proto/AvatarDieAnimationEndRsp.proto index 58c9ecb7c..eca9beb77 100755 --- a/proto/AvatarDieAnimationEndRsp.proto +++ b/proto/AvatarDieAnimationEndRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1765 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarDieAnimationEndRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1697; - } - - int32 retcode = 1; - uint64 die_guid = 2; - uint32 skill_id = 3; + int32 retcode = 12; + uint64 die_guid = 11; + uint32 skill_id = 13; } diff --git a/proto/AvatarEquipAffixInfo.proto b/proto/AvatarEquipAffixInfo.proto index ef4a49fa4..ed0c4130b 100755 --- a/proto/AvatarEquipAffixInfo.proto +++ b/proto/AvatarEquipAffixInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AvatarEquipAffixInfo { uint32 equip_affix_id = 1; uint32 left_cd_time = 2; diff --git a/proto/AvatarEquipChangeNotify.proto b/proto/AvatarEquipChangeNotify.proto index c69c73f82..95535b7b2 100755 --- a/proto/AvatarEquipChangeNotify.proto +++ b/proto/AvatarEquipChangeNotify.proto @@ -2,23 +2,18 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "SceneWeaponInfo.proto"; import "SceneReliquaryInfo.proto"; +import "SceneWeaponInfo.proto"; +// CmdId: 690 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarEquipChangeNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 615; - } - uint64 avatar_guid = 1; uint32 equip_type = 2; - uint32 item_id = 3; + uint32 item_id = 8; uint64 equip_guid = 4; - SceneWeaponInfo weapon = 5; - SceneReliquaryInfo reliquary = 6; + SceneWeaponInfo weapon = 13; + SceneReliquaryInfo reliquary = 11; } diff --git a/proto/AvatarExpeditionAllDataRsp.proto b/proto/AvatarExpeditionAllDataRsp.proto index 5ff61dbcd..535b9e8e7 100644 --- a/proto/AvatarExpeditionAllDataRsp.proto +++ b/proto/AvatarExpeditionAllDataRsp.proto @@ -1,19 +1,15 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionInfo.proto"; +// CmdId: 1636 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarExpeditionAllDataRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1783; - } - - int32 retcode = 1; - map expedition_info_map = 2; - repeated uint32 open_expedition_list = 3; - uint32 expedition_count_limit = 4; + int32 retcode = 11; + map expedition_info_map = 1; + repeated uint32 open_expedition_list = 6; + uint32 expedition_count_limit = 7; } diff --git a/proto/AvatarExpeditionCallBackReq.proto b/proto/AvatarExpeditionCallBackReq.proto index b1131a2aa..fefc45cbb 100644 --- a/proto/AvatarExpeditionCallBackReq.proto +++ b/proto/AvatarExpeditionCallBackReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1655 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarExpeditionCallBackReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1618; - } - - repeated uint64 avatar_guid = 1; + repeated uint64 avatar_guid = 12; } diff --git a/proto/AvatarExpeditionCallBackRsp.proto b/proto/AvatarExpeditionCallBackRsp.proto index 75adca0f6..6cd5ab850 100644 --- a/proto/AvatarExpeditionCallBackRsp.proto +++ b/proto/AvatarExpeditionCallBackRsp.proto @@ -1,17 +1,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionInfo.proto"; +// CmdId: 1642 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarExpeditionCallBackRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1633; - } - int32 retcode = 1; - map expedition_info_map = 2; + map expedition_info_map = 14; } diff --git a/proto/AvatarExpeditionDataNotify.proto b/proto/AvatarExpeditionDataNotify.proto index 8adef648a..68983c602 100644 --- a/proto/AvatarExpeditionDataNotify.proto +++ b/proto/AvatarExpeditionDataNotify.proto @@ -1,16 +1,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionInfo.proto"; +// CmdId: 1698 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarExpeditionDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1621; - } - map expedition_info_map = 1; } diff --git a/proto/AvatarExpeditionGetRewardReq.proto b/proto/AvatarExpeditionGetRewardReq.proto index 847f96fee..58f34055e 100644 --- a/proto/AvatarExpeditionGetRewardReq.proto +++ b/proto/AvatarExpeditionGetRewardReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1603 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarExpeditionGetRewardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1610; - } - - uint64 avatar_guid = 1; + uint64 avatar_guid = 5; } diff --git a/proto/AvatarExpeditionGetRewardRsp.proto b/proto/AvatarExpeditionGetRewardRsp.proto index c494b77a2..818c9cf2c 100644 --- a/proto/AvatarExpeditionGetRewardRsp.proto +++ b/proto/AvatarExpeditionGetRewardRsp.proto @@ -1,19 +1,16 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionInfo.proto"; - import "ItemParam.proto"; -message AvatarExpeditionGetRewardRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1670; - } - int32 retcode = 1; - map expedition_info_map = 2; - repeated ItemParam item_list = 3; +// CmdId: 1646 +// EnetChannelId: 0 +// EnetIsReliable: true +message AvatarExpeditionGetRewardRsp { + int32 retcode = 15; + map expedition_info_map = 5; + repeated ItemParam item_list = 6; + repeated ItemParam BNFDDKNNJJH = 2; } diff --git a/proto/AvatarExpeditionInfo.proto b/proto/AvatarExpeditionInfo.proto index 180482bd0..ae52bd889 100644 --- a/proto/AvatarExpeditionInfo.proto +++ b/proto/AvatarExpeditionInfo.proto @@ -1,6 +1,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionState.proto"; message AvatarExpeditionInfo { diff --git a/proto/AvatarExpeditionStartReq.proto b/proto/AvatarExpeditionStartReq.proto index cbfe1a15d..d40f3072d 100644 --- a/proto/AvatarExpeditionStartReq.proto +++ b/proto/AvatarExpeditionStartReq.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1675 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarExpeditionStartReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1609; - } - - uint64 avatar_guid = 1; + uint64 avatar_guid = 8; uint32 exp_id = 2; - uint32 hour_time = 3; + uint32 hour_time = 7; } diff --git a/proto/AvatarExpeditionStartRsp.proto b/proto/AvatarExpeditionStartRsp.proto index c48fe2ad4..b289cc46c 100644 --- a/proto/AvatarExpeditionStartRsp.proto +++ b/proto/AvatarExpeditionStartRsp.proto @@ -1,17 +1,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "AvatarExpeditionInfo.proto"; +// CmdId: 1688 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarExpeditionStartRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1646; - } - - int32 retcode = 1; - map expedition_info_map = 2; + int32 retcode = 4; + map expedition_info_map = 1; } diff --git a/proto/AvatarExpeditionState.proto b/proto/AvatarExpeditionState.proto index 7b43570a6..7ec3f8f78 100755 --- a/proto/AvatarExpeditionState.proto +++ b/proto/AvatarExpeditionState.proto @@ -3,9 +3,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum AvatarExpeditionState { - AVATAR_EXPEDITION_NONE = 0; - AVATAR_EXPEDITION_DOING = 1; - AVATAR_EXPEDITION_FINISH_WAIT_REWARD = 2; - AVATAR_EXPEDITION_CALLBACK_WAIT_REWARD = 3; - AVATAR_EXPEDITION_LOCKED = 4; + AVATAR_EXPEDITION_STATE_NONE = 0; + AVATAR_EXPEDITION_STATE_DOING = 1; + AVATAR_EXPEDITION_STATE_FINISH_WAIT_REWARD = 2; + AVATAR_EXPEDITION_STATE_CALLBACK_WAIT_REWARD = 3; + AVATAR_EXPEDITION_STATE_LOCKED = 4; } diff --git a/proto/AvatarFetterDataNotify.proto b/proto/AvatarFetterDataNotify.proto index cace9aba6..222322314 100644 --- a/proto/AvatarFetterDataNotify.proto +++ b/proto/AvatarFetterDataNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarFetterInfo.proto"; +// CmdId: 1777 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarFetterDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1685; - } - map fetter_info_map = 1; } diff --git a/proto/AvatarFetterLevelRewardReq.proto b/proto/AvatarFetterLevelRewardReq.proto index 56d941a7a..b9ec51925 100644 --- a/proto/AvatarFetterLevelRewardReq.proto +++ b/proto/AvatarFetterLevelRewardReq.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1704 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarFetterLevelRewardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1624; - } - - uint64 avatar_guid = 1; + uint64 avatar_guid = 15; uint32 fetter_level = 2; } diff --git a/proto/AvatarFetterLevelRewardRsp.proto b/proto/AvatarFetterLevelRewardRsp.proto index 0fbc864e8..684a9df07 100644 --- a/proto/AvatarFetterLevelRewardRsp.proto +++ b/proto/AvatarFetterLevelRewardRsp.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1606 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarFetterLevelRewardRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1704; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 fetter_level = 3; - uint32 reward_id = 4; + int32 retcode = 14; + uint64 avatar_guid = 12; + uint32 fetter_level = 10; + uint32 reward_id = 11; } diff --git a/proto/AvatarFightPropNotify.proto b/proto/AvatarFightPropNotify.proto index 00a50c17d..9d48d260b 100755 --- a/proto/AvatarFightPropNotify.proto +++ b/proto/AvatarFightPropNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1232 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarFightPropNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1300; - } - - uint64 avatar_guid = 1; - map fight_prop_map = 2; + uint64 avatar_guid = 3; + map fight_prop_map = 6; } diff --git a/proto/AvatarFightPropUpdateNotify.proto b/proto/AvatarFightPropUpdateNotify.proto index c187c2968..75ca268a2 100755 --- a/proto/AvatarFightPropUpdateNotify.proto +++ b/proto/AvatarFightPropUpdateNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1217 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarFightPropUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1201; - } - uint64 avatar_guid = 1; - map fight_prop_map = 2; + map fight_prop_map = 6; } diff --git a/proto/AvatarFlycloakChangeNotify.proto b/proto/AvatarFlycloakChangeNotify.proto index e7a92573f..7ccc46886 100755 --- a/proto/AvatarFlycloakChangeNotify.proto +++ b/proto/AvatarFlycloakChangeNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1681 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarFlycloakChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1759; - } - - uint64 avatar_guid = 1; - uint32 flycloak_id = 2; + uint64 avatar_guid = 12; + uint32 flycloak_id = 14; } diff --git a/proto/AvatarGainCostumeNotify.proto b/proto/AvatarGainCostumeNotify.proto index 2989054c6..c64ff586e 100755 --- a/proto/AvatarGainCostumeNotify.proto +++ b/proto/AvatarGainCostumeNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1670 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarGainCostumeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1734; - } - - uint32 costume_id = 1; + uint32 costume_id = 15; } diff --git a/proto/AvatarGainFlycloakNotify.proto b/proto/AvatarGainFlycloakNotify.proto index a3450d09d..b38269560 100755 --- a/proto/AvatarGainFlycloakNotify.proto +++ b/proto/AvatarGainFlycloakNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1615 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarGainFlycloakNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1604; - } - - uint32 flycloak_id = 1; + uint32 flycloak_id = 2; } diff --git a/proto/AvatarInfo.proto b/proto/AvatarInfo.proto index 3b77c9040..717300ca8 100755 --- a/proto/AvatarInfo.proto +++ b/proto/AvatarInfo.proto @@ -2,13 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "TrialAvatarInfo.proto"; -import "AvatarFetterInfo.proto"; -import "AvatarExpeditionState.proto"; -import "AvatarExcelInfo.proto"; -import "PropValue.proto"; -import "AvatarSkillInfo.proto"; import "AvatarEquipAffixInfo.proto"; +import "AvatarExcelInfo.proto"; +import "AvatarExpeditionState.proto"; +import "AvatarFetterInfo.proto"; +import "AvatarSkillInfo.proto"; +import "PropValue.proto"; +import "TrialAvatarInfo.proto"; message AvatarInfo { uint32 avatar_id = 1; diff --git a/proto/AvatarLifeStateChangeNotify.proto b/proto/AvatarLifeStateChangeNotify.proto index 9b0b8102d..6888cb904 100755 --- a/proto/AvatarLifeStateChangeNotify.proto +++ b/proto/AvatarLifeStateChangeNotify.proto @@ -5,20 +5,15 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerDieType.proto"; import "ServerBuff.proto"; +// CmdId: 1235 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarLifeStateChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1242; - } - - uint64 avatar_guid = 1; - uint32 life_state = 2; - uint32 source_entity_id = 3; - string attack_tag = 4; - PlayerDieType die_type = 5; - uint32 move_reliable_seq = 6; - repeated ServerBuff server_buff_list = 7; + uint64 avatar_guid = 8; + uint32 life_state = 15; + uint32 source_entity_id = 1; + string attack_tag = 10; + PlayerDieType die_type = 11; + uint32 move_reliable_seq = 7; + repeated ServerBuff server_buff_list = 6; } diff --git a/proto/AvatarPromoteGetRewardReq.proto b/proto/AvatarPromoteGetRewardReq.proto index 1f9d73fb7..1cbc3e1a1 100755 --- a/proto/AvatarPromoteGetRewardReq.proto +++ b/proto/AvatarPromoteGetRewardReq.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1676 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarPromoteGetRewardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1701; - } - - uint64 avatar_guid = 1; - uint32 promote_level = 2; + uint64 avatar_guid = 12; + uint32 promote_level = 8; } diff --git a/proto/AvatarPromoteGetRewardRsp.proto b/proto/AvatarPromoteGetRewardRsp.proto index a4cae2bca..b9f621c17 100755 --- a/proto/AvatarPromoteGetRewardRsp.proto +++ b/proto/AvatarPromoteGetRewardRsp.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1613 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarPromoteGetRewardRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1764; - } - - int32 retcode = 1; + int32 retcode = 11; uint64 avatar_guid = 2; - uint32 promote_level = 3; - uint32 reward_id = 4; + uint32 promote_level = 14; + uint32 reward_id = 1; } diff --git a/proto/AvatarPromoteReq.proto b/proto/AvatarPromoteReq.proto index 1f14f38bd..907f0f233 100755 --- a/proto/AvatarPromoteReq.proto +++ b/proto/AvatarPromoteReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1711 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarPromoteReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1692; - } - - uint64 guid = 1; + uint64 guid = 9; } diff --git a/proto/AvatarPromoteRsp.proto b/proto/AvatarPromoteRsp.proto index 3e1287006..24dd33029 100755 --- a/proto/AvatarPromoteRsp.proto +++ b/proto/AvatarPromoteRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1668 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarPromoteRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1728; - } - - int32 retcode = 1; - uint64 guid = 2; + int32 retcode = 15; + uint64 guid = 7; } diff --git a/proto/AvatarPropNotify.proto b/proto/AvatarPropNotify.proto index 46e7d41ac..e9449a4a9 100755 --- a/proto/AvatarPropNotify.proto +++ b/proto/AvatarPropNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1255 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarPropNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1212; - } - - uint64 avatar_guid = 1; - map prop_map = 2; + uint64 avatar_guid = 4; + map prop_map = 1; } diff --git a/proto/AvatarSkillChangeNotify.proto b/proto/AvatarSkillChangeNotify.proto index e0a10ac75..f08b33810 100755 --- a/proto/AvatarSkillChangeNotify.proto +++ b/proto/AvatarSkillChangeNotify.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1030 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarSkillChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1091; - } - - uint64 avatar_guid = 1; - uint32 entity_id = 2; - uint32 skill_depot_id = 3; - uint32 avatar_skill_id = 4; - uint32 old_level = 5; - uint32 cur_level = 6; + uint64 avatar_guid = 4; + uint32 entity_id = 15; + uint32 skill_depot_id = 5; + uint32 avatar_skill_id = 2; + uint32 old_level = 10; + uint32 cur_level = 7; } diff --git a/proto/AvatarSkillInfo.proto b/proto/AvatarSkillInfo.proto index da5c086c7..9d71c1b71 100755 --- a/proto/AvatarSkillInfo.proto +++ b/proto/AvatarSkillInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AvatarSkillInfo { uint32 pass_cd_time = 1; repeated uint32 full_cd_time_list = 2; diff --git a/proto/AvatarSkillInfoNotify.proto b/proto/AvatarSkillInfoNotify.proto index d56acb166..4f54cb866 100644 --- a/proto/AvatarSkillInfoNotify.proto +++ b/proto/AvatarSkillInfoNotify.proto @@ -4,7 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarSkillInfo.proto"; +// CmdId: 1035 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarSkillInfoNotify { - uint64 guid = 1; + uint64 guid = 4; map skill_map = 2; } diff --git a/proto/AvatarSkillMaxChargeCountNotify.proto b/proto/AvatarSkillMaxChargeCountNotify.proto index abbd17d2d..4a028ad2c 100644 --- a/proto/AvatarSkillMaxChargeCountNotify.proto +++ b/proto/AvatarSkillMaxChargeCountNotify.proto @@ -2,8 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1085 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarSkillMaxChargeCountNotify { - uint64 avatar_guid = 1; + uint64 avatar_guid = 15; uint32 skill_id = 2; - uint32 max_charge_count = 3; + uint32 max_charge_count = 1; } diff --git a/proto/AvatarSkillUpgradeReq.proto b/proto/AvatarSkillUpgradeReq.proto index 02ff7373d..611c3026b 100755 --- a/proto/AvatarSkillUpgradeReq.proto +++ b/proto/AvatarSkillUpgradeReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1027 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarSkillUpgradeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1026; - } - uint64 avatar_guid = 1; - uint32 avatar_skill_id = 2; - uint32 old_level = 3; + uint32 avatar_skill_id = 5; + uint32 old_level = 10; } diff --git a/proto/AvatarSkillUpgradeRsp.proto b/proto/AvatarSkillUpgradeRsp.proto index 7ec89d675..780c65a53 100755 --- a/proto/AvatarSkillUpgradeRsp.proto +++ b/proto/AvatarSkillUpgradeRsp.proto @@ -2,19 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1007 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarSkillUpgradeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1024; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 avatar_skill_id = 3; - uint32 old_level = 4; - uint32 cur_level = 5; + int32 retcode = 3; + uint64 avatar_guid = 10; + uint32 avatar_skill_id = 2; + uint32 old_level = 5; + uint32 cur_level = 7; } diff --git a/proto/AvatarTeam.proto b/proto/AvatarTeam.proto index 08b4885e6..aab6ee4cd 100755 --- a/proto/AvatarTeam.proto +++ b/proto/AvatarTeam.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AvatarTeam { repeated uint64 avatar_guid_list = 1; string team_name = 2; diff --git a/proto/AvatarTeamResonanceInfo.proto b/proto/AvatarTeamResonanceInfo.proto index b5569065b..182b84532 100755 --- a/proto/AvatarTeamResonanceInfo.proto +++ b/proto/AvatarTeamResonanceInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message AvatarTeamResonanceInfo { uint32 entity_id = 1; uint64 avatar_guid = 2; diff --git a/proto/AvatarTeamUpdateNotify.proto b/proto/AvatarTeamUpdateNotify.proto index ec6dbbda4..4c264f176 100755 --- a/proto/AvatarTeamUpdateNotify.proto +++ b/proto/AvatarTeamUpdateNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarTeam.proto"; +// CmdId: 1713 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarTeamUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1642; - } - - map avatar_team_map = 1; - repeated uint64 temp_avatar_guid_list = 2; + map avatar_team_map = 6; + repeated uint64 temp_avatar_guid_list = 9; } diff --git a/proto/AvatarUnlockTalentNotify.proto b/proto/AvatarUnlockTalentNotify.proto index b883c7dfc..5b37d18f6 100755 --- a/proto/AvatarUnlockTalentNotify.proto +++ b/proto/AvatarUnlockTalentNotify.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1041 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarUnlockTalentNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1089; - } - uint64 avatar_guid = 1; - uint32 entity_id = 2; - uint32 talent_id = 3; - uint32 skill_depot_id = 4; + uint32 entity_id = 15; + uint32 talent_id = 13; + uint32 skill_depot_id = 14; } diff --git a/proto/AvatarUpgradeReq.proto b/proto/AvatarUpgradeReq.proto index cc561e7bb..0d263afaf 100755 --- a/proto/AvatarUpgradeReq.proto +++ b/proto/AvatarUpgradeReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1680 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarUpgradeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1691; - } - - uint32 item_id = 1; - uint32 count = 2; - uint64 avatar_guid = 3; + uint32 item_id = 9; + uint32 count = 12; + uint64 avatar_guid = 14; } diff --git a/proto/AvatarUpgradeRsp.proto b/proto/AvatarUpgradeRsp.proto index f3a8f8ad7..14ac0fa43 100755 --- a/proto/AvatarUpgradeRsp.proto +++ b/proto/AvatarUpgradeRsp.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1779 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarUpgradeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1720; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 old_level = 3; - uint32 cur_level = 4; - map old_fight_prop_map = 5; - map cur_fight_prop_map = 6; + int32 retcode = 6; + uint64 avatar_guid = 15; + uint32 old_level = 5; + uint32 cur_level = 7; + map old_fight_prop_map = 2; + map cur_fight_prop_map = 4; } diff --git a/proto/AvatarWearFlycloakReq.proto b/proto/AvatarWearFlycloakReq.proto index aa99c6df4..1e480f7f7 100755 --- a/proto/AvatarWearFlycloakReq.proto +++ b/proto/AvatarWearFlycloakReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1728 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message AvatarWearFlycloakReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1635; - } - - uint64 avatar_guid = 1; - uint32 flycloak_id = 2; + uint64 avatar_guid = 11; + uint32 flycloak_id = 9; } diff --git a/proto/AvatarWearFlycloakRsp.proto b/proto/AvatarWearFlycloakRsp.proto index a78f0cada..062a4ad43 100755 --- a/proto/AvatarWearFlycloakRsp.proto +++ b/proto/AvatarWearFlycloakRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1770 +// EnetChannelId: 0 +// EnetIsReliable: true message AvatarWearFlycloakRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1709; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 flycloak_id = 3; + int32 retcode = 13; + uint64 avatar_guid = 8; + uint32 flycloak_id = 2; } diff --git a/proto/Birthday.proto b/proto/Birthday.proto index 027a9ed39..b360bcfd2 100755 --- a/proto/Birthday.proto +++ b/proto/Birthday.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message Birthday { uint32 month = 1; uint32 day = 2; diff --git a/proto/BlockInfo.proto b/proto/BlockInfo.proto index 93ecdad4f..8844d0287 100755 --- a/proto/BlockInfo.proto +++ b/proto/BlockInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message BlockInfo { uint32 block_id = 1; uint32 data_version = 2; diff --git a/proto/BuyGoodsReq.proto b/proto/BuyGoodsReq.proto index 976ccba51..57b1246a7 100644 --- a/proto/BuyGoodsReq.proto +++ b/proto/BuyGoodsReq.proto @@ -4,8 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ShopGoods.proto"; +// CmdId: 741 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message BuyGoodsReq { - uint32 shopType = 1; - repeated ShopGoods goodsList = 2; - uint32 boughtNum = 3; + uint32 shop_type = 15; + ShopGoods goods = 13; + uint32 buy_count = 6; } diff --git a/proto/BuyGoodsRsp.proto b/proto/BuyGoodsRsp.proto index 26d8c0bda..c266bc012 100644 --- a/proto/BuyGoodsRsp.proto +++ b/proto/BuyGoodsRsp.proto @@ -4,8 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "ShopGoods.proto"; +// CmdId: 737 +// EnetChannelId: 0 +// EnetIsReliable: true message BuyGoodsRsp { - uint32 shopType = 2; - uint32 boughtNum = 4; - repeated ShopGoods goodsList = 5; + int32 retcode = 15; + uint32 shop_type = 12; + ShopGoods goods = 13; + uint32 buy_count = 8; + repeated ShopGoods goods_list = 1; } diff --git a/proto/CBJEDMGOBPL.proto b/proto/CBJEDMGOBPL.proto new file mode 100644 index 000000000..861bdd601 --- /dev/null +++ b/proto/CBJEDMGOBPL.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum CBJEDMGOBPL { + CBJEDMGOBPL_MBLDLJOKLBL = 0; + CBJEDMGOBPL_ILOMIKADKGD = 1; + CBJEDMGOBPL_HGHOEJGHMDH = 2; + CBJEDMGOBPL_PJCONIDJGOD = 3; +} diff --git a/proto/CalcWeaponUpgradeReturnItemsReq.proto b/proto/CalcWeaponUpgradeReturnItemsReq.proto index 1a7c5a858..d75740eab 100755 --- a/proto/CalcWeaponUpgradeReturnItemsReq.proto +++ b/proto/CalcWeaponUpgradeReturnItemsReq.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 610 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message CalcWeaponUpgradeReturnItemsReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 669; - } - - uint64 target_weapon_guid = 1; - repeated uint64 food_weapon_guid_list = 2; - repeated ItemParam item_param_list = 3; + uint64 target_weapon_guid = 9; + repeated uint64 food_weapon_guid_list = 10; + repeated ItemParam item_param_list = 14; } diff --git a/proto/CalcWeaponUpgradeReturnItemsRsp.proto b/proto/CalcWeaponUpgradeReturnItemsRsp.proto index a3d78aa87..905b17fb8 100755 --- a/proto/CalcWeaponUpgradeReturnItemsRsp.proto +++ b/proto/CalcWeaponUpgradeReturnItemsRsp.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 666 +// EnetChannelId: 0 +// EnetIsReliable: true message CalcWeaponUpgradeReturnItemsRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 660; - } - - int32 retcode = 1; - uint64 target_weapon_guid = 2; + int32 retcode = 5; + uint64 target_weapon_guid = 10; repeated ItemParam item_param_list = 3; } diff --git a/proto/CanUseSkillNotify.proto b/proto/CanUseSkillNotify.proto new file mode 100644 index 000000000..fd61b1a92 --- /dev/null +++ b/proto/CanUseSkillNotify.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 1098 +// EnetChannelId: 0 +// EnetIsReliable: true +message CanUseSkillNotify { + bool is_can_use_skill = 6; +} diff --git a/proto/CardProductRewardNotify.proto b/proto/CardProductRewardNotify.proto index 109e685e1..c0b529e78 100644 --- a/proto/CardProductRewardNotify.proto +++ b/proto/CardProductRewardNotify.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 4104 +// EnetChannelId: 0 +// EnetIsReliable: true message CardProductRewardNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4105; - } - - string product_id = 1; - uint32 hcoin = 2; - uint32 remain_days = 3; + string product_id = 6; + uint32 hcoin = 11; + uint32 remain_days = 5; } diff --git a/proto/ChallengeDataNotify.proto b/proto/ChallengeDataNotify.proto index aaf5484ec..476dfdf23 100644 --- a/proto/ChallengeDataNotify.proto +++ b/proto/ChallengeDataNotify.proto @@ -2,8 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 963 +// EnetChannelId: 0 +// EnetIsReliable: true message ChallengeDataNotify { - uint32 challenge_index = 1; - uint32 param_index = 2; - uint32 value = 3; + uint32 challenge_index = 8; + uint32 param_index = 9; + uint32 value = 1; } diff --git a/proto/ChangeAvatarReq.proto b/proto/ChangeAvatarReq.proto index d6fdc2b1c..2e2218186 100755 --- a/proto/ChangeAvatarReq.proto +++ b/proto/ChangeAvatarReq.proto @@ -4,18 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 1662 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChangeAvatarReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1669; - } - - uint64 guid = 1; - uint32 skill_id = 2; - bool is_move = 3; - Vector move_pos = 4; + uint64 guid = 5; + uint32 skill_id = 11; + bool is_move = 7; + Vector move_pos = 9; } diff --git a/proto/ChangeAvatarRsp.proto b/proto/ChangeAvatarRsp.proto index d7308e51e..f644cdaf5 100755 --- a/proto/ChangeAvatarRsp.proto +++ b/proto/ChangeAvatarRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1710 +// EnetChannelId: 0 +// EnetIsReliable: true message ChangeAvatarRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1634; - } - - int32 retcode = 1; - uint64 cur_guid = 2; - uint32 skill_id = 3; + int32 retcode = 6; + uint64 cur_guid = 11; + uint32 skill_id = 5; } diff --git a/proto/ChangeEnergyReason.proto b/proto/ChangeEnergyReason.proto index 5e7558388..65104d09b 100644 --- a/proto/ChangeEnergyReason.proto +++ b/proto/ChangeEnergyReason.proto @@ -3,6 +3,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum ChangeEnergyReason { - CHANGE_ENERGY_NONE = 0; - CHANGE_ENERGY_SKILL_START = 1; + CHANGE_ENERGY_REASON_NONE = 0; + CHANGE_ENERGY_REASON_SKILL_START = 1; } diff --git a/proto/ChangeGameTimeReq.proto b/proto/ChangeGameTimeReq.proto index 9c080687f..74203a722 100755 --- a/proto/ChangeGameTimeReq.proto +++ b/proto/ChangeGameTimeReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 149 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChangeGameTimeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 161; - } - - uint32 game_time = 1; - bool is_force_set = 2; - uint32 extra_days = 3; + uint32 game_time = 9; + bool is_force_set = 7; + uint32 extra_days = 6; } diff --git a/proto/ChangeGameTimeRsp.proto b/proto/ChangeGameTimeRsp.proto index 221792204..078a73512 100755 --- a/proto/ChangeGameTimeRsp.proto +++ b/proto/ChangeGameTimeRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 182 +// EnetChannelId: 0 +// EnetIsReliable: true message ChangeGameTimeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 179; - } - - int32 retcode = 1; - uint32 cur_game_time = 2; - uint32 extra_days = 3; + int32 retcode = 7; + uint32 cur_game_time = 1; + uint32 extra_days = 2; } diff --git a/proto/ChangeHpReason.proto b/proto/ChangeHpReason.proto index e56d9acc3..48cdb4b53 100755 --- a/proto/ChangeHpReason.proto +++ b/proto/ChangeHpReason.proto @@ -3,29 +3,34 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum ChangeHpReason { - ChangeHpNone = 0; - ChangeHpSubAvatar = 1; - ChangeHpSubMonster = 2; - ChangeHpSubGear = 3; - ChangeHpSubEnvir = 4; - ChangeHpSubFall = 5; - ChangeHpSubDrawn = 6; - ChangeHpSubAbyss = 7; - ChangeHpSubAbility = 8; - ChangeHpSubSummon = 9; - ChangeHpSubScript = 10; - ChangeHpSubGm = 11; - ChangeHpSubKillSelf = 12; - ChangeHpSubClimateCold = 13; - ChangeHpSubStormLightning = 14; - ChangeHpSubKillServerGadget = 15; - ChangeHpByLua = 51; - ChangeHpAddAbility = 101; - ChangeHpAddItem = 102; - ChangeHpAddRevive = 103; - ChangeHpAddUpgrade = 104; - ChangeHpAddStatue = 105; - ChangeHpAddBackground = 106; - ChangeHpAddGm = 107; - ChangeHpAddTrialAvatarActivity = 108; + CHANGE_HP_REASON_CHANGE_HP_NONE = 0; + CHANGE_HP_REASON_CHANGE_HP_SUB_AVATAR = 1; + CHANGE_HP_REASON_CHANGE_HP_SUB_MONSTER = 2; + CHANGE_HP_REASON_CHANGE_HP_SUB_GEAR = 3; + CHANGE_HP_REASON_CHANGE_HP_SUB_ENVIR = 4; + CHANGE_HP_REASON_CHANGE_HP_SUB_FALL = 5; + CHANGE_HP_REASON_CHANGE_HP_SUB_DRAWN = 6; + CHANGE_HP_REASON_CHANGE_HP_SUB_ABYSS = 7; + CHANGE_HP_REASON_CHANGE_HP_SUB_ABILITY = 8; + CHANGE_HP_REASON_CHANGE_HP_SUB_SUMMON = 9; + CHANGE_HP_REASON_CHANGE_HP_SUB_SCRIPT = 10; + CHANGE_HP_REASON_CHANGE_HP_SUB_GM = 11; + CHANGE_HP_REASON_CHANGE_HP_SUB_KILL_SELF = 12; + CHANGE_HP_REASON_CHANGE_HP_SUB_CLIMATE_COLD = 13; + CHANGE_HP_REASON_CHANGE_HP_SUB_STORM_LIGHTNING = 14; + CHANGE_HP_REASON_CHANGE_HP_SUB_KILL_SERVER_GADGET = 15; + CHANGE_HP_REASON_CHANGE_HP_SUB_REPLACE = 16; + CHANGE_HP_REASON_CHANGE_HP_SUB_PLAYER_LEAVE = 17; + CHANGE_HP_REASON_CIKCDBOJGDK = 18; + CHANGE_HP_REASON_HEKLBLFBJJK = 19; + CHANGE_HP_REASON_CHANGE_HP_BY_LUA = 51; + CHANGE_HP_REASON_CHANGE_HP_ADD_ABILITY = 101; + CHANGE_HP_REASON_CHANGE_HP_ADD_ITEM = 102; + CHANGE_HP_REASON_CHANGE_HP_ADD_REVIVE = 103; + CHANGE_HP_REASON_CHANGE_HP_ADD_UPGRADE = 104; + CHANGE_HP_REASON_CHANGE_HP_ADD_STATUE = 105; + CHANGE_HP_REASON_CHANGE_HP_ADD_BACKGROUND = 106; + CHANGE_HP_REASON_CHANGE_HP_ADD_GM = 107; + CHANGE_HP_REASON_CHANGE_HP_ADD_TRIAL_AVATAR_ACTIVITY = 108; + CHANGE_HP_REASON_CHANGE_HP_ADD_ROUGUELIKE_SPRING = 109; } diff --git a/proto/ChangeMailStarNotify.proto b/proto/ChangeMailStarNotify.proto index e5347c86b..7588e662b 100644 --- a/proto/ChangeMailStarNotify.proto +++ b/proto/ChangeMailStarNotify.proto @@ -2,7 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1407 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChangeMailStarNotify { - repeated uint32 mail_id_list = 1; - bool is_star = 2; + repeated uint32 mail_id_list = 5; + bool is_star = 9; } diff --git a/proto/ChangeMpTeamAvatarReq.proto b/proto/ChangeMpTeamAvatarReq.proto index 9ab827372..021946592 100755 --- a/proto/ChangeMpTeamAvatarReq.proto +++ b/proto/ChangeMpTeamAvatarReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1689 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChangeMpTeamAvatarReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1731; - } - - repeated uint64 avatar_guid_list = 1; - uint64 cur_avatar_guid = 2; + repeated uint64 avatar_guid_list = 5; + uint64 cur_avatar_guid = 12; } diff --git a/proto/ChangeMpTeamAvatarRsp.proto b/proto/ChangeMpTeamAvatarRsp.proto index 4aca75336..6339f5aed 100755 --- a/proto/ChangeMpTeamAvatarRsp.proto +++ b/proto/ChangeMpTeamAvatarRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1617 +// EnetChannelId: 0 +// EnetIsReliable: true message ChangeMpTeamAvatarRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1640; - } - - int32 retcode = 1; - repeated uint64 avatar_guid_list = 2; - uint64 cur_avatar_guid = 3; + int32 retcode = 7; + repeated uint64 avatar_guid_list = 3; + uint64 cur_avatar_guid = 8; } diff --git a/proto/ChangeTeamNameReq.proto b/proto/ChangeTeamNameReq.proto index 764b49856..239edf51f 100755 --- a/proto/ChangeTeamNameReq.proto +++ b/proto/ChangeTeamNameReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1762 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChangeTeamNameReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1693; - } - - int32 team_id = 1; - string team_name = 2; + int32 team_id = 12; + string team_name = 15; } diff --git a/proto/ChangeTeamNameRsp.proto b/proto/ChangeTeamNameRsp.proto index 1e0ba48fe..f601b7550 100755 --- a/proto/ChangeTeamNameRsp.proto +++ b/proto/ChangeTeamNameRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1789 +// EnetChannelId: 0 +// EnetIsReliable: true message ChangeTeamNameRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1788; - } - - int32 team_id = 1; + int32 team_id = 6; string team_name = 2; - int32 retcode = 3; + int32 retcode = 8; } diff --git a/proto/ChatInfo.proto b/proto/ChatInfo.proto index b1f8f33bf..6491ced1e 100755 --- a/proto/ChatInfo.proto +++ b/proto/ChatInfo.proto @@ -2,26 +2,25 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ChatInfo { - enum SystemHintType { - CHAT_NONE = 0; - CHAT_ENTER_WORLD = 1; - CHAT_LEAVE_WORLD = 2; - } - - message SystemHint { - uint32 type = 1; - } - - oneof Content { - string text = 100; - uint32 icon = 101; - SystemHint system_hint = 102; - } uint32 time = 1; uint32 uid = 2; uint32 sequence = 3; uint32 to_uid = 4; bool is_read = 5; + oneof content { + string text = 100; + uint32 icon = 101; + SystemHint system_hint = 102; + } + + enum SystemHintType { + SYSTEM_HINT_TYPE_CHAT_NONE = 0; + SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD = 1; + SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD = 2; + } + + message SystemHint { + uint32 type = 1; + } } diff --git a/proto/CheckAddItemExceedLimitNotify.proto b/proto/CheckAddItemExceedLimitNotify.proto new file mode 100755 index 000000000..a7861117b --- /dev/null +++ b/proto/CheckAddItemExceedLimitNotify.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 653 +// EnetChannelId: 0 +// EnetIsReliable: true +message CheckAddItemExceedLimitNotify { + bool is_drop = 1; + repeated uint32 exceeded_item_list = 8; + repeated uint32 exceeded_item_type_list = 3; + ItemExceedLimitMsgType msg_type = 14; + + enum ItemExceedLimitMsgType { + ITEM_EXCEED_LIMIT_MSG_TYPE_DEFAULT = 0; + ITEM_EXCEED_LIMIT_MSG_TYPE_TEXT = 1; + ITEM_EXCEED_LIMIT_MSG_TYPE_DIALOG = 2; + ITEM_EXCEED_LIMIT_MSG_TYPE_BONLGEEEBBF = 3; + } +} diff --git a/proto/ChildQuest.proto b/proto/ChildQuest.proto new file mode 100644 index 000000000..fcec288c1 --- /dev/null +++ b/proto/ChildQuest.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message ChildQuest { + uint32 quest_id = 1; + uint32 state = 2; + uint32 quest_config_id = 3; +} diff --git a/proto/ChooseCurAvatarTeamReq.proto b/proto/ChooseCurAvatarTeamReq.proto index 1ea02de57..d039a395a 100755 --- a/proto/ChooseCurAvatarTeamReq.proto +++ b/proto/ChooseCurAvatarTeamReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1800 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ChooseCurAvatarTeamReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1663; - } - - uint32 team_id = 1; + uint32 team_id = 14; } diff --git a/proto/ChooseCurAvatarTeamRsp.proto b/proto/ChooseCurAvatarTeamRsp.proto index 0b1503781..ab77584ad 100755 --- a/proto/ChooseCurAvatarTeamRsp.proto +++ b/proto/ChooseCurAvatarTeamRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1673 +// EnetChannelId: 0 +// EnetIsReliable: true message ChooseCurAvatarTeamRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1798; - } - - int32 retcode = 1; - uint32 cur_team_id = 2; + int32 retcode = 7; + uint32 cur_team_id = 4; } diff --git a/proto/CityInfo.proto b/proto/CityInfo.proto index 5bf9163e0..c4559372d 100755 --- a/proto/CityInfo.proto +++ b/proto/CityInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message CityInfo { uint32 city_id = 1; uint32 level = 2; diff --git a/proto/ClientAbilityChangeNotify.proto b/proto/ClientAbilityChangeNotify.proto index cb3b23508..c2d727b94 100755 --- a/proto/ClientAbilityChangeNotify.proto +++ b/proto/ClientAbilityChangeNotify.proto @@ -4,16 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "AbilityInvokeEntry.proto"; +// CmdId: 1127 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ClientAbilityChangeNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1126; - } - - uint32 entity_id = 1; - repeated AbilityInvokeEntry invokes = 2; + uint32 entity_id = 6; + repeated AbilityInvokeEntry invokes = 8; + bool JCJNLMLGHJE = 10; } diff --git a/proto/ClientAbilityInitBeginNotify.proto b/proto/ClientAbilityInitBeginNotify.proto index 82dbd5b10..ba40b0262 100755 --- a/proto/ClientAbilityInitBeginNotify.proto +++ b/proto/ClientAbilityInitBeginNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1141 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ClientAbilityInitBeginNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1189; - } - uint32 entity_id = 1; } diff --git a/proto/ClientAbilityInitFinishNotify.proto b/proto/ClientAbilityInitFinishNotify.proto index a591eaa93..9860aad09 100755 --- a/proto/ClientAbilityInitFinishNotify.proto +++ b/proto/ClientAbilityInitFinishNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "AbilityInvokeEntry.proto"; +// CmdId: 1137 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ClientAbilityInitFinishNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1184; - } - - uint32 entity_id = 1; - repeated AbilityInvokeEntry invokes = 2; + uint32 entity_id = 13; + repeated AbilityInvokeEntry invokes = 9; } diff --git a/proto/ClientCollectorData.proto b/proto/ClientCollectorData.proto new file mode 100644 index 000000000..6092c8e37 --- /dev/null +++ b/proto/ClientCollectorData.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message ClientCollectorData { + uint32 material_id = 1; + uint32 max_points = 2; + uint32 curr_points = 3; +} diff --git a/proto/ClientCollectorDataNotify.proto b/proto/ClientCollectorDataNotify.proto new file mode 100644 index 000000000..ff75edd6c --- /dev/null +++ b/proto/ClientCollectorDataNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ClientCollectorData.proto"; + +// CmdId: 4264 +// EnetChannelId: 0 +// EnetIsReliable: true +message ClientCollectorDataNotify { + repeated ClientCollectorData client_collector_data_list = 8; +} diff --git a/proto/ClientGadgetInfo.proto b/proto/ClientGadgetInfo.proto index 14add090c..b28dedf58 100644 --- a/proto/ClientGadgetInfo.proto +++ b/proto/ClientGadgetInfo.proto @@ -9,4 +9,6 @@ message ClientGadgetInfo { uint32 owner_entity_id = 4; uint32 target_entity_id = 5; bool async_load = 6; + bool CEGHBCJMNFJ = 7; + repeated uint32 FCFECGFHLAD = 8; } diff --git a/proto/CodexDataFullNotify.proto b/proto/CodexDataFullNotify.proto new file mode 100644 index 000000000..1ba67f039 --- /dev/null +++ b/proto/CodexDataFullNotify.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "CodexTypeData.proto"; + +// CmdId: 4201 +// EnetChannelId: 0 +// EnetIsReliable: true +message CodexDataFullNotify { + repeated CodexTypeData type_data_list = 5; + repeated uint32 IGMFFAGOCIA = 11; + uint32 BIFMJKDHHLG = 8; + uint32 AEHJDIPOLHC = 10; +} diff --git a/proto/CodexDataUpdateNotify.proto b/proto/CodexDataUpdateNotify.proto new file mode 100644 index 000000000..8b881bd00 --- /dev/null +++ b/proto/CodexDataUpdateNotify.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "CodexType.proto"; + +// CmdId: 4210 +// EnetChannelId: 0 +// EnetIsReliable: true +message CodexDataUpdateNotify { + CodexType type = 3; + uint32 id = 4; + uint32 weapon_max_promote_level = 12; +} diff --git a/proto/CodexType.proto b/proto/CodexType.proto new file mode 100644 index 000000000..6dea0998c --- /dev/null +++ b/proto/CodexType.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum CodexType { + CODEX_TYPE_NONE = 0; + CODEX_TYPE_QUEST = 1; + CODEX_TYPE_WEAPON = 2; + CODEX_TYPE_ANIMAL = 3; + CODEX_TYPE_MATERIAL = 4; + CODEX_TYPE_BOOKS = 5; + CODEX_TYPE_PUSHTIPS = 6; + CODEX_TYPE_VIEW = 7; + CODEX_TYPE_RELIQUARY = 8; +} diff --git a/proto/CodexTypeComparer.proto b/proto/CodexTypeComparer.proto new file mode 100644 index 000000000..d87068c90 --- /dev/null +++ b/proto/CodexTypeComparer.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message CodexTypeComparer { +} diff --git a/proto/CodexTypeData.proto b/proto/CodexTypeData.proto new file mode 100644 index 000000000..061fd9a48 --- /dev/null +++ b/proto/CodexTypeData.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "CodexType.proto"; + +message CodexTypeData { + CodexType type = 1; + repeated uint32 codex_id_list = 2; + repeated bool have_viewed_list = 3; + map weapon_max_promote_level_map = 4; +} diff --git a/proto/CombatInvocationsNotify.proto b/proto/CombatInvocationsNotify.proto index 0f5c8e4bd..5025fed86 100755 --- a/proto/CombatInvocationsNotify.proto +++ b/proto/CombatInvocationsNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "CombatInvokeEntry.proto"; +// CmdId: 316 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message CombatInvocationsNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 359; - } - - repeated CombatInvokeEntry invoke_list = 1; + repeated CombatInvokeEntry invoke_list = 4; } diff --git a/proto/CombatTypeArgument.proto b/proto/CombatTypeArgument.proto index 9116aba0b..1449f42d6 100755 --- a/proto/CombatTypeArgument.proto +++ b/proto/CombatTypeArgument.proto @@ -3,20 +3,22 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum CombatTypeArgument { - COMBAT_NONE = 0; - COMBAT_EVT_BEING_HIT = 1; - COMBAT_ANIMATOR_STATE_CHANGED = 2; - COMBAT_FACE_TO_DIR = 3; - COMBAT_SET_ATTACK_TARGET = 4; - COMBAT_RUSH_MOVE = 5; - COMBAT_ANIMATOR_PARAMETER_CHANGED = 6; - ENTITY_MOVE = 7; - SYNC_ENTITY_POSITION = 8; - COMBAT_STEER_MOTION_INFO = 9; - COMBAT_FORCE_SET_POS_INFO = 10; - COMBAT_COMPENSATE_POS_DIFF = 11; - COMBAT_MONSTER_DO_BLINK = 12; - COMBAT_FIXED_RUSH_MOVE = 13; - COMBAT_SYNC_TRANSFORM = 14; - COMBAT_LIGHT_CORE_MOVE = 15; + COMBAT_TYPE_ARGUMENT_NONE = 0; + COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT = 1; + COMBAT_TYPE_ARGUMENT_ANIMATOR_STATE_CHANGED = 2; + COMBAT_TYPE_ARGUMENT_FACE_TO_DIR = 3; + COMBAT_TYPE_ARGUMENT_SET_ATTACK_TARGET = 4; + COMBAT_TYPE_ARGUMENT_RUSH_MOVE = 5; + COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED = 6; + COMBAT_TYPE_ARGUMENT_ENTITY_MOVE = 7; + COMBAT_TYPE_ARGUMENT_SYNC_ENTITY_POSITION = 8; + COMBAT_TYPE_ARGUMENT_STEER_MOTION_INFO = 9; + COMBAT_TYPE_ARGUMENT_FORCE_SET_POS_INFO = 10; + COMBAT_TYPE_ARGUMENT_COMPENSATE_POS_DIFF = 11; + COMBAT_TYPE_ARGUMENT_MONSTER_DO_BLINK = 12; + COMBAT_TYPE_ARGUMENT_FIXED_RUSH_MOVE = 13; + COMBAT_TYPE_ARGUMENT_SYNC_TRANSFORM = 14; + COMBAT_TYPE_ARGUMENT_LIGHT_CORE_MOVE = 15; + COMBAT_TYPE_ARGUMENT_KPDNFKCMKPG = 16; + COMBAT_TYPE_ARGUMENT_KPLOMOIALGF = 17; } diff --git a/proto/CombineDataNotify.proto b/proto/CombineDataNotify.proto index 1ef4c8a5f..9afc6856c 100644 --- a/proto/CombineDataNotify.proto +++ b/proto/CombineDataNotify.proto @@ -2,14 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 661 +// EnetChannelId: 0 +// EnetIsReliable: true message CombineDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 657; - } - - repeated uint32 combine_id_list = 1; + repeated uint32 combine_id_list = 5; } diff --git a/proto/CombineFormulaDataNotify.proto b/proto/CombineFormulaDataNotify.proto index 3c13553ed..2fd20a930 100644 --- a/proto/CombineFormulaDataNotify.proto +++ b/proto/CombineFormulaDataNotify.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 688 +// EnetChannelId: 0 +// EnetIsReliable: true message CombineFormulaDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 682; - } - - uint32 combine_id = 1; - bool is_locked = 2; + uint32 combine_id = 6; + bool is_locked = 5; } diff --git a/proto/CombineReq.proto b/proto/CombineReq.proto index 58d38e15b..f4c7c5f0a 100644 --- a/proto/CombineReq.proto +++ b/proto/CombineReq.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 654 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message CombineReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 655; - } - - uint32 combine_id = 1; - uint32 combine_count = 2; - uint64 avatar_guid = 3; + uint32 combine_id = 5; + uint32 combine_count = 3; + uint64 avatar_guid = 8; } diff --git a/proto/CombineRsp.proto b/proto/CombineRsp.proto index bba446ae7..9bd9e7d19 100644 --- a/proto/CombineRsp.proto +++ b/proto/CombineRsp.proto @@ -4,22 +4,17 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 646 +// EnetChannelId: 0 +// EnetIsReliable: true message CombineRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 695; - } - - int32 retcode = 1; - uint32 combine_id = 2; - uint32 combine_count = 3; - uint64 avatar_guid = 4; - repeated ItemParam cost_item_list = 5; - repeated ItemParam result_item_list = 6; - repeated ItemParam total_random_item_list = 7; - repeated ItemParam total_return_item_list = 8; - repeated ItemParam total_extra_item_list = 9; + int32 retcode = 13; + uint32 combine_id = 12; + uint32 combine_count = 6; + uint64 avatar_guid = 15; + repeated ItemParam cost_item_list = 10; + repeated ItemParam result_item_list = 2; + repeated ItemParam total_random_item_list = 9; + repeated ItemParam total_return_item_list = 4; + repeated ItemParam total_extra_item_list = 8; } diff --git a/proto/CoopCg.proto b/proto/CoopCg.proto index a507579d8..675289879 100755 --- a/proto/CoopCg.proto +++ b/proto/CoopCg.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message CoopCg { uint32 id = 1; bool is_unlock = 2; diff --git a/proto/CoopChapter.proto b/proto/CoopChapter.proto index 360df6249..c3f3e4cfc 100755 --- a/proto/CoopChapter.proto +++ b/proto/CoopChapter.proto @@ -2,18 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +import "CoopCg.proto"; import "CoopPoint.proto"; import "CoopReward.proto"; -import "CoopCg.proto"; message CoopChapter { - enum State { - CLOSE = 0; - COND_NOT_MEET = 1; - COND_MEET = 2; - ACCEPT = 3; - } - uint32 id = 1; State state = 2; repeated uint32 lock_reason_list = 3; @@ -24,4 +17,11 @@ message CoopChapter { uint32 finished_end_count = 8; map seen_ending_map = 9; repeated uint32 finish_dialog_list = 10; + + enum State { + STATE_CLOSE = 0; + STATE_COND_NOT_MEET = 1; + STATE_COND_MEET = 2; + STATE_ACCEPT = 3; + } } diff --git a/proto/CoopDataNotify.proto b/proto/CoopDataNotify.proto index a9e673f30..786e401f4 100755 --- a/proto/CoopDataNotify.proto +++ b/proto/CoopDataNotify.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "CoopChapter.proto"; +// CmdId: 1976 +// EnetChannelId: 0 +// EnetIsReliable: true message CoopDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1957; - } - - repeated CoopChapter chapter_list = 1; - bool is_have_progress = 2; - uint32 cur_coop_point = 3; - repeated uint32 viewed_chapter_list = 4; + repeated CoopChapter chapter_list = 13; + bool is_have_progress = 14; + uint32 cur_coop_point = 5; + repeated uint32 viewed_chapter_list = 2; } diff --git a/proto/CoopPoint.proto b/proto/CoopPoint.proto index d0c728eb5..ceacc8af4 100755 --- a/proto/CoopPoint.proto +++ b/proto/CoopPoint.proto @@ -2,15 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message CoopPoint { - enum State { - UNSTARTED = 0; - STARTED = 1; - FINISHED = 2; - } - uint32 id = 1; State state = 2; uint32 self_confidence = 3; + + enum State { + STATE_UNSTARTED = 0; + STATE_STARTED = 1; + STATE_FINISHED = 2; + } } diff --git a/proto/CoopReward.proto b/proto/CoopReward.proto index 38cac7285..43f060ffe 100755 --- a/proto/CoopReward.proto +++ b/proto/CoopReward.proto @@ -2,14 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message CoopReward { - enum State { - UNLOCK = 0; - LOCK = 1; - TAKEN = 2; - } - uint32 id = 1; State state = 2; + + enum State { + STATE_UNLOCK = 0; + STATE_LOCK = 1; + STATE_TAKEN = 2; + } } diff --git a/proto/CreateVehicleReq.proto b/proto/CreateVehicleReq.proto new file mode 100644 index 000000000..4affab707 --- /dev/null +++ b/proto/CreateVehicleReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +// CmdId: 819 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message CreateVehicleReq { + uint32 vehicle_id = 9; + uint32 scene_point_id = 15; + Vector pos = 1; + Vector rot = 7; +} diff --git a/proto/CreateVehicleRsp.proto b/proto/CreateVehicleRsp.proto new file mode 100644 index 000000000..baabe996f --- /dev/null +++ b/proto/CreateVehicleRsp.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 812 +// EnetChannelId: 0 +// EnetIsReliable: true +message CreateVehicleRsp { + int32 retcode = 7; + uint32 vehicle_id = 8; + uint32 entity_id = 10; +} diff --git a/proto/CutSceneBeginNotify.proto b/proto/CutSceneBeginNotify.proto new file mode 100644 index 000000000..a409b4bb0 --- /dev/null +++ b/proto/CutSceneBeginNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 300 +// EnetChannelId: 0 +// EnetIsReliable: true +message CutSceneBeginNotify { + uint32 cutscene_id = 9; + bool is_wait_others = 11; +} diff --git a/proto/CutSceneEndNotify.proto b/proto/CutSceneEndNotify.proto new file mode 100644 index 000000000..66e0a768b --- /dev/null +++ b/proto/CutSceneEndNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 299 +// EnetChannelId: 0 +// EnetIsReliable: true +message CutSceneEndNotify { + int32 retcode = 8; + uint32 cutscene_id = 11; +} diff --git a/proto/CutSceneFinishNotify.proto b/proto/CutSceneFinishNotify.proto new file mode 100644 index 000000000..49940c0b6 --- /dev/null +++ b/proto/CutSceneFinishNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 294 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message CutSceneFinishNotify { + uint32 cutscene_id = 14; +} diff --git a/proto/DealAddFriendReq.proto b/proto/DealAddFriendReq.proto index 1941a5cde..add0c673d 100755 --- a/proto/DealAddFriendReq.proto +++ b/proto/DealAddFriendReq.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "DealAddFriendResultType.proto"; +// CmdId: 4085 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DealAddFriendReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4094; - } - - uint32 target_uid = 1; - DealAddFriendResultType deal_add_friend_result = 2; + uint32 target_uid = 7; + DealAddFriendResultType deal_add_friend_result = 1; } diff --git a/proto/DealAddFriendResultType.proto b/proto/DealAddFriendResultType.proto index f0925b009..8336021a3 100755 --- a/proto/DealAddFriendResultType.proto +++ b/proto/DealAddFriendResultType.proto @@ -3,6 +3,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum DealAddFriendResultType { - DEAL_ADD_FRIEND_REJECT = 0; - DEAL_ADD_FRIEND_ACCEPT = 1; + DEAL_ADD_FRIEND_RESULT_TYPE_REJECT = 0; + DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT = 1; } diff --git a/proto/DealAddFriendRsp.proto b/proto/DealAddFriendRsp.proto index b8961f45a..75c6a4a4f 100755 --- a/proto/DealAddFriendRsp.proto +++ b/proto/DealAddFriendRsp.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "DealAddFriendResultType.proto"; +// CmdId: 4035 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DealAddFriendRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4042; - } - - int32 retcode = 1; + int32 retcode = 3; uint32 target_uid = 2; - DealAddFriendResultType deal_add_friend_result = 3; + DealAddFriendResultType deal_add_friend_result = 15; } diff --git a/proto/DelMailReq.proto b/proto/DelMailReq.proto index ac72fce2b..264b30a81 100644 --- a/proto/DelMailReq.proto +++ b/proto/DelMailReq.proto @@ -2,6 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1417 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DelMailReq { - repeated uint32 mail_id_list = 1; + repeated uint32 mail_id_list = 6; } diff --git a/proto/DelMailRsp.proto b/proto/DelMailRsp.proto index cd20e6fa9..517df959b 100644 --- a/proto/DelMailRsp.proto +++ b/proto/DelMailRsp.proto @@ -2,7 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1485 +// EnetChannelId: 0 +// EnetIsReliable: true message DelMailRsp { - int32 retcode = 1; - repeated uint32 mail_id_list = 2; + int32 retcode = 1; + repeated uint32 mail_id_list = 4; } diff --git a/proto/DelTeamEntityNotify.proto b/proto/DelTeamEntityNotify.proto index 28ff11662..85279fe15 100755 --- a/proto/DelTeamEntityNotify.proto +++ b/proto/DelTeamEntityNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 302 +// EnetChannelId: 0 +// EnetIsReliable: true message DelTeamEntityNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 366; - } - - uint32 scene_id = 1; - repeated uint32 del_entity_id_list = 2; + uint32 scene_id = 8; + repeated uint32 del_entity_id_list = 15; } diff --git a/proto/DeleteFriendNotify.proto b/proto/DeleteFriendNotify.proto index c8befa9e8..1d7d5fbd3 100755 --- a/proto/DeleteFriendNotify.proto +++ b/proto/DeleteFriendNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4063 +// EnetChannelId: 0 +// EnetIsReliable: true message DeleteFriendNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4032; - } - - uint32 target_uid = 1; + uint32 target_uid = 14; } diff --git a/proto/DeleteFriendReq.proto b/proto/DeleteFriendReq.proto index b27fd960d..1ed309a84 100755 --- a/proto/DeleteFriendReq.proto +++ b/proto/DeleteFriendReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4055 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DeleteFriendReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4012; - } - - uint32 target_uid = 1; + uint32 target_uid = 7; } diff --git a/proto/DeleteFriendRsp.proto b/proto/DeleteFriendRsp.proto index fe9412096..9ff896a49 100755 --- a/proto/DeleteFriendRsp.proto +++ b/proto/DeleteFriendRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4027 +// EnetChannelId: 0 +// EnetIsReliable: true message DeleteFriendRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4026; - } - - int32 retcode = 1; - uint32 target_uid = 2; + int32 retcode = 4; + uint32 target_uid = 8; } diff --git a/proto/DestroyMaterialReq.proto b/proto/DestroyMaterialReq.proto index a2a0915cf..ccb2ffc12 100755 --- a/proto/DestroyMaterialReq.proto +++ b/proto/DestroyMaterialReq.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "MaterialInfo.proto"; +// CmdId: 678 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DestroyMaterialReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 687; - } - - repeated MaterialInfo material_list = 1; + repeated MaterialInfo material_list = 12; } diff --git a/proto/DestroyMaterialRsp.proto b/proto/DestroyMaterialRsp.proto index 229784363..34e65315e 100755 --- a/proto/DestroyMaterialRsp.proto +++ b/proto/DestroyMaterialRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 608 +// EnetChannelId: 0 +// EnetIsReliable: true message DestroyMaterialRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 641; - } - - int32 retcode = 1; - repeated uint32 item_id_list = 2; - repeated uint32 item_count_list = 3; + int32 retcode = 9; + repeated uint32 item_id_list = 11; + repeated uint32 item_count_list = 10; } diff --git a/proto/DoGachaReq.proto b/proto/DoGachaReq.proto index 85a632c80..c6e4eded1 100755 --- a/proto/DoGachaReq.proto +++ b/proto/DoGachaReq.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1541 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DoGachaReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1589; - } - - uint32 gacha_type = 1; - uint32 gacha_times = 2; - uint32 gacha_random = 3; - uint32 gacha_schedule_id = 4; - string gacha_tag = 5; + uint32 gacha_type = 10; + uint32 gacha_times = 15; + uint32 gacha_random = 5; + uint32 gacha_schedule_id = 6; + string gacha_tag = 4; } diff --git a/proto/DoGachaRsp.proto b/proto/DoGachaRsp.proto index 83fd92899..51d2edd72 100755 --- a/proto/DoGachaRsp.proto +++ b/proto/DoGachaRsp.proto @@ -4,28 +4,25 @@ option java_package = "emu.grasscutter.net.proto"; import "GachaItem.proto"; +// CmdId: 1537 +// EnetChannelId: 0 +// EnetIsReliable: true message DoGachaRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1584; - } - - int32 retcode = 1; - uint32 gacha_type = 2; + int32 retcode = 9; + uint32 gacha_type = 11; uint32 gacha_times = 3; uint32 gacha_schedule_id = 4; - repeated GachaItem gacha_item_list = 5; - uint32 new_gacha_random = 6; - uint32 cost_item_id = 7; - uint32 cost_item_num = 8; - uint32 ten_cost_item_id = 9; - uint32 ten_cost_item_num = 10; - uint32 left_gacha_times = 11; - uint32 gacha_times_limit = 12; - uint32 wish_item_id = 13; - uint32 wish_progress = 14; - uint32 wish_max_progress = 15; + repeated GachaItem gacha_item_list = 2; + uint32 new_gacha_random = 8; + uint32 cost_item_id = 6; + uint32 cost_item_num = 1; + uint32 ten_cost_item_id = 14; + uint32 ten_cost_item_num = 7; + uint32 left_gacha_times = 15; + uint32 gacha_times_limit = 13; + uint32 wish_item_id = 10; + uint32 wish_progress = 5; + uint32 wish_max_progress = 12; + uint32 NKJOBOABFOJ = 1679; + bool PODALHILIKF = 1561; } diff --git a/proto/DropHintNotify.proto b/proto/DropHintNotify.proto index c22cb3d55..cece2eef9 100755 --- a/proto/DropHintNotify.proto +++ b/proto/DropHintNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 622 +// EnetChannelId: 0 +// EnetIsReliable: true message DropHintNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 609; - } - - repeated uint32 item_id_list = 1; - Vector position = 2; + repeated uint32 item_id_list = 12; + Vector position = 1; } diff --git a/proto/DungeonChallengeBeginNotify.proto b/proto/DungeonChallengeBeginNotify.proto index 936de9268..e34a9c8b2 100644 --- a/proto/DungeonChallengeBeginNotify.proto +++ b/proto/DungeonChallengeBeginNotify.proto @@ -2,11 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 990 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonChallengeBeginNotify { - uint32 challenge_id = 1; - uint32 challenge_index = 2; - repeated uint32 param_list = 3; - uint32 group_id = 4; - uint32 father_index = 5; - repeated uint32 uid_list = 6; + uint32 challenge_id = 8; + uint32 challenge_index = 11; + repeated uint32 param_list = 13; + uint32 group_id = 12; + uint32 father_index = 6; + repeated uint32 uid_list = 9; } diff --git a/proto/DungeonChallengeFinishNotify.proto b/proto/DungeonChallengeFinishNotify.proto index abababed3..47a3bcd1c 100644 --- a/proto/DungeonChallengeFinishNotify.proto +++ b/proto/DungeonChallengeFinishNotify.proto @@ -2,21 +2,29 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +//import "CDPBNKLFNKP.proto"; import "ChannellerSlabLoopDungeonResultInfo.proto"; import "EffigyChallengeDungeonResultInfo.proto"; +//import "FHOKHHBGPEG.proto"; +//import "IDFFMJEDODN.proto"; import "StrengthenPointData.proto"; +// CmdId: 986 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonChallengeFinishNotify { - oneof Detail { - ChannellerSlabLoopDungeonResultInfo channeller_slab_loop_dungeon_result_info = 101; - EffigyChallengeDungeonResultInfo effigy_challenge_dungeon_result_info = 102; + uint32 challenge_index = 11; + bool is_success = 4; + bool is_new_record = 2; + uint32 challenge_record_type = 10; + uint32 current_value = 12; + map strengthen_point_data_map = 13; + //FHOKHHBGPEG NJDMJAFIJNH = 15; + uint32 time_cost = 6; + oneof detail { + ChannellerSlabLoopDungeonResultInfo channeller_slab_loop_dungeon_result_info = 1758; + EffigyChallengeDungeonResultInfo effigy_challenge_dungeon_result_info = 913; + //CDPBNKLFNKP potion_dungeon_result_info = 382; + //IDFFMJEDODN custom_dungeon_result_info = 1411; } - uint32 challenge_index = 1; - bool is_success = 2; - bool is_new_record = 3; - uint32 challenge_record_type = 4; - uint32 current_value = 5; - map strengthen_point_data_map = 6; - uint32 unk1 = 7; - uint32 unk2 = 8; } diff --git a/proto/DungeonDataNotify.proto b/proto/DungeonDataNotify.proto index 797564f9e..2638b9305 100644 --- a/proto/DungeonDataNotify.proto +++ b/proto/DungeonDataNotify.proto @@ -2,6 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 945 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonDataNotify { - map dungeon_data_map = 1; + map dungeon_data_map = 6; } diff --git a/proto/DungeonEntryInfoReq.proto b/proto/DungeonEntryInfoReq.proto index 9bcc2edfe..b88d3ab74 100755 --- a/proto/DungeonEntryInfoReq.proto +++ b/proto/DungeonEntryInfoReq.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 909 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message DungeonEntryInfoReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 949; - } - - uint32 point_id = 1; + uint32 point_id = 15; + uint32 scene_id = 3; } diff --git a/proto/DungeonEntryInfoRsp.proto b/proto/DungeonEntryInfoRsp.proto index 4e529f95c..d385c7772 100755 --- a/proto/DungeonEntryInfoRsp.proto +++ b/proto/DungeonEntryInfoRsp.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "DungeonEntryInfo.proto"; +// CmdId: 931 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonEntryInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 918; - } - - int32 retcode = 1; - uint32 point_id = 2; - repeated DungeonEntryInfo dungeon_entry_list = 3; + int32 retcode = 14; + uint32 point_id = 9; + repeated DungeonEntryInfo dungeon_entry_list = 10; uint32 recommend_dungeon_id = 4; } diff --git a/proto/DungeonGetStatueDropRsp.proto b/proto/DungeonGetStatueDropRsp.proto index 29a8a76c7..09617113b 100644 --- a/proto/DungeonGetStatueDropRsp.proto +++ b/proto/DungeonGetStatueDropRsp.proto @@ -2,6 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 906 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonGetStatueDropRsp { - int32 retcode = 1; + int32 retcode = 13; } diff --git a/proto/DungeonSettleExhibitionInfo.proto b/proto/DungeonSettleExhibitionInfo.proto new file mode 100644 index 000000000..d8b9714ec --- /dev/null +++ b/proto/DungeonSettleExhibitionInfo.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ExhibitionDisplayInfo.proto"; +import "OnlinePlayerInfo.proto"; + +message DungeonSettleExhibitionInfo { + OnlinePlayerInfo player_info = 1; + repeated ExhibitionDisplayInfo card_list = 2; +} diff --git a/proto/DungeonSettleNotify.proto b/proto/DungeonSettleNotify.proto index c48ab8f6f..bd5cad6ab 100644 --- a/proto/DungeonSettleNotify.proto +++ b/proto/DungeonSettleNotify.proto @@ -2,20 +2,35 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +import "ChannellerSlabLoopDungeonResultInfo.proto"; +import "DungeonSettleExhibitionInfo.proto"; +import "EffigyChallengeDungeonResultInfo.proto"; +//import "KHPIGECGFKI.proto"; import "ParamList.proto"; +import "RoguelikeDungeonSettleInfo.proto"; import "StrengthenPointData.proto"; import "TowerLevelEndNotify.proto"; +import "TrialAvatarFirstPassDungeonNotify.proto"; +// CmdId: 982 +// EnetChannelId: 0 +// EnetIsReliable: true message DungeonSettleNotify { - oneof Detail { - TowerLevelEndNotify tower_level_end_notify = 101; - // it has more! + uint32 dungeon_id = 9; + bool is_success = 10; + repeated uint32 fail_cond_list = 13; + map settle_show = 11; + uint32 close_time = 12; + map strengthen_point_data_map = 4; + uint32 result = 15; + repeated DungeonSettleExhibitionInfo exhibition_info_list = 14; + //uint32 OMBINLAOGBM = 5; + oneof detail { + TowerLevelEndNotify tower_level_end_notify = 97; + TrialAvatarFirstPassDungeonNotify trial_avatar_first_pass_dungeon_notify = 796; + ChannellerSlabLoopDungeonResultInfo channeller_slab_loop_dungeon_result_info = 1671; + EffigyChallengeDungeonResultInfo effigy_challenge_dungeon_result_info = 1638; + RoguelikeDungeonSettleInfo roguelike_dungeon_settle_info = 71; + //KHPIGECGFKI crystal_link_settle_info = 430; } - uint32 dungeon_id = 1; - bool is_success = 2; - repeated uint32 fail_cond_list = 3; - map settle_show = 4; - uint32 close_time = 5; - map strengthen_point_data_map = 6; - uint32 result = 7; } diff --git a/proto/EnterSceneDoneRsp.proto b/proto/EnterSceneDoneRsp.proto index e4d9d4221..d5a4a1bc4 100755 --- a/proto/EnterSceneDoneRsp.proto +++ b/proto/EnterSceneDoneRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 269 +// EnetChannelId: 0 +// EnetIsReliable: true message EnterSceneDoneRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 248; - } - - int32 retcode = 1; - uint32 enter_scene_token = 2; + int32 retcode = 9; + uint32 enter_scene_token = 8; } diff --git a/proto/EnterScenePeerNotify.proto b/proto/EnterScenePeerNotify.proto index 61f39228f..e4ca37ced 100755 --- a/proto/EnterScenePeerNotify.proto +++ b/proto/EnterScenePeerNotify.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 257 +// EnetChannelId: 0 +// EnetIsReliable: true message EnterScenePeerNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 223; - } - - uint32 dest_scene_id = 1; - uint32 peer_id = 2; - uint32 host_peer_id = 3; - uint32 enter_scene_token = 4; + uint32 dest_scene_id = 13; + uint32 peer_id = 11; + uint32 host_peer_id = 6; + uint32 enter_scene_token = 15; } diff --git a/proto/EnterSceneReadyRsp.proto b/proto/EnterSceneReadyRsp.proto index 93ba80072..8f384a943 100755 --- a/proto/EnterSceneReadyRsp.proto +++ b/proto/EnterSceneReadyRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 252 +// EnetChannelId: 0 +// EnetIsReliable: true message EnterSceneReadyRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 245; - } - - int32 retcode = 1; - uint32 enter_scene_token = 2; + int32 retcode = 5; + uint32 enter_scene_token = 8; } diff --git a/proto/EnterTransPointRegionNotify.proto b/proto/EnterTransPointRegionNotify.proto index b6bb9fa9f..8441ff5be 100644 --- a/proto/EnterTransPointRegionNotify.proto +++ b/proto/EnterTransPointRegionNotify.proto @@ -1,7 +1,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 298 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EnterTransPointRegionNotify { - uint32 scene_id = 1; - uint32 point_id = 2; + uint32 scene_id = 15; + uint32 point_id = 12; } diff --git a/proto/EnterType.proto b/proto/EnterType.proto index 57a2e6823..85c960468 100755 --- a/proto/EnterType.proto +++ b/proto/EnterType.proto @@ -3,16 +3,16 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum EnterType { - ENTER_NONE = 0; - ENTER_SELF = 1; - ENTER_GOTO = 2; - ENTER_JUMP = 3; - ENTER_OTHER = 4; - ENTER_BACK = 5; - ENTER_DUNGEON = 6; - ENTER_DUNGEON_REPLAY = 7; - ENTER_GOTO_BY_PORTAL = 8; - ENTER_SELF_HOME = 9; - ENTER_OTHER_HOME = 10; - ENTER_GOTO_RECREATE = 11; + ENTER_TYPE_NONE = 0; + ENTER_TYPE_SELF = 1; + ENTER_TYPE_GOTO = 2; + ENTER_TYPE_JUMP = 3; + ENTER_TYPE_OTHER = 4; + ENTER_TYPE_BACK = 5; + ENTER_TYPE_DUNGEON = 6; + ENTER_TYPE_DUNGEON_REPLAY = 7; + ENTER_TYPE_GOTO_BY_PORTAL = 8; + ENTER_TYPE_SELF_HOME = 9; + ENTER_TYPE_OTHER_HOME = 10; + ENTER_TYPE_GOTO_RECREATE = 11; } diff --git a/proto/EnterWorldAreaReq.proto b/proto/EnterWorldAreaReq.proto index 45d5358d7..87612310f 100755 --- a/proto/EnterWorldAreaReq.proto +++ b/proto/EnterWorldAreaReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 222 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EnterWorldAreaReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 209; - } - - uint32 area_type = 1; - uint32 area_id = 2; + uint32 area_type = 12; + uint32 area_id = 10; } diff --git a/proto/EnterWorldAreaRsp.proto b/proto/EnterWorldAreaRsp.proto index ddba1f0be..269d4b728 100755 --- a/proto/EnterWorldAreaRsp.proto +++ b/proto/EnterWorldAreaRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 254 +// EnetChannelId: 0 +// EnetIsReliable: true message EnterWorldAreaRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 255; - } - - int32 retcode = 1; + int32 retcode = 15; uint32 area_type = 2; - uint32 area_id = 3; + uint32 area_id = 4; } diff --git a/proto/EntityAiSyncNotify.proto b/proto/EntityAiSyncNotify.proto index b2577d92c..9cc5e7fe7 100755 --- a/proto/EntityAiSyncNotify.proto +++ b/proto/EntityAiSyncNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "AiSyncInfo.proto"; +// CmdId: 343 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EntityAiSyncNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 352; - } - repeated AiSyncInfo info_list = 1; - repeated uint32 local_avatar_alerted_monster_list = 2; + repeated uint32 local_avatar_alerted_monster_list = 10; } diff --git a/proto/EntityAuthorityInfo.proto b/proto/EntityAuthorityInfo.proto index 69c377f9a..d39a97d70 100755 --- a/proto/EntityAuthorityInfo.proto +++ b/proto/EntityAuthorityInfo.proto @@ -3,10 +3,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "AbilitySyncStateInfo.proto"; +import "AnimatorParameterValueInfoPair.proto"; import "EntityRendererChangedInfo.proto"; +//import "HFMDKDHCJCM.proto"; import "SceneEntityAiInfo.proto"; import "Vector.proto"; -import "AnimatorParameterValueInfoPair.proto"; message EntityAuthorityInfo { AbilitySyncStateInfo ability_info = 1; @@ -14,4 +15,5 @@ message EntityAuthorityInfo { SceneEntityAiInfo ai_info = 3; Vector born_pos = 4; repeated AnimatorParameterValueInfoPair pose_para_list = 5; + //HFMDKDHCJCM NHJAJEMKIFE = 6; } diff --git a/proto/EntityClientData.proto b/proto/EntityClientData.proto index 50d8cb3e9..4bf26cc60 100755 --- a/proto/EntityClientData.proto +++ b/proto/EntityClientData.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message EntityClientData { uint32 wind_change_scene_time = 1; float windmill_sync_angle = 2; diff --git a/proto/EntityEnvironmentInfo.proto b/proto/EntityEnvironmentInfo.proto index ebc191218..2276d0674 100755 --- a/proto/EntityEnvironmentInfo.proto +++ b/proto/EntityEnvironmentInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message EntityEnvironmentInfo { uint32 json_climate_type = 1; uint32 climate_area_id = 2; diff --git a/proto/EntityFightPropChangeReasonNotify.proto b/proto/EntityFightPropChangeReasonNotify.proto index 11dd4f26d..330438da6 100755 --- a/proto/EntityFightPropChangeReasonNotify.proto +++ b/proto/EntityFightPropChangeReasonNotify.proto @@ -2,24 +2,19 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "PropChangeReason.proto"; -import "ChangeHpReason.proto"; import "ChangeEnergyReason.proto"; +import "ChangeHpReason.proto"; +import "PropChangeReason.proto"; +// CmdId: 1285 +// EnetChannelId: 0 +// EnetIsReliable: true message EntityFightPropChangeReasonNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1294; - } - - uint32 entity_id = 1; - uint32 prop_type = 2; - float prop_delta = 3; - PropChangeReason reason = 4; - repeated uint32 param_list = 5; - ChangeHpReason change_hp_reason = 6; - ChangeEnergyReason change_energy_reson = 7; + uint32 entity_id = 11; + uint32 prop_type = 6; + float prop_delta = 9; + PropChangeReason reason = 5; + repeated uint32 param_list = 10; + ChangeHpReason change_hp_reason = 12; + ChangeEnergyReason change_energy_reson = 4; } diff --git a/proto/EntityFightPropUpdateNotify.proto b/proto/EntityFightPropUpdateNotify.proto index bc1fb1ddb..660f68a8f 100755 --- a/proto/EntityFightPropUpdateNotify.proto +++ b/proto/EntityFightPropUpdateNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1237 +// EnetChannelId: 0 +// EnetIsReliable: true message EntityFightPropUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1284; - } - uint32 entity_id = 1; - map fight_prop_map = 2; + map fight_prop_map = 8; } diff --git a/proto/EntityPropNotify.proto b/proto/EntityPropNotify.proto index ae9412d04..5d0d70dc7 100755 --- a/proto/EntityPropNotify.proto +++ b/proto/EntityPropNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "PropValue.proto"; +// CmdId: 1209 +// EnetChannelId: 0 +// EnetIsReliable: true message EntityPropNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1249; - } - - uint32 entity_id = 1; - map prop_map = 2; + uint32 entity_id = 5; + map prop_map = 4; } diff --git a/proto/EntityRendererChangedInfo.proto b/proto/EntityRendererChangedInfo.proto index b516139cf..ff23a765d 100755 --- a/proto/EntityRendererChangedInfo.proto +++ b/proto/EntityRendererChangedInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message EntityRendererChangedInfo { map changed_renderers = 1; uint32 visibility_count = 2; diff --git a/proto/Equip.proto b/proto/Equip.proto index edfe05f6b..2d985e5c3 100755 --- a/proto/Equip.proto +++ b/proto/Equip.proto @@ -6,9 +6,9 @@ import "Reliquary.proto"; import "Weapon.proto"; message Equip { - oneof Detail { + bool is_locked = 3; + oneof detail { Reliquary reliquary = 1; Weapon weapon = 2; } - bool is_locked = 3; } diff --git a/proto/EquipParam.proto b/proto/EquipParam.proto index 52d24943e..51b07afb7 100644 --- a/proto/EquipParam.proto +++ b/proto/EquipParam.proto @@ -3,8 +3,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; message EquipParam { - uint32 item_id = 1; - uint32 item_num = 2; - uint32 item_level = 3; - uint32 promote_level = 4; + uint32 item_id = 1; + uint32 item_num = 2; + uint32 item_level = 3; + uint32 promote_level = 4; } diff --git a/proto/EvtAiSyncCombatThreatInfoNotify.proto b/proto/EvtAiSyncCombatThreatInfoNotify.proto index fb0c69071..108b63148 100755 --- a/proto/EvtAiSyncCombatThreatInfoNotify.proto +++ b/proto/EvtAiSyncCombatThreatInfoNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "AiThreatInfo.proto"; +// CmdId: 360 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtAiSyncCombatThreatInfoNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 373; - } - - map combat_threat_info_map = 1; + map combat_threat_info_map = 14; } diff --git a/proto/EvtAiSyncSkillCdNotify.proto b/proto/EvtAiSyncSkillCdNotify.proto index 8cc86faf1..6e6ca5b7d 100755 --- a/proto/EvtAiSyncSkillCdNotify.proto +++ b/proto/EvtAiSyncSkillCdNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "AiSkillCdInfo.proto"; +// CmdId: 333 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtAiSyncSkillCdNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 399; - } - - map ai_cd_map = 1; + map ai_cd_map = 5; } diff --git a/proto/EvtAvatarLockChairReq.proto b/proto/EvtAvatarLockChairReq.proto index cbdd42677..145bff412 100644 --- a/proto/EvtAvatarLockChairReq.proto +++ b/proto/EvtAvatarLockChairReq.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 308 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtAvatarLockChairReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 341; - } - - uint64 chair_id = 1; - Vector position = 2; + uint64 chair_id = 10; + Vector position = 3; } diff --git a/proto/EvtAvatarLockChairRsp.proto b/proto/EvtAvatarLockChairRsp.proto index bf2498c5a..b6139095e 100644 --- a/proto/EvtAvatarLockChairRsp.proto +++ b/proto/EvtAvatarLockChairRsp.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 304 +// EnetChannelId: 0 +// EnetIsReliable: true message EvtAvatarLockChairRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 305; - } - int32 retcode = 1; - uint32 entity_id = 2; - Vector position = 3; - uint64 chair_id = 4; + uint32 entity_id = 4; + Vector position = 12; + uint64 chair_id = 15; } diff --git a/proto/EvtAvatarSitDownNotify.proto b/proto/EvtAvatarSitDownNotify.proto index 69a42adf0..602364f81 100644 --- a/proto/EvtAvatarSitDownNotify.proto +++ b/proto/EvtAvatarSitDownNotify.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 359 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtAvatarSitDownNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 321; - } - - uint32 entity_id = 1; - Vector position = 2; - uint64 chair_id = 3; + uint32 entity_id = 10; + Vector position = 5; + uint64 chair_id = 8; } diff --git a/proto/EvtAvatarStandUpNotify.proto b/proto/EvtAvatarStandUpNotify.proto index ebae8f1e4..36f78310a 100644 --- a/proto/EvtAvatarStandUpNotify.proto +++ b/proto/EvtAvatarStandUpNotify.proto @@ -2,18 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 384 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtAvatarStandUpNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 331; - } - - uint32 entity_id = 1; - int32 direction = 2; - int32 perform_i_d = 3; - uint64 chair_id = 4; + uint32 entity_id = 10; + int32 direction = 3; + int32 perform_id = 8; + uint64 chair_id = 11; } diff --git a/proto/EvtBeingHitNotify.proto b/proto/EvtBeingHitNotify.proto index 0814dfefd..2281918b1 100755 --- a/proto/EvtBeingHitNotify.proto +++ b/proto/EvtBeingHitNotify.proto @@ -2,19 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ForwardType.proto"; import "EvtBeingHitInfo.proto"; +import "ForwardType.proto"; +// CmdId: 309 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtBeingHitNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 349; - } - - ForwardType forward_type = 1; - EvtBeingHitInfo being_hit_info = 2; + ForwardType forward_type = 13; + EvtBeingHitInfo being_hit_info = 7; } diff --git a/proto/EvtBeingHitsCombineNotify.proto b/proto/EvtBeingHitsCombineNotify.proto index e6356c1da..a26e9d837 100755 --- a/proto/EvtBeingHitsCombineNotify.proto +++ b/proto/EvtBeingHitsCombineNotify.proto @@ -2,19 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ForwardType.proto"; import "EvtBeingHitInfo.proto"; +import "ForwardType.proto"; +// CmdId: 336 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtBeingHitsCombineNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 375; - } - ForwardType forward_type = 1; - repeated EvtBeingHitInfo evt_being_hit_info_list = 2; + repeated EvtBeingHitInfo evt_being_hit_info_list = 14; } diff --git a/proto/EvtCreateGadgetNotify.proto b/proto/EvtCreateGadgetNotify.proto index e928fe285..0cebc616d 100755 --- a/proto/EvtCreateGadgetNotify.proto +++ b/proto/EvtCreateGadgetNotify.proto @@ -5,29 +5,28 @@ option java_package = "emu.grasscutter.net.proto"; import "ForwardType.proto"; import "Vector.proto"; +// CmdId: 332 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtCreateGadgetNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 400; - } - - ForwardType forward_type = 1; - uint32 entity_id = 2; - uint32 config_id = 3; - uint32 camp_id = 4; - uint32 camp_type = 5; - Vector init_pos = 6; - Vector init_euler_angles = 7; - uint64 guid = 8; - uint32 owner_entity_id = 9; - uint32 target_entity_id = 10; - bool is_async_load = 11; - uint32 target_lock_point_index = 12; - uint32 room_id = 13; - uint32 prop_owner_entity_id = 14; - bool sight_group_with_owner = 15; + ForwardType forward_type = 8; + uint32 entity_id = 14; + uint32 config_id = 11; + uint32 camp_id = 13; + uint32 camp_type = 3; + Vector init_pos = 15; + Vector init_euler_angles = 5; + uint64 guid = 1; + uint32 owner_entity_id = 2; + uint32 target_entity_id = 7; + bool is_async_load = 9; + uint32 target_lock_point_index = 4; + uint32 room_id = 10; + uint32 prop_owner_entity_id = 6; + bool sight_group_with_owner = 12; + bool CEGHBCJMNFJ = 1011; + bool NGANCEBKNKC = 1304; + repeated uint32 FCFECGFHLAD = 1525; + repeated uint32 GEHIKJLBKAH = 1637; } diff --git a/proto/EvtDestroyGadgetNotify.proto b/proto/EvtDestroyGadgetNotify.proto index 2fa5970c4..329ce398a 100755 --- a/proto/EvtDestroyGadgetNotify.proto +++ b/proto/EvtDestroyGadgetNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "ForwardType.proto"; +// CmdId: 317 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtDestroyGadgetNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 301; - } - - ForwardType forward_type = 1; - uint32 entity_id = 2; + ForwardType forward_type = 10; + uint32 entity_id = 8; } diff --git a/proto/EvtDoSkillSuccNotify.proto b/proto/EvtDoSkillSuccNotify.proto index 235743c66..80cfe334a 100755 --- a/proto/EvtDoSkillSuccNotify.proto +++ b/proto/EvtDoSkillSuccNotify.proto @@ -5,18 +5,13 @@ option java_package = "emu.grasscutter.net.proto"; import "ForwardType.proto"; import "Vector.proto"; +// CmdId: 337 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message EvtDoSkillSuccNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 384; - } - - ForwardType forward_type = 1; - uint32 caster_id = 2; - uint32 skill_id = 3; - Vector forward = 4; + ForwardType forward_type = 6; + uint32 caster_id = 10; + uint32 skill_id = 1; + Vector forward = 8; } diff --git a/proto/ExhibitionDisplayInfo.proto b/proto/ExhibitionDisplayInfo.proto new file mode 100644 index 000000000..58d83e76e --- /dev/null +++ b/proto/ExhibitionDisplayInfo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message ExhibitionDisplayInfo { + uint32 id = 1; + uint32 param = 2; + uint32 detail_param = 3; +} diff --git a/proto/FeatureBlockInfo.proto b/proto/FeatureBlockInfo.proto index d66896734..fd79b4cb8 100755 --- a/proto/FeatureBlockInfo.proto +++ b/proto/FeatureBlockInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message FeatureBlockInfo { uint32 feature_type = 1; uint32 end_time = 2; diff --git a/proto/FetterData.proto b/proto/FetterData.proto index 7b1b93609..bed18990f 100755 --- a/proto/FetterData.proto +++ b/proto/FetterData.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message FetterData { uint32 fetter_id = 1; uint32 fetter_state = 2; diff --git a/proto/FightPropPair.proto b/proto/FightPropPair.proto index 7c740032e..5ada4cc61 100755 --- a/proto/FightPropPair.proto +++ b/proto/FightPropPair.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message FightPropPair { uint32 prop_type = 1; float prop_value = 2; diff --git a/proto/FinishedParentQuestNotify.proto b/proto/FinishedParentQuestNotify.proto new file mode 100644 index 000000000..3d5b53530 --- /dev/null +++ b/proto/FinishedParentQuestNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ParentQuest.proto"; + +// CmdId: 437 +// EnetChannelId: 0 +// EnetIsReliable: true +message FinishedParentQuestNotify { + repeated ParentQuest parent_quest_list = 12; +} diff --git a/proto/FinishedParentQuestUpdateNotify.proto b/proto/FinishedParentQuestUpdateNotify.proto new file mode 100644 index 000000000..a4b97b35e --- /dev/null +++ b/proto/FinishedParentQuestUpdateNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ParentQuest.proto"; + +// CmdId: 432 +// EnetChannelId: 0 +// EnetIsReliable: true +message FinishedParentQuestUpdateNotify { + repeated ParentQuest parent_quest_list = 6; +} diff --git a/proto/ForgeDataNotify.proto b/proto/ForgeDataNotify.proto new file mode 100644 index 000000000..d5b06ba24 --- /dev/null +++ b/proto/ForgeDataNotify.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ForgeQueueData.proto"; + +// CmdId: 648 +// EnetChannelId: 0 +// EnetIsReliable: true +message ForgeDataNotify { + repeated uint32 forge_id_list = 13; + uint32 max_queue_num = 15; + map forge_queue_map = 1; +} diff --git a/proto/ForgeFormulaDataNotify.proto b/proto/ForgeFormulaDataNotify.proto new file mode 100644 index 000000000..940764c02 --- /dev/null +++ b/proto/ForgeFormulaDataNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 673 +// EnetChannelId: 0 +// EnetIsReliable: true +message ForgeFormulaDataNotify { + uint32 forge_id = 11; + bool is_locked = 8; +} diff --git a/proto/ForgeQueueData.proto b/proto/ForgeQueueData.proto new file mode 100644 index 000000000..c05e110ef --- /dev/null +++ b/proto/ForgeQueueData.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message ForgeQueueData { + uint32 queue_id = 1; + uint32 forge_id = 2; + uint32 finish_count = 3; + uint32 unfinish_count = 4; + uint32 next_finish_timestamp = 5; + uint32 total_finish_timestamp = 6; + uint32 avatar_id = 7; +} diff --git a/proto/ForwardType.proto b/proto/ForwardType.proto index b24643602..15e48d345 100755 --- a/proto/ForwardType.proto +++ b/proto/ForwardType.proto @@ -3,13 +3,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum ForwardType { - FORWARD_LOCAL = 0; - FORWARD_TO_ALL = 1; - FORWARD_TO_ALL_EXCEPT_CUR = 2; - FORWARD_TO_HOST = 3; - FORWARD_TO_ALL_GUEST = 4; - FORWARD_TO_PEER = 5; - FORWARD_TO_PEERS = 6; - FORWARD_ONLY_SERVER = 7; - FORWARD_TO_ALL_EXIST_EXCEPT_CUR = 8; + FORWARD_TYPE_LOCAL = 0; + FORWARD_TYPE_TO_ALL = 1; + FORWARD_TYPE_TO_ALL_EXCEPT_CUR = 2; + FORWARD_TYPE_TO_HOST = 3; + FORWARD_TYPE_TO_ALL_GUEST = 4; + FORWARD_TYPE_TO_PEER = 5; + FORWARD_TYPE_TO_PEERS = 6; + FORWARD_TYPE_ONLY_SERVER = 7; + FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR = 8; } diff --git a/proto/FoundationInfo.proto b/proto/FoundationInfo.proto index f99c2b110..acfc6be6e 100644 --- a/proto/FoundationInfo.proto +++ b/proto/FoundationInfo.proto @@ -3,16 +3,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "FoundationStatus.proto"; -import "BuildingInfo.proto"; message FoundationInfo { FoundationStatus status = 1; repeated uint32 uid_list = 2; uint32 current_building_id = 3; - uint64 begin_build_time_ms = 4; - uint32 demolition_refund = 5; - repeated BuildingInfo building_list = 6; - uint32 current_num = 7; - uint32 max_num = 8; - uint32 locked_by_uid = 9; + uint32 begin_build_time_ms = 4; } diff --git a/proto/FriendBrief.proto b/proto/FriendBrief.proto index 83b4f4fe3..1359c2432 100755 --- a/proto/FriendBrief.proto +++ b/proto/FriendBrief.proto @@ -2,10 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "FriendOnlineState.proto"; import "FriendEnterHomeOption.proto"; -import "ProfilePicture.proto"; +import "FriendOnlineState.proto"; import "PlatformType.proto"; +import "ProfilePicture.proto"; import "SocialShowAvatarInfo.proto"; message FriendBrief { diff --git a/proto/FriendEnterHomeOption.proto b/proto/FriendEnterHomeOption.proto index 3aa2bd726..ddeda8b59 100755 --- a/proto/FriendEnterHomeOption.proto +++ b/proto/FriendEnterHomeOption.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum FriendEnterHomeOption { - NEED_CONFIRM = 0; - REFUSE = 1; - DIRECT = 2; + FRIEND_ENTER_HOME_OPTION_NEED_CONFIRM = 0; + FRIEND_ENTER_HOME_OPTION_REFUSE = 1; + FRIEND_ENTER_HOME_OPTION_DIRECT = 2; } diff --git a/proto/FriendOnlineState.proto b/proto/FriendOnlineState.proto index 0c08222bd..1b7c9116c 100755 --- a/proto/FriendOnlineState.proto +++ b/proto/FriendOnlineState.proto @@ -3,6 +3,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum FriendOnlineState { - FREIEND_DISCONNECT = 0; - FRIEND_ONLINE = 1; + FRIEND_ONLINE_STATE_FREIEND_DISCONNECT = 0; + FRIEND_ONLINE_STATE_ONLINE = 1; } diff --git a/proto/Furniture.proto b/proto/Furniture.proto index ba058d8e3..dc4a2a383 100755 --- a/proto/Furniture.proto +++ b/proto/Furniture.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message Furniture { uint32 count = 1; } diff --git a/proto/GachaInfo.proto b/proto/GachaInfo.proto index ebf25b09f..92e67197d 100755 --- a/proto/GachaInfo.proto +++ b/proto/GachaInfo.proto @@ -5,25 +5,29 @@ option java_package = "emu.grasscutter.net.proto"; import "GachaUpInfo.proto"; message GachaInfo { - uint32 gachaType = 1; - uint32 scheduleId = 2; - uint32 beginTime = 3; - uint32 endTime = 4; - uint32 costItemId = 5; - uint32 costItemNum = 6; - string gachaPrefabPath = 7; - string gachaProbUrl = 8; - string gachaRecordUrl = 9; - string gachaPreviewPrefabPath = 10; - uint32 tenCostItemId = 11; - uint32 tenCostItemNum = 12; - uint32 leftGachaTimes = 13; - uint32 gachaTimesLimit = 14; - uint32 gachaSortId = 15; - string gachaProbUrlOversea = 16; - string gachaRecordUrlOversea = 17; - repeated GachaUpInfo gachaUpInfoList = 18; - string gachaTitlePath = 19; - repeated uint32 mainNameId = 20; - repeated uint32 subNameId = 21; -} \ No newline at end of file + uint32 gacha_type = 1; + uint32 schedule_id = 2; + uint32 begin_time = 3; + uint32 end_time = 4; + uint32 cost_item_id = 5; + uint32 cost_item_num = 6; + string gacha_prefab_path = 7; + string gacha_prob_url = 8; + string gacha_record_url = 9; + string gacha_preview_prefab_path = 10; + uint32 ten_cost_item_id = 11; + uint32 ten_cost_item_num = 12; + uint32 left_gacha_times = 13; + uint32 gacha_times_limit = 14; + uint32 gacha_sort_id = 15; + string gacha_prob_url_oversea = 16; + string gacha_record_url_oversea = 17; + repeated GachaUpInfo gacha_up_info_list = 18; + string title_textmap = 19; + repeated uint32 display_up_5_item_list = 20; + repeated uint32 display_up_4_item_list = 21; + uint32 wish_item_id = 22; + uint32 wish_progress = 23; + uint32 wish_max_progress = 24; + bool is_new_wish = 25; +} diff --git a/proto/GachaItem.proto b/proto/GachaItem.proto index a2d73af26..c20166cf7 100755 --- a/proto/GachaItem.proto +++ b/proto/GachaItem.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ItemParam.proto"; import "GachaTransferItem.proto"; +import "ItemParam.proto"; message GachaItem { ItemParam gacha_item_ = 1; diff --git a/proto/GachaUpInfo.proto b/proto/GachaUpInfo.proto index 37d1873a2..2000dc484 100755 --- a/proto/GachaUpInfo.proto +++ b/proto/GachaUpInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message GachaUpInfo { uint32 item_parent_type = 1; repeated uint32 item_id_list = 2; diff --git a/proto/GadgetAutoPickDropInfoNotify.proto b/proto/GadgetAutoPickDropInfoNotify.proto index f66c69860..bb0c77d85 100644 --- a/proto/GadgetAutoPickDropInfoNotify.proto +++ b/proto/GadgetAutoPickDropInfoNotify.proto @@ -4,6 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "Item.proto"; +// CmdId: 830 +// EnetChannelId: 0 +// EnetIsReliable: true message GadgetAutoPickDropInfoNotify { - repeated Item item_list = 1; + repeated Item item_list = 15; } diff --git a/proto/GadgetBornType.proto b/proto/GadgetBornType.proto index c20baa443..bd38b6f11 100755 --- a/proto/GadgetBornType.proto +++ b/proto/GadgetBornType.proto @@ -3,11 +3,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum GadgetBornType { - GADGET_BORN_NONE = 0; - GADGET_BORN_IN_AIR = 1; - GADGET_BORN_PLAYER = 2; - GADGET_BORN_MONSTER_HIT = 3; - GADGET_BORN_MONSTER_DIE = 4; - GADGET_BORN_GADGET = 5; - GADGET_BORN_GROUND = 6; + GADGET_BORN_TYPE_NONE = 0; + GADGET_BORN_TYPE_IN_AIR = 1; + GADGET_BORN_TYPE_PLAYER = 2; + GADGET_BORN_TYPE_MONSTER_HIT = 3; + GADGET_BORN_TYPE_MONSTER_DIE = 4; + GADGET_BORN_TYPE_GADGET = 5; + GADGET_BORN_TYPE_GROUND = 6; } diff --git a/proto/GadgetCrucibleInfo.proto b/proto/GadgetCrucibleInfo.proto index 3fbbcede2..8f98bfde1 100755 --- a/proto/GadgetCrucibleInfo.proto +++ b/proto/GadgetCrucibleInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message GadgetCrucibleInfo { uint32 mp_play_id = 1; uint32 prepare_end_time = 2; diff --git a/proto/GadgetInteractReq.proto b/proto/GadgetInteractReq.proto index 540f1922b..5795ab243 100755 --- a/proto/GadgetInteractReq.proto +++ b/proto/GadgetInteractReq.proto @@ -5,19 +5,15 @@ option java_package = "emu.grasscutter.net.proto"; import "InterOpType.proto"; import "ResinCostType.proto"; +// CmdId: 809 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GadgetInteractReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 849; - } - - uint32 gadget_entity_id = 1; - InterOpType op_type = 2; - uint32 gadget_id = 3; - bool is_use_condense_resin = 4; - ResinCostType resin_cost_type = 5; + uint32 gadget_entity_id = 9; + InterOpType op_type = 6; + uint32 gadget_id = 14; + bool is_use_condense_resin = 15; + ResinCostType resin_cost_type = 11; + uint32 GCIEIJIOADO = 12; } diff --git a/proto/GadgetInteractRsp.proto b/proto/GadgetInteractRsp.proto index 1c500d87f..1982c87ff 100755 --- a/proto/GadgetInteractRsp.proto +++ b/proto/GadgetInteractRsp.proto @@ -5,18 +5,13 @@ option java_package = "emu.grasscutter.net.proto"; import "InteractType.proto"; import "InterOpType.proto"; +// CmdId: 831 +// EnetChannelId: 0 +// EnetIsReliable: true message GadgetInteractRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 818; - } - - int32 retcode = 1; - uint32 gadget_entity_id = 2; - InteractType interact_type = 3; - InterOpType op_type = 4; - uint32 gadget_id = 5; + int32 retcode = 4; + uint32 gadget_entity_id = 6; + InteractType interact_type = 9; + InterOpType op_type = 1; + uint32 gadget_id = 14; } diff --git a/proto/GadgetPlayInfo.proto b/proto/GadgetPlayInfo.proto index 2ad76e24e..788f2c62b 100755 --- a/proto/GadgetPlayInfo.proto +++ b/proto/GadgetPlayInfo.proto @@ -5,13 +5,13 @@ option java_package = "emu.grasscutter.net.proto"; import "GadgetCrucibleInfo.proto"; message GadgetPlayInfo { - oneof PlayInfo { - GadgetCrucibleInfo crucible_info = 21; - } uint32 play_type = 1; uint32 duration = 2; repeated uint32 progress_stage_list = 3; uint32 start_cd = 4; uint32 start_time = 5; uint32 progress = 6; + oneof play_info { + GadgetCrucibleInfo crucible_info = 21; + } } diff --git a/proto/GadgetStateNotify.proto b/proto/GadgetStateNotify.proto index 5c37b7cde..9ea3b0526 100644 --- a/proto/GadgetStateNotify.proto +++ b/proto/GadgetStateNotify.proto @@ -2,8 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 841 +// EnetChannelId: 0 +// EnetIsReliable: true message GadgetStateNotify { - uint32 gadget_entity_id = 1; - uint32 gadget_state = 2; - bool is_enable_interact = 3; + uint32 gadget_entity_id = 2; + uint32 gadget_state = 11; + bool is_enable_interact = 10; } diff --git a/proto/GetActivityInfoRsp.proto b/proto/GetActivityInfoRsp.proto index 6da523f83..f826d910a 100755 --- a/proto/GetActivityInfoRsp.proto +++ b/proto/GetActivityInfoRsp.proto @@ -5,17 +5,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ActivityInfo.proto"; import "Uint32Pair.proto"; +// CmdId: 2144 +// EnetChannelId: 0 +// EnetIsReliable: true message GetActivityInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2011; - } - - int32 retcode = 1; - repeated ActivityInfo activity_info_list = 2; - repeated uint32 activated_sale_id_list = 3; + int32 retcode = 13; + repeated ActivityInfo activity_info_list = 14; + repeated uint32 activated_sale_id_list = 2; repeated Uint32Pair disable_transfer_point_interaction_list = 4; } diff --git a/proto/GetAllMailReq.proto b/proto/GetAllMailReq.proto index 8c6bce100..73b95157c 100644 --- a/proto/GetAllMailReq.proto +++ b/proto/GetAllMailReq.proto @@ -2,6 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1455 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetAllMailReq { - bool is_gift_mail = 1; + bool ANKKGPJCINB = 7; } diff --git a/proto/GetAllMailRsp.proto b/proto/GetAllMailRsp.proto index 968916640..2d64a6d03 100644 --- a/proto/GetAllMailRsp.proto +++ b/proto/GetAllMailRsp.proto @@ -4,9 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "MailData.proto"; +// CmdId: 1427 +// EnetChannelId: 0 +// EnetIsReliable: true message GetAllMailRsp { - int32 retcode = 1; - repeated MailData mail_list = 2; - bool is_truncated = 3; - bool isGiftMail = 4; + int32 retcode = 6; + repeated MailData mail_list = 9; + bool is_truncated = 5; + bool ANKKGPJCINB = 7; } diff --git a/proto/GetAllUnlockNameCardRsp.proto b/proto/GetAllUnlockNameCardRsp.proto index aaf13382b..388916914 100755 --- a/proto/GetAllUnlockNameCardRsp.proto +++ b/proto/GetAllUnlockNameCardRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4058 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetAllUnlockNameCardRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4076; - } - - int32 retcode = 1; + int32 retcode = 13; repeated uint32 name_card_list = 2; } diff --git a/proto/GetAuthkeyReq.proto b/proto/GetAuthkeyReq.proto index 8816c8140..1bf25903f 100755 --- a/proto/GetAuthkeyReq.proto +++ b/proto/GetAuthkeyReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1435 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetAuthkeyReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1442; - } - - string auth_appid = 1; - uint32 sign_type = 2; - uint32 authkey_ver = 3; + string auth_appid = 12; + uint32 sign_type = 15; + uint32 authkey_ver = 7; } diff --git a/proto/GetAuthkeyRsp.proto b/proto/GetAuthkeyRsp.proto index 35c1aee73..7ec1c6847 100755 --- a/proto/GetAuthkeyRsp.proto +++ b/proto/GetAuthkeyRsp.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1449 +// EnetChannelId: 0 +// EnetIsReliable: true message GetAuthkeyRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1461; - } - - int32 retcode = 1; - string authkey = 2; - string auth_appid = 3; - uint32 sign_type = 4; - uint32 authkey_ver = 5; - string game_biz = 6; + int32 retcode = 11; + string authkey = 1; + string auth_appid = 2; + uint32 sign_type = 7; + uint32 authkey_ver = 10; + string game_biz = 4; } diff --git a/proto/GetFriendShowAvatarInfoReq.proto b/proto/GetFriendShowAvatarInfoReq.proto index 33c888d42..98a047aa5 100644 --- a/proto/GetFriendShowAvatarInfoReq.proto +++ b/proto/GetFriendShowAvatarInfoReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 4003 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetFriendShowAvatarInfoReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4007; - } - - uint32 uid = 1; + uint32 uid = 9; } diff --git a/proto/GetFriendShowAvatarInfoRsp.proto b/proto/GetFriendShowAvatarInfoRsp.proto index abd7d2aae..8e060a699 100644 --- a/proto/GetFriendShowAvatarInfoRsp.proto +++ b/proto/GetFriendShowAvatarInfoRsp.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "ShowAvatarInfo.proto"; +// CmdId: 4034 +// EnetChannelId: 0 +// EnetIsReliable: true message GetFriendShowAvatarInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4008; - } - - int32 retcode = 1; - uint32 uid = 2; - repeated ShowAvatarInfo show_avatar_info_list = 3; + int32 retcode = 14; + uint32 uid = 11; + repeated ShowAvatarInfo show_avatar_info_list = 7; } diff --git a/proto/GetGachaInfoRsp.proto b/proto/GetGachaInfoRsp.proto index 0aca2e46b..ae1773659 100755 --- a/proto/GetGachaInfoRsp.proto +++ b/proto/GetGachaInfoRsp.proto @@ -4,16 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "GachaInfo.proto"; +// CmdId: 1531 +// EnetChannelId: 0 +// EnetIsReliable: true message GetGachaInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1518; - } - - int32 retcode = 1; - repeated GachaInfo gacha_info_list = 2; - uint32 gacha_random = 3; + int32 retcode = 14; + repeated GachaInfo gacha_info_list = 12; + uint32 gacha_random = 13; + uint32 NKJOBOABFOJ = 7; + bool PODALHILIKF = 9; } diff --git a/proto/GetMailItemReq.proto b/proto/GetMailItemReq.proto index 259c8ba5c..9189d3b1f 100644 --- a/proto/GetMailItemReq.proto +++ b/proto/GetMailItemReq.proto @@ -2,6 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1437 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetMailItemReq { - repeated uint32 mail_id_list = 1; + repeated uint32 mail_id_list = 8; } diff --git a/proto/GetMailItemRsp.proto b/proto/GetMailItemRsp.proto index e14bd54c8..68e900b9f 100644 --- a/proto/GetMailItemRsp.proto +++ b/proto/GetMailItemRsp.proto @@ -4,8 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "EquipParam.proto"; +// CmdId: 1432 +// EnetChannelId: 0 +// EnetIsReliable: true message GetMailItemRsp { - int32 retcode = 1; - repeated uint32 mail_id_list = 2; - repeated EquipParam item_list = 3; + int32 retcode = 13; + repeated uint32 mail_id_list = 10; + repeated EquipParam item_list = 5; } diff --git a/proto/GetOnlinePlayerListReq.proto b/proto/GetOnlinePlayerListReq.proto index dafef1a90..5a7139988 100644 --- a/proto/GetOnlinePlayerListReq.proto +++ b/proto/GetOnlinePlayerListReq.proto @@ -1,6 +1,10 @@ syntax = "proto3"; + option java_package = "emu.grasscutter.net.proto"; +// CmdId: 35 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetOnlinePlayerListReq { -uint32 targetUid = 1; } diff --git a/proto/GetOnlinePlayerListRsp.proto b/proto/GetOnlinePlayerListRsp.proto index b202195b9..c9f398853 100644 --- a/proto/GetOnlinePlayerListRsp.proto +++ b/proto/GetOnlinePlayerListRsp.proto @@ -1,10 +1,14 @@ syntax = "proto3"; + option java_package = "emu.grasscutter.net.proto"; + import "OnlinePlayerInfo.proto"; +// CmdId: 49 +// EnetChannelId: 0 +// EnetIsReliable: true message GetOnlinePlayerListRsp { - int32 retcode = 1; - repeated OnlinePlayerInfo player_info_list = 2; - uint32 param = 3; - uint32 targetUid = 4; + int32 retcode = 12; + repeated OnlinePlayerInfo player_info_list = 10; + uint32 param = 2; } diff --git a/proto/GetPlayerAskFriendListRsp.proto b/proto/GetPlayerAskFriendListRsp.proto index c3cfe9268..355949938 100755 --- a/proto/GetPlayerAskFriendListRsp.proto +++ b/proto/GetPlayerAskFriendListRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "FriendBrief.proto"; +// CmdId: 4004 +// EnetChannelId: 0 +// EnetIsReliable: true message GetPlayerAskFriendListRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4005; - } - - int32 retcode = 1; - repeated FriendBrief ask_friend_list = 2; + int32 retcode = 15; + repeated FriendBrief ask_friend_list = 13; } diff --git a/proto/GetPlayerBlacklistRsp.proto b/proto/GetPlayerBlacklistRsp.proto index 6a6966af0..b9de72c7c 100755 --- a/proto/GetPlayerBlacklistRsp.proto +++ b/proto/GetPlayerBlacklistRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "FriendBrief.proto"; +// CmdId: 4072 +// EnetChannelId: 0 +// EnetIsReliable: true message GetPlayerBlacklistRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4020; - } - - int32 retcode = 1; - repeated FriendBrief blacklist = 2; + int32 retcode = 12; + repeated FriendBrief blacklist = 5; } diff --git a/proto/GetPlayerFriendListRsp.proto b/proto/GetPlayerFriendListRsp.proto index 044f3bc2d..3ac03fc5a 100755 --- a/proto/GetPlayerFriendListRsp.proto +++ b/proto/GetPlayerFriendListRsp.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "FriendBrief.proto"; +// CmdId: 4031 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetPlayerFriendListRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4018; - } - - int32 retcode = 1; - repeated FriendBrief friend_list = 2; - repeated FriendBrief ask_friend_list = 3; + int32 retcode = 3; + repeated FriendBrief friend_list = 6; + repeated FriendBrief ask_friend_list = 5; } diff --git a/proto/GetPlayerSocialDetailReq.proto b/proto/GetPlayerSocialDetailReq.proto index c0a4bc400..6d9d8db20 100755 --- a/proto/GetPlayerSocialDetailReq.proto +++ b/proto/GetPlayerSocialDetailReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4049 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetPlayerSocialDetailReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4061; - } - - uint32 uid = 1; + uint32 uid = 14; } diff --git a/proto/GetPlayerSocialDetailRsp.proto b/proto/GetPlayerSocialDetailRsp.proto index 6ef02e88b..f68f2d4e8 100755 --- a/proto/GetPlayerSocialDetailRsp.proto +++ b/proto/GetPlayerSocialDetailRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "SocialDetail.proto"; +// CmdId: 4082 +// EnetChannelId: 0 +// EnetIsReliable: true message GetPlayerSocialDetailRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4079; - } - - int32 retcode = 1; - SocialDetail detail_data = 2; + int32 retcode = 2; + SocialDetail detail_data = 15; } diff --git a/proto/GetPlayerTokenReq.proto b/proto/GetPlayerTokenReq.proto index f43d00d0f..300058bd3 100755 --- a/proto/GetPlayerTokenReq.proto +++ b/proto/GetPlayerTokenReq.proto @@ -2,30 +2,26 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 109 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetPlayerTokenReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 149; - } - - uint32 account_type = 1; - string account_uid = 2; - string account_token = 3; - string account_ext = 4; - uint32 uid = 5; - bool is_guest = 6; + uint32 account_type = 3; + string account_uid = 12; + string account_token = 14; + string account_ext = 2; + uint32 uid = 8; + bool is_guest = 4; uint32 platform_type = 7; - uint32 cloud_client_ip = 8; + uint32 cloud_client_ip = 13; string online_id = 9; - string psn_region = 10; - uint32 channel_id = 11; - uint32 sub_channel_id = 12; - string country_code = 13; - string psn_id = 14; - string client_ip_str = 15; + string psn_region = 15; + uint32 channel_id = 10; + uint32 sub_channel_id = 1; + string country_code = 11; + string psn_id = 5; + string client_ip_str = 6; + string birthday = 966; + uint32 NNCIBOLDIAI = 1883; } diff --git a/proto/GetPlayerTokenRsp.proto b/proto/GetPlayerTokenRsp.proto index d48a6661d..39f87f2e8 100755 --- a/proto/GetPlayerTokenRsp.proto +++ b/proto/GetPlayerTokenRsp.proto @@ -2,38 +2,35 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 131 +// EnetChannelId: 0 +// EnetIsReliable: true message GetPlayerTokenRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 118; - } - - int32 retcode = 1; - string msg = 2; - uint32 uid = 3; - string token = 4; - uint32 black_uid_end_time = 5; - uint32 account_type = 6; - string account_uid = 7; - bool is_proficient_player = 8; - string secret_key = 9; - uint32 gm_uid = 10; + int32 retcode = 7; + string msg = 10; + uint32 uid = 2; + string token = 1; + uint32 black_uid_end_time = 15; + uint32 account_type = 12; + string account_uid = 4; + bool is_proficient_player = 5; + string secret_key = 13; + uint32 gm_uid = 14; uint64 secret_key_seed = 11; - bytes security_cmd_buffer = 12; - uint32 platform_type = 13; - bytes extra_bin_data = 14; - bool is_guest = 15; - uint32 channel_id = 16; - uint32 sub_channel_id = 17; - uint32 tag = 18; - string country_code = 19; - bool is_login_white_list = 20; - string psn_id = 21; - string client_version_random_key = 22; - uint32 reg_platform = 23; - string client_ip_str = 24; + bytes security_cmd_buffer = 6; + uint32 platform_type = 3; + bytes extra_bin_data = 8; + bool is_guest = 9; + uint32 channel_id = 1614; + uint32 sub_channel_id = 1911; + uint32 tag = 1855; + string country_code = 739; + bool is_login_white_list = 977; + string psn_id = 245; + string client_version_random_key = 1387; + uint32 reg_platform = 633; + string client_ip_str = 1238; + string birthday = 1109; + uint32 NNCIBOLDIAI = 1728; + bool FNECFLEAKKO = 1679; } diff --git a/proto/GetSceneAreaReq.proto b/proto/GetSceneAreaReq.proto index 9ff736755..0d5634365 100755 --- a/proto/GetSceneAreaReq.proto +++ b/proto/GetSceneAreaReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 238 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetSceneAreaReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 206; - } - - uint32 scene_id = 1; - uint32 belong_uid = 2; + uint32 scene_id = 4; + uint32 belong_uid = 3; } diff --git a/proto/GetSceneAreaRsp.proto b/proto/GetSceneAreaRsp.proto index c71a0ebb0..d72b3f633 100755 --- a/proto/GetSceneAreaRsp.proto +++ b/proto/GetSceneAreaRsp.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "CityInfo.proto"; +// CmdId: 206 +// EnetChannelId: 0 +// EnetIsReliable: true message GetSceneAreaRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 216; - } - - int32 retcode = 1; - uint32 scene_id = 2; - repeated uint32 area_id_list = 3; - repeated CityInfo city_info_list = 4; + int32 retcode = 2; + uint32 scene_id = 13; + repeated uint32 area_id_list = 6; + repeated CityInfo city_info_list = 3; } diff --git a/proto/GetScenePointReq.proto b/proto/GetScenePointReq.proto index d031cdf69..3c6bec970 100755 --- a/proto/GetScenePointReq.proto +++ b/proto/GetScenePointReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 230 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetScenePointReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 291; - } - - uint32 scene_id = 1; - uint32 belong_uid = 2; + uint32 scene_id = 4; + uint32 belong_uid = 10; } diff --git a/proto/GetScenePointRsp.proto b/proto/GetScenePointRsp.proto index 135ff2a54..3f1903cd3 100755 --- a/proto/GetScenePointRsp.proto +++ b/proto/GetScenePointRsp.proto @@ -2,25 +2,20 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 297 +// EnetChannelId: 0 +// EnetIsReliable: true message GetScenePointRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 236; - } - - int32 retcode = 1; - uint32 scene_id = 2; - repeated uint32 unlocked_point_list = 3; - uint32 belong_uid = 4; - repeated uint32 unlock_area_list = 5; - repeated uint32 locked_point_list = 6; - repeated uint32 to_be_explore_dungeon_entry_list = 7; - repeated uint32 not_explored_dungeon_entry_list = 8; - repeated uint32 group_unlimit_point_list = 9; - repeated uint32 not_interact_dungeon_entry_list = 10; - repeated uint32 hide_point_list = 11; + int32 retcode = 5; + uint32 scene_id = 12; + repeated uint32 unlocked_point_list = 14; + uint32 belong_uid = 15; + repeated uint32 unlock_area_list = 11; + repeated uint32 locked_point_list = 4; + repeated uint32 to_be_explore_dungeon_entry_list = 8; + repeated uint32 not_explored_dungeon_entry_list = 3; + repeated uint32 group_unlimit_point_list = 6; + repeated uint32 not_interact_dungeon_entry_list = 1; + repeated uint32 hide_point_list = 9; + repeated uint32 unhide_point_list = 7; } diff --git a/proto/GetShopReq.proto b/proto/GetShopReq.proto index 66d4a310f..fbc3e2a71 100755 --- a/proto/GetShopReq.proto +++ b/proto/GetShopReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 709 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message GetShopReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 749; - } - - uint32 shop_type = 1; + uint32 shop_type = 5; } diff --git a/proto/GetShopRsp.proto b/proto/GetShopRsp.proto index 994508352..3b2491f35 100755 --- a/proto/GetShopRsp.proto +++ b/proto/GetShopRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "Shop.proto"; +// CmdId: 731 +// EnetChannelId: 0 +// EnetIsReliable: true message GetShopRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 718; - } - - int32 retcode = 1; - Shop shop = 2; + int32 retcode = 11; + Shop shop = 14; } diff --git a/proto/GetShopmallDataRsp.proto b/proto/GetShopmallDataRsp.proto index e2b8e61b8..06bae1723 100755 --- a/proto/GetShopmallDataRsp.proto +++ b/proto/GetShopmallDataRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 717 +// EnetChannelId: 0 +// EnetIsReliable: true message GetShopmallDataRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 701; - } - - int32 retcode = 1; - repeated uint32 shop_type_list = 2; + int32 retcode = 4; + repeated uint32 shop_type_list = 15; } diff --git a/proto/GetWidgetSlotReq.proto b/proto/GetWidgetSlotReq.proto new file mode 100644 index 000000000..f0e3610a5 --- /dev/null +++ b/proto/GetWidgetSlotReq.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4267 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message GetWidgetSlotReq { +} diff --git a/proto/GetWidgetSlotRsp.proto b/proto/GetWidgetSlotRsp.proto new file mode 100644 index 000000000..c816bd1e1 --- /dev/null +++ b/proto/GetWidgetSlotRsp.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotData.proto"; + +// CmdId: 4300 +// EnetChannelId: 0 +// EnetIsReliable: true +message GetWidgetSlotRsp { + int32 retcode = 12; + repeated WidgetSlotData slot_list = 8; +} diff --git a/proto/GetWorldMpInfoRsp.proto b/proto/GetWorldMpInfoRsp.proto index 4e6faff53..ec4db00cd 100755 --- a/proto/GetWorldMpInfoRsp.proto +++ b/proto/GetWorldMpInfoRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 3179 +// EnetChannelId: 0 +// EnetIsReliable: true message GetWorldMpInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3394; - } - - int32 retcode = 1; - bool is_in_mp_mode = 2; - uint32 quit_mp_valid_time = 3; + int32 retcode = 11; + bool is_in_mp_mode = 5; + uint32 quit_mp_valid_time = 13; } diff --git a/proto/H5ActivityIdsNotify.proto b/proto/H5ActivityIdsNotify.proto index 1cd25d2be..c9eed0a80 100755 --- a/proto/H5ActivityIdsNotify.proto +++ b/proto/H5ActivityIdsNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 5693 +// EnetChannelId: 0 +// EnetIsReliable: true message H5ActivityIdsNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 5677; - } - - map h5_activity_map = 1; - uint32 client_red_dot_timestamp = 2; + map h_5_activity_map = 3; + uint32 client_red_dot_timestamp = 15; } diff --git a/proto/HitColliderType.proto b/proto/HitColliderType.proto index 6c04a4aa8..be99dbe33 100755 --- a/proto/HitColliderType.proto +++ b/proto/HitColliderType.proto @@ -3,8 +3,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum HitColliderType { - HIT_COLLIDER_INVALID = 0; - HIT_COLLIDER_HIT_BOX = 1; - HIT_COLLIDER_WET_HIT_BOX = 2; - HIT_COLLIDER_HEAD_BOX = 3; + HIT_COLLIDER_TYPE_INVALID = 0; + HIT_COLLIDER_TYPE_HIT_BOX = 1; + HIT_COLLIDER_TYPE_WET_HIT_BOX = 2; + HIT_COLLIDER_TYPE_HEAD_BOX = 3; } diff --git a/proto/HitTreeNotify.proto b/proto/HitTreeNotify.proto new file mode 100644 index 000000000..dc937a68f --- /dev/null +++ b/proto/HitTreeNotify.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +// Command code: 5222 + +message HitTreeNotify { + Vector hit_postion = 3; + uint32 wood_type = 4; + Vector hit_postion_duplicated = 13; //I don't understand the reason why ** makes two same positions data +} diff --git a/proto/HomeChooseModuleReq.proto b/proto/HomeChooseModuleReq.proto new file mode 100644 index 000000000..a75f8e8ba --- /dev/null +++ b/proto/HomeChooseModuleReq.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4479 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message HomeChooseModuleReq { + uint32 module_id = 2; +} diff --git a/proto/HomeChooseModuleRsp.proto b/proto/HomeChooseModuleRsp.proto new file mode 100644 index 000000000..dccf23fe8 --- /dev/null +++ b/proto/HomeChooseModuleRsp.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4745 +// EnetChannelId: 0 +// EnetIsReliable: true +message HomeChooseModuleRsp { + int32 retcode = 5; + uint32 module_id = 11; +} diff --git a/proto/HomeComfortInfoNotify.proto b/proto/HomeComfortInfoNotify.proto new file mode 100644 index 000000000..b56110116 --- /dev/null +++ b/proto/HomeComfortInfoNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "HomeModuleComfortInfo.proto"; + +// CmdId: 4649 +// EnetChannelId: 0 +// EnetIsReliable: true +message HomeComfortInfoNotify { + repeated HomeModuleComfortInfo module_info_list = 1; +} diff --git a/proto/HomeModuleComfortInfo.proto b/proto/HomeModuleComfortInfo.proto new file mode 100644 index 000000000..894c1fa5b --- /dev/null +++ b/proto/HomeModuleComfortInfo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message HomeModuleComfortInfo { + uint32 module_id = 1; + repeated uint32 world_scene_block_comfort_value_list = 2; + uint32 room_scene_comfort_value = 3; +} diff --git a/proto/HostPlayerNotify.proto b/proto/HostPlayerNotify.proto index 39127be7e..55a93a368 100755 --- a/proto/HostPlayerNotify.proto +++ b/proto/HostPlayerNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 341 +// EnetChannelId: 0 +// EnetIsReliable: true message HostPlayerNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 389; - } - - uint32 host_uid = 1; - uint32 host_peer_id = 2; + uint32 host_uid = 10; + uint32 host_peer_id = 7; } diff --git a/proto/InterOpType.proto b/proto/InterOpType.proto index 79110918a..744334e18 100755 --- a/proto/InterOpType.proto +++ b/proto/InterOpType.proto @@ -3,6 +3,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum InterOpType { - INTER_OP_FINISH = 0; - INTER_OP_START = 1; + INTER_OP_TYPE_FINISH = 0; + INTER_OP_TYPE_START = 1; } diff --git a/proto/InteractType.proto b/proto/InteractType.proto index cadaf32f1..c99f11537 100755 --- a/proto/InteractType.proto +++ b/proto/InteractType.proto @@ -3,19 +3,20 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum InteractType { - INTERACT_NONE = 0; - INTERACT_PICK_ITEM = 1; - INTERACT_GATHER = 2; - INTERACT_OPEN_CHEST = 3; - INTERACT_OPEN_STATUE = 4; - INTERACT_CONSUM = 5; - INTERACT_MP_PLAY_REWARD = 6; - INTERACT_VIEW = 7; - INTERACT_GENERAL_REWARD = 8; - INTERACT_MIRACLE_RING = 9; - INTERACT_FOUNDATION = 10; - INTERACT_ECHO_SHELL = 11; - INTERACT_HOME_GATHER = 12; - INTERACT_ENV_ANIMAL = 13; - INTERACT_QUEST_GADGET = 14; + INTERACT_TYPE_NONE = 0; + INTERACT_TYPE_PICK_ITEM = 1; + INTERACT_TYPE_GATHER = 2; + INTERACT_TYPE_OPEN_CHEST = 3; + INTERACT_TYPE_OPEN_STATUE = 4; + INTERACT_TYPE_CONSUM = 5; + INTERACT_TYPE_MP_PLAY_REWARD = 6; + INTERACT_TYPE_VIEW = 7; + INTERACT_TYPE_GENERAL_REWARD = 8; + INTERACT_TYPE_MIRACLE_RING = 9; + INTERACT_TYPE_FOUNDATION = 10; + INTERACT_TYPE_ECHO_SHELL = 11; + INTERACT_TYPE_HOME_GATHER = 12; + INTERACT_TYPE_ENV_ANIMAL = 13; + INTERACT_TYPE_QUEST_GADGET = 14; + INTERACT_TYPE_LIEIKFDFMGF = 15; } diff --git a/proto/Item.proto b/proto/Item.proto index 98f809887..d9c049fd4 100755 --- a/proto/Item.proto +++ b/proto/Item.proto @@ -2,16 +2,16 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Material.proto"; import "Equip.proto"; import "Furniture.proto"; +import "Material.proto"; message Item { - oneof Detail { + uint32 item_id = 1; + uint64 guid = 2; + oneof detail { Material material = 5; Equip equip = 6; Furniture furniture = 7; } - uint32 item_id = 1; - uint64 guid = 2; } diff --git a/proto/ItemAddHintNotify.proto b/proto/ItemAddHintNotify.proto index c9b5be100..f6a0ec539 100755 --- a/proto/ItemAddHintNotify.proto +++ b/proto/ItemAddHintNotify.proto @@ -2,24 +2,19 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "ItemHint.proto"; +import "Vector.proto"; +// CmdId: 632 +// EnetChannelId: 0 +// EnetIsReliable: true message ItemAddHintNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 700; - } - - repeated ItemHint item_list = 1; - Vector position = 2; - bool is_position_valid = 3; - uint32 reason = 4; - uint32 quest_id = 5; - bool is_transfered_from_avatar_card = 6; - repeated ItemHint overflow_transformed_item_list = 7; - bool is_general_reward_hiden = 8; + repeated ItemHint item_list = 10; + Vector position = 12; + bool is_position_valid = 13; + uint32 reason = 5; + uint32 quest_id = 14; + bool is_transfered_from_avatar_card = 11; + repeated ItemHint overflow_transformed_item_list = 3; + bool is_general_reward_hiden = 7; } diff --git a/proto/ItemExceedLimitNotify.proto b/proto/ItemExceedLimitNotify.proto deleted file mode 100755 index d294ba8b9..000000000 --- a/proto/ItemExceedLimitNotify.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -message ItemExceedLimitNotify { - bool isMaterialExceedLimit = 1; - bool isWeaponExceedLimit = 2; - bool isReliquaryExceedLimit = 3; - repeated uint32 itemIdList = 4; -} diff --git a/proto/ItemGivingReq.proto b/proto/ItemGivingReq.proto index 562e2ea46..08a82b34d 100755 --- a/proto/ItemGivingReq.proto +++ b/proto/ItemGivingReq.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 178 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ItemGivingReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 187; - } - - uint32 giving_id = 1; - repeated ItemParam item_param_list = 2; - map item_guid_count_map = 3; + uint32 giving_id = 14; + repeated ItemParam item_param_list = 10; + map item_guid_count_map = 6; } diff --git a/proto/ItemGivingRsp.proto b/proto/ItemGivingRsp.proto index ac5d6f674..91c49e6d3 100755 --- a/proto/ItemGivingRsp.proto +++ b/proto/ItemGivingRsp.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 108 +// EnetChannelId: 0 +// EnetIsReliable: true message ItemGivingRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 141; - } - - int32 retcode = 1; - uint32 giving_id = 2; + int32 retcode = 13; + uint32 giving_id = 6; + uint32 LEMILHEIALJ = 12; } diff --git a/proto/ItemHint.proto b/proto/ItemHint.proto index 5409b461e..8788b8d4b 100755 --- a/proto/ItemHint.proto +++ b/proto/ItemHint.proto @@ -2,9 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ItemHint { uint32 item_id = 1; uint32 count = 2; bool is_new = 3; + uint64 guid = 4; } diff --git a/proto/ItemParam.proto b/proto/ItemParam.proto index 10b7572c4..4c3280a2d 100755 --- a/proto/ItemParam.proto +++ b/proto/ItemParam.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ItemParam { uint32 item_id = 1; uint32 count = 2; diff --git a/proto/LifeStateChangeNotify.proto b/proto/LifeStateChangeNotify.proto index 076b27611..a95b43838 100755 --- a/proto/LifeStateChangeNotify.proto +++ b/proto/LifeStateChangeNotify.proto @@ -5,20 +5,15 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerDieType.proto"; import "ServerBuff.proto"; +// CmdId: 1231 +// EnetChannelId: 0 +// EnetIsReliable: true message LifeStateChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1218; - } - - uint32 entity_id = 1; - uint32 life_state = 2; - uint32 source_entity_id = 3; - string attack_tag = 4; - PlayerDieType die_type = 5; - uint32 move_reliable_seq = 6; - repeated ServerBuff server_buff_list = 7; + uint32 entity_id = 4; + uint32 life_state = 6; + uint32 source_entity_id = 5; + string attack_tag = 1; + PlayerDieType die_type = 13; + uint32 move_reliable_seq = 9; + repeated ServerBuff server_buff_list = 14; } diff --git a/proto/LunchBoxData.proto b/proto/LunchBoxData.proto new file mode 100644 index 000000000..3068abb34 --- /dev/null +++ b/proto/LunchBoxData.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message LunchBoxData { + map slot_material_map = 1; +} diff --git a/proto/LunchBoxSlotType.proto b/proto/LunchBoxSlotType.proto new file mode 100644 index 000000000..f2ab1f56a --- /dev/null +++ b/proto/LunchBoxSlotType.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum LunchBoxSlotType { + LUNCH_BOX_SLOT_NONE = 0; + LUNCH_BOX_SLOT_REVIVE = 1; + LUNCH_BOX_SLOT_HEAL = 2; +} diff --git a/proto/MailChangeNotify.proto b/proto/MailChangeNotify.proto index 1e362f6ff..f27221e2a 100644 --- a/proto/MailChangeNotify.proto +++ b/proto/MailChangeNotify.proto @@ -4,7 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "MailData.proto"; +// CmdId: 1431 +// EnetChannelId: 0 +// EnetIsReliable: true message MailChangeNotify { - repeated MailData mail_list = 1; - repeated uint32 del_mail_id_list = 2; + repeated MailData mail_list = 3; + repeated uint32 del_mail_id_list = 7; } diff --git a/proto/MailData.proto b/proto/MailData.proto index ba606c2e6..b6d439763 100644 --- a/proto/MailData.proto +++ b/proto/MailData.proto @@ -2,19 +2,20 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "MailTextContent.proto"; +import "CBJEDMGOBPL.proto"; import "MailItem.proto"; +import "MailTextContent.proto"; message MailData { - uint32 mail_id = 1; - MailTextContent mail_text_content = 4; - repeated MailItem item_list = 7; - uint32 send_time = 8; - uint32 expire_time = 9; - uint32 importance = 10; - bool is_read = 11; - bool is_attachment_got = 12; - uint32 config_id = 13; - repeated string argument_list = 14; - uint32 state_value = 15; + uint32 mail_id = 1; + MailTextContent mail_text_content = 4; + repeated MailItem item_list = 7; + uint32 send_time = 8; + uint32 expire_time = 9; + uint32 importance = 10; + bool is_read = 11; + bool is_attachment_got = 12; + uint32 config_id = 13; + repeated string argument_list = 14; + CBJEDMGOBPL BHCAHLJIKFF = 15; } diff --git a/proto/MailItem.proto b/proto/MailItem.proto index da657815e..3cdcdfd08 100644 --- a/proto/MailItem.proto +++ b/proto/MailItem.proto @@ -2,10 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ItemParam.proto"; +import "EquipParam.proto"; import "MaterialDeleteInfo.proto"; message MailItem { - ItemParam item_param = 1; - MaterialDeleteInfo delete_info = 2; + EquipParam equip_param = 1; + MaterialDeleteInfo delete_info = 2; } diff --git a/proto/MailTextContent.proto b/proto/MailTextContent.proto index 097710f87..cd26a735a 100644 --- a/proto/MailTextContent.proto +++ b/proto/MailTextContent.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; message MailTextContent { - string title = 1; - string content = 2; - string sender = 3; + string title = 1; + string content = 2; + string sender = 3; } diff --git a/proto/MapMarkFromType.proto b/proto/MapMarkFromType.proto index 1dcbc0a09..16cd4e9de 100755 --- a/proto/MapMarkFromType.proto +++ b/proto/MapMarkFromType.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum MapMarkFromType { - NOE = 0; - MONSTER = 1; - QUEST = 2; + MAP_MARK_FROM_TYPE_NOE = 0; + MAP_MARK_FROM_TYPE_MONSTER = 1; + MAP_MARK_FROM_TYPE_QUEST = 2; } diff --git a/proto/MapMarkPoint.proto b/proto/MapMarkPoint.proto index 2a615d49a..62b7098b5 100755 --- a/proto/MapMarkPoint.proto +++ b/proto/MapMarkPoint.proto @@ -2,9 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; -import "MapMarkPointType.proto"; import "MapMarkFromType.proto"; +import "MapMarkPointType.proto"; +import "Vector.proto"; message MapMarkPoint { uint32 scene_id = 1; diff --git a/proto/MapMarkTipsInfo.proto b/proto/MapMarkTipsInfo.proto index 90264c1a4..cac634900 100644 --- a/proto/MapMarkTipsInfo.proto +++ b/proto/MapMarkTipsInfo.proto @@ -1,10 +1,10 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -import "MapMarkTipsType.proto"; - -message MapMarkTipsInfo { - MapMarkTipsType tips_type = 1; - repeated uint32 point_id_list = 2; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "MapMarkTipsType.proto"; + +message MapMarkTipsInfo { + MapMarkTipsType tips_type = 1; + repeated uint32 point_id_list = 2; +} diff --git a/proto/MapMarkTipsType.proto b/proto/MapMarkTipsType.proto index 229a70e73..344596679 100644 --- a/proto/MapMarkTipsType.proto +++ b/proto/MapMarkTipsType.proto @@ -1,7 +1,7 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -enum MapMarkTipsType { - MARK_TIPS_DUNGEON_ELEMENT_TRIAL = 0; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum MapMarkTipsType { + MAP_MARK_TIPS_TYPE_DUNGEON_ELEMENT_TRIAL = 0; +} diff --git a/proto/MarkEntityInMinMapNotify.proto b/proto/MarkEntityInMinMapNotify.proto index c026332d4..ef02c2455 100644 --- a/proto/MarkEntityInMinMapNotify.proto +++ b/proto/MarkEntityInMinMapNotify.proto @@ -1,19 +1,14 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -import "Vector.proto"; - -message MarkEntityInMinMapNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 249; - } - - uint32 entity_id = 1; - Vector position = 2; - uint32 monster_id = 3; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +// CmdId: 202 +// EnetChannelId: 0 +// EnetIsReliable: true +message MarkEntityInMinMapNotify { + uint32 entity_id = 5; + Vector position = 13; + uint32 monster_id = 6; +} diff --git a/proto/MarkMapReq.proto b/proto/MarkMapReq.proto index 41e9fe2bd..55acb13aa 100755 --- a/proto/MarkMapReq.proto +++ b/proto/MarkMapReq.proto @@ -4,24 +4,19 @@ option java_package = "emu.grasscutter.net.proto"; import "MapMarkPoint.proto"; +// CmdId: 3208 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message MarkMapReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 3216; - } + Operation op = 15; + MapMarkPoint old = 10; + MapMarkPoint mark = 4; enum Operation { - ADD = 0; - MOD = 1; - DEL = 2; - GET = 3; + OPERATION_ADD = 0; + OPERATION_MOD = 1; + OPERATION_DEL = 2; + OPERATION_GET = 3; } - - Operation op = 1; - MapMarkPoint old = 2; - MapMarkPoint mark = 3; } diff --git a/proto/MarkMapRsp.proto b/proto/MarkMapRsp.proto index d2cb401ac..0f92c8236 100644 --- a/proto/MarkMapRsp.proto +++ b/proto/MarkMapRsp.proto @@ -1,18 +1,13 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -import "MapMarkPoint.proto"; - -message MarkMapRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3011; - } - - int32 retcode = 1; - repeated MapMarkPoint mark_list = 2; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "MapMarkPoint.proto"; + +// CmdId: 3421 +// EnetChannelId: 0 +// EnetIsReliable: true +message MarkMapRsp { + int32 retcode = 11; + repeated MapMarkPoint mark_list = 7; +} diff --git a/proto/MarkNewNotify.proto b/proto/MarkNewNotify.proto index 14f8c6466..3104ff91c 100644 --- a/proto/MarkNewNotify.proto +++ b/proto/MarkNewNotify.proto @@ -1,17 +1,11 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - - -message MarkNewNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1212; - } - - uint32 mark_new_type = 1; - repeated uint32 id_list = 2; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 1227 +// EnetChannelId: 0 +// EnetIsReliable: true +message MarkNewNotify { + uint32 mark_new_type = 10; + repeated uint32 id_list = 13; +} diff --git a/proto/MassivePropParam.proto b/proto/MassivePropParam.proto index 80ca7ee77..97725bb26 100755 --- a/proto/MassivePropParam.proto +++ b/proto/MassivePropParam.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message MassivePropParam { int32 type = 1; repeated uint32 reaction_info_list = 2; diff --git a/proto/MaterialDeleteInfo.proto b/proto/MaterialDeleteInfo.proto index 1c8877ca1..e511c1db1 100755 --- a/proto/MaterialDeleteInfo.proto +++ b/proto/MaterialDeleteInfo.proto @@ -2,25 +2,26 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message MaterialDeleteInfo { + bool has_delete_config = 1; + oneof delete_info { + CountDownDelete count_down_delete = 2; + DateTimeDelete date_delete = 3; + DelayWeekCountDownDelete delay_week_count_down_delete = 4; + } + message CountDownDelete { map delete_time_num_map = 1; uint32 config_count_down_time = 2; } + message DateTimeDelete { uint32 delete_time = 1; } + message DelayWeekCountDownDelete { map delete_time_num_map = 1; uint32 config_delay_week = 2; uint32 config_count_down_time = 3; } - - oneof DeleteInfo { - CountDownDelete count_down_delete = 2; - DateTimeDelete date_delete = 3; - DelayWeekCountDownDelete delay_week_count_down_delete = 4; - } - bool has_delete_config = 1; } diff --git a/proto/MathQuaternion.proto b/proto/MathQuaternion.proto index 131e9a1aa..a3689667a 100755 --- a/proto/MathQuaternion.proto +++ b/proto/MathQuaternion.proto @@ -2,10 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message MathQuaternion { - float X = 1; - float Y = 2; - float Z = 3; - float W = 4; + float x = 1; + float y = 2; + float z = 3; + float w = 4; } diff --git a/proto/McoinExchangeHcoinReq.proto b/proto/McoinExchangeHcoinReq.proto index 5b6f37ee9..4ce94ddfe 100644 --- a/proto/McoinExchangeHcoinReq.proto +++ b/proto/McoinExchangeHcoinReq.proto @@ -2,7 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 687 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message McoinExchangeHcoinReq { - uint32 mCoinNum = 1; - uint32 hCoinNum = 2; + uint32 mcoin_cost = 8; + uint32 hcoin = 12; } diff --git a/proto/McoinExchangeHcoinRsp.proto b/proto/McoinExchangeHcoinRsp.proto index 090341308..fe5e1bb1d 100644 --- a/proto/McoinExchangeHcoinRsp.proto +++ b/proto/McoinExchangeHcoinRsp.proto @@ -2,6 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 689 +// EnetChannelId: 0 +// EnetIsReliable: true message McoinExchangeHcoinRsp { - int32 retcode = 1; + int32 retcode = 9; + uint32 mcoin_cost = 10; + uint32 hcoin = 15; } diff --git a/proto/ModifierAction.proto b/proto/ModifierAction.proto new file mode 100644 index 000000000..a7a1c37a7 --- /dev/null +++ b/proto/ModifierAction.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum ModifierAction { + ADDED = 0; + REMOVED = 1; +} diff --git a/proto/ModifierDurability.proto b/proto/ModifierDurability.proto index f59ccd026..b6da88bf1 100755 --- a/proto/ModifierDurability.proto +++ b/proto/ModifierDurability.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ModifierDurability { float reduce_ratio = 1; float remaining_durability = 2; diff --git a/proto/ModifierProperty.proto b/proto/ModifierProperty.proto new file mode 100644 index 000000000..cc0aa742c --- /dev/null +++ b/proto/ModifierProperty.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "AbilityString.proto"; + +message ModifierProperty { + AbilityString key = 1; + float value = 2; +} diff --git a/proto/MonsterBornType.proto b/proto/MonsterBornType.proto index d44d80f5d..a79a9ba3c 100755 --- a/proto/MonsterBornType.proto +++ b/proto/MonsterBornType.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum MonsterBornType { - MONSTER_BORN_NONE = 0; - MONSTER_BORN_DEFAULT = 1; - MONSTER_BORN_RANDOM = 2; + MONSTER_BORN_TYPE_NONE = 0; + MONSTER_BORN_TYPE_DEFAULT = 1; + MONSTER_BORN_TYPE_RANDOM = 2; } diff --git a/proto/MotionInfo.proto b/proto/MotionInfo.proto index 3ce74eb94..7680ea8a6 100755 --- a/proto/MotionInfo.proto +++ b/proto/MotionInfo.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "MotionState.proto"; +import "Vector.proto"; message MotionInfo { Vector pos = 1; @@ -14,5 +14,5 @@ message MotionInfo { Vector ref_pos = 6; uint32 ref_id = 7; uint32 scene_time = 8; - uint32 interval_velocity = 9; + uint64 interval_velocity = 9; } diff --git a/proto/MotionState.proto b/proto/MotionState.proto index 6897fc380..c5f1eba52 100755 --- a/proto/MotionState.proto +++ b/proto/MotionState.proto @@ -3,59 +3,61 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum MotionState { - MOTION_NONE = 0; - MOTION_RESET = 1; - MOTION_STANDBY = 2; - MOTION_STANDBY_MOVE = 3; - MOTION_WALK = 4; - MOTION_RUN = 5; - MOTION_DASH = 6; - MOTION_CLIMB = 7; - MOTION_CLIMB_JUMP = 8; - MOTION_STANDBY_TO_CLIMB = 9; - MOTION_FIGHT = 10; - MOTION_JUMP = 11; - MOTION_DROP = 12; - MOTION_FLY = 13; - MOTION_SWIM_MOVE = 14; - MOTION_SWIM_IDLE = 15; - MOTION_SWIM_DASH = 16; - MOTION_SWIM_JUMP = 17; - MOTION_SLIP = 18; - MOTION_GO_UPSTAIRS = 19; - MOTION_FALL_ON_GROUND = 20; - MOTION_JUMP_UP_WALL_FOR_STANDBY = 21; - MOTION_JUMP_OFF_WALL = 22; - MOTION_POWERED_FLY = 23; - MOTION_LADDER_IDLE = 24; - MOTION_LADDER_MOVE = 25; - MOTION_LADDER_SLIP = 26; - MOTION_STANDBY_TO_LADDER = 27; - MOTION_LADDER_TO_STANDBY = 28; - MOTION_DANGER_STANDBY = 29; - MOTION_DANGER_STANDBY_MOVE = 30; - MOTION_DANGER_WALK = 31; - MOTION_DANGER_RUN = 32; - MOTION_DANGER_DASH = 33; - MOTION_CROUCH_IDLE = 34; - MOTION_CROUCH_MOVE = 35; - MOTION_CROUCH_ROLL = 36; - MOTION_NOTIFY = 37; - MOTION_LAND_SPEED = 38; - MOTION_MOVE_FAIL_ACK = 39; - MOTION_WATERFALL = 40; - MOTION_DASH_BEFORE_SHAKE = 41; - MOTION_SIT_IDLE = 42; - MOTION_FORCE_SET_POS = 43; - MOTION_QUEST_FORCE_DRAG = 44; - MOTION_FOLLOW_ROUTE = 45; - MOTION_SKIFF_BOARDING = 46; - MOTION_SKIFF_NORMAL = 47; - MOTION_SKIFF_DASH = 48; - MOTION_SKIFF_POWERED_DASH = 49; - MOTION_DESTROY_VEHICLE = 50; - MOTION_FLY_IDLE = 51; - MOTION_FLY_SLOW = 52; - MOTION_FLY_FAST = 53; - MOTION_NUM = 54; + MOTION_STATE_NONE = 0; + MOTION_STATE_RESET = 1; + MOTION_STATE_STANDBY = 2; + MOTION_STATE_STANDBY_MOVE = 3; + MOTION_STATE_WALK = 4; + MOTION_STATE_RUN = 5; + MOTION_STATE_DASH = 6; + MOTION_STATE_CLIMB = 7; + MOTION_STATE_CLIMB_JUMP = 8; + MOTION_STATE_STANDBY_TO_CLIMB = 9; + MOTION_STATE_FIGHT = 10; + MOTION_STATE_JUMP = 11; + MOTION_STATE_DROP = 12; + MOTION_STATE_FLY = 13; + MOTION_STATE_SWIM_MOVE = 14; + MOTION_STATE_SWIM_IDLE = 15; + MOTION_STATE_SWIM_DASH = 16; + MOTION_STATE_SWIM_JUMP = 17; + MOTION_STATE_SLIP = 18; + MOTION_STATE_GO_UPSTAIRS = 19; + MOTION_STATE_FALL_ON_GROUND = 20; + MOTION_STATE_JUMP_UP_WALL_FOR_STANDBY = 21; + MOTION_STATE_JUMP_OFF_WALL = 22; + MOTION_STATE_POWERED_FLY = 23; + MOTION_STATE_LADDER_IDLE = 24; + MOTION_STATE_LADDER_MOVE = 25; + MOTION_STATE_LADDER_SLIP = 26; + MOTION_STATE_STANDBY_TO_LADDER = 27; + MOTION_STATE_LADDER_TO_STANDBY = 28; + MOTION_STATE_DANGER_STANDBY = 29; + MOTION_STATE_DANGER_STANDBY_MOVE = 30; + MOTION_STATE_DANGER_WALK = 31; + MOTION_STATE_DANGER_RUN = 32; + MOTION_STATE_DANGER_DASH = 33; + MOTION_STATE_CROUCH_IDLE = 34; + MOTION_STATE_CROUCH_MOVE = 35; + MOTION_STATE_CROUCH_ROLL = 36; + MOTION_STATE_NOTIFY = 37; + MOTION_STATE_LAND_SPEED = 38; + MOTION_STATE_MOVE_FAIL_ACK = 39; + MOTION_STATE_WATERFALL = 40; + MOTION_STATE_DASH_BEFORE_SHAKE = 41; + MOTION_STATE_SIT_IDLE = 42; + MOTION_STATE_FORCE_SET_POS = 43; + MOTION_STATE_QUEST_FORCE_DRAG = 44; + MOTION_STATE_FOLLOW_ROUTE = 45; + MOTION_STATE_SKIFF_BOARDING = 46; + MOTION_STATE_SKIFF_NORMAL = 47; + MOTION_STATE_SKIFF_DASH = 48; + MOTION_STATE_SKIFF_POWERED_DASH = 49; + MOTION_STATE_DESTROY_VEHICLE = 50; + MOTION_STATE_FLY_IDLE = 51; + MOTION_STATE_FLY_SLOW = 52; + MOTION_STATE_FLY_FAST = 53; + MOTION_STATE_NUM = 54; + MOTION_STATE_OOFNNHKLEFE = 55; + MOTION_STATE_KMIGLMEGNOK = 56; } diff --git a/proto/MovingPlatformType.proto b/proto/MovingPlatformType.proto index 9821a8373..1baaa02ae 100755 --- a/proto/MovingPlatformType.proto +++ b/proto/MovingPlatformType.proto @@ -3,8 +3,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum MovingPlatformType { - MOVING_PLATFORM_NONE = 0; - MOVING_PLATFORM_USE_CONFIG = 1; - MOVING_PLATFORM_ABILITY = 2; - MOVING_PLATFORM_ROUTE = 3; + MOVING_PLATFORM_TYPE_NONE = 0; + MOVING_PLATFORM_TYPE_USE_CONFIG = 1; + MOVING_PLATFORM_TYPE_ABILITY = 2; + MOVING_PLATFORM_TYPE_ROUTE = 3; } diff --git a/proto/MpSettingType.proto b/proto/MpSettingType.proto index 886f1e43e..3766677b3 100755 --- a/proto/MpSettingType.proto +++ b/proto/MpSettingType.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum MpSettingType { - MP_SETTING_NO_ENTER = 0; - MP_SETTING_ENTER_FREELY = 1; - MP_SETTING_ENTER_AFTER_APPLY = 2; + MP_SETTING_TYPE_NO_ENTER = 0; + MP_SETTING_TYPE_ENTER_FREELY = 1; + MP_SETTING_TYPE_ENTER_AFTER_APPLY = 2; } diff --git a/proto/NpcTalkReq.proto b/proto/NpcTalkReq.proto index e6a90f068..917db99c6 100755 --- a/proto/NpcTalkReq.proto +++ b/proto/NpcTalkReq.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 509 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message NpcTalkReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 549; - } - - uint32 npc_entity_id = 1; - uint32 talk_id = 3; - uint32 entity_id = 4; + uint32 npc_entity_id = 5; + uint32 talk_id = 7; + uint32 entity_id = 6; } diff --git a/proto/NpcTalkRsp.proto b/proto/NpcTalkRsp.proto index 5e398ad1f..745d5dcce 100755 --- a/proto/NpcTalkRsp.proto +++ b/proto/NpcTalkRsp.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 531 +// EnetChannelId: 0 +// EnetIsReliable: true message NpcTalkRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 518; - } - - int32 retcode = 1; - uint32 npc_entity_id = 2; - uint32 cur_talk_id = 4; - uint32 entity_id = 5; + int32 retcode = 12; + uint32 npc_entity_id = 9; + uint32 cur_talk_id = 6; + uint32 entity_id = 7; } diff --git a/proto/OneoffGatherPointDetectorData.proto b/proto/OneoffGatherPointDetectorData.proto new file mode 100644 index 000000000..deec47762 --- /dev/null +++ b/proto/OneoffGatherPointDetectorData.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +message OneoffGatherPointDetectorData { + uint32 material_id = 1; + bool is_all_collected = 2; + bool is_hint_valid = 3; + Vector hint_center_pos = 4; + uint32 hint_radius = 5; + uint32 group_id = 6; + uint32 config_id = 7; +} diff --git a/proto/OneoffGatherPointDetectorDataNotify.proto b/proto/OneoffGatherPointDetectorDataNotify.proto new file mode 100644 index 000000000..ac8ba3df8 --- /dev/null +++ b/proto/OneoffGatherPointDetectorDataNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "OneoffGatherPointDetectorData.proto"; + +// CmdId: 4262 +// EnetChannelId: 0 +// EnetIsReliable: true +message OneoffGatherPointDetectorDataNotify { + repeated OneoffGatherPointDetectorData oneoff_gather_point_detector_data_list = 6; +} diff --git a/proto/OpenStateUpdateNotify.proto b/proto/OpenStateUpdateNotify.proto index 8d70a9d0a..b902aefe1 100755 --- a/proto/OpenStateUpdateNotify.proto +++ b/proto/OpenStateUpdateNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 119 +// EnetChannelId: 0 +// EnetIsReliable: true message OpenStateUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 196; - } - - map open_state_map = 1; + map open_state_map = 12; } diff --git a/proto/ParentQuest.proto b/proto/ParentQuest.proto new file mode 100644 index 000000000..e73e1f2f3 --- /dev/null +++ b/proto/ParentQuest.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "ChildQuest.proto"; +import "ParentQuestRandomInfo.proto"; + +message ParentQuest { + uint32 parent_quest_id = 1; + repeated ChildQuest child_quest_list = 2; + bool is_finished = 3; + bool is_random = 4; + ParentQuestRandomInfo random_info = 5; + repeated int32 quest_var = 6; + uint32 parent_quest_state = 7; + uint32 quest_var_seq = 8; + map time_var_map = 9; + uint64 GJJJKEIPAPC = 10; +} diff --git a/proto/ParentQuestRandomInfo.proto b/proto/ParentQuestRandomInfo.proto new file mode 100644 index 000000000..61f04a74f --- /dev/null +++ b/proto/ParentQuestRandomInfo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message ParentQuestRandomInfo { + uint32 entrance_id = 1; + uint32 template_id = 2; + repeated uint32 factor_list = 3; +} diff --git a/proto/PersonalSceneJumpReq.proto b/proto/PersonalSceneJumpReq.proto index cc269f258..808ccee41 100644 --- a/proto/PersonalSceneJumpReq.proto +++ b/proto/PersonalSceneJumpReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 266 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PersonalSceneJumpReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 260; - } - - uint32 point_id = 1; + uint32 point_id = 2; } diff --git a/proto/PersonalSceneJumpRsp.proto b/proto/PersonalSceneJumpRsp.proto index a91f6b5ca..d1b47473a 100644 --- a/proto/PersonalSceneJumpRsp.proto +++ b/proto/PersonalSceneJumpRsp.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "Vector.proto"; +// CmdId: 248 +// EnetChannelId: 0 +// EnetIsReliable: true message PersonalSceneJumpRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 228; - } - - int32 retcode = 1; + int32 retcode = 15; uint32 dest_scene_id = 2; - Vector dest_pos = 3; + Vector dest_pos = 6; } diff --git a/proto/PingReq.proto b/proto/PingReq.proto index e5bc38cc7..786048547 100755 --- a/proto/PingReq.proto +++ b/proto/PingReq.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 32 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PingReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 100; - } - - uint32 seq = 1; - uint32 client_time = 2; - bytes sc_data = 3; - float ue_time = 4; - double total_tick_time = 5; + uint32 seq = 2; + uint32 client_time = 14; + bytes sc_data = 11; + float ue_time = 15; + double total_tick_time = 12; } diff --git a/proto/PingRsp.proto b/proto/PingRsp.proto index b898469e1..bd8cee3a2 100755 --- a/proto/PingRsp.proto +++ b/proto/PingRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 17 +// EnetChannelId: 0 +// EnetIsReliable: true message PingRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - CMD_ID = 1; - ENET_IS_RELIABLE = 1; - } - - int32 retcode = 1; - uint32 seq = 2; - uint32 client_time = 3; + int32 retcode = 9; + uint32 seq = 4; + uint32 client_time = 8; } diff --git a/proto/PlatformInfo.proto b/proto/PlatformInfo.proto index 659afc373..8c3046bdc 100755 --- a/proto/PlatformInfo.proto +++ b/proto/PlatformInfo.proto @@ -2,10 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "MathQuaternion.proto"; import "MovingPlatformType.proto"; import "Route.proto"; +import "Vector.proto"; message PlatformInfo { uint32 route_id = 1; diff --git a/proto/PlatformType.proto b/proto/PlatformType.proto index 8f4904622..134bb6806 100644 --- a/proto/PlatformType.proto +++ b/proto/PlatformType.proto @@ -3,15 +3,17 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum PlatformType { - EDITOR = 0; - IOS = 1; - ANDROID = 2; - PC = 3; - PS4 = 4; - SERVER = 5; - CLOUD_ANDROID = 6; - CLOUD_IOS = 7; - PS5 = 8; - CLOUD_WEB = 9; - CLOUD_TV = 10; + PLATFORM_TYPE_EDITOR = 0; + PLATFORM_TYPE_IOS = 1; + PLATFORM_TYPE_ANDROID = 2; + PLATFORM_TYPE_PC = 3; + PLATFORM_TYPE_PS_4 = 4; + PLATFORM_TYPE_SERVER = 5; + PLATFORM_TYPE_CLOUD_ANDROID = 6; + PLATFORM_TYPE_CLOUD_IOS = 7; + PLATFORM_TYPE_PS_5 = 8; + PLATFORM_TYPE_CLOUD_WEB = 9; + PLATFORM_TYPE_CLOUD_TV = 10; + PLATFORM_TYPE_IBBEKBJLMAJ = 11; + PLATFORM_TYPE_BCEICMDNIIG = 12; } diff --git a/proto/PlayerApplyEnterMpNotify.proto b/proto/PlayerApplyEnterMpNotify.proto index b742a4227..d38addc2d 100755 --- a/proto/PlayerApplyEnterMpNotify.proto +++ b/proto/PlayerApplyEnterMpNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "OnlinePlayerInfo.proto"; +// CmdId: 1818 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerApplyEnterMpNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1803; - } - - OnlinePlayerInfo src_player_info = 1; - uint32 src_app_id = 2; - uint32 src_thread_index = 3; + OnlinePlayerInfo src_player_info = 11; + uint32 src_app_id = 6; + uint32 src_thread_index = 13; } diff --git a/proto/PlayerApplyEnterMpReq.proto b/proto/PlayerApplyEnterMpReq.proto index 8d4c5f18b..7670dfef1 100755 --- a/proto/PlayerApplyEnterMpReq.proto +++ b/proto/PlayerApplyEnterMpReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1809 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerApplyEnterMpReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1843; - } - - uint32 target_uid = 1; + uint32 target_uid = 3; } diff --git a/proto/PlayerApplyEnterMpResultNotify.proto b/proto/PlayerApplyEnterMpResultNotify.proto index 7c8921ad1..2915ada81 100755 --- a/proto/PlayerApplyEnterMpResultNotify.proto +++ b/proto/PlayerApplyEnterMpResultNotify.proto @@ -2,35 +2,29 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1804 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerApplyEnterMpResultNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1805; - } + uint32 target_uid = 7; + bool is_agreed = 4; + Reason reason = 14; + string target_nickname = 5; enum Reason { - PLAYER_JUDGE = 0; - SCENE_CANNOT_ENTER = 1; - PLAYER_CANNOT_ENTER_MP = 2; - SYSTEM_JUDGE = 3; - ALLOW_ENTER_PLAYER_FULL = 4; - WORLD_LEVEL_LOWER_THAN_HOST = 5; - HOST_IN_MATCH = 6; - PLAYER_IN_BLACKLIST = 7; - PS_PLAYER_NOT_ACCEPT_OTHERS = 8; - HOST_IS_BLOCKED = 9; - OTHER_DATA_VERSION_NOT_LATEST = 10; - DATA_VERSION_NOT_LATEST = 11; - PLAYER_NOT_IN_PLAYER_WORLD = 12; - MAX_PLAYER = 13; + REASON_PLAYER_JUDGE = 0; + REASON_SCENE_CANNOT_ENTER = 1; + REASON_PLAYER_CANNOT_ENTER_MP = 2; + REASON_SYSTEM_JUDGE = 3; + REASON_ALLOW_ENTER_PLAYER_FULL = 4; + REASON_WORLD_LEVEL_LOWER_THAN_HOST = 5; + REASON_HOST_IN_MATCH = 6; + REASON_PLAYER_IN_BLACKLIST = 7; + REASON_PS_PLAYER_NOT_ACCEPT_OTHERS = 8; + REASON_HOST_IS_BLOCKED = 9; + REASON_OTHER_DATA_VERSION_NOT_LATEST = 10; + REASON_DATA_VERSION_NOT_LATEST = 11; + REASON_PLAYER_NOT_IN_PLAYER_WORLD = 12; + REASON_MAX_PLAYER = 13; } - - uint32 target_uid = 1; - bool is_agreed = 2; - Reason reason = 3; - string target_nickname = 4; } diff --git a/proto/PlayerApplyEnterMpResultReq.proto b/proto/PlayerApplyEnterMpResultReq.proto index c084c00f8..9b9170bff 100755 --- a/proto/PlayerApplyEnterMpResultReq.proto +++ b/proto/PlayerApplyEnterMpResultReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1828 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerApplyEnterMpResultReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1824; - } - - uint32 apply_uid = 1; - bool is_agreed = 2; + uint32 apply_uid = 15; + bool is_agreed = 9; } diff --git a/proto/PlayerApplyEnterMpResultRsp.proto b/proto/PlayerApplyEnterMpResultRsp.proto index d7d42eb6a..e23612664 100755 --- a/proto/PlayerApplyEnterMpResultRsp.proto +++ b/proto/PlayerApplyEnterMpResultRsp.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1803 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerApplyEnterMpResultRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1832; - } - - int32 retcode = 1; - uint32 apply_uid = 2; - bool is_agreed = 3; - uint32 param = 4; + int32 retcode = 6; + uint32 apply_uid = 4; + bool is_agreed = 12; + uint32 param = 9; } diff --git a/proto/PlayerApplyEnterMpRsp.proto b/proto/PlayerApplyEnterMpRsp.proto index 05e7e3499..93559b377 100755 --- a/proto/PlayerApplyEnterMpRsp.proto +++ b/proto/PlayerApplyEnterMpRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1843 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerApplyEnterMpRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1827; - } - - int32 retcode = 1; - uint32 target_uid = 2; - uint32 param = 3; + int32 retcode = 5; + uint32 target_uid = 4; + uint32 param = 9; } diff --git a/proto/PlayerChatNotify.proto b/proto/PlayerChatNotify.proto index 738602a06..4ab075b4c 100755 --- a/proto/PlayerChatNotify.proto +++ b/proto/PlayerChatNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "ChatInfo.proto"; +// CmdId: 3295 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerChatNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3122; - } - - uint32 channel_id = 1; - ChatInfo chat_info = 2; + uint32 channel_id = 14; + ChatInfo chat_info = 12; } diff --git a/proto/PlayerChatReq.proto b/proto/PlayerChatReq.proto index 4568a6b23..855851255 100755 --- a/proto/PlayerChatReq.proto +++ b/proto/PlayerChatReq.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "ChatInfo.proto"; +// CmdId: 3378 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerChatReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 3326; - } - - uint32 channel_id = 1; - ChatInfo chat_info = 2; + uint32 channel_id = 9; + ChatInfo chat_info = 1; } diff --git a/proto/PlayerChatRsp.proto b/proto/PlayerChatRsp.proto index 1b9e8e04d..2495c1d4e 100755 --- a/proto/PlayerChatRsp.proto +++ b/proto/PlayerChatRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 3321 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerChatRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3485; - } - - int32 retcode = 1; - uint32 chat_forbidden_endtime = 2; + int32 retcode = 4; + uint32 chat_forbidden_endtime = 15; } diff --git a/proto/PlayerDataNotify.proto b/proto/PlayerDataNotify.proto index 117e4fdca..ddf86e630 100755 --- a/proto/PlayerDataNotify.proto +++ b/proto/PlayerDataNotify.proto @@ -4,18 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "PropValue.proto"; +// CmdId: 135 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerDataNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 142; - } - - string nick_name = 1; + string nick_name = 15; uint64 server_time = 2; - bool is_first_login_today = 3; - uint32 region_id = 4; - map prop_map = 6; + bool is_first_login_today = 11; + uint32 region_id = 9; + map prop_map = 8; } diff --git a/proto/PlayerDieType.proto b/proto/PlayerDieType.proto index bd9edaf69..05bff89e8 100755 --- a/proto/PlayerDieType.proto +++ b/proto/PlayerDieType.proto @@ -3,13 +3,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum PlayerDieType { - PLAYER_DIE_NONE = 0; - PLAYER_DIE_KILL_BY_MONSTER = 1; - PLAYER_DIE_KILL_BY_GEAR = 2; - PLAYER_DIE_FALL = 3; - PLAYER_DIE_DRAWN = 4; - PLAYER_DIE_ABYSS = 5; - PLAYER_DIE_GM = 6; - PLAYER_DIE_CLIMATE_COLD = 7; - PLAYER_DIE_STORM_LIGHTING = 8; + PLAYER_DIE_TYPE_NONE = 0; + PLAYER_DIE_TYPE_KILL_BY_MONSTER = 1; + PLAYER_DIE_TYPE_KILL_BY_GEAR = 2; + PLAYER_DIE_TYPE_FALL = 3; + PLAYER_DIE_TYPE_DRAWN = 4; + PLAYER_DIE_TYPE_ABYSS = 5; + PLAYER_DIE_TYPE_GM = 6; + PLAYER_DIE_TYPE_CLIMATE_COLD = 7; + PLAYER_DIE_TYPE_STORM_LIGHTING = 8; } diff --git a/proto/PlayerEnterDungeonReq.proto b/proto/PlayerEnterDungeonReq.proto index aef860d18..e18790d47 100644 --- a/proto/PlayerEnterDungeonReq.proto +++ b/proto/PlayerEnterDungeonReq.proto @@ -2,7 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 941 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerEnterDungeonReq { - uint32 point_id = 1; - uint32 dungeon_id = 2; + uint32 point_id = 5; + uint32 dungeon_id = 12; } diff --git a/proto/PlayerEnterDungeonRsp.proto b/proto/PlayerEnterDungeonRsp.proto index ba9325eb0..ce73f6b57 100644 --- a/proto/PlayerEnterDungeonRsp.proto +++ b/proto/PlayerEnterDungeonRsp.proto @@ -2,8 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 937 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerEnterDungeonRsp { - int32 retcode = 1; - uint32 point_id = 2; - uint32 dungeon_id = 3; + int32 retcode = 2; + uint32 point_id = 1; + uint32 dungeon_id = 13; } diff --git a/proto/PlayerEnterSceneInfoNotify.proto b/proto/PlayerEnterSceneInfoNotify.proto index 1202f058e..9f74e3eb0 100755 --- a/proto/PlayerEnterSceneInfoNotify.proto +++ b/proto/PlayerEnterSceneInfoNotify.proto @@ -2,23 +2,18 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "TeamEnterSceneInfo.proto"; -import "MPLevelEntityInfo.proto"; import "AvatarEnterSceneInfo.proto"; +import "MPLevelEntityInfo.proto"; +import "TeamEnterSceneInfo.proto"; +// CmdId: 274 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerEnterSceneInfoNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 246; - } - - uint32 cur_avatar_entity_id = 1; - repeated AvatarEnterSceneInfo avatar_enter_info = 2; - TeamEnterSceneInfo team_enter_info = 3; - MPLevelEntityInfo mp_level_entity_info = 4; - uint32 enter_scene_token = 5; + uint32 cur_avatar_entity_id = 8; + repeated AvatarEnterSceneInfo avatar_enter_info = 14; + TeamEnterSceneInfo team_enter_info = 9; + MPLevelEntityInfo mp_level_entity_info = 5; + uint32 enter_scene_token = 7; } diff --git a/proto/PlayerEnterSceneNotify.proto b/proto/PlayerEnterSceneNotify.proto index 3dc84e10b..8c7d79c8c 100755 --- a/proto/PlayerEnterSceneNotify.proto +++ b/proto/PlayerEnterSceneNotify.proto @@ -2,32 +2,27 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "EnterType.proto"; +import "Vector.proto"; +// CmdId: 209 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerEnterSceneNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 249; - } - - uint32 scene_id = 1; - Vector pos = 2; - uint64 scene_begin_time = 3; - EnterType type = 4; - uint32 target_uid = 6; - uint32 prev_scene_id = 9; - Vector prev_pos = 10; - uint32 dungeon_id = 11; - uint32 world_level = 12; - uint32 enter_scene_token = 13; - bool is_first_login_enter_scene = 14; - repeated uint32 scene_tag_id_list = 15; - bool is_skip_ui = 16; - uint32 enter_reason = 17; - uint32 world_type = 18; - string scene_transaction = 19; + uint32 scene_id = 14; + Vector pos = 15; + uint64 scene_begin_time = 12; + EnterType type = 2; + uint32 target_uid = 4; + uint32 prev_scene_id = 7; + Vector prev_pos = 6; + uint32 dungeon_id = 13; + uint32 world_level = 3; + uint32 enter_scene_token = 9; + bool is_first_login_enter_scene = 11; + repeated uint32 scene_tag_id_list = 1; + bool is_skip_ui = 1430; + uint32 enter_reason = 1982; + uint32 world_type = 1067; + string scene_transaction = 1081; } diff --git a/proto/PlayerGameTimeNotify.proto b/proto/PlayerGameTimeNotify.proto index 53f0daf96..b9e526dac 100755 --- a/proto/PlayerGameTimeNotify.proto +++ b/proto/PlayerGameTimeNotify.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 155 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerGameTimeNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 112; - } - - uint32 game_time = 1; - uint32 uid = 2; - bool is_home = 3; + uint32 game_time = 7; + uint32 uid = 13; + bool is_home = 12; } diff --git a/proto/PlayerGetForceQuitBanInfoRsp.proto b/proto/PlayerGetForceQuitBanInfoRsp.proto index bdac2277a..ac27d5c8f 100755 --- a/proto/PlayerGetForceQuitBanInfoRsp.proto +++ b/proto/PlayerGetForceQuitBanInfoRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4162 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerGetForceQuitBanInfoRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4188; - } - - int32 retcode = 1; - uint32 match_id = 2; - uint32 expire_time = 3; + int32 retcode = 11; + uint32 match_id = 8; + uint32 expire_time = 5; } diff --git a/proto/PlayerHomeCompInfo.proto b/proto/PlayerHomeCompInfo.proto new file mode 100644 index 000000000..1668d65a1 --- /dev/null +++ b/proto/PlayerHomeCompInfo.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "FriendEnterHomeOption.proto"; + +message PlayerHomeCompInfo { + FriendEnterHomeOption friend_enter_home_option = 1; + repeated uint32 unlocked_module_id_list = 2; + repeated uint32 levelup_reward_got_level_list = 3; + repeated uint32 seen_module_id_list = 4; +} diff --git a/proto/PlayerHomeCompInfoNotify.proto b/proto/PlayerHomeCompInfoNotify.proto new file mode 100644 index 000000000..b9021918a --- /dev/null +++ b/proto/PlayerHomeCompInfoNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "PlayerHomeCompInfo.proto"; + +// CmdId: 4563 +// EnetChannelId: 0 +// EnetIsReliable: true +message PlayerHomeCompInfoNotify { + PlayerHomeCompInfo comp_info = 2; +} diff --git a/proto/PlayerLevelRewardUpdateNotify.proto b/proto/PlayerLevelRewardUpdateNotify.proto index dc3dd44dc..3266ee40c 100755 --- a/proto/PlayerLevelRewardUpdateNotify.proto +++ b/proto/PlayerLevelRewardUpdateNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 143 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerLevelRewardUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 152; - } - - repeated uint32 level_list = 1; + repeated uint32 level_list = 14; } diff --git a/proto/PlayerLoginReq.proto b/proto/PlayerLoginReq.proto index 095047fa2..dd702cb4f 100755 --- a/proto/PlayerLoginReq.proto +++ b/proto/PlayerLoginReq.proto @@ -2,55 +2,54 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "TrackingIOInfo.proto"; import "AdjustTrackingInfo.proto"; +import "TrackingIOInfo.proto"; +// CmdId: 141 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerLoginReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 189; - } - - string token = 1; - string client_version = 2; - string system_version = 3; - string device_name = 4; - string device_uuid = 5; - uint32 target_uid = 6; - uint64 login_rand = 7; - bool is_editor = 8; - uint32 language_type = 9; - uint32 account_type = 10; - string account_uid = 11; - string platform = 12; - string device_info = 13; - uint32 platform_type = 14; - bool is_guest = 15; - uint32 cloud_client_ip = 16; - uint32 gm_uid = 17; - string checksum = 18; - string online_id = 19; - uint32 client_token = 20; - bytes security_cmd_reply = 21; - bytes extra_bin_data = 22; - string cps = 23; - uint32 channel_id = 24; - uint32 sub_channel_id = 25; - string checksum_client_version = 26; - uint32 tag = 27; - TrackingIOInfo tracking_io_info = 28; - string country_code = 29; - uint32 client_data_version = 30; - bytes environment_error_code = 31; - uint32 target_home_owner_uid = 32; - string psn_id = 33; - string client_verison_hash = 34; - bool is_transfer = 35; - uint32 reg_platform = 36; - uint32 target_home_param = 37; - AdjustTrackingInfo adjust_tracking_info = 38; + string token = 5; + string client_version = 7; + string system_version = 12; + string device_name = 3; + string device_uuid = 14; + uint32 target_uid = 15; + uint64 login_rand = 11; + bool is_editor = 2; + uint32 language_type = 13; + uint32 account_type = 1; + string account_uid = 8; + string platform = 6; + string device_info = 4; + uint32 platform_type = 10; + bool is_guest = 9; + uint32 cloud_client_ip = 233; + uint32 gm_uid = 1423; + string checksum = 485; + string online_id = 1974; + uint32 client_token = 133; + bytes security_cmd_reply = 96; + bytes extra_bin_data = 814; + string cps = 467; + uint32 channel_id = 2028; + uint32 sub_channel_id = 1571; + string checksum_client_version = 1844; + uint32 tag = 843; + TrackingIOInfo tracking_io_info = 1882; + string country_code = 1060; + uint32 client_data_version = 1570; + bytes environment_error_code = 1303; + uint32 target_home_owner_uid = 1054; + string psn_id = 921; + string client_verison_hash = 1972; + bool is_transfer = 1918; + uint32 reg_platform = 167; + uint32 target_home_param = 1129; + AdjustTrackingInfo adjust_tracking_info = 280; + string birthday = 174; + string MADLMMNJICA = 135; + string CCLJBEJHFOP = 745; + uint32 LKCFGDBHHIL = 1881; } diff --git a/proto/PlayerLoginRsp.proto b/proto/PlayerLoginRsp.proto index 0aa59e21e..5591755b9 100755 --- a/proto/PlayerLoginRsp.proto +++ b/proto/PlayerLoginRsp.proto @@ -2,51 +2,47 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ResVersionConfig.proto"; import "BlockInfo.proto"; -import "ShortAbilityHashPair.proto"; import "FeatureBlockInfo.proto"; +import "ResVersionConfig.proto"; +import "ShortAbilityHashPair.proto"; +// CmdId: 137 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerLoginRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 184; - } - int32 retcode = 1; - bytes player_data = 2; - bool is_new_player = 3; - uint32 target_uid = 4; - uint64 login_rand = 5; - bool is_use_ability_hash = 6; + bytes player_data = 6; + bool is_new_player = 11; + uint32 target_uid = 15; + uint64 login_rand = 12; + bool is_use_ability_hash = 3; int32 ability_hash_code = 7; - map ability_hash_map = 8; - uint32 client_data_version = 9; - bool is_relogin = 11; - uint32 client_silence_data_version = 13; - string game_biz = 14; - uint32 player_data_version = 15; - string client_md5 = 16; - string client_silence_md5 = 17; - ResVersionConfig res_version_config = 20; - map block_info_map = 21; - string client_version_suffix = 24; - string client_silence_version_suffix = 25; - repeated ShortAbilityHashPair short_ability_hash_map = 27; - bytes sc_info = 28; - bool is_audit = 29; - bool is_sc_open = 30; - string register_cps = 31; - repeated FeatureBlockInfo feature_block_info_list = 32; - bool is_data_need_relogin = 33; - string country_code = 34; - ResVersionConfig next_res_version_config = 35; - string next_resource_url = 36; - uint32 target_home_owner_uid = 37; - bool is_enable_client_hash_debug = 38; - bool is_transfer = 39; - double total_tick_time = 40; + map ability_hash_map = 13; + uint32 client_data_version = 14; + bool is_relogin = 2; + uint32 client_silence_data_version = 10; + string game_biz = 9; + uint32 player_data_version = 8; + string client_md_5 = 1706; + string client_silence_md_5 = 271; + ResVersionConfig res_version_config = 933; + map block_info_map = 1156; + string client_version_suffix = 1984; + string client_silence_version_suffix = 49; + repeated ShortAbilityHashPair short_ability_hash_map = 364; + bytes sc_info = 2014; + bool is_audit = 1545; + bool is_sc_open = 1974; + string register_cps = 715; + repeated FeatureBlockInfo feature_block_info_list = 408; + bool is_data_need_relogin = 110; + string country_code = 1306; + ResVersionConfig next_res_version_config = 749; + string next_resource_url = 1744; + uint32 target_home_owner_uid = 945; + bool is_enable_client_hash_debug = 713; + bool is_transfer = 138; + double total_tick_time = 1923; + string birthday = 1977; } diff --git a/proto/PlayerPropNotify.proto b/proto/PlayerPropNotify.proto index 22d32bdce..9223a5693 100755 --- a/proto/PlayerPropNotify.proto +++ b/proto/PlayerPropNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "PropValue.proto"; +// CmdId: 127 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerPropNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 126; - } - - map prop_map = 1; + map prop_map = 10; } diff --git a/proto/PlayerQuitDungeonReq.proto b/proto/PlayerQuitDungeonReq.proto index b94eb9975..2f8d50583 100644 --- a/proto/PlayerQuitDungeonReq.proto +++ b/proto/PlayerQuitDungeonReq.proto @@ -2,7 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 932 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerQuitDungeonReq { - uint32 point_id = 1; - bool is_quit_immediately = 2; + uint32 point_id = 12; + bool is_quit_immediately = 4; } diff --git a/proto/PlayerQuitDungeonRsp.proto b/proto/PlayerQuitDungeonRsp.proto index c2538b630..78d2f5b4c 100644 --- a/proto/PlayerQuitDungeonRsp.proto +++ b/proto/PlayerQuitDungeonRsp.proto @@ -2,7 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 917 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerQuitDungeonRsp { - int32 retcode = 1; - uint32 point_id = 2; + int32 retcode = 12; + uint32 point_id = 6; } diff --git a/proto/PlayerRTTInfo.proto b/proto/PlayerRTTInfo.proto index 4618fcb0e..2ed543319 100755 --- a/proto/PlayerRTTInfo.proto +++ b/proto/PlayerRTTInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message PlayerRTTInfo { uint32 uid = 1; uint32 rtt = 2; diff --git a/proto/PlayerSetPauseReq.proto b/proto/PlayerSetPauseReq.proto index 442bc47c2..fbc0f768d 100755 --- a/proto/PlayerSetPauseReq.proto +++ b/proto/PlayerSetPauseReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 159 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PlayerSetPauseReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 121; - } - - bool is_paused = 1; + bool is_paused = 7; } diff --git a/proto/PlayerStoreNotify.proto b/proto/PlayerStoreNotify.proto index b81b78479..8d3d17e6c 100755 --- a/proto/PlayerStoreNotify.proto +++ b/proto/PlayerStoreNotify.proto @@ -2,19 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "StoreType.proto"; import "Item.proto"; +import "StoreType.proto"; +// CmdId: 609 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerStoreNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 649; - } - - StoreType store_type = 1; - repeated Item item_list = 2; - uint32 weight_limit = 3; + StoreType store_type = 4; + repeated Item item_list = 3; + uint32 weight_limit = 15; } diff --git a/proto/PlayerTimeNotify.proto b/proto/PlayerTimeNotify.proto index 3b004f6f0..4c6a0eed5 100755 --- a/proto/PlayerTimeNotify.proto +++ b/proto/PlayerTimeNotify.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 172 +// EnetChannelId: 0 +// EnetIsReliable: true message PlayerTimeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 120; - } - - bool is_paused = 1; - uint64 player_time = 2; - uint64 server_time = 3; + bool is_paused = 8; + uint64 player_time = 4; + uint64 server_time = 14; } diff --git a/proto/PlayerWorldSceneInfo.proto b/proto/PlayerWorldSceneInfo.proto new file mode 100644 index 000000000..24f940345 --- /dev/null +++ b/proto/PlayerWorldSceneInfo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message PlayerWorldSceneInfo { + uint32 scene_id = 1; + bool is_locked = 2; + repeated uint32 scene_tag_id_list = 3; +} diff --git a/proto/PlayerWorldSceneInfoListNotify.proto b/proto/PlayerWorldSceneInfoListNotify.proto new file mode 100755 index 000000000..c51e74c0d --- /dev/null +++ b/proto/PlayerWorldSceneInfoListNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "PlayerWorldSceneInfo.proto"; + +// CmdId: 3172 +// EnetChannelId: 0 +// EnetIsReliable: true +message PlayerWorldSceneInfoListNotify { + repeated PlayerWorldSceneInfo info_list = 5; +} diff --git a/proto/PostEnterSceneRsp.proto b/proto/PostEnterSceneRsp.proto index 7e836219f..06496ffa0 100755 --- a/proto/PostEnterSceneRsp.proto +++ b/proto/PostEnterSceneRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 3344 +// EnetChannelId: 0 +// EnetIsReliable: true message PostEnterSceneRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3139; - } - - int32 retcode = 1; - uint32 enter_scene_token = 2; + int32 retcode = 13; + uint32 enter_scene_token = 15; } diff --git a/proto/PrivateChatNotify.proto b/proto/PrivateChatNotify.proto index d40a879ff..68d720552 100755 --- a/proto/PrivateChatNotify.proto +++ b/proto/PrivateChatNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "ChatInfo.proto"; +// CmdId: 4991 +// EnetChannelId: 0 +// EnetIsReliable: true message PrivateChatNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 5039; - } - ChatInfo chat_info = 1; } diff --git a/proto/PrivateChatReq.proto b/proto/PrivateChatReq.proto index 388d254ab..f46501868 100755 --- a/proto/PrivateChatReq.proto +++ b/proto/PrivateChatReq.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4959 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PrivateChatReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4999; + uint32 target_uid = 2; + oneof content { + string text = 8; + uint32 icon = 6; } - - oneof Content { - string text = 2; - uint32 icon = 3; - } - uint32 target_uid = 1; } diff --git a/proto/PrivateChatRsp.proto b/proto/PrivateChatRsp.proto index cbea58d75..a831234b6 100755 --- a/proto/PrivateChatRsp.proto +++ b/proto/PrivateChatRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4981 +// EnetChannelId: 0 +// EnetIsReliable: true message PrivateChatRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4968; - } - - int32 retcode = 1; - uint32 chat_forbidden_endtime = 2; + int32 retcode = 2; + uint32 chat_forbidden_endtime = 10; } diff --git a/proto/PropChangeReason.proto b/proto/PropChangeReason.proto index f947a8ea7..62ee20ad1 100755 --- a/proto/PropChangeReason.proto +++ b/proto/PropChangeReason.proto @@ -3,18 +3,18 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum PropChangeReason { - PROP_CHANGE_NONE = 0; - PROP_CHANGE_STATUE_RECOVER = 1; - PROP_CHANGE_ENERGY_BALL = 2; - PROP_CHANGE_ABILITY = 3; - PROP_CHANGE_LEVELUP = 4; - PROP_CHANGE_ITEM = 5; - PROP_CHANGE_AVATAR_CARD = 6; - PROP_CHANGE_CITY_LEVELUP = 7; - PROP_CHANGE_AVATAR_UPGRADE = 8; - PROP_CHANGE_AVATAR_PROMOTE = 9; - PROP_CHANGE_PLAYER_ADD_EXP = 10; - PROP_CHANGE_FINISH_QUEST = 11; - PROP_CHANGE_GM = 12; - PROP_CHANGE_MANUAL_ADJUST_WORLD_LEVEL = 13; + PROP_CHANGE_REASON_NONE = 0; + PROP_CHANGE_REASON_STATUE_RECOVER = 1; + PROP_CHANGE_REASON_ENERGY_BALL = 2; + PROP_CHANGE_REASON_ABILITY = 3; + PROP_CHANGE_REASON_LEVELUP = 4; + PROP_CHANGE_REASON_ITEM = 5; + PROP_CHANGE_REASON_AVATAR_CARD = 6; + PROP_CHANGE_REASON_CITY_LEVELUP = 7; + PROP_CHANGE_REASON_AVATAR_UPGRADE = 8; + PROP_CHANGE_REASON_AVATAR_PROMOTE = 9; + PROP_CHANGE_REASON_PLAYER_ADD_EXP = 10; + PROP_CHANGE_REASON_FINISH_QUEST = 11; + PROP_CHANGE_REASON_GM = 12; + PROP_CHANGE_REASON_MANUAL_ADJUST_WORLD_LEVEL = 13; } diff --git a/proto/PropValue.proto b/proto/PropValue.proto index 15ff0e37f..988205cb9 100755 --- a/proto/PropValue.proto +++ b/proto/PropValue.proto @@ -2,12 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message PropValue { - oneof Value { + uint32 type = 1; + int64 val = 4; + oneof value { int64 ival = 2; float fval = 3; } - uint32 type = 1; - int64 val = 4; } diff --git a/proto/ProtEntityType.proto b/proto/ProtEntityType.proto index 03a451c20..17fcf4f7b 100755 --- a/proto/ProtEntityType.proto +++ b/proto/ProtEntityType.proto @@ -3,19 +3,19 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum ProtEntityType { - PROT_ENTITY_NONE = 0; - PROT_ENTITY_AVATAR = 1; - PROT_ENTITY_MONSTER = 2; - PROT_ENTITY_NPC = 3; - PROT_ENTITY_GADGET = 4; - PROT_ENTITY_REGION = 5; - PROT_ENTITY_WEAPON = 6; - PROT_ENTITY_WEATHER = 7; - PROT_ENTITY_SCENE = 8; - PROT_ENTITY_TEAM = 9; - PROT_ENTITY_MASSIVE_ENTITY = 10; - PROT_ENTITY_MP_LEVEL = 11; - PROT_ENTITY_PLAY_TEAM_ENTITY = 12; - PROT_ENTITY_EYE_POINT = 13; - PROT_ENTITY_MAX = 14; + PROT_ENTITY_TYPE_NONE = 0; + PROT_ENTITY_TYPE_AVATAR = 1; + PROT_ENTITY_TYPE_MONSTER = 2; + PROT_ENTITY_TYPE_NPC = 3; + PROT_ENTITY_TYPE_GADGET = 4; + PROT_ENTITY_TYPE_REGION = 5; + PROT_ENTITY_TYPE_WEAPON = 6; + PROT_ENTITY_TYPE_WEATHER = 7; + PROT_ENTITY_TYPE_SCENE = 8; + PROT_ENTITY_TYPE_TEAM = 9; + PROT_ENTITY_TYPE_MASSIVE_ENTITY = 10; + PROT_ENTITY_TYPE_MP_LEVEL = 11; + PROT_ENTITY_TYPE_PLAY_TEAM_ENTITY = 12; + PROT_ENTITY_TYPE_EYE_POINT = 13; + PROT_ENTITY_TYPE_MAX = 14; } diff --git a/proto/ProudSkillChangeNotify.proto b/proto/ProudSkillChangeNotify.proto index eab257802..f0bdc561d 100755 --- a/proto/ProudSkillChangeNotify.proto +++ b/proto/ProudSkillChangeNotify.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1055 +// EnetChannelId: 0 +// EnetIsReliable: true message ProudSkillChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1012; - } - - uint64 avatar_guid = 1; - uint32 entity_id = 2; - uint32 skill_depot_id = 3; + uint64 avatar_guid = 12; + uint32 entity_id = 11; + uint32 skill_depot_id = 7; repeated uint32 proud_skill_list = 4; } diff --git a/proto/ProudSkillExtraLevelNotify.proto b/proto/ProudSkillExtraLevelNotify.proto index 77d5e666d..1c62e0e09 100755 --- a/proto/ProudSkillExtraLevelNotify.proto +++ b/proto/ProudSkillExtraLevelNotify.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1097 +// EnetChannelId: 0 +// EnetIsReliable: true message ProudSkillExtraLevelNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1036; - } - - uint64 avatar_guid = 1; - uint32 talent_type = 2; - uint32 talent_index = 3; - uint32 extra_level = 4; + uint64 avatar_guid = 14; + uint32 talent_type = 10; + uint32 talent_index = 4; + uint32 extra_level = 5; } diff --git a/proto/PullPrivateChatReq.proto b/proto/PullPrivateChatReq.proto index 8dc4d5fc2..a0cf0a649 100755 --- a/proto/PullPrivateChatReq.proto +++ b/proto/PullPrivateChatReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4967 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message PullPrivateChatReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4951; - } - - uint32 target_uid = 1; - uint32 from_sequence = 2; - uint32 pull_num = 3; + uint32 target_uid = 2; + uint32 from_sequence = 7; + uint32 pull_num = 5; } diff --git a/proto/PullPrivateChatRsp.proto b/proto/PullPrivateChatRsp.proto index 3a3c44ce1..61e4ad601 100755 --- a/proto/PullPrivateChatRsp.proto +++ b/proto/PullPrivateChatRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "ChatInfo.proto"; +// CmdId: 5035 +// EnetChannelId: 0 +// EnetIsReliable: true message PullPrivateChatRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 5044; - } - - int32 retcode = 1; - repeated ChatInfo chat_info = 2; + int32 retcode = 15; + repeated ChatInfo chat_info = 12; } diff --git a/proto/PullRecentChatRsp.proto b/proto/PullRecentChatRsp.proto index 43ab77dd7..8049c9e8e 100755 --- a/proto/PullRecentChatRsp.proto +++ b/proto/PullRecentChatRsp.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "ChatInfo.proto"; +// CmdId: 4999 +// EnetChannelId: 0 +// EnetIsReliable: true message PullRecentChatRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 5011; - } - - int32 retcode = 1; - repeated ChatInfo chat_info = 2; + int32 retcode = 13; + repeated ChatInfo chat_info = 12; } diff --git a/proto/QueryCodexMonsterBeKilledNumReq.proto b/proto/QueryCodexMonsterBeKilledNumReq.proto new file mode 100644 index 000000000..032fc0360 --- /dev/null +++ b/proto/QueryCodexMonsterBeKilledNumReq.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4207 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message QueryCodexMonsterBeKilledNumReq { + repeated uint32 codex_id_list = 11; +} diff --git a/proto/QueryCodexMonsterBeKilledNumRsp.proto b/proto/QueryCodexMonsterBeKilledNumRsp.proto new file mode 100644 index 000000000..f92211d36 --- /dev/null +++ b/proto/QueryCodexMonsterBeKilledNumRsp.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4205 +// EnetChannelId: 0 +// EnetIsReliable: true +message QueryCodexMonsterBeKilledNumRsp { + int32 retcode = 1; + repeated uint32 codex_id_list = 4; + repeated uint32 be_killed_num_list = 11; + repeated uint32 CHPBKCLKPCJ = 2; +} diff --git a/proto/Quest.proto b/proto/Quest.proto new file mode 100644 index 000000000..a8b8e9adc --- /dev/null +++ b/proto/Quest.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message Quest { + uint32 quest_id = 1; + uint32 state = 2; + uint32 start_time = 4; + bool is_random = 5; + uint32 parent_quest_id = 6; + uint32 quest_config_id = 7; + uint32 start_game_time = 8; + uint32 accept_time = 9; + repeated uint32 lacked_npc_list = 10; + repeated uint32 finish_progress_list = 11; + repeated uint32 fail_progress_list = 12; + map lacked_npc_map = 13; + repeated uint32 lacked_place_list = 14; + map lacked_place_map = 15; +} diff --git a/proto/QuestDelNotify.proto b/proto/QuestDelNotify.proto new file mode 100644 index 000000000..6828e5221 --- /dev/null +++ b/proto/QuestDelNotify.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 441 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestDelNotify { + uint32 quest_id = 12; +} diff --git a/proto/QuestGlobalVar.proto b/proto/QuestGlobalVar.proto new file mode 100644 index 000000000..c5df4ac9f --- /dev/null +++ b/proto/QuestGlobalVar.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message QuestGlobalVar { + uint32 key = 1; + int32 value = 2; +} diff --git a/proto/QuestGlobalVarNotify.proto b/proto/QuestGlobalVarNotify.proto new file mode 100644 index 000000000..7308f7360 --- /dev/null +++ b/proto/QuestGlobalVarNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "QuestGlobalVar.proto"; + +// CmdId: 411 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestGlobalVarNotify { + repeated QuestGlobalVar var_list = 9; +} diff --git a/proto/QuestListNotify.proto b/proto/QuestListNotify.proto new file mode 100644 index 000000000..1a57d6dc7 --- /dev/null +++ b/proto/QuestListNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Quest.proto"; + +// CmdId: 409 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestListNotify { + repeated Quest quest_list = 12; +} diff --git a/proto/QuestListUpdateNotify.proto b/proto/QuestListUpdateNotify.proto new file mode 100644 index 000000000..af8954052 --- /dev/null +++ b/proto/QuestListUpdateNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Quest.proto"; + +// CmdId: 431 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestListUpdateNotify { + repeated Quest quest_list = 13; +} diff --git a/proto/QuestProgressUpdateNotify.proto b/proto/QuestProgressUpdateNotify.proto new file mode 100644 index 000000000..94827174d --- /dev/null +++ b/proto/QuestProgressUpdateNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 445 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestProgressUpdateNotify { + uint32 quest_id = 14; + repeated uint32 finish_progress_list = 7; + repeated uint32 fail_progress_list = 12; +} diff --git a/proto/QuestUpdateQuestVarNotify.proto b/proto/QuestUpdateQuestVarNotify.proto new file mode 100644 index 000000000..709aaa99d --- /dev/null +++ b/proto/QuestUpdateQuestVarNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 463 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestUpdateQuestVarNotify { + uint32 parent_quest_id = 3; + repeated int32 quest_var = 6; + uint32 parent_quest_var_seq = 15; +} diff --git a/proto/QuestUpdateQuestVarReq.proto b/proto/QuestUpdateQuestVarReq.proto new file mode 100644 index 000000000..84394870d --- /dev/null +++ b/proto/QuestUpdateQuestVarReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "QuestVarOp.proto"; + +// CmdId: 490 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message QuestUpdateQuestVarReq { + uint32 quest_id = 15; + repeated QuestVarOp quest_var_op_list = 11; + uint32 parent_quest_id = 3; + uint32 parent_quest_var_seq = 8; +} diff --git a/proto/QuestUpdateQuestVarRsp.proto b/proto/QuestUpdateQuestVarRsp.proto new file mode 100644 index 000000000..49735c37f --- /dev/null +++ b/proto/QuestUpdateQuestVarRsp.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 486 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuestUpdateQuestVarRsp { + int32 retcode = 8; + uint32 quest_id = 7; + uint32 parent_quest_id = 12; + uint32 parent_quest_var_seq = 3; +} diff --git a/proto/QuestVarOp.proto b/proto/QuestVarOp.proto new file mode 100644 index 000000000..51d4411b9 --- /dev/null +++ b/proto/QuestVarOp.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message QuestVarOp { + uint32 index = 1; + int32 value = 2; + bool is_add = 3; +} diff --git a/proto/QuickUseWidgetReq.proto b/proto/QuickUseWidgetReq.proto new file mode 100644 index 000000000..34e778f72 --- /dev/null +++ b/proto/QuickUseWidgetReq.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetCameraInfo.proto"; +import "WidgetCreateLocationInfo.proto"; +import "WidgetCreatorInfo.proto"; +import "WidgetThunderBirdFeatherInfo.proto"; + +// CmdId: 4251 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message QuickUseWidgetReq { + oneof param { + WidgetCreateLocationInfo location_info = 1800; + WidgetCameraInfo camera_info = 479; + WidgetCreatorInfo creator_info = 1204; + WidgetThunderBirdFeatherInfo thunder_bird_feather_info = 1198; + } +} diff --git a/proto/QuickUseWidgetRsp.proto b/proto/QuickUseWidgetRsp.proto new file mode 100644 index 000000000..568e601ef --- /dev/null +++ b/proto/QuickUseWidgetRsp.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +//import "AHCELAJGOLN.proto"; +import "ClientCollectorData.proto"; +import "OneoffGatherPointDetectorData.proto"; + +// CmdId: 4252 +// EnetChannelId: 0 +// EnetIsReliable: true +message QuickUseWidgetRsp { + int32 retcode = 9; + uint32 material_id = 1; + oneof ELHGGAPPEBG { + OneoffGatherPointDetectorData detector_data = 11; + ClientCollectorData client_collector_data = 3; + //AHCELAJGOLN sky_crystal_detector_quick_use_result = 32767; + } +} diff --git a/proto/ReadMailNotify.proto b/proto/ReadMailNotify.proto index f485c8a6c..796a57cfb 100644 --- a/proto/ReadMailNotify.proto +++ b/proto/ReadMailNotify.proto @@ -2,6 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 1441 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ReadMailNotify { - repeated uint32 mail_id_list = 1; + repeated uint32 mail_id_list = 9; } diff --git a/proto/Reliquary.proto b/proto/Reliquary.proto index a38387bab..73743905c 100755 --- a/proto/Reliquary.proto +++ b/proto/Reliquary.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message Reliquary { uint32 level = 1; uint32 exp = 2; diff --git a/proto/ReliquaryPromoteReq.proto b/proto/ReliquaryPromoteReq.proto index 780844be0..75c120b3c 100755 --- a/proto/ReliquaryPromoteReq.proto +++ b/proto/ReliquaryPromoteReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 612 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ReliquaryPromoteReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 622; - } - - uint64 target_guid = 1; - uint64 item_guid = 2; + uint64 target_guid = 4; + uint64 item_guid = 14; } diff --git a/proto/ReliquaryPromoteRsp.proto b/proto/ReliquaryPromoteRsp.proto index 36cd6aec6..d6a2180c7 100755 --- a/proto/ReliquaryPromoteRsp.proto +++ b/proto/ReliquaryPromoteRsp.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 658 +// EnetChannelId: 0 +// EnetIsReliable: true message ReliquaryPromoteRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 676; - } - - int32 retcode = 1; - uint64 target_reliquary_guid = 2; - uint32 old_promote_level = 3; - uint32 cur_promote_level = 4; - repeated uint32 old_append_prop_list = 5; - repeated uint32 cur_append_prop_list = 6; + int32 retcode = 2; + uint64 target_reliquary_guid = 4; + uint32 old_promote_level = 11; + uint32 cur_promote_level = 14; + repeated uint32 old_append_prop_list = 3; + repeated uint32 cur_append_prop_list = 13; } diff --git a/proto/ReliquaryUpgradeReq.proto b/proto/ReliquaryUpgradeReq.proto index 78e136bb1..6649b6de4 100755 --- a/proto/ReliquaryUpgradeReq.proto +++ b/proto/ReliquaryUpgradeReq.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 606 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message ReliquaryUpgradeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 616; - } - - uint64 target_reliquary_guid = 1; - repeated uint64 food_reliquary_guid_list = 2; - repeated ItemParam item_param_list = 3; + uint64 target_reliquary_guid = 5; + repeated uint64 food_reliquary_guid_list = 15; + repeated ItemParam item_param_list = 13; } diff --git a/proto/ReliquaryUpgradeRsp.proto b/proto/ReliquaryUpgradeRsp.proto index f5fe7eae1..9f7708382 100755 --- a/proto/ReliquaryUpgradeRsp.proto +++ b/proto/ReliquaryUpgradeRsp.proto @@ -2,21 +2,15 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 619 +// EnetChannelId: 0 +// EnetIsReliable: true message ReliquaryUpgradeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 696; - } - int32 retcode = 1; - uint64 target_reliquary_guid = 2; - uint32 old_level = 3; - uint32 cur_level = 4; - uint32 power_up_rate = 5; - repeated uint32 old_append_prop_list = 6; - repeated uint32 cur_append_prop_list = 7; + uint64 target_reliquary_guid = 10; + uint32 old_level = 5; + uint32 cur_level = 6; + uint32 power_up_rate = 2; + repeated uint32 old_append_prop_list = 7; + repeated uint32 cur_append_prop_list = 14; } diff --git a/proto/ResVersionConfig.proto b/proto/ResVersionConfig.proto index 36073f2af..d22a8ef50 100755 --- a/proto/ResVersionConfig.proto +++ b/proto/ResVersionConfig.proto @@ -2,11 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ResVersionConfig { uint32 version = 1; bool relogin = 2; - string md5 = 3; + string md_5 = 3; string release_total_size = 4; string version_suffix = 5; string branch = 6; diff --git a/proto/ResinChangeNotify.proto b/proto/ResinChangeNotify.proto index d68c0db22..5041f4a6c 100755 --- a/proto/ResinChangeNotify.proto +++ b/proto/ResinChangeNotify.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 670 +// EnetChannelId: 0 +// EnetIsReliable: true message ResinChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 611; - } - - uint32 cur_value = 1; + uint32 cur_value = 4; uint32 next_add_timestamp = 2; uint32 cur_buy_count = 3; } diff --git a/proto/ResinCostType.proto b/proto/ResinCostType.proto index 92e395509..c22cfa797 100755 --- a/proto/ResinCostType.proto +++ b/proto/ResinCostType.proto @@ -3,10 +3,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum ResinCostType { - NONE = 0; - NORMAL = 1; - CONDENSE = 2; - REUNION_PRIVILEGE = 3; - OP_ACTIVITY = 4; - MATERIAL = 5; + RESIN_COST_TYPE_NONE = 0; + RESIN_COST_TYPE_NORMAL = 1; + RESIN_COST_TYPE_CONDENSE = 2; + RESIN_COST_TYPE_REUNION_PRIVILEGE = 3; + RESIN_COST_TYPE_OP_ACTIVITY = 4; + RESIN_COST_TYPE_MATERIAL = 5; } diff --git a/proto/RoguelikeDungeonSettleInfo.proto b/proto/RoguelikeDungeonSettleInfo.proto new file mode 100644 index 000000000..720158b91 --- /dev/null +++ b/proto/RoguelikeDungeonSettleInfo.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "RoguelikeSettleCoinInfo.proto"; + +message RoguelikeDungeonSettleInfo { + uint32 stage_id = 1; + uint32 cur_level = 2; + map finished_challenge_cell_num_map = 3; + bool is_final_level = 4; + uint32 total_coin_b_num = 5; + uint32 total_coin_c_num = 6; + bool is_coin_c_reach_limit = 7; +} diff --git a/proto/RoguelikeSettleCoinInfo.proto b/proto/RoguelikeSettleCoinInfo.proto new file mode 100644 index 000000000..465a73218 --- /dev/null +++ b/proto/RoguelikeSettleCoinInfo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message RoguelikeSettleCoinInfo { + uint32 cell_num = 1; + uint32 coin_b = 2; + uint32 coin_c = 3; +} diff --git a/proto/RoutePoint.proto b/proto/RoutePoint.proto index d6266de5f..5390d5b67 100755 --- a/proto/RoutePoint.proto +++ b/proto/RoutePoint.proto @@ -2,19 +2,19 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "MathQuaternion.proto"; +import "Vector.proto"; message RoutePoint { - oneof MoveParams { + Vector position = 1; + float arrive_range = 2; + oneof move_params { float velocity = 11; float time = 12; } - oneof RotateParams { + oneof rotate_params { Vector rotation = 21; MathQuaternion rotation_speed = 22; MathQuaternion axis_speed = 23; } - Vector position = 1; - float arrive_range = 2; } diff --git a/proto/SceneAreaWeatherNotify.proto b/proto/SceneAreaWeatherNotify.proto index 51b168130..8ae1b43ce 100755 --- a/proto/SceneAreaWeatherNotify.proto +++ b/proto/SceneAreaWeatherNotify.proto @@ -2,19 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 229 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneAreaWeatherNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 251; - } - - uint32 weather_gadget_id = 1; - map weather_value_map = 2; - uint32 weather_area_id = 3; - uint32 climate_type = 4; - float trans_duration = 5; + uint32 weather_gadget_id = 13; + map weather_value_map = 10; + uint32 weather_area_id = 15; + uint32 climate_type = 14; + float trans_duration = 11; } diff --git a/proto/SceneAvatarInfo.proto b/proto/SceneAvatarInfo.proto index f6b23cf05..617c3fc53 100755 --- a/proto/SceneAvatarInfo.proto +++ b/proto/SceneAvatarInfo.proto @@ -2,10 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "SceneWeaponInfo.proto"; -import "CurVehicleInfo.proto"; import "AvatarExcelInfo.proto"; +import "CurVehicleInfo.proto"; import "SceneReliquaryInfo.proto"; +import "SceneWeaponInfo.proto"; import "ServerBuff.proto"; message SceneAvatarInfo { diff --git a/proto/SceneEntityAiInfo.proto b/proto/SceneEntityAiInfo.proto index bc85ef4f2..8eb55e72e 100755 --- a/proto/SceneEntityAiInfo.proto +++ b/proto/SceneEntityAiInfo.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Vector.proto"; import "ServantInfo.proto"; +import "Vector.proto"; message SceneEntityAiInfo { bool is_ai_open = 1; diff --git a/proto/SceneEntityAppearNotify.proto b/proto/SceneEntityAppearNotify.proto index 388c69dcd..9f0e4dff5 100755 --- a/proto/SceneEntityAppearNotify.proto +++ b/proto/SceneEntityAppearNotify.proto @@ -2,19 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "VisionType.proto"; import "SceneEntityInfo.proto"; +import "VisionType.proto"; +// CmdId: 217 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneEntityAppearNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 201; - } - - repeated SceneEntityInfo entity_list = 1; - VisionType appear_type = 2; - uint32 param = 3; + repeated SceneEntityInfo entity_list = 6; + VisionType appear_type = 8; + uint32 param = 11; } diff --git a/proto/SceneEntityDisappearNotify.proto b/proto/SceneEntityDisappearNotify.proto index 45a4c02fb..adb5d4702 100755 --- a/proto/SceneEntityDisappearNotify.proto +++ b/proto/SceneEntityDisappearNotify.proto @@ -4,15 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "VisionType.proto"; +// CmdId: 285 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneEntityDisappearNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 294; - } - - repeated uint32 entity_list = 1; - VisionType disappear_type = 2; + repeated uint32 entity_list = 9; + VisionType disappear_type = 10; + uint32 param = 6; } diff --git a/proto/SceneEntityDrownReq.proto b/proto/SceneEntityDrownReq.proto index a0a98e9c2..8b822e93b 100644 --- a/proto/SceneEntityDrownReq.proto +++ b/proto/SceneEntityDrownReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 212 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SceneEntityDrownReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 222; - } - - uint32 entity_id = 1; + uint32 entity_id = 14; } diff --git a/proto/SceneEntityDrownRsp.proto b/proto/SceneEntityDrownRsp.proto index 8db1aece0..1d323d3a2 100644 --- a/proto/SceneEntityDrownRsp.proto +++ b/proto/SceneEntityDrownRsp.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 258 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneEntityDrownRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 276; - } - - int32 retcode = 1; - uint32 entity_id = 2; + int32 retcode = 14; + uint32 entity_id = 10; } diff --git a/proto/SceneEntityInfo.proto b/proto/SceneEntityInfo.proto index 0c56b7043..6cd667b0a 100755 --- a/proto/SceneEntityInfo.proto +++ b/proto/SceneEntityInfo.proto @@ -2,27 +2,21 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +import "AnimatorParameterValueInfoPair.proto"; +import "EntityAuthorityInfo.proto"; +import "EntityClientData.proto"; +import "EntityEnvironmentInfo.proto"; +import "FightPropPair.proto"; +import "MotionInfo.proto"; +import "PropPair.proto"; +import "ProtEntityType.proto"; import "SceneAvatarInfo.proto"; +import "SceneGadgetInfo.proto"; import "SceneMonsterInfo.proto"; import "SceneNpcInfo.proto"; -import "SceneGadgetInfo.proto"; -import "ProtEntityType.proto"; -import "MotionInfo.proto"; -import "EntityClientData.proto"; -import "EntityAuthorityInfo.proto"; -import "PropPair.proto"; -import "FightPropPair.proto"; -import "AnimatorParameterValueInfoPair.proto"; -import "EntityEnvironmentInfo.proto"; import "ServerBuff.proto"; message SceneEntityInfo { - oneof Entity { - SceneAvatarInfo avatar = 10; - SceneMonsterInfo monster = 11; - SceneNpcInfo npc = 12; - SceneGadgetInfo gadget = 13; - } ProtEntityType entity_type = 1; uint32 entity_id = 2; string name = 3; @@ -38,4 +32,10 @@ message SceneEntityInfo { EntityAuthorityInfo entity_authority_info = 21; repeated string tag_list = 22; repeated ServerBuff server_buff_list = 23; + oneof entity { + SceneAvatarInfo avatar = 10; + SceneMonsterInfo monster = 11; + SceneNpcInfo npc = 12; + SceneGadgetInfo gadget = 13; + } } diff --git a/proto/SceneEntityMoveNotify.proto b/proto/SceneEntityMoveNotify.proto index 58b430c68..116b5a130 100755 --- a/proto/SceneEntityMoveNotify.proto +++ b/proto/SceneEntityMoveNotify.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "MotionInfo.proto"; +// CmdId: 227 +// EnetChannelId: 1 +// EnetIsReliable: true message SceneEntityMoveNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_IS_RELIABLE = 1; - ENET_CHANNEL_ID = 1; - CMD_ID = 226; - } - - uint32 entity_id = 1; - MotionInfo motion_info = 2; - uint32 scene_time = 3; - uint32 reliable_seq = 4; + uint32 entity_id = 10; + MotionInfo motion_info = 3; + uint32 scene_time = 12; + uint32 reliable_seq = 11; } diff --git a/proto/SceneFishInfo.proto b/proto/SceneFishInfo.proto index 212a244c2..b5b0368d6 100644 --- a/proto/SceneFishInfo.proto +++ b/proto/SceneFishInfo.proto @@ -9,4 +9,5 @@ message SceneFishInfo { uint32 fish_pool_entity_id = 2; Vector fish_pool_pos = 3; uint32 fish_pool_gadget_id = 4; + uint32 LPNFLHKPHEC = 5; } diff --git a/proto/SceneForceUnlockNotify.proto b/proto/SceneForceUnlockNotify.proto index b260606df..8acaf733d 100755 --- a/proto/SceneForceUnlockNotify.proto +++ b/proto/SceneForceUnlockNotify.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 201 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneForceUnlockNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 292; - } - repeated uint32 force_id_list = 1; - bool is_add = 2; + bool is_add = 5; } diff --git a/proto/SceneGadgetInfo.proto b/proto/SceneGadgetInfo.proto index 0c405e475..ac847eab3 100755 --- a/proto/SceneGadgetInfo.proto +++ b/proto/SceneGadgetInfo.proto @@ -2,31 +2,49 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "Item.proto"; -import "GatherGadgetInfo.proto"; -import "WorktopInfo.proto"; -import "ClientGadgetInfo.proto"; -import "WeatherInfo.proto"; import "AbilityGadgetInfo.proto"; -import "StatueGadgetInfo.proto"; -import "BossChestInfo.proto"; import "BlossomChestInfo.proto"; -import "MpPlayRewardInfo.proto"; -import "GadgetGeneralRewardInfo.proto"; -import "OfferingInfo.proto"; -import "FoundationInfo.proto"; -import "VehicleInfo.proto"; -import "EchoShellInfo.proto"; -import "ScreenInfo.proto"; -import "FishPoolInfo.proto"; +import "BossChestInfo.proto"; +import "ClientGadgetInfo.proto"; import "CustomGadgetTreeInfo.proto"; -import "RoguelikeGadgetInfo.proto"; +import "EchoShellInfo.proto"; +import "FishPoolInfo.proto"; +import "FoundationInfo.proto"; import "GadgetBornType.proto"; -import "PlatformInfo.proto"; +import "GadgetGeneralRewardInfo.proto"; import "GadgetPlayInfo.proto"; +import "GatherGadgetInfo.proto"; +import "Item.proto"; +import "MpPlayRewardInfo.proto"; +import "OfferingInfo.proto"; +import "PlatformInfo.proto"; +import "RoguelikeGadgetInfo.proto"; +import "ScreenInfo.proto"; +import "StatueGadgetInfo.proto"; +import "VehicleInfo.proto"; +import "WeatherInfo.proto"; +import "WorktopInfo.proto"; message SceneGadgetInfo { - oneof Content { + uint32 gadget_id = 1; + uint32 group_id = 2; + uint32 config_id = 3; + uint32 owner_entity_id = 4; + GadgetBornType born_type = 5; + uint32 gadget_state = 6; + uint32 gadget_type = 7; + bool is_show_cutscene = 8; + uint32 authority_peer_id = 9; + bool is_enable_interact = 10; + uint32 interact_id = 11; + uint32 mark_flag = 21; + uint32 prop_owner_entity_id = 22; + PlatformInfo platform = 23; + repeated uint32 interact_uid_list = 24; + uint32 draft_id = 25; + uint32 gadget_talk_state = 26; + GadgetPlayInfo play_info = 100; + oneof content { Item trifle_item = 12; GatherGadgetInfo gather_gadget = 13; WorktopInfo worktop = 14; @@ -47,22 +65,4 @@ message SceneGadgetInfo { CustomGadgetTreeInfo custom_gadget_tree_info = 60; RoguelikeGadgetInfo roguelike_gadget_info = 61; } - uint32 gadget_id = 1; - uint32 group_id = 2; - uint32 config_id = 3; - uint32 owner_entity_id = 4; - GadgetBornType born_type = 5; - uint32 gadget_state = 6; - uint32 gadget_type = 7; - bool is_show_cutscene = 8; - uint32 authority_peer_id = 9; - bool is_enable_interact = 10; - uint32 interact_id = 11; - uint32 mark_flag = 21; - uint32 prop_owner_entity_id = 22; - PlatformInfo platform = 23; - repeated uint32 interact_uid_list = 24; - uint32 draft_id = 25; - uint32 gadget_talk_state = 26; - GadgetPlayInfo play_info = 100; } diff --git a/proto/SceneInitFinishRsp.proto b/proto/SceneInitFinishRsp.proto index bdc518b88..cec0970ed 100755 --- a/proto/SceneInitFinishRsp.proto +++ b/proto/SceneInitFinishRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 232 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SceneInitFinishRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 300; - } - - int32 retcode = 1; - uint32 enter_scene_token = 2; + int32 retcode = 10; + uint32 enter_scene_token = 15; } diff --git a/proto/SceneKickPlayerNotify.proto b/proto/SceneKickPlayerNotify.proto index cb8e5f070..f4a6bcb95 100755 --- a/proto/SceneKickPlayerNotify.proto +++ b/proto/SceneKickPlayerNotify.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 292 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SceneKickPlayerNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 235; - } - - uint32 kicker_uid = 1; - uint32 target_uid = 2; + uint32 kicker_uid = 9; + uint32 target_uid = 13; } diff --git a/proto/SceneKickPlayerReq.proto b/proto/SceneKickPlayerReq.proto index eada835ad..61b83f5bc 100755 --- a/proto/SceneKickPlayerReq.proto +++ b/proto/SceneKickPlayerReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 295 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SceneKickPlayerReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 268; - } - - uint32 target_uid = 1; + uint32 target_uid = 12; } diff --git a/proto/SceneKickPlayerRsp.proto b/proto/SceneKickPlayerRsp.proto index 68eadc25d..4e61298be 100755 --- a/proto/SceneKickPlayerRsp.proto +++ b/proto/SceneKickPlayerRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 215 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneKickPlayerRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 272; - } - - int32 retcode = 1; - uint32 target_uid = 2; + int32 retcode = 9; + uint32 target_uid = 12; } diff --git a/proto/SceneMonsterInfo.proto b/proto/SceneMonsterInfo.proto index ef9572818..291ce0ace 100755 --- a/proto/SceneMonsterInfo.proto +++ b/proto/SceneMonsterInfo.proto @@ -2,15 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "SceneFishInfo.proto"; import "MonsterBornType.proto"; import "MonsterRoute.proto"; +import "SceneFishInfo.proto"; import "SceneWeaponInfo.proto"; message SceneMonsterInfo { - oneof Content { - SceneFishInfo fish_info = 50; - } uint32 monster_id = 1; uint32 group_id = 2; uint32 config_id = 3; @@ -32,4 +29,7 @@ message SceneMonsterInfo { uint32 ai_config_id = 19; uint32 level_route_id = 20; uint32 init_pose_id = 21; + oneof content { + SceneFishInfo fish_info = 50; + } } diff --git a/proto/SceneNpcInfo.proto b/proto/SceneNpcInfo.proto index b04265cb8..76d878aff 100755 --- a/proto/SceneNpcInfo.proto +++ b/proto/SceneNpcInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message SceneNpcInfo { uint32 npc_id = 1; uint32 room_id = 2; diff --git a/proto/ScenePlayerInfoNotify.proto b/proto/ScenePlayerInfoNotify.proto index 7f789f3fb..bb515149f 100755 --- a/proto/ScenePlayerInfoNotify.proto +++ b/proto/ScenePlayerInfoNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "ScenePlayerInfo.proto"; +// CmdId: 225 +// EnetChannelId: 0 +// EnetIsReliable: true message ScenePlayerInfoNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 293; - } - - repeated ScenePlayerInfo player_info_list = 1; + repeated ScenePlayerInfo player_info_list = 11; } diff --git a/proto/ScenePlayerLocationNotify.proto b/proto/ScenePlayerLocationNotify.proto index 6e8478848..60fd1fc3e 100755 --- a/proto/ScenePlayerLocationNotify.proto +++ b/proto/ScenePlayerLocationNotify.proto @@ -5,16 +5,11 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerLocationInfo.proto"; import "VehicleLocationInfo.proto"; +// CmdId: 207 +// EnetChannelId: 1 +// EnetIsReliable: true message ScenePlayerLocationNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_IS_RELIABLE = 1; - ENET_CHANNEL_ID = 1; - CMD_ID = 224; - } - uint32 scene_id = 1; - repeated PlayerLocationInfo player_loc_list = 2; - repeated VehicleLocationInfo vehicle_loc_list = 3; + repeated PlayerLocationInfo player_loc_list = 8; + repeated VehicleLocationInfo vehicle_loc_list = 5; } diff --git a/proto/SceneReliquaryInfo.proto b/proto/SceneReliquaryInfo.proto index 8d785d459..782d41de3 100755 --- a/proto/SceneReliquaryInfo.proto +++ b/proto/SceneReliquaryInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message SceneReliquaryInfo { uint32 item_id = 1; uint64 guid = 2; diff --git a/proto/SceneTeamAvatar.proto b/proto/SceneTeamAvatar.proto index 1b09ddb45..8ad79b45d 100755 --- a/proto/SceneTeamAvatar.proto +++ b/proto/SceneTeamAvatar.proto @@ -2,11 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +import "AbilityControlBlock.proto"; +import "AbilitySyncStateInfo.proto"; import "AvatarInfo.proto"; import "SceneAvatarInfo.proto"; -import "AbilitySyncStateInfo.proto"; import "SceneEntityInfo.proto"; -import "AbilityControlBlock.proto"; import "ServerBuff.proto"; message SceneTeamAvatar { diff --git a/proto/SceneTeamUpdateNotify.proto b/proto/SceneTeamUpdateNotify.proto index 183d88f81..44800556f 100755 --- a/proto/SceneTeamUpdateNotify.proto +++ b/proto/SceneTeamUpdateNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "SceneTeamAvatar.proto"; +// CmdId: 1699 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneTeamUpdateNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1793; - } - - repeated SceneTeamAvatar scene_team_avatar_list = 1; - bool is_in_mp = 3; + repeated SceneTeamAvatar scene_team_avatar_list = 11; + bool is_in_mp = 1; } diff --git a/proto/SceneTimeNotify.proto b/proto/SceneTimeNotify.proto index 601be2773..6130e0537 100755 --- a/proto/SceneTimeNotify.proto +++ b/proto/SceneTimeNotify.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 262 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneTimeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 230; - } - - uint32 scene_id = 1; - bool is_paused = 2; - uint64 scene_time = 3; + uint32 scene_id = 3; + bool is_paused = 5; + uint64 scene_time = 14; } diff --git a/proto/SceneTransToPointReq.proto b/proto/SceneTransToPointReq.proto index aed746d33..7b366cbef 100755 --- a/proto/SceneTransToPointReq.proto +++ b/proto/SceneTransToPointReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 286 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SceneTransToPointReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 270; - } - - uint32 scene_id = 1; - uint32 point_id = 2; + uint32 scene_id = 12; + uint32 point_id = 4; } diff --git a/proto/SceneTransToPointRsp.proto b/proto/SceneTransToPointRsp.proto index 3448f263f..a880f56ab 100755 --- a/proto/SceneTransToPointRsp.proto +++ b/proto/SceneTransToPointRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 263 +// EnetChannelId: 0 +// EnetIsReliable: true message SceneTransToPointRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 232; - } - - int32 retcode = 1; - uint32 scene_id = 2; - uint32 point_id = 3; + int32 retcode = 4; + uint32 scene_id = 11; + uint32 point_id = 13; } diff --git a/proto/SceneUnlockInfoNotify.proto b/proto/SceneUnlockInfoNotify.proto deleted file mode 100755 index 28be03d6c..000000000 --- a/proto/SceneUnlockInfoNotify.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -import "SceneUnlockInfo.proto"; - -message SceneUnlockInfoNotify { - repeated SceneUnlockInfo unlockInfos = 1; -} diff --git a/proto/SceneWeaponInfo.proto b/proto/SceneWeaponInfo.proto index db45af89e..8ef4dae94 100755 --- a/proto/SceneWeaponInfo.proto +++ b/proto/SceneWeaponInfo.proto @@ -3,6 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "AbilitySyncStateInfo.proto"; +import "EntityRendererChangedInfo.proto"; message SceneWeaponInfo { uint32 entity_id = 1; @@ -13,4 +14,5 @@ message SceneWeaponInfo { uint32 promote_level = 6; AbilitySyncStateInfo ability_info = 7; map affix_map = 8; + EntityRendererChangedInfo renderer_changed_info = 9; } diff --git a/proto/SelectWorktopOptionReq.proto b/proto/SelectWorktopOptionReq.proto index 10f36bc47..449cfe51a 100644 --- a/proto/SelectWorktopOptionReq.proto +++ b/proto/SelectWorktopOptionReq.proto @@ -2,7 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 832 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SelectWorktopOptionReq { - uint32 gadget_entity_id = 1; - uint32 option_id = 2; + uint32 gadget_entity_id = 2; + uint32 option_id = 5; } diff --git a/proto/SelectWorktopOptionRsp.proto b/proto/SelectWorktopOptionRsp.proto index 423882e42..13beed8ee 100644 --- a/proto/SelectWorktopOptionRsp.proto +++ b/proto/SelectWorktopOptionRsp.proto @@ -2,8 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 817 +// EnetChannelId: 0 +// EnetIsReliable: true message SelectWorktopOptionRsp { - int32 retcode = 1; - uint32 gadget_entity_id = 2; - uint32 option_id = 3; + int32 retcode = 7; + uint32 gadget_entity_id = 12; + uint32 option_id = 10; } diff --git a/proto/ServantInfo.proto b/proto/ServantInfo.proto index 3ed3e9b0b..28b5bff0c 100755 --- a/proto/ServantInfo.proto +++ b/proto/ServantInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ServantInfo { uint32 master_entity_id = 1; uint32 born_slot_index = 2; diff --git a/proto/ServerBuff.proto b/proto/ServerBuff.proto index bc9695843..92f0829d0 100755 --- a/proto/ServerBuff.proto +++ b/proto/ServerBuff.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ServerBuff { uint32 server_buff_uid = 1; uint32 server_buff_id = 2; diff --git a/proto/ServerCondMeetQuestListUpdateNotify.proto b/proto/ServerCondMeetQuestListUpdateNotify.proto new file mode 100644 index 000000000..615c704d6 --- /dev/null +++ b/proto/ServerCondMeetQuestListUpdateNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 401 +// EnetChannelId: 0 +// EnetIsReliable: true +message ServerCondMeetQuestListUpdateNotify { + repeated uint32 add_quest_id_list = 9; + repeated uint32 del_quest_id_list = 6; +} diff --git a/proto/ServerTimeNotify.proto b/proto/ServerTimeNotify.proto index f20266a02..efc231af6 100755 --- a/proto/ServerTimeNotify.proto +++ b/proto/ServerTimeNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 82 +// EnetChannelId: 1 +// EnetIsReliable: true message ServerTimeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_IS_RELIABLE = 1; - ENET_CHANNEL_ID = 1; - CMD_ID = 79; - } - - uint64 server_time = 1; + uint64 server_time = 15; } diff --git a/proto/SetEntityClientDataNotify.proto b/proto/SetEntityClientDataNotify.proto index 2760a4d58..b61e44d48 100755 --- a/proto/SetEntityClientDataNotify.proto +++ b/proto/SetEntityClientDataNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "EntityClientData.proto"; +// CmdId: 3375 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetEntityClientDataNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 3187; - } - - uint32 entity_id = 1; - EntityClientData entity_client_data = 2; + uint32 entity_id = 13; + EntityClientData entity_client_data = 1; } diff --git a/proto/SetEquipLockStateReq.proto b/proto/SetEquipLockStateReq.proto index 91c97d472..9280ee17f 100755 --- a/proto/SetEquipLockStateReq.proto +++ b/proto/SetEquipLockStateReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 604 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetEquipLockStateReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 605; - } - - uint64 target_equip_guid = 1; - bool is_locked = 2; + uint64 target_equip_guid = 10; + bool is_locked = 11; } diff --git a/proto/SetEquipLockStateRsp.proto b/proto/SetEquipLockStateRsp.proto index 7afa7503d..118081845 100755 --- a/proto/SetEquipLockStateRsp.proto +++ b/proto/SetEquipLockStateRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 605 +// EnetChannelId: 0 +// EnetIsReliable: true message SetEquipLockStateRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 662; - } - - int32 retcode = 1; - uint64 target_equip_guid = 2; - bool is_locked = 3; + int32 retcode = 7; + uint64 target_equip_guid = 13; + bool is_locked = 5; } diff --git a/proto/SetNameCardReq.proto b/proto/SetNameCardReq.proto index d89eedb1e..a0edfb69c 100755 --- a/proto/SetNameCardReq.proto +++ b/proto/SetNameCardReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4006 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetNameCardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4016; - } - - uint32 name_card_id = 1; + uint32 name_card_id = 4; } diff --git a/proto/SetNameCardRsp.proto b/proto/SetNameCardRsp.proto index f45961a5b..d7c5a557f 100755 --- a/proto/SetNameCardRsp.proto +++ b/proto/SetNameCardRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4019 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetNameCardRsp { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4096; - } - - int32 retcode = 1; + int32 retcode = 11; uint32 name_card_id = 2; } diff --git a/proto/SetPlayerBirthdayReq.proto b/proto/SetPlayerBirthdayReq.proto index 3085c75b0..ceeeb0b77 100644 --- a/proto/SetPlayerBirthdayReq.proto +++ b/proto/SetPlayerBirthdayReq.proto @@ -1,18 +1,13 @@ syntax = "proto3"; -import "Birthday.proto"; - option java_package = "emu.grasscutter.net.proto"; -message SetPlayerBirthdayReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4024; - } +import "Birthday.proto"; - Birthday birthday = 1; +// CmdId: 4007 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message SetPlayerBirthdayReq { + Birthday birthday = 10; } diff --git a/proto/SetPlayerBirthdayRsp.proto b/proto/SetPlayerBirthdayRsp.proto index a7ac3c01f..1f2b92f83 100644 --- a/proto/SetPlayerBirthdayRsp.proto +++ b/proto/SetPlayerBirthdayRsp.proto @@ -1,18 +1,13 @@ syntax = "proto3"; -import "Birthday.proto"; - option java_package = "emu.grasscutter.net.proto"; -message SetPlayerBirthdayRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4091; - } +import "Birthday.proto"; - int32 retcode = 1; - Birthday birthday = 2; +// CmdId: 4030 +// EnetChannelId: 0 +// EnetIsReliable: true +message SetPlayerBirthdayRsp { + int32 retcode = 12; + Birthday birthday = 14; } diff --git a/proto/SetPlayerBornDataReq.proto b/proto/SetPlayerBornDataReq.proto index ce0594d33..cd5cbf4b5 100644 --- a/proto/SetPlayerBornDataReq.proto +++ b/proto/SetPlayerBornDataReq.proto @@ -2,16 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 198 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetPlayerBornDataReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 119; - } - - uint32 avatar_id = 1; - string nick_name = 2; + uint32 avatar_id = 3; + string nick_name = 12; } diff --git a/proto/SetPlayerBornDataRsp.proto b/proto/SetPlayerBornDataRsp.proto index 9192576c8..fd5051078 100644 --- a/proto/SetPlayerBornDataRsp.proto +++ b/proto/SetPlayerBornDataRsp.proto @@ -2,14 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 145 +// EnetChannelId: 0 +// EnetIsReliable: true message SetPlayerBornDataRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 114; - } - - int32 retcode = 1; + int32 retcode = 4; } diff --git a/proto/SetPlayerHeadImageReq.proto b/proto/SetPlayerHeadImageReq.proto index d2182baaa..53e6ce188 100755 --- a/proto/SetPlayerHeadImageReq.proto +++ b/proto/SetPlayerHeadImageReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4045 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetPlayerHeadImageReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4014; - } - - uint32 avatar_id = 1; + uint32 avatar_id = 4; } diff --git a/proto/SetPlayerHeadImageRsp.proto b/proto/SetPlayerHeadImageRsp.proto index 28d568caa..5cbef4f1d 100755 --- a/proto/SetPlayerHeadImageRsp.proto +++ b/proto/SetPlayerHeadImageRsp.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "ProfilePicture.proto"; +// CmdId: 4090 +// EnetChannelId: 0 +// EnetIsReliable: true message SetPlayerHeadImageRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4015; - } - - int32 retcode = 1; - uint32 avatar_id = 2; - ProfilePicture profile_picture = 3; + int32 retcode = 13; + uint32 avatar_id = 3; + ProfilePicture profile_picture = 5; } diff --git a/proto/SetPlayerNameReq.proto b/proto/SetPlayerNameReq.proto index d9b60621d..962b188a2 100755 --- a/proto/SetPlayerNameReq.proto +++ b/proto/SetPlayerNameReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 163 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetPlayerNameReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 132; - } - - string nick_name = 1; + string nick_name = 8; } diff --git a/proto/SetPlayerNameRsp.proto b/proto/SetPlayerNameRsp.proto index 0e4be0996..c59cc2226 100755 --- a/proto/SetPlayerNameRsp.proto +++ b/proto/SetPlayerNameRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 124 +// EnetChannelId: 0 +// EnetIsReliable: true message SetPlayerNameRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 147; - } - - int32 retcode = 1; - string nick_name = 2; + int32 retcode = 12; + string nick_name = 6; } diff --git a/proto/SetPlayerPropReq.proto b/proto/SetPlayerPropReq.proto index 41b018ed7..1f8e286db 100755 --- a/proto/SetPlayerPropReq.proto +++ b/proto/SetPlayerPropReq.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "PropValue.proto"; +// CmdId: 130 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetPlayerPropReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 191; - } - - repeated PropValue prop_list = 1; + repeated PropValue prop_list = 14; } diff --git a/proto/SetPlayerPropRsp.proto b/proto/SetPlayerPropRsp.proto index 935754f19..9c486533d 100755 --- a/proto/SetPlayerPropRsp.proto +++ b/proto/SetPlayerPropRsp.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 197 +// EnetChannelId: 0 +// EnetIsReliable: true message SetPlayerPropRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 136; - } - - int32 retcode = 1; + int32 retcode = 5; } diff --git a/proto/SetPlayerSignatureReq.proto b/proto/SetPlayerSignatureReq.proto index dd1f5e8bd..5e006a60f 100755 --- a/proto/SetPlayerSignatureReq.proto +++ b/proto/SetPlayerSignatureReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4097 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetPlayerSignatureReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4036; - } - - string signature = 1; + string signature = 15; } diff --git a/proto/SetPlayerSignatureRsp.proto b/proto/SetPlayerSignatureRsp.proto index b225cec4c..268760e72 100755 --- a/proto/SetPlayerSignatureRsp.proto +++ b/proto/SetPlayerSignatureRsp.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4098 +// EnetChannelId: 0 +// EnetIsReliable: true message SetPlayerSignatureRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4019; - } - - int32 retcode = 1; - string signature = 2; + int32 retcode = 14; + string signature = 6; } diff --git a/proto/SetUpAvatarTeamReq.proto b/proto/SetUpAvatarTeamReq.proto index 3c2db15d2..418c3a2eb 100755 --- a/proto/SetUpAvatarTeamReq.proto +++ b/proto/SetUpAvatarTeamReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1753 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message SetUpAvatarTeamReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1653; - } - - uint32 team_id = 1; - repeated uint64 avatar_team_guid_list = 2; - uint64 cur_avatar_guid = 3; + uint32 team_id = 10; + repeated uint64 avatar_team_guid_list = 1; + uint64 cur_avatar_guid = 2; } diff --git a/proto/SetUpAvatarTeamRsp.proto b/proto/SetUpAvatarTeamRsp.proto index dbcc81d63..bdba9900d 100755 --- a/proto/SetUpAvatarTeamRsp.proto +++ b/proto/SetUpAvatarTeamRsp.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1664 +// EnetChannelId: 0 +// EnetIsReliable: true message SetUpAvatarTeamRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1744; - } - - int32 retcode = 1; - uint32 team_id = 2; - repeated uint64 avatar_team_guid_list = 3; - uint64 cur_avatar_guid = 4; + int32 retcode = 2; + uint32 team_id = 5; + repeated uint64 avatar_team_guid_list = 12; + uint64 cur_avatar_guid = 3; } diff --git a/proto/SetUpLunchBoxWidgetReq.proto b/proto/SetUpLunchBoxWidgetReq.proto new file mode 100644 index 000000000..e6f4b4f89 --- /dev/null +++ b/proto/SetUpLunchBoxWidgetReq.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "LunchBoxData.proto"; + +// CmdId: 4297 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message SetUpLunchBoxWidgetReq { + LunchBoxData lunch_box_data = 12; +} diff --git a/proto/SetUpLunchBoxWidgetRsp.proto b/proto/SetUpLunchBoxWidgetRsp.proto new file mode 100644 index 000000000..d58ecb56f --- /dev/null +++ b/proto/SetUpLunchBoxWidgetRsp.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "LunchBoxData.proto"; + +// CmdId: 4266 +// EnetChannelId: 0 +// EnetIsReliable: true +message SetUpLunchBoxWidgetRsp { + int32 retcode = 9; + LunchBoxData lunch_box_data = 3; +} diff --git a/proto/SetWidgetSlotReq.proto b/proto/SetWidgetSlotReq.proto new file mode 100644 index 000000000..72ce5a0d8 --- /dev/null +++ b/proto/SetWidgetSlotReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotOp.proto"; +import "WidgetSlotTag.proto"; + +// CmdId: 4269 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message SetWidgetSlotReq { + WidgetSlotOp op = 4; + repeated WidgetSlotTag tag_list = 11; + uint32 material_id = 9; +} diff --git a/proto/SetWidgetSlotRsp.proto b/proto/SetWidgetSlotRsp.proto new file mode 100644 index 000000000..821729c1d --- /dev/null +++ b/proto/SetWidgetSlotRsp.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotOp.proto"; +import "WidgetSlotTag.proto"; + +// CmdId: 4260 +// EnetChannelId: 0 +// EnetIsReliable: true +message SetWidgetSlotRsp { + int32 retcode = 7; + WidgetSlotOp op = 14; + repeated WidgetSlotTag tag_list = 4; + uint32 material_id = 9; +} diff --git a/proto/Shop.proto b/proto/Shop.proto index a5b9ad6e5..1b9cc4b56 100755 --- a/proto/Shop.proto +++ b/proto/Shop.proto @@ -2,10 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "ShopGoods.proto"; -import "ShopMcoinProduct.proto"; import "ShopCardProduct.proto"; import "ShopConcertProduct.proto"; +import "ShopGoods.proto"; +import "ShopMcoinProduct.proto"; message Shop { uint32 shop_type = 1; diff --git a/proto/ShopCardProduct.proto b/proto/ShopCardProduct.proto index 45971007a..c583fbc95 100755 --- a/proto/ShopCardProduct.proto +++ b/proto/ShopCardProduct.proto @@ -5,14 +5,6 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; message ShopCardProduct { - message ResinCard { - repeated ItemParam base_item_list = 1; - repeated ItemParam per_day_item_list = 2; - } - - oneof ExtraCardData { - ResinCard resin_card = 101; - } string product_id = 1; string price_tier = 2; uint32 mcoin_base = 3; @@ -20,4 +12,12 @@ message ShopCardProduct { uint32 days = 5; uint32 remain_reward_days = 6; uint32 card_product_type = 7; + oneof extra_card_data { + ResinCard resin_card = 101; + } + + message ResinCard { + repeated ItemParam base_item_list = 1; + repeated ItemParam per_day_item_list = 2; + } } diff --git a/proto/ShopMcoinProduct.proto b/proto/ShopMcoinProduct.proto index 3962ad173..e4ab50860 100755 --- a/proto/ShopMcoinProduct.proto +++ b/proto/ShopMcoinProduct.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ShopMcoinProduct { string product_id = 1; string price_tier = 2; diff --git a/proto/ShortAbilityHashPair.proto b/proto/ShortAbilityHashPair.proto index ec02252ae..5272cc29d 100755 --- a/proto/ShortAbilityHashPair.proto +++ b/proto/ShortAbilityHashPair.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message ShortAbilityHashPair { int32 ability_name_hash = 1; int32 ability_config_hash = 2; diff --git a/proto/ShowAvatarInfo.proto b/proto/ShowAvatarInfo.proto index 61be51d80..b6188c415 100644 --- a/proto/ShowAvatarInfo.proto +++ b/proto/ShowAvatarInfo.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "AvatarFetterInfo.proto"; import "AvatarExcelInfo.proto"; +import "AvatarFetterInfo.proto"; import "PropValue.proto"; import "ShowEquip.proto"; diff --git a/proto/ShowEquip.proto b/proto/ShowEquip.proto index a35882de1..29807b7a1 100644 --- a/proto/ShowEquip.proto +++ b/proto/ShowEquip.proto @@ -6,9 +6,9 @@ import "Reliquary.proto"; import "Weapon.proto"; message ShowEquip { - oneof Detail { + uint32 item_id = 1; + oneof detail { Reliquary reliquary = 2; Weapon weapon = 3; } - uint32 item_id = 1; } diff --git a/proto/SocialDetail.proto b/proto/SocialDetail.proto index 0d8752c92..875ac7eda 100755 --- a/proto/SocialDetail.proto +++ b/proto/SocialDetail.proto @@ -3,8 +3,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "Birthday.proto"; -import "FriendOnlineState.proto"; import "FriendEnterHomeOption.proto"; +import "FriendOnlineState.proto"; import "ProfilePicture.proto"; import "SocialShowAvatarInfo.proto"; diff --git a/proto/SocialShowAvatarInfo.proto b/proto/SocialShowAvatarInfo.proto index c682d366c..6e69bb8e6 100755 --- a/proto/SocialShowAvatarInfo.proto +++ b/proto/SocialShowAvatarInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message SocialShowAvatarInfo { uint32 avatar_id = 1; uint32 level = 2; diff --git a/proto/StoreItemChangeNotify.proto b/proto/StoreItemChangeNotify.proto index c76d0ef7f..5644b71f2 100755 --- a/proto/StoreItemChangeNotify.proto +++ b/proto/StoreItemChangeNotify.proto @@ -2,18 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "StoreType.proto"; import "Item.proto"; +import "StoreType.proto"; +// CmdId: 641 +// EnetChannelId: 0 +// EnetIsReliable: true message StoreItemChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 689; - } - - StoreType store_type = 1; - repeated Item item_list = 2; + StoreType store_type = 9; + repeated Item item_list = 3; } diff --git a/proto/StoreItemDelNotify.proto b/proto/StoreItemDelNotify.proto index bf9f23267..40af0508a 100755 --- a/proto/StoreItemDelNotify.proto +++ b/proto/StoreItemDelNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "StoreType.proto"; +// CmdId: 637 +// EnetChannelId: 0 +// EnetIsReliable: true message StoreItemDelNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 684; - } - - StoreType store_type = 1; - repeated uint64 guid_list = 2; + StoreType store_type = 14; + repeated uint64 guid_list = 10; } diff --git a/proto/StoreType.proto b/proto/StoreType.proto index 91163c522..291085159 100755 --- a/proto/StoreType.proto +++ b/proto/StoreType.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum StoreType { - STORE_NONE = 0; - STORE_PACK = 1; - STORE_DEPOT = 2; + STORE_TYPE_NONE = 0; + STORE_TYPE_PACK = 1; + STORE_TYPE_DEPOT = 2; } diff --git a/proto/StoreWeightLimitNotify.proto b/proto/StoreWeightLimitNotify.proto index 24e58560e..097f6ee0b 100755 --- a/proto/StoreWeightLimitNotify.proto +++ b/proto/StoreWeightLimitNotify.proto @@ -4,19 +4,14 @@ option java_package = "emu.grasscutter.net.proto"; import "StoreType.proto"; +// CmdId: 631 +// EnetChannelId: 0 +// EnetIsReliable: true message StoreWeightLimitNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 618; - } - - StoreType store_type = 1; - uint32 weight_limit = 3; - uint32 material_count_limit = 4; + StoreType store_type = 4; + uint32 weight_limit = 2; + uint32 material_count_limit = 1; uint32 weapon_count_limit = 5; uint32 reliquary_count_limit = 6; - uint32 furniture_count_limit = 7; + uint32 furniture_count_limit = 8; } diff --git a/proto/SyncScenePlayTeamEntityNotify.proto b/proto/SyncScenePlayTeamEntityNotify.proto index e14237da3..5e48cb64a 100755 --- a/proto/SyncScenePlayTeamEntityNotify.proto +++ b/proto/SyncScenePlayTeamEntityNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayTeamEntityInfo.proto"; +// CmdId: 3096 +// EnetChannelId: 0 +// EnetIsReliable: true message SyncScenePlayTeamEntityNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 3375; - } - - uint32 scene_id = 1; + uint32 scene_id = 13; repeated PlayTeamEntityInfo entity_info_list = 2; } diff --git a/proto/SyncTeamEntityNotify.proto b/proto/SyncTeamEntityNotify.proto index e41525177..ca32092b7 100755 --- a/proto/SyncTeamEntityNotify.proto +++ b/proto/SyncTeamEntityNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "TeamEntityInfo.proto"; +// CmdId: 334 +// EnetChannelId: 0 +// EnetIsReliable: true message SyncTeamEntityNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 308; - } - - uint32 scene_id = 1; + uint32 scene_id = 13; repeated TeamEntityInfo team_entity_info_list = 2; } diff --git a/proto/TakeAchievementRewardReq.proto b/proto/TakeAchievementRewardReq.proto index 64ac2d3ae..1534895bb 100644 --- a/proto/TakeAchievementRewardReq.proto +++ b/proto/TakeAchievementRewardReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "AchievementInfo.proto"; +// CmdId: 2693 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TakeAchievementRewardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 2677; - } - - repeated AchievementInfo a_list = 1; + repeated uint32 id_list = 2; } diff --git a/proto/TakePlayerLevelRewardReq.proto b/proto/TakePlayerLevelRewardReq.proto index fbaa3c1bf..e5483d662 100755 --- a/proto/TakePlayerLevelRewardReq.proto +++ b/proto/TakePlayerLevelRewardReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 160 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TakePlayerLevelRewardReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 173; - } - - uint32 level = 1; + uint32 level = 5; } diff --git a/proto/TakePlayerLevelRewardRsp.proto b/proto/TakePlayerLevelRewardRsp.proto index ec1944c28..d6afc7f55 100755 --- a/proto/TakePlayerLevelRewardRsp.proto +++ b/proto/TakePlayerLevelRewardRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 177 +// EnetChannelId: 0 +// EnetIsReliable: true message TakePlayerLevelRewardRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 102; - } - - int32 retcode = 1; - uint32 level = 2; - uint32 reward_id = 3; + int32 retcode = 14; + uint32 level = 13; + uint32 reward_id = 12; } diff --git a/proto/TakeoffEquipReq.proto b/proto/TakeoffEquipReq.proto index e956faeec..3275c5feb 100755 --- a/proto/TakeoffEquipReq.proto +++ b/proto/TakeoffEquipReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 698 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TakeoffEquipReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 619; - } - - uint64 avatar_guid = 1; - uint32 slot = 2; + uint64 avatar_guid = 15; + uint32 slot = 9; } diff --git a/proto/TakeoffEquipRsp.proto b/proto/TakeoffEquipRsp.proto index db6dcedae..834a6fe35 100755 --- a/proto/TakeoffEquipRsp.proto +++ b/proto/TakeoffEquipRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 645 +// EnetChannelId: 0 +// EnetIsReliable: true message TakeoffEquipRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 614; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 slot = 3; + int32 retcode = 8; + uint64 avatar_guid = 3; + uint32 slot = 4; } diff --git a/proto/TeamEnterSceneInfo.proto b/proto/TeamEnterSceneInfo.proto index b6adbe8ca..3d26987b2 100755 --- a/proto/TeamEnterSceneInfo.proto +++ b/proto/TeamEnterSceneInfo.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "AbilitySyncStateInfo.proto"; import "AbilityControlBlock.proto"; +import "AbilitySyncStateInfo.proto"; message TeamEnterSceneInfo { uint32 team_entity_id = 1; diff --git a/proto/TeamResonanceChangeNotify.proto b/proto/TeamResonanceChangeNotify.proto index fe8e8b4e0..fbebbed84 100755 --- a/proto/TeamResonanceChangeNotify.proto +++ b/proto/TeamResonanceChangeNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "AvatarTeamResonanceInfo.proto"; +// CmdId: 1045 +// EnetChannelId: 0 +// EnetIsReliable: true message TeamResonanceChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1014; - } - - repeated AvatarTeamResonanceInfo info_list = 1; + repeated AvatarTeamResonanceInfo info_list = 15; } diff --git a/proto/TowerAllDataRsp.proto b/proto/TowerAllDataRsp.proto index e99d62873..414084f6f 100755 --- a/proto/TowerAllDataRsp.proto +++ b/proto/TowerAllDataRsp.proto @@ -3,33 +3,28 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; import "TowerCurLevelRecord.proto"; -import "TowerMonthlyBrief.proto"; import "TowerFloorRecord.proto"; +import "TowerMonthlyBrief.proto"; +// CmdId: 2449 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerAllDataRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2461; - } - - uint32 tower_schedule_id = 1; - repeated TowerFloorRecord tower_floor_record_list = 2; - uint32 daily_floor_id = 3; - uint32 daily_level_index = 4; - TowerCurLevelRecord cur_level_record = 5; - uint32 next_schedule_change_time = 6; - map floor_open_time_map = 7; - bool is_first_interact = 8; - TowerMonthlyBrief monthly_brief = 9; - uint32 skip_to_floor_index = 10; - uint32 commemorative_reward_id = 11; - map skip_floor_granted_reward_item_map = 12; - uint32 valid_tower_record_num = 13; - int32 retcode = 14; - bool is_finished_entrance_floor = 15; - uint32 schedule_start_time = 16; - TowerMonthlyBrief last_schedule_monthly_brief = 17; + uint32 tower_schedule_id = 13; + repeated TowerFloorRecord tower_floor_record_list = 12; + uint32 daily_floor_id = 9; + uint32 daily_level_index = 6; + TowerCurLevelRecord cur_level_record = 2; + uint32 next_schedule_change_time = 8; + map floor_open_time_map = 11; + bool is_first_interact = 14; + TowerMonthlyBrief monthly_brief = 1; + uint32 skip_to_floor_index = 3; + uint32 commemorative_reward_id = 15; + map skip_floor_granted_reward_item_map = 5; + uint32 valid_tower_record_num = 10; + int32 retcode = 4; + bool is_finished_entrance_floor = 7; + uint32 schedule_start_time = 490; + TowerMonthlyBrief last_schedule_monthly_brief = 395; } diff --git a/proto/TowerBuffSelectReq.proto b/proto/TowerBuffSelectReq.proto index 1641b350a..3ecd69847 100644 --- a/proto/TowerBuffSelectReq.proto +++ b/proto/TowerBuffSelectReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 2407 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TowerBuffSelectReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 2424; - } - - uint32 tower_buff_id = 1; + uint32 tower_buff_id = 2; } diff --git a/proto/TowerBuffSelectRsp.proto b/proto/TowerBuffSelectRsp.proto index 7a32a8e1e..a2f6e4b71 100644 --- a/proto/TowerBuffSelectRsp.proto +++ b/proto/TowerBuffSelectRsp.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 2430 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerBuffSelectRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2491; - } - - int32 retcode = 1; - uint32 tower_buff_id = 2; + int32 retcode = 15; + uint32 tower_buff_id = 6; } diff --git a/proto/TowerCurLevelRecord.proto b/proto/TowerCurLevelRecord.proto index bfd4a84a6..42b3701bc 100755 --- a/proto/TowerCurLevelRecord.proto +++ b/proto/TowerCurLevelRecord.proto @@ -10,4 +10,5 @@ message TowerCurLevelRecord { repeated TowerTeam tower_team_list = 3; repeated uint32 buff_id_list = 4; bool is_empty = 5; + bool MPLIGMAKFAM = 6; } diff --git a/proto/TowerCurLevelRecordChangeNotify.proto b/proto/TowerCurLevelRecordChangeNotify.proto index fd9f94c97..997ec674f 100644 --- a/proto/TowerCurLevelRecordChangeNotify.proto +++ b/proto/TowerCurLevelRecordChangeNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "TowerCurLevelRecord.proto"; +// CmdId: 2441 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerCurLevelRecordChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2489; - } - - TowerCurLevelRecord cur_level_record = 1; + TowerCurLevelRecord cur_level_record = 10; } diff --git a/proto/TowerEnterLevelReq.proto b/proto/TowerEnterLevelReq.proto index 551f47729..8334a01eb 100644 --- a/proto/TowerEnterLevelReq.proto +++ b/proto/TowerEnterLevelReq.proto @@ -2,15 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 2455 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TowerEnterLevelReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 2412; - } - - uint32 enter_point_id = 1; + uint32 enter_point_id = 4; } diff --git a/proto/TowerEnterLevelRsp.proto b/proto/TowerEnterLevelRsp.proto index fbcc4067f..255e2efea 100644 --- a/proto/TowerEnterLevelRsp.proto +++ b/proto/TowerEnterLevelRsp.proto @@ -2,17 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 2427 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerEnterLevelRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2426; - } - - int32 retcode = 1; - uint32 floor_id = 2; - uint32 level_index = 3; - repeated uint32 tower_buff_id_list = 4; + int32 retcode = 14; + uint32 floor_id = 6; + uint32 level_index = 8; + repeated uint32 tower_buff_id_list = 7; } diff --git a/proto/TowerFloorRecordChangeNotify.proto b/proto/TowerFloorRecordChangeNotify.proto index 74a7135ec..9d8d600da 100644 --- a/proto/TowerFloorRecordChangeNotify.proto +++ b/proto/TowerFloorRecordChangeNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "TowerFloorRecord.proto"; +// CmdId: 2431 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerFloorRecordChangeNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2418; - } - - repeated TowerFloorRecord tower_floor_record_list = 1; - bool is_finished_entrance_floor = 2; + repeated TowerFloorRecord tower_floor_record_list = 9; + bool is_finished_entrance_floor = 1; } diff --git a/proto/TowerLevelEndNotify.proto b/proto/TowerLevelEndNotify.proto index d9f2da543..36db9969b 100644 --- a/proto/TowerLevelEndNotify.proto +++ b/proto/TowerLevelEndNotify.proto @@ -1,26 +1,22 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; + import "ItemParam.proto"; +// CmdId: 2442 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerLevelEndNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2456; - } + bool is_success = 14; + repeated uint32 finished_star_cond_list = 1; + repeated ItemParam reward_item_list = 9; + uint32 continue_state = 2; + uint32 next_floor_id = 8; enum ContinueStateType { - CONTINUE_STATE_CAN_NOT_CONTINUE = 0; - CONTINUE_STATE_CAN_ENTER_NEXT_LEVEL = 1; - CONTINUE_STATE_CAN_ENTER_NEXT_FLOOR = 2; + CONTINUE_STATE_TYPE_CAN_NOT_CONTINUE = 0; + CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_LEVEL = 1; + CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_FLOOR = 2; } - - bool is_success = 1; - repeated uint32 finished_star_cond_list = 2; - repeated ItemParam reward_item_list = 3; - uint32 continue_state = 4; - uint32 next_floor_id = 5; } diff --git a/proto/TowerLevelRecord.proto b/proto/TowerLevelRecord.proto index 30dbed4bd..9546f072f 100755 --- a/proto/TowerLevelRecord.proto +++ b/proto/TowerLevelRecord.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message TowerLevelRecord { uint32 level_id = 1; repeated uint32 satisfied_cond_list = 2; diff --git a/proto/TowerLevelStarCondData.proto b/proto/TowerLevelStarCondData.proto index d46334422..d2fb51a8b 100644 --- a/proto/TowerLevelStarCondData.proto +++ b/proto/TowerLevelStarCondData.proto @@ -6,4 +6,5 @@ message TowerLevelStarCondData { uint32 star_cond_index = 3; uint32 cond_value = 4; bool is_pause = 5; + bool OAFMGGMJPIL = 6; } diff --git a/proto/TowerLevelStarCondNotify.proto b/proto/TowerLevelStarCondNotify.proto index e605496fb..a0b9b14cc 100644 --- a/proto/TowerLevelStarCondNotify.proto +++ b/proto/TowerLevelStarCondNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "TowerLevelStarCondData.proto"; +// CmdId: 2401 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerLevelStarCondNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2492; - } - - uint32 floor_id = 1; - uint32 level_index = 2; - repeated TowerLevelStarCondData cond_data_list = 3; + uint32 floor_id = 3; + uint32 level_index = 6; + repeated TowerLevelStarCondData cond_data_list = 12; } diff --git a/proto/TowerMiddleLevelChangeTeamNotify.proto b/proto/TowerMiddleLevelChangeTeamNotify.proto new file mode 100644 index 000000000..21ff9f380 --- /dev/null +++ b/proto/TowerMiddleLevelChangeTeamNotify.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 2411 +// EnetChannelId: 0 +// EnetIsReliable: true +message TowerMiddleLevelChangeTeamNotify { +} diff --git a/proto/TowerMonthlyBrief.proto b/proto/TowerMonthlyBrief.proto index fecf3aebb..bc3b48ccc 100755 --- a/proto/TowerMonthlyBrief.proto +++ b/proto/TowerMonthlyBrief.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message TowerMonthlyBrief { uint32 tower_schedule_id = 1; uint32 best_floor_index = 2; diff --git a/proto/TowerTeam.proto b/proto/TowerTeam.proto index 374c59313..295b403b6 100755 --- a/proto/TowerTeam.proto +++ b/proto/TowerTeam.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message TowerTeam { uint32 tower_team_id = 1; repeated uint64 avatar_guid_list = 2; diff --git a/proto/TowerTeamSelectReq.proto b/proto/TowerTeamSelectReq.proto index 903968061..1f9fd18ee 100644 --- a/proto/TowerTeamSelectReq.proto +++ b/proto/TowerTeamSelectReq.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "TowerTeam.proto"; +// CmdId: 2417 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message TowerTeamSelectReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 2401; - } - - uint32 floor_id = 1; + uint32 floor_id = 15; repeated TowerTeam tower_team_list = 2; } diff --git a/proto/TowerTeamSelectRsp.proto b/proto/TowerTeamSelectRsp.proto index b135e5364..3bfab9df5 100644 --- a/proto/TowerTeamSelectRsp.proto +++ b/proto/TowerTeamSelectRsp.proto @@ -2,14 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 2485 +// EnetChannelId: 0 +// EnetIsReliable: true message TowerTeamSelectRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 2494; - } - int32 retcode = 1; } diff --git a/proto/TrackingIOInfo.proto b/proto/TrackingIOInfo.proto index 976185e84..b5ddcd551 100755 --- a/proto/TrackingIOInfo.proto +++ b/proto/TrackingIOInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message TrackingIOInfo { string appid = 1; string deviceid = 2; diff --git a/proto/TrialAvatarFirstPassDungeonNotify.proto b/proto/TrialAvatarFirstPassDungeonNotify.proto new file mode 100644 index 000000000..ba873752a --- /dev/null +++ b/proto/TrialAvatarFirstPassDungeonNotify.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 2137 +// EnetChannelId: 0 +// EnetIsReliable: true +message TrialAvatarFirstPassDungeonNotify { + uint32 trial_avatar_index_id = 2; +} diff --git a/proto/TrialAvatarGrantRecord.proto b/proto/TrialAvatarGrantRecord.proto index fbfe446cc..dad252e1d 100755 --- a/proto/TrialAvatarGrantRecord.proto +++ b/proto/TrialAvatarGrantRecord.proto @@ -2,17 +2,19 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message TrialAvatarGrantRecord { - enum GrantReason { - INVALID = 0; - GRANT_BY_QUEST = 1; - GRANT_BY_TRIAL_AVATAR_ACTIVITY = 2; - GRANT_BY_DUNGEON_ELEMENT_CHALLENGE = 3; - GRANT_BY_MIST_TRIAL_ACTIVITY = 4; - GRANT_BY_SUMO_ACTIVITY = 5; - } - uint32 grant_reason = 1; uint32 from_parent_quest_id = 2; + + enum GrantReason { + GRANT_REASON_INVALID = 0; + GRANT_REASON_BY_QUEST = 1; + GRANT_REASON_BY_TRIAL_AVATAR_ACTIVITY = 2; + GRANT_REASON_BY_DUNGEON_ELEMENT_CHALLENGE = 3; + GRANT_REASON_BY_MIST_TRIAL_ACTIVITY = 4; + GRANT_REASON_BY_SUMO_ACTIVITY = 5; + GRANT_REASON_ELPMDIEIOHP = 6; + GRANT_REASON_FALPDBLGHJB = 7; + GRANT_REASON_GAMADMGGMBC = 8; + } } diff --git a/proto/TrialAvatarInfo.proto b/proto/TrialAvatarInfo.proto index d72fec872..1c17e9040 100755 --- a/proto/TrialAvatarInfo.proto +++ b/proto/TrialAvatarInfo.proto @@ -2,8 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -import "TrialAvatarGrantRecord.proto"; import "Item.proto"; +import "TrialAvatarGrantRecord.proto"; message TrialAvatarInfo { uint32 trial_avatar_id = 1; diff --git a/proto/TryEnterHomeReq.proto b/proto/TryEnterHomeReq.proto new file mode 100644 index 000000000..d1563a13b --- /dev/null +++ b/proto/TryEnterHomeReq.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4553 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message TryEnterHomeReq { + uint32 target_uid = 10; + uint32 target_point = 13; +} diff --git a/proto/TryEnterHomeRsp.proto b/proto/TryEnterHomeRsp.proto new file mode 100644 index 000000000..74da867c3 --- /dev/null +++ b/proto/TryEnterHomeRsp.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4610 +// EnetChannelId: 0 +// EnetIsReliable: true +message TryEnterHomeRsp { + int32 retcode = 12; + uint32 target_uid = 2; + repeated uint32 param_list = 11; +} diff --git a/proto/UnionCmd.proto b/proto/UnionCmd.proto index 5483633b0..7d7adea1e 100755 --- a/proto/UnionCmd.proto +++ b/proto/UnionCmd.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message UnionCmd { uint32 message_id = 1; bytes body = 2; diff --git a/proto/UnionCmdNotify.proto b/proto/UnionCmdNotify.proto index 6dc0437bd..0f10f1fc4 100755 --- a/proto/UnionCmdNotify.proto +++ b/proto/UnionCmdNotify.proto @@ -4,15 +4,10 @@ option java_package = "emu.grasscutter.net.proto"; import "UnionCmd.proto"; +// CmdId: 98 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message UnionCmdNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 19; - } - - repeated UnionCmd cmd_list = 1; + repeated UnionCmd cmd_list = 13; } diff --git a/proto/UnlockAvatarTalentReq.proto b/proto/UnlockAvatarTalentReq.proto index b7dd1bed6..8eb49c973 100755 --- a/proto/UnlockAvatarTalentReq.proto +++ b/proto/UnlockAvatarTalentReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1009 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message UnlockAvatarTalentReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 1049; - } - - uint64 avatar_guid = 1; - uint32 talent_id = 2; + uint64 avatar_guid = 13; + uint32 talent_id = 9; } diff --git a/proto/UnlockAvatarTalentRsp.proto b/proto/UnlockAvatarTalentRsp.proto index 5bbfe4150..81cd6f02c 100755 --- a/proto/UnlockAvatarTalentRsp.proto +++ b/proto/UnlockAvatarTalentRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 1031 +// EnetChannelId: 0 +// EnetIsReliable: true message UnlockAvatarTalentRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 1018; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint32 talent_id = 3; + int32 retcode = 2; + uint64 avatar_guid = 14; + uint32 talent_id = 12; } diff --git a/proto/UnlockNameCardNotify.proto b/proto/UnlockNameCardNotify.proto index d423d6fac..e8475c0da 100755 --- a/proto/UnlockNameCardNotify.proto +++ b/proto/UnlockNameCardNotify.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 4001 +// EnetChannelId: 0 +// EnetIsReliable: true message UnlockNameCardNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4092; - } - - uint32 name_card_id = 1; + uint32 name_card_id = 14; } diff --git a/proto/UpdatePlayerShowAvatarListReq.proto b/proto/UpdatePlayerShowAvatarListReq.proto index 199ed2059..0f82b78e5 100644 --- a/proto/UpdatePlayerShowAvatarListReq.proto +++ b/proto/UpdatePlayerShowAvatarListReq.proto @@ -1,17 +1,12 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -message UpdatePlayerShowAvatarListReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 4093; - } - - repeated uint32 show_avatar_id_list = 1; - bool is_show_avatar = 2; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4025 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message UpdatePlayerShowAvatarListReq { + repeated uint32 show_avatar_id_list = 13; + bool is_show_avatar = 2; +} diff --git a/proto/UpdatePlayerShowAvatarListRsp.proto b/proto/UpdatePlayerShowAvatarListRsp.proto index edb7cf323..20d9f0f19 100644 --- a/proto/UpdatePlayerShowAvatarListRsp.proto +++ b/proto/UpdatePlayerShowAvatarListRsp.proto @@ -1,17 +1,12 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -message UpdatePlayerShowAvatarListRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 4053; - } - - int32 retcode = 1; - repeated uint32 show_avatar_id_list = 2; - bool is_show_avatar = 3; -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4083 +// EnetChannelId: 0 +// EnetIsReliable: true +message UpdatePlayerShowAvatarListRsp { + int32 retcode = 2; + repeated uint32 show_avatar_id_list = 1; + bool is_show_avatar = 8; +} diff --git a/proto/UseItemReq.proto b/proto/UseItemReq.proto index 27ab74830..52754385b 100755 --- a/proto/UseItemReq.proto +++ b/proto/UseItemReq.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 635 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message UseItemReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 642; - } - uint64 guid = 1; - uint32 count = 2; - uint64 target_guid = 3; - uint32 option_idx = 4; - bool is_enter_mp_dungeon_team = 5; + uint32 count = 12; + uint64 target_guid = 14; + uint32 option_idx = 10; + bool is_enter_mp_dungeon_team = 3; } diff --git a/proto/UseItemRsp.proto b/proto/UseItemRsp.proto index de693da2c..9a9b34b6f 100755 --- a/proto/UseItemRsp.proto +++ b/proto/UseItemRsp.proto @@ -2,19 +2,13 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 649 +// EnetChannelId: 0 +// EnetIsReliable: true message UseItemRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 661; - } - - int32 retcode = 1; - uint64 guid = 2; - uint32 item_id = 3; - uint64 target_guid = 4; - uint32 option_idx = 5; + int32 retcode = 15; + uint64 guid = 8; + uint32 item_id = 11; + uint64 target_guid = 12; + uint32 option_idx = 13; } diff --git a/proto/UseWidgetCreateGadgetReq.proto b/proto/UseWidgetCreateGadgetReq.proto new file mode 100644 index 000000000..a8a7732c7 --- /dev/null +++ b/proto/UseWidgetCreateGadgetReq.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +// CmdId: 4283 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message UseWidgetCreateGadgetReq { + uint32 material_id = 1; + Vector pos = 10; + Vector rot = 4; +} diff --git a/proto/UseWidgetCreateGadgetRsp.proto b/proto/UseWidgetCreateGadgetRsp.proto new file mode 100644 index 000000000..50c66b51b --- /dev/null +++ b/proto/UseWidgetCreateGadgetRsp.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4279 +// EnetChannelId: 0 +// EnetIsReliable: true +message UseWidgetCreateGadgetRsp { + int32 retcode = 13; + uint32 material_id = 2; +} diff --git a/proto/UseWidgetRetractGadgetReq.proto b/proto/UseWidgetRetractGadgetReq.proto new file mode 100644 index 000000000..3bcc7cec7 --- /dev/null +++ b/proto/UseWidgetRetractGadgetReq.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4290 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message UseWidgetRetractGadgetReq { + uint32 entity_id = 7; +} diff --git a/proto/UseWidgetRetractGadgetRsp.proto b/proto/UseWidgetRetractGadgetRsp.proto new file mode 100644 index 000000000..a64cf7677 --- /dev/null +++ b/proto/UseWidgetRetractGadgetRsp.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4271 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message UseWidgetRetractGadgetRsp { + int32 retcode = 9; + uint32 entity_id = 15; +} diff --git a/proto/Vector.proto b/proto/Vector.proto index 0c0554276..562e7436a 100755 --- a/proto/Vector.proto +++ b/proto/Vector.proto @@ -2,9 +2,8 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message Vector { - float X = 1; - float Y = 2; - float Z = 3; + float x = 1; + float y = 2; + float z = 3; } diff --git a/proto/VehicleInteractReq.proto b/proto/VehicleInteractReq.proto index c94bfcf65..fdbb5b859 100644 --- a/proto/VehicleInteractReq.proto +++ b/proto/VehicleInteractReq.proto @@ -4,8 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "VehicleInteractType.proto"; +// CmdId: 838 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message VehicleInteractReq { - uint32 entity_id = 1; - VehicleInteractType interact_type = 2; - uint32 pos = 3; + uint32 entity_id = 8; + VehicleInteractType interact_type = 3; + uint32 pos = 10; } diff --git a/proto/VehicleInteractRsp.proto b/proto/VehicleInteractRsp.proto index 62c3a040c..a8107fbd5 100644 --- a/proto/VehicleInteractRsp.proto +++ b/proto/VehicleInteractRsp.proto @@ -5,9 +5,12 @@ option java_package = "emu.grasscutter.net.proto"; import "VehicleInteractType.proto"; import "VehicleMember.proto"; +// CmdId: 806 +// EnetChannelId: 0 +// EnetIsReliable: true message VehicleInteractRsp { - int32 retcode = 1; - uint32 entity_id = 2; + int32 retcode = 15; + uint32 entity_id = 14; VehicleInteractType interact_type = 3; - VehicleMember member = 4; + VehicleMember member = 1; } diff --git a/proto/VehicleInteractType.proto b/proto/VehicleInteractType.proto index f7e10b6fd..d2e1b3106 100644 --- a/proto/VehicleInteractType.proto +++ b/proto/VehicleInteractType.proto @@ -3,7 +3,7 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum VehicleInteractType { - VEHICLE_INTERACT_NONE = 0; - VEHICLE_INTERACT_IN = 1; - VEHICLE_INTERACT_OUT = 2; + VEHICLE_INTERACT_TYPE_NONE = 0; + VEHICLE_INTERACT_TYPE_IN = 1; + VEHICLE_INTERACT_TYPE_OUT = 2; } diff --git a/proto/VehicleSpawnReq.proto b/proto/VehicleSpawnReq.proto deleted file mode 100644 index aa4e74c74..000000000 --- a/proto/VehicleSpawnReq.proto +++ /dev/null @@ -1,12 +0,0 @@ -syntax = "proto3"; - -option java_package = "emu.grasscutter.net.proto"; - -import "Vector.proto"; - -message VehicleSpawnReq { - uint32 vehicleId = 1; - uint32 pointId = 2; - Vector pos = 3; - Vector rot = 4; -} diff --git a/proto/VehicleStaminaNotify.proto b/proto/VehicleStaminaNotify.proto index 390174f4c..140efb80c 100644 --- a/proto/VehicleStaminaNotify.proto +++ b/proto/VehicleStaminaNotify.proto @@ -2,7 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 811 +// EnetChannelId: 0 +// EnetIsReliable: true message VehicleStaminaNotify { - uint32 entity_id = 1; - float cur_stamina = 2; + uint32 entity_id = 8; + float cur_stamina = 4; } diff --git a/proto/VisionType.proto b/proto/VisionType.proto index 444584c12..fc2a6a39d 100755 --- a/proto/VisionType.proto +++ b/proto/VisionType.proto @@ -3,23 +3,24 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; enum VisionType { - VISION_NONE = 0; - VISION_MEET = 1; - VISION_REBORN = 2; - VISION_REPLACE = 3; - VISION_WAYPOINT_REBORN = 4; - VISION_MISS = 5; - VISION_DIE = 6; - VISION_GATHER_ESCAPE = 7; - VISION_REFRESH = 8; - VISION_TRANSPORT = 9; - VISION_REPLACE_DIE = 10; - VISION_REPLACE_NO_NOTIFY = 11; - VISION_BORN = 12; - VISION_PICKUP = 13; - VISION_REMOVE = 14; - VISION_CHANGE_COSTUME = 15; - VISION_FISH_REFRESH = 16; - VISION_FISH_BIG_SHOCK = 17; - VISION_FISH_QTE_SUCC = 18; + VISION_TYPE_NONE = 0; + VISION_TYPE_MEET = 1; + VISION_TYPE_REBORN = 2; + VISION_TYPE_REPLACE = 3; + VISION_TYPE_WAYPOINT_REBORN = 4; + VISION_TYPE_MISS = 5; + VISION_TYPE_DIE = 6; + VISION_TYPE_GATHER_ESCAPE = 7; + VISION_TYPE_REFRESH = 8; + VISION_TYPE_TRANSPORT = 9; + VISION_TYPE_REPLACE_DIE = 10; + VISION_TYPE_REPLACE_NO_NOTIFY = 11; + VISION_TYPE_BORN = 12; + VISION_TYPE_PICKUP = 13; + VISION_TYPE_REMOVE = 14; + VISION_TYPE_CHANGE_COSTUME = 15; + VISION_TYPE_FISH_REFRESH = 16; + VISION_TYPE_FISH_BIG_SHOCK = 17; + VISION_TYPE_FISH_QTE_SUCC = 18; + VISION_TYPE_EPFKMOIPADB = 19; } diff --git a/proto/Weapon.proto b/proto/Weapon.proto index aedbbf877..a1bb2fe51 100755 --- a/proto/Weapon.proto +++ b/proto/Weapon.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message Weapon { uint32 level = 1; uint32 exp = 2; diff --git a/proto/WeaponAwakenReq.proto b/proto/WeaponAwakenReq.proto index 4a04f457b..86e55c0bb 100755 --- a/proto/WeaponAwakenReq.proto +++ b/proto/WeaponAwakenReq.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 642 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WeaponAwakenReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 656; - } - - uint64 target_weapon_guid = 1; - uint64 item_guid = 2; - map affix_level_map = 3; + uint64 target_weapon_guid = 9; + uint64 item_guid = 3; + map affix_level_map = 2; } diff --git a/proto/WeaponAwakenRsp.proto b/proto/WeaponAwakenRsp.proto index c715044f9..4184bd49b 100755 --- a/proto/WeaponAwakenRsp.proto +++ b/proto/WeaponAwakenRsp.proto @@ -2,20 +2,14 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 601 +// EnetChannelId: 0 +// EnetIsReliable: true message WeaponAwakenRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 692; - } - - int32 retcode = 1; - uint64 target_weapon_guid = 2; - uint32 target_weapon_awaken_level = 3; - map old_affix_level_map = 4; - map cur_affix_level_map = 5; - uint64 avatar_guid = 6; + int32 retcode = 3; + uint64 target_weapon_guid = 1; + uint32 target_weapon_awaken_level = 13; + map old_affix_level_map = 7; + map cur_affix_level_map = 14; + uint64 avatar_guid = 10; } diff --git a/proto/WeaponPromoteReq.proto b/proto/WeaponPromoteReq.proto index e7cf1f178..dfdcad6e7 100755 --- a/proto/WeaponPromoteReq.proto +++ b/proto/WeaponPromoteReq.proto @@ -2,16 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 624 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WeaponPromoteReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 647; - } - - uint64 target_weapon_guid = 1; + uint64 target_weapon_guid = 6; } diff --git a/proto/WeaponPromoteRsp.proto b/proto/WeaponPromoteRsp.proto index 6df2aa714..b2f983390 100755 --- a/proto/WeaponPromoteRsp.proto +++ b/proto/WeaponPromoteRsp.proto @@ -2,18 +2,12 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 638 +// EnetChannelId: 0 +// EnetIsReliable: true message WeaponPromoteRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 606; - } - - int32 retcode = 1; - uint64 target_weapon_guid = 2; - uint32 old_promote_level = 3; - uint32 cur_promote_level = 4; + int32 retcode = 11; + uint64 target_weapon_guid = 15; + uint32 old_promote_level = 5; + uint32 cur_promote_level = 2; } diff --git a/proto/WeaponUpgradeReq.proto b/proto/WeaponUpgradeReq.proto index 860f43986..c7f6a8a6e 100755 --- a/proto/WeaponUpgradeReq.proto +++ b/proto/WeaponUpgradeReq.proto @@ -4,17 +4,12 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 686 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WeaponUpgradeReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 670; - } - - uint64 target_weapon_guid = 1; - repeated uint64 food_weapon_guid_list = 2; - repeated ItemParam item_param_list = 3; + uint64 target_weapon_guid = 3; + repeated uint64 food_weapon_guid_list = 8; + repeated ItemParam item_param_list = 14; } diff --git a/proto/WeaponUpgradeRsp.proto b/proto/WeaponUpgradeRsp.proto index e15a82ec7..c85641780 100755 --- a/proto/WeaponUpgradeRsp.proto +++ b/proto/WeaponUpgradeRsp.proto @@ -4,18 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "ItemParam.proto"; +// CmdId: 663 +// EnetChannelId: 0 +// EnetIsReliable: true message WeaponUpgradeRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 632; - } - - int32 retcode = 1; - uint64 target_weapon_guid = 2; - uint32 old_level = 3; - uint32 cur_level = 4; - repeated ItemParam item_param_list = 5; + int32 retcode = 11; + uint64 target_weapon_guid = 8; + uint32 old_level = 4; + uint32 cur_level = 7; + repeated ItemParam item_param_list = 2; } diff --git a/proto/WearEquipReq.proto b/proto/WearEquipReq.proto index d12c5049a..0f5954876 100755 --- a/proto/WearEquipReq.proto +++ b/proto/WearEquipReq.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 630 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WearEquipReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 691; - } - - uint64 avatar_guid = 1; + uint64 avatar_guid = 14; uint64 equip_guid = 2; } diff --git a/proto/WearEquipRsp.proto b/proto/WearEquipRsp.proto index 01760f9fb..3f3c925c8 100755 --- a/proto/WearEquipRsp.proto +++ b/proto/WearEquipRsp.proto @@ -2,17 +2,11 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 697 +// EnetChannelId: 0 +// EnetIsReliable: true message WearEquipRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 636; - } - - int32 retcode = 1; - uint64 avatar_guid = 2; - uint64 equip_guid = 3; + int32 retcode = 6; + uint64 avatar_guid = 10; + uint64 equip_guid = 5; } diff --git a/proto/WeeklyBossResinDiscountInfo.proto b/proto/WeeklyBossResinDiscountInfo.proto index 740fa4d2c..97425694e 100755 --- a/proto/WeeklyBossResinDiscountInfo.proto +++ b/proto/WeeklyBossResinDiscountInfo.proto @@ -2,7 +2,6 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - message WeeklyBossResinDiscountInfo { uint32 discount_num = 1; uint32 discount_num_limit = 2; diff --git a/proto/WidgetActiveChangeNotify.proto b/proto/WidgetActiveChangeNotify.proto new file mode 100644 index 000000000..e91e1f58a --- /dev/null +++ b/proto/WidgetActiveChangeNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotData.proto"; + +// CmdId: 4295 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetActiveChangeNotify { + repeated WidgetSlotData widget_data_list = 4; +} diff --git a/proto/WidgetCameraInfo.proto b/proto/WidgetCameraInfo.proto new file mode 100644 index 000000000..0f8d47423 --- /dev/null +++ b/proto/WidgetCameraInfo.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message WidgetCameraInfo { + uint32 target_entity_id = 1; +} diff --git a/proto/WidgetCoolDownData.proto b/proto/WidgetCoolDownData.proto new file mode 100644 index 000000000..30b9f08ac --- /dev/null +++ b/proto/WidgetCoolDownData.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message WidgetCoolDownData { + uint32 id = 1; + uint64 cool_down_time = 2; + bool is_success = 3; +} diff --git a/proto/WidgetCoolDownNotify.proto b/proto/WidgetCoolDownNotify.proto new file mode 100644 index 000000000..bba876fbe --- /dev/null +++ b/proto/WidgetCoolDownNotify.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetCoolDownData.proto"; + +// CmdId: 4263 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetCoolDownNotify { + repeated WidgetCoolDownData group_cool_down_data_list = 4; + repeated WidgetCoolDownData normal_cool_down_data_list = 8; +} diff --git a/proto/VehicleSpawnRsp.proto b/proto/WidgetCreateLocationInfo.proto similarity index 58% rename from proto/VehicleSpawnRsp.proto rename to proto/WidgetCreateLocationInfo.proto index 0904aa5b9..0f4c7178f 100644 --- a/proto/VehicleSpawnRsp.proto +++ b/proto/WidgetCreateLocationInfo.proto @@ -2,7 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; -message VehicleSpawnRsp { - uint32 vehicleId = 2; - uint32 entityId = 3; +import "Vector.proto"; + +message WidgetCreateLocationInfo { + Vector pos = 1; + Vector rot = 2; } diff --git a/proto/WidgetCreatorInfo.proto b/proto/WidgetCreatorInfo.proto new file mode 100644 index 000000000..cbc5a90ab --- /dev/null +++ b/proto/WidgetCreatorInfo.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetCreateLocationInfo.proto"; +import "WidgetCreatorOpType.proto"; + +message WidgetCreatorInfo { + WidgetCreatorOpType op_type = 1; + uint32 entity_id = 2; + WidgetCreateLocationInfo location_info = 3; +} diff --git a/proto/WidgetCreatorOpType.proto b/proto/WidgetCreatorOpType.proto new file mode 100644 index 000000000..3ea428dec --- /dev/null +++ b/proto/WidgetCreatorOpType.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum WidgetCreatorOpType { + WIDGET_CREATOR_OP_TYPE_NONE = 0; + WIDGET_CREATOR_OP_TYPE_RETRACT = 1; + WIDGET_CREATOR_OP_TYPE_RETRACT_AND_CREATE = 2; +} diff --git a/proto/WidgetDoBagReq.proto b/proto/WidgetDoBagReq.proto new file mode 100644 index 000000000..188a12e1a --- /dev/null +++ b/proto/WidgetDoBagReq.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetCreateLocationInfo.proto"; +import "WidgetCreatorInfo.proto"; + +// CmdId: 4284 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message WidgetDoBagReq { + uint32 material_id = 15; + oneof op_info { + WidgetCreateLocationInfo location_info = 351; + WidgetCreatorInfo widget_creator_info = 46; + } +} diff --git a/proto/WidgetDoBagRsp.proto b/proto/WidgetDoBagRsp.proto new file mode 100644 index 000000000..07d4ea3a9 --- /dev/null +++ b/proto/WidgetDoBagRsp.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4286 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetDoBagRsp { + int32 retcode = 12; + uint32 material_id = 9; +} diff --git a/proto/WidgetGadgetAllDataNotify.proto b/proto/WidgetGadgetAllDataNotify.proto new file mode 100644 index 000000000..5662c6b27 --- /dev/null +++ b/proto/WidgetGadgetAllDataNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetGadgetData.proto"; + +// CmdId: 4285 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetGadgetAllDataNotify { + repeated WidgetGadgetData widget_gadget_data = 8; +} diff --git a/proto/WidgetGadgetData.proto b/proto/WidgetGadgetData.proto new file mode 100644 index 000000000..8bd1cf364 --- /dev/null +++ b/proto/WidgetGadgetData.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message WidgetGadgetData { + uint32 gadget_id = 1; + repeated uint32 gadget_entity_id_list = 3; +} diff --git a/proto/WidgetGadgetDataNotify.proto b/proto/WidgetGadgetDataNotify.proto new file mode 100644 index 000000000..c80b1bc88 --- /dev/null +++ b/proto/WidgetGadgetDataNotify.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetGadgetData.proto"; + +// CmdId: 4292 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetGadgetDataNotify { + WidgetGadgetData widget_gadget_data = 13; +} diff --git a/proto/WidgetGadgetDestroyNotify.proto b/proto/WidgetGadgetDestroyNotify.proto new file mode 100644 index 000000000..2b0a8cd22 --- /dev/null +++ b/proto/WidgetGadgetDestroyNotify.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4275 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetGadgetDestroyNotify { + uint32 entity_id = 7; +} diff --git a/proto/WidgetReportReq.proto b/proto/WidgetReportReq.proto new file mode 100644 index 000000000..6a70c80c9 --- /dev/null +++ b/proto/WidgetReportReq.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4287 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message WidgetReportReq { + uint32 material_id = 7; + bool is_clear_hint = 13; + bool is_client_collect = 9; + bool BHCBOJNGOIK = 1; +} diff --git a/proto/WidgetReportRsp.proto b/proto/WidgetReportRsp.proto new file mode 100644 index 000000000..117701158 --- /dev/null +++ b/proto/WidgetReportRsp.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4282 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetReportRsp { + int32 retcode = 12; + uint32 material_id = 7; +} diff --git a/proto/WidgetSlotChangeNotify.proto b/proto/WidgetSlotChangeNotify.proto new file mode 100644 index 000000000..8a1f7401d --- /dev/null +++ b/proto/WidgetSlotChangeNotify.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotData.proto"; +import "WidgetSlotOp.proto"; + +// CmdId: 4274 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetSlotChangeNotify { + WidgetSlotOp op = 6; + WidgetSlotData slot = 8; +} diff --git a/proto/WidgetSlotData.proto b/proto/WidgetSlotData.proto new file mode 100644 index 000000000..095915d18 --- /dev/null +++ b/proto/WidgetSlotData.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "WidgetSlotTag.proto"; + +message WidgetSlotData { + WidgetSlotTag tag = 1; + uint32 material_id = 2; + uint32 cd_over_time = 3; + bool is_active = 4; +} diff --git a/proto/WidgetSlotOp.proto b/proto/WidgetSlotOp.proto new file mode 100644 index 000000000..4f809f84b --- /dev/null +++ b/proto/WidgetSlotOp.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum WidgetSlotOp { + WIDGET_SLOT_OP_ATTACH = 0; + WIDGET_SLOT_OP_DETACH = 1; +} diff --git a/proto/WidgetSlotTag.proto b/proto/WidgetSlotTag.proto new file mode 100644 index 000000000..530296631 --- /dev/null +++ b/proto/WidgetSlotTag.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +enum WidgetSlotTag { + WIDGET_SLOT_TAG_QUICK_USE = 0; + WIDGET_SLOT_TAG_ATTACH_AVATAR = 1; +} diff --git a/proto/WidgetSlotTagComparer.proto b/proto/WidgetSlotTagComparer.proto new file mode 100644 index 000000000..5f6253c17 --- /dev/null +++ b/proto/WidgetSlotTagComparer.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + + +message WidgetSlotTagComparer { +} diff --git a/proto/WidgetThunderBirdFeatherInfo.proto b/proto/WidgetThunderBirdFeatherInfo.proto new file mode 100644 index 000000000..5533c83b6 --- /dev/null +++ b/proto/WidgetThunderBirdFeatherInfo.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message WidgetThunderBirdFeatherInfo { + repeated uint32 entity_id_list = 1; +} diff --git a/proto/WidgetUseAttachAbilityGroupChangeNotify.proto b/proto/WidgetUseAttachAbilityGroupChangeNotify.proto new file mode 100644 index 000000000..3af9d79bb --- /dev/null +++ b/proto/WidgetUseAttachAbilityGroupChangeNotify.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 4299 +// EnetChannelId: 0 +// EnetIsReliable: true +message WidgetUseAttachAbilityGroupChangeNotify { + uint32 material_id = 4; + bool is_attach = 11; +} diff --git a/proto/WorktopOptionNotify.proto b/proto/WorktopOptionNotify.proto index 5dfdc94ab..e9dfeb206 100644 --- a/proto/WorktopOptionNotify.proto +++ b/proto/WorktopOptionNotify.proto @@ -2,7 +2,10 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; +// CmdId: 837 +// EnetChannelId: 0 +// EnetIsReliable: true message WorktopOptionNotify { - uint32 gadget_entity_id = 1; - repeated uint32 option_list = 2; + uint32 gadget_entity_id = 12; + repeated uint32 option_list = 5; } diff --git a/proto/WorldDataNotify.proto b/proto/WorldDataNotify.proto index 345c279ef..7885be8f9 100755 --- a/proto/WorldDataNotify.proto +++ b/proto/WorldDataNotify.proto @@ -4,21 +4,16 @@ option java_package = "emu.grasscutter.net.proto"; import "PropValue.proto"; +// CmdId: 3131 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WorldDataNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 3219; - } + map world_prop_map = 3; enum DataType { - DATA_NONE = 0; - WORLD_LEVEL = 1; - IS_IN_MP_MODE = 2; + DATA_TYPE_NONE = 0; + DATA_TYPE_WORLD_LEVEL = 1; + DATA_TYPE_IS_IN_MP_MODE = 2; } - - map world_prop_map = 1; } diff --git a/proto/WorldPlayerDieNotify.proto b/proto/WorldPlayerDieNotify.proto index e1e27b100..5af482971 100755 --- a/proto/WorldPlayerDieNotify.proto +++ b/proto/WorldPlayerDieNotify.proto @@ -4,19 +4,14 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerDieType.proto"; +// CmdId: 296 +// EnetChannelId: 0 +// EnetIsReliable: true message WorldPlayerDieNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 254; + PlayerDieType die_type = 9; + uint32 murderer_entity_id = 14; + oneof entity { + uint32 monster_id = 10; + uint32 gadget_id = 11; } - - oneof Entity { - uint32 monster_id = 3; - uint32 gadget_id = 4; - } - PlayerDieType die_type = 1; - uint32 murderer_entity_id = 2; } diff --git a/proto/WorldPlayerInfoNotify.proto b/proto/WorldPlayerInfoNotify.proto index 276940d5b..e6bd93c4c 100755 --- a/proto/WorldPlayerInfoNotify.proto +++ b/proto/WorldPlayerInfoNotify.proto @@ -4,16 +4,11 @@ option java_package = "emu.grasscutter.net.proto"; import "OnlinePlayerInfo.proto"; +// CmdId: 3304 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true message WorldPlayerInfoNotify { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 3109; - } - - repeated OnlinePlayerInfo player_info_list = 1; - repeated uint32 player_uid_list = 2; + repeated OnlinePlayerInfo player_info_list = 6; + repeated uint32 player_uid_list = 5; } diff --git a/proto/WorldPlayerLocationNotify.proto b/proto/WorldPlayerLocationNotify.proto index 1b8e9d71d..6c8f5b2a5 100755 --- a/proto/WorldPlayerLocationNotify.proto +++ b/proto/WorldPlayerLocationNotify.proto @@ -5,15 +5,10 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerLocationInfo.proto"; import "PlayerWorldLocationInfo.proto"; +// CmdId: 283 +// EnetChannelId: 0 +// EnetIsReliable: true message WorldPlayerLocationNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 253; - } - - repeated PlayerLocationInfo player_loc_list = 1; - repeated PlayerWorldLocationInfo player_world_loc_list = 2; + repeated PlayerLocationInfo player_loc_list = 6; + repeated PlayerWorldLocationInfo player_world_loc_list = 15; } diff --git a/proto/WorldPlayerRTTNotify.proto b/proto/WorldPlayerRTTNotify.proto index a927198ae..46c02f1ce 100755 --- a/proto/WorldPlayerRTTNotify.proto +++ b/proto/WorldPlayerRTTNotify.proto @@ -4,14 +4,9 @@ option java_package = "emu.grasscutter.net.proto"; import "PlayerRTTInfo.proto"; +// CmdId: 24 +// EnetChannelId: 0 +// EnetIsReliable: true message WorldPlayerRTTNotify { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 47; - } - - repeated PlayerRTTInfo player_rtt_list = 1; + repeated PlayerRTTInfo player_rtt_list = 14; } diff --git a/proto/WorldPlayerReviveReq.proto b/proto/WorldPlayerReviveReq.proto index edaeab683..e4315701e 100644 --- a/proto/WorldPlayerReviveReq.proto +++ b/proto/WorldPlayerReviveReq.proto @@ -1,15 +1,10 @@ -syntax = "proto3"; -option csharp_namespace = "YSFreedom.Common.Protocol"; - - -message WorldPlayerReviveReq { - enum CmdId { - option allow_alias = true; - ENET_CHANNEL_ID = 0; - NONE = 0; - ENET_IS_RELIABLE = 1; - IS_ALLOW_CLIENT = 1; - CMD_ID = 288; - } - -} +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +// CmdId: 247 +// EnetChannelId: 0 +// EnetIsReliable: true +// IsAllowClient: true +message WorldPlayerReviveReq { +} diff --git a/proto/WorldPlayerReviveRsp.proto b/proto/WorldPlayerReviveRsp.proto index d08ce1e2e..bbac891ff 100755 --- a/proto/WorldPlayerReviveRsp.proto +++ b/proto/WorldPlayerReviveRsp.proto @@ -2,15 +2,9 @@ syntax = "proto3"; option java_package = "emu.grasscutter.net.proto"; - +// CmdId: 280 +// EnetChannelId: 0 +// EnetIsReliable: true message WorldPlayerReviveRsp { - enum CmdId { - option allow_alias = true; - NONE = 0; - ENET_CHANNEL_ID = 0; - ENET_IS_RELIABLE = 1; - CMD_ID = 227; - } - - int32 retcode = 1; + int32 retcode = 8; } diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java deleted file mode 100644 index 6473e2846..000000000 --- a/src/main/java/emu/grasscutter/Config.java +++ /dev/null @@ -1,110 +0,0 @@ -package emu.grasscutter; - -import java.util.Locale; -import emu.grasscutter.Grasscutter.ServerDebugMode; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.game.mail.Mail; - -public final class Config { - public String DatabaseUrl = "mongodb://localhost:27017"; - public String DatabaseCollection = "grasscutter"; - - public String RESOURCE_FOLDER = "./resources/"; - public String DATA_FOLDER = "./data/"; - public String PACKETS_FOLDER = "./packets/"; - public String DUMPS_FOLDER = "./dumps/"; - public String KEY_FOLDER = "./keys/"; - public String SCRIPTS_FOLDER = "./resources/Scripts/"; - public String PLUGINS_FOLDER = "./plugins/"; - - public ServerDebugMode DebugMode = ServerDebugMode.NONE; // ALL, MISSING, NONE - public ServerRunMode RunMode = ServerRunMode.HYBRID; // HYBRID, DISPATCH_ONLY, GAME_ONLY - public GameServerOptions GameServer = new GameServerOptions(); - public DispatchServerOptions DispatchServer = new DispatchServerOptions(); - public Locale LocaleLanguage = Locale.getDefault(); - public Locale DefaultLanguage = Locale.ENGLISH; - - public Boolean OpenStamina = true; - public GameServerOptions getGameServerOptions() { - return GameServer; - } - - public DispatchServerOptions getDispatchOptions() { return DispatchServer; } - - public static class DispatchServerOptions { - public String Ip = "0.0.0.0"; - public String PublicIp = "127.0.0.1"; - public int Port = 443; - public int PublicPort = 0; - public String KeystorePath = "./keystore.p12"; - public String KeystorePassword = "123456"; - public Boolean UseSSL = true; - public Boolean FrontHTTPS = true; - public Boolean CORS = false; - public String[] CORSAllowedOrigins = new String[] { "*" }; - - public boolean AutomaticallyCreateAccounts = false; - public String[] defaultPermissions = new String[] { "" }; - - public RegionInfo[] GameServers = {}; - - public RegionInfo[] getGameServers() { - return GameServers; - } - - public static class RegionInfo { - public String Name = "os_usa"; - public String Title = "Test"; - public String Ip = "127.0.0.1"; - public int Port = 22102; - } - } - - public static class GameServerOptions { - public String Name = "Test"; - public String Ip = "0.0.0.0"; - public String PublicIp = "127.0.0.1"; - public int Port = 22102; - public int PublicPort = 0; - - public String DispatchServerDatabaseUrl = "mongodb://localhost:27017"; - public String DispatchServerDatabaseCollection = "grasscutter"; - - public int InventoryLimitWeapon = 2000; - public int InventoryLimitRelic = 2000; - public int InventoryLimitMaterial = 2000; - public int InventoryLimitFurniture = 2000; - public int InventoryLimitAll = 30000; - public int MaxAvatarsInTeam = 4; - public int MaxAvatarsInTeamMultiplayer = 4; - public int MaxEntityLimit = 1000; // Max entity limit per world. // TODO: Enforce later. - public boolean WatchGacha = false; - public String ServerNickname = "Server"; - public int ServerAvatarId = 10000007; - public int ServerNameCardId = 210001; - public int ServerLevel = 1; - public int ServerWorldLevel = 1; - public String ServerSignature = "Server Signature"; - public int[] WelcomeEmotes = {2007, 1002, 4010}; - public String WelcomeMotd = "Welcome to Grasscutter emu"; - public String WelcomeMailTitle = "Welcome to Grasscutter!"; - public String WelcomeMailSender = "Lawnmower"; - public String WelcomeMailContent = "Hi there!\r\nFirst of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r\n\r\nCheck out our:\r\n"; - public Mail.MailItem[] WelcomeMailItems = { - new Mail.MailItem(13509, 1, 1), - new Mail.MailItem(201, 10000, 1), - }; - - public boolean EnableOfficialShop = true; - - public GameRates Game = new GameRates(); - - public GameRates getGameRates() { return Game; } - - public static class GameRates { - public float ADVENTURE_EXP_RATE = 1.0f; - public float MORA_RATE = 1.0f; - public float DOMAIN_DROP_RATE = 1.0f; - } - } -} diff --git a/src/main/java/emu/grasscutter/Configuration.java b/src/main/java/emu/grasscutter/Configuration.java new file mode 100644 index 000000000..486c5d33c --- /dev/null +++ b/src/main/java/emu/grasscutter/Configuration.java @@ -0,0 +1,111 @@ +package emu.grasscutter; + +import emu.grasscutter.utils.ConfigContainer; +import emu.grasscutter.utils.ConfigContainer.*; + +import java.util.Locale; +import java.nio.file.Paths; + +import static emu.grasscutter.Grasscutter.config; + + +/** + * A data container for the server's configuration. + * + * Use `import static emu.grasscutter.Configuration.*;` + * to import all configuration constants. + */ +public final class Configuration extends ConfigContainer { + + /* + * Constants + */ + + // 'c' is short for 'config' and makes code look 'cleaner'. + public static final ConfigContainer c = config; + + public static final Locale LANGUAGE = config.language.language; + public static final Locale FALLBACK_LANGUAGE = config.language.fallback; + public static final String DOCUMENT_LANGUAGE = config.language.document; + private static final String DATA_FOLDER = config.folderStructure.data; + private static final String RESOURCES_FOLDER = config.folderStructure.resources; + private static final String PLUGINS_FOLDER = config.folderStructure.plugins; + private static final String SCRIPTS_FOLDER = config.folderStructure.scripts; + private static final String PACKETS_FOLDER = config.folderStructure.packets; + + public static final Server SERVER = config.server; + public static final Database DATABASE = config.databaseInfo; + public static final Account ACCOUNT = config.account; + + public static final HTTP HTTP_INFO = config.server.http; + public static final Game GAME_INFO = config.server.game; + public static final Dispatch DISPATCH_INFO = config.server.dispatch; + + public static final Encryption HTTP_ENCRYPTION = config.server.http.encryption; + public static final Policies HTTP_POLICIES = config.server.http.policies; + public static final Files HTTP_STATIC_FILES = config.server.http.files; + + public static final GameOptions GAME_OPTIONS = config.server.game.gameOptions; + public static final GameOptions.InventoryLimits INVENTORY_LIMITS = config.server.game.gameOptions.inventoryLimits; + + /* + * Utilities + */ + public static String DATA() { + return DATA_FOLDER; + } + + public static String DATA(String path) { + return Paths.get(DATA_FOLDER, path).toString(); + } + + public static String RESOURCE(String path) { + return Paths.get(RESOURCES_FOLDER, path).toString(); + } + + public static String PLUGIN() { + return PLUGINS_FOLDER; + } + + public static String PLUGIN(String path) { + return Paths.get(PLUGINS_FOLDER, path).toString(); + } + + public static String SCRIPT(String path) { + return Paths.get(SCRIPTS_FOLDER, path).toString(); + } + + public static String PACKET(String path) { + return Paths.get(PACKETS_FOLDER, path).toString(); + } + + /** + * Fallback method. + * @param left Attempt to use. + * @param right Use if left is undefined. + * @return Left or right. + */ + public static T lr(T left, T right) { + return left == null ? right : left; + } + + /** + * {@link Configuration#lr(Object, Object)} for {@link String}s. + * @param left Attempt to use. + * @param right Use if left is empty. + * @return Left or right. + */ + public static String lr(String left, String right) { + return left.isEmpty() ? right : left; + } + + /** + * {@link Configuration#lr(Object, Object)} for {@link Integer}s. + * @param left Attempt to use. + * @param right Use if left is 0. + * @return Left or right. + */ + public static int lr(int left, int right) { + return left == 0 ? right : left; + } +} diff --git a/src/main/java/emu/grasscutter/GameConstants.java b/src/main/java/emu/grasscutter/GameConstants.java index dc07c32e1..5e50e3fd6 100644 --- a/src/main/java/emu/grasscutter/GameConstants.java +++ b/src/main/java/emu/grasscutter/GameConstants.java @@ -6,7 +6,7 @@ import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Utils; public final class GameConstants { - public static String VERSION = "2.6.0"; + public static String VERSION = "2.7.0"; public static final int MAX_TEAMS = 4; public static final int MAIN_CHARACTER_MALE = 10000005; diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index c593f5f13..af88b74ac 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -1,15 +1,22 @@ package emu.grasscutter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOError; +import java.io.*; import java.util.Calendar; +import emu.grasscutter.auth.AuthenticationSystem; +import emu.grasscutter.auth.DefaultAuthentication; import emu.grasscutter.command.CommandMap; +import emu.grasscutter.game.managers.EnergyManager.EnergyManager; +import emu.grasscutter.game.managers.StaminaManager.StaminaManager; import emu.grasscutter.plugin.PluginManager; import emu.grasscutter.plugin.api.ServerHook; import emu.grasscutter.scripts.ScriptLoader; +import emu.grasscutter.server.http.HttpServer; +import emu.grasscutter.server.http.dispatch.DispatchHandler; +import emu.grasscutter.server.http.handlers.*; +import emu.grasscutter.server.http.dispatch.RegionHandler; +import emu.grasscutter.server.http.documentation.DocumentationServerHandler; +import emu.grasscutter.utils.ConfigContainer; import emu.grasscutter.utils.Utils; import org.jline.reader.EndOfFileException; import org.jline.reader.LineReader; @@ -27,30 +34,33 @@ import ch.qos.logback.classic.Logger; import emu.grasscutter.data.ResourceLoader; import emu.grasscutter.database.DatabaseManager; import emu.grasscutter.utils.Language; -import emu.grasscutter.server.dispatch.DispatchServer; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.tools.Tools; import emu.grasscutter.utils.Crypto; +import javax.annotation.Nullable; + import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; public final class Grasscutter { private static final Logger log = (Logger) LoggerFactory.getLogger(Grasscutter.class); private static LineReader consoleLineReader = null; - - private static Config config; + private static Language language; private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); - private static final File configFile = new File("./config.json"); + public static final File configFile = new File("./config.json"); private static int day; // Current day of week. - private static DispatchServer dispatchServer; + private static HttpServer httpServer; private static GameServer gameServer; private static PluginManager pluginManager; + private static AuthenticationSystem authenticationSystem; public static final Reflections reflector = new Reflections("emu.grasscutter"); + public static ConfigContainer config; static { // Declare logback configuration. @@ -58,6 +68,8 @@ public final class Grasscutter { // Load server configuration. Grasscutter.loadConfig(); + // Attempt to update configuration. + ConfigContainer.updateConfig(); // Load translation files. Grasscutter.loadLanguage(); @@ -66,9 +78,9 @@ public final class Grasscutter { Utils.startupCheck(); } - public static void main(String[] args) throws Exception { - Crypto.loadKeys(); // Load keys from buffers. - + public static void main(String[] args) throws Exception { + Crypto.loadKeys(); // Load keys from buffers. + // Parse arguments. boolean exitEarly = false; for (String arg : args) { @@ -77,57 +89,81 @@ public final class Grasscutter { Tools.createGmHandbook(); exitEarly = true; } case "-gachamap" -> { - Tools.createGachaMapping(Grasscutter.getConfig().DATA_FOLDER + "/gacha_mappings.js"); exitEarly = true; + Tools.createGachaMapping(DATA("gacha_mappings.js")); exitEarly = true; + } + case "-version" -> { + System.out.println("Grasscutter version: " + BuildConfig.VERSION + "-" + BuildConfig.GIT_HASH); exitEarly = true; } } } // Exit early if argument sets it. if(exitEarly) System.exit(0); - + // Initialize server. Grasscutter.getLogger().info(translate("messages.status.starting")); - + Grasscutter.getLogger().info(translate("messages.status.game_version", GameConstants.VERSION)); + Grasscutter.getLogger().info(translate("messages.status.version", BuildConfig.VERSION, BuildConfig.GIT_HASH)); + // Load all resources. Grasscutter.updateDayOfWeek(); ResourceLoader.loadAll(); ScriptLoader.init(); - + EnergyManager.initialize(); + // Initialize database. DatabaseManager.initialize(); - + + // Initialize the default authentication system. + authenticationSystem = new DefaultAuthentication(); + // Create server instances. - dispatchServer = new DispatchServer(); + httpServer = new HttpServer(); gameServer = new GameServer(); // Create a server hook instance with both servers. - new ServerHook(gameServer, dispatchServer); + new ServerHook(gameServer, httpServer); + // Create plugin manager instance. pluginManager = new PluginManager(); - + // Add HTTP routes after loading plugins. + httpServer.addRouter(HttpServer.UnhandledRequestRouter.class); + httpServer.addRouter(HttpServer.DefaultRequestRouter.class); + httpServer.addRouter(RegionHandler.class); + httpServer.addRouter(LogHandler.class); + httpServer.addRouter(GenericHandler.class); + httpServer.addRouter(AnnouncementsHandler.class); + httpServer.addRouter(DispatchHandler.class); + httpServer.addRouter(GachaHandler.class); + httpServer.addRouter(DocumentationServerHandler.class); + + // TODO: find a better place? + StaminaManager.initialize(); + // Start servers. - if (getConfig().RunMode == ServerRunMode.HYBRID) { - dispatchServer.start(); + var runMode = SERVER.runMode; + if (runMode == ServerRunMode.HYBRID) { + httpServer.start(); gameServer.start(); - } else if (getConfig().RunMode == ServerRunMode.DISPATCH_ONLY) { - dispatchServer.start(); - } else if (getConfig().RunMode == ServerRunMode.GAME_ONLY) { + } else if (runMode == ServerRunMode.DISPATCH_ONLY) { + httpServer.start(); + } else if (runMode == ServerRunMode.GAME_ONLY) { gameServer.start(); } else { - getLogger().error(translate("messages.status.run_mode_error", getConfig().RunMode)); + getLogger().error(translate("messages.status.run_mode_error", runMode)); getLogger().error(translate("messages.status.run_mode_help")); getLogger().error(translate("messages.status.shutdown")); System.exit(1); } - + // Enable all plugins. pluginManager.enablePlugins(); - + // Hook into shutdown event. Runtime.getRuntime().addShutdownHook(new Thread(Grasscutter::onShutdown)); - + // Open console. startConsole(); - } + } /** * Server shutdown event. @@ -137,75 +173,61 @@ public final class Grasscutter { pluginManager.disablePlugins(); } - public static void loadConfig() { - try (FileReader file = new FileReader(configFile)) { - config = gson.fromJson(file, Config.class); - saveConfig(); - } catch (Exception e) { - Grasscutter.config = new Config(); - saveConfig(); - } - } - + /* + * Methods for the language system component. + */ + public static void loadLanguage() { - var locale = config.LocaleLanguage; - var languageTag = locale.toLanguageTag(); - - if (languageTag.equals("und")) { - Grasscutter.getLogger().error("Illegal locale language, using 'en-US' instead."); - language = Language.getLanguage("en-US"); - } else { - language = Language.getLanguage(languageTag); - } + var locale = config.language.language; + language = Language.getLanguage(Utils.getLanguageCode(locale)); + } + + /* + * Methods for the configuration system component. + */ + + /** + * Attempts to load the configuration from a file. + */ + public static void loadConfig() { + // Check if config.json exists. If not, we generate a new config. + if (!configFile.exists()) { + getLogger().info("config.json could not be found. Generating a default configuration ..."); + config = new ConfigContainer(); + Grasscutter.saveConfig(config); + return; + } + + // If the file already exists, we attempt to load it. + try (FileReader file = new FileReader(configFile)) { + config = gson.fromJson(file, ConfigContainer.class); + } catch (Exception exception) { + getLogger().error("There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); + System.exit(1); + } } - public static void saveConfig() { + /** + * Saves the provided server configuration. + * @param config The configuration to save, or null for a new one. + */ + public static void saveConfig(@Nullable ConfigContainer config) { + if(config == null) config = new ConfigContainer(); + try (FileWriter file = new FileWriter(configFile)) { file.write(gson.toJson(config)); + } catch (IOException ignored) { + Grasscutter.getLogger().error("Unable to write to config file."); } catch (Exception e) { - Grasscutter.getLogger().error("Unable to save config file."); + Grasscutter.getLogger().error("Unable to save config file.", e); } } - public static void startConsole() { - // Console should not start in dispatch only mode. - if (getConfig().RunMode == ServerRunMode.DISPATCH_ONLY) { - getLogger().info(translate("messages.dispatch.no_commands_error")); - return; - } - - getLogger().info(translate("messages.status.done")); - String input = null; - boolean isLastInterrupted = false; - while (true) { - try { - input = consoleLineReader.readLine("> "); - } catch (UserInterruptException e) { - if (!isLastInterrupted) { - isLastInterrupted = true; - Grasscutter.getLogger().info("Press Ctrl-C again to shutdown."); - continue; - } else { - Runtime.getRuntime().exit(0); - } - } catch (EndOfFileException e) { - Grasscutter.getLogger().info("EOF detected."); - continue; - } catch (IOError e) { - Grasscutter.getLogger().error("An IO error occurred.", e); - continue; - } - - isLastInterrupted = false; - try { - CommandMap.getInstance().invoke(null, null, input); - } catch (Exception e) { - Grasscutter.getLogger().error(translate("messages.game.command_error"), e); - } - } - } - - public static Config getConfig() { + /* + * Getters for the various server components. + */ + + public static ConfigContainer getConfig() { return config; } @@ -213,6 +235,14 @@ public final class Grasscutter { return language; } + public static void setLanguage(Language language) { + Grasscutter.language = language; + } + + public static Language getLanguage(String langCode) { + return Language.getLanguage(langCode); + } + public static Logger getLogger() { return log; } @@ -241,8 +271,8 @@ public final class Grasscutter { return gson; } - public static DispatchServer getDispatchServer() { - return dispatchServer; + public static HttpServer getHttpServer() { + return httpServer; } public static GameServer getGameServer() { @@ -252,16 +282,74 @@ public final class Grasscutter { public static PluginManager getPluginManager() { return pluginManager; } - - public static void updateDayOfWeek() { - Calendar calendar = Calendar.getInstance(); - day = calendar.get(Calendar.DAY_OF_WEEK); + + public static AuthenticationSystem getAuthenticationSystem() { + return authenticationSystem; } public static int getCurrentDayOfWeek() { return day; } + + /* + * Utility methods. + */ + + public static void updateDayOfWeek() { + Calendar calendar = Calendar.getInstance(); + day = calendar.get(Calendar.DAY_OF_WEEK); + } + public static void startConsole() { + // Console should not start in dispatch only mode. + if (SERVER.runMode == ServerRunMode.DISPATCH_ONLY) { + getLogger().info(translate("messages.dispatch.no_commands_error")); + return; + } + + getLogger().info(translate("messages.status.done")); + String input = null; + boolean isLastInterrupted = false; + while (config.server.game.enableConsole) { + try { + input = consoleLineReader.readLine("> "); + } catch (UserInterruptException e) { + if (!isLastInterrupted) { + isLastInterrupted = true; + Grasscutter.getLogger().info("Press Ctrl-C again to shutdown."); + continue; + } else { + Runtime.getRuntime().exit(0); + } + } catch (EndOfFileException e) { + Grasscutter.getLogger().info("EOF detected."); + continue; + } catch (IOError e) { + Grasscutter.getLogger().error("An IO error occurred.", e); + continue; + } + + isLastInterrupted = false; + try { + CommandMap.getInstance().invoke(null, null, input); + } catch (Exception e) { + Grasscutter.getLogger().error(translate("messages.game.command_error"), e); + } + } + } + + /** + * Sets the authentication system for the server. + * @param authenticationSystem The authentication system to use. + */ + public static void setAuthenticationSystem(AuthenticationSystem authenticationSystem) { + Grasscutter.authenticationSystem = authenticationSystem; + } + + /* + * Enums for the configuration. + */ + public enum ServerRunMode { HYBRID, DISPATCH_ONLY, GAME_ONLY } diff --git a/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java b/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java new file mode 100644 index 000000000..90f2648c5 --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/AuthenticationSystem.java @@ -0,0 +1,134 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.*; +import express.http.Request; +import express.http.Response; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import javax.annotation.Nullable; + +/** + * Defines an authenticator for the server. + * Can be changed by plugins. + */ +public interface AuthenticationSystem { + + /** + * Called when a user requests to make an account. + * @param username The provided username. + * @param password The provided password. (SHA-256'ed) + */ + void createAccount(String username, String password); + + /** + * Called when a user requests to reset their password. + * @param username The username of the account to reset. + */ + void resetPassword(String username); + + /** + * Called by plugins to internally verify a user's identity. + * @param details A unique identifier to identify the user. (For example: a JWT token) + * @return The user's account if the verification was successful, null if the user was unable to be verified. + */ + Account verifyUser(String details); + + /** + * This is the authenticator used for password authentication. + * @return An authenticator. + */ + Authenticator getPasswordAuthenticator(); + + /** + * This is the authenticator used for token authentication. + * @return An authenticator. + */ + Authenticator getTokenAuthenticator(); + + /** + * This is the authenticator used for session authentication. + * @return An authenticator. + */ + Authenticator getSessionKeyAuthenticator(); + + /** + * This is the authenticator used for handling external authentication requests. + * @return An authenticator. + */ + ExternalAuthenticator getExternalAuthenticator(); + + /** + * This is the authenticator used for handling OAuth authentication requests. + * @return An authenticator. + */ + OAuthAuthenticator getOAuthAuthenticator(); + + /** + * A data container that holds relevant data for authenticating a client. + */ + @Builder @AllArgsConstructor @Getter + class AuthenticationRequest { + private final Request request; + @Nullable private final Response response; + + @Nullable private final LoginAccountRequestJson passwordRequest; + @Nullable private final LoginTokenRequestJson tokenRequest; + @Nullable private final ComboTokenReqJson sessionKeyRequest; + @Nullable private final ComboTokenReqJson.LoginTokenData sessionKeyData; + } + + /** + * Generates an authentication request from a {@link LoginAccountRequestJson} object. + * @param request The Express request. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromPasswordRequest(Request request, LoginAccountRequestJson jsonData) { + return AuthenticationRequest.builder() + .request(request) + .passwordRequest(jsonData) + .build(); + } + + /** + * Generates an authentication request from a {@link LoginTokenRequestJson} object. + * @param request The Express request. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromTokenRequest(Request request, LoginTokenRequestJson jsonData) { + return AuthenticationRequest.builder() + .request(request) + .tokenRequest(jsonData) + .build(); + } + + /** + * Generates an authentication request from a {@link ComboTokenReqJson} object. + * @param request The Express request. + * @param jsonData The JSON data. + * @return An authentication request. + */ + static AuthenticationRequest fromComboTokenRequest(Request request, ComboTokenReqJson jsonData, + ComboTokenReqJson.LoginTokenData tokenData) { + return AuthenticationRequest.builder() + .request(request) + .sessionKeyRequest(jsonData) + .sessionKeyData(tokenData) + .build(); + } + + /** + * Generates an authentication request from a {@link Response} object. + * @param request The Express request. + * @param response the Express response. + * @return An authentication request. + */ + static AuthenticationRequest fromExternalRequest(Request request, Response response) { + return AuthenticationRequest.builder().request(request) + .response(response).build(); + } +} diff --git a/src/main/java/emu/grasscutter/auth/Authenticator.java b/src/main/java/emu/grasscutter/auth/Authenticator.java new file mode 100644 index 000000000..a5d756d8c --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/Authenticator.java @@ -0,0 +1,17 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.server.http.objects.*; + +/** + * Handles username/password authentication from the client. + * @param The response object type. Should be {@link LoginResultJson} or {@link ComboTokenResJson} + */ +public interface Authenticator { + + /** + * Attempt to authenticate the client with the provided credentials. + * @param request The authentication request wrapped in a {@link AuthenticationSystem.AuthenticationRequest} object. + * @return The result of the login in an object. + */ + T authenticate(AuthenticationSystem.AuthenticationRequest request); +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java b/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java new file mode 100644 index 000000000..ba77e7d6e --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/DefaultAuthentication.java @@ -0,0 +1,62 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.DefaultAuthenticators.*; +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.ComboTokenResJson; +import emu.grasscutter.server.http.objects.LoginResultJson; + +import static emu.grasscutter.utils.Language.translate; + +/** + * The default Grasscutter authentication implementation. + * Allows all users to access any account. + */ +public final class DefaultAuthentication implements AuthenticationSystem { + private final Authenticator passwordAuthenticator = new PasswordAuthenticator(); + private final Authenticator tokenAuthenticator = new TokenAuthenticator(); + private final Authenticator sessionKeyAuthenticator = new SessionKeyAuthenticator(); + private final ExternalAuthenticator externalAuthenticator = new ExternalAuthentication(); + private final OAuthAuthenticator oAuthAuthenticator = new OAuthAuthentication(); + + @Override + public void createAccount(String username, String password) { + // Unhandled. The default authenticator doesn't store passwords. + } + + @Override + public void resetPassword(String username) { + // Unhandled. The default authenticator doesn't store passwords. + } + + @Override + public Account verifyUser(String details) { + Grasscutter.getLogger().info(translate("dispatch.authentication.default_unable_to_verify")); + return null; + } + + @Override + public Authenticator getPasswordAuthenticator() { + return this.passwordAuthenticator; + } + + @Override + public Authenticator getTokenAuthenticator() { + return this.tokenAuthenticator; + } + + @Override + public Authenticator getSessionKeyAuthenticator() { + return this.sessionKeyAuthenticator; + } + + @Override + public ExternalAuthenticator getExternalAuthenticator() { + return this.externalAuthenticator; + } + + @Override + public OAuthAuthenticator getOAuthAuthenticator() { + return this.oAuthAuthenticator; + } +} diff --git a/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java b/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java new file mode 100644 index 000000000..905535380 --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java @@ -0,0 +1,228 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.server.http.objects.*; + +import static emu.grasscutter.Configuration.*; +import static emu.grasscutter.utils.Language.translate; + +/** + * A class containing default authenticators. + */ +public final class DefaultAuthenticators { + + /** + * Handles the authentication request from the username and password form. + */ + public static class PasswordAuthenticator implements Authenticator { + @Override public LoginResultJson authenticate(AuthenticationRequest request) { + var response = new LoginResultJson(); + + var requestData = request.getPasswordRequest(); + assert requestData != null; // This should never be null. + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + boolean successfulLogin = false; + String address = request.getRequest().ip(); + String responseMessage = translate("messages.dispatch.account.username_error"); + String loggerMessage = ""; + + // Get account from database. + Account account = DatabaseHelper.getAccountByName(requestData.account); + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + // Check if account exists. + if(account == null && ACCOUNT.autoCreate) { + // This account has been created AUTOMATICALLY. There will be no permissions added. + account = DatabaseHelper.createAccountWithUid(requestData.account, 0); + + // Check if the account was created successfully. + if(account == null) { + responseMessage = translate("messages.dispatch.account.username_create_error"); + Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_error", address)); + } else { + // Continue with login. + successfulLogin = true; + + // Log the creation. + Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_success", address, response.data.account.uid)); + } + } else if(account != null) + successfulLogin = true; + else + loggerMessage = translate("messages.dispatch.account.account_login_exist_error", address); + + } else { + responseMessage = translate("messages.dispatch.account.server_max_player_limit"); + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + + // Set response data. + if(successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.generateSessionKey(); + response.data.account.email = account.getEmail(); + + loggerMessage = translate("messages.dispatch.account.login_success", address, account.getId()); + } else { + response.retcode = -201; + response.message = responseMessage; + + } + Grasscutter.getLogger().info(loggerMessage); + + return response; + } + } + + /** + * Handles the authentication request from the game when using a registry token. + */ + public static class TokenAuthenticator implements Authenticator { + @Override public LoginResultJson authenticate(AuthenticationRequest request) { + var response = new LoginResultJson(); + + var requestData = request.getTokenRequest(); + assert requestData != null; + + boolean successfulLogin; + String address = request.getRequest().ip(); + String loggerMessage; + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + // Log the attempt. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", address)); + + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + + // Get account from database. + Account account = DatabaseHelper.getAccountById(requestData.uid); + + // Check if account exists/token is valid. + successfulLogin = account != null && account.getSessionKey().equals(requestData.token); + + // Set response data. + if(successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.getSessionKey(); + response.data.account.email = account.getEmail(); + + // Log the login. + loggerMessage = translate("messages.dispatch.account.login_token_success", address, requestData.uid); + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.account_cache_error"); + + // Log the failure. + loggerMessage = translate("messages.dispatch.account.login_token_error", address); + } + + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.server_max_player_limit"); + + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + Grasscutter.getLogger().info(loggerMessage); + return response; + } + } + + /** + * Handles the authentication request from the game when using a combo token/session key. + */ + public static class SessionKeyAuthenticator implements Authenticator { + @Override public ComboTokenResJson authenticate(AuthenticationRequest request) { + var response = new ComboTokenResJson(); + + var requestData = request.getSessionKeyRequest(); + var loginData = request.getSessionKeyData(); + assert requestData != null; assert loginData != null; + + boolean successfulLogin; + String address = request.getRequest().ip(); + String loggerMessage; + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { + // Get account from database. + Account account = DatabaseHelper.getAccountById(loginData.uid); + + // Check if account exists/token is valid. + successfulLogin = account != null && account.getSessionKey().equals(loginData.token); + + // Set response data. + if(successfulLogin) { + response.message = "OK"; + response.data.open_id = account.getId(); + response.data.combo_id = "157795300"; + response.data.combo_token = account.generateLoginToken(); + + // Log the login. + loggerMessage = translate("messages.dispatch.account.combo_token_success", address); + + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.session_key_error"); + + // Log the failure. + loggerMessage = translate("messages.dispatch.account.combo_token_error", address); + } + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.server_max_player_limit"); + + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); + } + + Grasscutter.getLogger().info(loggerMessage); + return response; + } + } + + /** + * Handles authentication requests from external sources. + */ + public static class ExternalAuthentication implements ExternalAuthenticator { + @Override public void handleLogin(AuthenticationRequest request) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + + @Override public void handleAccountCreation(AuthenticationRequest request) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + + @Override public void handlePasswordReset(AuthenticationRequest request) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + } + + /** + * Handles authentication requests from OAuth sources. + */ + public static class OAuthAuthentication implements OAuthAuthenticator { + @Override public void handleLogin(AuthenticationRequest request) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + + @Override public void handleRedirection(AuthenticationRequest request, ClientType type) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + + @Override public void handleTokenProcess(AuthenticationRequest request) { + assert request.getResponse() != null; + request.getResponse().send("Authentication is not available with the default authentication method."); + } + } +} diff --git a/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java b/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java new file mode 100644 index 000000000..6bf78af6e --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/ExternalAuthenticator.java @@ -0,0 +1,33 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; + +/** + * Handles authentication via external routes. + */ +public interface ExternalAuthenticator { + + /** + * Called when an external login request is made. + * @param request The authentication request. + */ + void handleLogin(AuthenticationRequest request); + + /** + * Called when an external account creation request is made. + * @param request The authentication request. + * + * For developers: Use {@link AuthenticationRequest#getRequest()} to get the request body. + * Use {@link AuthenticationRequest#getResponse()} to get the response body. + */ + void handleAccountCreation(AuthenticationRequest request); + + /** + * Called when an external password reset request is made. + * @param request The authentication request. + * + * For developers: Use {@link AuthenticationRequest#getRequest()} to get the request body. + * Use {@link AuthenticationRequest#getResponse()} to get the response body. + */ + void handlePasswordReset(AuthenticationRequest request); +} diff --git a/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java b/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java new file mode 100644 index 000000000..2d7a73454 --- /dev/null +++ b/src/main/java/emu/grasscutter/auth/OAuthAuthenticator.java @@ -0,0 +1,35 @@ +package emu.grasscutter.auth; + +import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest; + +/** + * Handles authentication via OAuth routes. + */ +public interface OAuthAuthenticator { + + /** + * Called when an OAuth login request is made. + * @param request The authentication request. + */ + void handleLogin(AuthenticationRequest request); + + /** + * Called when a client requests to redirect to login page. + * @param request The authentication request. + */ + void handleRedirection(AuthenticationRequest request, ClientType clientType); + + /** + * Called when an OAuth login requests callback. + * @param request The authentication request. + */ + void handleTokenProcess(AuthenticationRequest request); + + /** + * The type of the client. + * Used for handling redirection. + */ + enum ClientType { + DESKTOP, MOBILE + } +} diff --git a/src/main/java/emu/grasscutter/command/Command.java b/src/main/java/emu/grasscutter/command/Command.java index 734f454ea..37f813f16 100644 --- a/src/main/java/emu/grasscutter/command/Command.java +++ b/src/main/java/emu/grasscutter/command/Command.java @@ -9,7 +9,7 @@ public @interface Command { String usage() default "No usage specified"; - String description() default "No description specified"; + String description() default "commands.generic.no_description_specified"; String[] aliases() default {}; @@ -17,5 +17,13 @@ public @interface Command { String permissionTargeted() default ""; + public enum TargetRequirement { + NONE, // targetPlayer is not required + OFFLINE, // targetPlayer must be offline + PLAYER, // targetPlayer can be online or offline + ONLINE // targetPlayer must be online + } + TargetRequirement targetRequirement() default TargetRequirement.ONLINE; + boolean threading() default false; } diff --git a/src/main/java/emu/grasscutter/command/CommandHandler.java b/src/main/java/emu/grasscutter/command/CommandHandler.java index ffe21c9be..66553d60a 100644 --- a/src/main/java/emu/grasscutter/command/CommandHandler.java +++ b/src/main/java/emu/grasscutter/command/CommandHandler.java @@ -2,10 +2,14 @@ package emu.grasscutter.command; import emu.grasscutter.Grasscutter; import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.game.CommandResponseEvent; +import emu.grasscutter.server.event.types.ServerEvent; +import static emu.grasscutter.utils.Language.translate; import java.util.List; public interface CommandHandler { + /** * Send a message to the target. * @@ -18,6 +22,12 @@ public interface CommandHandler { } else { player.dropMessage(message); } + CommandResponseEvent event = new CommandResponseEvent(ServerEvent.Type.GAME,player, message); + event.call(); + } + + static void sendTranslatedMessage(Player player, String messageKey, Object... args) { + sendMessage(player, translate(player, messageKey, args)); } /** diff --git a/src/main/java/emu/grasscutter/command/CommandMap.java b/src/main/java/emu/grasscutter/command/CommandMap.java index a183c6ac3..2495bf4ad 100644 --- a/src/main/java/emu/grasscutter/command/CommandMap.java +++ b/src/main/java/emu/grasscutter/command/CommandMap.java @@ -8,8 +8,6 @@ import org.reflections.Reflections; import java.util.*; -import static emu.grasscutter.utils.Language.translate; - @SuppressWarnings({"UnusedReturnValue", "unused"}) public final class CommandMap { private final Map commands = new HashMap<>(); @@ -117,7 +115,7 @@ public final class CommandMap { public void invoke(Player player, Player targetPlayer, String rawMessage) { rawMessage = rawMessage.trim(); if (rawMessage.length() == 0) { - CommandHandler.sendMessage(player, translate("commands.generic.not_specified")); + CommandHandler.sendTranslatedMessage(player, "commands.generic.not_specified"); return; } @@ -144,19 +142,20 @@ public final class CommandMap { if (targetUidStr != null) { if (targetUidStr.equals("")) { // Clears the default targetPlayer. targetPlayerIds.remove(playerId); - CommandHandler.sendMessage(player, translate("commands.execution.clear_target")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.clear_target"); } else { // Sets default targetPlayer to the UID provided. try { int uid = Integer.parseInt(targetUidStr); - targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid); + targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); if (targetPlayer == null) { - CommandHandler.sendMessage(player, translate("commands.generic.execution.player_exist_offline_error")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); } else { targetPlayerIds.put(playerId, uid); - CommandHandler.sendMessage(player, translate("commands.execution.set_target", targetUidStr)); + CommandHandler.sendTranslatedMessage(player, "commands.execution.set_target", targetUidStr); + CommandHandler.sendTranslatedMessage(player, targetPlayer.isOnline()? "commands.execution.set_target_online" : "commands.execution.set_target_offline", targetUidStr); } } catch (NumberFormatException e) { - CommandHandler.sendMessage(player, translate("commands.execution.uid_error")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.uid_error"); } } return; @@ -165,7 +164,7 @@ public final class CommandMap { // Get command handler. CommandHandler handler = this.commands.get(label); if (handler == null) { - CommandHandler.sendMessage(player, translate("commands.generic.unknown_command", label)); + CommandHandler.sendTranslatedMessage(player, "commands.generic.unknown_command", label); return; } @@ -176,14 +175,14 @@ public final class CommandMap { arg = args.remove(i).substring(1); try { int uid = Integer.parseInt(arg); - targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid); + targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true); if (targetPlayer == null) { - CommandHandler.sendMessage(player, translate("commands.generic.execution.player_exist_offline_error")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); return; } break; } catch (NumberFormatException e) { - CommandHandler.sendMessage(player, translate("commands.execution.uid_error")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.uid_error"); return; } } @@ -192,9 +191,9 @@ public final class CommandMap { // If there's still no targetPlayer at this point, use previously-set target if (targetPlayer == null) { if (targetPlayerIds.containsKey(playerId)) { - targetPlayer = Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.get(playerId)); // We check every time in case the target goes offline after being targeted + targetPlayer = Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.get(playerId), true); // We check every time in case the target is deleted after being targeted if (targetPlayer == null) { - CommandHandler.sendMessage(player, translate("commands.generic.execution.player_exist_offline_error")); + CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error"); return; } } else { @@ -210,12 +209,29 @@ public final class CommandMap { Account account = player.getAccount(); if (player != targetPlayer) { // Additional permission required for targeting another player if (!permissionNodeTargeted.isEmpty() && !account.hasPermission(permissionNodeTargeted)) { - CommandHandler.sendMessage(player, translate("commands.generic.permission_error")); + CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); return; } } if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) { - CommandHandler.sendMessage(player, translate("commands.generic.permission_error")); + CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error"); + return; + } + } + + // Check if command has unfulfilled constraints on targetPlayer + Command.TargetRequirement targetRequirement = this.annotations.get(label).targetRequirement(); + if (targetRequirement != Command.TargetRequirement.NONE) { + if (targetPlayer == null) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target"); + return; + } + if ((targetRequirement == Command.TargetRequirement.ONLINE) && !targetPlayer.isOnline()) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_online"); + return; + } + if ((targetRequirement == Command.TargetRequirement.OFFLINE) && targetPlayer.isOnline()) { + CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_offline"); return; } } diff --git a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java index 627f4680f..0d50b3787 100644 --- a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java @@ -1,26 +1,28 @@ package emu.grasscutter.command.commands; +import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; import emu.grasscutter.game.player.Player; import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "account", usage = "account [uid]", description = "Modify user accounts") +@Command(label = "account", usage = "account [uid]", description = "commands.account.description", targetRequirement = Command.TargetRequirement.NONE) public final class AccountCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { if (sender != null) { - CommandHandler.sendMessage(sender, translate("commands.generic.console_execute_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.console_execute_error")); return; } if (args.size() < 2) { - CommandHandler.sendMessage(null, translate("commands.account.command_usage")); + CommandHandler.sendMessage(null, translate(sender, "commands.account.command_usage")); return; } @@ -29,7 +31,7 @@ public final class AccountCommand implements CommandHandler { switch (action) { default: - CommandHandler.sendMessage(null, translate("commands.account.command_usage")); + CommandHandler.sendMessage(null, translate(sender, "commands.account.command_usage")); return; case "create": int uid = 0; @@ -37,28 +39,41 @@ public final class AccountCommand implements CommandHandler { try { uid = Integer.parseInt(args.get(2)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(null, translate("commands.account.invalid")); + CommandHandler.sendMessage(null, translate(sender, "commands.account.invalid")); return; } } - emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithId(username, uid); + emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithUid(username, uid); if (account == null) { - CommandHandler.sendMessage(null, translate("commands.account.exists")); + CommandHandler.sendMessage(null, translate(sender, "commands.account.exists")); return; } else { account.addPermission("*"); account.save(); // Save account to database. - CommandHandler.sendMessage(null, translate("commands.account.create", Integer.toString(account.getPlayerUid()))); + CommandHandler.sendMessage(null, translate(sender, "commands.account.create", Integer.toString(account.getReservedPlayerUid()))); } return; case "delete": - if (DatabaseHelper.deleteAccount(username)) { - CommandHandler.sendMessage(null, translate("commands.account.delete")); - } else { - CommandHandler.sendMessage(null, translate("commands.account.no_account")); + // Get the account we want to delete. + Account toDelete = DatabaseHelper.getAccountByName(username); + + if (toDelete == null) { + CommandHandler.sendMessage(null, translate(sender, "commands.account.no_account")); + return; } + + // Get the player for the account. + // If that player is currently online, we kick them before proceeding with the deletion. + Player player = Grasscutter.getGameServer().getPlayerByAccountId(toDelete.getId()); + if (player != null) { + player.getSession().close(); + } + + // Finally, we do the actual deletion. + DatabaseHelper.deleteAccount(toDelete); + CommandHandler.sendMessage(null, translate(sender, "commands.account.delete")); } } } diff --git a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java index 1aa234919..163db3891 100644 --- a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java @@ -9,14 +9,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "broadcast", usage = "broadcast ", - description = "Sends a message to all the players", aliases = {"b"}, permission = "server.broadcast") +@Command(label = "broadcast", usage = "broadcast ", aliases = {"b"}, permission = "server.broadcast", description = "commands.broadcast.description", targetRequirement = Command.TargetRequirement.NONE) public final class BroadcastCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { if (args.size() < 1) { - CommandHandler.sendMessage(sender, translate("commands.broadcast.command_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.broadcast.command_usage")); return; } @@ -26,6 +25,6 @@ public final class BroadcastCommand implements CommandHandler { CommandHandler.sendMessage(p, message); } - CommandHandler.sendMessage(sender, translate("commands.broadcast.message_sent")); + CommandHandler.sendMessage(sender, translate(sender, "commands.broadcast.message_sent")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java index 1a4e97927..3d41205cc 100644 --- a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java @@ -8,36 +8,32 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "changescene", usage = "changescene ", - description = "Changes your scene", aliases = {"scene"}, permission = "player.changescene") +@Command(label = "changescene", usage = "changescene ", aliases = {"scene"}, permission = "player.changescene", permissionTargeted = "player.changescene.others", description = "commands.changescene.description") public final class ChangeSceneCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() != 1) { - CommandHandler.sendMessage(sender, translate("commands.changescene.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.changescene.usage")); return; } try { int sceneId = Integer.parseInt(args.get(0)); if (sceneId == targetPlayer.getSceneId()) { - CommandHandler.sendMessage(sender, translate("commands.changescene.already_in_scene")); + CommandHandler.sendMessage(sender, translate(sender, "commands.changescene.already_in_scene")); return; } boolean result = targetPlayer.getWorld().transferPlayerToScene(targetPlayer, sceneId, targetPlayer.getPos()); - CommandHandler.sendMessage(sender, translate("commands.changescene.result", Integer.toString(sceneId))); - if (!result) { - CommandHandler.sendMessage(sender, translate("commands.changescene.exists_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.changescene.exists_error")); + return; } + + CommandHandler.sendMessage(sender, translate(sender, "commands.changescene.success", Integer.toString(sceneId))); } catch (Exception e) { - CommandHandler.sendMessage(sender, translate("commands.execution.argument_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); } } } diff --git a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java index 47d9f2c0d..d28957450 100644 --- a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java @@ -13,19 +13,15 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "clear", usage = "clear ", //Merged /clearartifacts and /clearweapons to /clear [uid] - description = "Deletes unequipped unlocked items, including yellow rarity ones from your inventory", - aliases = {"clear"}, permission = "player.clearinv") + description = "commands.clear.description", + aliases = {"clear"}, permission = "player.clearinv", permissionTargeted = "player.clearinv.others") public final class ClearCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } if (args.size() < 1) { - CommandHandler.sendMessage(sender, translate("commands.clear.command_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.command_usage")); return; } Inventory playerInventory = targetPlayer.getInventory(); @@ -37,7 +33,7 @@ public final class ClearCommand implements CommandHandler { .filter(item -> item.getItemType() == ItemType.ITEM_WEAPON) .filter(item -> !item.isLocked() && !item.isEquipped()) .toList(); - CommandHandler.sendMessage(sender, translate("commands.clear.weapons", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.weapons", targetPlayer.getNickname())); } case "art" -> { toDelete = playerInventory.getItems().values().stream() @@ -45,7 +41,7 @@ public final class ClearCommand implements CommandHandler { .filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> !item.isLocked() && !item.isEquipped()) .toList(); - CommandHandler.sendMessage(sender, translate("commands.clear.artifacts", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.artifacts", targetPlayer.getNickname())); } case "mat" -> { toDelete = playerInventory.getItems().values().stream() @@ -53,7 +49,7 @@ public final class ClearCommand implements CommandHandler { .filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> !item.isLocked() && !item.isEquipped()) .toList(); - CommandHandler.sendMessage(sender, translate("commands.clear.materials", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.materials", targetPlayer.getNickname())); } case "all" -> { toDelete = playerInventory.getItems().values().stream() @@ -61,7 +57,7 @@ public final class ClearCommand implements CommandHandler { .filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0) .filter(item1 -> !item1.isLocked() && !item1.isEquipped()) .toList(); - CommandHandler.sendMessage(sender, translate("commands.clear.artifacts", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.artifacts", targetPlayer.getNickname())); playerInventory.removeItems(toDelete); toDelete = playerInventory.getItems().values().stream() @@ -69,7 +65,7 @@ public final class ClearCommand implements CommandHandler { .filter(item2 -> !item2.isLocked() && !item2.isEquipped()) .toList(); playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate("commands.clear.materials", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.materials", targetPlayer.getNickname())); toDelete = playerInventory.getItems().values().stream() .filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON) @@ -77,28 +73,28 @@ public final class ClearCommand implements CommandHandler { .filter(item3 -> !item3.isLocked() && !item3.isEquipped()) .toList(); playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate("commands.clear.weapons", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.weapons", targetPlayer.getNickname())); toDelete = playerInventory.getItems().values().stream() .filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE) .filter(item4 -> !item4.isLocked() && !item4.isEquipped()) .toList(); playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate("commands.clear.furniture", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.furniture", targetPlayer.getNickname())); toDelete = playerInventory.getItems().values().stream() .filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY) .filter(item5 -> !item5.isLocked() && !item5.isEquipped()) .toList(); playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate("commands.clear.displays", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.displays", targetPlayer.getNickname())); toDelete = playerInventory.getItems().values().stream() .filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL) .filter(item6 -> !item6.isLocked() && !item6.isEquipped()) .toList(); - CommandHandler.sendMessage(sender, translate("commands.clear.virtuals", targetPlayer.getNickname())); - CommandHandler.sendMessage(sender, translate("commands.clear.everything", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.virtuals", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.clear.everything", targetPlayer.getNickname())); } } diff --git a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java index 96411019b..c8961340e 100644 --- a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java @@ -9,20 +9,15 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "coop", usage = "coop [host UID]", - description = "Forces someone to join the world of others", permission = "server.coop") +@Command(label = "coop", usage = "coop [host uid]", permission = "server.coop", permissionTargeted = "server.coop.others", description = "commands.coop.description") public final class CoopCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - Player host = sender; switch (args.size()) { case 0: // Summon target to self - CommandHandler.sendMessage(sender, translate("commands.coop.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.coop.usage")); if (sender == null) // Console doesn't have a self to summon to return; break; @@ -31,16 +26,16 @@ public final class CoopCommand implements CommandHandler { int hostId = Integer.parseInt(args.get(0)); host = Grasscutter.getGameServer().getPlayerByUid(hostId); if (host == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.player_offline_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.player_offline_error")); return; } break; } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.execution.uid_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.uid_error")); return; } default: - CommandHandler.sendMessage(sender, translate("commands.coop.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.coop.usage")); return; } @@ -50,6 +45,6 @@ public final class CoopCommand implements CommandHandler { } host.getServer().getMultiplayerManager().applyEnterMp(targetPlayer, host.getUid()); targetPlayer.getServer().getMultiplayerManager().applyEnterMpReply(host, targetPlayer.getUid(), true); - CommandHandler.sendMessage(sender, translate("commands.coop.success", targetPlayer.getNickname(), host.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.coop.success", targetPlayer.getNickname(), host.getNickname())); } } diff --git a/src/main/java/emu/grasscutter/command/commands/DropCommand.java b/src/main/java/emu/grasscutter/command/commands/DropCommand.java index a33a32603..ce1a1761b 100644 --- a/src/main/java/emu/grasscutter/command/commands/DropCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/DropCommand.java @@ -4,7 +4,7 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.player.Player; import emu.grasscutter.utils.Position; @@ -13,17 +13,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "drop", usage = "drop [amount]", - description = "Drops an item near you", aliases = {"d", "dropitem"}, permission = "server.drop") +@Command(label = "drop", usage = "drop [amount]", aliases = {"d", "dropitem"}, permission = "server.drop", permissionTargeted = "server.drop.others", description = "commands.drop.description") public final class DropCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(null, translate("commands.execution.need_target")); - return; - } - int item = 0; int amount = 1; @@ -32,25 +26,25 @@ public final class DropCommand implements CommandHandler { try { amount = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.amount")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount")); return; } // Slightly cheeky here: no break, so it falls through to initialize the first argument too case 1: try { item = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId")); return; } break; default: - CommandHandler.sendMessage(sender, translate("commands.drop.command_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.drop.command_usage")); return; } ItemData itemData = GameData.getItemDataMap().get(item); if (itemData == null) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId")); return; } if (itemData.isEquip()) { @@ -64,6 +58,6 @@ public final class DropCommand implements CommandHandler { EntityItem entity = new EntityItem(targetPlayer.getScene(), targetPlayer, itemData, targetPlayer.getPos().clone().addY(3f), amount); targetPlayer.getScene().addEntity(entity); } - CommandHandler.sendMessage(sender, translate("commands.drop.success", Integer.toString(amount), Integer.toString(item))); + CommandHandler.sendMessage(sender, translate(sender, "commands.drop.success", Integer.toString(amount), Integer.toString(item))); } -} \ No newline at end of file +} diff --git a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java index 434e80c8f..33e25dca3 100644 --- a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java @@ -8,36 +8,31 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "enterdungeon", usage = "enterdungeon ", - description = "Enter a dungeon", aliases = {"dungeon"}, permission = "player.enterdungeon") +@Command(label = "enterdungeon", usage = "enterdungeon ", aliases = {"dungeon"}, permission = "player.enterdungeon", permissionTargeted = "player.enterdungeon.others", description = "commands.enter_dungeon.description") public final class EnterDungeonCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(null, translate("commands.execution.need_target")); - return; - } - if (args.size() < 1) { - CommandHandler.sendMessage(sender, translate("commands.enter_dungeon.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.usage")); return; } try { int dungeonId = Integer.parseInt(args.get(0)); if (dungeonId == targetPlayer.getSceneId()) { - CommandHandler.sendMessage(sender, translate("commands.enter_dungeon.in_dungeon_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.in_dungeon_error")); return; } boolean result = targetPlayer.getServer().getDungeonManager().enterDungeon(targetPlayer.getSession().getPlayer(), 0, dungeonId); - CommandHandler.sendMessage(sender, translate("commands.enter_dungeon.changed", dungeonId)); + CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.changed", dungeonId)); if (!result) { - CommandHandler.sendMessage(sender, translate("commands.enter_dungeon.not_found_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.not_found_error")); } } catch (Exception e) { - CommandHandler.sendMessage(sender, translate("commands.enter_dungeon.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.usage")); } } } diff --git a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java index bb11de3c2..12c8526a5 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java @@ -4,8 +4,8 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.ItemType; @@ -15,16 +15,11 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveall", usage = "giveall [amount]", - description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true) +@Command(label = "giveall", usage = "giveall [amount]", aliases = {"givea"}, permission = "player.giveall", permissionTargeted = "player.giveall.others", threading = true, description = "commands.giveAll.description") public final class GiveAllCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } int amount = 99999; switch (args.size()) { @@ -34,21 +29,21 @@ public final class GiveAllCommand implements CommandHandler { try { amount = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.amount")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount")); return; } break; default: // invalid - CommandHandler.sendMessage(sender, translate("commands.giveAll.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveAll.usage")); return; } this.giveAllItems(targetPlayer, amount); - CommandHandler.sendMessage(sender, translate("commands.giveAll.success", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(targetPlayer, "commands.giveAll.success", targetPlayer.getNickname())); } public void giveAllItems(Player player, int amount) { - CommandHandler.sendMessage(player, translate("commands.giveAll.started")); + CommandHandler.sendMessage(player, translate(player, "commands.giveAll.started")); for (AvatarData avatarData: GameData.getAvatarDataMap().values()) { //Exclude test avatar @@ -62,7 +57,8 @@ public final class GiveAllCommand implements CommandHandler { } // This will handle stats and talents avatar.recalcStats(); - player.addAvatar(avatar); + // Don't try to add each avatar to the current team + player.addAvatar(avatar, false); } //some test items @@ -159,7 +155,7 @@ public final class GiveAllCommand implements CommandHandler { private static final Integer[] testItemsIds = new Integer[] { 210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202,10366, 101212, 11411, 11506, 11507, 11508, 12505, 12506, 12508, 12509, 13503, - 13506, 14411, 14503, 14505, 14508, 15411, 15504, 15505, 15506, 15508, + 13506, 14411, 14503, 14505, 14508, 15504, 15505, 15506, 20001, 10002, 10003, 10004, 10005, 10006, 10008,100231,100232,100431, 101689,105001,105004, 106000,106001,108000,110000 }; diff --git a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java index 541cc440e..eaa0635dc 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java @@ -4,53 +4,158 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.inventory.EquipType; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import static java.util.Map.entry; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveart", usage = "giveart [[,]]... [level]", description = "Gives the player a specified artifact", aliases = {"gart"}, permission = "player.giveart") +@Command(label = "giveart", usage = "giveart [[,]]... [level]", aliases = {"gart"}, permission = "player.giveart", permissionTargeted = "player.giveart.others", description = "commands.giveArtifact.description") public final class GiveArtifactCommand implements CommandHandler { + private static final Map> mainPropMap = Map.ofEntries( + entry("hp", Map.ofEntries(entry(EquipType.EQUIP_BRACER, 14001))), + entry("hp%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10980), entry(EquipType.EQUIP_RING, 50980), entry(EquipType.EQUIP_DRESS, 30980))), + entry("atk", Map.ofEntries(entry(EquipType.EQUIP_NECKLACE, 12001))), + entry("atk%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10990), entry(EquipType.EQUIP_RING, 50990), entry(EquipType.EQUIP_DRESS, 30990))), + entry("def%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10970), entry(EquipType.EQUIP_RING, 50970), entry(EquipType.EQUIP_DRESS, 30970))), + entry("er", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10960))), + entry("em", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10950), entry(EquipType.EQUIP_RING, 50880), entry(EquipType.EQUIP_DRESS, 30930))), + entry("hb", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30940))), + entry("cdmg", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30950))), + entry("cr", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30960))), + entry("phys%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50890))), + entry("dendro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50900))), + entry("geo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50910))), + entry("anemo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50920))), + entry("hydro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50930))), + entry("cryo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50940))), + entry("electro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50950))), + entry("pyro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50960))) + ); + private static final Map appendPropMap = Map.ofEntries( + entry("hp", "0102"), + entry("hp%", "0103"), + entry("atk", "0105"), + entry("atk%", "0106"), + entry("def", "0108"), + entry("def%", "0109"), + entry("er", "0123"), + entry("em", "0124"), + entry("cr", "0120"), + entry("cdmg", "0122") + ); + + private int getAppendPropId(String substatText, ItemData itemData) { + int res; + + // If the given substat text is an integer, we just use that + // as the append prop ID. + try { + res = Integer.parseInt(substatText); + return res; + } + catch (NumberFormatException ignores) { + // No need to handle this here. We just continue with the + // possibility of the argument being a substat string. + } + + // If the argument was not an integer, we try to determine + // the append prop ID from the given text + artifact information. + // A substat string has the format `substat_tier`, with the + // `_tier` part being optional. + String[] substatArgs = substatText.split("_"); + String substatType; + int substatTier; + + if (substatArgs.length == 1) { + substatType = substatArgs[0]; + substatTier = + itemData.getRankLevel() == 1 ? 2 + : itemData.getRankLevel() == 2 ? 3 + : 4; + } + else if (substatArgs.length == 2) { + substatType = substatArgs[0]; + substatTier = Integer.parseInt(substatArgs[1]); + } + else { + throw new IllegalArgumentException(); + } + + // Check if the specified tier is legal for the artifact rarity. + if (substatTier < 1 || substatTier > 4) { + throw new IllegalArgumentException(); + } + if (itemData.getRankLevel() == 1 && substatTier > 2) { + throw new IllegalArgumentException(); + } + if (itemData.getRankLevel() == 2 && substatTier > 3) { + throw new IllegalArgumentException(); + } + + // Check if the given substat type string is a legal stat. + if (!appendPropMap.containsKey(substatType)) { + throw new IllegalArgumentException(); + } + + // Build the append prop ID. + return Integer.parseInt(Integer.toString(itemData.getRankLevel()) + appendPropMap.get(substatType) + Integer.toString(substatTier)); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - + // Sanity check if (args.size() < 2) { - CommandHandler.sendMessage(sender, translate("commands.giveArtifact.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.usage")); return; } + // Get the artifact piece ID from the arguments. int itemId; try { itemId = Integer.parseInt(args.remove(0)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.giveArtifact.id_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.id_error")); return; } + ItemData itemData = GameData.getItemDataMap().get(itemId); if (itemData.getItemType() != ItemType.ITEM_RELIQUARY) { - CommandHandler.sendMessage(sender, translate("commands.giveArtifact.id_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.id_error")); return; } + // Get the main stat from the arguments. + // If the given argument is an integer, we use that. + // If not, we check if the argument string is in the main prop map. + String mainPropIdString = args.remove(0); int mainPropId; + try { - mainPropId = Integer.parseInt(args.remove(0)); + mainPropId = Integer.parseInt(mainPropIdString); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.execution.argument_error")); + mainPropId = -1; + } + + if (mainPropMap.containsKey(mainPropIdString) && mainPropMap.get(mainPropIdString).containsKey(itemData.getEquipType())) { + mainPropId = mainPropMap.get(mainPropIdString).get(itemData.getEquipType()); + } + + if (mainPropId == -1) { + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); return; } + // Get the level from the arguments. int level = 1; try { int last = Integer.parseInt(args.get(args.size()-1)); @@ -61,9 +166,13 @@ public final class GiveArtifactCommand implements CommandHandler { } catch (NumberFormatException ignored) { // Could be a stat,times string so no need to panic } - List appendPropIdList = new ArrayList<>(); + // Get substats. + ArrayList appendPropIdList = new ArrayList<>(); try { + // Every remaining argument is a substat. args.forEach(it -> { + // The substat syntax permits specifying a number of rolls for the given + // substat. Split the string into stat and number if that is the case here. String[] arr; int n = 1; if ((arr = it.split(",")).length == 2) { @@ -73,13 +182,19 @@ public final class GiveArtifactCommand implements CommandHandler { n = 200; } } - appendPropIdList.addAll(Collections.nCopies(n, Integer.parseInt(it))); + + // Determine the substat ID. + int appendPropId = getAppendPropId(it, itemData); + + // Add the current substat. + appendPropIdList.addAll(Collections.nCopies(n, appendPropId)); }); } catch (Exception ignored) { - CommandHandler.sendMessage(sender, translate("commands.execution.argument_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); return; } + // Create item for the artifact. GameItem item = new GameItem(itemData); item.setLevel(level); item.setMainPropId(mainPropId); @@ -87,7 +202,7 @@ public final class GiveArtifactCommand implements CommandHandler { item.getAppendPropIdList().addAll(appendPropIdList); targetPlayer.getInventory().addItem(item, ActionReason.SubfieldDrop); - CommandHandler.sendMessage(sender, translate("commands.giveArtifact.success", Integer.toString(itemId), Integer.toString(targetPlayer.getUid()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.success", Integer.toString(itemId), Integer.toString(targetPlayer.getUid()))); } } diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java index 4b3279202..34592fb81 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java @@ -4,7 +4,7 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarData; +import emu.grasscutter.data.excels.AvatarData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.player.Player; @@ -12,17 +12,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "givechar", usage = "givechar [level]", - description = "Gives the player a specified character", aliases = {"givec"}, permission = "player.givechar") +@Command(label = "givechar", usage = "givechar [level]", aliases = {"givec"}, permission = "player.givechar", permissionTargeted = "player.givechar.others", description = "commands.giveChar.description") public final class GiveCharCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - int avatarId; int level = 1; @@ -32,7 +26,7 @@ public final class GiveCharCommand implements CommandHandler { level = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { // TODO: Parse from avatar name using GM Handbook. - CommandHandler.sendMessage(sender, translate("commands.execution.invalid.avatarLevel")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarLevel")); return; } // Cheeky fall-through to parse first argument too case 1: @@ -40,33 +34,34 @@ public final class GiveCharCommand implements CommandHandler { avatarId = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { // TODO: Parse from avatar name using GM Handbook. - CommandHandler.sendMessage(sender, translate("commands.execution.invalid.avatarId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarId")); return; } break; default: - CommandHandler.sendMessage(sender, translate("commands.giveChar.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveChar.usage")); return; } AvatarData avatarData = GameData.getAvatarDataMap().get(avatarId); if (avatarData == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.invalid.avatarId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarId")); return; } // Check level. if (level > 90) { - CommandHandler.sendMessage(sender, translate("commands.execution.invalid.avatarLevel")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarLevel")); return; } // Calculate ascension level. int ascension; if (level <= 40) { - ascension = (int) Math.ceil(level / 20f); + ascension = (int) Math.ceil(level / 20f) - 1; } else { ascension = (int) Math.ceil(level / 10f) - 3; + ascension = Math.min(ascension, 6); } Avatar avatar = new Avatar(avatarId); @@ -77,6 +72,6 @@ public final class GiveCharCommand implements CommandHandler { avatar.recalcStats(); targetPlayer.addAvatar(avatar); - CommandHandler.sendMessage(sender, translate("commands.giveChar.given", Integer.toString(avatarId), Integer.toString(level), Integer.toString(targetPlayer.getUid()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.giveChar.given", Integer.toString(avatarId), Integer.toString(level), Integer.toString(targetPlayer.getUid()))); } } diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java index 2f020f7b3..dbe02a1cd 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java @@ -1,10 +1,9 @@ package emu.grasscutter.command.commands; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.player.Player; @@ -12,13 +11,13 @@ import emu.grasscutter.game.props.ActionReason; import java.util.LinkedList; import java.util.List; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; import static emu.grasscutter.utils.Language.translate; -@Command(label = "give", usage = "give [amount] [level]", description = "Gives an item to you or the specified player", aliases = { - "g", "item", "giveitem"}, permission = "player.give") +@Command(label = "give", usage = "give [amount] [level]", aliases = { + "g", "item", "giveitem"}, permission = "player.give", permissionTargeted = "player.give.others", description = "commands.give.description") public final class GiveCommand implements CommandHandler { Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java is a joke of a proglang that doesn't have raw string literals Pattern refineRegex = Pattern.compile("r(\\d+)"); @@ -34,10 +33,6 @@ public final class GiveCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } int item; int lvl = 1; int amount = 1; @@ -69,21 +64,21 @@ public final class GiveCommand implements CommandHandler { try { refinement = Integer.parseInt(args.get(3)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemRefinement")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemRefinement")); return; } // Fallthrough case 3: // [amount] [level] try { lvl = Integer.parseInt(args.get(2)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemLevel")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemLevel")); return; } // Fallthrough case 2: // [amount] try { amount = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.amount")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount")); return; } // Fallthrough case 1: // @@ -91,28 +86,28 @@ public final class GiveCommand implements CommandHandler { item = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { // TODO: Parse from item name using GM Handbook. - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId")); return; } break; default: // *No args* - CommandHandler.sendMessage(sender, translate("commands.give.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.usage")); return; } ItemData itemData = GameData.getItemDataMap().get(item); if (itemData == null) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId")); return; } if (refinement != 0) { if (itemData.getItemType() == ItemType.ITEM_WEAPON) { if (refinement < 1 || refinement > 5) { - CommandHandler.sendMessage(sender, translate("commands.give.refinement_must_between_1_and_5")); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.refinement_must_between_1_and_5")); return; } } else { - CommandHandler.sendMessage(sender, translate("commands.give.refinement_only_applicable_weapons")); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.refinement_only_applicable_weapons")); return; } } @@ -120,11 +115,11 @@ public final class GiveCommand implements CommandHandler { this.item(targetPlayer, itemData, amount, lvl, refinement); if (!itemData.isEquip()) { - CommandHandler.sendMessage(sender, translate("commands.give.given", Integer.toString(amount), Integer.toString(item), Integer.toString(targetPlayer.getUid()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.given", Integer.toString(amount), Integer.toString(item), Integer.toString(targetPlayer.getUid()))); } else if (itemData.getItemType() == ItemType.ITEM_WEAPON) { - CommandHandler.sendMessage(sender, translate("commands.give.given_with_level_and_refinement", Integer.toString(item), Integer.toString(lvl), Integer.toString(refinement), Integer.toString(amount), Integer.toString(targetPlayer.getUid()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.given_with_level_and_refinement", Integer.toString(item), Integer.toString(lvl), Integer.toString(refinement), Integer.toString(amount), Integer.toString(targetPlayer.getUid()))); } else { - CommandHandler.sendMessage(sender, translate("commands.give.given_level", Integer.toString(item), Integer.toString(lvl), Integer.toString(amount))); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.given_level", Integer.toString(item), Integer.toString(lvl), Integer.toString(amount), Integer.toString(targetPlayer.getUid()))); } } diff --git a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java index 9abebb8db..0b635b897 100644 --- a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java @@ -1,6 +1,5 @@ package emu.grasscutter.command.commands; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.game.player.Player; @@ -9,17 +8,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "godmode", usage = "godmode [on|off|toggle]", - description = "Prevents you from taking damage. Defaults to toggle.", permission = "player.godmode") +@Command(label = "godmode", usage = "godmode [on|off|toggle]", permission = "player.godmode", permissionTargeted = "player.godmode.others", description = "commands.godmode.description") public final class GodModeCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - boolean enabled = !targetPlayer.inGodmode(); if (args.size() == 1) { switch (args.get(0).toLowerCase()) { @@ -37,6 +30,6 @@ public final class GodModeCommand implements CommandHandler { } targetPlayer.setGodmode(enabled); - CommandHandler.sendMessage(sender, translate("commands.godmode.success", (enabled ? translate("commands.status.enabled") : translate("commands.status.disabled")), targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.godmode.success", (enabled ? translate(sender, "commands.status.enabled") : translate(sender, "commands.status.disabled")), targetPlayer.getNickname())); } } diff --git a/src/main/java/emu/grasscutter/command/commands/HealCommand.java b/src/main/java/emu/grasscutter/command/commands/HealCommand.java index bb0b861b0..56354d676 100644 --- a/src/main/java/emu/grasscutter/command/commands/HealCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HealCommand.java @@ -11,16 +11,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "heal", usage = "heal|h", aliases = {"h"}, - description = "Heal all characters in your current team.", permission = "player.heal") +@Command(label = "heal", usage = "heal|h", aliases = {"h"}, permission = "player.heal", permissionTargeted = "player.heal.others", description = "commands.heal.description") public final class HealCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - targetPlayer.getTeamManager().getActiveTeam().forEach(entity -> { boolean isAlive = entity.isAlive(); entity.setFightProperty( @@ -32,6 +27,6 @@ public final class HealCommand implements CommandHandler { entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); } }); - CommandHandler.sendMessage(sender, translate("commands.heal.success")); + CommandHandler.sendMessage(sender, translate(sender, "commands.heal.success")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java index 93ac831b3..431890fda 100644 --- a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java @@ -10,8 +10,7 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "help", usage = "help [command]", - description = "Sends the help message or shows information about a specified command") +@Command(label = "help", usage = "help [command]", description = "commands.help.description", targetRequirement = Command.TargetRequirement.NONE) public final class HelpCommand implements CommandHandler { @Override @@ -33,16 +32,16 @@ public final class HelpCommand implements CommandHandler { } else { String command = args.get(0); CommandHandler handler = CommandMap.getInstance().getHandler(command); - StringBuilder builder = new StringBuilder(player == null ? "\n" + translate("commands.status.help") + " - " : translate("commands.status.help") + " - ").append(command).append(": \n"); + StringBuilder builder = new StringBuilder(player == null ? "\n" + translate(player, "commands.status.help") + " - " : translate(player, "commands.status.help") + " - ").append(command).append(": \n"); if (handler == null) { - builder.append(translate("commands.generic.command_exist_error")); + builder.append(translate(player, "commands.generic.command_exist_error")); } else { Command annotation = handler.getClass().getAnnotation(Command.class); - builder.append(" ").append(annotation.description()).append("\n"); - builder.append(translate("commands.help.usage")).append(annotation.usage()); + builder.append(" ").append(translate(player, annotation.description())).append("\n"); + builder.append(translate(player, "commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { - builder.append("\n").append(translate("commands.help.aliases")); + builder.append("\n").append(translate(player, "commands.help.aliases")); for (String alias : annotation.aliases()) { builder.append(alias).append(" "); } @@ -58,13 +57,13 @@ public final class HelpCommand implements CommandHandler { void SendAllHelpMessage(Player player, List annotations) { if (player == null) { - StringBuilder builder = new StringBuilder("\n" + translate("commands.help.available_commands") + "\n"); + StringBuilder builder = new StringBuilder("\n" + translate(player, "commands.help.available_commands") + "\n"); annotations.forEach(annotation -> { builder.append(annotation.label()).append("\n"); - builder.append(" ").append(annotation.description()).append("\n"); - builder.append(translate("commands.help.usage")).append(annotation.usage()); + builder.append(" ").append(translate(player, annotation.description())).append("\n"); + builder.append(translate(player, "commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { - builder.append("\n").append(translate("commands.help.aliases")); + builder.append("\n").append(translate(player, "commands.help.aliases")); for (String alias : annotation.aliases()) { builder.append(alias).append(" "); } @@ -75,13 +74,13 @@ public final class HelpCommand implements CommandHandler { CommandHandler.sendMessage(null, builder.toString()); } else { - CommandHandler.sendMessage(player, translate("commands.help.available_commands")); + CommandHandler.sendMessage(player, translate(player, "commands.help.available_commands")); annotations.forEach(annotation -> { StringBuilder builder = new StringBuilder(annotation.label()).append("\n"); - builder.append(" ").append(annotation.description()).append("\n"); - builder.append(translate("commands.help.usage")).append(annotation.usage()); + builder.append(" ").append(translate(player, annotation.description())).append("\n"); + builder.append(translate(player, "commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { - builder.append("\n").append(translate("commands.help.aliases")); + builder.append("\n").append(translate(player, "commands.help.aliases")); for (String alias : annotation.aliases()) { builder.append(alias).append(" "); } diff --git a/src/main/java/emu/grasscutter/command/commands/KickCommand.java b/src/main/java/emu/grasscutter/command/commands/KickCommand.java index 270e28150..546fe905d 100644 --- a/src/main/java/emu/grasscutter/command/commands/KickCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KickCommand.java @@ -8,23 +8,17 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "kick", usage = "kick", - description = "Kicks the specified player from the server (WIP)", permission = "server.kick") +@Command(label = "kick", usage = "kick", permission = "server.kick", description = "commands.kick.description") public final class KickCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (sender != null) { - CommandHandler.sendMessage(sender, translate("commands.kick.player_kick_player", - Integer.toString(sender.getAccount().getPlayerUid()), sender.getAccount().getUsername(), + CommandHandler.sendMessage(sender, translate(sender, "commands.kick.player_kick_player", + Integer.toString(sender.getUid()), sender.getAccount().getUsername(), Integer.toString(targetPlayer.getUid()), targetPlayer.getAccount().getUsername())); } else { - CommandHandler.sendMessage(null, translate("commands.kick.server_kick_player", Integer.toString(targetPlayer.getUid()), targetPlayer.getAccount().getUsername())); + CommandHandler.sendMessage(null, translate(sender, "commands.kick.server_kick_player", Integer.toString(targetPlayer.getUid()), targetPlayer.getAccount().getUsername())); } targetPlayer.getSession().close(); diff --git a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java index 423c60bbd..6361a726f 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java @@ -12,17 +12,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killall", usage = "killall [sceneId]", - description = "Kill all entities", permission = "server.killall") +@Command(label = "killall", usage = "killall [sceneId]", permission = "server.killall", permissionTargeted = "server.killall.others", description = "commands.killall.description") public final class KillAllCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - Scene scene = targetPlayer.getScene(); try { switch (args.size()) { @@ -32,14 +26,14 @@ public final class KillAllCommand implements CommandHandler { scene = targetPlayer.getWorld().getSceneById(Integer.parseInt(args.get(0))); break; default: - CommandHandler.sendMessage(sender, translate("commands.kill.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.killall.usage")); return; } } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.execution.argument_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); } if (scene == null) { - CommandHandler.sendMessage(sender, translate("commands.kill.scene_not_found_in_player_world")); + CommandHandler.sendMessage(sender, translate(sender, "commands.killall.scene_not_found_in_player_world")); return; } @@ -49,6 +43,6 @@ public final class KillAllCommand implements CommandHandler { .filter(entity -> entity instanceof EntityMonster) .toList(); toKill.forEach(entity -> sceneF.killEntity(entity, 0)); - CommandHandler.sendMessage(sender, translate("commands.kill.kill_monsters_in_scene", Integer.toString(toKill.size()), Integer.toString(scene.getId()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.killall.kill_monsters_in_scene", Integer.toString(toKill.size()), Integer.toString(scene.getId()))); } } diff --git a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java index f1e0f0f8c..9f811373d 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java @@ -13,14 +13,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, - description = "Kills the players current character", permission = "player.killcharacter") +@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, permission = "player.killcharacter", permissionTargeted = "player.killcharacter.others", description = "commands.killCharacter.description") public final class KillCharacterCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); + if (args.isEmpty()) { + CommandHandler.sendMessage(sender, translate(sender, "commands.killCharacter.usage")); return; } @@ -33,6 +32,6 @@ public final class KillCharacterCommand implements CommandHandler { targetPlayer.getScene().removeEntity(entity); entity.onDeath(0); - CommandHandler.sendMessage(sender, translate("commands.killCharacter.success", targetPlayer.getNickname())); + CommandHandler.sendMessage(sender, translate(sender, "commands.killCharacter.success", targetPlayer.getNickname())); } } diff --git a/src/main/java/emu/grasscutter/command/commands/LanguageCommand.java b/src/main/java/emu/grasscutter/command/commands/LanguageCommand.java new file mode 100644 index 000000000..bd5c6f3ec --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/LanguageCommand.java @@ -0,0 +1,57 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.utils.Utils; + +import java.util.List; +import java.util.Locale; + +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "language", usage = "language [language code]", description = "commands.language.description", aliases = {"lang"}, targetRequirement = Command.TargetRequirement.NONE) +public final class LanguageCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.isEmpty()) { + String curLangCode = null; + if (sender != null) { + curLangCode = Utils.getLanguageCode(sender.getAccount().getLocale()); + } + else { + curLangCode = Grasscutter.getLanguage().getLanguageCode(); + } + CommandHandler.sendMessage(sender, translate(sender, "commands.language.current_language", curLangCode)); + return; + } + + String langCode = args.get(0); + + var languageInst = Grasscutter.getLanguage(langCode); + var actualLangCode = languageInst.getLanguageCode(); + var locale = Locale.forLanguageTag(actualLangCode); + if (sender != null) { + var account = sender.getAccount(); + account.setLocale(locale); + account.save(); + } + else { + Grasscutter.setLanguage(languageInst); + var config = Grasscutter.getConfig(); + config.language.language = locale; + Grasscutter.saveConfig(config); + } + + if (!langCode.equals(actualLangCode)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.language.language_not_found", langCode)); + } + + CommandHandler.sendMessage(sender, translate(sender, "commands.language.language_changed", actualLangCode)); + + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/ListCommand.java b/src/main/java/emu/grasscutter/command/commands/ListCommand.java index bc35e65e1..1e6906cc8 100644 --- a/src/main/java/emu/grasscutter/command/commands/ListCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ListCommand.java @@ -10,8 +10,7 @@ import java.util.Map; import static emu.grasscutter.utils.Language.translate; -@Command(label = "list", usage = "list [uid]", - description = "List online players", aliases = {"players"}) +@Command(label = "list", usage = "list [uid]", aliases = {"players"}, description = "commands.list.description", targetRequirement = Command.TargetRequirement.NONE) public final class ListCommand implements CommandHandler { @Override @@ -23,7 +22,7 @@ public final class ListCommand implements CommandHandler { needUID = args.get(0).equals("uid"); } - CommandHandler.sendMessage(sender, translate("commands.list.success", Integer.toString(playersMap.size()))); + CommandHandler.sendMessage(sender, translate(sender, "commands.list.success", Integer.toString(playersMap.size()))); if (playersMap.size() != 0) { StringBuilder playerSet = new StringBuilder(); diff --git a/src/main/java/emu/grasscutter/command/commands/NoStaminaCommand.java b/src/main/java/emu/grasscutter/command/commands/NoStaminaCommand.java new file mode 100644 index 000000000..4a1ef8873 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/NoStaminaCommand.java @@ -0,0 +1,34 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; + +import java.util.List; + +import static emu.grasscutter.utils.Language.translate; + + +@Command(label = "nostamina", usage = "nostamina [on|off|toggle]", aliases = {"ns"}, permission = "player.nostamina", permissionTargeted = "player.nostamina.others", description = "commands.nostamina.description") +public final class NoStaminaCommand implements CommandHandler { + @Override + public void execute(Player sender, Player targetPlayer, List args) { + boolean stamina = !targetPlayer.getStamina(); + if (args.size() == 1) { + switch (args.get(0).toLowerCase()) { + case "on": + stamina = true; + break; + case "off": + stamina = false; + break; + default: + // toggled + break; + } + } + targetPlayer.setStamina(stamina); //Set + + CommandHandler.sendMessage(sender, translate(sender, "commands.nostamina.success", (stamina ? translate(sender, "commands.status.enabled") : translate(sender, "commands.status.disabled")), targetPlayer.getNickname())); + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java index 69c8ce899..8efc8de43 100644 --- a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java @@ -10,19 +10,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "permission", usage = "permission ", - description = "Grants or removes a permission for a user", permission = "*") +@Command(label = "permission", usage = "permission ", permission = "permission", description = "commands.permission.description") public final class PermissionCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() != 2) { - CommandHandler.sendMessage(sender, translate("commands.permission.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.permission.usage")); return; } @@ -31,26 +25,26 @@ public final class PermissionCommand implements CommandHandler { Account account = targetPlayer.getAccount(); if (account == null) { - CommandHandler.sendMessage(sender, translate("commands.permission.account_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.permission.account_error")); return; } switch (action) { default: - CommandHandler.sendMessage(sender, translate("commands.permission.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.permission.usage")); break; case "add": if (account.addPermission(permission)) { - CommandHandler.sendMessage(sender, translate("commands.permission.add")); - } else CommandHandler.sendMessage(sender, translate("commands.permission.has_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.permission.add")); + } else CommandHandler.sendMessage(sender, translate(sender, "commands.permission.has_error")); break; case "remove": if (account.removePermission(permission)) { - CommandHandler.sendMessage(sender, translate("commands.permission.remove")); - } else CommandHandler.sendMessage(sender, translate("commands.permission.not_have_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.permission.remove")); + } else CommandHandler.sendMessage(sender, translate(sender, "commands.permission.not_have_error")); break; } account.save(); } -} \ No newline at end of file +} diff --git a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java index 7f6548c5b..221afe801 100644 --- a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java @@ -9,19 +9,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "position", usage = "position", aliases = {"pos"}, - description = "Get coordinates.") +@Command(label = "position", usage = "position", aliases = {"pos"}, description = "commands.position.description") public final class PositionCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - Position pos = targetPlayer.getPos(); - CommandHandler.sendMessage(sender, translate("commands.position.success", + CommandHandler.sendMessage(sender, translate(sender, "commands.position.success", Float.toString(pos.getX()), Float.toString(pos.getY()), Float.toString(pos.getZ()), Integer.toString(targetPlayer.getSceneId()))); } diff --git a/src/main/java/emu/grasscutter/command/commands/QuestCommand.java b/src/main/java/emu/grasscutter/command/commands/QuestCommand.java new file mode 100644 index 000000000..f9a555149 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/QuestCommand.java @@ -0,0 +1,61 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameQuest; + +import java.util.List; + +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "quest", usage = "quest [questId]", permission = "player.quest", permissionTargeted = "player.quest.others", description = "commands.quest.description") +public final class QuestCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.size() != 2) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.usage")); + return; + } + + String cmd = args.get(0).toLowerCase(); + int questId; + + try { + questId = Integer.parseInt(args.get(1)); + } catch (Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.invalid_id")); + return; + } + + switch (cmd) { + case "add" -> { + GameQuest quest = targetPlayer.getQuestManager().addQuest(questId); + + if (quest != null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.added", questId)); + return; + } + + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found")); + } + case "finish" -> { + GameQuest quest = targetPlayer.getQuestManager().getQuestById(questId); + + if (quest == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found")); + return; + } + + quest.finish(); + + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.finished", questId)); + } + default -> { + CommandHandler.sendMessage(sender, translate(sender, "commands.quest.usage")); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java index 6c85d2024..d18567f9b 100644 --- a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java @@ -9,21 +9,19 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "reload", usage = "reload", - description = "Reload server config", permission = "server.reload") +@Command(label = "reload", usage = "reload", permission = "server.reload", description = "commands.reload.description", targetRequirement = Command.TargetRequirement.NONE) public final class ReloadCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - CommandHandler.sendMessage(sender, translate("commands.reload.reload_start")); + CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_start")); Grasscutter.loadConfig(); Grasscutter.loadLanguage(); Grasscutter.getGameServer().getGachaManager().load(); Grasscutter.getGameServer().getDropManager().load(); Grasscutter.getGameServer().getShopManager().load(); - Grasscutter.getDispatchServer().loadQueries(); - CommandHandler.sendMessage(sender, translate("commands.reload.reload_done")); + CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_done")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java index 706fb95e0..0bca27768 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java @@ -11,20 +11,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "resetconst", usage = "resetconst [all]", - description = "Resets the constellation level on your current active character, will need to relog after using the command to see any changes.", - aliases = {"resetconstellation"}, permission = "player.resetconstellation") + aliases = {"resetconstellation"}, permission = "player.resetconstellation", permissionTargeted = "player.resetconstellation.others", description = "commands.resetConst.description") public final class ResetConstCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() > 0 && args.get(0).equalsIgnoreCase("all")) { targetPlayer.getAvatars().forEach(this::resetConstellation); - CommandHandler.sendMessage(sender, translate("commands.resetConst.reset_all")); + CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.reset_all")); } else { EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity(); if (entity == null) { @@ -34,7 +28,7 @@ public final class ResetConstCommand implements CommandHandler { Avatar avatar = entity.getAvatar(); this.resetConstellation(avatar); - CommandHandler.sendMessage(sender, translate("commands.resetConst.success", avatar.getAvatarData().getName())); + CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.success", avatar.getAvatarData().getName())); } } @@ -44,4 +38,4 @@ public final class ResetConstCommand implements CommandHandler { avatar.recalcStats(); avatar.save(); } -} \ No newline at end of file +} diff --git a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java index aeae0abbf..51695b551 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java @@ -9,18 +9,18 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "resetshop", usage = "resetshop", - description = "Reset target player's shop refresh time.", permission = "server.resetshop") +@Command(label = "resetshop", usage = "resetshop", permission = "server.resetshop", permissionTargeted = "server.resetshop.others", description = "commands.resetShopLimit.description") public final class ResetShopLimitCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); + if (args.isEmpty()) { + CommandHandler.sendMessage(sender, translate(sender, "commands.resetShopLimit.usage")); return; } targetPlayer.getShopLimit().forEach(x -> x.setNextRefreshTime(0)); targetPlayer.save(); - CommandHandler.sendMessage(sender, translate("commands.status.success")); + CommandHandler.sendMessage(sender, translate(sender, "commands.resetShopLimit.success")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java index e3b8b2747..3f73b6f3f 100644 --- a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java @@ -6,7 +6,9 @@ import emu.grasscutter.game.player.Player; import java.util.List; -@Command(label = "restart", usage = "restart - Restarts the current session") +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "restart", usage = "restart", description = "commands.restart.description", targetRequirement = Command.TargetRequirement.NONE) public final class RestartCommand implements CommandHandler { @Override diff --git a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java index 838bea567..c4369fa86 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java @@ -13,8 +13,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @SuppressWarnings("ConstantConditions") -@Command(label = "sendmail", usage = "sendmail [templateId]", - description = "Sends mail to the specified user. The usage of this command changes based on it's composition state.", permission = "server.sendmail") +@Command(label = "sendmail", usage = "sendmail [templateId]", permission = "server.sendmail", description = "commands.sendMail.description", targetRequirement = Command.TargetRequirement.NONE) public final class SendMailCommand implements CommandHandler { // TODO: You should be able to do /sendmail and then just send subsequent messages until you finish @@ -40,24 +39,24 @@ public final class SendMailCommand implements CommandHandler { MailBuilder mailBuilder; switch (args.get(0).toLowerCase()) { case "help" -> { - CommandHandler.sendMessage(sender, this.getClass().getAnnotation(Command.class).description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage()); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.usage")); return; } case "all" -> mailBuilder = new MailBuilder(true, new Mail()); default -> { - if (DatabaseHelper.getPlayerById(Integer.parseInt(args.get(0))) != null) { + if (DatabaseHelper.getPlayerByUid(Integer.parseInt(args.get(0))) != null) { mailBuilder = new MailBuilder(Integer.parseInt(args.get(0)), new Mail()); } else { - CommandHandler.sendMessage(sender, translate("commands.sendMail.user_not_exist", args.get(0))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.user_not_exist", args.get(0))); return; } } } mailBeingConstructed.put(senderId, mailBuilder); - CommandHandler.sendMessage(sender, translate("commands.sendMail.start_composition")); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.start_composition")); } - case 2 -> CommandHandler.sendMessage(sender, translate("commands.sendMail.templates")); - default -> CommandHandler.sendMessage(sender, translate("commands.sendMail.invalid_arguments")); + case 2 -> CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.templates")); + default -> CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.invalid_arguments")); } } else { MailBuilder mailBuilder = mailBeingConstructed.get(senderId); @@ -66,28 +65,28 @@ public final class SendMailCommand implements CommandHandler { switch (args.get(0).toLowerCase()) { case "stop" -> { mailBeingConstructed.remove(senderId); - CommandHandler.sendMessage(sender, translate("commands.sendMail.sendCancel")); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.sendCancel")); return; } case "finish" -> { if (mailBuilder.constructionStage == 3) { if (!mailBuilder.sendToAll) { Grasscutter.getGameServer().getPlayerByUid(mailBuilder.recipient, true).sendMail(mailBuilder.mail); - CommandHandler.sendMessage(sender, translate("commands.sendMail.send_done", Integer.toString(mailBuilder.recipient))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_done", Integer.toString(mailBuilder.recipient))); } else { for (Player player : DatabaseHelper.getAllPlayers()) { Grasscutter.getGameServer().getPlayerByUid(player.getUid(), true).sendMail(mailBuilder.mail); } - CommandHandler.sendMessage(sender, translate("commands.sendMail.send_all_done")); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_all_done")); } mailBeingConstructed.remove(senderId); } else { - CommandHandler.sendMessage(sender, translate("commands.sendMail.not_composition_end", getConstructionArgs(mailBuilder.constructionStage))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.not_composition_end", getConstructionArgs(mailBuilder.constructionStage, sender))); } return; } case "help" -> { - CommandHandler.sendMessage(sender, translate("commands.sendMail.please_use", getConstructionArgs(mailBuilder.constructionStage))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.please_use", getConstructionArgs(mailBuilder.constructionStage, sender))); return; } default -> { @@ -95,19 +94,19 @@ public final class SendMailCommand implements CommandHandler { case 0 -> { String title = String.join(" ", args.subList(0, args.size())); mailBuilder.mail.mailContent.title = title; - CommandHandler.sendMessage(sender, translate("commands.sendMail.set_title", title)); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_title", title)); mailBuilder.constructionStage++; } case 1 -> { String contents = String.join(" ", args.subList(0, args.size())); mailBuilder.mail.mailContent.content = contents; - CommandHandler.sendMessage(sender, translate("commands.sendMail.set_contents", contents)); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_contents", contents)); mailBuilder.constructionStage++; } case 2 -> { String msgSender = String.join(" ", args.subList(0, args.size())); mailBuilder.mail.mailContent.sender = msgSender; - CommandHandler.sendMessage(sender, translate("commands.sendMail.set_message_sender", msgSender)); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_message_sender", msgSender)); mailBuilder.constructionStage++; } case 3 -> { @@ -120,21 +119,21 @@ public final class SendMailCommand implements CommandHandler { try { refinement = Integer.parseInt(args.get(3)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemRefinement")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemRefinement")); return; } // Fallthrough case 3: // [amount] [level] try { lvl = Integer.parseInt(args.get(2)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemLevel")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemLevel")); return; } // Fallthrough case 2: // [amount] try { amount = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.amount")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount")); return; } // Fallthrough case 1: // @@ -142,33 +141,33 @@ public final class SendMailCommand implements CommandHandler { item = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { // TODO: Parse from item name using GM Handbook. - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.itemId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId")); return; } break; default: // *No args* - CommandHandler.sendMessage(sender, translate("commands.give.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.give.usage")); return; } mailBuilder.mail.itemList.add(new Mail.MailItem(item, amount, lvl)); - CommandHandler.sendMessage(sender, translate("commands.sendMail.send", Integer.toString(amount), Integer.toString(item), Integer.toString(lvl))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send", Integer.toString(amount), Integer.toString(item), Integer.toString(lvl))); } } } } } else { - CommandHandler.sendMessage(sender, translate("commands.sendMail.invalid_arguments_please_use", getConstructionArgs(mailBuilder.constructionStage))); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.invalid_arguments_please_use", getConstructionArgs(mailBuilder.constructionStage, sender))); } } } - private String getConstructionArgs(int stage) { + private String getConstructionArgs(int stage, Player sender) { return switch(stage) { - case 0 -> translate("commands.sendMail.title"); - case 1 -> translate("commands.sendMail.message"); - case 2 -> translate("commands.sendMail.sender"); - case 3 -> translate("commands.sendMail.arguments"); - default -> translate("commands.sendMail.error", Integer.toString(stage)); + case 0 -> translate(sender, "commands.sendMail.title"); + case 1 -> translate(sender, "commands.sendMail.message"); + case 2 -> translate(sender, "commands.sendMail.sender"); + case 3 -> translate(sender, "commands.sendMail.arguments"); + default -> translate(sender, "commands.sendMail.error", Integer.toString(stage)); }; } diff --git a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java index acf63dea0..d8051f7c7 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java @@ -8,23 +8,19 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "say", usage = "say ", description = "Sends a message to a player as the server", - aliases = {"sendservmsg", "sendservermessage", "sendmessage"}, permission = "server.sendmessage") +@Command(label = "sendmessage", usage = "sendmessage ", + aliases = {"say", "sendservmsg", "sendservermessage"}, permission = "server.sendmessage", permissionTargeted = "server.sendmessage.others", description = "commands.sendMessage.description") public final class SendMessageCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } if (args.size() == 0) { - CommandHandler.sendMessage(null, translate("commands.sendMessage.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMessage.usage")); return; } String message = String.join(" ", args); CommandHandler.sendMessage(targetPlayer, message); - CommandHandler.sendMessage(sender, translate("commands.sendMessage.success")); + CommandHandler.sendMessage(sender, translate(sender, "commands.sendMessage.success")); } -} \ No newline at end of file +} diff --git a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java index 7184c679c..863989d75 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java @@ -12,26 +12,20 @@ import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify; import static emu.grasscutter.utils.Language.translate; @Command(label = "setfetterlevel", usage = "setfetterlevel ", - description = "Sets your fetter level for your current active character", - aliases = {"setfetterlvl", "setfriendship"}, permission = "player.setfetterlevel") + aliases = {"setfetterlvl", "setfriendship"}, permission = "player.setfetterlevel", permissionTargeted = "player.setfetterlevel.others", description = "commands.setFetterLevel.description") public final class SetFetterLevelCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() != 1) { - CommandHandler.sendMessage(sender, translate("commands.setFetterLevel.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.usage")); return; } try { int fetterLevel = Integer.parseInt(args.get(0)); if (fetterLevel < 0 || fetterLevel > 10) { - CommandHandler.sendMessage(sender, translate("commands.setFetterLevel.range_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.range_error")); return; } Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar(); @@ -43,9 +37,9 @@ public final class SetFetterLevelCommand implements CommandHandler { avatar.save(); targetPlayer.sendPacket(new PacketAvatarFetterDataNotify(avatar)); - CommandHandler.sendMessage(sender, translate("commands.setFetterLevel.success", fetterLevel)); + CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.success", fetterLevel)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.setFetterLevel.level_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.level_error")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java index 233eb4d73..643b313f8 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java @@ -15,8 +15,7 @@ import emu.grasscutter.utils.Language; import static emu.grasscutter.utils.Language.translate; -@Command(label = "setstats", usage = "setstats|stats ", - description = "Set fight property for your current active character", aliases = {"stats"}, permission = "player.setstats") +@Command(label = "setstats", usage = "setstats|stats ", aliases = {"stats"}, permission = "player.setstats", permissionTargeted = "player.setstats.others", description = "commands.setStats.description") public final class SetStatsCommand implements CommandHandler { static class Stat { String name; @@ -176,16 +175,11 @@ public final class SetStatsCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - String syntax = sender == null ? translate("commands.setStats.usage_console") : translate("commands.setStats.ingame"); - String usage = syntax + translate("commands.setStats.help_message"); + String syntax = sender == null ? translate(sender, "commands.setStats.usage_console") : translate(sender, "commands.setStats.usage_ingame"); + String usage = syntax + translate(sender, "commands.setStats.help_message"); String statStr; String valueStr; - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() == 2) { statStr = args.get(0).toLowerCase(); valueStr = args.get(1); @@ -204,7 +198,7 @@ public final class SetStatsCommand implements CommandHandler { value = Float.parseFloat(valueStr); } } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.setStats.value_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setStats.value_error")); return; } @@ -218,10 +212,10 @@ public final class SetStatsCommand implements CommandHandler { valueStr = String.format("%.0f", value); } if (targetPlayer == sender) { - CommandHandler.sendMessage(sender, translate("commands.setStats.set_self", stat.name, valueStr)); + CommandHandler.sendMessage(sender, translate(sender, "commands.setStats.set_self", stat.name, valueStr)); } else { String uidStr = targetPlayer.getAccount().getId(); - CommandHandler.sendMessage(sender, translate("commands.setStats.set_self", stat.name, uidStr, valueStr)); + CommandHandler.sendMessage(sender, translate(sender, "commands.setStats.set_for_uid", stat.name, uidStr, valueStr)); } } else { CommandHandler.sendMessage(sender, usage); diff --git a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java index 914d8cecc..c142dc01d 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java @@ -10,26 +10,20 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "setworldlevel", usage = "setworldlevel ", - description = "Sets your world level (Relog to see proper effects)", - aliases = {"setworldlvl"}, permission = "player.setworldlevel") + aliases = {"setworldlvl"}, permission = "player.setworldlevel", permissionTargeted = "player.setworldlevel.others", description = "commands.setWorldLevel.description") public final class SetWorldLevelCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() < 1) { - CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.usage")); return; } try { int level = Integer.parseInt(args.get(0)); if (level > 8 || level < 0) { - CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.value_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.value_error")); return; } @@ -37,9 +31,9 @@ public final class SetWorldLevelCommand implements CommandHandler { targetPlayer.getWorld().setWorldLevel(level); targetPlayer.setWorldLevel(level); - CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.success", Integer.toString(level))); + CommandHandler.sendMessage(sender, translate(sender, "commands.setWorldLevel.success", Integer.toString(level))); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(null, translate("commands.setWorldLevel.invalid_world_level")); + CommandHandler.sendMessage(null, translate(sender, "commands.setWorldLevel.invalid_world_level")); } } } diff --git a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java index c66a45b50..7bf320383 100644 --- a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java @@ -4,10 +4,10 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.GadgetData; -import emu.grasscutter.data.def.ItemData; -import emu.grasscutter.data.def.MonsterData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.GadgetData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.entity.*; import emu.grasscutter.game.player.Player; @@ -20,59 +20,75 @@ import javax.swing.text.html.parser.Entity; import java.util.List; import java.util.Random; +import static emu.grasscutter.Configuration.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "spawn", usage = "spawn [amount] [level(monster only)]", - description = "Spawns an entity near you", permission = "server.spawn") +@Command(label = "spawn", usage = "spawn [amount] [level(monster only)] [ (monster only, optional)]", permission = "server.spawn", permissionTargeted = "server.spawn.others", description = "commands.spawn.description") public final class SpawnCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - int id = 0; // This is just to shut up the linter, it's not a real default int amount = 1; int level = 1; + float x = 0, y = 0, z = 0; switch (args.size()) { + case 6: + try { + x = Float.parseFloat(args.get(3)); + y = Float.parseFloat(args.get(4)); + z = Float.parseFloat(args.get(5)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); + } // Fallthrough case 3: try { level = Integer.parseInt(args.get(2)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.execution.argument_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); } // Fallthrough case 2: try { amount = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.error.amount")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount")); } // Fallthrough case 1: try { id = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.generic.error.entityId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId")); } break; default: - CommandHandler.sendMessage(sender, translate("commands.spawn.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.spawn.usage")); return; } - + MonsterData monsterData = GameData.getMonsterDataMap().get(id); GadgetData gadgetData = GameData.getGadgetDataMap().get(id); ItemData itemData = GameData.getItemDataMap().get(id); if (monsterData == null && gadgetData == null && itemData == null) { - CommandHandler.sendMessage(sender, translate("commands.generic.error.entityId")); + CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId")); return; } + Scene scene = targetPlayer.getScene(); + + if (scene.getEntities().size() + amount > GAME_OPTIONS.sceneEntityLimit) { + amount = Math.max(Math.min(GAME_OPTIONS.sceneEntityLimit - scene.getEntities().size(), amount), 0); + CommandHandler.sendMessage(sender, translate(sender, "commands.spawn.limit_reached", amount)); + if (amount <= 0) { + return; + } + } double maxRadius = Math.sqrt(amount * 0.2 / Math.PI); for (int i = 0; i < amount; i++) { Position pos = GetRandomPositionInCircle(targetPlayer.getPos(), maxRadius).addY(3); + if(x != 0 && y != 0 && z != 0) { + pos = GetRandomPositionInCircle(new Position(x, y, z), maxRadius).addY(3); + } GameEntity entity = null; if (itemData != null) { entity = new EntityItem(scene, null, itemData, pos, 1, true); @@ -101,7 +117,7 @@ public final class SpawnCommand implements CommandHandler { scene.addEntity(entity); } - CommandHandler.sendMessage(sender, translate("commands.spawn.success", Integer.toString(amount), Integer.toString(id))); + CommandHandler.sendMessage(sender, translate(sender, "commands.spawn.success", Integer.toString(amount), Integer.toString(id))); } private Position GetRandomPositionInCircle(Position origin, double radius){ diff --git a/src/main/java/emu/grasscutter/command/commands/StopCommand.java b/src/main/java/emu/grasscutter/command/commands/StopCommand.java index ad4903107..ca7a80ec5 100644 --- a/src/main/java/emu/grasscutter/command/commands/StopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/StopCommand.java @@ -9,15 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "stop", usage = "stop", - description = "Stops the server", permission = "server.stop") +@Command(label = "stop", usage = "stop", permission = "server.stop", description = "commands.stop.description", targetRequirement = Command.TargetRequirement.NONE) public final class StopCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { CommandHandler.sendMessage(null, translate("commands.stop.success")); for (Player p : Grasscutter.getGameServer().getPlayers().values()) { - CommandHandler.sendMessage(p, translate("commands.stop.success")); + CommandHandler.sendMessage(p, translate(p, "commands.stop.success")); } System.exit(1000); diff --git a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java index c9b2e8931..27ed8de4e 100644 --- a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java @@ -3,7 +3,7 @@ package emu.grasscutter.command.commands; import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.data.def.AvatarSkillDepotData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.player.Player; @@ -14,18 +14,17 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "talent", usage = "talent ", - description = "Set talent level for your current active character", permission = "player.settalent") +@Command(label = "talent", usage = "talent ", permission = "player.settalent", permissionTargeted = "player.settalent.others", description = "commands.talent.description") public final class TalentCommand implements CommandHandler { private void setTalentLevel(Player sender, Player player, Avatar avatar, int talentId, int talentLevel) { int oldLevel = avatar.getSkillLevelMap().get(talentId); if (talentLevel < 0 || talentLevel > 15) { - CommandHandler.sendMessage(sender, translate("commands.talent.lower_16")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.lower_16")); return; } // Upgrade skill - avatar.getSkillLevelMap().put(talentLevel, talentLevel); + avatar.getSkillLevelMap().put(talentId, talentLevel); avatar.save(); // Packet @@ -41,20 +40,15 @@ public final class TalentCommand implements CommandHandler { } else if (talentId == depot.getEnergySkill()) { successMessage = "commands.talent.set_q"; } - CommandHandler.sendMessage(sender, translate(successMessage, talentLevel)); + CommandHandler.sendMessage(sender, translate(sender, successMessage, talentLevel)); } @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (args.size() < 1){ - CommandHandler.sendMessage(sender, translate("commands.talent.usage_1")); - CommandHandler.sendMessage(sender, translate("commands.talent.usage_2")); - CommandHandler.sendMessage(sender, translate("commands.talent.usage_3")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_1")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_2")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_3")); return; } @@ -63,15 +57,15 @@ public final class TalentCommand implements CommandHandler { String cmdSwitch = args.get(0); switch (cmdSwitch) { default -> { - CommandHandler.sendMessage(sender, translate("commands.talent.usage_1")); - CommandHandler.sendMessage(sender, translate("commands.talent.usage_2")); - CommandHandler.sendMessage(sender, translate("commands.talent.usage_3")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_1")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_2")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_3")); return; } case "set" -> { if (args.size() < 3) { - CommandHandler.sendMessage(sender, translate("commands.talent.usage_1")); - CommandHandler.sendMessage(sender, translate("commands.talent.usage_3")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_1")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_3")); return; } try { @@ -79,13 +73,13 @@ public final class TalentCommand implements CommandHandler { int newLevel = Integer.parseInt(args.get(2)); setTalentLevel(sender, targetPlayer, avatar, skillId, newLevel); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.talent.invalid_skill_id")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.invalid_skill_id")); return; } } case "n", "e", "q" -> { if (args.size() < 2) { - CommandHandler.sendMessage(sender, translate("commands.talent.usage_2")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.usage_2")); return; } AvatarSkillDepotData SkillDepot = avatar.getData().getSkillDepot(); @@ -98,7 +92,7 @@ public final class TalentCommand implements CommandHandler { int newLevel = Integer.parseInt(args.get(1)); setTalentLevel(sender, targetPlayer, avatar, skillId, newLevel); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.talent.invalid_level")); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.invalid_level")); return; } } @@ -106,9 +100,9 @@ public final class TalentCommand implements CommandHandler { int skillIdNorAtk = avatar.getData().getSkillDepot().getSkills().get(0); int skillIdE = avatar.getData().getSkillDepot().getSkills().get(1); int skillIdQ = avatar.getData().getSkillDepot().getEnergySkill(); - CommandHandler.sendMessage(sender, translate("commands.talent.normal_attack_id", Integer.toString(skillIdNorAtk))); - CommandHandler.sendMessage(sender, translate("commands.talent.e_skill_id", Integer.toString(skillIdE))); - CommandHandler.sendMessage(sender, translate("commands.talent.q_skill_id", Integer.toString(skillIdQ))); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.normal_attack_id", Integer.toString(skillIdNorAtk))); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.e_skill_id", Integer.toString(skillIdE))); + CommandHandler.sendMessage(sender, translate(sender, "commands.talent.q_skill_id", Integer.toString(skillIdQ))); } } } diff --git a/src/main/java/emu/grasscutter/command/commands/TeamCommand.java b/src/main/java/emu/grasscutter/command/commands/TeamCommand.java new file mode 100644 index 000000000..c425059f7 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/TeamCommand.java @@ -0,0 +1,254 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashSet; + +import static emu.grasscutter.Configuration.*; + +@Command(label = "team", usage = "team [avatarId,...] [index|first|last|index-index,...]", +permission = "player.team", permissionTargeted = "player.team.others", description = "commands.team.description") +public final class TeamCommand implements CommandHandler { + private static final int BASE_AVATARID = 10000000; + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (args.isEmpty()) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.usage"); + return; + } + + switch (args.get(0)) { + case "add": + if (!addCommand(sender, targetPlayer, args)) return; + break; + + case "remove": + if (!removeCommand(sender, targetPlayer, args)) return; + break; + + case "set": + if (!setCommand(sender, targetPlayer, args)) return; + break; + + default: + CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage"); + CommandHandler.sendTranslatedMessage(sender, "commands.team.usage"); + return; + } + + targetPlayer.getTeamManager().updateTeamEntities( + new PacketChangeMpTeamAvatarRsp(targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo())); + } + + private boolean addCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 2) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage"); + CommandHandler.sendTranslatedMessage(sender, "commands.team.add_usage"); + return false; + } + + int index = -1; + if (args.size() > 2) { + try { + index = Integer.parseInt(args.get(2)) - 1; + if (index < 0) index = 0; + } catch (Exception e) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_index"); + return false; + } + } + + var avatarIds = args.get(1).split(","); + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + + if (currentTeamAvatars.size() + avatarIds.length > GAME_OPTIONS.avatarLimits.singlePlayerTeam) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.add_too_much", GAME_OPTIONS.avatarLimits.singlePlayerTeam); + return false; + } + + for (var avatarId: avatarIds) { + int id = Integer.parseInt(avatarId); + var success = addAvatar(sender, targetPlayer, id, index); + if (index > 0) ++index; + } + return true; + } + + private boolean removeCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 2) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage"); + CommandHandler.sendTranslatedMessage(sender, "commands.team.remove_usage"); + return false; + } + + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + var avatarCount = currentTeamAvatars.size(); + + var metaIndexList = args.get(1).split(","); + var indexes = new HashSet(); + var ignoreList = new ArrayList(); + for (var metaIndex: metaIndexList) { + // step 1: parse metaIndex to indexes + var subIndexes = transformToIndexes(metaIndex, avatarCount); + if (subIndexes == null) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_to_parse_index", metaIndex); + continue; + } + + // step 2: get all of the avatar id through indexes + for (var avatarIndex: subIndexes) { + try { + indexes.add(currentTeamAvatars.get(avatarIndex - 1)); + } catch (Exception e) { + ignoreList.add(avatarIndex); + continue; + } + } + } + + // step 3: check if user remove all of the avatar + if (indexes.size() >= avatarCount) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.remove_too_much"); + return false; + } + + // step 4: hint user for ignore index + if (!ignoreList.isEmpty()) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.ignore_index", ignoreList); + } + + // step 5: remove + currentTeamAvatars.removeAll(indexes); + return true; + } + + private boolean setCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 3) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage"); + CommandHandler.sendTranslatedMessage(sender, "commands.team.set_usage"); + return false; + } + + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + + int index; + try { + index = Integer.parseInt(args.get(1)) - 1; + if (index < 0) index = 0; + } catch(Exception e) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_to_parse_index", args.get(1)); + return false; + } + + if (index + 1 > currentTeamAvatars.size()) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.index_out_of_range"); + return false; + } + + int avatarId; + try { + avatarId = Integer.parseInt(args.get(2)); + } catch(Exception e) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_parse_avatar_id", args.get(2)); + return false; + } + if (avatarId < BASE_AVATARID) { + avatarId += BASE_AVATARID; + } + + if (currentTeamAvatars.contains(avatarId)) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_already_in_team", avatarId); + return false; + } + + if (!targetPlayer.getAvatars().hasAvatar(avatarId)) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId); + return false; + } + + currentTeamAvatars.set(index, avatarId); + return true; + } + + private boolean addAvatar(Player sender, Player targetPlayer, int avatarId, int index) { + if (avatarId < BASE_AVATARID) { + avatarId += BASE_AVATARID; + } + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + if (currentTeamAvatars.contains(avatarId)) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_already_in_team", avatarId); + return false; + } + if (!targetPlayer.getAvatars().hasAvatar(avatarId)) { + CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId); + return false; + } + if (index < 0) { + currentTeamAvatars.add(avatarId); + } else { + currentTeamAvatars.add(index, avatarId); + } + return true; + } + + private List transformToIndexes(String metaIndexes, int listLength) { + // step 1: check if metaIndexes is a special constants + if (metaIndexes.equals("first")) { + return List.of(1); + } else if (metaIndexes.equals("last")) { + return List.of(listLength); + } + + // step 2: check if metaIndexes is a range + if (metaIndexes.contains("-")) { + var range = metaIndexes.split("-"); + if (range.length < 2) { + return null; + } + + int min, max; + try { + min = switch (range[0]) { + case "first" -> 1; + case "last" -> listLength; + default -> Integer.parseInt(range[0]); + }; + + max = switch (range[1]) { + case "first" -> 1; + case "last" -> listLength; + default -> Integer.parseInt(range[1]); + }; + } catch (Exception e) { + return null; + } + + if (min > max) { + min ^= max; + max ^= min; + min ^= max; + } + + var indexes = new ArrayList(); + for (int i = min; i <= max; ++i) { + indexes.add(i); + } + return indexes; + } + + // step 3: index is a value, simply return + try { + int index = Integer.parseInt(metaIndexes); + return List.of(index); + } catch (Exception e) { + return null; + } + } + +} diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java index 54c6101f7..5a28383a3 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java @@ -10,18 +10,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "tpall", usage = "tpall", - description = "Teleports all players in your world to your position", permission = "player.tpall") +@Command(label = "tpall", usage = "tpall", permission = "player.tpall", permissionTargeted = "player.tpall.others", description = "commands.teleportAll.description") public final class TeleportAllCommand implements CommandHandler { + @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - if (!targetPlayer.getWorld().isMultiplayer()) { - CommandHandler.sendMessage(sender, translate("commands.teleportAll.error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.error")); return; } @@ -33,6 +28,6 @@ public final class TeleportAllCommand implements CommandHandler { player.getWorld().transferPlayerToScene(player, targetPlayer.getSceneId(), pos); } - CommandHandler.sendMessage(sender, translate("commands.teleportAll.success")); + CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.success")); } } diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java index 06b669a17..4f0e14040 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java @@ -10,8 +10,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "teleport", usage = "teleport [scene id]", aliases = {"tp"}, - description = "Change the player's position.", permission = "player.teleport") +@Command(label = "teleport", usage = "teleport [sceneId]", aliases = {"tp"}, permission = "player.teleport", permissionTargeted = "player.teleport.others", description = "commands.teleport.description") public final class TeleportCommand implements CommandHandler { private float parseRelative(String input, Float current) { // TODO: Maybe this will be useful elsewhere later @@ -27,11 +26,6 @@ public final class TeleportCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - Position pos = targetPlayer.getPos(); float x = pos.getX(); float y = pos.getY(); @@ -43,7 +37,7 @@ public final class TeleportCommand implements CommandHandler { try { sceneId = Integer.parseInt(args.get(3)); }catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.execution.argument_error")); + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error")); } // Fallthrough case 3: try { @@ -51,20 +45,20 @@ public final class TeleportCommand implements CommandHandler { y = parseRelative(args.get(1), y); z = parseRelative(args.get(2), z); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.teleport.invalid_position")); + CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.invalid_position")); } break; default: - CommandHandler.sendMessage(sender, translate("commands.teleport.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.usage")); return; } Position target_pos = new Position(x, y, z); boolean result = targetPlayer.getWorld().transferPlayerToScene(targetPlayer, sceneId, target_pos); if (!result) { - CommandHandler.sendMessage(sender, translate("commands.teleport.invalid_position")); + CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.invalid_position")); } else { - CommandHandler.sendMessage(sender, translate("commands.teleport.success", + CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.success", targetPlayer.getNickname(), Float.toString(x), Float.toString(y), Float.toString(z), Integer.toString(sceneId)) ); diff --git a/src/main/java/emu/grasscutter/command/commands/UnlimitEnergyCommand.java b/src/main/java/emu/grasscutter/command/commands/UnlimitEnergyCommand.java new file mode 100644 index 000000000..943a21ea1 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/UnlimitEnergyCommand.java @@ -0,0 +1,55 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.managers.EnergyManager.EnergyManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.player.TeamManager; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass; +import emu.grasscutter.utils.Position; + +import java.util.List; + +import static emu.grasscutter.Configuration.GAME_OPTIONS; +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "unlimitenergy", usage = "unlimitenergy [on|off|toggle]", aliases = {"ule"}, permission = "player.unlimitenergy", permissionTargeted = "player.unlimitenergy.others", description = "commands.unlimitenergy.description") +public final class UnlimitEnergyCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if(!GAME_OPTIONS.energyUsage){ + CommandHandler.sendMessage(sender, translate(sender, "commands.unlimitenergy.config_error")); + return; + } + Boolean status = targetPlayer.getEnergyManager().getEnergyUsage(); + if (args.size() == 1) { + switch (args.get(0).toLowerCase()) { + case "on": + status = true; + break; + case "off": + status = false; + break; + default: + status = !status; + break; + } + } + EnergyManager energyManager=targetPlayer.getEnergyManager(); + energyManager.setEnergyUsage(!status); + // if unlimitEnergy is enable , make currentActiveTeam's Avatar full-energy + if (status) { + for (EntityAvatar entityAvatar : targetPlayer.getTeamManager().getActiveTeam()) { + entityAvatar.addEnergy(1000, + PropChangeReasonOuterClass.PropChangeReason.PROP_CHANGE_REASON_GM,true); + } + } + + CommandHandler.sendMessage(sender, translate(sender, "commands.unlimitenergy.success", (status ? translate(sender, "commands.status.enabled") : translate(sender, "commands.status.disabled")), targetPlayer.getNickname())); + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java b/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java new file mode 100644 index 000000000..acb1489a2 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java @@ -0,0 +1,32 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.tower.TowerLevelRecord; + +import java.util.List; + +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "unlocktower", usage = "unlocktower", aliases = {"ut"}, + description = "commands.unlocktower.description", permission = "player.tower") +public class UnlockTowerCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + unlockFloor(targetPlayer, targetPlayer.getServer().getTowerScheduleManager() + .getCurrentTowerScheduleData().getEntranceFloorId()); + + unlockFloor(targetPlayer, targetPlayer.getServer().getTowerScheduleManager() + .getScheduleFloors()); + + CommandHandler.sendMessage(sender, translate(sender, "commands.unlocktower.success")); + } + + public void unlockFloor(Player player, List floors){ + floors.stream() + .filter(id -> !player.getTowerManager().getRecordMap().containsKey(id)) + .forEach(id -> player.getTowerManager().getRecordMap().put(id, new TowerLevelRecord(id))); + } +} diff --git a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java index df8a6a01f..78a284968 100644 --- a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java @@ -11,17 +11,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "weather", usage = "weather [climateId]", - description = "Changes the weather.", aliases = {"w"}, permission = "player.weather") +@Command(label = "weather", usage = "weather ", aliases = {"w"}, permission = "player.weather", permissionTargeted = "player.weather.others", description = "commands.weather.description") public final class WeatherCommand implements CommandHandler { @Override public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate("commands.execution.need_target")); - return; - } - int weatherId = 0; int climateId = 1; switch (args.size()) { @@ -29,17 +23,17 @@ public final class WeatherCommand implements CommandHandler { try { climateId = Integer.parseInt(args.get(1)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.weather.invalid_id")); + CommandHandler.sendMessage(sender, translate(sender, "commands.weather.invalid_id")); } case 1: try { weatherId = Integer.parseInt(args.get(0)); } catch (NumberFormatException ignored) { - CommandHandler.sendMessage(sender, translate("commands.weather.invalid_id")); + CommandHandler.sendMessage(sender, translate(sender, "commands.weather.invalid_id")); } break; default: - CommandHandler.sendMessage(sender, translate("commands.weather.usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.weather.usage")); return; } @@ -48,6 +42,6 @@ public final class WeatherCommand implements CommandHandler { targetPlayer.getScene().setWeather(weatherId); targetPlayer.getScene().setClimate(climate); targetPlayer.getScene().broadcastPacket(new PacketSceneAreaWeatherNotify(targetPlayer)); - CommandHandler.sendMessage(sender, translate("commands.weather.success", Integer.toString(weatherId), Integer.toString(climateId))); + CommandHandler.sendMessage(sender, translate(sender, "commands.weather.success", Integer.toString(weatherId), Integer.toString(climateId))); } } diff --git a/src/main/java/emu/grasscutter/data/DataLoader.java b/src/main/java/emu/grasscutter/data/DataLoader.java new file mode 100644 index 000000000..69a17491c --- /dev/null +++ b/src/main/java/emu/grasscutter/data/DataLoader.java @@ -0,0 +1,106 @@ +package emu.grasscutter.data; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.server.http.handlers.GachaHandler; +import emu.grasscutter.tools.Tools; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; + +import java.io.*; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.List; +import java.util.regex.Pattern; + +import static emu.grasscutter.Configuration.DATA; + +public class DataLoader { + + /** + * Load a data file by its name. If the file isn't found within the /data directory then it will fallback to the default within the jar resources + * @see #load(String, boolean) + * @param resourcePath The path to the data file to be loaded. + * @return InputStream of the data file. + * @throws FileNotFoundException + */ + public static InputStream load(String resourcePath) throws FileNotFoundException { + return load(resourcePath, true); + } + + /** + * Load a data file by its name. + * @param resourcePath The path to the data file to be loaded. + * @param useFallback If the file does not exist in the /data directory, should it use the default file in the jar? + * @return InputStream of the data file. + * @throws FileNotFoundException + */ + public static InputStream load(String resourcePath, boolean useFallback) throws FileNotFoundException { + if(Utils.fileExists(DATA(resourcePath))) { + // Data is in the resource directory + return new FileInputStream(DATA(resourcePath)); + } else { + if(useFallback) { + return FileUtils.readResourceAsStream("/defaults/data/" + resourcePath); + } + } + + return null; + } + + public static void CheckAllFiles() { + try { + List filenames = FileUtils.getPathsFromResource("/defaults/data/"); + + if (filenames == null) { + Grasscutter.getLogger().error("We were unable to locate your default data files."); + } + + for (Path file : filenames) { + String relativePath = String.valueOf(file).split("defaults[\\\\\\/]data[\\\\\\/]")[1]; + + CheckAndCopyData(relativePath); + } + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e); + } + + GenerateGachaMappings(); + } + + private static void CheckAndCopyData(String name) { + String filePath = Utils.toFilePath(DATA(name)); + + if (!Utils.fileExists(filePath)) { + // Check if file is in subdirectory + if (name.indexOf("/") != -1) { + String[] path = name.split("/"); + + String folder = ""; + for(int i = 0; i < (path.length - 1); i++) { + folder += path[i] + "/"; + + // Make sure the current folder exists + String folderToCreate = Utils.toFilePath(DATA(folder)); + if(!Utils.fileExists(folderToCreate)) { + Grasscutter.getLogger().info("Creating data folder '" + folder + "'"); + Utils.createFolder(folderToCreate); + } + } + } + + Grasscutter.getLogger().info("Creating default '" + name + "' data"); + FileUtils.copyResource("/defaults/data/" + name, filePath); + } + } + + private static void GenerateGachaMappings() { + if (!Utils.fileExists(GachaHandler.gachaMappings)) { + try { + Grasscutter.getLogger().info("Creating default '" + GachaHandler.gachaMappings + "' data"); + Tools.createGachaMapping(GachaHandler.gachaMappings); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 76a7f1652..1a3663784 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -8,10 +8,12 @@ import java.util.Map; import emu.grasscutter.Grasscutter; import emu.grasscutter.utils.Utils; -import emu.grasscutter.data.custom.AbilityEmbryoEntry; -import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.ScenePointEntry; -import emu.grasscutter.data.def.*; +import emu.grasscutter.data.binout.AbilityEmbryoEntry; +import emu.grasscutter.data.binout.AbilityModifierEntry; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.binout.OpenConfigEntry; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.data.excels.*; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -22,8 +24,10 @@ public class GameData { // BinOutputs private static final Int2ObjectMap abilityHashes = new Int2ObjectOpenHashMap<>(); private static final Map abilityEmbryos = new HashMap<>(); + private static final Map abilityModifiers = new HashMap<>(); private static final Map openConfigEntries = new HashMap<>(); private static final Map scenePointEntries = new HashMap<>(); + private static final Int2ObjectMap mainQuestData = new Int2ObjectOpenHashMap<>(); // ExcelConfigs private static final Int2ObjectMap playerLevelDataMap = new Int2ObjectOpenHashMap<>(); @@ -47,7 +51,8 @@ public class GameData { private static final Int2ObjectMap weaponPromoteDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap weaponCurveDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap equipAffixDataMap = new Int2ObjectOpenHashMap<>(); - + + private static final Int2ObjectMap envAnimalGatherConfigDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap monsterDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap npcDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap gadgetDataMap = new Int2ObjectOpenHashMap<>(); @@ -60,16 +65,28 @@ public class GameData { private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>(); private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexQuestDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexQuestDataIdMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexAnimalDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexWeaponDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexWeaponDataIdMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexMaterialDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexMaterialDataIdMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexReliquaryDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap codexReliquaryDataIdMap = new Int2ObjectOpenHashMap<>(); + private static final ArrayList codexReliquaryArrayList = new ArrayList<>(); private static final Int2ObjectMap fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap questDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap shopGoodsDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); // Cache private static Map> fetters = new HashMap<>(); @@ -101,6 +118,10 @@ public class GameData { return abilityEmbryos; } + public static Map getAbilityModifiers() { + return abilityModifiers; + } + public static Map getOpenConfigEntries() { return openConfigEntries; } @@ -114,6 +135,10 @@ public class GameData { return getScenePointEntries().get(sceneId + "_" + pointId); } + public static Int2ObjectMap getMainQuestDataMap() { + return mainQuestData; + } + public static Int2ObjectMap getAvatarDataMap() { return avatarDataMap; } @@ -216,6 +241,9 @@ public class GameData { public static Int2ObjectMap getMonsterDataMap() { return monsterDataMap; } + public static Int2ObjectMap getEnvAnimalGatherConfigDataMap() { + return envAnimalGatherConfigDataMap; + } public static Int2ObjectMap getNpcDataMap() { return npcDataMap; @@ -278,6 +306,18 @@ public class GameData { return fetters; } + public static Int2ObjectMap getCodexQuestDataIdMap(){return codexQuestDataIdMap;} + + public static Int2ObjectMap getCodexAnimalDataMap(){return codexAnimalDataMap;} + + public static Int2ObjectMap getCodexWeaponDataIdMap(){return codexWeaponDataIdMap;} + + public static Int2ObjectMap getCodexMaterialDataIdMap(){return codexMaterialDataIdMap;} + + public static Int2ObjectMap getcodexReliquaryIdMap(){return codexReliquaryDataIdMap;} + + public static ArrayList getcodexReliquaryArrayList(){return codexReliquaryArrayList;} + public static Int2ObjectMap getWorldLevelDataMap() { return worldLevelDataMap; } @@ -320,4 +360,11 @@ public class GameData { public static Int2ObjectMap getTowerLevelDataMap(){ return towerLevelDataMap; } + public static Int2ObjectMap getTowerScheduleDataMap(){ + return towerScheduleDataMap; + } + + public static Int2ObjectMap getQuestDataMap() { + return questDataMap; + } } diff --git a/src/main/java/emu/grasscutter/data/GameDepot.java b/src/main/java/emu/grasscutter/data/GameDepot.java index fa5aecba5..851e6c464 100644 --- a/src/main/java/emu/grasscutter/data/GameDepot.java +++ b/src/main/java/emu/grasscutter/data/GameDepot.java @@ -7,8 +7,8 @@ import org.danilopianini.util.FlexibleQuadTree; import org.danilopianini.util.SpatialIndex; import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.def.ReliquaryAffixData; -import emu.grasscutter.data.def.ReliquaryMainPropData; +import emu.grasscutter.data.excels.ReliquaryAffixData; +import emu.grasscutter.data.excels.ReliquaryMainPropData; import emu.grasscutter.game.world.SpawnDataEntry; import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; import emu.grasscutter.utils.WeightedList; diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index b1e3da9ff..b0892b28f 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -1,7 +1,6 @@ package emu.grasscutter.data; -import java.io.File; -import java.io.FileReader; +import java.io.*; import java.util.*; import java.util.Map.Entry; import java.util.regex.Matcher; @@ -12,20 +11,30 @@ import emu.grasscutter.utils.Utils; import org.reflections.Reflections; import com.google.gson.JsonElement; +import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.binout.AbilityEmbryoEntry; +import emu.grasscutter.data.binout.AbilityModifier; +import emu.grasscutter.data.binout.AbilityModifierEntry; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.binout.OpenConfigEntry; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.data.binout.AbilityModifier.AbilityConfigData; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierActionType; import emu.grasscutter.data.common.PointData; import emu.grasscutter.data.common.ScenePointConfig; -import emu.grasscutter.data.custom.AbilityEmbryoEntry; -import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.ScenePointEntry; -import emu.grasscutter.game.world.SpawnDataEntry; -import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; +import emu.grasscutter.game.world.SpawnDataEntry.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import static emu.grasscutter.Configuration.*; + public class ResourceLoader { + private static List loadedResources = new ArrayList(); + public static List> getResourceDefClasses() { Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName()); Set classes = reflections.getSubTypesOf(GameResource.class); @@ -47,12 +56,14 @@ public class ResourceLoader { // Load ability lists loadAbilityEmbryos(); loadOpenConfig(); + loadAbilityModifiers(); // Load resources loadResources(); // Process into depots GameDepot.load(); - // Load spawn data + // Load spawn data and quests loadSpawnData(); + loadQuests(); // Load scene points - must be done AFTER resources are loaded loadScenePoints(); // Custom - TODO move this somewhere else @@ -89,6 +100,10 @@ public class ResourceLoader { } public static void loadResources() { + loadResources(false); + } + + public static void loadResources(boolean doReload) { for (Class resourceDefinition : getResourceDefClasses()) { ResourceType type = resourceDefinition.getAnnotation(ResourceType.class); @@ -104,7 +119,7 @@ public class ResourceLoader { } try { - loadFromResource(resourceDefinition, type, map); + loadFromResource(resourceDefinition, type, map, doReload); } catch (Exception e) { Grasscutter.getLogger().error("Error loading resource file: " + Arrays.toString(type.name()), e); } @@ -112,30 +127,32 @@ public class ResourceLoader { } @SuppressWarnings("rawtypes") - protected static void loadFromResource(Class c, ResourceType type, Int2ObjectMap map) throws Exception { - for (String name : type.name()) { - loadFromResource(c, name, map); + protected static void loadFromResource(Class c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception { + if(!loadedResources.contains(c.getSimpleName()) || doReload) { + for (String name : type.name()) { + loadFromResource(c, name, map); + } + Grasscutter.getLogger().info("Loaded " + map.size() + " " + c.getSimpleName() + "s."); + loadedResources.add(c.getSimpleName()); } - Grasscutter.getLogger().info("Loaded " + map.size() + " " + c.getSimpleName() + "s."); } - + @SuppressWarnings({"rawtypes", "unchecked"}) protected static void loadFromResource(Class c, String fileName, Int2ObjectMap map) throws Exception { - FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "ExcelBinOutput/" + fileName); - Gson gson = Grasscutter.getGsonFactory(); - List list = gson.fromJson(fileReader, List.class); + try (FileReader fileReader = new FileReader(RESOURCE("ExcelBinOutput/" + fileName))) { + List list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, c).getType()); - for (Object o : list) { - Map tempMap = Utils.switchPropertiesUpperLowerCase((Map) o, c); - GameResource res = gson.fromJson(gson.toJson(tempMap), TypeToken.get(c).getType()); - res.onLoad(); - map.put(res.getId(), res); + for (Object o : list) { + GameResource res = (GameResource) o; + res.onLoad(); + map.put(res.getId(), res); + } } } private static void loadScenePoints() { Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)"); - File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Scene/Point"); + File folder = new File(RESOURCE("BinOutput/Scene/Point")); if (!folder.isDirectory() || !folder.exists() || folder.listFiles() == null) { Grasscutter.getLogger().error("Scene point files cannot be found, you cannot use teleport waypoints!"); @@ -144,8 +161,7 @@ public class ResourceLoader { List scenePointList = new ArrayList<>(); for (File file : Objects.requireNonNull(folder.listFiles())) { - ScenePointConfig config = null; - Integer sceneId = null; + ScenePointConfig config; Integer sceneId; Matcher matcher = pattern.matcher(file.getName()); if (matcher.find()) { @@ -183,23 +199,19 @@ public class ResourceLoader { } private static void loadAbilityEmbryos() { - // Read from cached file if exists - File embryoCache = new File(Grasscutter.getConfig().DATA_FOLDER + "AbilityEmbryos.json"); List embryoList = null; - - if (embryoCache.exists()) { - // Load from cache - try (FileReader fileReader = new FileReader(embryoCache)) { - embryoList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, AbilityEmbryoEntry.class).getType()); - } catch (Exception e) { - e.printStackTrace(); - } - } else { + + // Read from cached file if exists + try(InputStream embryoCache = DataLoader.load("AbilityEmbryos.json", false)) { + embryoList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(embryoCache), TypeToken.getParameterized(Collection.class, AbilityEmbryoEntry.class).getType()); + } catch(Exception ignored) {} + + if(embryoList == null) { // Load from BinOutput Pattern pattern = Pattern.compile("(?<=ConfigAvatar_)(.*?)(?=.json)"); embryoList = new LinkedList<>(); - File folder = new File(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Avatar/")); + File folder = new File(Utils.toFilePath(RESOURCE("BinOutput/Avatar/"))); File[] files = folder.listFiles(); if(files == null) { Grasscutter.getLogger().error("Error loading ability embryos: no files found in " + folder.getAbsolutePath()); @@ -244,19 +256,76 @@ public class ResourceLoader { } } - private static void loadSpawnData() { - // Read from cached file if exists - File spawnDataEntries = new File(Grasscutter.getConfig().DATA_FOLDER + "Spawns.json"); - List spawnEntryList = null; - - if (spawnDataEntries.exists()) { - // Load from cache - try (FileReader fileReader = new FileReader(spawnDataEntries)) { - spawnEntryList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType()); + private static void loadAbilityModifiers() { + // Load from BinOutput + File folder = new File(Utils.toFilePath(RESOURCE("BinOutput/Ability/Temp/AvatarAbilities/"))); + File[] files = folder.listFiles(); + if (files == null) { + Grasscutter.getLogger().error("Error loading ability modifiers: no files found in " + folder.getAbsolutePath()); + return; + } + + for (File file : files) { + List abilityConfigList; + + try (FileReader fileReader = new FileReader(file)) { + abilityConfigList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, AbilityConfigData.class).getType()); } catch (Exception e) { e.printStackTrace(); + continue; + } + + for (AbilityConfigData data : abilityConfigList) { + if (data.Default.modifiers == null || data.Default.modifiers.size() == 0) { + continue; + } + + AbilityModifierEntry modifierEntry = new AbilityModifierEntry(data.Default.abilityName); + + for (Entry entry : data.Default.modifiers.entrySet()) { + AbilityModifier modifier = entry.getValue(); + + // Stare. + if (modifier.onAdded != null) { + for (AbilityModifierAction action : modifier.onAdded) { + if (action.$type.contains("HealHP")) { + action.type = AbilityModifierActionType.HealHP; + modifierEntry.getOnAdded().add(action); + } + } + } + + if (modifier.onThinkInterval != null) { + for (AbilityModifierAction action : modifier.onThinkInterval) { + if (action.$type.contains("HealHP")) { + action.type = AbilityModifierActionType.HealHP; + modifierEntry.getOnThinkInterval().add(action); + } + } + } + + if (modifier.onRemoved != null) { + for (AbilityModifierAction action : modifier.onRemoved) { + if (action.$type.contains("HealHP")) { + action.type = AbilityModifierActionType.HealHP; + modifierEntry.getOnRemoved().add(action); + } + } + } + } + + GameData.getAbilityModifiers().put(modifierEntry.getName(), modifierEntry); } } + } + + private static void loadSpawnData() { + List spawnEntryList = null; + + // Read from cached file if exists + try(InputStream spawnDataEntries = DataLoader.load("Spawns.json")) { + spawnEntryList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType()); + } catch (Exception ignored) {} if (spawnEntryList == null || spawnEntryList.isEmpty()) { Grasscutter.getLogger().error("No spawn data loaded!"); @@ -264,31 +333,26 @@ public class ResourceLoader { } for (SpawnGroupEntry entry : spawnEntryList) { - entry.getSpawns().stream().forEach(s -> { - s.setGroup(entry); - }); + entry.getSpawns().forEach(s -> s.setGroup(entry)); GameDepot.getSpawnListById(entry.getSceneId()).insert(entry, entry.getPos().getX(), entry.getPos().getZ()); } } private static void loadOpenConfig() { // Read from cached file if exists - File openConfigCache = new File(Grasscutter.getConfig().DATA_FOLDER + "OpenConfig.json"); List list = null; - - if (openConfigCache.exists()) { - try (FileReader fileReader = new FileReader(openConfigCache)) { - list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, OpenConfigEntry.class).getType()); - } catch (Exception e) { - e.printStackTrace(); - } - } else { + + try(InputStream openConfigCache = DataLoader.load("OpenConfig.json", false)) { + list = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(openConfigCache), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType()); + } catch (Exception ignored) {} + + if (list == null) { Map map = new TreeMap<>(); java.lang.reflect.Type type = new TypeToken>() {}.getType(); String[] folderNames = {"BinOutput/Talent/EquipTalents/", "BinOutput/Talent/AvatarTalents/"}; for (String name : folderNames) { - File folder = new File(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + name)); + File folder = new File(Utils.toFilePath(RESOURCE(name))); File[] files = folder.listFiles(); if(files == null) { Grasscutter.getLogger().error("Error loading open config: no files found in " + folder.getAbsolutePath()); return; @@ -327,6 +391,29 @@ public class ResourceLoader { GameData.getOpenConfigEntries().put(entry.getName(), entry); } } + + private static void loadQuests() { + File folder = new File(RESOURCE("BinOutput/Quest/")); + + if (!folder.exists()) { + return; + } + + for (File file : folder.listFiles()) { + MainQuestData mainQuest = null; + + try (FileReader fileReader = new FileReader(file)) { + mainQuest = Grasscutter.getGsonFactory().fromJson(fileReader, MainQuestData.class); + } catch (Exception e) { + e.printStackTrace(); + continue; + } + + GameData.getMainQuestDataMap().put(mainQuest.getId(), mainQuest); + } + + Grasscutter.getLogger().info("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas."); + } // BinOutput configs @@ -348,8 +435,14 @@ public class ResourceLoader { public static class OpenConfigData { public String $type; public String abilityName; + + @SerializedName(value="talentIndex", alternate={"OJOFFKLNAHN"}) public int talentIndex; + + @SerializedName(value="skillID", alternate={"overtime"}) public int skillID; + + @SerializedName(value="pointDelta", alternate={"IGEBKIHPOIF"}) public int pointDelta; } } diff --git a/src/main/java/emu/grasscutter/data/custom/AbilityEmbryoEntry.java b/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java similarity index 90% rename from src/main/java/emu/grasscutter/data/custom/AbilityEmbryoEntry.java rename to src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java index 9c5510145..e0a047a58 100644 --- a/src/main/java/emu/grasscutter/data/custom/AbilityEmbryoEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/AbilityEmbryoEntry.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.custom; +package emu.grasscutter.data.binout; public class AbilityEmbryoEntry { private String name; diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java new file mode 100644 index 000000000..38e82db01 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/binout/AbilityModifier.java @@ -0,0 +1,36 @@ +package emu.grasscutter.data.binout; + +import java.util.Map; + +public class AbilityModifier { + public AbilityModifierAction[] onAdded; + public AbilityModifierAction[] onThinkInterval; + public AbilityModifierAction[] onRemoved; + + public static class AbilityConfigData { + public AbilityData Default; + } + + public static class AbilityData { + public String abilityName; + public Map modifiers; + } + + public static class AbilityModifierAction { + public String $type; + public AbilityModifierActionType type; + public String target; + public AbilityModifierValue amount; + public AbilityModifierValue amountByTargetCurrentHPRatio; + } + + public static class AbilityModifierValue { + public boolean isFormula; + public boolean isDynamic; + public String dynamicKey; + } + + public enum AbilityModifierActionType { + HealHP, ApplyModifier, LoseHP; + } +} diff --git a/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java b/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java new file mode 100644 index 000000000..348c0f2c4 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/binout/AbilityModifierEntry.java @@ -0,0 +1,37 @@ +package emu.grasscutter.data.binout; + +import java.util.ArrayList; +import java.util.List; + +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; + +public class AbilityModifierEntry { + private String name; // Custom value + public List onModifierAdded; + public List onThinkInterval; + public List onRemoved; + + public AbilityModifierEntry(String name) { + this.name = name; + this.onModifierAdded = new ArrayList<>(); + this.onThinkInterval = new ArrayList<>(); + this.onRemoved = new ArrayList<>(); + } + + public String getName() { + return name; + } + + public List getOnAdded() { + return onModifierAdded; + } + + public List getOnThinkInterval() { + return onThinkInterval; + } + + public List getOnRemoved() { + return onRemoved; + } + +} diff --git a/src/main/java/emu/grasscutter/data/binout/MainQuestData.java b/src/main/java/emu/grasscutter/data/binout/MainQuestData.java new file mode 100644 index 000000000..96075bd61 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/binout/MainQuestData.java @@ -0,0 +1,53 @@ +package emu.grasscutter.data.binout; + +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.enums.QuestType; + +public class MainQuestData { + private int id; + private int series; + private QuestType type; + + private long titleTextMapHash; + private int[] suggestTrackMainQuestList; + private int[] rewardIdList; + + private SubQuestData[] subQuests; + + public int getId() { + return id; + } + + public int getSeries() { + return series; + } + + public QuestType getType() { + return type; + } + + public long getTitleTextMapHash() { + return titleTextMapHash; + } + + public int[] getSuggestTrackMainQuestList() { + return suggestTrackMainQuestList; + } + + public int[] getRewardIdList() { + return rewardIdList; + } + + public SubQuestData[] getSubQuests() { + return subQuests; + } + + public static class SubQuestData { + private int subId; + + public int getSubId() { + return subId; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/custom/OpenConfigEntry.java b/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java similarity index 97% rename from src/main/java/emu/grasscutter/data/custom/OpenConfigEntry.java rename to src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java index 8ff646fa9..01d9c9833 100644 --- a/src/main/java/emu/grasscutter/data/custom/OpenConfigEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/OpenConfigEntry.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.custom; +package emu.grasscutter.data.binout; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/emu/grasscutter/data/custom/ScenePointEntry.java b/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java similarity index 86% rename from src/main/java/emu/grasscutter/data/custom/ScenePointEntry.java rename to src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java index 3e904f5c8..603701246 100644 --- a/src/main/java/emu/grasscutter/data/custom/ScenePointEntry.java +++ b/src/main/java/emu/grasscutter/data/binout/ScenePointEntry.java @@ -1,21 +1,21 @@ -package emu.grasscutter.data.custom; - -import emu.grasscutter.data.common.PointData; - -public class ScenePointEntry { - private String name; - private PointData pointData; - - public ScenePointEntry(String name, PointData pointData) { - this.name = name; - this.pointData = pointData; - } - - public String getName() { - return name; - } - - public PointData getPointData() { - return pointData; - } -} +package emu.grasscutter.data.binout; + +import emu.grasscutter.data.common.PointData; + +public class ScenePointEntry { + private String name; + private PointData pointData; + + public ScenePointEntry(String name, PointData pointData) { + this.name = name; + this.pointData = pointData; + } + + public String getName() { + return name; + } + + public PointData getPointData() { + return pointData; + } +} diff --git a/src/main/java/emu/grasscutter/data/common/CurveInfo.java b/src/main/java/emu/grasscutter/data/common/CurveInfo.java index 00c3de3f8..bd53b9a42 100644 --- a/src/main/java/emu/grasscutter/data/common/CurveInfo.java +++ b/src/main/java/emu/grasscutter/data/common/CurveInfo.java @@ -1,17 +1,17 @@ package emu.grasscutter.data.common; public class CurveInfo { - private String Type; - private String Arith; - private float Value; + private String type; + private String arith; + private float value; public String getType() { - return Type; + return type; } public String getArith() { - return Arith; + return arith; } public float getValue() { - return Value; + return value; } } diff --git a/src/main/java/emu/grasscutter/data/common/FightPropData.java b/src/main/java/emu/grasscutter/data/common/FightPropData.java index aee15a6c5..aed67227b 100644 --- a/src/main/java/emu/grasscutter/data/common/FightPropData.java +++ b/src/main/java/emu/grasscutter/data/common/FightPropData.java @@ -3,16 +3,16 @@ package emu.grasscutter.data.common; import emu.grasscutter.game.props.FightProperty; public class FightPropData { - private String PropType; + private String propType; private FightProperty prop; - private float Value; + private float value; public String getPropType() { - return PropType; + return propType; } public float getValue() { - return Value; + return value; } public FightProperty getProp() { @@ -20,6 +20,6 @@ public class FightPropData { } public void onLoad() { - this.prop = FightProperty.getPropByName(PropType); + this.prop = FightProperty.getPropByName(propType); } } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/data/common/ItemParamData.java b/src/main/java/emu/grasscutter/data/common/ItemParamData.java index a962c4618..cc96240bb 100644 --- a/src/main/java/emu/grasscutter/data/common/ItemParamData.java +++ b/src/main/java/emu/grasscutter/data/common/ItemParamData.java @@ -1,20 +1,33 @@ package emu.grasscutter.data.common; +import com.google.gson.annotations.SerializedName; + public class ItemParamData { - private int Id; - private int Count; + @SerializedName(value="id", alternate={"itemId"}) + private int id; + + @SerializedName(value="count", alternate={"itemCount"}) + private int count; public ItemParamData() {} public ItemParamData(int id, int count) { - this.Id = id; - this.Count = count; + this.id = id; + this.count = count; } public int getId() { - return Id; + return id; + } + + public int getItemId() { + return id; } public int getCount() { - return Count; + return count; + } + + public int getItemCount() { + return count; } } diff --git a/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java b/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java index 5fad12511..573065925 100644 --- a/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java +++ b/src/main/java/emu/grasscutter/data/common/ItemParamStringData.java @@ -1,26 +1,26 @@ package emu.grasscutter.data.common; public class ItemParamStringData { - private int Id; - private String Count; + private int id; + private String count; public ItemParamStringData() {} public int getId() { - return Id; + return id; } public String getCount() { - return Count; + return count; } public ItemParamData toItemParamData() { - if (Count.contains(";")) { - String[] split = Count.split(";"); - Count = Count.split(";")[split.length - 1]; - } else if (Count.contains(".")) { - return new ItemParamData(Id, (int) Math.ceil(Double.parseDouble(Count))); + if (count.contains(";")) { + String[] split = count.split(";"); + count = count.split(";")[split.length - 1]; + } else if (count.contains(".")) { + return new ItemParamData(id, (int) Math.ceil(Double.parseDouble(count))); } - return new ItemParamData(Id, Integer.parseInt(Count)); + return new ItemParamData(id, Integer.parseInt(count)); } } diff --git a/src/main/java/emu/grasscutter/data/common/ItemUseData.java b/src/main/java/emu/grasscutter/data/common/ItemUseData.java new file mode 100644 index 000000000..7f905c206 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/common/ItemUseData.java @@ -0,0 +1,24 @@ +package emu.grasscutter.data.common; + +import java.util.List; + +public class ItemUseData { + private String useOp; + private List useParam; + + public String getUseOp() { + return useOp; + } + + public void setUseOp(String useOp) { + this.useOp = useOp; + } + + public List getUseParam() { + return useParam; + } + + public void setUseParam(List useParam) { + this.useParam = useParam; + } +} diff --git a/src/main/java/emu/grasscutter/data/common/OpenCondData.java b/src/main/java/emu/grasscutter/data/common/OpenCondData.java index 9e7b62b11..112bed1ac 100644 --- a/src/main/java/emu/grasscutter/data/common/OpenCondData.java +++ b/src/main/java/emu/grasscutter/data/common/OpenCondData.java @@ -3,22 +3,22 @@ package emu.grasscutter.data.common; import java.util.List; public class OpenCondData { - private String CondType; - private List ParamList; + private String condType; + private List paramList; public String getCondType() { - return CondType; + return condType; } public void setCondType(String condType) { - CondType = condType; + condType = condType; } public List getParamList() { - return ParamList; + return paramList; } public void setParamList(List paramList) { - ParamList = paramList; + paramList = paramList; } } diff --git a/src/main/java/emu/grasscutter/data/common/PointData.java b/src/main/java/emu/grasscutter/data/common/PointData.java index 492f1fc60..13c51cac7 100644 --- a/src/main/java/emu/grasscutter/data/common/PointData.java +++ b/src/main/java/emu/grasscutter/data/common/PointData.java @@ -1,8 +1,10 @@ package emu.grasscutter.data.common; +import com.google.gson.annotations.SerializedName; + import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.DailyDungeonData; +import emu.grasscutter.data.excels.DailyDungeonData; import emu.grasscutter.utils.Position; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; @@ -11,7 +13,11 @@ public class PointData { private int id; private String $type; private Position tranPos; + + @SerializedName(value="dungeonIds", alternate={"JHHFPGJNMIN"}) private int[] dungeonIds; + + @SerializedName(value="dungeonRandomList", alternate={"OIBKFJNBLHO"}) private int[] dungeonRandomList; private int tranSceneId; diff --git a/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java b/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java index b8f11233c..ac8cac5f0 100644 --- a/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java +++ b/src/main/java/emu/grasscutter/data/common/PropGrowCurve.java @@ -1,13 +1,15 @@ package emu.grasscutter.data.common; public class PropGrowCurve { - private String Type; - private String GrowCurve; + private String type; + private String growCurve; public String getType(){ - return this.Type; + return this.type; } + public String getGrowCurve(){ - return this.GrowCurve; + return this.growCurve; } + } diff --git a/src/main/java/emu/grasscutter/data/common/RewardItemData.java b/src/main/java/emu/grasscutter/data/common/RewardItemData.java deleted file mode 100644 index 024b89f7f..000000000 --- a/src/main/java/emu/grasscutter/data/common/RewardItemData.java +++ /dev/null @@ -1,22 +0,0 @@ -package emu.grasscutter.data.common; - -public class RewardItemData { - private int ItemId; - private int ItemCount; - - public int getItemId() { - return ItemId; - } - - public void setItemId(int itemId) { - ItemId = itemId; - } - - public int getItemCount() { - return ItemCount; - } - - public void setItemCount(int itemCount) { - ItemCount = itemCount; - } -} diff --git a/src/main/java/emu/grasscutter/data/def/AvatarSkillData.java b/src/main/java/emu/grasscutter/data/def/AvatarSkillData.java deleted file mode 100644 index 3efc2a142..000000000 --- a/src/main/java/emu/grasscutter/data/def/AvatarSkillData.java +++ /dev/null @@ -1,84 +0,0 @@ -package emu.grasscutter.data.def; - -import java.util.List; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; - -@ResourceType(name = "AvatarSkillExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) -public class AvatarSkillData extends GameResource { - private int Id; - private float CdTime; - private int CostElemVal; - private int MaxChargeNum; - private int TriggerID; - private boolean IsAttackCameraLock; - private int ProudSkillGroupId; - private String CostElemType; - private List LockWeightParams; - - private long NameTextMapHash; - - private String AbilityName; - private String LockShape; - private String GlobalValueKey; - - @Override - public int getId(){ - return this.Id; - } - - public float getCdTime() { - return CdTime; - } - - public int getCostElemVal() { - return CostElemVal; - } - - public int getMaxChargeNum() { - return MaxChargeNum; - } - - public int getTriggerID() { - return TriggerID; - } - - public boolean isIsAttackCameraLock() { - return IsAttackCameraLock; - } - - public int getProudSkillGroupId() { - return ProudSkillGroupId; - } - - public String getCostElemType() { - return CostElemType; - } - - public List getLockWeightParams() { - return LockWeightParams; - } - - public long getNameTextMapHash() { - return NameTextMapHash; - } - - public String getAbilityName() { - return AbilityName; - } - - public String getLockShape() { - return LockShape; - } - - public String getGlobalValueKey() { - return GlobalValueKey; - } - - @Override - public void onLoad() { - - } -} diff --git a/src/main/java/emu/grasscutter/data/def/CombineData.java b/src/main/java/emu/grasscutter/data/def/CombineData.java deleted file mode 100644 index bfcf6af68..000000000 --- a/src/main/java/emu/grasscutter/data/def/CombineData.java +++ /dev/null @@ -1,173 +0,0 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -import java.util.List; -import java.util.stream.Collectors; - -@ResourceType(name = "CombineExcelConfigData.json") -public class CombineData extends GameResource { - - private int CombineId; - - private int PlayerLevel; - - private boolean IsDefaultShow; - - private int CombineType; - - private int SubCombineType; - - private int ResultItemId; - - private int ResultItemCount; - - private int ScoinCost; - - private List RandomItems; - - private List MaterialItems; - - private long EffectDescTextMapHash; - - private String RecipeType; - - @Override - public int getId() { - return this.CombineId; - } - - @Override - public void onLoad() { - super.onLoad(); - // clean data - RandomItems = RandomItems.stream().filter(item -> item.Id > 0).collect(Collectors.toList()); - MaterialItems = MaterialItems.stream().filter(item -> item.Id > 0).collect(Collectors.toList()); - } - - public static class CombineItemPair { - - private int Id; - - private int Count; - - public CombineItemPair(int id, int count) { - Id = id; - Count = count; - } - - public int getId() { - return Id; - } - - public void setId(int id) { - Id = id; - } - - public int getCount() { - return Count; - } - - public void setCount(int count) { - Count = count; - } - } - - public int getCombineId() { - return CombineId; - } - - public void setCombineId(int combineId) { - CombineId = combineId; - } - - public int getPlayerLevel() { - return PlayerLevel; - } - - public void setPlayerLevel(int playerLevel) { - PlayerLevel = playerLevel; - } - - public boolean isDefaultShow() { - return IsDefaultShow; - } - - public void setDefaultShow(boolean defaultShow) { - IsDefaultShow = defaultShow; - } - - public int getCombineType() { - return CombineType; - } - - public void setCombineType(int combineType) { - CombineType = combineType; - } - - public int getSubCombineType() { - return SubCombineType; - } - - public void setSubCombineType(int subCombineType) { - SubCombineType = subCombineType; - } - - public int getResultItemId() { - return ResultItemId; - } - - public void setResultItemId(int resultItemId) { - ResultItemId = resultItemId; - } - - public int getResultItemCount() { - return ResultItemCount; - } - - public void setResultItemCount(int resultItemCount) { - ResultItemCount = resultItemCount; - } - - public int getScoinCost() { - return ScoinCost; - } - - public void setScoinCost(int scoinCost) { - ScoinCost = scoinCost; - } - - public List getRandomItems() { - return RandomItems; - } - - public void setRandomItems(List randomItems) { - RandomItems = randomItems; - } - - public List getMaterialItems() { - return MaterialItems; - } - - public void setMaterialItems(List materialItems) { - MaterialItems = materialItems; - } - - public long getEffectDescTextMapHash() { - return EffectDescTextMapHash; - } - - public void setEffectDescTextMapHash(long effectDescTextMapHash) { - EffectDescTextMapHash = effectDescTextMapHash; - } - - public String getRecipeType() { - return RecipeType; - } - - public void setRecipeType(String recipeType) { - RecipeType = recipeType; - } -} - diff --git a/src/main/java/emu/grasscutter/data/def/ItemData.java b/src/main/java/emu/grasscutter/data/def/ItemData.java deleted file mode 100644 index 5cd1df751..000000000 --- a/src/main/java/emu/grasscutter/data/def/ItemData.java +++ /dev/null @@ -1,258 +0,0 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.game.props.FightProperty; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; - -@ResourceType(name = {"MaterialExcelConfigData.json", "WeaponExcelConfigData.json", "ReliquaryExcelConfigData.json"}) -public class ItemData extends GameResource { - - private int Id; - private int StackLimit = 1; - private int MaxUseCount; - private int RankLevel; - private String EffectName; - private int[] SatiationParams; - private int Rank; - private int Weight; - private int GadgetId; - - private int[] DestroyReturnMaterial; - private int[] DestroyReturnMaterialCount; - - // Food - private String FoodQuality; - private String UseTarget; - private String[] UseParam; - - // String enums - private String ItemType; - private String MaterialType; - private String EquipType; - private String EffectType; - private String DestroyRule; - - // Relic - private int MainPropDepotId; - private int AppendPropDepotId; - private int AppendPropNum; - private int SetId; - private int[] AddPropLevels; - private int BaseConvExp; - private int MaxLevel; - - // Weapon - private int WeaponPromoteId; - private int WeaponBaseExp; - private int StoryId; - private int AvatarPromoteId; - private int AwakenMaterial; - private int[] AwakenCosts; - private int[] SkillAffix; - private WeaponProperty[] WeaponProp; - - // Hash - private String Icon; - private long NameTextMapHash; - - // Post load - private transient emu.grasscutter.game.inventory.MaterialType materialType; - private transient emu.grasscutter.game.inventory.ItemType itemType; - private transient emu.grasscutter.game.inventory.EquipType equipType; - - private IntSet addPropLevelSet; - - @Override - public int getId(){ - return this.Id; - } - - public String getMaterialTypeString(){ - return this.MaterialType; - } - - public int getStackLimit(){ - return this.StackLimit; - } - - public int getMaxUseCount(){ - return this.MaxUseCount; - } - - public String getUseTarget(){ - return this.UseTarget; - } - - public String[] getUseParam(){ - return this.UseParam; - } - - public int getRankLevel(){ - return this.RankLevel; - } - - public String getFoodQuality(){ - return this.FoodQuality; - } - - public String getEffectName(){ - return this.EffectName; - } - - public int[] getSatiationParams(){ - return this.SatiationParams; - } - - public int[] getDestroyReturnMaterial(){ - return this.DestroyReturnMaterial; - } - - public int[] getDestroyReturnMaterialCount(){ - return this.DestroyReturnMaterialCount; - } - - public long getNameTextMapHash(){ - return this.NameTextMapHash; - } - - public String getIcon(){ - return this.Icon; - } - - public String getItemTypeString(){ - return this.ItemType; - } - - public int getRank(){ - return this.Rank; - } - - public int getGadgetId() { - return GadgetId; - } - - public int getBaseConvExp() { - return BaseConvExp; - } - - public int getMainPropDepotId() { - return MainPropDepotId; - } - - public int getAppendPropDepotId() { - return AppendPropDepotId; - } - - public int getAppendPropNum() { - return AppendPropNum; - } - - public int getSetId() { - return SetId; - } - - public int getWeaponPromoteId() { - return WeaponPromoteId; - } - - public int getWeaponBaseExp() { - return WeaponBaseExp; - } - - public int getAwakenMaterial() { - return AwakenMaterial; - } - - public int[] getAwakenCosts() { - return AwakenCosts; - } - - public IntSet getAddPropLevelSet() { - return addPropLevelSet; - } - - public int[] getSkillAffix() { - return SkillAffix; - } - - public WeaponProperty[] getWeaponProperties() { - return WeaponProp; - } - - public int getMaxLevel() { - return MaxLevel; - } - - public emu.grasscutter.game.inventory.ItemType getItemType() { - return this.itemType; - } - - public emu.grasscutter.game.inventory.MaterialType getMaterialType() { - return this.materialType; - } - - public emu.grasscutter.game.inventory.EquipType getEquipType() { - return this.equipType; - } - - public boolean canAddRelicProp(int level) { - return this.addPropLevelSet != null & this.addPropLevelSet.contains(level); - } - - public boolean isEquip() { - return this.itemType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY || this.itemType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON; - } - - @Override - public void onLoad() { - this.itemType = emu.grasscutter.game.inventory.ItemType.getTypeByName(getItemTypeString()); - this.materialType = emu.grasscutter.game.inventory.MaterialType.getTypeByName(getMaterialTypeString()); - - if (this.itemType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY) { - this.equipType = emu.grasscutter.game.inventory.EquipType.getTypeByName(this.EquipType); - if (this.AddPropLevels != null && this.AddPropLevels.length > 0) { - this.addPropLevelSet = new IntOpenHashSet(this.AddPropLevels); - } - } else if (this.itemType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON) { - this.equipType = emu.grasscutter.game.inventory.EquipType.EQUIP_WEAPON; - } else { - this.equipType = emu.grasscutter.game.inventory.EquipType.EQUIP_NONE; - } - - if (this.getWeaponProperties() != null) { - for (WeaponProperty weaponProperty : this.getWeaponProperties()) { - weaponProperty.onLoad(); - } - } - } - - public static class WeaponProperty { - private FightProperty fightProp; - private String PropType; - private float InitValue; - private String Type; - - public String getPropType(){ - return this.PropType; - } - - public float getInitValue(){ - return this.InitValue; - } - - public String getType(){ - return this.Type; - } - - public FightProperty getFightProp() { - return fightProp; - } - - public void onLoad() { - this.fightProp = FightProperty.getPropByName(PropType); - } - - } -} diff --git a/src/main/java/emu/grasscutter/data/def/RewardData.java b/src/main/java/emu/grasscutter/data/def/RewardData.java deleted file mode 100644 index d8ea58415..000000000 --- a/src/main/java/emu/grasscutter/data/def/RewardData.java +++ /dev/null @@ -1,27 +0,0 @@ -package emu.grasscutter.data.def; - -import java.util.List; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.common.RewardItemData; - -@ResourceType(name = "RewardExcelConfigData.json") -public class RewardData extends GameResource { - public int RewardId; - public List RewardItemList; - - @Override - public int getId() { - return RewardId; - } - - public List getRewardItemList() { - return RewardItemList; - } - - @Override - public void onLoad() { - - } -} diff --git a/src/main/java/emu/grasscutter/data/def/TowerFloorData.java b/src/main/java/emu/grasscutter/data/def/TowerFloorData.java deleted file mode 100644 index d9d0082c7..000000000 --- a/src/main/java/emu/grasscutter/data/def/TowerFloorData.java +++ /dev/null @@ -1,73 +0,0 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "TowerFloorExcelConfigData.json") -public class TowerFloorData extends GameResource { - - private int FloorId; - private int FloorIndex; - private int LevelId; - private int OverrideMonsterLevel; - private int TeamNum; - private int FloorLevelConfigId; - - @Override - public int getId() { - return this.FloorId; - } - - @Override - public void onLoad() { - super.onLoad(); - } - - public int getFloorId() { - return FloorId; - } - - public void setFloorId(int floorId) { - FloorId = floorId; - } - - public int getFloorIndex() { - return FloorIndex; - } - - public void setFloorIndex(int floorIndex) { - FloorIndex = floorIndex; - } - - public int getLevelId() { - return LevelId; - } - - public void setLevelId(int levelId) { - LevelId = levelId; - } - - public int getOverrideMonsterLevel() { - return OverrideMonsterLevel; - } - - public void setOverrideMonsterLevel(int overrideMonsterLevel) { - OverrideMonsterLevel = overrideMonsterLevel; - } - - public int getTeamNum() { - return TeamNum; - } - - public void setTeamNum(int teamNum) { - TeamNum = teamNum; - } - - public int getFloorLevelConfigId() { - return FloorLevelConfigId; - } - - public void setFloorLevelConfigId(int floorLevelConfigId) { - FloorLevelConfigId = floorLevelConfigId; - } -} diff --git a/src/main/java/emu/grasscutter/data/def/TowerLevelData.java b/src/main/java/emu/grasscutter/data/def/TowerLevelData.java deleted file mode 100644 index 6cc45cc06..000000000 --- a/src/main/java/emu/grasscutter/data/def/TowerLevelData.java +++ /dev/null @@ -1,55 +0,0 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "TowerLevelExcelConfigData.json") -public class TowerLevelData extends GameResource { - - private int ID; - private int LevelId; - private int LevelIndex; - private int DungeonId; - - @Override - public int getId() { - return this.ID; - } - - @Override - public void onLoad() { - super.onLoad(); - } - - public int getID() { - return ID; - } - - public void setID(int ID) { - this.ID = ID; - } - - public int getLevelId() { - return LevelId; - } - - public void setLevelId(int levelId) { - LevelId = levelId; - } - - public int getLevelIndex() { - return LevelIndex; - } - - public void setLevelIndex(int levelIndex) { - LevelIndex = levelIndex; - } - - public int getDungeonId() { - return DungeonId; - } - - public void setDungeonId(int dungeonId) { - DungeonId = dungeonId; - } -} diff --git a/src/main/java/emu/grasscutter/data/def/AvatarCostumeData.java b/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java similarity index 72% rename from src/main/java/emu/grasscutter/data/def/AvatarCostumeData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java index c6166bd71..342a30652 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarCostumeData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarCostumeData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameResource; @@ -6,21 +6,21 @@ import emu.grasscutter.data.ResourceType; @ResourceType(name = "AvatarCostumeExcelConfigData.json") public class AvatarCostumeData extends GameResource { - private int CostumeId; - private int ItemId; - private int AvatarId; + private int costumeId; + private int itemId; + private int avatarId; @Override public int getId() { - return this.CostumeId; + return this.costumeId; } public int getItemId() { - return this.ItemId; + return this.itemId; } public int getAvatarId() { - return AvatarId; + return avatarId; } @Override diff --git a/src/main/java/emu/grasscutter/data/def/AvatarCurveData.java b/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java similarity index 59% rename from src/main/java/emu/grasscutter/data/def/AvatarCurveData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java index 586c0517d..9fb219da4 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarCurveData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.HashMap; import java.util.Map; @@ -10,27 +10,27 @@ import emu.grasscutter.data.common.CurveInfo; @ResourceType(name = "AvatarCurveExcelConfigData.json") public class AvatarCurveData extends GameResource { - private int Level; - private CurveInfo[] CurveInfos; + private int level; + private CurveInfo[] curveInfos; - private Map curveInfos; + private Map curveInfoMap; @Override public int getId() { - return this.Level; + return this.level; } public int getLevel() { - return Level; + return level; } public Map getCurveInfos() { - return curveInfos; + return curveInfoMap; } @Override public void onLoad() { - this.curveInfos = new HashMap<>(); - Stream.of(this.CurveInfos).forEach(info -> this.curveInfos.put(info.getType(), info.getValue())); + this.curveInfoMap = new HashMap<>(); + Stream.of(this.curveInfos).forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); } } diff --git a/src/main/java/emu/grasscutter/data/def/AvatarData.java b/src/main/java/emu/grasscutter/data/excels/AvatarData.java similarity index 65% rename from src/main/java/emu/grasscutter/data/def/AvatarData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarData.java index 27555fc0d..b9b4cfb22 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.List; @@ -6,9 +6,10 @@ import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.binout.AbilityEmbryoEntry; import emu.grasscutter.data.common.PropGrowCurve; -import emu.grasscutter.data.custom.AbilityEmbryoEntry; import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.WeaponType; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -17,38 +18,36 @@ import it.unimi.dsi.fastutil.ints.IntList; @ResourceType(name = "AvatarExcelConfigData.json", loadPriority = LoadPriority.LOW) public class AvatarData extends GameResource { - private String name; - private String IconName; - private String BodyType; - private String QualityType; - private int ChargeEfficiency; - private int InitialWeapon; - private String WeaponType; - private String ImageName; - private int AvatarPromoteId; - private String CutsceneShow; - private int SkillDepotId; - private int StaminaRecoverSpeed; - private List CandSkillDepotIds; - private long DescTextMapHash; - private String AvatarIdentityType; - private List AvatarPromoteRewardLevelList; - private List AvatarPromoteRewardIdList; - private int FeatureTagGroupID; - - private long NameTextMapHash; - private long GachaImageNameHashSuffix; - private long InfoDescTextMapHash; - - private float HpBase; - private float AttackBase; - private float DefenseBase; - private float Critical; - private float CriticalHurt; + private String iconName; + private String bodyType; + private String qualityType; + private int chargeEfficiency; + private int initialWeapon; + private WeaponType weaponType; + private String imageName; + private int avatarPromoteId; + private String cutsceneShow; + private int skillDepotId; + private int staminaRecoverSpeed; + private List candSkillDepotIds; + private String avatarIdentityType; + private List avatarPromoteRewardLevelList; + private List avatarPromoteRewardIdList; - private List PropGrowCurves; - private int Id; + private long nameTextMapHash; + private float hpBase; + private float attackBase; + private float defenseBase; + private float critical; + private float criticalHurt; + + private List propGrowCurves; + private int id; + + // Transient + private String name; + private Int2ObjectMap growthCurveMap; private float[] hpGrowthCurve; private float[] attackGrowthCurve; @@ -58,11 +57,11 @@ public class AvatarData extends GameResource { private List fetters; private int nameCardRewardId; - private int nameCardId; + private int nameCardId; @Override public int getId(){ - return this.Id; + return this.id; } public String getName() { @@ -70,107 +69,91 @@ public class AvatarData extends GameResource { } public String getBodyType(){ - return this.BodyType; + return this.bodyType; } public String getQualityType(){ - return this.QualityType; + return this.qualityType; } public int getChargeEfficiency(){ - return this.ChargeEfficiency; + return this.chargeEfficiency; } public int getInitialWeapon(){ - return this.InitialWeapon; + return this.initialWeapon; } - public String getWeaponType(){ - return this.WeaponType; + public WeaponType getWeaponType(){ + return this.weaponType; } public String getImageName(){ - return this.ImageName; + return this.imageName; } public int getAvatarPromoteId(){ - return this.AvatarPromoteId; - } - - public long getGachaImageNameHashSuffix(){ - return this.GachaImageNameHashSuffix; + return this.avatarPromoteId; } public String getCutsceneShow(){ - return this.CutsceneShow; + return this.cutsceneShow; } public int getSkillDepotId(){ - return this.SkillDepotId; + return this.skillDepotId; } public int getStaminaRecoverSpeed(){ - return this.StaminaRecoverSpeed; + return this.staminaRecoverSpeed; } public List getCandSkillDepotIds(){ - return this.CandSkillDepotIds; + return this.candSkillDepotIds; } - - public long getDescTextMapHash(){ - return this.DescTextMapHash; - } - + public String getAvatarIdentityType(){ - return this.AvatarIdentityType; + return this.avatarIdentityType; } public List getAvatarPromoteRewardLevelList(){ - return this.AvatarPromoteRewardLevelList; + return this.avatarPromoteRewardLevelList; } public List getAvatarPromoteRewardIdList(){ - return this.AvatarPromoteRewardIdList; + return this.avatarPromoteRewardIdList; } - public int getFeatureTagGroupID(){ - return this.FeatureTagGroupID; - } - - public long getInfoDescTextMapHash(){ - return this.InfoDescTextMapHash; - } - public float getBaseHp(int level){ try { - return this.HpBase * this.hpGrowthCurve[level - 1]; + return this.hpBase * this.hpGrowthCurve[level - 1]; } catch (Exception e) { - return this.HpBase; + return this.hpBase; } } public float getBaseAttack(int level){ try { - return this.AttackBase * this.attackGrowthCurve[level - 1]; + return this.attackBase * this.attackGrowthCurve[level - 1]; } catch (Exception e) { - return this.AttackBase; + return this.attackBase; } } public float getBaseDefense(int level){ try { - return this.DefenseBase * this.defenseGrowthCurve[level - 1]; + return this.defenseBase * this.defenseGrowthCurve[level - 1]; } catch (Exception e) { - return this.DefenseBase; + return this.defenseBase; } } public float getBaseCritical(){ - return this.Critical; + return this.critical; } public float getBaseCriticalHurt(){ - return this.CriticalHurt; + return this.criticalHurt; } public float getGrowthCurveById(int level, FightProperty prop) { @@ -186,7 +169,7 @@ public class AvatarData extends GameResource { } public long getNameTextMapHash(){ - return this.NameTextMapHash; + return this.nameTextMapHash; } public AvatarSkillDepotData getSkillDepot() { @@ -211,13 +194,13 @@ public class AvatarData extends GameResource { @Override public void onLoad() { - this.skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.SkillDepotId); + this.skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.skillDepotId); // Get fetters from GameData - this.fetters = GameData.getFetterDataEntries().get(this.Id); + this.fetters = GameData.getFetterDataEntries().get(this.id); - if (GameData.getFetterCharacterCardDataMap().get(this.Id) != null) { - this.nameCardRewardId = GameData.getFetterCharacterCardDataMap().get(this.Id).getRewardId(); + if (GameData.getFetterCharacterCardDataMap().get(this.id) != null) { + this.nameCardRewardId = GameData.getFetterCharacterCardDataMap().get(this.id).getRewardId(); } if (GameData.getRewardDataMap().get(this.nameCardRewardId) != null) { @@ -230,7 +213,7 @@ public class AvatarData extends GameResource { this.defenseGrowthCurve = new float[size]; for (AvatarCurveData curveData : GameData.getAvatarCurveDataMap().values()) { int level = curveData.getLevel() - 1; - for (PropGrowCurve growCurve : this.PropGrowCurves) { + for (PropGrowCurve growCurve : this.propGrowCurves) { FightProperty prop = FightProperty.getPropByName(growCurve.getType()); switch (prop) { case FIGHT_PROP_BASE_HP: @@ -256,7 +239,7 @@ public class AvatarData extends GameResource { */ // Cache abilities - String[] split = this.IconName.split("_"); + String[] split = this.iconName.split("_"); if (split.length > 0) { this.name = split[split.length - 1]; diff --git a/src/main/java/emu/grasscutter/data/def/AvatarFetterLevelData.java b/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java similarity index 63% rename from src/main/java/emu/grasscutter/data/def/AvatarFetterLevelData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java index a02915069..efc44147a 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarFetterLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarFetterLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; - -@ResourceType(name = "AvatarFettersLevelExcelConfigData.json") -public class AvatarFetterLevelData extends GameResource { - private int FetterLevel; - private int NeedExp; - - @Override - public int getId() { - return this.FetterLevel; - } - - public int getLevel() { - return FetterLevel; - } - - public int getExp() { - return NeedExp; - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "AvatarFettersLevelExcelConfigData.json") +public class AvatarFetterLevelData extends GameResource { + private int fetterLevel; + private int needExp; + + @Override + public int getId() { + return this.fetterLevel; + } + + public int getLevel() { + return fetterLevel; + } + + public int getExp() { + return needExp; + } +} diff --git a/src/main/java/emu/grasscutter/data/def/AvatarFlycloakData.java b/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java similarity index 68% rename from src/main/java/emu/grasscutter/data/def/AvatarFlycloakData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java index 100a6c87c..ab8106eab 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarFlycloakData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarFlycloakData.java @@ -1,20 +1,20 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "AvatarFlycloakExcelConfigData.json") public class AvatarFlycloakData extends GameResource { - private int FlycloakId; - private long NameTextMapHash; + private int flycloakId; + private long nameTextMapHash; @Override public int getId() { - return this.FlycloakId; + return this.flycloakId; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } @Override diff --git a/src/main/java/emu/grasscutter/data/def/AvatarLevelData.java b/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java similarity index 69% rename from src/main/java/emu/grasscutter/data/def/AvatarLevelData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java index bc6ca671c..3b37c3886 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "AvatarLevelExcelConfigData.json") public class AvatarLevelData extends GameResource { - private int Level; - private int Exp; + private int level; + private int exp; @Override public int getId() { - return this.Level; + return this.level; } public int getLevel() { - return Level; + return level; } public int getExp() { - return Exp; + return exp; } } diff --git a/src/main/java/emu/grasscutter/data/def/AvatarPromoteData.java b/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java similarity index 66% rename from src/main/java/emu/grasscutter/data/def/AvatarPromoteData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java index c397902e4..226105aac 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarPromoteData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarPromoteData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.ArrayList; import emu.grasscutter.data.GameResource; @@ -9,45 +9,45 @@ import emu.grasscutter.data.common.ItemParamData; @ResourceType(name = "AvatarPromoteExcelConfigData.json") public class AvatarPromoteData extends GameResource { - private int AvatarPromoteId; - private int PromoteLevel; - private int ScoinCost; - private ItemParamData[] CostItems; - private int UnlockMaxLevel; - private FightPropData[] AddProps; - private int RequiredPlayerLevel; + private int avatarPromoteId; + private int promoteLevel; + private int scoinCost; + private ItemParamData[] costItems; + private int unlockMaxLevel; + private FightPropData[] addProps; + private int requiredPlayerLevel; @Override public int getId() { - return (AvatarPromoteId << 8) + PromoteLevel; + return (avatarPromoteId << 8) + promoteLevel; } public int getAvatarPromoteId() { - return AvatarPromoteId; + return avatarPromoteId; } public int getPromoteLevel() { - return PromoteLevel; + return promoteLevel; } public ItemParamData[] getCostItems() { - return CostItems; + return costItems; } public int getCoinCost() { - return ScoinCost; + return scoinCost; } public FightPropData[] getAddProps() { - return AddProps; + return addProps; } public int getUnlockMaxLevel() { - return UnlockMaxLevel; + return unlockMaxLevel; } public int getRequiredPlayerLevel() { - return RequiredPlayerLevel; + return requiredPlayerLevel; } @Override @@ -60,7 +60,7 @@ public class AvatarPromoteData extends GameResource { } trim.add(itemParam); } - this.CostItems = trim.toArray(new ItemParamData[trim.size()]); + this.costItems = trim.toArray(new ItemParamData[trim.size()]); // Trim fight prop data (just in case) ArrayList parsed = new ArrayList<>(getAddProps().length); for (FightPropData prop : getAddProps()) { @@ -69,6 +69,6 @@ public class AvatarPromoteData extends GameResource { parsed.add(prop); } } - this.AddProps = parsed.toArray(new FightPropData[parsed.size()]); + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); } } diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java b/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java new file mode 100644 index 000000000..76c56ef2e --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/AvatarSkillData.java @@ -0,0 +1,85 @@ +package emu.grasscutter.data.excels; + +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.game.props.ElementType; + +@ResourceType(name = "AvatarSkillExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) +public class AvatarSkillData extends GameResource { + private int id; + private float cdTime; + private int costElemVal; + private int maxChargeNum; + private int triggerID; + private boolean isAttackCameraLock; + private int proudSkillGroupId; + private ElementType costElemType; + private List lockWeightParams; + + private long nameTextMapHash; + + private String abilityName; + private String lockShape; + private String globalValueKey; + + @Override + public int getId(){ + return this.id; + } + + public float getCdTime() { + return cdTime; + } + + public int getCostElemVal() { + return costElemVal; + } + + public int getMaxChargeNum() { + return maxChargeNum; + } + + public int getTriggerID() { + return triggerID; + } + + public boolean isIsAttackCameraLock() { + return isAttackCameraLock; + } + + public int getProudSkillGroupId() { + return proudSkillGroupId; + } + + public ElementType getCostElemType() { + return costElemType; + } + + public List getLockWeightParams() { + return lockWeightParams; + } + + public long getNameTextMapHash() { + return nameTextMapHash; + } + + public String getAbilityName() { + return abilityName; + } + + public String getLockShape() { + return lockShape; + } + + public String getGlobalValueKey() { + return globalValueKey; + } + + @Override + public void onLoad() { + + } +} diff --git a/src/main/java/emu/grasscutter/data/def/AvatarSkillDepotData.java b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java similarity index 59% rename from src/main/java/emu/grasscutter/data/def/AvatarSkillDepotData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java index 7916bfd45..152ec31bd 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarSkillDepotData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.List; @@ -6,7 +6,7 @@ import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.custom.AbilityEmbryoEntry; +import emu.grasscutter.data.binout.AbilityEmbryoEntry; import emu.grasscutter.game.props.ElementType; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -15,62 +15,63 @@ import it.unimi.dsi.fastutil.ints.IntList; @ResourceType(name = "AvatarSkillDepotExcelConfigData.json", loadPriority = LoadPriority.HIGH) public class AvatarSkillDepotData extends GameResource { - private int Id; - private int EnergySkill; - private int AttackModeSkill; + private int id; + private int energySkill; + private int attackModeSkill; - private List Skills; - private List SubSkills; - private List ExtraAbilities; - private List Talents; - private List InherentProudSkillOpens; + private List skills; + private List subSkills; + private List extraAbilities; + private List talents; + private List inherentProudSkillOpens; - private String TalentStarName; - private String SkillDepotAbilityGroup; + private String talentStarName; + private String skillDepotAbilityGroup; + // Transient private AvatarSkillData energySkillData; private ElementType elementType; private IntList abilities; @Override public int getId(){ - return this.Id; + return this.id; } public int getEnergySkill(){ - return this.EnergySkill; + return this.energySkill; } public List getSkills(){ - return this.Skills; + return this.skills; } public List getSubSkills(){ - return this.SubSkills; + return this.subSkills; } public int getAttackModeSkill(){ - return this.AttackModeSkill; + return this.attackModeSkill; } public List getExtraAbilities(){ - return this.ExtraAbilities; + return this.extraAbilities; } public List getTalents(){ - return this.Talents; + return this.talents; } public String getTalentStarName(){ - return this.TalentStarName; + return this.talentStarName; } public List getInherentProudSkillOpens(){ - return this.InherentProudSkillOpens; + return this.inherentProudSkillOpens; } public String getSkillDepotAbilityGroup(){ - return this.SkillDepotAbilityGroup; + return this.skillDepotAbilityGroup; } public AvatarSkillData getEnergySkillData() { @@ -94,30 +95,24 @@ public class AvatarSkillDepotData extends GameResource { @Override public void onLoad() { - this.energySkillData = GameData.getAvatarSkillDataMap().get(this.EnergySkill); + this.energySkillData = GameData.getAvatarSkillDataMap().get(this.energySkill); if (getEnergySkillData() != null) { - this.elementType = ElementType.getTypeByName(getEnergySkillData().getCostElemType()); + this.elementType = getEnergySkillData().getCostElemType(); } else { this.elementType = ElementType.None; } } public static class InherentProudSkillOpens { - private int ProudSkillGroupId; + private int proudSkillGroupId; + private int needAvatarPromoteLevel; - private int NeedAvatarPromoteLevel; - - public void setProudSkillGroupId(int ProudSkillGroupId){ - this.ProudSkillGroupId = ProudSkillGroupId; - } public int getProudSkillGroupId(){ - return this.ProudSkillGroupId; - } - public void setNeedAvatarPromoteLevel(int NeedAvatarPromoteLevel){ - this.NeedAvatarPromoteLevel = NeedAvatarPromoteLevel; + return this.proudSkillGroupId; } + public int getNeedAvatarPromoteLevel(){ - return this.NeedAvatarPromoteLevel; + return this.needAvatarPromoteLevel; } } } diff --git a/src/main/java/emu/grasscutter/data/def/AvatarTalentData.java b/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java similarity index 63% rename from src/main/java/emu/grasscutter/data/def/AvatarTalentData.java rename to src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java index fdf96875d..f02d2e50a 100644 --- a/src/main/java/emu/grasscutter/data/def/AvatarTalentData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarTalentData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.ArrayList; import emu.grasscutter.data.GameResource; @@ -8,51 +8,51 @@ import emu.grasscutter.data.common.FightPropData; @ResourceType(name = "AvatarTalentExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) public class AvatarTalentData extends GameResource { - private int TalentId; - private int PrevTalent; - private long NameTextMapHash; - private String Icon; - private int MainCostItemId; - private int MainCostItemCount; - private String OpenConfig; - private FightPropData[] AddProps; - private float[] ParamList; + private int talentId; + private int prevTalent; + private long nameTextMapHash; + private String icon; + private int mainCostItemId; + private int mainCostItemCount; + private String openConfig; + private FightPropData[] addProps; + private float[] paramList; @Override public int getId(){ - return this.TalentId; + return this.talentId; } public int PrevTalent() { - return PrevTalent; + return prevTalent; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public String getIcon() { - return Icon; + return icon; } public int getMainCostItemId() { - return MainCostItemId; + return mainCostItemId; } public int getMainCostItemCount() { - return MainCostItemCount; + return mainCostItemCount; } public String getOpenConfig() { - return OpenConfig; + return openConfig; } public FightPropData[] getAddProps() { - return AddProps; + return addProps; } public float[] getParamList() { - return ParamList; + return paramList; } @Override @@ -64,6 +64,6 @@ public class AvatarTalentData extends GameResource { parsed.add(prop); } } - this.AddProps = parsed.toArray(new FightPropData[parsed.size()]); + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); } } diff --git a/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java b/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java new file mode 100644 index 000000000..0bc9c0521 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CodexAnimalData.java @@ -0,0 +1,39 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"AnimalCodexExcelConfigData.json"}) +public class CodexAnimalData extends GameResource { + private int Id; + private String type; + private int describeId; + private int sortOrder; + private CodexAnimalUnlockCondition OCCLHPBCDGL; + + @Override + public int getId() { + return Id; + } + + public String getType() { + return type; + } + + public int getDescribeId() { + return describeId; + } + + public int getSortOrder() { + return sortOrder; + } + + public CodexAnimalUnlockCondition getUnlockCondition() { + return OCCLHPBCDGL; + } + + public enum CodexAnimalUnlockCondition { + CODEX_COUNT_TYPE_KILL, + CODEX_COUNT_TYPE_CAPTURE + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexMaterialData.java b/src/main/java/emu/grasscutter/data/excels/CodexMaterialData.java new file mode 100644 index 000000000..3ab32be5c --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CodexMaterialData.java @@ -0,0 +1,29 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"MaterialCodexExcelConfigData.json"}) +public class CodexMaterialData extends GameResource { + private int Id; + private int materialId; + private int sortOrder; + + public int getSortOrder() { + return sortOrder; + } + + public int getMaterialId() { + return materialId; + } + + public int getId() { + return Id; + } + + @Override + public void onLoad() { + GameData.getCodexMaterialDataIdMap().put(this.getMaterialId(), this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java b/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java new file mode 100644 index 000000000..09ccf0b6b --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CodexQuestData.java @@ -0,0 +1,41 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"QuestCodexExcelConfigData.json"}) +public class CodexQuestData extends GameResource { + private int Id; + private int parentQuestId; + private int chapterId; + private int sortOrder; + private boolean isDisuse; + + public int getParentQuestId() { + return parentQuestId; + } + + public int getId() { + return Id; + } + + public int getChapterId() { + return chapterId; + } + + public int getSortOrder() { + return sortOrder; + } + + public boolean getIsDisuse() { + return isDisuse; + } + + @Override + public void onLoad() { + if(!this.getIsDisuse()) { + GameData.getCodexQuestDataIdMap().put(this.getParentQuestId(), this); + } + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java b/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java new file mode 100644 index 000000000..8ed747b53 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CodexReliquaryData.java @@ -0,0 +1,60 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"ReliquaryCodexExcelConfigData.json"}) +public class CodexReliquaryData extends GameResource { + private int Id; + private int suitId; + private int level; + private int cupId; + private int leatherId; + private int capId; + private int flowerId; + private int sandId; + private int sortOrder; + + public int getSortOrder() { + return sortOrder; + } + + public int getId() { + return Id; + } + + public int getSuitId() { + return suitId; + } + + public int getLevel() { + return level; + } + + public int getCupId() { + return cupId; + } + + public int getLeatherId() { + return leatherId; + } + + public int getCapId() { + return capId; + } + + public int getFlowerId() { + return flowerId; + } + + public int getSandId() { + return sandId; + } + + @Override + public void onLoad() { + GameData.getcodexReliquaryArrayList().add(this); + GameData.getcodexReliquaryIdMap().put(getSuitId(), this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CodexWeaponData.java b/src/main/java/emu/grasscutter/data/excels/CodexWeaponData.java new file mode 100644 index 000000000..7b08290ec --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CodexWeaponData.java @@ -0,0 +1,29 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = {"WeaponCodexExcelConfigData.json"}) +public class CodexWeaponData extends GameResource { + private int Id; + private int weaponId; + private int sortOrder; + + public int getSortOrder() { + return sortOrder; + } + + public int getWeaponId() { + return weaponId; + } + + public int getId() { + return Id; + } + + @Override + public void onLoad() { + GameData.getCodexWeaponDataIdMap().put(this.getWeaponId(), this); + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/CombineData.java b/src/main/java/emu/grasscutter/data/excels/CombineData.java new file mode 100644 index 000000000..38ac7f641 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CombineData.java @@ -0,0 +1,83 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; + +import java.util.List; +import java.util.stream.Collectors; + +@ResourceType(name = "CombineExcelConfigData.json") +public class CombineData extends GameResource { + + private int combineId; + private int playerLevel; + private boolean isDefaultShow; + private int combineType; + private int subCombineType; + private int resultItemId; + private int resultItemCount; + private int scoinCost; + private List randomItems; + private List materialItems; + private String recipeType; + + @Override + public int getId() { + return this.combineId; + } + + @Override + public void onLoad() { + super.onLoad(); + // clean data + randomItems = randomItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); + materialItems = materialItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); + } + + public int getCombineId() { + return combineId; + } + + public int getPlayerLevel() { + return playerLevel; + } + + public boolean isDefaultShow() { + return isDefaultShow; + } + + public int getCombineType() { + return combineType; + } + + public int getSubCombineType() { + return subCombineType; + } + + public int getResultItemId() { + return resultItemId; + } + + public int getResultItemCount() { + return resultItemCount; + } + + public int getScoinCost() { + return scoinCost; + } + + public List getRandomItems() { + return randomItems; + } + + public List getMaterialItems() { + return materialItems; + } + + public String getRecipeType() { + return recipeType; + } + +} + diff --git a/src/main/java/emu/grasscutter/data/def/DailyDungeonData.java b/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java similarity index 59% rename from src/main/java/emu/grasscutter/data/def/DailyDungeonData.java rename to src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java index 8cd878125..39f1da4f3 100644 --- a/src/main/java/emu/grasscutter/data/def/DailyDungeonData.java +++ b/src/main/java/emu/grasscutter/data/excels/DailyDungeonData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.Calendar; @@ -12,14 +12,14 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @ResourceType(name = "DailyDungeonConfigData.json") public class DailyDungeonData extends GameResource { - private int Id; - private int[] Monday; - private int[] Tuesday; - private int[] Wednesday; - private int[] Thursday; - private int[] Friday; - private int[] Saturday; - private int[] Sunday; + private int id; + private int[] monday; + private int[] tuesday; + private int[] wednesday; + private int[] thursday; + private int[] friday; + private int[] saturday; + private int[] sunday; private static final int[] empty = new int[0]; private final Int2ObjectMap map; @@ -30,7 +30,7 @@ public class DailyDungeonData extends GameResource { @Override public int getId() { - return this.Id; + return this.id; } public int[] getDungeonsByDay(int day) { @@ -39,12 +39,12 @@ public class DailyDungeonData extends GameResource { @Override public void onLoad() { - map.put(Calendar.MONDAY, Monday); - map.put(Calendar.TUESDAY, Tuesday); - map.put(Calendar.WEDNESDAY, Wednesday); - map.put(Calendar.THURSDAY, Thursday); - map.put(Calendar.FRIDAY, Friday); - map.put(Calendar.SATURDAY, Saturday); - map.put(Calendar.SUNDAY, Sunday); + map.put(Calendar.MONDAY, monday); + map.put(Calendar.TUESDAY, tuesday); + map.put(Calendar.WEDNESDAY, wednesday); + map.put(Calendar.THURSDAY, thursday); + map.put(Calendar.FRIDAY, friday); + map.put(Calendar.SATURDAY, saturday); + map.put(Calendar.SUNDAY, sunday); } } diff --git a/src/main/java/emu/grasscutter/data/def/DungeonData.java b/src/main/java/emu/grasscutter/data/excels/DungeonData.java similarity index 67% rename from src/main/java/emu/grasscutter/data/def/DungeonData.java rename to src/main/java/emu/grasscutter/data/excels/DungeonData.java index 086cbb6bf..3b18c01ef 100644 --- a/src/main/java/emu/grasscutter/data/def/DungeonData.java +++ b/src/main/java/emu/grasscutter/data/excels/DungeonData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameResource; @@ -8,25 +8,25 @@ import emu.grasscutter.game.props.SceneType; @ResourceType(name = "DungeonExcelConfigData.json") public class DungeonData extends GameResource { - private int Id; - private int SceneId; - private int ShowLevel; - private int PassRewardPreviewID; - private String InvolveType; // TODO enum + private int id; + private int sceneId; + private int showLevel; + private int passRewardPreviewID; + private String involveType; // TODO enum private RewardPreviewData previewData; @Override public int getId() { - return this.Id; + return this.id; } public int getSceneId() { - return SceneId; + return sceneId; } public int getShowLevel() { - return ShowLevel; + return showLevel; } public RewardPreviewData getRewardPreview() { @@ -35,8 +35,8 @@ public class DungeonData extends GameResource { @Override public void onLoad() { - if (this.PassRewardPreviewID > 0) { - this.previewData = GameData.getRewardPreviewDataMap().get(this.PassRewardPreviewID); + if (this.passRewardPreviewID > 0) { + this.previewData = GameData.getRewardPreviewDataMap().get(this.passRewardPreviewID); } } } diff --git a/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java b/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java new file mode 100644 index 000000000..e99d681e0 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/EnvAnimalGatherConfigData.java @@ -0,0 +1,40 @@ +package emu.grasscutter.data.excels; + +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "EnvAnimalGatherExcelConfigData.json", loadPriority = ResourceType.LoadPriority.LOW) +public class EnvAnimalGatherConfigData extends GameResource { + private int animalId; + private String entityType; + private List gatherItemId; + private String excludeWeathers; + private int aliveTime; + private int escapeTime; + private int escapeRadius; + @Override + public int getId() { + return animalId; + } + public int getAnimalId(){ + return animalId; + } + public String getEntityType(){ + return entityType; + } + public GatherItem gatherItem(){ + return gatherItemId.get(0); + } + public static class GatherItem{ + private int id; + private int count; + public int getId(){ + return id; + } + public int getCount(){ + return count; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/def/EquipAffixData.java b/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java similarity index 65% rename from src/main/java/emu/grasscutter/data/def/EquipAffixData.java rename to src/main/java/emu/grasscutter/data/excels/EquipAffixData.java index 9020c7b46..e7356d939 100644 --- a/src/main/java/emu/grasscutter/data/def/EquipAffixData.java +++ b/src/main/java/emu/grasscutter/data/excels/EquipAffixData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.ArrayList; import emu.grasscutter.data.GameResource; @@ -8,41 +8,41 @@ import emu.grasscutter.data.common.FightPropData; @ResourceType(name = "EquipAffixExcelConfigData.json") public class EquipAffixData extends GameResource { - private int AffixId; - private int Id; - private int Level; - private long NameTextMapHash; - private String OpenConfig; - private FightPropData[] AddProps; - private float[] ParamList; + private int affixId; + private int id; + private int level; + private long nameTextMapHash; + private String openConfig; + private FightPropData[] addProps; + private float[] paramList; @Override public int getId() { - return AffixId; + return affixId; } public int getMainId() { - return Id; + return id; } public int getLevel() { - return Level; + return level; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public String getOpenConfig() { - return OpenConfig; + return openConfig; } public FightPropData[] getAddProps() { - return AddProps; + return addProps; } public float[] getParamList() { - return ParamList; + return paramList; } @Override @@ -54,6 +54,6 @@ public class EquipAffixData extends GameResource { parsed.add(prop); } } - this.AddProps = parsed.toArray(new FightPropData[parsed.size()]); + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); } } diff --git a/src/main/java/emu/grasscutter/data/def/FetterCharacterCardData.java b/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java similarity index 73% rename from src/main/java/emu/grasscutter/data/def/FetterCharacterCardData.java rename to src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java index 62e323509..771bd9cb2 100644 --- a/src/main/java/emu/grasscutter/data/def/FetterCharacterCardData.java +++ b/src/main/java/emu/grasscutter/data/excels/FetterCharacterCardData.java @@ -1,24 +1,24 @@ -package emu.grasscutter.data.def; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; - -@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) -public class FetterCharacterCardData extends GameResource { - private int AvatarId; - private int RewardId; - - @Override - public int getId() { - return AvatarId; - } - - public int getRewardId() { - return RewardId; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; + +@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) +public class FetterCharacterCardData extends GameResource { + private int avatarId; + private int rewardId; + + @Override + public int getId() { + return avatarId; + } + + public int getRewardId() { + return rewardId; + } + + @Override + public void onLoad() { + } +} diff --git a/src/main/java/emu/grasscutter/data/def/FetterData.java b/src/main/java/emu/grasscutter/data/excels/FetterData.java similarity index 75% rename from src/main/java/emu/grasscutter/data/def/FetterData.java rename to src/main/java/emu/grasscutter/data/excels/FetterData.java index 697843680..101f31915 100644 --- a/src/main/java/emu/grasscutter/data/def/FetterData.java +++ b/src/main/java/emu/grasscutter/data/excels/FetterData.java @@ -1,32 +1,32 @@ -package emu.grasscutter.data.def; - -import java.util.List; - -import emu.grasscutter.data.GameResource; -import emu.grasscutter.data.ResourceType; -import emu.grasscutter.data.ResourceType.LoadPriority; -import emu.grasscutter.data.common.OpenCondData; - -@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json", "PhotographExpressionExcelConfigData.json", "PhotographPosenameExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST) -public class FetterData extends GameResource { - private int AvatarId; - private int FetterId; - private List OpenCond; - - @Override - public int getId() { - return FetterId; - } - - public int getAvatarId() { - return AvatarId; - } - - public List getOpenConds() { - return OpenCond; - } - - @Override - public void onLoad() { - } -} +package emu.grasscutter.data.excels; + +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import emu.grasscutter.data.common.OpenCondData; + +@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json", "PhotographExpressionExcelConfigData.json", "PhotographPosenameExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST) +public class FetterData extends GameResource { + private int avatarId; + private int fetterId; + private List openCond; + + @Override + public int getId() { + return fetterId; + } + + public int getAvatarId() { + return avatarId; + } + + public List getOpenConds() { + return openCond; + } + + @Override + public void onLoad() { + } +} diff --git a/src/main/java/emu/grasscutter/data/def/GadgetData.java b/src/main/java/emu/grasscutter/data/excels/GadgetData.java similarity index 60% rename from src/main/java/emu/grasscutter/data/def/GadgetData.java rename to src/main/java/emu/grasscutter/data/excels/GadgetData.java index 6f1a8aa46..2cd79f6c2 100644 --- a/src/main/java/emu/grasscutter/data/def/GadgetData.java +++ b/src/main/java/emu/grasscutter/data/excels/GadgetData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @@ -6,53 +6,53 @@ import emu.grasscutter.game.props.EntityType; @ResourceType(name = "GadgetExcelConfigData.json") public class GadgetData extends GameResource { - private int Id; + private int id; - private EntityType Type; - private String JsonName; - private boolean IsInteractive; - private String[] Tags; - private String ItemJsonName; - private String InteeIconName; - private long NameTextMapHash; - private int CampID; + private EntityType type; + private String jsonName; + private boolean isInteractive; + private String[] tags; + private String itemJsonName; + private String inteeIconName; + private long nameTextMapHash; + private int campID; private String LODPatternName; @Override public int getId() { - return this.Id; + return this.id; } public EntityType getType() { - return Type; + return type; } public String getJsonName() { - return JsonName; + return jsonName; } public boolean isInteractive() { - return IsInteractive; + return isInteractive; } public String[] getTags() { - return Tags; + return tags; } public String getItemJsonName() { - return ItemJsonName; + return itemJsonName; } public String getInteeIconName() { - return InteeIconName; + return inteeIconName; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public int getCampID() { - return CampID; + return campID; } public String getLODPatternName() { return LODPatternName; } diff --git a/src/main/java/emu/grasscutter/data/excels/ItemData.java b/src/main/java/emu/grasscutter/data/excels/ItemData.java new file mode 100644 index 000000000..fba8d9ec0 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/ItemData.java @@ -0,0 +1,267 @@ +package emu.grasscutter.data.excels; + +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemUseData; +import emu.grasscutter.game.props.FightProperty; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; + +@ResourceType(name = {"MaterialExcelConfigData.json", "WeaponExcelConfigData.json", "ReliquaryExcelConfigData.json"}) +public class ItemData extends GameResource { + + private int id; + private int stackLimit = 1; + private int maxUseCount; + private int rankLevel; + private String effectName; + private int[] satiationParams; + private int rank; + private int weight; + private int gadgetId; + + private int[] destroyReturnMaterial; + private int[] destroyReturnMaterialCount; + + private List itemUse; + + // Food + private String foodQuality; + private String useTarget; + private String[] iseParam; + + // String enums + private String itemType; + private String materialType; + private String equipType; + private String effectType; + private String destroyRule; + + // Relic + private int mainPropDepotId; + private int appendPropDepotId; + private int appendPropNum; + private int setId; + private int[] addPropLevels; + private int baseConvExp; + private int maxLevel; + + // Weapon + private int weaponPromoteId; + private int weaponBaseExp; + private int storyId; + private int avatarPromoteId; + private int awakenMaterial; + private int[] awakenCosts; + private int[] skillAffix; + private WeaponProperty[] weaponProp; + + // Hash + private String icon; + private long nameTextMapHash; + + // Post load + private transient emu.grasscutter.game.inventory.MaterialType materialEnumType; + private transient emu.grasscutter.game.inventory.ItemType itemEnumType; + private transient emu.grasscutter.game.inventory.EquipType equipEnumType; + + private IntSet addPropLevelSet; + + @Override + public int getId(){ + return this.id; + } + + public String getMaterialTypeString(){ + return this.materialType; + } + + public int getStackLimit(){ + return this.stackLimit; + } + + public int getMaxUseCount(){ + return this.maxUseCount; + } + + public String getUseTarget(){ + return this.useTarget; + } + + public String[] getUseParam(){ + return this.iseParam; + } + + public int getRankLevel(){ + return this.rankLevel; + } + + public String getFoodQuality(){ + return this.foodQuality; + } + + public String getEffectName(){ + return this.effectName; + } + + public int[] getSatiationParams(){ + return this.satiationParams; + } + + public int[] getDestroyReturnMaterial(){ + return this.destroyReturnMaterial; + } + + public int[] getDestroyReturnMaterialCount(){ + return this.destroyReturnMaterialCount; + } + + public List getItemUse() { + return itemUse; + } + + public long getNameTextMapHash(){ + return this.nameTextMapHash; + } + + public String getIcon(){ + return this.icon; + } + + public String getItemTypeString(){ + return this.itemType; + } + + public int getRank(){ + return this.rank; + } + + public int getGadgetId() { + return gadgetId; + } + + public int getBaseConvExp() { + return baseConvExp; + } + + public int getMainPropDepotId() { + return mainPropDepotId; + } + + public int getAppendPropDepotId() { + return appendPropDepotId; + } + + public int getAppendPropNum() { + return appendPropNum; + } + + public int getSetId() { + return setId; + } + + public int getWeaponPromoteId() { + return weaponPromoteId; + } + + public int getWeaponBaseExp() { + return weaponBaseExp; + } + + public int getAwakenMaterial() { + return awakenMaterial; + } + + public int[] getAwakenCosts() { + return awakenCosts; + } + + public IntSet getAddPropLevelSet() { + return addPropLevelSet; + } + + public int[] getSkillAffix() { + return skillAffix; + } + + public WeaponProperty[] getWeaponProperties() { + return weaponProp; + } + + public int getMaxLevel() { + return maxLevel; + } + + public emu.grasscutter.game.inventory.ItemType getItemType() { + return this.itemEnumType; + } + + public emu.grasscutter.game.inventory.MaterialType getMaterialType() { + return this.materialEnumType; + } + + public emu.grasscutter.game.inventory.EquipType getEquipType() { + return this.equipEnumType; + } + + public boolean canAddRelicProp(int level) { + return this.addPropLevelSet != null & this.addPropLevelSet.contains(level); + } + + public boolean isEquip() { + return this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY || this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON; + } + + @Override + public void onLoad() { + this.itemEnumType = emu.grasscutter.game.inventory.ItemType.getTypeByName(getItemTypeString()); + this.materialEnumType = emu.grasscutter.game.inventory.MaterialType.getTypeByName(getMaterialTypeString()); + + if (this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_RELIQUARY) { + this.equipEnumType = emu.grasscutter.game.inventory.EquipType.getTypeByName(this.equipType); + if (this.addPropLevels != null && this.addPropLevels.length > 0) { + this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels); + } + } else if (this.itemEnumType == emu.grasscutter.game.inventory.ItemType.ITEM_WEAPON) { + this.equipEnumType = emu.grasscutter.game.inventory.EquipType.EQUIP_WEAPON; + } else { + this.equipEnumType = emu.grasscutter.game.inventory.EquipType.EQUIP_NONE; + } + + if (this.getWeaponProperties() != null) { + for (WeaponProperty weaponProperty : this.getWeaponProperties()) { + weaponProperty.onLoad(); + } + } + } + + public static class WeaponProperty { + private FightProperty fightProp; + private String propType; + private float initValue; + private String type; + + public String getPropType(){ + return this.propType; + } + + public float getInitValue(){ + return this.initValue; + } + + public String getType(){ + return this.type; + } + + public FightProperty getFightProp() { + return fightProp; + } + + public void onLoad() { + this.fightProp = FightProperty.getPropByName(propType); + } + + } +} diff --git a/src/main/java/emu/grasscutter/data/def/MonsterCurveData.java b/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java similarity index 57% rename from src/main/java/emu/grasscutter/data/def/MonsterCurveData.java rename to src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java index 07c705403..29e7da2fb 100644 --- a/src/main/java/emu/grasscutter/data/def/MonsterCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterCurveData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.HashMap; import java.util.Map; @@ -10,23 +10,23 @@ import emu.grasscutter.data.common.CurveInfo; @ResourceType(name = "MonsterCurveExcelConfigData.json") public class MonsterCurveData extends GameResource { - private int Level; - private CurveInfo[] CurveInfos; + private int level; + private CurveInfo[] curveInfos; - private Map curveInfos; + private Map curveInfoMap; @Override public int getId() { - return Level; + return level; } public float getMultByProp(String fightProp) { - return curveInfos.getOrDefault(fightProp, 1f); + return curveInfoMap.getOrDefault(fightProp, 1f); } @Override public void onLoad() { - this.curveInfos = new HashMap<>(); - Stream.of(this.CurveInfos).forEach(info -> this.curveInfos.put(info.getType(), info.getValue())); + this.curveInfoMap = new HashMap<>(); + Stream.of(this.curveInfos).forEach(info -> this.curveInfoMap.put(info.getType(), info.getValue())); } } diff --git a/src/main/java/emu/grasscutter/data/def/MonsterData.java b/src/main/java/emu/grasscutter/data/excels/MonsterData.java similarity index 56% rename from src/main/java/emu/grasscutter/data/def/MonsterData.java rename to src/main/java/emu/grasscutter/data/excels/MonsterData.java index 341a10ce0..758937fda 100644 --- a/src/main/java/emu/grasscutter/data/def/MonsterData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.List; @@ -7,155 +7,157 @@ import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.common.PropGrowCurve; +import emu.grasscutter.game.props.MonsterType; @ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW) public class MonsterData extends GameResource { - private int Id; + private int id; - private String MonsterName; - private String Type; - private String ServerScript; - private List Affix; - private String Ai; - private int[] Equips; - private List HpDrops; - private int KillDropId; - private String ExcludeWeathers; - private int FeatureTagGroupID; - private int MpPropID; - private String Skin; - private int DescribeId; - private int CombatBGMLevel; - private int EntityBudgetLevel; - private float HpBase; - private float AttackBase; - private float DefenseBase; - private float FireSubHurt; - private float ElecSubHurt; - private float GrassSubHurt; - private float WaterSubHurt; - private float WindSubHurt; - private float RockSubHurt; - private float IceSubHurt; - private float PhysicalSubHurt; - private List PropGrowCurves; - private long NameTextMapHash; - private int CampID; + private String monsterName; + private MonsterType type; + private String serverScript; + private List affix; + private String ai; + private int[] equips; + private List hpDrops; + private int killDropId; + private String excludeWeathers; + private int featureTagGroupID; + private int mpPropID; + private String skin; + private int describeId; + private int combatBGMLevel; + private int entityBudgetLevel; + private float hpBase; + private float attackBase; + private float defenseBase; + private float fireSubHurt; + private float elecSubHurt; + private float grassSubHurt; + private float waterSubHurt; + private float windSubHurt; + private float rockSubHurt; + private float iceSubHurt; + private float physicalSubHurt; + private List propGrowCurves; + private long nameTextMapHash; + private int campID; + // Transient private int weaponId; private MonsterDescribeData describeData; @Override public int getId() { - return this.Id; + return this.id; } public String getMonsterName() { - return MonsterName; + return monsterName; } - public String getType() { - return Type; + public MonsterType getType() { + return type; } public String getServerScript() { - return ServerScript; + return serverScript; } public List getAffix() { - return Affix; + return affix; } public String getAi() { - return Ai; + return ai; } public int[] getEquips() { - return Equips; + return equips; } public List getHpDrops() { - return HpDrops; + return hpDrops; } public int getKillDropId() { - return KillDropId; + return killDropId; } public String getExcludeWeathers() { - return ExcludeWeathers; + return excludeWeathers; } public int getFeatureTagGroupID() { - return FeatureTagGroupID; + return featureTagGroupID; } public int getMpPropID() { - return MpPropID; + return mpPropID; } public String getSkin() { - return Skin; + return skin; } public int getDescribeId() { - return DescribeId; + return describeId; } public int getCombatBGMLevel() { - return CombatBGMLevel; + return combatBGMLevel; } public int getEntityBudgetLevel() { - return EntityBudgetLevel; + return entityBudgetLevel; } public float getBaseHp() { - return HpBase; + return hpBase; } public float getBaseAttack() { - return AttackBase; + return attackBase; } public float getBaseDefense() { - return DefenseBase; + return defenseBase; } public float getElecSubHurt() { - return ElecSubHurt; + return elecSubHurt; } public float getGrassSubHurt() { - return GrassSubHurt; + return grassSubHurt; } public float getWaterSubHurt() { - return WaterSubHurt; + return waterSubHurt; } public float getWindSubHurt() { - return WindSubHurt; + return windSubHurt; } public float getIceSubHurt() { - return IceSubHurt; + return iceSubHurt; } public float getPhysicalSubHurt() { - return PhysicalSubHurt; + return physicalSubHurt; } public List getPropGrowCurves() { - return PropGrowCurves; + return propGrowCurves; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public int getCampID() { - return CampID; + return campID; } public MonsterDescribeData getDescribeData() { @@ -170,7 +172,7 @@ public class MonsterData extends GameResource { public void onLoad() { this.describeData = GameData.getMonsterDescribeDataMap().get(this.getDescribeId()); - for (int id : this.Equips) { + for (int id : this.equips) { if (id == 0) { continue; } diff --git a/src/main/java/emu/grasscutter/data/def/MonsterDescribeData.java b/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java similarity index 65% rename from src/main/java/emu/grasscutter/data/def/MonsterDescribeData.java rename to src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java index 41b826c5b..9f6c81e25 100644 --- a/src/main/java/emu/grasscutter/data/def/MonsterDescribeData.java +++ b/src/main/java/emu/grasscutter/data/excels/MonsterDescribeData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @@ -6,31 +6,31 @@ import emu.grasscutter.data.ResourceType.LoadPriority; @ResourceType(name = "MonsterDescribeExcelConfigData.json", loadPriority = LoadPriority.HIGH) public class MonsterDescribeData extends GameResource { - private int Id; - private long NameTextMapHash; - private int TitleID; - private int SpecialNameLabID; - private String Icon; + private int id; + private long nameTextMapHash; + private int titleID; + private int specialNameLabID; + private String icon; @Override public int getId() { - return Id; + return id; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public int getTitleID() { - return TitleID; + return titleID; } public int getSpecialNameLabID() { - return SpecialNameLabID; + return specialNameLabID; } public String getIcon() { - return Icon; + return icon; } @Override diff --git a/src/main/java/emu/grasscutter/data/def/NpcData.java b/src/main/java/emu/grasscutter/data/excels/NpcData.java similarity index 51% rename from src/main/java/emu/grasscutter/data/def/NpcData.java rename to src/main/java/emu/grasscutter/data/excels/NpcData.java index 37fa78776..cd6323525 100644 --- a/src/main/java/emu/grasscutter/data/def/NpcData.java +++ b/src/main/java/emu/grasscutter/data/excels/NpcData.java @@ -1,68 +1,68 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "NpcExcelConfigData.json") public class NpcData extends GameResource { - private int Id; + private int id; - private String JsonName; - private String Alias; - private String ScriptDataPath; - private String LuaDataPath; + private String jsonName; + private String alias; + private String scriptDataPath; + private String luaDataPath; - private boolean IsInteractive; - private boolean HasMove; - private String DyePart; - private String BillboardIcon; + private boolean isInteractive; + private boolean hasMove; + private String dyePart; + private String billboardIcon; - private long NameTextMapHash; - private int CampID; + private long nameTextMapHash; + private int campID; @Override public int getId() { - return this.Id; + return this.id; } public String getJsonName() { - return JsonName; + return jsonName; } public String getAlias() { - return Alias; + return alias; } public String getScriptDataPath() { - return ScriptDataPath; + return scriptDataPath; } public String getLuaDataPath() { - return LuaDataPath; + return luaDataPath; } public boolean isIsInteractive() { - return IsInteractive; + return isInteractive; } public boolean isHasMove() { - return HasMove; + return hasMove; } public String getDyePart() { - return DyePart; + return dyePart; } public String getBillboardIcon() { - return BillboardIcon; + return billboardIcon; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } public int getCampID() { - return CampID; + return campID; } @Override diff --git a/src/main/java/emu/grasscutter/data/def/PlayerLevelData.java b/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java similarity index 61% rename from src/main/java/emu/grasscutter/data/def/PlayerLevelData.java rename to src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java index 1e02e3eca..646c06e3b 100644 --- a/src/main/java/emu/grasscutter/data/def/PlayerLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/PlayerLevelData.java @@ -1,33 +1,33 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "PlayerLevelExcelConfigData.json") public class PlayerLevelData extends GameResource { - private int Level; - private int Exp; - private int RewardId; - private int UnlockWorldLevel; + private int level; + private int exp; + private int rewardId; + private int unlockWorldLevel; @Override public int getId() { - return this.Level; + return this.level; } public int getLevel() { - return Level; + return level; } public int getExp() { - return Exp; + return exp; } public int getRewardId() { - return RewardId; + return rewardId; } public int getUnlockWorldLevel() { - return UnlockWorldLevel; + return unlockWorldLevel; } } diff --git a/src/main/java/emu/grasscutter/data/def/ProudSkillData.java b/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java similarity index 57% rename from src/main/java/emu/grasscutter/data/def/ProudSkillData.java rename to src/main/java/emu/grasscutter/data/excels/ProudSkillData.java index 3eff8b94d..34701ffe5 100644 --- a/src/main/java/emu/grasscutter/data/def/ProudSkillData.java +++ b/src/main/java/emu/grasscutter/data/excels/ProudSkillData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.ArrayList; import java.util.List; @@ -11,82 +11,82 @@ import emu.grasscutter.data.common.ItemParamData; @ResourceType(name = "ProudSkillExcelConfigData.json") public class ProudSkillData extends GameResource { - private int ProudSkillId; - private int ProudSkillGroupId; - private int Level; - private int CoinCost; - private int BreakLevel; - private int ProudSkillType; - private String OpenConfig; - private List CostItems; - private List FilterConds; - private List LifeEffectParams; - private FightPropData[] AddProps; - private float[] ParamList; - private long[] ParamDescList; - private long NameTextMapHash; + private int proudSkillId; + private int proudSkillGroupId; + private int level; + private int coinCost; + private int breakLevel; + private int proudSkillType; + private String openConfig; + private List costItems; + private List filterConds; + private List lifeEffectParams; + private FightPropData[] addProps; + private float[] paramList; + private long[] paramDescList; + private long nameTextMapHash; @Override public int getId() { - return ProudSkillId; + return proudSkillId; } public int getProudSkillGroupId() { - return ProudSkillGroupId; + return proudSkillGroupId; } public int getLevel() { - return Level; + return level; } public int getCoinCost() { - return CoinCost; + return coinCost; } public int getBreakLevel() { - return BreakLevel; + return breakLevel; } public int getProudSkillType() { - return ProudSkillType; + return proudSkillType; } public String getOpenConfig() { - return OpenConfig; + return openConfig; } public List getCostItems() { - return CostItems; + return costItems; } public List getFilterConds() { - return FilterConds; + return filterConds; } public List getLifeEffectParams() { - return LifeEffectParams; + return lifeEffectParams; } public FightPropData[] getAddProps() { - return AddProps; + return addProps; } public float[] getParamList() { - return ParamList; + return paramList; } public long[] getParamDescList() { - return ParamDescList; + return paramDescList; } public long getNameTextMapHash() { - return NameTextMapHash; + return nameTextMapHash; } @Override public void onLoad() { if (this.getOpenConfig() != null & this.getOpenConfig().length() > 0) { - this.OpenConfig = "Avatar_" + this.getOpenConfig(); + this.openConfig = "Avatar_" + this.getOpenConfig(); } // Fight props ArrayList parsed = new ArrayList(getAddProps().length); @@ -96,6 +96,6 @@ public class ProudSkillData extends GameResource { parsed.add(prop); } } - this.AddProps = parsed.toArray(new FightPropData[parsed.size()]); + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); } } diff --git a/src/main/java/emu/grasscutter/data/excels/QuestData.java b/src/main/java/emu/grasscutter/data/excels/QuestData.java new file mode 100644 index 000000000..7866eeb45 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/QuestData.java @@ -0,0 +1,126 @@ +package emu.grasscutter.data.excels; + +import java.util.Arrays; +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestTrigger; + +@ResourceType(name = "QuestExcelConfigData.json") +public class QuestData extends GameResource { + private int subId; + private int mainId; + private int order; + private long descTextMapHash; + + private boolean finishParent; + private boolean isRewind; + + private LogicType acceptCondComb; + private QuestCondition[] acceptConditons; + private LogicType finishCondComb; + private QuestCondition[] finishConditons; + private LogicType failCondComb; + private QuestCondition[] failConditons; + + private List acceptCond; + private List finishCond; + private List failCond; + private List beginExec; + private List finishExec; + private List failExec; + + public int getId() { + return subId; + } + + public int getMainId() { + return mainId; + } + + public int getOrder() { + return order; + } + + public long getDescTextMapHash() { + return descTextMapHash; + } + + public boolean finishParent() { + return finishParent; + } + + public boolean isRewind() { + return isRewind; + } + + public LogicType getAcceptCondComb() { + return acceptCondComb; + } + + public QuestCondition[] getAcceptCond() { + return acceptConditons; + } + + public LogicType getFinishCondComb() { + return finishCondComb; + } + + public QuestCondition[] getFinishCond() { + return finishConditons; + } + + public LogicType getFailCondComb() { + return failCondComb; + } + + public QuestCondition[] getFailCond() { + return failConditons; + } + + public void onLoad() { + this.acceptConditons = acceptCond.stream().filter(p -> p._type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + acceptCond = null; + this.finishConditons = finishCond.stream().filter(p -> p._type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + finishCond = null; + this.failConditons = failCond.stream().filter(p -> p._type != null).map(QuestCondition::new).toArray(QuestCondition[]::new); + failCond = null; + } + + public class QuestParam { + QuestTrigger _type; + int[] _param; + String _count; + } + + public class QuestExecParam { + QuestTrigger _type; + String[] _param; + String _count; + } + + public static class QuestCondition { + private QuestTrigger type; + private int[] param; + private String count; + + public QuestCondition(QuestParam param) { + this.type = param._type; + this.param = param._param; + } + + public QuestTrigger getType() { + return type; + } + + public int[] getParam() { + return param; + } + + public String getCount() { + return count; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/def/ReliquaryAffixData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java similarity index 51% rename from src/main/java/emu/grasscutter/data/def/ReliquaryAffixData.java rename to src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java index ba9b1d369..cd4a04497 100644 --- a/src/main/java/emu/grasscutter/data/def/ReliquaryAffixData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryAffixData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @@ -6,43 +6,41 @@ import emu.grasscutter.game.props.FightProperty; @ResourceType(name = "ReliquaryAffixExcelConfigData.json") public class ReliquaryAffixData extends GameResource { - private int Id; + private int id; - private int DepotId; - private int GroupId; - private String PropType; - private float PropValue; - private int Weight; - private int UpgradeWeight; - - private FightProperty fightProp; + private int depotId; + private int groupId; + private FightProperty propType; + private float propValue; + private int weight; + private int upgradeWeight; @Override public int getId() { - return Id; + return id; } + public int getDepotId() { - return DepotId; + return depotId; } + public int getGroupId() { - return GroupId; + return groupId; } + public float getPropValue() { - return PropValue; + return propValue; } + public int getWeight() { - return Weight; + return weight; } + public int getUpgradeWeight() { - return UpgradeWeight; + return upgradeWeight; } public FightProperty getFightProp() { - return fightProp; - } - - @Override - public void onLoad() { - this.fightProp = FightProperty.getPropByName(this.PropType); + return propType; } } diff --git a/src/main/java/emu/grasscutter/data/def/ReliquaryLevelData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java similarity index 74% rename from src/main/java/emu/grasscutter/data/def/ReliquaryLevelData.java rename to src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java index b4e37dd90..488cca1e6 100644 --- a/src/main/java/emu/grasscutter/data/def/ReliquaryLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryLevelData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.List; @@ -13,10 +13,10 @@ public class ReliquaryLevelData extends GameResource { private int id; private Int2ObjectMap propMap; - private int Rank; - private int Level; - private int Exp; - private List AddProps; + private int rank; + private int level; + private int exp; + private List addProps; @Override public int getId() { @@ -24,15 +24,15 @@ public class ReliquaryLevelData extends GameResource { } public int getRank() { - return Rank; + return rank; } public int getLevel() { - return Level; + return level; } public int getExp() { - return Exp; + return exp; } public float getPropValue(FightProperty prop) { @@ -45,23 +45,23 @@ public class ReliquaryLevelData extends GameResource { @Override public void onLoad() { - this.id = (Rank << 8) + this.getLevel(); + this.id = (rank << 8) + this.getLevel(); this.propMap = new Int2ObjectOpenHashMap<>(); - for (RelicLevelProperty p : AddProps) { + for (RelicLevelProperty p : addProps) { this.propMap.put(FightProperty.getPropByName(p.getPropType()).getId(), (Float) p.getValue()); } } public class RelicLevelProperty { - private String PropType; - private float Value; + private String propType; + private float value; public String getPropType() { - return PropType; + return propType; } public float getValue() { - return Value; + return value; } } } diff --git a/src/main/java/emu/grasscutter/data/def/ReliquaryMainPropData.java b/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java similarity index 53% rename from src/main/java/emu/grasscutter/data/def/ReliquaryMainPropData.java rename to src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java index 6b2c920e4..5039849ff 100644 --- a/src/main/java/emu/grasscutter/data/def/ReliquaryMainPropData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquaryMainPropData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @@ -6,32 +6,26 @@ import emu.grasscutter.game.props.FightProperty; @ResourceType(name = "ReliquaryMainPropExcelConfigData.json") public class ReliquaryMainPropData extends GameResource { - private int Id; + private int id; - private int PropDepotId; - private String PropType; - private String AffixName; - private int Weight; - - private FightProperty fightProp; + private int propDepotId; + private FightProperty propType; + private int weight; @Override public int getId() { - return Id; + return id; } + public int getPropDepotId() { - return PropDepotId; + return propDepotId; } + public int getWeight() { - return Weight; + return weight; } public FightProperty getFightProp() { - return fightProp; - } - - @Override - public void onLoad() { - this.fightProp = FightProperty.getPropByName(this.PropType); + return propType; } } diff --git a/src/main/java/emu/grasscutter/data/def/ReliquarySetData.java b/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java similarity index 67% rename from src/main/java/emu/grasscutter/data/def/ReliquarySetData.java rename to src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java index 9eac2c050..910b8d724 100644 --- a/src/main/java/emu/grasscutter/data/def/ReliquarySetData.java +++ b/src/main/java/emu/grasscutter/data/excels/ReliquarySetData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "ReliquarySetExcelConfigData.json") public class ReliquarySetData extends GameResource { - private int SetId; - private int[] SetNeedNum; + private int setId; + private int[] setNeedNum; private int EquipAffixId; - private int DisableFilter; - private int[] ContainsList; + private int disableFilter; + private int[] containsList; @Override public int getId() { - return SetId; + return setId; } public int[] getSetNeedNum() { - return SetNeedNum; + return setNeedNum; } public int getEquipAffixId() { @@ -25,11 +25,11 @@ public class ReliquarySetData extends GameResource { } public int getDisableFilter() { - return DisableFilter; + return disableFilter; } public int[] getContainsList() { - return ContainsList; + return containsList; } @Override diff --git a/src/main/java/emu/grasscutter/data/excels/RewardData.java b/src/main/java/emu/grasscutter/data/excels/RewardData.java new file mode 100644 index 000000000..7df00b641 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/RewardData.java @@ -0,0 +1,27 @@ +package emu.grasscutter.data.excels; + +import java.util.List; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.common.ItemParamData; + +@ResourceType(name = "RewardExcelConfigData.json") +public class RewardData extends GameResource { + public int rewardId; + public List rewardItemList; + + @Override + public int getId() { + return rewardId; + } + + public List getRewardItemList() { + return rewardItemList; + } + + @Override + public void onLoad() { + rewardItemList = rewardItemList.stream().filter(i -> i.getId() > 0).toList(); + } +} diff --git a/src/main/java/emu/grasscutter/data/def/RewardPreviewData.java b/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java similarity index 70% rename from src/main/java/emu/grasscutter/data/def/RewardPreviewData.java rename to src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java index f971ee1cf..4a783f2b5 100644 --- a/src/main/java/emu/grasscutter/data/def/RewardPreviewData.java +++ b/src/main/java/emu/grasscutter/data/excels/RewardPreviewData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.Arrays; import java.util.List; @@ -16,28 +16,28 @@ import emu.grasscutter.data.common.ItemParamStringData; @ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH) public class RewardPreviewData extends GameResource { - private int Id; - private ItemParamStringData[] PreviewItems; - private ItemParamData[] PreviewItemsArray; + private int id; + private ItemParamStringData[] previewItems; + private ItemParamData[] previewItemsArray; @Override public int getId() { - return this.Id; + return this.id; } public ItemParamData[] getPreviewItems() { - return PreviewItemsArray; + return previewItemsArray; } @Override public void onLoad() { - if (this.PreviewItems != null && this.PreviewItems.length > 0) { - this.PreviewItemsArray = Arrays.stream(this.PreviewItems) + if (this.previewItems != null && this.previewItems.length > 0) { + this.previewItemsArray = Arrays.stream(this.previewItems) .filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty()) .map(ItemParamStringData::toItemParamData) .toArray(size -> new ItemParamData[size]); } else { - this.PreviewItemsArray = new ItemParamData[0]; + this.previewItemsArray = new ItemParamData[0]; } } } diff --git a/src/main/java/emu/grasscutter/data/def/SceneData.java b/src/main/java/emu/grasscutter/data/excels/SceneData.java similarity index 71% rename from src/main/java/emu/grasscutter/data/def/SceneData.java rename to src/main/java/emu/grasscutter/data/excels/SceneData.java index cd1510e1d..a0b9583c8 100644 --- a/src/main/java/emu/grasscutter/data/def/SceneData.java +++ b/src/main/java/emu/grasscutter/data/excels/SceneData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameResource; @@ -8,22 +8,21 @@ import emu.grasscutter.game.props.SceneType; @ResourceType(name = "SceneExcelConfigData.json") public class SceneData extends GameResource { - private int Id; - private SceneType Type; - private String ScriptData; + private int id; + private SceneType type; + private String scriptData; - @Override public int getId() { - return this.Id; + return this.id; } public SceneType getSceneType() { - return Type; + return type; } public String getScriptData() { - return ScriptData; + return scriptData; } @Override diff --git a/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java b/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java similarity index 57% rename from src/main/java/emu/grasscutter/data/def/ShopGoodsData.java rename to src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java index 1a4168637..4c0a14b58 100644 --- a/src/main/java/emu/grasscutter/data/def/ShopGoodsData.java +++ b/src/main/java/emu/grasscutter/data/excels/ShopGoodsData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @@ -9,34 +9,34 @@ import java.util.List; @ResourceType(name = "ShopGoodsExcelConfigData.json") public class ShopGoodsData extends GameResource { - private int GoodsId; - private int ShopType; - private int ItemId; + private int goodsId; + private int shopType; + private int itemId; - private int ItemCount; + private int itemCount; - private int CostScoin; - private int CostHcoin; - private int CostMcoin; + private int costScoin; + private int costHcoin; + private int costMcoin; - private List CostItems; - private int MinPlayerLevel; - private int MaxPlayerLevel; + private List costItems; + private int minPlayerLevel; + private int maxPlayerLevel; - private int BuyLimit; - private int SubTabId; + private int buyLimit; + private int subTabId; - private String RefreshType; - private transient ShopInfo.ShopRefreshType RefreshTypeEnum; + private String refreshType; + private transient ShopInfo.ShopRefreshType refreshTypeEnum; - private int RefreshParam; + private int refreshParam; @Override public void onLoad() { - if (this.RefreshType == null) - this.RefreshTypeEnum = ShopInfo.ShopRefreshType.NONE; + if (this.refreshType == null) + this.refreshTypeEnum = ShopInfo.ShopRefreshType.NONE; else { - this.RefreshTypeEnum = switch (this.RefreshType) { + this.refreshTypeEnum = switch (this.refreshType) { case "SHOP_REFRESH_DAILY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_DAILY; case "SHOP_REFRESH_WEEKLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_WEEKLY; case "SHOP_REFRESH_MONTHLY" -> ShopInfo.ShopRefreshType.SHOP_REFRESH_MONTHLY; @@ -51,58 +51,58 @@ public class ShopGoodsData extends GameResource { } public int getGoodsId() { - return GoodsId; + return goodsId; } public int getShopType() { - return ShopType; + return shopType; } public int getItemId() { - return ItemId; + return itemId; } public int getItemCount() { - return ItemCount; + return itemCount; } public int getCostScoin() { - return CostScoin; + return costScoin; } public int getCostHcoin() { - return CostHcoin; + return costHcoin; } public int getCostMcoin() { - return CostMcoin; + return costMcoin; } public List getCostItems() { - return CostItems; + return costItems; } public int getMinPlayerLevel() { - return MinPlayerLevel; + return minPlayerLevel; } public int getMaxPlayerLevel() { - return MaxPlayerLevel; + return maxPlayerLevel; } public int getBuyLimit() { - return BuyLimit; + return buyLimit; } public int getSubTabId() { - return SubTabId; + return subTabId; } public ShopInfo.ShopRefreshType getRefreshType() { - return RefreshTypeEnum; + return refreshTypeEnum; } public int getRefreshParam() { - return RefreshParam; + return refreshParam; } } diff --git a/src/main/java/emu/grasscutter/data/excels/TowerFloorData.java b/src/main/java/emu/grasscutter/data/excels/TowerFloorData.java new file mode 100644 index 000000000..6cb3008f0 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/TowerFloorData.java @@ -0,0 +1,49 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "TowerFloorExcelConfigData.json") +public class TowerFloorData extends GameResource { + + private int floorId; + private int floorIndex; + private int levelGroupId; + private int overrideMonsterLevel; + private int teamNum; + private int floorLevelConfigId; + + @Override + public int getId() { + return this.floorId; + } + + @Override + public void onLoad() { + super.onLoad(); + } + + public int getFloorId() { + return floorId; + } + + public int getFloorIndex() { + return floorIndex; + } + + public int getLevelGroupId() { + return levelGroupId; + } + + public int getOverrideMonsterLevel() { + return overrideMonsterLevel; + } + + public int getTeamNum() { + return teamNum; + } + + public int getFloorLevelConfigId() { + return floorLevelConfigId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java b/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java new file mode 100644 index 000000000..5bfcc61fb --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/TowerLevelData.java @@ -0,0 +1,34 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "TowerLevelExcelConfigData.json") +public class TowerLevelData extends GameResource { + + private int levelId; + private int levelIndex; + private int levelGroupId; + private int dungeonId; + + @Override + public int getId() { + return this.getLevelId(); + } + + public int getLevelId() { + return levelId; + } + + public int getLevelGroupId() { + return levelGroupId; + } + + public int getLevelIndex() { + return levelIndex; + } + + public int getDungeonId() { + return dungeonId; + } +} diff --git a/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java b/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java new file mode 100644 index 000000000..fc8a0cfc2 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/TowerScheduleData.java @@ -0,0 +1,51 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +import java.util.List; + +@ResourceType(name = "TowerScheduleExcelConfigData.json") +public class TowerScheduleData extends GameResource { + private int scheduleId; + private List entranceFloorId; + private List schedules; + private int monthlyLevelConfigId; + + @Override + public int getId() { + return scheduleId; + } + + @Override + public void onLoad() { + super.onLoad(); + this.schedules = this.schedules.stream() + .filter(item -> item.getFloorList().size() > 0) + .toList(); + } + + public int getScheduleId() { + return scheduleId; + } + + public List getEntranceFloorId() { + return entranceFloorId; + } + + public List getSchedules() { + return schedules; + } + + public int getMonthlyLevelConfigId() { + return monthlyLevelConfigId; + } + + public static class ScheduleDetail{ + private List floorList; + + public List getFloorList() { + return floorList; + } + } +} diff --git a/src/main/java/emu/grasscutter/data/def/WeaponCurveData.java b/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java similarity index 56% rename from src/main/java/emu/grasscutter/data/def/WeaponCurveData.java rename to src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java index 287ce8af6..05e64c8ed 100644 --- a/src/main/java/emu/grasscutter/data/def/WeaponCurveData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponCurveData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.HashMap; import java.util.Map; @@ -10,23 +10,23 @@ import emu.grasscutter.data.common.CurveInfo; @ResourceType(name = "WeaponCurveExcelConfigData.json") public class WeaponCurveData extends GameResource { - private int Level; - private CurveInfo[] CurveInfos; + private int level; + private CurveInfo[] curveInfos; - private Map curveInfos; + private Map curveInfosMap; @Override public int getId() { - return Level; + return level; } public float getMultByProp(String fightProp) { - return curveInfos.getOrDefault(fightProp, 1f); + return curveInfosMap.getOrDefault(fightProp, 1f); } @Override public void onLoad() { - this.curveInfos = new HashMap<>(); - Stream.of(this.CurveInfos).forEach(info -> this.curveInfos.put(info.getType(), info.getValue())); + this.curveInfosMap = new HashMap<>(); + Stream.of(this.curveInfos).forEach(info -> this.curveInfosMap.put(info.getType(), info.getValue())); } } diff --git a/src/main/java/emu/grasscutter/data/def/WeaponLevelData.java b/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java similarity index 67% rename from src/main/java/emu/grasscutter/data/def/WeaponLevelData.java rename to src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java index 98550b24a..3f69e2145 100644 --- a/src/main/java/emu/grasscutter/data/def/WeaponLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponLevelData.java @@ -1,23 +1,23 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "WeaponLevelExcelConfigData.json") public class WeaponLevelData extends GameResource { - private int Level; - private int[] RequiredExps; + private int level; + private int[] requiredExps; @Override public int getId() { - return this.Level; + return this.level; } public int getLevel() { - return Level; + return level; } public int[] getRequiredExps() { - return RequiredExps; + return requiredExps; } } diff --git a/src/main/java/emu/grasscutter/data/def/WeaponPromoteData.java b/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java similarity index 65% rename from src/main/java/emu/grasscutter/data/def/WeaponPromoteData.java rename to src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java index 8e75b2b7c..ee0306115 100644 --- a/src/main/java/emu/grasscutter/data/def/WeaponPromoteData.java +++ b/src/main/java/emu/grasscutter/data/excels/WeaponPromoteData.java @@ -1,4 +1,4 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import java.util.ArrayList; import emu.grasscutter.data.GameResource; @@ -9,45 +9,45 @@ import emu.grasscutter.data.common.ItemParamData; @ResourceType(name = "WeaponPromoteExcelConfigData.json") public class WeaponPromoteData extends GameResource { - private int WeaponPromoteId; - private int PromoteLevel; - private ItemParamData[] CostItems; - private int CoinCost; - private FightPropData[] AddProps; - private int UnlockMaxLevel; - private int RequiredPlayerLevel; + private int weaponPromoteId; + private int promoteLevel; + private ItemParamData[] costItems; + private int coinCost; + private FightPropData[] addProps; + private int unlockMaxLevel; + private int requiredPlayerLevel; @Override public int getId() { - return (WeaponPromoteId << 8) + PromoteLevel; + return (weaponPromoteId << 8) + promoteLevel; } public int getWeaponPromoteId() { - return WeaponPromoteId; + return weaponPromoteId; } public int getPromoteLevel() { - return PromoteLevel; + return promoteLevel; } public ItemParamData[] getCostItems() { - return CostItems; + return costItems; } public int getCoinCost() { - return CoinCost; + return coinCost; } public FightPropData[] getAddProps() { - return AddProps; + return addProps; } public int getUnlockMaxLevel() { - return UnlockMaxLevel; + return unlockMaxLevel; } public int getRequiredPlayerLevel() { - return RequiredPlayerLevel; + return requiredPlayerLevel; } @Override @@ -60,7 +60,7 @@ public class WeaponPromoteData extends GameResource { } trim.add(itemParam); } - this.CostItems = trim.toArray(new ItemParamData[trim.size()]); + this.costItems = trim.toArray(new ItemParamData[trim.size()]); // Trim fight prop data ArrayList parsed = new ArrayList<>(getAddProps().length); for (FightPropData prop : getAddProps()) { @@ -69,6 +69,6 @@ public class WeaponPromoteData extends GameResource { parsed.add(prop); } } - this.AddProps = parsed.toArray(new FightPropData[parsed.size()]); + this.addProps = parsed.toArray(new FightPropData[parsed.size()]); } } diff --git a/src/main/java/emu/grasscutter/data/def/WorldLevelData.java b/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java similarity index 71% rename from src/main/java/emu/grasscutter/data/def/WorldLevelData.java rename to src/main/java/emu/grasscutter/data/excels/WorldLevelData.java index 3b101f9b8..e31713b67 100644 --- a/src/main/java/emu/grasscutter/data/def/WorldLevelData.java +++ b/src/main/java/emu/grasscutter/data/excels/WorldLevelData.java @@ -1,20 +1,20 @@ -package emu.grasscutter.data.def; +package emu.grasscutter.data.excels; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; @ResourceType(name = "WorldLevelExcelConfigData.json") public class WorldLevelData extends GameResource { - private int Level; - private int MonsterLevel; + private int level; + private int monsterLevel; @Override public int getId() { - return this.Level; + return this.level; } public int getMonsterLevel() { - return MonsterLevel; + return monsterLevel; } @Override diff --git a/src/main/java/emu/grasscutter/database/DatabaseHelper.java b/src/main/java/emu/grasscutter/database/DatabaseHelper.java index f63798988..5defbca6b 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseHelper.java +++ b/src/main/java/emu/grasscutter/database/DatabaseHelper.java @@ -3,10 +3,12 @@ package emu.grasscutter.database; import java.util.List; import com.mongodb.client.result.DeleteResult; + import dev.morphia.query.FindOptions; import dev.morphia.query.Sort; import dev.morphia.query.experimental.filters.Filters; import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; import emu.grasscutter.game.Account; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.friends.Friendship; @@ -14,27 +16,34 @@ import emu.grasscutter.game.gacha.GachaRecord; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; + +import static com.mongodb.client.model.Filters.eq; public final class DatabaseHelper { public static Account createAccount(String username) { - return createAccountWithId(username, 0); + return createAccountWithUid(username, 0); } - public static Account createAccountWithId(String username, int reservedId) { + public static Account createAccountWithUid(String username, int reservedUid) { // Unique names only - Account exists = DatabaseHelper.getAccountByName(username); - if (exists != null) { + if (DatabaseHelper.checkIfAccountExists(username)) { return null; } // Make sure there are no id collisions - if (reservedId > 0) { + if (reservedUid > 0) { // Cannot make account with the same uid as the server console - if (reservedId == GameConstants.SERVER_CONSOLE_UID) { + if (reservedUid == GameConstants.SERVER_CONSOLE_UID) { return null; } - exists = DatabaseHelper.getAccountByPlayerId(reservedId); - if (exists != null) { + + if (DatabaseHelper.checkIfAccountExists(reservedUid)) { + return null; + } + + // Make sure no existing player already has this id. + if (DatabaseHelper.checkIfPlayerExists(reservedUid)) { return null; } } @@ -44,8 +53,8 @@ public final class DatabaseHelper { account.setUsername(username); account.setId(Integer.toString(DatabaseManager.getNextId(account))); - if (reservedId > 0) { - account.setPlayerId(reservedId); + if (reservedUid > 0) { + account.setReservedPlayerUid(reservedUid); } DatabaseHelper.saveAccount(account); @@ -74,118 +83,158 @@ public final class DatabaseHelper { } public static Account getAccountByName(String username) { - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("username", username)).first(); + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("username", username)).first(); } public static Account getAccountByToken(String token) { if(token == null) return null; - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("token", token)).first(); + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("token", token)).first(); } public static Account getAccountBySessionKey(String sessionKey) { if(sessionKey == null) return null; - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("sessionKey", sessionKey)).first(); + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("sessionKey", sessionKey)).first(); } public static Account getAccountById(String uid) { - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first(); + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("_id", uid)).first(); } public static Account getAccountByPlayerId(int playerId) { - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("playerId", playerId)).first(); + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("reservedPlayerId", playerId)).first(); + } + + public static boolean checkIfAccountExists(String name) { + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("username", name)).count() > 0; + } + + public static boolean checkIfAccountExists(int reservedUid) { + return DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("reservedPlayerId", reservedUid)).count() > 0; } - public static boolean deleteAccount(String username) { - return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("username", username)).delete().getDeletedCount() > 0; + public static void deleteAccount(Account target) { + // To delete an account, we need to also delete all the other documents in the database that reference the account. + // This should optimally be wrapped inside a transaction, to make sure an error thrown mid-way does not leave the + // database in an inconsistent state, but unfortunately Mongo only supports that when we have a replica set ... + + Player player = Grasscutter.getGameServer().getPlayerByAccountId(target.getId()); + + if (player != null) { + // Close session first + player.getSession().close(); + + // Delete data from collections + DatabaseManager.getGameDatabase().getCollection("mail").deleteMany(eq("ownerUid", player.getUid())); + DatabaseManager.getGameDatabase().getCollection("avatars").deleteMany(eq("ownerId", player.getUid())); + DatabaseManager.getGameDatabase().getCollection("gachas").deleteMany(eq("ownerId", player.getUid())); + DatabaseManager.getGameDatabase().getCollection("items").deleteMany(eq("ownerId", player.getUid())); + DatabaseManager.getGameDatabase().getCollection("quests").deleteMany(eq("ownerUid", player.getUid())); + + // Delete friendships. + // Here, we need to make sure to not only delete the deleted account's friendships, + // but also all friendship entries for that account's friends. + DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("ownerId", player.getUid())); + DatabaseManager.getGameDatabase().getCollection("friendships").deleteMany(eq("friendId", player.getUid())); + + // Delete the player last. + DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("id", player.getUid())).delete(); + } + + // Finally, delete the account itself. + DatabaseManager.getGameDatastore().find(Account.class).filter(Filters.eq("id", target.getId())).delete(); } public static List getAllPlayers() { - return DatabaseManager.getDatastore().find(Player.class).stream().toList(); + return DatabaseManager.getGameDatastore().find(Player.class).stream().toList(); } - public static Player getPlayerById(int id) { - return DatabaseManager.getDatastore().find(Player.class).filter(Filters.eq("_id", id)).first(); + public static Player getPlayerByUid(int id) { + return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", id)).first(); + } + + public static Player getPlayerByAccount(Account account) { + return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("accountId", account.getId())).first(); + } + + public static boolean checkIfPlayerExists(int uid) { + return DatabaseManager.getGameDatastore().find(Player.class).filter(Filters.eq("_id", uid)).count() > 0; } - public static boolean checkPlayerExists(int id) { - return DatabaseManager.getDatastore().find(Player.class).filter(Filters.eq("_id", id)).first() != null; - } - - public static synchronized Player createPlayer(Player character, int reservedId) { + public static synchronized Player generatePlayerUid(Player character, int reservedId) { // Check if reserved id int id; - if (reservedId > 0 && !checkPlayerExists(reservedId)) { + if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { id = reservedId; character.setUid(id); } else { do { id = DatabaseManager.getNextId(character); } - while (checkPlayerExists(id)); + while (checkIfPlayerExists(id)); character.setUid(id); } // Save to database - DatabaseManager.getDatastore().save(character); + DatabaseManager.getGameDatastore().save(character); return character; } public static synchronized int getNextPlayerId(int reservedId) { // Check if reserved id int id; - if (reservedId > 0 && !checkPlayerExists(reservedId)) { + if (reservedId > 0 && !checkIfPlayerExists(reservedId)) { id = reservedId; } else { do { id = DatabaseManager.getNextId(Player.class); } - while (checkPlayerExists(id)); + while (checkIfPlayerExists(id)); } return id; } public static void savePlayer(Player character) { - DatabaseManager.getDatastore().save(character); + DatabaseManager.getGameDatastore().save(character); } public static void saveAvatar(Avatar avatar) { - DatabaseManager.getDatastore().save(avatar); + DatabaseManager.getGameDatastore().save(avatar); } public static List getAvatars(Player player) { - return DatabaseManager.getDatastore().find(Avatar.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); + return DatabaseManager.getGameDatastore().find(Avatar.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); } public static void saveItem(GameItem item) { - DatabaseManager.getDatastore().save(item); + DatabaseManager.getGameDatastore().save(item); } public static boolean deleteItem(GameItem item) { - DeleteResult result = DatabaseManager.getDatastore().delete(item); + DeleteResult result = DatabaseManager.getGameDatastore().delete(item); return result.wasAcknowledged(); } public static List getInventoryItems(Player player) { - return DatabaseManager.getDatastore().find(GameItem.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); + return DatabaseManager.getGameDatastore().find(GameItem.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); } public static List getFriends(Player player) { - return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); + return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("ownerId", player.getUid())).stream().toList(); } public static List getReverseFriends(Player player) { - return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.eq("friendId", player.getUid())).stream().toList(); + return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.eq("friendId", player.getUid())).stream().toList(); } public static void saveFriendship(Friendship friendship) { - DatabaseManager.getDatastore().save(friendship); + DatabaseManager.getGameDatastore().save(friendship); } public static void deleteFriendship(Friendship friendship) { - DatabaseManager.getDatastore().delete(friendship); + DatabaseManager.getGameDatastore().delete(friendship); } public static Friendship getReverseFriendship(Friendship friendship) { - return DatabaseManager.getDatastore().find(Friendship.class).filter(Filters.and( + return DatabaseManager.getGameDatastore().find(Friendship.class).filter(Filters.and( Filters.eq("ownerId", friendship.getFriendId()), Filters.eq("friendId", friendship.getOwnerId()) )).first(); @@ -196,7 +245,7 @@ public final class DatabaseHelper { } public static List getGachaRecords(int ownerId, int page, int gachaType, int pageSize){ - return DatabaseManager.getDatastore().find(GachaRecord.class).filter( + return DatabaseManager.getGameDatastore().find(GachaRecord.class).filter( Filters.eq("ownerId", ownerId), Filters.eq("gachaType", gachaType) ).iterator(new FindOptions() @@ -211,7 +260,7 @@ public final class DatabaseHelper { } public static long getGachaRecordsMaxPage(int ownerId, int page, int gachaType, int pageSize){ - long count = DatabaseManager.getDatastore().find(GachaRecord.class).filter( + long count = DatabaseManager.getGameDatastore().find(GachaRecord.class).filter( Filters.eq("ownerId", ownerId), Filters.eq("gachaType", gachaType) ).count(); @@ -219,19 +268,31 @@ public final class DatabaseHelper { } public static void saveGachaRecord(GachaRecord gachaRecord){ - DatabaseManager.getDatastore().save(gachaRecord); + DatabaseManager.getGameDatastore().save(gachaRecord); } public static List getAllMail(Player player) { - return DatabaseManager.getDatastore().find(Mail.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); + return DatabaseManager.getGameDatastore().find(Mail.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); } public static void saveMail(Mail mail) { - DatabaseManager.getDatastore().save(mail); + DatabaseManager.getGameDatastore().save(mail); } public static boolean deleteMail(Mail mail) { - DeleteResult result = DatabaseManager.getDatastore().delete(mail); + DeleteResult result = DatabaseManager.getGameDatastore().delete(mail); return result.wasAcknowledged(); } + + public static List getAllQuests(Player player) { + return DatabaseManager.getGameDatastore().find(GameMainQuest.class).filter(Filters.eq("ownerUid", player.getUid())).stream().toList(); + } + + public static void saveQuest(GameMainQuest quest) { + DatabaseManager.getGameDatastore().save(quest); + } + + public static boolean deleteQuest(GameMainQuest quest) { + return DatabaseManager.getGameDatastore().delete(quest).wasAcknowledged(); + } } diff --git a/src/main/java/emu/grasscutter/database/DatabaseManager.java b/src/main/java/emu/grasscutter/database/DatabaseManager.java index 90ff17238..7c1360f7c 100644 --- a/src/main/java/emu/grasscutter/database/DatabaseManager.java +++ b/src/main/java/emu/grasscutter/database/DatabaseManager.java @@ -1,6 +1,5 @@ package emu.grasscutter.database; -import com.mongodb.MongoClientURI; import com.mongodb.MongoCommandException; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; @@ -20,69 +19,70 @@ import emu.grasscutter.game.gacha.GachaRecord; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; + +import static emu.grasscutter.Configuration.*; public final class DatabaseManager { - - private static MongoClient mongoClient; - private static MongoClient dispatchMongoClient; - - private static Datastore datastore; + private static Datastore gameDatastore; private static Datastore dispatchDatastore; private static final Class[] mappedClasses = new Class[] { - DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, GachaRecord.class, Mail.class + DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, + GachaRecord.class, Mail.class, GameMainQuest.class }; - public static Datastore getDatastore() { - return datastore; + public static Datastore getGameDatastore() { + return gameDatastore; } - public static MongoDatabase getDatabase() { - return getDatastore().getDatabase(); + public static MongoDatabase getGameDatabase() { + return getGameDatastore().getDatabase(); } // Yes. I very dislike this method. However, this will be good for now. // TODO: Add dispatch routes for player account management public static Datastore getAccountDatastore() { - if(Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) { + if(SERVER.runMode == ServerRunMode.GAME_ONLY) { return dispatchDatastore; } else { - return datastore; + return gameDatastore; } } public static void initialize() { // Initialize - MongoClient mongoClient = MongoClients.create(Grasscutter.getConfig().DatabaseUrl); + MongoClient gameMongoClient = MongoClients.create(DATABASE.game.connectionUri); // Set mapper options. MapperOptions mapperOptions = MapperOptions.builder() .storeEmpties(true).storeNulls(false).build(); // Create data store. - datastore = Morphia.createDatastore(mongoClient, Grasscutter.getConfig().DatabaseCollection, mapperOptions); + gameDatastore = Morphia.createDatastore(gameMongoClient, DATABASE.game.collection, mapperOptions); // Map classes. - datastore.getMapper().map(mappedClasses); + gameDatastore.getMapper().map(mappedClasses); // Ensure indexes try { - datastore.ensureIndexes(); + gameDatastore.ensureIndexes(); } catch (MongoCommandException exception) { Grasscutter.getLogger().info("Mongo index error: ", exception); // Duplicate index error if (exception.getCode() == 85) { // Drop all indexes and re add them - MongoIterable collections = datastore.getDatabase().listCollectionNames(); + MongoIterable collections = gameDatastore.getDatabase().listCollectionNames(); for (String name : collections) { - datastore.getDatabase().getCollection(name).dropIndexes(); + gameDatastore.getDatabase().getCollection(name).dropIndexes(); } // Add back indexes - datastore.ensureIndexes(); + gameDatastore.ensureIndexes(); } } - if(Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) { - dispatchMongoClient = MongoClients.create(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl); - dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection); + if(SERVER.runMode == ServerRunMode.GAME_ONLY) { + MongoClient dispatchMongoClient = MongoClients.create(DATABASE.server.connectionUri); + dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, DATABASE.server.collection); // Ensure indexes for dispatch server try { @@ -104,14 +104,14 @@ public final class DatabaseManager { } public static synchronized int getNextId(Class c) { - DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first(); + DatabaseCounter counter = getGameDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first(); if (counter == null) { counter = new DatabaseCounter(c.getSimpleName()); } try { return counter.getNextId(); } finally { - getDatastore().save(counter); + getGameDatastore().save(counter); } } diff --git a/src/main/java/emu/grasscutter/game/Account.java b/src/main/java/emu/grasscutter/game/Account.java index 5b8523ec3..3697dade5 100644 --- a/src/main/java/emu/grasscutter/game/Account.java +++ b/src/main/java/emu/grasscutter/game/Account.java @@ -5,12 +5,12 @@ import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.Utils; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.stream.Stream; import org.bson.Document; -import com.mongodb.DBObject; +import static emu.grasscutter.Configuration.*; @Entity(value = "accounts", useDiscriminator = false) public class Account { @@ -21,16 +21,18 @@ public class Account { private String username; private String password; // Unused for now - @AlsoLoad("playerUid") private int playerId; + private int reservedPlayerId; private String email; private String token; private String sessionKey; // Session token for dispatch server private List permissions; + private Locale locale; @Deprecated public Account() { this.permissions = new ArrayList<>(); + this.locale = LANGUAGE; } public String getId() { @@ -65,12 +67,12 @@ public class Account { this.token = token; } - public int getPlayerUid() { - return this.playerId; + public int getReservedPlayerUid() { + return this.reservedPlayerId; } - public void setPlayerId(int playerId) { - this.playerId = playerId; + public void setReservedPlayerUid(int playerId) { + this.reservedPlayerId = playerId; } public String getEmail() { @@ -95,6 +97,14 @@ public class Account { return this.sessionKey; } + public Locale getLocale() { + return locale; + } + + public void setLocale(Locale locale) { + this.locale = locale; + } + /** * The collection of a player's permissions. */ @@ -107,13 +117,49 @@ public class Account { this.permissions.add(permission); return true; } - public boolean hasPermission(String permission) { - return this.permissions.contains(permission) || - this.permissions.contains("*") || - (this.permissions.contains("player") || this.permissions.contains("player.*")) && permission.startsWith("player.") || - (this.permissions.contains("server") || this.permissions.contains("server.*")) && permission.startsWith("server."); + public static boolean permissionMatchesWildcard(String wildcard, String[] permissionParts) { + String[] wildcardParts = wildcard.split("\\."); + if (permissionParts.length < wildcardParts.length) { // A longer wildcard can never match a shorter permission + return false; + } + for (int i=0; i= (permissionParts.length-1)) { + return true; + } + break; + default: // This layer isn't a wildcard, it needs to match exactly + if (!wildcardParts[i].equals(permissionParts[i])) { + return false; + } + } + } + // At this point the wildcard will have matched every layer, but if it is shorter then the permission then this is not a match at this point (no **). + return (wildcardParts.length == permissionParts.length); } - + + public boolean hasPermission(String permission) { + if(this.permissions.contains("*") && this.permissions.size() == 1) return true; + + // Add default permissions if it doesn't exist + List permissions = Stream.of(this.permissions, Arrays.asList(ACCOUNT.defaultPermissions)) + .flatMap(Collection::stream) + .distinct().toList(); + + if (permissions.contains(permission)) return true; + + String[] permissionParts = permission.split("\\."); + for (String p : permissions) { + if (p.startsWith("-") && permissionMatchesWildcard(p.substring(1), permissionParts)) return false; + if (permissionMatchesWildcard(p, permissionParts)) return true; + } + + return permissions.contains("*"); + } + public boolean removePermission(String permission) { return this.permissions.remove(permission); } @@ -135,5 +181,10 @@ public class Account { if (!document.containsKey("permissions")) { this.addPermission("*"); } + + // Set account default language as server default language + if (!document.containsKey("locale")) { + this.locale = LANGUAGE; + } } } diff --git a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java new file mode 100644 index 000000000..078ef1b71 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java @@ -0,0 +1,190 @@ +package emu.grasscutter.game.ability; + +import java.util.Optional; + +import com.google.protobuf.InvalidProtocolBufferException; + +import emu.grasscutter.Grasscutter; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.AbilityModifierEntry; +import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntityClientGadget; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; +import emu.grasscutter.net.proto.AbilityInvokeEntryHeadOuterClass.AbilityInvokeEntryHead; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange; +import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap; +import emu.grasscutter.net.proto.AbilityMixinCostStaminaOuterClass.AbilityMixinCostStamina; +import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry; +import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction; +import emu.grasscutter.utils.Position; +import emu.grasscutter.utils.Utils; + +public class AbilityManager { + private Player player; + + public AbilityManager(Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } + + public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception { + // Grasscutter.getLogger().info(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray())); + switch (invoke.getArgumentType()) { + case ABILITY_INVOKE_ARGUMENT_META_OVERRIDE_PARAM: + handleOverrideParam(invoke); + break; + case ABILITY_INVOKE_ARGUMENT_META_REINIT_OVERRIDEMAP: + handleReinitOverrideMap(invoke); + break; + case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE: + handleModifierChange(invoke); + break; + case ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA: + handleMixinCostStamina(invoke); + break; + case ABILITY_INVOKE_ARGUMENT_ACTION_GENERATE_ELEM_BALL: + handleGenerateElemBall(invoke); + break; + default: + break; + } + } + + private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception { + GameEntity entity = player.getScene().getEntityById(invoke.getEntityId()); + + if (entity == null) { + return; + } + + AbilityScalarValueEntry entry = AbilityScalarValueEntry.parseFrom(invoke.getAbilityData()); + + entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); + } + + private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception { + GameEntity entity = player.getScene().getEntityById(invoke.getEntityId()); + + if (entity == null) { + return; + } + + AbilityMetaReInitOverrideMap map = AbilityMetaReInitOverrideMap.parseFrom(invoke.getAbilityData()); + + for (AbilityScalarValueEntry entry : map.getOverrideMapList()) { + entity.getMetaOverrideMap().put(entry.getKey().getStr(), entry.getFloatValue()); + } + } + + private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception { + GameEntity target = player.getScene().getEntityById(invoke.getEntityId()); + if (target == null) { + return; + } + + AbilityInvokeEntryHead head = invoke.getHead(); + if (head == null) { + return; + } + + AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData()); + if (data == null) { + return; + } + + GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId()); + if (sourceEntity == null) { + return; + } + + // This is not how it works but we will keep it for now since healing abilities dont work properly anyways + if (data.getAction() == ModifierAction.ADDED && data.getParentAbilityName() != null) { + // Handle add modifier here + String modifierString = data.getParentAbilityName().getStr(); + AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); + + if (modifier != null && modifier.getOnAdded().size() > 0) { + for (AbilityModifierAction action : modifier.getOnAdded()) { + invokeAction(action, target, sourceEntity); + } + } + + // Add to meta modifier list + target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString); + } else if (data.getAction() == ModifierAction.REMOVED) { + String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId()); + + if (modifierString != null) { + // Get modifier and call on remove event + AbilityModifierEntry modifier = GameData.getAbilityModifiers().get(modifierString); + + if (modifier != null && modifier.getOnRemoved().size() > 0) { + for (AbilityModifierAction action : modifier.getOnRemoved()) { + invokeAction(action, target, sourceEntity); + } + } + + // Remove from meta modifiers + target.getMetaModifiers().remove(head.getInstancedModifierId()); + } + } + } + + private void handleMixinCostStamina(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { + AbilityMixinCostStamina costStamina = AbilityMixinCostStamina.parseFrom((invoke.getAbilityData())); + getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim()); + } + + private void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { + this.player.getEnergyManager().handleGenerateElemBall(invoke); + } + + private void invokeAction(AbilityModifierAction action, GameEntity target, GameEntity sourceEntity) { + switch (action.type) { + case HealHP -> { + if (action.amount == null) { + return; + } + + float healAmount = 0; + + if (action.amount.isDynamic && action.amount.dynamicKey != null) { + healAmount = sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f); + } + + if (healAmount > 0) { + target.heal(healAmount); + } + } + case LoseHP -> { + if (action.amountByTargetCurrentHPRatio == null) { + return; + } + + float damageAmount = 0; + + if (action.amount.isDynamic && action.amount.dynamicKey != null) { + damageAmount = sourceEntity.getMetaOverrideMap().getOrDefault(action.amount.dynamicKey, 0f); + } + + if (damageAmount > 0) { + target.damage(damageAmount); + } + } + } + } +} + diff --git a/src/main/java/emu/grasscutter/game/avatar/Avatar.java b/src/main/java/emu/grasscutter/game/avatar/Avatar.java index b0bfb0801..588052c42 100644 --- a/src/main/java/emu/grasscutter/game/avatar/Avatar.java +++ b/src/main/java/emu/grasscutter/game/avatar/Avatar.java @@ -17,24 +17,24 @@ import dev.morphia.annotations.PostLoad; import dev.morphia.annotations.PrePersist; import dev.morphia.annotations.Transient; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.OpenConfigEntry; +import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier; import emu.grasscutter.data.common.FightPropData; -import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.OpenConfigEntry.SkillPointModifier; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.AvatarPromoteData; -import emu.grasscutter.data.def.AvatarSkillData; -import emu.grasscutter.data.def.AvatarSkillDepotData; -import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens; -import emu.grasscutter.data.def.AvatarTalentData; -import emu.grasscutter.data.def.EquipAffixData; -import emu.grasscutter.data.def.ItemData.WeaponProperty; -import emu.grasscutter.data.def.ProudSkillData; -import emu.grasscutter.data.def.ReliquaryAffixData; -import emu.grasscutter.data.def.ReliquaryLevelData; -import emu.grasscutter.data.def.ReliquaryMainPropData; -import emu.grasscutter.data.def.ReliquarySetData; -import emu.grasscutter.data.def.WeaponCurveData; -import emu.grasscutter.data.def.WeaponPromoteData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarPromoteData; +import emu.grasscutter.data.excels.AvatarSkillData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.AvatarTalentData; +import emu.grasscutter.data.excels.EquipAffixData; +import emu.grasscutter.data.excels.ProudSkillData; +import emu.grasscutter.data.excels.ReliquaryAffixData; +import emu.grasscutter.data.excels.ReliquaryLevelData; +import emu.grasscutter.data.excels.ReliquaryMainPropData; +import emu.grasscutter.data.excels.ReliquarySetData; +import emu.grasscutter.data.excels.WeaponCurveData; +import emu.grasscutter.data.excels.WeaponPromoteData; +import emu.grasscutter.data.excels.AvatarSkillDepotData.InherentProudSkillOpens; +import emu.grasscutter.data.excels.ItemData.WeaponProperty; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.inventory.EquipType; @@ -62,6 +62,8 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import static emu.grasscutter.Configuration.GAME_OPTIONS; + @Entity(value = "avatars", useDiscriminator = false) public class Avatar { @Id private ObjectId id; @@ -69,6 +71,7 @@ public class Avatar { @Transient private Player owner; @Transient private AvatarData data; + @Transient private AvatarSkillDepotData skillDepot; @Transient private long guid; // Player unique id private int avatarId; // Id of avatar @@ -78,6 +81,7 @@ public class Avatar { private int satiation; // ? private int satiationPenalty; // ? private float currentHp; + private float currentEnergy; @Transient private final Int2ObjectMap equips; @Transient private final Int2FloatOpenHashMap fightProp; @@ -103,8 +107,8 @@ public class Avatar { private int nameCardRewardId; private int nameCardId; + @Deprecated // Do not use. Morhpia only! public Avatar() { - // Morhpia only! this.equips = new Int2ObjectOpenHashMap<>(); this.fightProp = new Int2FloatOpenHashMap(); this.extraAbilityEmbryos = new HashSet<>(); @@ -140,13 +144,13 @@ public class Avatar { } // Skill depot - this.setSkillDepot(getAvatarData().getSkillDepot()); + this.setSkillDepotData(getAvatarData().getSkillDepot()); // Set stats this.recalcStats(); this.currentHp = getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.currentHp); - + this.currentEnergy = 0f; // Load handler this.onLoad(); } @@ -164,7 +168,8 @@ public class Avatar { } protected void setAvatarData(AvatarData data) { - this.data = data; + if (this.data != null) return; + this.data = data; // Used while loading this from the database } public int getOwnerId() { @@ -257,9 +262,19 @@ public class Avatar { return skillDepotId; } - public void setSkillDepot(AvatarSkillDepotData skillDepot) { - // Set id + public AvatarSkillDepotData getSkillDepot() { + return skillDepot; + } + + protected void setSkillDepot(AvatarSkillDepotData skillDepot) { + if (this.skillDepot != null) return; + this.skillDepot = skillDepot; // Used while loading this from the database + } + + public void setSkillDepotData(AvatarSkillDepotData skillDepot) { + // Set id and depot this.skillDepotId = skillDepot.getId(); + this.skillDepot = skillDepot; // Clear, then add skills getSkillLevelMap().clear(); if (skillDepot.getEnergySkill() > 0) { @@ -344,6 +359,34 @@ public class Avatar { this.currentHp = currentHp; } + public void setCurrentEnergy() { + if (GAME_OPTIONS.energyUsage) { + this.setCurrentEnergy(this.currentEnergy); + } + } + + public void setCurrentEnergy(float currentEnergy) { + if (this.getSkillDepot() != null && this.getSkillDepot().getEnergySkillData() != null) { + ElementType element = this.getSkillDepot().getElementType(); + this.setFightProperty(element.getMaxEnergyProp(), this.getSkillDepot().getEnergySkillData().getCostElemVal()); + + if (GAME_OPTIONS.energyUsage) { + this.setFightProperty(element.getCurEnergyProp(), currentEnergy); + } + else { + this.setFightProperty(element.getCurEnergyProp(), this.getSkillDepot().getEnergySkillData().getCostElemVal()); + } + } + } + + public void setCurrentEnergy(FightProperty curEnergyProp, float currentEnergy) { + if (GAME_OPTIONS.energyUsage) { + this.setFightProperty(curEnergyProp, currentEnergy); + this.currentEnergy = currentEnergy; + this.save(); + } + } + public Int2FloatOpenHashMap getFightProperties() { return fightProp; } @@ -481,6 +524,9 @@ public class Avatar { // Get hp percent, set to 100% if none float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + // Store current energy value for later + float currentEnergy = (this.getSkillDepot() != null) ? this.getFightProperty(this.getSkillDepot().getElementType().getCurEnergyProp()) : 0f; + // Clear properties this.getFightProperties().clear(); @@ -499,11 +545,7 @@ public class Avatar { } // Set energy usage - if (data.getSkillDepot() != null && data.getSkillDepot().getEnergySkillData() != null) { - ElementType element = data.getSkillDepot().getElementType(); - this.setFightProperty(element.getEnergyProperty(), data.getSkillDepot().getEnergySkillData().getCostElemVal()); - this.setFightProperty((element.getEnergyProperty().getId() % 70) + 1000, data.getSkillDepot().getEnergySkillData().getCostElemVal()); - } + setCurrentEnergy(currentEnergy); // Artifacts for (int slotId = 1; slotId <= 5; slotId++) { diff --git a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java index 2486e36ab..8feae29c6 100644 --- a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java +++ b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java @@ -4,7 +4,8 @@ import java.util.Iterator; import java.util.List; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.inventory.GameItem; @@ -139,12 +140,14 @@ public class AvatarStorage implements Iterable { } AvatarData avatarData = GameData.getAvatarDataMap().get(avatar.getAvatarId()); - if (avatarData == null) { + AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId()); + if (avatarData == null || skillDepot == null) { continue; } // Set ownerships avatar.setAvatarData(avatarData); + avatar.setSkillDepot(skillDepot); avatar.setOwner(getPlayer()); // Force recalc of const boosted skills diff --git a/src/main/java/emu/grasscutter/game/combine/CombineManger.java b/src/main/java/emu/grasscutter/game/combine/CombineManger.java index 478edfedb..641a69a0c 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineManger.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineManger.java @@ -1,7 +1,8 @@ package emu.grasscutter.game.combine; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.CombineData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CombineData; import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.proto.RetcodeOuterClass; @@ -71,7 +72,7 @@ public class CombineManger { CombineResult result = new CombineResult(); result.setMaterial(List.of()); - result.setResult(List.of(new CombineData.CombineItemPair(combineData.getResultItemId(), + result.setResult(List.of(new ItemParamData(combineData.getResultItemId(), combineData.getResultItemCount() * count))); // TODO lucky characters result.setExtra(List.of()); diff --git a/src/main/java/emu/grasscutter/game/combine/CombineResult.java b/src/main/java/emu/grasscutter/game/combine/CombineResult.java index f67a64737..067d55568 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineResult.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineResult.java @@ -1,44 +1,45 @@ package emu.grasscutter.game.combine; -import emu.grasscutter.data.def.CombineData; - import java.util.List; -public class CombineResult { - private List material; - private List result; - private List extra; - private List back; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CombineData; - public List getMaterial() { +public class CombineResult { + private List material; + private List result; + private List extra; + private List back; + + public List getMaterial() { return material; } - public void setMaterial(List material) { + public void setMaterial(List material) { this.material = material; } - public List getResult() { + public List getResult() { return result; } - public void setResult(List result) { + public void setResult(List result) { this.result = result; } - public List getExtra() { + public List getExtra() { return extra; } - public void setExtra(List extra) { + public void setExtra(List extra) { this.extra = extra; } - public List getBack() { + public List getBack() { return back; } - public void setBack(List back) { + public void setBack(List back) { this.back = back; } diff --git a/src/main/java/emu/grasscutter/game/drop/DropManager.java b/src/main/java/emu/grasscutter/game/drop/DropManager.java index e304d37b5..8908afbcd 100644 --- a/src/main/java/emu/grasscutter/game/drop/DropManager.java +++ b/src/main/java/emu/grasscutter/game/drop/DropManager.java @@ -2,8 +2,9 @@ package emu.grasscutter.game.drop; import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.inventory.GameItem; @@ -17,7 +18,8 @@ import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; import java.util.Collection; import java.util.List; @@ -41,7 +43,7 @@ public class DropManager { } public synchronized void load() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Drop.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("Drop.json"))) { getDropData().clear(); List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType()); if(banners.size() > 0) { @@ -69,9 +71,7 @@ public class DropManager { } else { // target is null if items will be added are shared. no one could pick it up because of the combination(give + shared) // so it will be sent to all players' inventories directly. - dropScene.getPlayers().forEach(x -> { - x.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true); - }); + dropScene.getPlayers().forEach(x -> x.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true)); } } } diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java index 2e07f0058..fbaf26cc5 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java @@ -1,7 +1,7 @@ package emu.grasscutter.game.dungeons; import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.def.DungeonData; +import emu.grasscutter.data.excels.DungeonData; import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; @@ -28,14 +28,20 @@ public class DungeonChallenge { private int challengeId; private boolean success; private boolean progress; - + /** + * has more challenge + */ + private boolean stage; private int score; private int objective = 0; private IntSet rewardedPlayers; - public DungeonChallenge(Scene scene, SceneGroup group) { + public DungeonChallenge(Scene scene, SceneGroup group, int challengeId, int challengeIndex, int objective) { this.scene = scene; this.group = group; + this.challengeId = challengeId; + this.challengeIndex = challengeIndex; + this.objective = objective; this.setRewardedPlayers(new IntOpenHashSet()); } @@ -86,7 +92,15 @@ public class DungeonChallenge { public int getScore() { return score; } - + + public boolean isStage() { + return stage; + } + + public void setStage(boolean stage) { + this.stage = stage; + } + public int getTimeLimit() { return 600; } @@ -112,7 +126,7 @@ public class DungeonChallenge { if (this.isSuccess()) { // Call success script event this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, null); - + // Settle settle(); } else { @@ -122,8 +136,10 @@ public class DungeonChallenge { private void settle() { getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene())); - - getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); + + if(!stage){ + getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); + } } public void onMonsterDie(EntityMonster entity) { diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java index 0a68e6ab0..367120bb8 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java @@ -3,10 +3,12 @@ package emu.grasscutter.game.dungeons; import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.ScenePointEntry; -import emu.grasscutter.data.def.DungeonData; +import emu.grasscutter.data.binout.ScenePointEntry; +import emu.grasscutter.data.excels.DungeonData; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.world.Scene; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.server.game.GameServer; @@ -51,8 +53,9 @@ public class DungeonManager { int sceneId = data.getSceneId(); player.getScene().setPrevScene(sceneId); - if(player.getWorld().transferPlayerToScene(player, sceneId, data)){ + if (player.getWorld().transferPlayerToScene(player, sceneId, data)) { player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); + player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId()); } player.getScene().setPrevScenePoint(pointId); @@ -78,19 +81,21 @@ public class DungeonManager { } public void exitDungeon(Player player) { - if (player.getScene().getSceneType() != SceneType.SCENE_DUNGEON) { + Scene scene = player.getScene(); + + if (scene==null || scene.getSceneType() != SceneType.SCENE_DUNGEON) { return; } // Get previous scene - int prevScene = player.getScene().getPrevScene() > 0 ? player.getScene().getPrevScene() : 3; + int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3; // Get previous position - DungeonData dungeonData = player.getScene().getDungeonData(); + DungeonData dungeonData = scene.getDungeonData(); Position prevPos = new Position(GameConstants.START_POSITION); if (dungeonData != null) { - ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, player.getScene().getPrevScenePoint()); + ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint()); if (entry != null) { prevPos.set(entry.getPointData().getTranPos()); diff --git a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java index 5b1ff7a30..3f212ce4a 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java +++ b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java @@ -9,15 +9,25 @@ public class TowerDungeonSettleListener implements DungeonSettleListener { @Override public void onDungeonSettle(Scene scene) { + if(scene.getScriptManager().getVariables().containsKey("stage") + && scene.getScriptManager().getVariables().get("stage") == 1){ + return; + } scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000); var towerManager = scene.getPlayers().get(0).getTowerManager(); - towerManager.notifyCurLevelRecordChangeWhenDone(); - scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify(towerManager.getCurrentFloorId())); - scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge(), - true, + towerManager.notifyCurLevelRecordChangeWhenDone(3); + scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify( + towerManager.getCurrentFloorId(), + 3, + towerManager.canEnterScheduleFloor() + )); + + scene.broadcastPacket(new PacketDungeonSettleNotify( + scene.getChallenge(), + towerManager.hasNextFloor(), towerManager.hasNextLevel(), - towerManager.getNextFloorId() + towerManager.hasNextLevel() ? 0 : towerManager.getNextFloorId() )); } diff --git a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java index 82efb795f..478f7e268 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java @@ -2,8 +2,8 @@ package emu.grasscutter.game.entity; import emu.grasscutter.GameConstants; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.AvatarSkillDepotData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.EquipType; import emu.grasscutter.game.inventory.GameItem; @@ -12,22 +12,25 @@ import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.world.Scene; -import emu.grasscutter.game.world.World; import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock; import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo; import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; import emu.grasscutter.net.proto.PropPairOuterClass.PropPair; import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType; import emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo; import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo; import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; import emu.grasscutter.utils.Position; import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.Utils; @@ -43,6 +46,7 @@ public class EntityAvatar extends GameEntity { public EntityAvatar(Scene scene, Avatar avatar) { super(scene); this.avatar = avatar; + this.avatar.setCurrentEnergy(); this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR); GameItem weapon = this.getAvatar().getWeapon(); @@ -54,6 +58,7 @@ public class EntityAvatar extends GameEntity { public EntityAvatar(Avatar avatar) { super(null); this.avatar = avatar; + this.avatar.setCurrentEnergy(); } public Player getPlayer() { @@ -101,15 +106,69 @@ public class EntityAvatar extends GameEntity { @Override public void onDeath(int killerId) { - this.killedType = PlayerDieType.PLAYER_DIE_KILL_BY_MONSTER; + this.killedType = PlayerDieType.PLAYER_DIE_TYPE_KILL_BY_MONSTER; this.killedBy = killerId; + clearEnergy(PropChangeReason.PROP_CHANGE_REASON_STATUE_RECOVER); } public void onDeath(PlayerDieType dieType, int killerId) { this.killedType = dieType; this.killedBy = killerId; + clearEnergy(PropChangeReason.PROP_CHANGE_REASON_STATUE_RECOVER); } + @Override + public float heal(float amount) { + float healed = super.heal(amount); + + if (healed > 0f) { + getScene().broadcastPacket( + new PacketEntityFightPropChangeReasonNotify(this, FightProperty.FIGHT_PROP_CUR_HP, healed, PropChangeReason.PROP_CHANGE_REASON_ABILITY, ChangeHpReason.CHANGE_HP_REASON_CHANGE_HP_ADD_ABILITY) + ); + } + + return healed; + } + + public void clearEnergy(PropChangeReason reason) { + FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); + this.avatar.setCurrentEnergy(curEnergyProp, 0); + + this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); + this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, 0f, reason)); + } + + public void addEnergy(float amount, PropChangeReason reason) { + this.addEnergy(amount, reason, false); + } + public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) { + // Get current and maximum energy for this avatar. + FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); + FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp(); + + float curEnergy = this.getFightProperty(curEnergyProp); + float maxEnergy = this.getFightProperty(maxEnergyProp); + + // Get energy recharge. + float energyRecharge = this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY); + + // Scale amount by energy recharge, if the amount is not flat. + if (!isFlat) { + amount *= energyRecharge; + } + + // Determine the new energy value. + float newEnergy = Math.min(curEnergy + amount, maxEnergy); + + // Set energy and notify. + if (newEnergy != curEnergy) { + this.avatar.setCurrentEnergy(curEnergyProp, newEnergy); + + this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); + this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason)); + } + } + public SceneAvatarInfo getSceneAvatarInfo() { SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder() .setUid(this.getPlayer().getUid()) @@ -150,7 +209,7 @@ public class EntityAvatar extends GameEntity { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_AVATAR) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setEntityClientData(EntityClientData.newBuilder()) .setEntityAuthorityInfo(authority) @@ -241,5 +300,5 @@ public class EntityAvatar extends GameEntity { // return abilityControlBlock.build(); - } + } } diff --git a/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java index 77b76566a..5e0c5eb00 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java @@ -35,6 +35,8 @@ public class EntityClientGadget extends EntityBaseGadget { private int ownerEntityId; private int targetEntityId; private boolean asyncLoad; + + private int originalOwnerEntityId; public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) { super(scene); @@ -48,6 +50,14 @@ public class EntityClientGadget extends EntityBaseGadget { this.ownerEntityId = notify.getPropOwnerEntityId(); this.targetEntityId = notify.getTargetEntityId(); this.asyncLoad = notify.getIsAsyncLoad(); + + GameEntity owner = scene.getEntityById(this.ownerEntityId); + if (owner instanceof EntityClientGadget ownerGadget) { + this.originalOwnerEntityId = ownerGadget.getOriginalOwnerEntityId(); + } + else { + this.originalOwnerEntityId = this.ownerEntityId; + } } @Override @@ -79,6 +89,10 @@ public class EntityClientGadget extends EntityBaseGadget { return this.asyncLoad; } + public int getOriginalOwnerEntityId() { + return this.originalOwnerEntityId; + } + @Override public void onDeath(int killerId) { @@ -113,7 +127,7 @@ public class EntityClientGadget extends EntityBaseGadget { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_GADGET) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setEntityClientData(EntityClientData.newBuilder()) diff --git a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java index 640f93f22..5eb9c8fab 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityGadget.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityGadget.java @@ -4,7 +4,7 @@ import java.util.Arrays; import java.util.List; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.GadgetData; +import emu.grasscutter.data.excels.GadgetData; import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; @@ -122,7 +122,7 @@ public class EntityGadget extends EntityBaseGadget { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_GADGET) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setEntityClientData(EntityClientData.newBuilder()) diff --git a/src/main/java/emu/grasscutter/game/entity/EntityItem.java b/src/main/java/emu/grasscutter/game/entity/EntityItem.java index f2b7386e1..791b230a1 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityItem.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityItem.java @@ -1,6 +1,6 @@ package emu.grasscutter.game.entity; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.EntityIdType; @@ -111,7 +111,7 @@ public class EntityItem extends EntityBaseGadget { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_GADGET) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setEntityClientData(EntityClientData.newBuilder()) @@ -127,7 +127,7 @@ public class EntityItem extends EntityBaseGadget { SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() .setGadgetId(this.getItemData().getGadgetId()) .setTrifleItem(this.getItem().toProto()) - .setBornType(GadgetBornType.GADGET_BORN_IN_AIR) + .setBornType(GadgetBornType.GADGET_BORN_TYPE_IN_AIR) .setAuthorityPeerId(this.getWorld().getHostPeerId()) .setIsEnableInteract(true); diff --git a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java index c9d0c0982..bd9785497 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java @@ -2,9 +2,10 @@ package emu.grasscutter.game.entity; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.PropGrowCurve; -import emu.grasscutter.data.def.MonsterCurveData; -import emu.grasscutter.data.def.MonsterData; +import emu.grasscutter.data.excels.MonsterCurveData; +import emu.grasscutter.data.excels.MonsterData; import emu.grasscutter.game.dungeons.DungeonChallenge; +import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.PlayerProperty; @@ -111,17 +112,41 @@ public class EntityMonster extends GameEntity { this.poseId = poseId; } + @Override + public void damage(float amount, int killerId) { + // Get HP before damage. + float hpBeforeDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + + // Apply damage. + super.damage(amount, killerId); + + // Get HP after damage. + float hpAfterDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + + // Invoke energy drop logic. + for (Player player : this.getScene().getPlayers()) { + player.getEnergyManager().handleMonsterEnergyDrop(this, hpBeforeDamage, hpAfterDamage); + } + } + @Override public void onDeath(int killerId) { if (this.getSpawnEntry() != null) { this.getScene().getDeadSpawnedEntities().add(getSpawnEntry()); } - if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) { - getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null); - } + // first set the challenge data if (getScene().getChallenge() != null && getScene().getChallenge().getGroup().id == this.getGroupId()) { getScene().getChallenge().onMonsterDie(this); } + if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) { + if(getScene().getScriptManager().getScriptMonsterSpawnService() != null){ + getScene().getScriptManager().getScriptMonsterSpawnService().onMonsterDead(this); + } + // prevent spawn monster after success + if(getScene().getChallenge() != null && getScene().getChallenge().inProgress()){ + getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null); + } + } } public void recalcStats() { @@ -186,7 +211,7 @@ public class EntityMonster extends GameEntity { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_MONSTER) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER) .setMotionInfo(this.getMotionInfo()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setEntityClientData(EntityClientData.newBuilder()) @@ -215,7 +240,7 @@ public class EntityMonster extends GameEntity { .setAuthorityPeerId(getWorld().getHostPeerId()) .setPoseId(this.getPoseId()) .setBlockId(3001) - .setBornType(MonsterBornType.MONSTER_BORN_DEFAULT) + .setBornType(MonsterBornType.MONSTER_BORN_TYPE_DEFAULT) .setSpecialNameId(40); if (getMonsterData().getDescribeData() != null) { diff --git a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java index 09f80e15b..ceab84bc3 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityVehicle.java @@ -106,7 +106,7 @@ public class EntityVehicle extends EntityBaseGadget { SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() .setEntityId(getId()) - .setEntityType(ProtEntityType.PROT_ENTITY_GADGET) + .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .setGadget(gadgetInfo) diff --git a/src/main/java/emu/grasscutter/game/entity/GameEntity.java b/src/main/java/emu/grasscutter/game/entity/GameEntity.java index 627b41103..b9ca01aea 100644 --- a/src/main/java/emu/grasscutter/game/entity/GameEntity.java +++ b/src/main/java/emu/grasscutter/game/entity/GameEntity.java @@ -1,5 +1,8 @@ package emu.grasscutter.game.entity; +import java.util.HashMap; +import java.util.Map; + import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.world.Scene; @@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.utils.Position; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; public abstract class GameEntity { protected int id; @@ -25,9 +31,13 @@ public abstract class GameEntity { private int lastMoveSceneTimeMs; private int lastMoveReliableSeq; + // Abilities + private Map metaOverrideMap; + private Int2ObjectMap metaModifiers; + public GameEntity(Scene scene) { this.scene = scene; - this.moveState = MotionState.MOTION_NONE; + this.moveState = MotionState.MOTION_STATE_NONE; } public int getId() { @@ -54,6 +64,20 @@ public abstract class GameEntity { return isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD; } + public Map getMetaOverrideMap() { + if (this.metaOverrideMap == null) { + this.metaOverrideMap = new HashMap<>(); + } + return this.metaOverrideMap; + } + + public Int2ObjectMap getMetaModifiers() { + if (this.metaModifiers == null) { + this.metaModifiers = new Int2ObjectOpenHashMap<>(); + } + return this.metaModifiers; + } + public abstract Int2FloatOpenHashMap getFightProperties(); public abstract Position getPosition(); @@ -146,4 +170,53 @@ public abstract class GameEntity { public void setSpawnEntry(SpawnDataEntry spawnEntry) { this.spawnEntry = spawnEntry; } + + public float heal(float amount) { + if (this.getFightProperties() == null) { + return 0f; + } + + float curHp = getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + float maxHp = getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + + if (curHp >= maxHp) { + return 0f; + } + + float healed = Math.min(maxHp - curHp, amount); + this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed); + + getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); + + return healed; + } + + public void damage(float amount) { + damage(amount, 0); + } + + public void damage(float amount, int killerId) { + // Sanity check + if (getFightProperties() == null) { + return; + } + + // Lose hp + addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -amount); + + // Check if dead + boolean isDead = false; + if (getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) { + setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f); + isDead = true; + } + + // Packets + this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP)); + + // Check if dead + if (isDead) { + getScene().killEntity(this, killerId); + } + } } diff --git a/src/main/java/emu/grasscutter/game/expedition/ExpeditionManager.java b/src/main/java/emu/grasscutter/game/expedition/ExpeditionManager.java index 5d1b652e1..9aab70992 100644 --- a/src/main/java/emu/grasscutter/game/expedition/ExpeditionManager.java +++ b/src/main/java/emu/grasscutter/game/expedition/ExpeditionManager.java @@ -2,14 +2,19 @@ package emu.grasscutter.game.expedition; import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; import emu.grasscutter.server.game.GameServer; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; import java.util.Collection; import java.util.List; +import static emu.grasscutter.Configuration.*; + public class ExpeditionManager { public GameServer getGameServer() { return gameServer; @@ -28,7 +33,7 @@ public class ExpeditionManager { } public synchronized void load() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ExpeditionReward.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("ExpeditionReward.json"))) { getExpeditionRewardDataList().clear(); List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ExpeditionRewardInfo.class).getType()); if(banners.size() > 0) { diff --git a/src/main/java/emu/grasscutter/game/friends/FriendsList.java b/src/main/java/emu/grasscutter/game/friends/FriendsList.java index de73ecb30..70eace5ca 100644 --- a/src/main/java/emu/grasscutter/game/friends/FriendsList.java +++ b/src/main/java/emu/grasscutter/game/friends/FriendsList.java @@ -104,7 +104,7 @@ public class FriendsList { } // Handle - if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_ACCEPT) { // Request accepted + if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT) { // Request accepted myFriendship.setIsFriend(true); theirFriendship.setIsFriend(true); diff --git a/src/main/java/emu/grasscutter/game/friends/Friendship.java b/src/main/java/emu/grasscutter/game/friends/Friendship.java index 79439bb3a..91afc85aa 100644 --- a/src/main/java/emu/grasscutter/game/friends/Friendship.java +++ b/src/main/java/emu/grasscutter/game/friends/Friendship.java @@ -95,13 +95,13 @@ public class Friendship { .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId())) .setWorldLevel(getFriendProfile().getWorldLevel()) .setSignature(getFriendProfile().getSignature()) - .setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE : FriendOnlineState.FREIEND_DISCONNECT) + .setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE : FriendOnlineState.FRIEND_ONLINE_STATE_FREIEND_DISCONNECT) .setIsMpModeAvailable(true) .setLastActiveTime(getFriendProfile().getLastActiveTime()) .setNameCardId(getFriendProfile().getNameCard()) .setParam(getFriendProfile().getDaysSinceLogin()) .setIsGameSource(true) - .setPlatformType(PlatformTypeOuterClass.PlatformType.PC) + .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) .build(); return proto; diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java index b48cb0898..f0dfca88c 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java @@ -1,8 +1,13 @@ package emu.grasscutter.game.gacha; -import emu.grasscutter.Grasscutter; import emu.grasscutter.net.proto.GachaInfoOuterClass.GachaInfo; import emu.grasscutter.net.proto.GachaUpInfoOuterClass.GachaUpInfo; +import emu.grasscutter.utils.Utils; + +import static emu.grasscutter.Configuration.*; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.common.ItemParamData; public class GachaBanner { private int gachaType; @@ -10,18 +15,35 @@ public class GachaBanner { private String prefabPath; private String previewPrefabPath; private String titlePath; - private int costItem; + private int costItemId = 0; + private int costItemAmount = 1; + private int costItemId10 = 0; + private int costItemAmount10 = 10; private int beginTime; private int endTime; private int sortId; - private int[] rateUpItems1; - private int[] rateUpItems2; - private int baseYellowWeight = 60; // Max 10000 - private int basePurpleWeight = 510; // Max 10000 - private int eventChance = 50; // Chance to win a featured event item - private int softPity = 75; - private int hardPity = 90; + private int[] rateUpItems4 = {}; + private int[] rateUpItems5 = {}; + private int[] fallbackItems3 = {11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304}; + private int[] fallbackItems4Pool1 = {1014, 1020, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1064}; + private int[] fallbackItems4Pool2 = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405}; + private int[] fallbackItems5Pool1 = {1003, 1016, 1042, 1035, 1041}; + private int[] fallbackItems5Pool2 = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; + private boolean removeC6FromPool = false; + private boolean autoStripRateUpFromFallback = true; + private int[][] weights4 = {{1,510}, {8,510}, {10,10000}}; + private int[][] weights5 = {{1,75}, {73,150}, {90,10000}}; + private int[][] poolBalanceWeights4 = {{1,255}, {17,255}, {21,10455}}; + private int[][] poolBalanceWeights5 = {{1,30}, {147,150}, {181,10230}}; + private int eventChance4 = 50; // Chance to win a featured event item + private int eventChance5 = 50; // Chance to win a featured event item private BannerType bannerType = BannerType.STANDARD; + + // Kinda wanna deprecate these but they're in people's configs + private int[] rateUpItems1 = {}; + private int[] rateUpItems2 = {}; + private int eventChance = -1; + private int costItem = 0; public int getGachaType() { return gachaType; @@ -47,8 +69,15 @@ public class GachaBanner { return titlePath; } + public ItemParamData getCost(int numRolls) { + return switch (numRolls) { + case 10 -> new ItemParamData((costItemId10 > 0) ? costItemId10 : getCostItem(), costItemAmount10); + default -> new ItemParamData(getCostItem(), costItemAmount * numRolls); + }; + } + public int getCostItem() { - return costItem; + return (costItem > 0) ? costItem : costItemId; } public int getBeginTime() { @@ -63,90 +92,102 @@ public class GachaBanner { return sortId; } - public int getBaseYellowWeight() { - return baseYellowWeight; + public int[] getRateUpItems4() { + return (rateUpItems2.length > 0) ? rateUpItems2 : rateUpItems4; + } + public int[] getRateUpItems5() { + return (rateUpItems1.length > 0) ? rateUpItems1 : rateUpItems5; } - public int getBasePurpleWeight() { - return basePurpleWeight; + public int[] getFallbackItems3() {return fallbackItems3;} + public int[] getFallbackItems4Pool1() {return fallbackItems4Pool1;} + public int[] getFallbackItems4Pool2() {return fallbackItems4Pool2;} + public int[] getFallbackItems5Pool1() {return fallbackItems5Pool1;} + public int[] getFallbackItems5Pool2() {return fallbackItems5Pool2;} + + public boolean getRemoveC6FromPool() {return removeC6FromPool;} + public boolean getAutoStripRateUpFromFallback() {return autoStripRateUpFromFallback;} + + + public int getWeight(int rarity, int pity) { + return switch(rarity) { + case 4 -> Utils.lerp(pity, weights4); + default -> Utils.lerp(pity, weights5); + }; } - public int[] getRateUpItems1() { - return rateUpItems1; + public int getPoolBalanceWeight(int rarity, int pity) { + return switch(rarity) { + case 4 -> Utils.lerp(pity, poolBalanceWeights4); + default -> Utils.lerp(pity, poolBalanceWeights5); + }; } - public int[] getRateUpItems2() { - return rateUpItems2; - } - - public int getSoftPity() { - return softPity - 1; - } - - public int getHardPity() { - return hardPity - 1; - } - - public int getEventChance() { - return eventChance; + public int getEventChance(int rarity) { + return switch(rarity) { + case 4 -> eventChance4; + default -> (eventChance > -1) ? eventChance : eventChance5; + }; } @Deprecated public GachaInfo toProto() { return toProto(""); } + public GachaInfo toProto(String sessionKey) { - String record = "http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" - + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? - Grasscutter.getConfig().getDispatchOptions().Ip : - Grasscutter.getConfig().getDispatchOptions().PublicIp) - + ":" - + Integer.toString(Grasscutter.getConfig().getDispatchOptions().PublicPort == 0 ? - Grasscutter.getConfig().getDispatchOptions().Port : - Grasscutter.getConfig().getDispatchOptions().PublicPort) + String record = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) + "/gacha?s=" + sessionKey + "&gachaType=" + gachaType; + String details = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort) + + "/gacha/details?s=" + sessionKey + "&scheduleId=" + scheduleId; + // Grasscutter.getLogger().info("record = " + record); + ItemParamData costItem1 = this.getCost(1); + ItemParamData costItem10 = this.getCost(10); GachaInfo.Builder info = GachaInfo.newBuilder() .setGachaType(this.getGachaType()) .setScheduleId(this.getScheduleId()) .setBeginTime(this.getBeginTime()) .setEndTime(this.getEndTime()) - .setCostItemId(this.getCostItem()) - .setCostItemNum(1) + .setCostItemId(costItem1.getId()) + .setCostItemNum(costItem1.getCount()) + .setTenCostItemId(costItem10.getId()) + .setTenCostItemNum(costItem10.getCount()) .setGachaPrefabPath(this.getPrefabPath()) .setGachaPreviewPrefabPath(this.getPreviewPrefabPath()) - .setGachaProbUrl(record) - .setGachaProbUrlOversea(record) + .setGachaProbUrl(details) + .setGachaProbUrlOversea(details) .setGachaRecordUrl(record) .setGachaRecordUrlOversea(record) - .setTenCostItemId(this.getCostItem()) - .setTenCostItemNum(10) .setLeftGachaTimes(Integer.MAX_VALUE) .setGachaTimesLimit(Integer.MAX_VALUE) .setGachaSortId(this.getSortId()); - if (this.getTitlePath() != null) { - info.setGachaTitlePath(this.getTitlePath()); + info.setTitleTextmap(this.getTitlePath()); } - if (this.getRateUpItems1().length > 0) { + if (this.getRateUpItems5().length > 0) { GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(1); - for (int id : getRateUpItems1()) { + for (int id : getRateUpItems5()) { upInfo.addItemIdList(id); - info.addMainNameId(id); + info.addDisplayUp5ItemList(id); } info.addGachaUpInfoList(upInfo); } - if (this.getRateUpItems2().length > 0) { + if (this.getRateUpItems4().length > 0) { GachaUpInfo.Builder upInfo = GachaUpInfo.newBuilder().setItemParentType(2); - for (int id : getRateUpItems2()) { + for (int id : getRateUpItems4()) { upInfo.addItemIdList(id); - if (info.getSubNameIdCount() == 0) { - info.addSubNameId(id); + if (info.getDisplayUp4ItemListCount() == 0) { + info.addDisplayUp4ItemList(id); } } diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java index ca7640e17..4ebce55e8 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java @@ -2,8 +2,11 @@ package emu.grasscutter.game.gacha; import java.io.File; import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; import java.nio.file.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.ThreadLocalRandom; @@ -12,12 +15,15 @@ import com.google.gson.reflect.TypeToken; import com.sun.nio.file.SensitivityWatchEventModifier; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.gacha.GachaBanner.BannerType; import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.inventory.MaterialType; import emu.grasscutter.game.player.Player; @@ -28,26 +34,25 @@ import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServerTickEvent; import emu.grasscutter.server.packet.send.PacketDoGachaRsp; +import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import org.greenrobot.eventbus.Subscribe; +import static emu.grasscutter.Configuration.*; + public class GachaManager { private final GameServer server; private final Int2ObjectMap gachaBanners; private GetGachaInfoRsp cachedProto; WatchService watchService; - - private int[] yellowAvatars = new int[] {1003, 1016, 1042, 1035, 1041}; - private int[] yellowWeapons = new int[] {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; - private int[] purpleAvatars = new int[] {1006, 1014, 1015, 1020, 1021, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1064}; - private int[] purpleWeapons = new int[] {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405}; - private int[] blueWeapons = new int[] {11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304}; - private static int starglitterId = 221; - private static int stardustId = 222; + private static final int starglitterId = 221; + private static final int stardustId = 222; + private int[] fallbackItems4Pool2Default = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405}; + private int[] fallbackItems5Pool2Default = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; public GachaManager(GameServer server) { this.server = server; @@ -64,7 +69,7 @@ public class GachaManager { return gachaBanners; } - public int randomRange(int min, int max) { + public int randomRange(int min, int max) { // Both are inclusive return ThreadLocalRandom.current().nextInt(max - min + 1) + min; } @@ -73,14 +78,16 @@ public class GachaManager { } public synchronized void load() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Banners.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("Banners.json"))) { getGachaBanners().clear(); List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, GachaBanner.class).getType()); if(banners.size() > 0) { for (GachaBanner banner : banners) { - getGachaBanners().put(banner.getGachaType(), banner); + getGachaBanners().put(banner.getScheduleId(), banner); } Grasscutter.getLogger().info("Banners successfully loaded."); + + this.cachedProto = createProto(); } else { Grasscutter.getLogger().error("Unable to load banners. Banners size is 0."); @@ -90,116 +97,196 @@ public class GachaManager { e.printStackTrace(); } } + + private class BannerPools { + public int[] rateUpItems4; + public int[] rateUpItems5; + public int[] fallbackItems4Pool1; + public int[] fallbackItems4Pool2; + public int[] fallbackItems5Pool1; + public int[] fallbackItems5Pool2; + + public BannerPools(GachaBanner banner) { + rateUpItems4 = banner.getRateUpItems4(); + rateUpItems5 = banner.getRateUpItems5(); + fallbackItems4Pool1 = banner.getFallbackItems4Pool1(); + fallbackItems4Pool2 = banner.getFallbackItems4Pool2(); + fallbackItems5Pool1 = banner.getFallbackItems5Pool1(); + fallbackItems5Pool2 = banner.getFallbackItems5Pool2(); + + if (banner.getAutoStripRateUpFromFallback()) { + fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, rateUpItems4); + fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, rateUpItems4); + fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, rateUpItems5); + fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, rateUpItems5); + } + } + + public void removeFromAllPools(int[] itemIds) { + rateUpItems4 = Utils.setSubtract(rateUpItems4, itemIds); + rateUpItems5 = Utils.setSubtract(rateUpItems5, itemIds); + fallbackItems4Pool1 = Utils.setSubtract(fallbackItems4Pool1, itemIds); + fallbackItems4Pool2 = Utils.setSubtract(fallbackItems4Pool2, itemIds); + fallbackItems5Pool1 = Utils.setSubtract(fallbackItems5Pool1, itemIds); + fallbackItems5Pool2 = Utils.setSubtract(fallbackItems5Pool2, itemIds); + } + } + + private synchronized int checkPlayerAvatarConstellationLevel(Player player, int itemId) { // Maybe this would be useful in the Player class? + ItemData itemData = GameData.getItemDataMap().get(itemId); + if ((itemData == null) || (itemData.getMaterialType() != MaterialType.MATERIAL_AVATAR)){ + return -2; // Not an Avatar + } + Avatar avatar = player.getAvatars().getAvatarById((itemId % 1000) + 10000000); + if (avatar == null) { + return -1; // Doesn't have + } + // Constellation + int constLevel = avatar.getCoreProudSkillLevel(); + GameItem constItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId + 100); + constLevel += (constItem == null)? 0 : constItem.getCount(); + return constLevel; + } + + private synchronized int[] removeC6FromPool(int[] itemPool, Player player) { + IntList temp = new IntArrayList(); + for (int itemId : itemPool) { + if (checkPlayerAvatarConstellationLevel(player, itemId) < 6) { + temp.add(itemId); + } + } + return temp.toIntArray(); + } + + private synchronized int drawRoulette(int[] weights, int cutoff) { + // This follows the logic laid out in issue #183 + // Simple weighted selection with an upper bound for the roll that cuts off trailing entries + // All weights must be >= 0 + int total = 0; + for (int weight : weights) { + if (weight < 0) { + throw new IllegalArgumentException("Weights must be non-negative!"); + } + total += weight; + } + int roll = ThreadLocalRandom.current().nextInt((total < cutoff)? total : cutoff); + int subTotal = 0; + for (int i=0; i= 1) // Lost previous coinflip + || (this.randomRange(1, 100) <= banner.getEventChance(rarity)); // Won this coinflip + if (pullFeatured && (featured.length > 0)) { + itemId = getRandom(featured); + gachaInfo.setFailedFeaturedItemPulls(rarity, 0); + } else { + gachaInfo.addFailedFeaturedItemPulls(rarity, 1); + if (fallback1.length < 1) { + if (fallback2.length < 1) { + itemId = getRandom((rarity==5)? fallbackItems5Pool2Default : fallbackItems4Pool2Default); + } else { + itemId = getRandom(fallback2); + } + } else if (fallback2.length < 1) { + itemId = getRandom(fallback1); + } else { // Both pools are possible, use the pool balancer + int pityPool1 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 1)); + int pityPool2 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 2)); + int chosenPool = switch ((pityPool1 >= pityPool2)? 1 : 0) { // Larger weight must come first for the hard cutoff to function correctly + case 1 -> 1 + drawRoulette(new int[] {pityPool1, pityPool2}, 10000); + default -> 2 - drawRoulette(new int[] {pityPool2, pityPool1}, 10000); + }; + itemId = switch (chosenPool) { + case 1: + gachaInfo.setPityPool(rarity, 1, 0); + yield getRandom(fallback1); + default: + gachaInfo.setPityPool(rarity, 2, 0); + yield getRandom(fallback2); + }; + } + } + return itemId; + } + + private synchronized int doPull(GachaBanner banner, PlayerGachaBannerInfo gachaInfo, BannerPools pools) { + // Pre-increment all pity pools (yes this makes all calculations assume 1-indexed pity) + gachaInfo.incPityAll(); + + int[] weights = {banner.getWeight(5, gachaInfo.getPity5()), banner.getWeight(4, gachaInfo.getPity4()), 10000}; + int levelWon = 5 - drawRoulette(weights, 10000); + + return switch (levelWon) { + case 5: + gachaInfo.setPity5(0); + yield doRarePull(pools.rateUpItems5, pools.fallbackItems5Pool1, pools.fallbackItems5Pool2, 5, banner, gachaInfo); + case 4: + gachaInfo.setPity4(0); + yield doRarePull(pools.rateUpItems4, pools.fallbackItems4Pool1, pools.fallbackItems4Pool2, 4, banner, gachaInfo); + default: + yield getRandom(banner.getFallbackItems3()); + }; + } - public synchronized void doPulls(Player player, int gachaType, int times) { + public synchronized void doPulls(Player player, int scheduleId, int times) { // Sanity check if (times != 10 && times != 1) { return; } - if (player.getInventory().getInventoryTab(ItemType.ITEM_WEAPON).getSize() + times > player.getInventory().getInventoryTab(ItemType.ITEM_WEAPON).getMaxCapacity()) { + Inventory inventory = player.getInventory(); + if (inventory.getInventoryTab(ItemType.ITEM_WEAPON).getSize() + times > inventory.getInventoryTab(ItemType.ITEM_WEAPON).getMaxCapacity()) { player.sendPacket(new PacketDoGachaRsp()); return; } // Get banner - GachaBanner banner = this.getGachaBanners().get(gachaType); + GachaBanner banner = this.getGachaBanners().get(scheduleId); if (banner == null) { player.sendPacket(new PacketDoGachaRsp()); return; } // Spend currency - if (banner.getCostItem() > 0) { - GameItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(banner.getCostItem()); - if (costItem == null || costItem.getCount() < times) { - return; - } - - player.getInventory().removeItem(costItem, times); - } - - // Roll - PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(banner); - IntList wonItems = new IntArrayList(times); - - for (int i = 0; i < times; i++) { - int random = this.randomRange(1, 10000); - int itemId = 0; - - int bonusYellowChance = gachaInfo.getPity5() >= banner.getSoftPity() ? 100 * (gachaInfo.getPity5() - banner.getSoftPity() - 1): 0; - int yellowChance = banner.getBaseYellowWeight() + (int) Math.floor(100f * (gachaInfo.getPity5() / (banner.getSoftPity() - 1D))) + bonusYellowChance; - int purpleChance = 10000 - (banner.getBasePurpleWeight() + (int) Math.floor(790f * (gachaInfo.getPity4() / 8f))); - - if (random <= yellowChance || gachaInfo.getPity5() >= banner.getHardPity()) { - if (banner.getRateUpItems1().length > 0) { - int eventChance = this.randomRange(1, 100); - - if (eventChance <= banner.getEventChance() || gachaInfo.getFailedFeaturedItemPulls() >= 1) { - itemId = getRandom(banner.getRateUpItems1()); - gachaInfo.setFailedFeaturedItemPulls(0); - } else { - // Lost the 50/50... rip - gachaInfo.addFailedFeaturedItemPulls(1); - } - } - - if (itemId == 0) { - int typeChance = this.randomRange(banner.getBannerType() == BannerType.WEAPON ? 2 : 1, banner.getBannerType() == BannerType.EVENT ? 1 : 2); - if (typeChance == 1) { - itemId = getRandom(this.yellowAvatars); - } else { - itemId = getRandom(this.yellowWeapons); - } - } - - // Pity - gachaInfo.addPity4(1); - gachaInfo.setPity5(0); - } else if (random >= purpleChance || gachaInfo.getPity4() >= 9) { - if (banner.getRateUpItems2().length > 0) { - int eventChance = this.randomRange(1, 100); - - if (eventChance >= 50) { - itemId = getRandom(banner.getRateUpItems2()); - } - } - - if (itemId == 0) { - int typeChance = this.randomRange(banner.getBannerType() == BannerType.WEAPON ? 2 : 1, banner.getBannerType() == BannerType.EVENT ? 1 : 2); - if (typeChance == 1) { - itemId = getRandom(this.purpleAvatars); - } else { - itemId = getRandom(this.purpleWeapons); - } - } - - // Pity - gachaInfo.addPity5(1); - gachaInfo.setPity4(0); - } else { - itemId = getRandom(this.blueWeapons); - - // Pity - gachaInfo.addPity4(1); - gachaInfo.addPity5(1); - } - - // Add winning item - wonItems.add(itemId); + ItemParamData cost = banner.getCost(times); + if (cost.getCount() > 0 && !inventory.payItem(cost)) { + player.sendPacket(new PacketDoGachaRsp()); + return; } // Add to character + PlayerGachaBannerInfo gachaInfo = player.getGachaInfo().getBannerInfo(banner); + BannerPools pools = new BannerPools(banner); List list = new ArrayList<>(); int stardust = 0, starglitter = 0; + + if (banner.getRemoveC6FromPool()) { // The ultimate form of pity (non-vanilla) + pools.rateUpItems4 = removeC6FromPool(pools.rateUpItems4, player); + pools.rateUpItems5 = removeC6FromPool(pools.rateUpItems5, player); + pools.fallbackItems4Pool1 = removeC6FromPool(pools.fallbackItems4Pool1, player); + pools.fallbackItems4Pool2 = removeC6FromPool(pools.fallbackItems4Pool2, player); + pools.fallbackItems5Pool1 = removeC6FromPool(pools.fallbackItems5Pool1, player); + pools.fallbackItems5Pool2 = removeC6FromPool(pools.fallbackItems5Pool2, player); + } - for (int itemId : wonItems) { + for (int i = 0; i < times; i++) { + // Roll + int itemId = doPull(banner, gachaInfo, pools); ItemData itemData = GameData.getItemDataMap().get(itemId); if (itemData == null) { - continue; + continue; // Maybe we should bail out if an item fails instead of rolling the rest? } // Write gacha record - GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), gachaType); + GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), banner.getGachaType()); DatabaseHelper.saveGachaRecord(gachaRecord); // Create gacha item @@ -208,63 +295,47 @@ public class GachaManager { boolean isTransferItem = false; // Const check - if (itemData.getMaterialType() == MaterialType.MATERIAL_AVATAR) { - int avatarId = (itemData.getId() % 1000) + 10000000; - Avatar avatar = player.getAvatars().getAvatarById(avatarId); - if (avatar != null) { - int constLevel = avatar.getCoreProudSkillLevel(); - int constItemId = itemData.getId() + 100; - GameItem constItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId); - if (constItem != null) { - constLevel += constItem.getCount(); + int constellation = checkPlayerAvatarConstellationLevel(player, itemId); + switch (constellation) { + case -2: // Is weapon + switch (itemData.getRankLevel()) { + case 5 -> addStarglitter = 10; + case 4 -> addStarglitter = 2; + default -> addStardust = 15; } - - if (constLevel < 6) { - // Not max const - addStarglitter = 2; - // Add 1 const - gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null)); - player.getInventory().addItem(constItemId, 1); - } else { - // Is max const - addStarglitter = 5; - } - - if (itemData.getRankLevel() == 5) { - addStarglitter *= 5; - } - - isTransferItem = true; - } else { - // New + break; + case -1: // New character gachaItem.setIsGachaItemNew(true); - } - } else { - // Is weapon - switch (itemData.getRankLevel()) { - case 5: - addStarglitter = 10; - break; - case 4: - addStarglitter = 2; - break; - case 3: - addStardust = 15; - break; - } + break; + default: + if (constellation >= 6) { // C6, give consolation starglitter + addStarglitter = (itemData.getRankLevel()==5)? 25 : 5; + } else { // C0-C5, give constellation item + if (banner.getRemoveC6FromPool() && constellation == 5) { // New C6, remove it from the pools so we don't get C7 in a 10pull + pools.removeFromAllPools(new int[] {itemId}); + } + addStarglitter = (itemData.getRankLevel()==5)? 10 : 2; + int constItemId = itemId + 100; + GameItem constItem = inventory.getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId); + gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null)); + inventory.addItem(constItemId, 1); + } + isTransferItem = true; + break; } // Create item GameItem item = new GameItem(itemData); gachaItem.setGachaItem(item.toItemParam()); - player.getInventory().addItem(item); + inventory.addItem(item); stardust += addStardust; starglitter += addStarglitter; if (addStardust > 0) { gachaItem.addTokenItemList(ItemParam.newBuilder().setItemId(stardustId).setCount(addStardust)); - } if (addStarglitter > 0) { + } + if (addStarglitter > 0) { ItemParam starglitterParam = ItemParam.newBuilder().setItemId(starglitterId).setCount(addStarglitter).build(); if (isTransferItem) { gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(starglitterParam)); @@ -277,9 +348,10 @@ public class GachaManager { // Add stardust/starglitter if (stardust > 0) { - player.getInventory().addItem(stardustId, stardust); - } if (starglitter > 0) { - player.getInventory().addItem(starglitterId, starglitter); + inventory.addItem(stardustId, stardust); + } + if (starglitter > 0) { + inventory.addItem(starglitterId, starglitter); } // Packets @@ -290,7 +362,7 @@ public class GachaManager { if(this.watchService == null) { try { this.watchService = FileSystems.getDefault().newWatchService(); - Path path = new File(Grasscutter.getConfig().DATA_FOLDER).toPath(); + Path path = new File(DATA()).toPath(); path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH); } catch (Exception e) { Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"); @@ -303,7 +375,7 @@ public class GachaManager { @Subscribe public synchronized void watchBannerJson(GameServerTickEvent tickEvent) { - if(Grasscutter.getConfig().getGameServerOptions().WatchGacha) { + if(GAME_OPTIONS.watchGachaConfig) { try { WatchKey watchKey = watchService.take(); @@ -340,8 +412,13 @@ public class GachaManager { private synchronized GetGachaInfoRsp createProto(String sessionKey) { GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345); + long currentTime = System.currentTimeMillis() / 1000L; + for (GachaBanner banner : getGachaBanners().values()) { - proto.addGachaInfoList(banner.toProto(sessionKey)); + if ((banner.getEndTime() >= currentTime && banner.getBeginTime() <= currentTime) || (banner.getBannerType() == BannerType.STANDARD)) + { + proto.addGachaInfoList(banner.toProto(sessionKey)); + } } return proto.build(); diff --git a/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java b/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java index b0c85d355..f07d2eff0 100644 --- a/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java +++ b/src/main/java/emu/grasscutter/game/gacha/PlayerGachaBannerInfo.java @@ -7,6 +7,11 @@ public class PlayerGachaBannerInfo { private int pity5 = 0; private int pity4 = 0; private int failedFeaturedItemPulls = 0; + private int failedFeatured4ItemPulls = 0; + private int pity5Pool1 = 0; + private int pity5Pool2 = 0; + private int pity4Pool1 = 0; + private int pity4Pool2 = 0; public int getPity5() { return pity5; @@ -32,15 +37,82 @@ public class PlayerGachaBannerInfo { this.pity4 += amount; } - public int getFailedFeaturedItemPulls() { - return failedFeaturedItemPulls; + public int getFailedFeaturedItemPulls(int rarity) { + return switch (rarity) { + case 4 -> failedFeatured4ItemPulls; + default -> failedFeaturedItemPulls; // 5 + }; } - public void setFailedFeaturedItemPulls(int failedEventCharacterPulls) { - this.failedFeaturedItemPulls = failedEventCharacterPulls; + public void setFailedFeaturedItemPulls(int rarity, int amount) { + switch (rarity) { + case 4 -> failedFeatured4ItemPulls = amount; + default -> failedFeaturedItemPulls = amount; // 5 + }; } - public void addFailedFeaturedItemPulls(int amount) { - failedFeaturedItemPulls += amount; + public void addFailedFeaturedItemPulls(int rarity, int amount) { + switch (rarity) { + case 4 -> failedFeatured4ItemPulls += amount; + default -> failedFeaturedItemPulls += amount; // 5 + }; + } + + public int getPityPool(int rarity, int pool) { + return switch (rarity) { + case 4 -> switch (pool) { + case 1 -> pity4Pool1; + default -> pity4Pool2; + }; + default -> switch (pool) { + case 1 -> pity5Pool1; + default -> pity5Pool2; + }; + }; + } + + public void setPityPool(int rarity, int pool, int amount) { + switch (rarity) { + case 4: + switch (pool) { + case 1 -> pity4Pool1 = amount; + default -> pity4Pool2 = amount; + }; + break; + case 5: + default: + switch (pool) { + case 1 -> pity5Pool1 = amount; + default -> pity5Pool2 = amount; + }; + break; + }; + } + + public void addPityPool(int rarity, int pool, int amount) { + switch (rarity) { + case 4: + switch (pool) { + case 1 -> pity4Pool1 += amount; + default -> pity4Pool2 += amount; + }; + break; + case 5: + default: + switch (pool) { + case 1 -> pity5Pool1 += amount; + default -> pity5Pool2 += amount; + }; + break; + }; + } + + public void incPityAll() { + pity4++; + pity5++; + pity4Pool1++; + pity4Pool2++; + pity5Pool1++; + pity5Pool2++; } } diff --git a/src/main/java/emu/grasscutter/game/inventory/GameItem.java b/src/main/java/emu/grasscutter/game/inventory/GameItem.java index 9fbc1e8c1..9aae598ff 100644 --- a/src/main/java/emu/grasscutter/game/inventory/GameItem.java +++ b/src/main/java/emu/grasscutter/game/inventory/GameItem.java @@ -15,9 +15,9 @@ import dev.morphia.annotations.Transient; import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameDepot; -import emu.grasscutter.data.def.ItemData; -import emu.grasscutter.data.def.ReliquaryAffixData; -import emu.grasscutter.data.def.ReliquaryMainPropData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.ReliquaryAffixData; +import emu.grasscutter.data.excels.ReliquaryMainPropData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.FightProperty; diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index 14d1ae203..e175aef01 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -6,16 +6,15 @@ import java.util.LinkedList; import java.util.List; import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.AvatarCostumeData; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.AvatarFlycloakData; -import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.AvatarCostumeData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.AvatarFlycloakData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.avatar.AvatarStorage; import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; @@ -28,6 +27,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import static emu.grasscutter.Configuration.*; + public class Inventory implements Iterable { private final Player player; @@ -39,10 +40,10 @@ public class Inventory implements Iterable { this.store = new Long2ObjectOpenHashMap<>(); this.inventoryTypes = new Int2ObjectOpenHashMap<>(); - this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon)); - this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic)); - this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial)); - this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture)); + this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(INVENTORY_LIMITS.weapons)); + this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(INVENTORY_LIMITS.relics)); + this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(INVENTORY_LIMITS.materials)); + this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(INVENTORY_LIMITS.furniture)); } public Player getPlayer() { @@ -149,6 +150,14 @@ public class Inventory implements Iterable { addItems(items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), null); } + public void addItemParamDatas(Collection items) { + addItemParamDatas(items, null); + } + + public void addItemParamDatas(Collection items, ActionReason reason) { + addItems(items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), reason); + } + private synchronized GameItem putItem(GameItem item) { // Dont add items that dont have a valid item definition. if (item.getItemData() == null) { @@ -172,6 +181,9 @@ public class Inventory implements Iterable { // Handle this.addVirtualItem(item.getItemId(), item.getCount()); return item; + } else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_ADSORBATE) { + this.player.getEnergyManager().handlePickupElemBall(item); + return null; } else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_AVATAR) { // Get avatar id int avatarId = (item.getItemId() % 1000) + 10000000; @@ -228,6 +240,7 @@ public class Inventory implements Iterable { } private synchronized void putItem(GameItem item, InventoryTab tab) { + getPlayer().getCodex().checkAddedItem(item); // Set owner and guid FIRST! item.setOwner(getPlayer()); // Put in item store @@ -239,26 +252,78 @@ public class Inventory implements Iterable { private void addVirtualItem(int itemId, int count) { switch (itemId) { - case 101: // Character exp - getPlayer().getServer().getInventoryManager().upgradeAvatar(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count); - break; - case 102: // Adventure exp - getPlayer().addExpDirectly(count); - break; - case 105: // Companionship exp - getPlayer().getServer().getInventoryManager().upgradeAvatarFetterLevel(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count); - break; - case 201: // Primogem - getPlayer().setPrimogems(player.getPrimogems() + count); - break; - case 202: // Mora - getPlayer().setMora(player.getMora() + count); - break; - case 203: // Genesis Crystals - getPlayer().setCrystals(player.getCrystals() + count); - break; + case 101 -> // Character exp + getPlayer().getServer().getInventoryManager().upgradeAvatar(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count); + case 102 -> // Adventure exp + getPlayer().addExpDirectly(count); + case 105 -> // Companionship exp + getPlayer().getServer().getInventoryManager().upgradeAvatarFetterLevel(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count); + case 201 -> // Primogem + getPlayer().setPrimogems(player.getPrimogems() + count); + case 202 -> // Mora + getPlayer().setMora(player.getMora() + count); + case 203 -> // Genesis Crystals + getPlayer().setCrystals(player.getCrystals() + count); } } + + private int getVirtualItemCount(int itemId) { + switch (itemId) { + case 201: // Primogem + return player.getPrimogems(); + case 202: // Mora + return player.getMora(); + case 203: // Genesis Crystals + return player.getCrystals(); + default: + GameItem item = getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); // What if we ever want to operate on weapons/relics/furniture? :S + return (item == null) ? 0 : item.getCount(); + } + } + + public boolean payItem(int id, int count) { + return payItem(new ItemParamData(id, count)); + } + + public boolean payItem(ItemParamData costItem) { + return payItems(new ItemParamData[] {costItem}, 1, null); + } + + public boolean payItems(ItemParamData[] costItems) { + return payItems(costItems, 1, null); + } + + public boolean payItems(ItemParamData[] costItems, int quantity) { + return payItems(costItems, quantity, null); + } + + public synchronized boolean payItems(ItemParamData[] costItems, int quantity, ActionReason reason) { + // Make sure player has requisite items + for (ItemParamData cost : costItems) { + if (getVirtualItemCount(cost.getId()) < (cost.getCount() * quantity)) { + return false; + } + } + // All costs are satisfied, now remove them all + for (ItemParamData cost : costItems) { + switch (cost.getId()) { + case 201 -> // Primogem + player.setPrimogems(player.getPrimogems() - (cost.getCount() * quantity)); + case 202 -> // Mora + player.setMora(player.getMora() - (cost.getCount() * quantity)); + case 203 -> // Genesis Crystals + player.setCrystals(player.getCrystals() - (cost.getCount() * quantity)); + default -> + removeItem(getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()), cost.getCount() * quantity); + } + } + + if (reason != null) { // Do we need these? + // getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason)); + } + // getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems)); + return true; + } public void removeItems(List items) { // TODO Bulk delete diff --git a/src/main/java/emu/grasscutter/game/managers/ChatManager.java b/src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManager.java similarity index 95% rename from src/main/java/emu/grasscutter/game/managers/ChatManager.java rename to src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManager.java index 7377717a5..42ff2df41 100644 --- a/src/main/java/emu/grasscutter/game/managers/ChatManager.java +++ b/src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManager.java @@ -1,4 +1,4 @@ -package emu.grasscutter.game.managers; +package emu.grasscutter.game.managers.ChatManager; import emu.grasscutter.command.CommandMap; import emu.grasscutter.game.player.Player; @@ -10,7 +10,7 @@ import emu.grasscutter.server.packet.send.PacketPrivateChatNotify; import java.util.Arrays; import java.util.List; -public class ChatManager { +public class ChatManager implements ChatManagerHandler { static final List PREFIXES = Arrays.asList('/', '!'); private final GameServer server; diff --git a/src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManagerHandler.java b/src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManagerHandler.java new file mode 100644 index 000000000..3239265e2 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/ChatManager/ChatManagerHandler.java @@ -0,0 +1,12 @@ +package emu.grasscutter.game.managers.ChatManager; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.game.GameServer; + +public interface ChatManagerHandler { + GameServer getServer(); + void sendPrivateMessage(Player player, int targetUid, String message); + void sendPrivateMessage(Player player, int targetUid, int emote); + void sendTeamMessage(Player player, int channel, String message); + void sendTeamMessage(Player player, int channel, int icon); +} diff --git a/src/main/java/emu/grasscutter/game/managers/DeforestationManager/DeforestationManager.java b/src/main/java/emu/grasscutter/game/managers/DeforestationManager/DeforestationManager.java new file mode 100644 index 000000000..ff7c0b1a9 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/DeforestationManager/DeforestationManager.java @@ -0,0 +1,91 @@ +package emu.grasscutter.game.managers.DeforestationManager; + +import java.util.ArrayList; +import java.util.HashMap; + +import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.proto.HitTreeNotifyOuterClass; +import emu.grasscutter.net.proto.VectorOuterClass; +import emu.grasscutter.utils.Position; + +public class DeforestationManager { + final static int RECORD_EXPIRED_SECONDS = 60*5; // 5 min + final static int RECORD_MAX_TIMES = 3; // max number of wood + final static int RECORD_MAX_TIMES_OTHER_HIT_TREE = 10; // if hit 10 times other trees, reset wood + + @Transient private final Player player; + @Transient private final ArrayList currentRecord; + @Transient private final static HashMap ColliderTypeToWoodItemID = new HashMap<>(); + static { + /* define wood types which reflected to item id*/ + ColliderTypeToWoodItemID.put(1,101301); + ColliderTypeToWoodItemID.put(2,101302); + ColliderTypeToWoodItemID.put(3,101303); + ColliderTypeToWoodItemID.put(4,101304); + ColliderTypeToWoodItemID.put(5,101305); + ColliderTypeToWoodItemID.put(6,101306); + ColliderTypeToWoodItemID.put(7,101307); + ColliderTypeToWoodItemID.put(8,101308); + ColliderTypeToWoodItemID.put(9,101309); + ColliderTypeToWoodItemID.put(10,101310); + ColliderTypeToWoodItemID.put(11,101311); + ColliderTypeToWoodItemID.put(12,101312); + } + public DeforestationManager(Player player){ + this.player = player; + this.currentRecord = new ArrayList<>(); + } + public void resetWood(){ + synchronized (currentRecord) { + currentRecord.clear(); + } + } + public void onDeforestationInvoke(HitTreeNotifyOuterClass.HitTreeNotify hit){ + synchronized (currentRecord) { + //Grasscutter.getLogger().info("onDeforestationInvoke! Wood records {}", currentRecord); + VectorOuterClass.Vector hitPosition = hit.getHitPostion(); + int woodType = hit.getWoodType(); + if (ColliderTypeToWoodItemID.containsKey(woodType)) {// is a available wood type + Scene scene = player.getScene(); + int itemId = ColliderTypeToWoodItemID.get(woodType); + int positionHash = hitPosition.hashCode(); + HitTreeRecord record = searchRecord(positionHash); + if (record == null) { + record = new HitTreeRecord(positionHash); + }else{ + currentRecord.remove(record);// move it to last position + } + currentRecord.add(record); + if(currentRecord.size()>RECORD_MAX_TIMES_OTHER_HIT_TREE){ + currentRecord.remove(0); + } + if(record.record()) { + EntityItem entity = new EntityItem(scene, + null, + GameData.getItemDataMap().get(itemId), + new Position(hitPosition.getX(), hitPosition.getY(), hitPosition.getZ()), + 1, + false); + scene.addEntity(entity); + } + //record.record()=false : too many wood they have deforested, no more wood dropped! + } else { + Grasscutter.getLogger().warn("No wood type {} found.", woodType); + } + } + // unknown wood type + } + private HitTreeRecord searchRecord(int id){ + for (HitTreeRecord record : currentRecord) { + if (record.getUnique() == id) { + return record; + } + } + return null; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/DeforestationManager/HitTreeRecord.java b/src/main/java/emu/grasscutter/game/managers/DeforestationManager/HitTreeRecord.java new file mode 100644 index 000000000..ee78c7506 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/DeforestationManager/HitTreeRecord.java @@ -0,0 +1,57 @@ +package emu.grasscutter.game.managers.DeforestationManager; + + + +public class HitTreeRecord { + private final int unique; + private short count; // hit this tree times + private long time; // last available hitting time + HitTreeRecord(int unique){ + this.count = 0; + this.time = 0; + this.unique = unique; + } + + /** + * reset hit time + */ + private void resetTime(){ + this.time = System.currentTimeMillis(); + } + + + /** + * commit hit behavior + */ + public boolean record(){ + if (this.count < DeforestationManager.RECORD_MAX_TIMES) { + this.count++; + resetTime(); + return true; + } + // check expired + boolean isWaiting = System.currentTimeMillis() - this.time < DeforestationManager.RECORD_EXPIRED_SECONDS * 1000L; + if(isWaiting){ + return false; + }else{ + this.count = 1; + resetTime(); + return true; + } + } + /** + * get unique id + */ + public int getUnique(){ + return unique; + } + + @Override + public String toString() { + return "HitTreeRecord{" + + "unique=" + unique + + ", count=" + count + + ", time=" + time + + '}'; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropEntry.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropEntry.java new file mode 100644 index 000000000..a26140521 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropEntry.java @@ -0,0 +1,16 @@ +package emu.grasscutter.game.managers.EnergyManager; + +import java.util.List; + +public class EnergyDropEntry { + private int dropId; + private List dropList; + + public int getDropId() { + return this.dropId; + } + + public List getDropList() { + return this.dropList; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropInfo.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropInfo.java new file mode 100644 index 000000000..40145c545 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyDropInfo.java @@ -0,0 +1,14 @@ +package emu.grasscutter.game.managers.EnergyManager; + +public class EnergyDropInfo { + private int ballId; + private int count; + + public int getBallId() { + return this.ballId; + } + + public int getCount() { + return this.count; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyManager.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyManager.java new file mode 100644 index 000000000..4e1439e5a --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager/EnergyManager.java @@ -0,0 +1,449 @@ +package emu.grasscutter.game.managers.EnergyManager; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData.HpDrops; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntityClientGadget; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.MonsterType; +import emu.grasscutter.game.props.WeaponType; +import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; +import emu.grasscutter.net.proto.AbilityIdentifierOuterClass.AbilityIdentifier; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; +import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Position; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import static emu.grasscutter.Configuration.GAME_OPTIONS; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; +import static java.util.Map.entry; + +import com.google.gson.reflect.TypeToken; +import com.google.protobuf.InvalidProtocolBufferException; + +public class EnergyManager { + private final Player player; + private final Map avatarNormalProbabilities; +// energyUsage for each player + private Boolean energyUsage; + private final static Int2ObjectMap> energyDropData = new Int2ObjectOpenHashMap<>(); + private final static Int2ObjectMap> skillParticleGenerationData = new Int2ObjectOpenHashMap<>(); + + public EnergyManager(Player player) { + this.player = player; + this.avatarNormalProbabilities = new HashMap<>(); + this.energyUsage=GAME_OPTIONS.energyUsage; + } + + public Player getPlayer() { + return this.player; + } + + public static void initialize() { + // Read the data we need for monster energy drops. + try (Reader fileReader = new InputStreamReader(DataLoader.load("EnergyDrop.json"))) { + List energyDropList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, EnergyDropEntry.class).getType()); + + for (EnergyDropEntry entry : energyDropList) { + energyDropData.put(entry.getDropId(), entry.getDropList()); + } + + Grasscutter.getLogger().info("Energy drop data successfully loaded."); + } + catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load energy drop data.", ex); + } + + // Read the data for particle generation from skills + try (Reader fileReader = new InputStreamReader(DataLoader.load("SkillParticleGeneration.json"))) { + List skillParticleGenerationList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, SkillParticleGenerationEntry.class).getType()); + + for (SkillParticleGenerationEntry entry : skillParticleGenerationList) { + skillParticleGenerationData.put(entry.getAvatarId(), entry.getAmountList()); + } + + Grasscutter.getLogger().info("Skill particle generation data successfully loaded."); + } + catch (Exception ex) { + Grasscutter.getLogger().error("Unable to load skill particle generation data data.", ex); + } + } + + /********** + Particle creation for elemental skills. + **********/ + private int getBallCountForAvatar(int avatarId) { + // We default to two particles. + int count = 2; + + // If we don't have any data for this avatar, stop. + if (!skillParticleGenerationData.containsKey(avatarId)) { + Grasscutter.getLogger().warn("No particle generation data for avatarId {} found.", avatarId); + } + // If we do have data, roll for how many particles we should generate. + else { + int roll = ThreadLocalRandom.current().nextInt(0, 100); + int percentageStack = 0; + for (SkillParticleGenerationInfo info : skillParticleGenerationData.get(avatarId)) { + int chance = info.getChance(); + percentageStack += chance; + if (roll < percentageStack) { + count = info.getValue(); + break; + } + } + } + + // Done. + return count; + } + + private int getBallIdForElement(ElementType element) { + // If we have no element, we default to an elementless particle. + if (element == null) { + return 2024; + } + + // Otherwise, we determin the particle's ID based on the element. + return switch (element) { + case Fire -> 2017; + case Water -> 2018; + case Grass -> 2019; + case Electric -> 2020; + case Wind -> 2021; + case Ice -> 2022; + case Rock -> 2023; + default -> 2024; + }; + } + + public void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { + // ToDo: + // This is also called when a weapon like Favonius Warbow etc. creates energy through its passive. + // We are not handling this correctly at the moment. + + // Get action info. + AbilityActionGenerateElemBall action = AbilityActionGenerateElemBall.parseFrom(invoke.getAbilityData()); + if (action == null) { + return; + } + + // Default to an elementless particle. + int itemId = 2024; + + // Generate 2 particles by default. + int amount = 2; + + // Try to get the casting avatar from the player's party. + Optional avatarEntity = getCastingAvatarEntityForEnergy(invoke.getEntityId()); + + // Bug: invokes twice sometimes, Ayato, Keqing + // ToDo: deal with press, hold difference. deal with charge(Beidou, Yunjin) + if (avatarEntity.isPresent()) { + Avatar avatar = avatarEntity.get().getAvatar(); + + if (avatar != null) { + int avatarId = avatar.getAvatarId(); + AvatarSkillDepotData skillDepotData = avatar.getSkillDepot(); + + // Determine how many particles we need to create for this avatar. + amount = this.getBallCountForAvatar(avatarId); + + // Determine the avatar's element, and based on that the ID of the + // particles we have to generate. + if (skillDepotData != null) { + ElementType element = skillDepotData.getElementType(); + itemId = getBallIdForElement(element); + } + } + } + + // Generate the particles. + for (int i = 0; i < amount; i++) { + generateElemBall(itemId, new Position(action.getPos()), 1); + } + } + + /********** + Pickup of elemental particles and orbs. + **********/ + public void handlePickupElemBall(GameItem elemBall) { + // Check if the item is indeed an energy particle/orb. + if (elemBall.getItemId() < 2001 ||elemBall.getItemId() > 2024) { + return; + } + + // Determine the base amount of energy given by the particle/orb. + // Particles have a base amount of 1.0, and orbs a base amount of 3.0. + float baseEnergy = (elemBall.getItemId() <= 2008) ? 3.0f : 1.0f; + + // Add energy to every team member. + for (int i = 0; i < this.player.getTeamManager().getActiveTeam().size(); i++) { + EntityAvatar entity = this.player.getTeamManager().getActiveTeam().get(i); + + // On-field vs off-field multiplier. + // The on-field character gets no penalty. + // Off-field characters get a penalty depending on the team size, as follows: + // - 2 character team: 0.8 + // - 3 character team: 0.7 + // - 4 character team: 0.6 + // - etc. + // We set a lower bound of 0.1 here, to avoid gaining no or negative energy. + float offFieldPenalty = + (this.player.getTeamManager().getCurrentCharacterIndex() == i) + ? 1.0f + : 1.0f - this.player.getTeamManager().getActiveTeam().size() * 0.1f; + offFieldPenalty = Math.max(offFieldPenalty, 0.1f); + + // Same element/neutral bonus. + // Same-element characters get a bonus of *3, while different-element characters get no bonus at all. + // For neutral particles/orbs, the multiplier is always *2. + if (entity.getAvatar().getSkillDepot() == null) { + continue; + } + + ElementType avatarElement = entity.getAvatar().getSkillDepot().getElementType(); + ElementType ballElement = switch (elemBall.getItemId()) { + case 2001, 2017 -> ElementType.Fire; + case 2002, 2018 -> ElementType.Water; + case 2003, 2019 -> ElementType.Grass; + case 2004, 2020 -> ElementType.Electric; + case 2005, 2021 -> ElementType.Wind; + case 2006, 2022 -> ElementType.Ice; + case 2007, 2023 -> ElementType.Rock; + default -> null; + }; + + float elementBonus = (ballElement == null) ? 2.0f : (avatarElement == ballElement) ? 3.0f : 1.0f; + + // Add the energy. + entity.addEnergy(baseEnergy * elementBonus * offFieldPenalty * elemBall.getCount(), PropChangeReason.PROP_CHANGE_REASON_ENERGY_BALL); + } + } + + /********** + Energy generation for NAs/CAs. + **********/ + private void generateEnergyForNormalAndCharged(EntityAvatar avatar) { + // This logic is based on the descriptions given in + // https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks + // https://library.keqingmains.com/combat-mechanics/energy#auto-attacking + // Those descriptions are lacking in some information, so this implementation most likely + // does not fully replicate the behavior of the official server. Open questions: + // - Does the probability for a character reset after some time? + // - Does the probability for a character reset when switching them out? + // - Does this really count every individual hit separately? + + // Get the avatar's weapon type. + WeaponType weaponType = avatar.getAvatar().getAvatarData().getWeaponType(); + + // Check if we already have probability data for this avatar. If not, insert it. + if (!this.avatarNormalProbabilities.containsKey(avatar)) { + this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); + } + + // Roll for energy. + int currentProbability = this.avatarNormalProbabilities.get(avatar); + int roll = ThreadLocalRandom.current().nextInt(0, 100); + + // If the player wins the roll, we increase the avatar's energy and reset the probability. + if (roll < currentProbability) { + avatar.addEnergy(1.0f, PropChangeReason.PROP_CHANGE_REASON_ABILITY, true); + this.avatarNormalProbabilities.put(avatar, weaponType.getEnergyGainInitialProbability()); + } + // Otherwise, we increase the probability for the next hit. + else { + this.avatarNormalProbabilities.put(avatar, currentProbability + weaponType.getEnergyGainIncreaseProbability()); + } + } + + public void handleAttackHit(EvtBeingHitInfo hitInfo) { + // Get the attack result. + AttackResult attackRes = hitInfo.getAttackResult(); + + // Make sure the attack was performed by the currently active avatar. If not, we ignore the hit. + Optional attackerEntity = this.getCastingAvatarEntityForEnergy(attackRes.getAttackerId()); + if (attackerEntity.isEmpty() || this.player.getTeamManager().getCurrentAvatarEntity().getId() != attackerEntity.get().getId()) { + return; + } + + // Make sure the target is an actual enemy. + GameEntity targetEntity = this.player.getScene().getEntityById(attackRes.getDefenseId()); + if (!(targetEntity instanceof EntityMonster)) { + return; + } + + EntityMonster targetMonster = (EntityMonster)targetEntity; + MonsterType targetType = targetMonster.getMonsterData().getType(); + if (targetType != MonsterType.MONSTER_ORDINARY && targetType != MonsterType.MONSTER_BOSS) { + return; + } + + // Get the ability that caused this hit. + AbilityIdentifier ability = attackRes.getAbilityIdentifier(); + + // Make sure there is no actual "ability" associated with the hit. For now, this is how we + // identify normal and charged attacks. Note that this is not completely accurate: + // - Many character's charged attacks have an ability associated with them. This means that, + // for now, we don't identify charged attacks reliably. + // - There might also be some cases where we incorrectly identify something as a normal or + // charged attack that is not (Diluc's E?). + // - Catalyst normal attacks have an ability, so we don't handle those for now. + // ToDo: Fix all of that. + if (ability != AbilityIdentifier.getDefaultInstance()) { + return; + } + + // Handle the energy generation. + this.generateEnergyForNormalAndCharged(attackerEntity.get()); + } + + + /********** + Energy logic related to using skills. + **********/ + private void handleBurstCast(Avatar avatar, int skillId) { + // Don't do anything if energy usage is disabled. + if (!GAME_OPTIONS.energyUsage || !this.energyUsage) { + return; + } + + // If the cast skill was a burst, consume energy. + if (avatar.getSkillDepot() != null && skillId == avatar.getSkillDepot().getEnergySkill()) { + avatar.getAsEntity().clearEnergy(PropChangeReason.PROP_CHANGE_REASON_ABILITY); + } + } + + public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { + // Determine the entity that has cast the skill. Cancel if we can't find that avatar. + Optional caster = this.player.getTeamManager().getActiveTeam().stream() + .filter(character -> character.getId() == casterId) + .findFirst(); + + if (caster.isEmpty()) { + return; + } + + Avatar avatar = caster.get().getAvatar(); + + // Handle elemental burst. + this.handleBurstCast(avatar, skillId); + } + + /********** + Monster energy drops. + **********/ + private void generateElemBallDrops(EntityMonster monster, int dropId) { + // Generate all drops specified for the given drop id. + if (!energyDropData.containsKey(dropId)) { + Grasscutter.getLogger().warn("No drop data for dropId {} found.", dropId); + return; + } + + for (EnergyDropInfo info : energyDropData.get(dropId)) { + this.generateElemBall(info.getBallId(), monster.getPosition(), info.getCount()); + } + } + public void handleMonsterEnergyDrop(EntityMonster monster, float hpBeforeDamage, float hpAfterDamage) { + // Make sure this is actually a monster. + // Note that some wildlife also has that type, like boars or birds. + MonsterType type = monster.getMonsterData().getType(); + if (type != MonsterType.MONSTER_ORDINARY && type != MonsterType.MONSTER_BOSS) { + return; + } + + // Calculate the HP tresholds for before and after the damage was taken. + float maxHp = monster.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + float thresholdBefore = hpBeforeDamage / maxHp; + float thresholdAfter = hpAfterDamage / maxHp; + + // Determine the thresholds the monster has passed, and generate drops based on that. + for (HpDrops drop : monster.getMonsterData().getHpDrops()) { + if (drop.getDropId() == 0) { + continue; + } + + float threshold = drop.getHpPercent() / 100.0f; + if (threshold < thresholdBefore && threshold >= thresholdAfter) { + generateElemBallDrops(monster, drop.getDropId()); + } + } + + // Handle kill drops. + if (hpAfterDamage <= 0 && monster.getMonsterData().getKillDropId() != 0) { + generateElemBallDrops(monster, monster.getMonsterData().getKillDropId()); + } + } + + /********** + Utility. + **********/ + private void generateElemBall(int ballId, Position position, int count) { + // Generate a particle/orb with the specified parameters. + ItemData itemData = GameData.getItemDataMap().get(ballId); + if (itemData == null) { + return; + } + + EntityItem energyBall = new EntityItem(this.getPlayer().getScene(), this.getPlayer(), itemData, position, count); + this.getPlayer().getScene().addEntity(energyBall); + } + + private Optional getCastingAvatarEntityForEnergy(int invokeEntityId) { + // To determine the avatar that has cast the skill that caused the energy particle to be generated, + // we have to look at the entity that has invoked the ability. This can either be that avatar directly, + // or it can be an `EntityClientGadget`, owned (some way up the owner hierarchy) by the avatar + // that cast the skill. + + // Try to get the invoking entity from the scene. + GameEntity entity = player.getScene().getEntityById(invokeEntityId); + + // Determine the ID of the entity that originally cast this skill. If the scene entity is null, + // or not an `EntityClientGadget`, we assume that we are directly looking at the casting avatar + // (the null case will happen if the avatar was switched out between casting the skill and the + // particle being generated). If the scene entity is an `EntityClientGadget`, we need to find the + // ID of the original owner of that gadget. + int avatarEntityId = + (!(entity instanceof EntityClientGadget)) + ? invokeEntityId + : ((EntityClientGadget)entity).getOriginalOwnerEntityId(); + + // Finally, find the avatar entity in the player's team. + return player.getTeamManager().getActiveTeam() + .stream() + .filter(character -> character.getId() == avatarEntityId) + .findFirst(); + } + + public Boolean getEnergyUsage() { + return energyUsage; + } + + public void setEnergyUsage(Boolean energyUsage) { + this.energyUsage = energyUsage; + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationEntry.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationEntry.java new file mode 100644 index 000000000..e99f99231 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationEntry.java @@ -0,0 +1,16 @@ +package emu.grasscutter.game.managers.EnergyManager; + +import java.util.List; + +public class SkillParticleGenerationEntry { + private int avatarId; + private List amountList; + + public int getAvatarId() { + return this.avatarId; + } + + public List getAmountList() { + return this.amountList; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationInfo.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationInfo.java new file mode 100644 index 000000000..a461b1035 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager/SkillParticleGenerationInfo.java @@ -0,0 +1,14 @@ +package emu.grasscutter.game.managers.EnergyManager; + +public class SkillParticleGenerationInfo { + private int value; + private int chance; + + public int getValue() { + return this.value; + } + + public int getChance() { + return this.chance; + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java b/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java new file mode 100644 index 000000000..9fe5623b1 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java @@ -0,0 +1,44 @@ +package emu.grasscutter.game.managers; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.EnvAnimalGatherConfigData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.net.proto.VisionTypeOuterClass; + +public record InsectCaptureManager(Player player) { + public void arrestSmallCreature(GameEntity entity) { + //System.out.println("arrestSmallCreature!"); + EnvAnimalGatherConfigData gather; + int thingId; + if (entity instanceof EntityMonster monster) { + thingId = monster.getMonsterData().getId(); + gather = GameData.getEnvAnimalGatherConfigDataMap().get(thingId); + } else if (entity instanceof EntityVehicle gadget) { + thingId = gadget.getGadgetId(); + gather = GameData.getEnvAnimalGatherConfigDataMap().get(thingId); + } else { + return; + } + if (gather == null) { + Grasscutter.getLogger().warn("monster/gather(id={}) couldn't be caught.", thingId); + return; + } + String type = gather.getEntityType(); + if ((type.equals("Monster") && entity instanceof EntityMonster) || (type.equals("Gadget") && entity instanceof EntityVehicle)) { + EnvAnimalGatherConfigData.GatherItem gatherItem = gather.gatherItem(); + ItemData data = GameData.getItemDataMap().get(gatherItem.getId()); + GameItem item = new GameItem(data, gatherItem.getCount()); + player.getInventory().addItem(item, ActionReason.SubfieldDrop); + entity.getScene().removeEntity(entity, VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE); + } else { + Grasscutter.getLogger().warn("monster/gather(id={}) has a wrong type.", thingId); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java index f3b9c0293..3d50873bf 100644 --- a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java +++ b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java @@ -1,22 +1,24 @@ package emu.grasscutter.game.managers; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.OpenConfigEntry; +import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier; import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.custom.OpenConfigEntry; -import emu.grasscutter.data.custom.OpenConfigEntry.SkillPointModifier; -import emu.grasscutter.data.def.AvatarPromoteData; -import emu.grasscutter.data.def.AvatarSkillData; -import emu.grasscutter.data.def.AvatarSkillDepotData; -import emu.grasscutter.data.def.ItemData; -import emu.grasscutter.data.def.WeaponPromoteData; -import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens; -import emu.grasscutter.data.def.AvatarTalentData; -import emu.grasscutter.data.def.ProudSkillData; +import emu.grasscutter.data.excels.AvatarPromoteData; +import emu.grasscutter.data.excels.AvatarSkillData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.AvatarTalentData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.ProudSkillData; +import emu.grasscutter.data.excels.WeaponPromoteData; +import emu.grasscutter.data.excels.AvatarSkillDepotData.InherentProudSkillOpens; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.ItemType; @@ -27,6 +29,7 @@ import emu.grasscutter.game.shop.ShopChestBatchUseTable; import emu.grasscutter.game.shop.ShopChestTable; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; +import emu.grasscutter.server.packet.send.PacketForgeFormulaDataNotify; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.Utils; @@ -38,6 +41,8 @@ public class InventoryManager { private final static int RELIC_MATERIAL_1 = 105002; // Sanctifying Unction private final static int RELIC_MATERIAL_2 = 105003; // Sanctifying Essence + private final static int RELIC_MATERIAL_EXP_1 = 2500; // Sanctifying Unction + private final static int RELIC_MATERIAL_EXP_2 = 10000; // Sanctifying Essence private final static int WEAPON_ORE_1 = 104011; // Enhancement Ore private final static int WEAPON_ORE_2 = 104012; // Fine Enhancement Ore @@ -85,6 +90,7 @@ public class InventoryManager { int moraCost = 0; int expGain = 0; + List foodRelics = new ArrayList(); for (long guid : foodRelicList) { // Add to delete queue GameItem food = player.getInventory().getItemByGuid(guid); @@ -96,23 +102,21 @@ public class InventoryManager { expGain += food.getItemData().getBaseConvExp(); // Feeding artifact with exp already if (food.getTotalExp() > 0) { - expGain += (int) Math.floor(food.getTotalExp() * .8f); + expGain += (food.getTotalExp() * 4) / 5; } + foodRelics.add(food); } + List payList = new ArrayList(); for (ItemParam itemParam : list) { - GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId()); - if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) { - continue; - } - int amount = Math.min(food.getCount(), itemParam.getCount()); - int gain = 0; - if (food.getItemId() == RELIC_MATERIAL_2) { - gain = 10000 * amount; - } else if (food.getItemId() == RELIC_MATERIAL_1) { - gain = 2500 * amount; - } + int amount = itemParam.getCount(); // Previously this capped to inventory amount, but rejecting the payment makes more sense for an invalid order + int gain = amount * switch(itemParam.getItemId()) { + case RELIC_MATERIAL_1 -> RELIC_MATERIAL_EXP_1; + case RELIC_MATERIAL_2 -> RELIC_MATERIAL_EXP_2; + default -> 0; + }; expGain += gain; moraCost += gain; + payList.add(new ItemParamData(itemParam.getItemId(), itemParam.getCount())); } // Make sure exp gain is valid @@ -120,28 +124,14 @@ public class InventoryManager { return; } - // Check mora - if (player.getMora() < moraCost) { + // Confirm payment of materials and mora (assume food relics are payable afterwards) + payList.add(new ItemParamData(202, moraCost)); + if (!player.getInventory().payItems(payList.toArray(new ItemParamData[0]))) { return; } - player.setMora(player.getMora() - moraCost); - // Consume food items - for (long guid : foodRelicList) { - GameItem food = player.getInventory().getItemByGuid(guid); - if (food == null || !food.isDestroyable()) { - continue; - } - player.getInventory().removeItem(food); - } - for (ItemParam itemParam : list) { - GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId()); - if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) { - continue; - } - int amount = Math.min(food.getCount(), itemParam.getCount()); - player.getInventory().removeItem(food, amount); - } + // Consume food relics + player.getInventory().removeItems(foodRelics); // Implement random rate boost int rate = 1; @@ -231,22 +221,16 @@ public class InventoryManager { } expGain += food.getItemData().getWeaponBaseExp(); if (food.getTotalExp() > 0) { - expGain += (int) Math.floor(food.getTotalExp() * .8f); + expGain += (food.getTotalExp() * 4) / 5; } } for (ItemParam param : itemParamList) { - GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); - if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { - continue; - } - int amount = Math.min(param.getCount(), food.getCount()); - if (food.getItemId() == WEAPON_ORE_3) { - expGain += 10000 * amount; - } else if (food.getItemId() == WEAPON_ORE_2) { - expGain += 2000 * amount; - } else if (food.getItemId() == WEAPON_ORE_1) { - expGain += 400 * amount; - } + expGain += param.getCount() * switch(param.getItemId()) { + case WEAPON_ORE_1 -> WEAPON_ORE_EXP_1; + case WEAPON_ORE_2 -> WEAPON_ORE_EXP_2; + case WEAPON_ORE_3 -> WEAPON_ORE_EXP_3; + default -> 0; + }; } // Try @@ -288,65 +272,45 @@ public class InventoryManager { } // Get exp gain - int expGain = 0, moraCost = 0; - + int expGain = 0, expGainFree = 0; + List foodWeapons = new ArrayList(); for (long guid : foodWeaponGuidList) { GameItem food = player.getInventory().getItemByGuid(guid); if (food == null || !food.isDestroyable()) { continue; } expGain += food.getItemData().getWeaponBaseExp(); - moraCost += (int) Math.floor(food.getItemData().getWeaponBaseExp() * .1f); if (food.getTotalExp() > 0) { - expGain += (int) Math.floor(food.getTotalExp() * .8f); + expGainFree += (food.getTotalExp() * 4) / 5; // No tax :D } + foodWeapons.add(food); } + List payList = new ArrayList(); for (ItemParam param : itemParamList) { - GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); - if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { - continue; - } - int amount = Math.min(param.getCount(), food.getCount()); - int gain = 0; - if (food.getItemId() == WEAPON_ORE_3) { - gain = 10000 * amount; - } else if (food.getItemId() == WEAPON_ORE_2) { - gain = 2000 * amount; - } else if (food.getItemId() == WEAPON_ORE_1) { - gain = 400 * amount; - } + int amount = param.getCount(); // Previously this capped to inventory amount, but rejecting the payment makes more sense for an invalid order + int gain = amount * switch(param.getItemId()) { + case WEAPON_ORE_1 -> WEAPON_ORE_EXP_1; + case WEAPON_ORE_2 -> WEAPON_ORE_EXP_2; + case WEAPON_ORE_3 -> WEAPON_ORE_EXP_3; + default -> 0; + }; expGain += gain; - moraCost += (int) Math.floor(gain * .1f); + payList.add(new ItemParamData(param.getItemId(), amount)); } // Make sure exp gain is valid + int moraCost = expGain / 10; + expGain += expGainFree; if (expGain <= 0) { return; } - - // Mora check - if (player.getMora() >= moraCost) { - player.setMora(player.getMora() - moraCost); - } else { + + // Confirm payment of materials and mora (assume food weapons are payable afterwards) + payList.add(new ItemParamData(202, moraCost)); + if (!player.getInventory().payItems(payList.toArray(new ItemParamData[0]))) { return; } - - // Consume weapon/items used to feed - for (long guid : foodWeaponGuidList) { - GameItem food = player.getInventory().getItemByGuid(guid); - if (food == null || !food.isDestroyable()) { - continue; - } - player.getInventory().removeItem(food); - } - for (ItemParam param : itemParamList) { - GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); - if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { - continue; - } - int amount = Math.min(param.getCount(), food.getCount()); - player.getInventory().removeItem(food, amount); - } + player.getInventory().removeItems(foodWeapons); // Level up int maxLevel = promoteData.getUnlockMaxLevel(); @@ -393,7 +357,7 @@ public class InventoryManager { player.sendPacket(new PacketWeaponUpgradeRsp(weapon, oldLevel, leftovers)); } - private List getLeftoverOres(float leftover) { + private List getLeftoverOres(int leftover) { List leftoverOreList = new ArrayList<>(3); if (leftover < WEAPON_ORE_EXP_1) { @@ -401,11 +365,11 @@ public class InventoryManager { } // Get leftovers - int ore3 = (int) Math.floor(leftover / WEAPON_ORE_EXP_3); + int ore3 = leftover / WEAPON_ORE_EXP_3; leftover = leftover % WEAPON_ORE_EXP_3; - int ore2 = (int) Math.floor(leftover / WEAPON_ORE_EXP_2); + int ore2 = leftover / WEAPON_ORE_EXP_2; leftover = leftover % WEAPON_ORE_EXP_2; - int ore1 = (int) Math.floor(leftover / WEAPON_ORE_EXP_1); + int ore1 = leftover / WEAPON_ORE_EXP_1; if (ore3 > 0) { leftoverOreList.add(ItemParam.newBuilder().setItemId(WEAPON_ORE_3).setCount(ore3).build()); @@ -496,27 +460,16 @@ public class InventoryManager { return; } - // Make sure player has promote items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length-1] = new ItemParamData(202, nextPromoteData.getCoinCost()); } - - // Mora check - if (player.getMora() >= nextPromoteData.getCoinCost()) { - player.setMora(player.getMora() - nextPromoteData.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs)) { return; } - // Consume promote filler items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - int oldPromoteLevel = weapon.getPromoteLevel(); weapon.setPromoteLevel(nextPromoteLevel); weapon.save(); @@ -552,27 +505,16 @@ public class InventoryManager { return; } - // Make sure player has cost items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + ItemParamData[] costs = nextPromoteData.getCostItems(); // Can this be null? + if (nextPromoteData.getCoinCost() > 0) { + costs = Arrays.copyOf(costs, costs.length + 1); + costs[costs.length-1] = new ItemParamData(202, nextPromoteData.getCoinCost()); } - - // Mora check - if (player.getMora() >= nextPromoteData.getCoinCost()) { - player.setMora(player.getMora() - nextPromoteData.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs)) { return; } - // Consume promote filler items - for (ItemParamData cost : nextPromoteData.getCostItems()) { - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - // Update promote level avatar.setPromoteLevel(nextPromoteLevel); @@ -616,34 +558,25 @@ public class InventoryManager { return; } - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); - - if (feedItem == null || feedItem.getItemData().getMaterialType() != MaterialType.MATERIAL_EXP_FRUIT || feedItem.getCount() < count) { - return; - } - // Calc exp - int expGain = 0, moraCost = 0; + int expGain = switch(itemId) { + case AVATAR_BOOK_1 -> AVATAR_BOOK_EXP_1 * count; + case AVATAR_BOOK_2 -> AVATAR_BOOK_EXP_2 * count; + case AVATAR_BOOK_3 -> AVATAR_BOOK_EXP_3 * count; + default -> 0; + }; - // TODO clean up - if (itemId == AVATAR_BOOK_3) { - expGain = AVATAR_BOOK_EXP_3 * count; - } else if (itemId == AVATAR_BOOK_2) { - expGain = AVATAR_BOOK_EXP_2 * count; - } else if (itemId == AVATAR_BOOK_1) { - expGain = AVATAR_BOOK_EXP_1 * count; - } - moraCost = (int) Math.floor(expGain * .2f); - - // Mora check - if (player.getMora() >= moraCost) { - player.setMora(player.getMora() - moraCost); - } else { + // Sanity check + if (expGain <= 0) { + return; + } + + // Payment check + int moraCost = expGain / 5; + ItemParamData[] costItems = new ItemParamData[] {new ItemParamData(itemId, count), new ItemParamData(202, moraCost)}; + if (!player.getInventory().payItems(costItems)) { return; } - - // Consume items - player.getInventory().removeItem(feedItem, count); // Level up upgradeAvatar(player, avatar, promoteData, expGain); @@ -764,33 +697,15 @@ public class InventoryManager { return; } - // Make sure player has cost items - for (ItemParamData cost : proudSkill.getCostItems()) { - if (cost.getId() == 0) { - continue; - } - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - if (feedItem == null || feedItem.getCount() < cost.getCount()) { - return; - } + // Pay materials and mora if possible + List costs = new ArrayList(proudSkill.getCostItems()); // Can this be null? + if (proudSkill.getCoinCost() > 0) { + costs.add(new ItemParamData(202, proudSkill.getCoinCost())); } - - // Mora check - if (player.getMora() >= proudSkill.getCoinCost()) { - player.setMora(player.getMora() - proudSkill.getCoinCost()); - } else { + if (!player.getInventory().payItems(costs.toArray(new ItemParamData[0]))) { return; } - // Consume promote filler items - for (ItemParamData cost : proudSkill.getCostItems()) { - if (cost.getId() == 0) { - continue; - } - GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); - player.getInventory().removeItem(feedItem, cost.getCount()); - } - // Upgrade skill avatar.getSkillLevelMap().put(skillId, nextLevel); avatar.save(); @@ -822,14 +737,11 @@ public class InventoryManager { return; } - GameItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(talentData.getMainCostItemId()); - if (costItem == null || costItem.getCount() < talentData.getMainCostItemCount()) { + // Pay constellation item if possible + if (!player.getInventory().payItem(talentData.getMainCostItemId(), 1)) { return; } - // Consume item - player.getInventory().removeItem(costItem, talentData.getMainCostItemCount()); - // Apply + recalc avatar.getTalentIdList().add(talentData.getId()); avatar.setCoreProudSkillLevel(currentTalentLevel + 1); @@ -932,6 +844,25 @@ public class InventoryManager { used = player.getTeamManager().healAvatar(target, SatiationParams[0], SatiationParams[1]) ? 1 : 0; } break; + case MATERIAL_CONSUME: + // Make sure we have usage data for this material. + if (useItem.getItemData().getItemUse() == null) { + break; + } + + // Handle forging blueprints. + if (useItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_FORGE")) { + // Determine the forging item we should unlock. + int forgeId = Integer.parseInt(useItem.getItemData().getItemUse().get(0).getUseParam().get(0)); + + // Tell the client that this blueprint is now unlocked and add the unlocked item to the player. + player.sendPacket(new PacketForgeFormulaDataNotify(forgeId)); + player.getUnlockedForgingBlueprints().add(forgeId); + + // Use up the blueprint item. + used = 1; + } + break; case MATERIAL_CHEST: List shopChestTableList = player.getServer().getShopManager().getShopChestData(); List rewardItemList = new ArrayList<>(); diff --git a/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMark.java b/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMark.java index 2dcbf7972..e49d0c802 100644 --- a/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMark.java +++ b/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMark.java @@ -1,9 +1,9 @@ package emu.grasscutter.game.managers.MapMarkManager; import dev.morphia.annotations.Entity; -import emu.grasscutter.net.proto.MapMarkFromTypeOuterClass; -import emu.grasscutter.net.proto.MapMarkPointOuterClass; -import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass; +import emu.grasscutter.net.proto.MapMarkFromTypeOuterClass.MapMarkFromType; +import emu.grasscutter.net.proto.MapMarkPointOuterClass.MapMarkPoint; +import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; import emu.grasscutter.utils.Position; @Entity @@ -11,63 +11,56 @@ public class MapMark { private int sceneId; private String name; private Position position; - private MapMarkPointTypeOuterClass.MapMarkPointType pointType; - private int monsterId = 0; - private MapMarkFromTypeOuterClass.MapMarkFromType fromType; - private int questId = 7; - - public MapMark(Position position, MapMarkPointTypeOuterClass.MapMarkPointType type) { - this.position = position; + private MapMarkPointType mapMarkPointType; + private int monsterId; + private MapMarkFromType mapMarkFromType; + private int questId; + + @Deprecated // Morhpia + public MapMark() { + this.mapMarkPointType = MapMarkPointType.MAP_MARK_POINT_TYPE_MONSTER; + this.mapMarkFromType = MapMarkFromType.MAP_MARK_FROM_TYPE_MONSTER; } - public MapMark(MapMarkPointOuterClass.MapMarkPoint mapMarkPoint) { + public MapMark(MapMarkPoint mapMarkPoint) { this.sceneId = mapMarkPoint.getSceneId(); this.name = mapMarkPoint.getName(); - this.position = new Position(mapMarkPoint.getPos().getX(), mapMarkPoint.getPos().getY(), mapMarkPoint.getPos().getZ()); - this.pointType = mapMarkPoint.getPointType(); + this.position = new Position( + mapMarkPoint.getPos().getX(), + mapMarkPoint.getPos().getY(), + mapMarkPoint.getPos().getZ() + ); + this.mapMarkPointType = mapMarkPoint.getPointType(); this.monsterId = mapMarkPoint.getMonsterId(); - this.fromType = mapMarkPoint.getFromType(); + this.mapMarkFromType = mapMarkPoint.getFromType(); this.questId = mapMarkPoint.getQuestId(); } public int getSceneId() { return this.sceneId; } - + public String getName() { return this.name; } - + public Position getPosition() { return this.position; } - - public MapMarkPointTypeOuterClass.MapMarkPointType getMapMarkPointType() { - return this.pointType; + + public MapMarkPointType getMapMarkPointType() { + return this.mapMarkPointType; } - - public void setMapMarkPointType(MapMarkPointTypeOuterClass.MapMarkPointType pointType) { - this.pointType = pointType; - } - + public int getMonsterId() { return this.monsterId; } - - public void setMonsterId(int monsterId) { - this.monsterId = monsterId; + + public MapMarkFromType getMapMarkFromType() { + return this.mapMarkFromType; } - - public MapMarkFromTypeOuterClass.MapMarkFromType getMapMarkFromType() { - return this.fromType; - } - + public int getQuestId() { return this.questId; } - - public void setQuestId(int questId) { - this.questId = questId; - } - -} +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMarksManager.java b/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMarksManager.java index 5249f59d9..949786d12 100644 --- a/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMarksManager.java +++ b/src/main/java/emu/grasscutter/game/managers/MapMarkManager/MapMarksManager.java @@ -1,61 +1,90 @@ package emu.grasscutter.game.managers.MapMarkManager; -import dev.morphia.annotations.Entity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType; +import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; +import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq.Operation; +import emu.grasscutter.server.packet.send.PacketMarkMapRsp; +import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; import emu.grasscutter.utils.Position; + import java.util.HashMap; -@Entity public class MapMarksManager { - - static final int mapMarkMaxCount = 150; + public static final int mapMarkMaxCount = 150; private HashMap mapMarks; + private final Player player; - public MapMarksManager() { - mapMarks = new HashMap(); + public MapMarksManager(Player player) { + this.player = player; + this.mapMarks = player.getMapMarks(); + if (this.mapMarks == null) { this.mapMarks = new HashMap<>(); } } - public MapMarksManager(HashMap mapMarks) { - this.mapMarks = mapMarks; - } - - public HashMap getAllMapMarks() { - return mapMarks; - } - - public MapMark getMapMark(Position position) { - String key = getMapMarkKey(position); - if (mapMarks.containsKey(key)) { - return mapMarks.get(key); - } else { - return null; + public void handleMapMarkReq(MarkMapReq req) { + Operation op = req.getOp(); + switch (op) { + case OPERATION_ADD -> { + MapMark createMark = new MapMark(req.getMark()); + // keep teleporting functionality on fishhook mark. + if (createMark.getMapMarkPointType() == MapMarkPointType.MAP_MARK_POINT_TYPE_FISH_POOL) { + teleport(player, createMark); + return; + } + addMapMark(createMark); + } + case OPERATION_MOD -> { + MapMark oldMark = new MapMark(req.getOld()); + removeMapMark(oldMark.getPosition()); + MapMark newMark = new MapMark(req.getMark()); + addMapMark(newMark); + } + case OPERATION_DEL -> { + MapMark deleteMark = new MapMark(req.getMark()); + removeMapMark(deleteMark.getPosition()); + } } + if (op != Operation.OPERATION_GET) { + saveMapMarks(); + } + player.getSession().send(new PacketMarkMapRsp(getMapMarks())); + } + + public HashMap getMapMarks() { + return mapMarks; } public String getMapMarkKey(Position position) { return "x" + (int)position.getX()+ "z" + (int)position.getZ(); } - public boolean removeMapMark(Position position) { - String key = getMapMarkKey(position); - if (mapMarks.containsKey(key)) { - mapMarks.remove(key); - return true; - } - return false; + public void removeMapMark(Position position) { + mapMarks.remove(getMapMarkKey(position)); } - public boolean addMapMark(MapMark mapMark) { + public void addMapMark(MapMark mapMark) { if (mapMarks.size() < mapMarkMaxCount) { - if (!mapMarks.containsKey(mapMark.getPosition())) { - mapMarks.put(getMapMarkKey(mapMark.getPosition()), mapMark); - return true; - } + mapMarks.put(getMapMarkKey(mapMark.getPosition()), mapMark); } - return false; } - public void setMapMarks(HashMap mapMarks) { - this.mapMarks = mapMarks; + private void saveMapMarks() { + player.setMapMarks(mapMarks); + player.save(); } + private void teleport(Player player, MapMark mapMark) { + float y; + try { + y = (float)Integer.parseInt(mapMark.getName()); + } catch (Exception e) { + y = 300; + } + Position pos = mapMark.getPosition(); + player.getPos().set(pos.getX(), y, pos.getZ()); + if (mapMark.getSceneId() != player.getSceneId()) { + player.getWorld().transferPlayerToScene(player, mapMark.getSceneId(), player.getPos()); + } + player.getScene().broadcastPacket(new PacketSceneEntityAppearNotify(player)); + } } diff --git a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java b/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java deleted file mode 100644 index 23b45903a..000000000 --- a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java +++ /dev/null @@ -1,442 +0,0 @@ -package emu.grasscutter.game.managers.MovementManager; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.LifeState; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.proto.EntityMoveInfoOuterClass; -import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; -import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; -import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.net.proto.VectorOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.*; -import emu.grasscutter.utils.Position; -import org.jetbrains.annotations.NotNull; - -import java.lang.Math; -import java.util.*; - -public class MovementManager { - - public HashMap> MotionStatesCategorized = new HashMap<>(); - - private enum ConsumptionType { - None(0), - - // consume - CLIMB_START(-500), - CLIMBING(-150), - CLIMB_JUMP(-2500), - DASH(-1800), - SPRINT(-360), - FLY(-60), - SWIM_DASH_START(-200), - SWIM_DASH(-200), - SWIMMING(-80), - FIGHT(0), - - // restore - STANDBY(500), - RUN(500), - WALK(500), - STANDBY_MOVE(500), - POWERED_FLY(500); - - public final int amount; - ConsumptionType(int amount) { - this.amount = amount; - } - } - - private class Consumption { - public ConsumptionType consumptionType; - public int amount; - public Consumption(ConsumptionType ct, int a) { - consumptionType = ct; - amount = a; - } - public Consumption(ConsumptionType ct) { - this(ct, ct.amount); - } - } - - private MotionState previousState = MotionState.MOTION_STANDBY; - private MotionState currentState = MotionState.MOTION_STANDBY; - private Position previousCoordinates = new Position(0, 0, 0); - private Position currentCoordinates = new Position(0, 0, 0); - - private final Player player; - - private float landSpeed = 0; - private long landTimeMillisecond = 0; - private Timer movementManagerTickTimer; - private GameSession cachedSession = null; - private GameEntity cachedEntity = null; - private int staminaRecoverDelay = 0; - private int skillCaster = 0; - private int skillCasting = 0; - - public MovementManager(Player player) { - previousCoordinates.add(new Position(0,0,0)); - this.player = player; - - MotionStatesCategorized.put("SWIM", new HashSet<>(Arrays.asList( - MotionState.MOTION_SWIM_MOVE, - MotionState.MOTION_SWIM_IDLE, - MotionState.MOTION_SWIM_DASH, - MotionState.MOTION_SWIM_JUMP - ))); - - MotionStatesCategorized.put("STANDBY", new HashSet<>(Arrays.asList( - MotionState.MOTION_STANDBY, - MotionState.MOTION_STANDBY_MOVE, - MotionState.MOTION_DANGER_STANDBY, - MotionState.MOTION_DANGER_STANDBY_MOVE, - MotionState.MOTION_LADDER_TO_STANDBY, - MotionState.MOTION_JUMP_UP_WALL_FOR_STANDBY - ))); - - MotionStatesCategorized.put("CLIMB", new HashSet<>(Arrays.asList( - MotionState.MOTION_CLIMB, - MotionState.MOTION_CLIMB_JUMP, - MotionState.MOTION_STANDBY_TO_CLIMB, - MotionState.MOTION_LADDER_IDLE, - MotionState.MOTION_LADDER_MOVE, - MotionState.MOTION_LADDER_SLIP, - MotionState.MOTION_STANDBY_TO_LADDER - ))); - - MotionStatesCategorized.put("FLY", new HashSet<>(Arrays.asList( - MotionState.MOTION_FLY, - MotionState.MOTION_FLY_IDLE, - MotionState.MOTION_FLY_SLOW, - MotionState.MOTION_FLY_FAST, - MotionState.MOTION_POWERED_FLY - ))); - - MotionStatesCategorized.put("RUN", new HashSet<>(Arrays.asList( - MotionState.MOTION_DASH, - MotionState.MOTION_DANGER_DASH, - MotionState.MOTION_DASH_BEFORE_SHAKE, - MotionState.MOTION_RUN, - MotionState.MOTION_DANGER_RUN, - MotionState.MOTION_WALK, - MotionState.MOTION_DANGER_WALK - ))); - - MotionStatesCategorized.put("FIGHT", new HashSet<>(Arrays.asList( - MotionState.MOTION_FIGHT - ))); - - - } - - public void handle(GameSession session, EntityMoveInfoOuterClass.EntityMoveInfo moveInfo, GameEntity entity) { - if (movementManagerTickTimer == null) { - movementManagerTickTimer = new Timer(); - movementManagerTickTimer.scheduleAtFixedRate(new MotionManagerTick(), 0, 200); - } - // cache info for later use in tick - cachedSession = session; - cachedEntity = entity; - - MotionInfo motionInfo = moveInfo.getMotionInfo(); - moveEntity(entity, moveInfo); - VectorOuterClass.Vector posVector = motionInfo.getPos(); - Position newPos = new Position(posVector.getX(), - posVector.getY(), posVector.getZ());; - if (newPos.getX() != 0 && newPos.getY() != 0 && newPos.getZ() != 0) { - currentCoordinates = newPos; - } - currentState = motionInfo.getState(); - Grasscutter.getLogger().debug("" + currentState + "\t" + (moveInfo.getIsReliable() ? "reliable" : "")); - handleFallOnGround(motionInfo); - } - - public void resetTimer() { - Grasscutter.getLogger().debug("MovementManager ticker stopped"); - movementManagerTickTimer.cancel(); - movementManagerTickTimer = null; - } - - private void moveEntity(GameEntity entity, EntityMoveInfoOuterClass.EntityMoveInfo moveInfo) { - entity.getPosition().set(moveInfo.getMotionInfo().getPos()); - entity.getRotation().set(moveInfo.getMotionInfo().getRot()); - entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); - entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); - entity.setMotionState(moveInfo.getMotionInfo().getState()); - } - - private boolean isPlayerMoving() { - float diffX = currentCoordinates.getX() - previousCoordinates.getX(); - float diffY = currentCoordinates.getY() - previousCoordinates.getY(); - float diffZ = currentCoordinates.getZ() - previousCoordinates.getZ(); - // Grasscutter.getLogger().debug("isPlayerMoving: " + previousCoordinates + ", " + currentCoordinates + ", " + diffX + ", " + diffY + ", " + diffZ); - return Math.abs(diffX) > 0.2 || Math.abs(diffY) > 0.1 || Math.abs(diffZ) > 0.2; - } - - private int getCurrentStamina() { - return player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); - } - - private int getMaximumStamina() { - return player.getProperty(PlayerProperty.PROP_MAX_STAMINA); - } - - // Returns new stamina - public int updateStamina(GameSession session, int amount) { - int currentStamina = session.getPlayer().getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); - if (amount == 0) { - return currentStamina; - } - int playerMaxStamina = session.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA); - int newStamina = currentStamina + amount; - if (newStamina < 0) { - newStamina = 0; - } - if (newStamina > playerMaxStamina) { - newStamina = playerMaxStamina; - } - session.getPlayer().setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, newStamina); - session.send(new PacketPlayerPropNotify(player, PlayerProperty.PROP_CUR_PERSIST_STAMINA)); - return newStamina; - } - - private void handleFallOnGround(@NotNull MotionInfo motionInfo) { - MotionState state = motionInfo.getState(); - // land speed and fall on ground event arrive in different packets - // cache land speed - if (state == MotionState.MOTION_LAND_SPEED) { - landSpeed = motionInfo.getSpeed().getY(); - landTimeMillisecond = System.currentTimeMillis(); - } - if (state == MotionState.MOTION_FALL_ON_GROUND) { - // if not received immediately after MOTION_LAND_SPEED, discard this packet. - // TODO: Test in high latency. - int maxDelay = 200; - if ((System.currentTimeMillis() - landTimeMillisecond) > maxDelay) { - Grasscutter.getLogger().debug("MOTION_FALL_ON_GROUND received after " + maxDelay + "ms, discard."); - return; - } - float currentHP = cachedEntity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - float maxHP = cachedEntity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - float damage = 0; - Grasscutter.getLogger().debug("LandSpeed: " + landSpeed); - if (landSpeed < -23.5) { - damage = (float)(maxHP * 0.33); - } - if (landSpeed < -25) { - damage = (float)(maxHP * 0.5); - } - if (landSpeed < -26.5) { - damage = (float)(maxHP * 0.66); - } - if (landSpeed < -28) { - damage = (maxHP * 1); - } - float newHP = currentHP - damage; - if (newHP < 0) { - newHP = 0; - } - Grasscutter.getLogger().debug("Max: " + maxHP + "\tCurr: " + currentHP + "\tDamage: " + damage + "\tnewHP: " + newHP); - cachedEntity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); - cachedEntity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(cachedEntity, FightProperty.FIGHT_PROP_CUR_HP)); - if (newHP == 0) { - killAvatar(cachedSession, cachedEntity, PlayerDieType.PLAYER_DIE_FALL); - } - landSpeed = 0; - } - } - - private void handleDrowning() { - int stamina = getCurrentStamina(); - if (stamina < 10) { - boolean isSwimming = MotionStatesCategorized.get("SWIM").contains(currentState); - Grasscutter.getLogger().debug(player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA) + "/" + player.getProperty(PlayerProperty.PROP_MAX_STAMINA) + "\t" + currentState + "\t" + isSwimming); - if (isSwimming && currentState != MotionState.MOTION_SWIM_IDLE) { - killAvatar(cachedSession, cachedEntity, PlayerDieType.PLAYER_DIE_DRAWN); - } - } - } - - public void killAvatar(GameSession session, GameEntity entity, PlayerDieType dieType) { - cachedSession.send(new PacketAvatarLifeStateChangeNotify( - cachedSession.getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), - LifeState.LIFE_DEAD, - dieType - )); - cachedSession.send(new PacketLifeStateChangeNotify( - cachedEntity, - LifeState.LIFE_DEAD, - dieType - )); - cachedEntity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); - cachedEntity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(cachedEntity, FightProperty.FIGHT_PROP_CUR_HP)); - entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD)); - session.getPlayer().getScene().removeEntity(entity); - ((EntityAvatar)entity).onDeath(dieType, 0); - } - - private class MotionManagerTick extends TimerTask - { - public void run() { - if (Grasscutter.getConfig().OpenStamina) { - boolean moving = isPlayerMoving(); - if (moving || (getCurrentStamina() < getMaximumStamina())) { - // Grasscutter.getLogger().debug("Player moving: " + moving + ", stamina full: " + (getCurrentStamina() >= getMaximumStamina()) + ", recalculate stamina"); - Consumption consumption = new Consumption(ConsumptionType.None); - - // TODO: refactor these conditions. - if (MotionStatesCategorized.get("CLIMB").contains(currentState)) { - consumption = getClimbConsumption(); - } else if (MotionStatesCategorized.get("SWIM").contains((currentState))) { - consumption = getSwimConsumptions(); - } else if (MotionStatesCategorized.get("RUN").contains(currentState)) { - consumption = getRunWalkDashConsumption(); - } else if (MotionStatesCategorized.get("FLY").contains(currentState)) { - consumption = getFlyConsumption(); - } else if (MotionStatesCategorized.get("STANDBY").contains(currentState)) { - consumption = getStandConsumption(); - } else if (MotionStatesCategorized.get("FIGHT").contains(currentState)) { - consumption = getFightConsumption(); - } - - // delay 2 seconds before start recovering - as official server does. - if (cachedSession != null) { - if (consumption.amount < 0) { - staminaRecoverDelay = 0; - } - if (consumption.amount > 0 && consumption.consumptionType != ConsumptionType.POWERED_FLY) { - if (staminaRecoverDelay < 10) { - staminaRecoverDelay++; - consumption = new Consumption(ConsumptionType.None); - } - } - // Grasscutter.getLogger().debug(getCurrentStamina() + "/" + getMaximumStamina() + "\t" + currentState + "\t" + "isMoving: " + isPlayerMoving() + "\t(" + consumption.consumptionType + "," + consumption.amount + ")"); - updateStamina(cachedSession, consumption.amount); - } - - // tick triggered - handleDrowning(); - } - } - - previousState = currentState; - previousCoordinates = new Position(currentCoordinates.getX(), - currentCoordinates.getY(), currentCoordinates.getZ());; - } - } - - private Consumption getClimbConsumption() { - Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_CLIMB) { - consumption = new Consumption(ConsumptionType.CLIMBING); - if (previousState != MotionState.MOTION_CLIMB && previousState != MotionState.MOTION_CLIMB_JUMP) { - consumption = new Consumption(ConsumptionType.CLIMB_START); - } - if (!isPlayerMoving()) { - consumption = new Consumption(ConsumptionType.None); - } - } - if (currentState == MotionState.MOTION_CLIMB_JUMP) { - if (previousState != MotionState.MOTION_CLIMB_JUMP) { - consumption = new Consumption(ConsumptionType.CLIMB_JUMP); - } - } - return consumption; - } - - private Consumption getSwimConsumptions() { - Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_SWIM_MOVE) { - consumption = new Consumption(ConsumptionType.SWIMMING); - } - if (currentState == MotionState.MOTION_SWIM_DASH) { - consumption = new Consumption(ConsumptionType.SWIM_DASH_START); - if (previousState == MotionState.MOTION_SWIM_DASH) { - consumption = new Consumption(ConsumptionType.SWIM_DASH); - } - } - return consumption; - } - - private Consumption getRunWalkDashConsumption() { - Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_DASH_BEFORE_SHAKE) { - consumption = new Consumption(ConsumptionType.DASH); - if (previousState == MotionState.MOTION_DASH_BEFORE_SHAKE) { - // only charge once - consumption = new Consumption(ConsumptionType.SPRINT); - } - } - if (currentState == MotionState.MOTION_DASH) { - consumption = new Consumption(ConsumptionType.SPRINT); - } - if (currentState == MotionState.MOTION_RUN) { - consumption = new Consumption(ConsumptionType.RUN); - } - if (currentState == MotionState.MOTION_WALK) { - consumption = new Consumption(ConsumptionType.WALK); - } - return consumption; - } - - private Consumption getFlyConsumption() { - Consumption consumption = new Consumption(ConsumptionType.FLY); - HashMap glidingCostReduction = new HashMap<>() {{ - put(212301, 0.8f); // Amber - put(222301, 0.8f); // Venti - }}; - float reduction = 1; - for (EntityAvatar entity: cachedSession.getPlayer().getTeamManager().getActiveTeam()) { - for (int skillId: entity.getAvatar().getProudSkillList()) { - if (glidingCostReduction.containsKey(skillId)) { - reduction = glidingCostReduction.get(skillId); - } - } - } - consumption.amount *= reduction; - - // POWERED_FLY, e.g. wind tunnel - if (currentState == MotionState.MOTION_POWERED_FLY) { - consumption = new Consumption(ConsumptionType.POWERED_FLY); - } - return consumption; - } - - private Consumption getStandConsumption() { - Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_STANDBY) { - consumption = new Consumption(ConsumptionType.STANDBY); - } - if (currentState == MotionState.MOTION_STANDBY_MOVE) { - consumption = new Consumption(ConsumptionType.STANDBY_MOVE); - } - return consumption; - } - - private Consumption getFightConsumption() { - Consumption consumption = new Consumption(ConsumptionType.None); - HashMap fightingCost = new HashMap<>() {{ - put(10013, -1000); // Kamisato Ayaka - put(10413, -1000); // Mona - }}; - if (fightingCost.containsKey(skillCasting)) { - consumption = new Consumption(ConsumptionType.FIGHT, fightingCost.get(skillCasting)); - // only handle once, so reset. - skillCasting = 0; - skillCaster = 0; - } - return consumption; - } - - public void notifySkill(int caster, int skillId) { - skillCaster = caster; - skillCasting = skillId; - } -} - diff --git a/src/main/java/emu/grasscutter/game/managers/MultiplayerManager.java b/src/main/java/emu/grasscutter/game/managers/MultiplayerManager.java index 247b3356d..91566ef20 100644 --- a/src/main/java/emu/grasscutter/game/managers/MultiplayerManager.java +++ b/src/main/java/emu/grasscutter/game/managers/MultiplayerManager.java @@ -27,7 +27,7 @@ public class MultiplayerManager { public void applyEnterMp(Player player, int targetUid) { Player target = getServer().getPlayerByUid(targetUid); if (target == null) { - player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP)); + player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.REASON_PLAYER_CANNOT_ENTER_MP)); return; } @@ -72,12 +72,12 @@ public class MultiplayerManager { // Sanity checks - Dont let the requesting player join if they are already in multiplayer if (requester.getWorld().isMultiplayer()) { - request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP)); + request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.REASON_PLAYER_CANNOT_ENTER_MP)); return; } // Response packet - request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_JUDGE)); + request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.REASON_PLAYER_JUDGE)); // Declined if (!isAgreed) { @@ -93,7 +93,7 @@ public class MultiplayerManager { world.addPlayer(hostPlayer); // Rejoin packet - hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.ENTER_SELF, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos())); + hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.ENTER_TYPE_SELF, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos())); } // Set scene pos and id of requester to the host player's @@ -105,7 +105,7 @@ public class MultiplayerManager { hostPlayer.getWorld().addPlayer(requester); // Packet - requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.ENTER_OTHER, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos())); + requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.ENTER_TYPE_OTHER, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos())); } public boolean leaveCoop(Player player) { @@ -126,7 +126,7 @@ public class MultiplayerManager { world.addPlayer(player); // Packet - player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_SELF, EnterReason.TeamBack, player.getScene().getId(), player.getPos())); + player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_TYPE_SELF, EnterReason.TeamBack, player.getScene().getId(), player.getPos())); return true; } @@ -153,7 +153,7 @@ public class MultiplayerManager { World world = new World(victim); world.addPlayer(victim); - victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos())); + victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_TYPE_SELF, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos())); return true; } } diff --git a/src/main/java/emu/grasscutter/game/managers/SotSManager.java b/src/main/java/emu/grasscutter/game/managers/SotSManager.java new file mode 100644 index 000000000..b80058142 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/SotSManager.java @@ -0,0 +1,192 @@ +package emu.grasscutter.game.managers; + +import ch.qos.logback.classic.Logger; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; + +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +// Statue of the Seven Manager +public class SotSManager { + + // NOTE: Spring volume balance *1 = fight prop HP *100 + + private final Player player; + private final Logger logger = Grasscutter.getLogger(); + private Timer autoRecoverTimer; + private final boolean enablePriorityHealing = false; + + public final static int GlobalMaximumSpringVolume = 8500000; + + public SotSManager(Player player) { + this.player = player; + } + + public boolean getIsAutoRecoveryEnabled() { + return player.getProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE) == 1; + } + + public void setIsAutoRecoveryEnabled(boolean enabled) { + player.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, enabled ? 1 : 0); + player.save(); + } + + public int getAutoRecoveryPercentage() { + return player.getProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT); + } + + public void setAutoRecoveryPercentage(int percentage) { + player.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, percentage); + player.save(); + } + + public long getLastUsed() { + return player.getSpringLastUsed(); + } + + public void setLastUsed() { + player.setSpringLastUsed(System.currentTimeMillis() / 1000); + player.save(); + } + + public int getMaxVolume() { + return player.getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); + } + + public void setMaxVolume(int volume) { + player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, volume); + player.save(); + } + + public int getCurrentVolume() { + return player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); + } + + public void setCurrentVolume(int volume) { + player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, volume); + setLastUsed(); + player.save(); + } + + public void handleEnterTransPointRegionNotify() { + logger.trace("Player entered statue region"); + autoRevive(); + if (autoRecoverTimer == null) { + autoRecoverTimer = new Timer(); + autoRecoverTimer.schedule(new AutoRecoverTimerTick(), 2500, 15000); + } + } + + public void handleExitTransPointRegionNotify() { + logger.trace("Player left statue region"); + if (autoRecoverTimer != null) { + autoRecoverTimer.cancel(); + autoRecoverTimer = null; + } + } + + // autoRevive automatically revives all team members. + public void autoRevive() { + player.getTeamManager().getActiveTeam().forEach(entity -> { + boolean isAlive = entity.isAlive(); + if (isAlive) { + return; + } + logger.trace("Reviving avatar " + entity.getAvatar().getAvatarData().getName()); + player.getTeamManager().reviveAvatar(entity.getAvatar()); + player.getTeamManager().healAvatar(entity.getAvatar(), 30, 0); + }); + } + + private class AutoRecoverTimerTick extends TimerTask { + // autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level. + public void run() { + refillSpringVolume(); + + logger.trace("isAutoRecoveryEnabled: " + getIsAutoRecoveryEnabled() + "\tautoRecoverPercentage: " + getAutoRecoveryPercentage()); + + if (getIsAutoRecoveryEnabled()) { + List activeTeam = player.getTeamManager().getActiveTeam(); + // When the statue does not have enough remaining volume: + // Enhanced experience: Enable priority healing + // The current active character will get healed first, then sequential. + // Vanilla experience: Disable priority healing + // Sequential healing based on character index. + int priorityIndex = enablePriorityHealing ? player.getTeamManager().getCurrentCharacterIndex() : -1; + if (priorityIndex >= 0) { + checkAndHealAvatar(activeTeam.get(priorityIndex)); + } + for (int i = 0; i < activeTeam.size(); i++) { + if (i != priorityIndex) { + checkAndHealAvatar(activeTeam.get(i)); + } + } + } + } + } + + public void checkAndHealAvatar(EntityAvatar entity) { + int maxHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * 100); + int currentHP = (int) (entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) * 100); + if (currentHP == maxHP) { + return; + } + int targetHP = maxHP * getAutoRecoveryPercentage() / 100; + + if (targetHP > currentHP) { + int needHP = targetHP - currentHP; + int currentVolume = getCurrentVolume(); + if (currentVolume >= needHP) { + // sufficient + setCurrentVolume(currentVolume - needHP); + } else { + // insufficient balance + needHP = currentVolume; + setCurrentVolume(0); + } + if (needHP > 0) { + logger.trace("Healing avatar " + entity.getAvatar().getAvatarData().getName() + " +" + needHP); + player.getTeamManager().healAvatar(entity.getAvatar(), 0, needHP); + player.getSession().send(new PacketEntityFightPropChangeReasonNotify(entity, FightProperty.FIGHT_PROP_CUR_HP, + ((float) needHP / 100), List.of(3), PropChangeReason.PROP_CHANGE_REASON_STATUE_RECOVER, + ChangeHpReason.CHANGE_HP_REASON_CHANGE_HP_ADD_STATUE)); + player.getSession().send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + + } + } + } + + public void refillSpringVolume() { + // Temporary: Max spring volume depends on level of the statues in Mondstadt and Liyue. Override until we have statue level. + // TODO: remove + // https://genshin-impact.fandom.com/wiki/Statue_of_The_Seven#:~:text=region%20of%20Inazuma.-,Statue%20Levels,-Upon%20first%20unlocking + setMaxVolume(8500000); + // Temporary: Auto enable 100% statue recovery until we can adjust statue settings in game + // TODO: remove + setAutoRecoveryPercentage(100); + setIsAutoRecoveryEnabled(true); + + int maxVolume = getMaxVolume(); + int currentVolume = getCurrentVolume(); + if (currentVolume < maxVolume) { + long now = System.currentTimeMillis() / 1000; + int secondsSinceLastUsed = (int) (now - getLastUsed()); + // 15s = 1% max volume + int volumeRefilled = secondsSinceLastUsed * maxVolume / 15 / 100; + logger.trace("Statue has refilled HP volume: " + volumeRefilled); + currentVolume = Math.min(currentVolume + volumeRefilled, maxVolume); + logger.trace("Statue remaining HP volume: " + currentVolume); + setCurrentVolume(currentVolume); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java b/src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java deleted file mode 100644 index 0bfdf9454..000000000 --- a/src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java +++ /dev/null @@ -1,175 +0,0 @@ -package emu.grasscutter.game.managers.SotSManager; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.managers.MovementManager.MovementManager; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.World; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass; -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; - -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -// Statue of the Seven Manager -public class SotSManager { - - // NOTE: Spring volume balance *1 = fight prop HP *100 - - private final Player player; - private Timer autoRecoverTimer; - - public SotSManager(Player player) { - this.player = player; - } - - public boolean getIsAutoRecoveryEnabled() { - return player.getProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE) == 1; - } - - public void setIsAutoRecoveryEnabled(boolean enabled) { - player.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, enabled ? 1 : 0); - } - - public int getAutoRecoveryPercentage() { - return player.getProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT); - } - - public void setAutoRecoveryPercentage(int percentage) { - player.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, percentage); - } - - // autoRevive automatically revives all team members. - public void autoRevive(GameSession session) { - player.getTeamManager().getActiveTeam().forEach(entity -> { - boolean isAlive = entity.isAlive(); - float currentHP = entity.getAvatar().getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - float maxHP = entity.getAvatar().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); -// Grasscutter.getLogger().debug("" + entity.getAvatar().getAvatarData().getName() + "\t" + currentHP + "/" + maxHP + "\t" + (isAlive ? "ALIVE":"DEAD")); - float newHP = (float)(maxHP * 0.3); - if (currentHP < newHP) { - updateAvatarCurHP(session, entity, newHP); - } - if (!isAlive) { - entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); - } - }); - } - - public void scheduleAutoRecover(GameSession session) { - if (autoRecoverTimer == null) { - autoRecoverTimer = new Timer(); - autoRecoverTimer.schedule(new AutoRecoverTimerTick(session), 2500); - } - } - - public void cancelAutoRecover() { - if (autoRecoverTimer != null) { - autoRecoverTimer.cancel(); - autoRecoverTimer = null; - } - } - - private class AutoRecoverTimerTick extends TimerTask - { - private GameSession session; - - public AutoRecoverTimerTick(GameSession session) { - this.session = session; - } - public void run() { - autoRecover(session); - cancelAutoRecover(); - } - } - - public void refillSpringVolume() { - // TODO: max spring volume depends on level of the statues in Mondstadt and Liyue. - // https://genshin-impact.fandom.com/wiki/Statue_of_The_Seven#:~:text=region%20of%20Inazuma.-,Statue%20Levels,-Upon%20first%20unlocking - player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, 8500000); - - long now = System.currentTimeMillis() / 1000; - long secondsSinceLastUsed = now - player.getSpringLastUsed(); - float percentageRefilled = (float)secondsSinceLastUsed / 15 / 100; // 15s = 1% max volume - int maxVolume = player.getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); - int currentVolume = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); - if (currentVolume < maxVolume) { - int volumeRefilled = (int)(percentageRefilled * maxVolume); - int newVolume = currentVolume + volumeRefilled; - if (currentVolume + volumeRefilled > maxVolume) { - newVolume = maxVolume; - } - player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, newVolume); - } - player.setSpringLastUsed(now); - player.save(); - } - - // autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level. - public void autoRecover(GameSession session) { - // TODO: In MP, respect SotS settings from the HOST. - boolean isAutoRecoveryEnabled = getIsAutoRecoveryEnabled(); - int autoRecoverPercentage = getAutoRecoveryPercentage(); - Grasscutter.getLogger().debug("isAutoRecoveryEnabled: " + isAutoRecoveryEnabled + "\tautoRecoverPercentage: " + autoRecoverPercentage); - - if (isAutoRecoveryEnabled) { - player.getTeamManager().getActiveTeam().forEach(entity -> { - float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - if (currentHP == maxHP) { - return; - } - float targetHP = maxHP * autoRecoverPercentage / 100; - - if (targetHP > currentHP) { - float needHP = targetHP - currentHP; - float needSV = needHP * 100; // convert HP needed to Spring Volume needed - - int sotsSVBalance = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); - if (sotsSVBalance >= needSV) { - // sufficient - sotsSVBalance -= needSV; - } else { - // insufficient balance - needSV = sotsSVBalance; - sotsSVBalance = 0; - } - player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, sotsSVBalance); - player.setSpringLastUsed(System.currentTimeMillis() / 1000); - - float newHP = currentHP + needSV / 100; // convert SV to HP - - updateAvatarCurHP(session, entity, newHP); - } - }); - } - } - - private void updateAvatarCurHP(GameSession session, EntityAvatar entity, float newHP) { - // TODO: Figure out why client shows current HP instead of added HP. - // Say an avatar had 12000 and now has 14000, it should show "2000". - // The client always show "+14000" which is incorrect. - entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); - session.send(new PacketEntityFightPropChangeReasonNotify(entity, FightProperty.FIGHT_PROP_CUR_HP, - newHP, List.of(3), PropChangeReasonOuterClass.PropChangeReason.PROP_CHANGE_STATUE_RECOVER, - ChangeHpReasonOuterClass.ChangeHpReason.ChangeHpAddStatue)); - session.send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); - - Avatar avatar = entity.getAvatar(); - avatar.setCurrentHp(newHP); - session.send(new PacketAvatarFightPropUpdateNotify(avatar, FightProperty.FIGHT_PROP_CUR_HP)); - player.save(); - } - - -} diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/AfterUpdateStaminaListener.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/AfterUpdateStaminaListener.java new file mode 100644 index 000000000..11a5c9178 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/AfterUpdateStaminaListener.java @@ -0,0 +1,12 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public interface AfterUpdateStaminaListener { + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. + * This gives listeners a chance to intercept this update. + * + * @param reason Why updating stamina. + * @param newStamina New Stamina value. + */ + void onAfterUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); +} diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/BeforeUpdateStaminaListener.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/BeforeUpdateStaminaListener.java new file mode 100644 index 000000000..39075f35b --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/BeforeUpdateStaminaListener.java @@ -0,0 +1,20 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public interface BeforeUpdateStaminaListener { + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. + * This gives listeners a chance to intercept this update. + * @param reason Why updating stamina. + * @param newStamina New ABSOLUTE stamina value. + * @return true if you want to cancel this update, otherwise false. + */ + int onBeforeUpdateStamina(String reason, int newStamina, boolean isCharacterStamina); + /** + * onBeforeUpdateStamina() will be called before StaminaManager attempt to update the player's current stamina. + * This gives listeners a chance to intercept this update. + * @param reason Why updating stamina. + * @param consumption ConsumptionType and RELATIVE stamina change amount. + * @return true if you want to cancel this update, otherwise false. + */ + Consumption onBeforeUpdateStamina(String reason, Consumption consumption, boolean isCharacterStamina); +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java new file mode 100644 index 000000000..a6185f063 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public class Consumption { + public ConsumptionType type = ConsumptionType.None; + public int amount = 0; + + public Consumption(ConsumptionType type, int amount) { + this.type = type; + this.amount = amount; + } + + public Consumption(ConsumptionType type) { + this(type, type.amount); + } + + public Consumption() { + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java new file mode 100644 index 000000000..506bf1728 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java @@ -0,0 +1,37 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public enum ConsumptionType { + None(0), + + // consume + CLIMBING(-150), + CLIMB_START(-500), + CLIMB_JUMP(-2500), + DASH(-360), + FIGHT(0), // See StaminaManager.getFightConsumption() + FLY(-60), + // Slow swimming is handled per movement, not per second. + // Arm movement frequency depends on gender/age/height. + // TODO: Instead of cost -80 per tick, find a proper way to calculate cost. + SKIFF_DASH(-204), + SPRINT(-1800), + SWIM_DASH_START(-2000), + SWIM_DASH(-204), // -10.2 per second, 5Hz = -204 each tick + SWIMMING(-80), + TALENT_DASH(-300), // -1500 per second, 5Hz = -300 each tick + TALENT_DASH_START(-1000), + + // restore + POWERED_FLY(500), + POWERED_SKIFF(500), + RUN(500), + SKIFF(500), + STANDBY(500), + WALK(500); + + public final int amount; + + ConsumptionType(int amount) { + this.amount = amount; + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/README.md b/src/main/java/emu/grasscutter/game/managers/StaminaManager/README.md new file mode 100644 index 000000000..39a4e7988 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/README.md @@ -0,0 +1,73 @@ +# Stamina Manager + +--- +## UpdateStamina +```java +// will use consumption.consumptionType as reason +public int updateStaminaRelative(GameSession session, Consumption consumption); +``` +```java +public int updateStaminaAbsolute(GameSession session, String reason, int newStamina) +``` + +--- +## Pause and Resume +```java +public void startSustainedStaminaHandler() +``` +```java +public void stopSustainedStaminaHandler() +``` + + +--- +## Stamina change listeners and intercepting +### BeforeUpdateStaminaListener +```java + +import emu.grasscutter.game.managers.StaminaManager.BeforeUpdateStaminaListener; + +// Listener sample: plugin disable CLIMB_JUMP stamina cost. +private class MyClass implements BeforeUpdateStaminaListener { + // Make your class implement the listener, and pass in your class as a listener. + + public MyClass() { + getStaminaManager().registerBeforeUpdateStaminaListener("myClass", this); + } + + @Override + public boolean onBeforeUpdateStamina(String reason, int newStamina) { + // do not intercept this update + return false; + } + + @Override + public boolean onBeforeUpdateStamina(String reason, Consumption consumption) { + // Try to intercept if this update is CLIMB_JUMP + if (consumption.consumptionType == ConsumptionType.CLIMB_JUMP) { + return true; + } + // If it is not CLIMB_JUMP, do not intercept. + return false; + } +} +``` +### AfterUpdateStaminaListener +```java + +import emu.grasscutter.game.managers.StaminaManager.AfterUpdateStaminaListener; + +// Listener sample: plugin listens for changes already made. +private class MyClass implements AfterUpdateStaminaListener { + // Make your class implement the listener, and pass in your class as a listener. + + public MyClass() { + registerAfterUpdateStaminaListener("myClass", this); + } + + @Override + public void onAfterUpdateStamina(String reason, int newStamina) { + // ... + } +} +``` \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java new file mode 100644 index 000000000..4d69e7a99 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java @@ -0,0 +1,717 @@ +package emu.grasscutter.game.managers.StaminaManager; + +import ch.qos.logback.classic.Logger; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.commands.NoStaminaCommand; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.props.WeaponType; +import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; +import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass.VehicleInteractType; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.*; +import emu.grasscutter.utils.Position; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +import static emu.grasscutter.Configuration.GAME_OPTIONS; + +public class StaminaManager { + + // TODO: Skiff state detection? + private final Player player; + private static final HashMap> MotionStatesCategorized = new HashMap<>() {{ + put("CLIMB", new HashSet<>(List.of( + MotionState.MOTION_STATE_CLIMB, // sustained, when not moving no cost no recover + MotionState.MOTION_STATE_STANDBY_TO_CLIMB // NOT OBSERVED, see MOTION_JUMP_UP_WALL_FOR_STANDBY + ))); + put("DASH", new HashSet<>(List.of( + MotionState.MOTION_STATE_DANGER_DASH, // sustained + MotionState.MOTION_STATE_DASH // sustained + ))); + put("FLY", new HashSet<>(List.of( + MotionState.MOTION_STATE_FLY, // sustained + MotionState.MOTION_STATE_FLY_FAST, // sustained + MotionState.MOTION_STATE_FLY_SLOW, // sustained + MotionState.MOTION_STATE_POWERED_FLY // sustained, recover + ))); + put("RUN", new HashSet<>(List.of( + MotionState.MOTION_STATE_DANGER_RUN, // sustained, recover + MotionState.MOTION_STATE_RUN // sustained, recover + ))); + put("SKIFF", new HashSet<>(List.of( + MotionState.MOTION_STATE_SKIFF_BOARDING, // NOT OBSERVED even when boarding + MotionState.MOTION_STATE_SKIFF_DASH, // sustained, observed with waverider entity ID. + MotionState.MOTION_STATE_SKIFF_NORMAL, // sustained, OBSERVED when both normal and dashing + MotionState.MOTION_STATE_SKIFF_POWERED_DASH // sustained, recover + ))); + put("STANDBY", new HashSet<>(List.of( + MotionState.MOTION_STATE_DANGER_STANDBY_MOVE, // sustained, recover + MotionState.MOTION_STATE_DANGER_STANDBY, // sustained, recover + MotionState.MOTION_STATE_LADDER_TO_STANDBY, // NOT OBSERVED + MotionState.MOTION_STATE_STANDBY_MOVE, // sustained, recover + MotionState.MOTION_STATE_STANDBY // sustained, recover + ))); + put("SWIM", new HashSet<>(List.of( + MotionState.MOTION_STATE_SWIM_IDLE, // sustained + MotionState.MOTION_STATE_SWIM_DASH, // immediate and sustained + MotionState.MOTION_STATE_SWIM_JUMP, // NOT OBSERVED + MotionState.MOTION_STATE_SWIM_MOVE // sustained + ))); + put("WALK", new HashSet<>(List.of( + MotionState.MOTION_STATE_DANGER_WALK, // sustained, recover + MotionState.MOTION_STATE_WALK // sustained, recover + ))); + put("OTHER", new HashSet<>(List.of( + MotionState.MOTION_STATE_CLIMB_JUMP, // cost only once if repeated without switching state + MotionState.MOTION_STATE_DASH_BEFORE_SHAKE, // immediate one time sprint charge. + MotionState.MOTION_STATE_FIGHT, // immediate, if sustained then subsequent will be MOTION_NOTIFY + MotionState.MOTION_STATE_JUMP_UP_WALL_FOR_STANDBY, // immediate, observed when RUN/WALK->CLIMB + MotionState.MOTION_STATE_NOTIFY, // can be either cost or recover - check previous state and check skill casting + MotionState.MOTION_STATE_SIT_IDLE, // sustained, recover + MotionState.MOTION_STATE_JUMP // recover + ))); + put("NOCOST_NORECOVER", new HashSet<>(List.of( + MotionState.MOTION_STATE_LADDER_SLIP, // NOT OBSERVED + MotionState.MOTION_STATE_SLIP, // sustained, no cost no recover + MotionState.MOTION_STATE_FLY_IDLE // NOT OBSERVED + ))); + put("IGNORE", new HashSet<>(List.of( + // these states have no impact on stamina + MotionState.MOTION_STATE_CROUCH_IDLE, + MotionState.MOTION_STATE_CROUCH_MOVE, + MotionState.MOTION_STATE_CROUCH_ROLL, + MotionState.MOTION_STATE_DESTROY_VEHICLE, + MotionState.MOTION_STATE_FALL_ON_GROUND, + MotionState.MOTION_STATE_FOLLOW_ROUTE, + MotionState.MOTION_STATE_FORCE_SET_POS, + MotionState.MOTION_STATE_GO_UPSTAIRS, + MotionState.MOTION_STATE_JUMP_OFF_WALL, + MotionState.MOTION_STATE_LADDER_IDLE, + MotionState.MOTION_STATE_LADDER_MOVE, + MotionState.MOTION_STATE_LAND_SPEED, + MotionState.MOTION_STATE_MOVE_FAIL_ACK, + MotionState.MOTION_STATE_NONE, + MotionState.MOTION_STATE_NUM, + MotionState.MOTION_STATE_QUEST_FORCE_DRAG, + MotionState.MOTION_STATE_RESET, + MotionState.MOTION_STATE_STANDBY_TO_LADDER, + MotionState.MOTION_STATE_WATERFALL + ))); + }}; + + private final Logger logger = Grasscutter.getLogger(); + public final static int GlobalCharacterMaximumStamina = 24000; + public final static int GlobalVehicleMaxStamina = 24000; + private Position currentCoordinates = new Position(0, 0, 0); + private Position previousCoordinates = new Position(0, 0, 0); + private MotionState currentState = MotionState.MOTION_STATE_STANDBY; + private MotionState previousState = MotionState.MOTION_STATE_STANDBY; + private Timer sustainedStaminaHandlerTimer; + private GameSession cachedSession = null; + private GameEntity cachedEntity = null; + private int staminaRecoverDelay = 0; + private final HashMap beforeUpdateStaminaListeners = new HashMap<>(); + private final HashMap afterUpdateStaminaListeners = new HashMap<>(); + private int lastSkillId = 0; + private int lastSkillCasterId = 0; + private boolean lastSkillFirstTick = true; + private int vehicleId = -1; + private int vehicleStamina = GlobalVehicleMaxStamina; + private static final HashSet TalentMovements = new HashSet<>(List.of( + 10013, 10413 + )); + private static final HashMap ClimbFoodReductionMap = new HashMap<>() {{ + // TODO: get real food id + put(0, 0.8f); // Sample food + }}; + private static final HashMap DashFoodReductionMap = new HashMap<>() {{ + // TODO: get real food id + put(0, 0.8f); // Sample food + }}; + private static final HashMap FlyFoodReductionMap = new HashMap<>() {{ + // TODO: get real food id + put(0, 0.8f); // Sample food + }}; + private static final HashMap SwimFoodReductionMap = new HashMap<>() {{ + // TODO: get real food id + put(0, 0.8f); // Sample food + }}; + private static final HashMap ClimbTalentReductionMap = new HashMap<>() {{ + put(262301, 0.8f); + }}; + private static final HashMap FlyTalentReductionMap = new HashMap<>() {{ + put(212301, 0.8f); + put(222301, 0.8f); + }}; + private static final HashMap SwimTalentReductionMap = new HashMap<>() {{ + put(242301, 0.8f); + put(542301, 0.8f); + }}; + + public static void initialize() { + // TODO: Initialize foods etc. + } + + public StaminaManager(Player player) { + this.player = player; + } + + // Accessors + + public void setSkillCast(int skillId, int skillCasterId) { + lastSkillFirstTick = true; + lastSkillId = skillId; + lastSkillCasterId = skillCasterId; + } + + public int getMaxCharacterStamina() { + return player.getProperty(PlayerProperty.PROP_MAX_STAMINA); + } + + public int getCurrentCharacterStamina() { + return player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); + } + + public int getMaxVehicleStamina() { + return GlobalVehicleMaxStamina; + } + + public int getCurrentVehicleStamina() { + return vehicleStamina; + } + + public boolean registerBeforeUpdateStaminaListener(String listenerName, BeforeUpdateStaminaListener listener) { + if (beforeUpdateStaminaListeners.containsKey(listenerName)) { + return false; + } + beforeUpdateStaminaListeners.put(listenerName, listener); + return true; + } + + public boolean unregisterBeforeUpdateStaminaListener(String listenerName) { + if (!beforeUpdateStaminaListeners.containsKey(listenerName)) { + return false; + } + beforeUpdateStaminaListeners.remove(listenerName); + return true; + } + + public boolean registerAfterUpdateStaminaListener(String listenerName, AfterUpdateStaminaListener listener) { + if (afterUpdateStaminaListeners.containsKey(listenerName)) { + return false; + } + afterUpdateStaminaListeners.put(listenerName, listener); + return true; + } + + public boolean unregisterAfterUpdateStaminaListener(String listenerName) { + if (!afterUpdateStaminaListeners.containsKey(listenerName)) { + return false; + } + afterUpdateStaminaListeners.remove(listenerName); + return true; + } + + private boolean isPlayerMoving() { + float diffX = currentCoordinates.getX() - previousCoordinates.getX(); + float diffY = currentCoordinates.getY() - previousCoordinates.getY(); + float diffZ = currentCoordinates.getZ() - previousCoordinates.getZ(); + logger.trace("isPlayerMoving: " + previousCoordinates + ", " + currentCoordinates + + ", " + diffX + ", " + diffY + ", " + diffZ); + return Math.abs(diffX) > 0.3 || Math.abs(diffY) > 0.2 || Math.abs(diffZ) > 0.3; + } + + public int updateStaminaRelative(GameSession session, Consumption consumption, boolean isCharacterStamina) { + int currentStamina = isCharacterStamina ? getCurrentCharacterStamina() : getCurrentVehicleStamina(); + if (consumption.amount == 0) { + return currentStamina; + } + // notify will update + for (Map.Entry listener : beforeUpdateStaminaListeners.entrySet()) { + Consumption overriddenConsumption = listener.getValue().onBeforeUpdateStamina(consumption.type.toString(), consumption, isCharacterStamina); + if ((overriddenConsumption.type != consumption.type) && (overriddenConsumption.amount != consumption.amount)) { + logger.debug("Stamina update relative(" + + consumption.type.toString() + ", " + consumption.amount + ") overridden to relative(" + + consumption.type.toString() + ", " + consumption.amount + ") by: " + listener.getKey()); + return currentStamina; + } + } + int maxStamina = isCharacterStamina ? getMaxCharacterStamina() : getMaxVehicleStamina(); + logger.trace((isCharacterStamina ? "C " : "V ") + currentStamina + "/" + maxStamina + "\t" + currentState + "\t" + + (isPlayerMoving() ? "moving" : " ") + "\t(" + consumption.type + "," + + consumption.amount + ")"); + int newStamina = currentStamina + consumption.amount; + if (newStamina < 0) { + newStamina = 0; + } else if (newStamina > maxStamina) { + newStamina = maxStamina; + } + return setStamina(session, consumption.type.toString(), newStamina, isCharacterStamina); + } + + public int updateStaminaAbsolute(GameSession session, String reason, int newStamina, boolean isCharacterStamina) { + int currentStamina = isCharacterStamina ? getCurrentCharacterStamina() : getCurrentVehicleStamina(); + // notify will update + for (Map.Entry listener : beforeUpdateStaminaListeners.entrySet()) { + int overriddenNewStamina = listener.getValue().onBeforeUpdateStamina(reason, newStamina, isCharacterStamina); + if (overriddenNewStamina != newStamina) { + logger.debug("Stamina update absolute(" + + reason + ", " + newStamina + ") overridden to absolute(" + + reason + ", " + newStamina + ") by: " + listener.getKey()); + return currentStamina; + } + } + int maxStamina = isCharacterStamina ? getMaxCharacterStamina() : getMaxVehicleStamina(); + if (newStamina < 0) { + newStamina = 0; + } else if (newStamina > maxStamina) { + newStamina = maxStamina; + } + return setStamina(session, reason, newStamina, isCharacterStamina); + } + + // Returns new stamina and sends PlayerPropNotify or VehicleStaminaNotify + public int setStamina(GameSession session, String reason, int newStamina, boolean isCharacterStamina) { + // Target Player + if (!GAME_OPTIONS.staminaUsage || session.getPlayer().getStamina()) { + newStamina = getMaxCharacterStamina(); + } + + // set stamina if is character stamina + if (isCharacterStamina) { + player.setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, newStamina); + session.send(new PacketPlayerPropNotify(player, PlayerProperty.PROP_CUR_PERSIST_STAMINA)); + } else { + vehicleStamina = newStamina; + session.send(new PacketVehicleStaminaNotify(vehicleId, ((float) newStamina) / 100)); + } + // notify updated + for (Map.Entry listener : afterUpdateStaminaListeners.entrySet()) { + listener.getValue().onAfterUpdateStamina(reason, newStamina, isCharacterStamina); + } + return newStamina; + } + + // Kills avatar, removes entity and sends notification. + // TODO: Probably move this to Avatar class? since other components may also need to kill avatar. + public void killAvatar(GameSession session, GameEntity entity, PlayerDieType dieType) { + session.send(new PacketAvatarLifeStateChangeNotify(player.getTeamManager().getCurrentAvatarEntity().getAvatar(), + LifeState.LIFE_DEAD, dieType)); + session.send(new PacketLifeStateChangeNotify(entity, LifeState.LIFE_DEAD, dieType)); + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); + entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD)); + player.getScene().removeEntity(entity); + ((EntityAvatar) entity).onDeath(dieType, 0); + } + + public void startSustainedStaminaHandler() { + if (!player.isPaused() && sustainedStaminaHandlerTimer == null) { + sustainedStaminaHandlerTimer = new Timer(); + sustainedStaminaHandlerTimer.scheduleAtFixedRate(new SustainedStaminaHandler(), 0, 200); + logger.debug("[MovementManager] SustainedStaminaHandlerTimer started"); + } + } + + public void stopSustainedStaminaHandler() { + if (sustainedStaminaHandlerTimer != null) { + sustainedStaminaHandlerTimer.cancel(); + sustainedStaminaHandlerTimer = null; + logger.debug("[MovementManager] SustainedStaminaHandlerTimer stopped"); + } + } + + // Handlers + + // External trigger handler + + public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { + // Ignore if skill not cast by not current active avatar + if (casterId != player.getTeamManager().getCurrentAvatarEntity().getId()) { + return; + } + setSkillCast(skillId, casterId); + // Handle immediate stamina cost + Avatar currentAvatar = player.getTeamManager().getCurrentAvatarEntity().getAvatar(); + if (currentAvatar.getAvatarData().getWeaponType() == WeaponType.WEAPON_CLAYMORE) { + // Exclude claymore as their stamina cost starts when MixinStaminaCost gets in + return; + } + // TODO: Differentiate normal attacks from charged attacks and exclude + // TODO: Temporary: Exclude non-claymore attacks for now + /* + if (BowAvatars.contains(currentAvatarId) + || SwordAvatars.contains(currentAvatarId) + || PolearmAvatars.contains(currentAvatarId) + || CatalystAvatars.contains(currentAvatarId) + ) { + return; + } + */ + //handleImmediateStamina(session, skillId); + } + + public void handleMixinCostStamina(boolean isSwim) { + // Talent moving and claymore avatar charged attack duration + // logger.trace("abilityMixinCostStamina: isSwim: " + isSwim + "\tlastSkill: " + lastSkillId); + if (lastSkillCasterId == player.getTeamManager().getCurrentAvatarEntity().getId()) { + handleImmediateStamina(cachedSession, lastSkillId); + } + } + + public void handleCombatInvocationsNotify(@NotNull GameSession session, @NotNull EntityMoveInfo moveInfo, @NotNull GameEntity entity) { + // cache info for later use in SustainedStaminaHandler tick + cachedSession = session; + cachedEntity = entity; + MotionInfo motionInfo = moveInfo.getMotionInfo(); + MotionState motionState = motionInfo.getState(); + int notifyEntityId = entity.getId(); + int currentAvatarEntityId = session.getPlayer().getTeamManager().getCurrentAvatarEntity().getId(); + if (notifyEntityId != currentAvatarEntityId && notifyEntityId != vehicleId) { + return; + } + currentState = motionState; + // logger.trace(currentState + "\t" + (notifyEntityId == currentAvatarEntityId ? "character" : "vehicle")); + Vector posVector = motionInfo.getPos(); + Position newPos = new Position(posVector.getX(), posVector.getY(), posVector.getZ()); + if (newPos.getX() != 0 && newPos.getY() != 0 && newPos.getZ() != 0) { + currentCoordinates = newPos; + } + startSustainedStaminaHandler(); + handleImmediateStamina(session, motionState); + } + + public void handleVehicleInteractReq(GameSession session, int vehicleId, VehicleInteractType vehicleInteractType) { + if (vehicleInteractType == VehicleInteractType.VEHICLE_INTERACT_TYPE_IN) { + this.vehicleId = vehicleId; + // Reset character stamina here to prevent falling into water immediately on ejection if char stamina is + // close to empty when boarding. + updateStaminaAbsolute(session, "board vehicle", getMaxCharacterStamina(), true); + updateStaminaAbsolute(session, "board vehicle", getMaxVehicleStamina(), false); + } else { + this.vehicleId = -1; + } + } + + // Internal handler + + private void handleImmediateStamina(GameSession session, @NotNull MotionState motionState) { + switch (motionState) { + case MOTION_STATE_CLIMB: + if (currentState != MotionState.MOTION_STATE_CLIMB) { + updateStaminaRelative(session, new Consumption(ConsumptionType.CLIMB_START), true); + } + break; + case MOTION_STATE_DASH_BEFORE_SHAKE: + if (previousState != MotionState.MOTION_STATE_DASH_BEFORE_SHAKE) { + updateStaminaRelative(session, new Consumption(ConsumptionType.SPRINT), true); + } + break; + case MOTION_STATE_CLIMB_JUMP: + if (previousState != MotionState.MOTION_STATE_CLIMB_JUMP) { + updateStaminaRelative(session, new Consumption(ConsumptionType.CLIMB_JUMP), true); + } + break; + case MOTION_STATE_SWIM_DASH: + if (previousState != MotionState.MOTION_STATE_SWIM_DASH) { + updateStaminaRelative(session, new Consumption(ConsumptionType.SWIM_DASH_START), true); + } + break; + } + } + + private void handleImmediateStamina(GameSession session, int skillId) { + Consumption consumption = getFightConsumption(skillId); + updateStaminaRelative(session, consumption, true); + } + + private class SustainedStaminaHandler extends TimerTask { + public void run() { + boolean moving = isPlayerMoving(); + int currentCharacterStamina = getCurrentCharacterStamina(); + int maxCharacterStamina = getMaxCharacterStamina(); + int currentVehicleStamina = getCurrentVehicleStamina(); + int maxVehicleStamina = getMaxVehicleStamina(); + if (moving || (currentCharacterStamina < maxCharacterStamina) || (currentVehicleStamina < maxVehicleStamina)) { + logger.trace("Player moving: " + moving + ", stamina full: " + + (currentCharacterStamina >= maxCharacterStamina) + ", recalculate stamina"); + boolean isCharacterStamina = true; + Consumption consumption; + if (MotionStatesCategorized.get("CLIMB").contains(currentState)) { + consumption = getClimbConsumption(); + } else if (MotionStatesCategorized.get("DASH").contains(currentState)) { + consumption = getDashConsumption(); + } else if (MotionStatesCategorized.get("FLY").contains(currentState)) { + consumption = getFlyConsumption(); + } else if (MotionStatesCategorized.get("RUN").contains(currentState)) { + consumption = new Consumption(ConsumptionType.RUN); + } else if (MotionStatesCategorized.get("SKIFF").contains(currentState)) { + consumption = getSkiffConsumption(); + isCharacterStamina = false; + } else if (MotionStatesCategorized.get("STANDBY").contains(currentState)) { + consumption = new Consumption(ConsumptionType.STANDBY); + } else if (MotionStatesCategorized.get("SWIM").contains(currentState)) { + consumption = getSwimConsumptions(); + } else if (MotionStatesCategorized.get("WALK").contains(currentState)) { + consumption = new Consumption(ConsumptionType.WALK); + } else if (MotionStatesCategorized.get("NOCOST_NORECOVER").contains(currentState)) { + consumption = new Consumption(); + } else if (MotionStatesCategorized.get("OTHER").contains(currentState)) { + consumption = getOtherConsumptions(); + } else { // ignore + return; + } + + if (consumption.amount < 0 && isCharacterStamina) { + // Do not apply reduction factor when recovering stamina + if (player.getTeamManager().getTeamResonances().contains(10301)) { + consumption.amount *= 0.85f; + } + } + // Delay 1 seconds before starts recovering stamina + if (consumption.amount != 0 && cachedSession != null) { + if (consumption.amount < 0) { + staminaRecoverDelay = 0; + } + if (consumption.amount > 0 + && consumption.type != ConsumptionType.POWERED_FLY + && consumption.type != ConsumptionType.POWERED_SKIFF) { + // For POWERED_* recover immediately - things like Amber's gliding exam and skiff challenges may require this. + if (staminaRecoverDelay < 5) { + // For others recover after 1 seconds (5 ticks) - as official server does. + staminaRecoverDelay++; + consumption.amount = 0; + logger.trace("Delaying recovery: " + staminaRecoverDelay); + } + } + updateStaminaRelative(cachedSession, consumption, isCharacterStamina); + } + } + previousState = currentState; + previousCoordinates = new Position( + currentCoordinates.getX(), + currentCoordinates.getY(), + currentCoordinates.getZ() + ); + } + } + + private void handleDrowning() { + // TODO: fix drowning waverider entity + int stamina = getCurrentCharacterStamina(); + if (stamina < 10) { + logger.trace(getCurrentCharacterStamina() + "/" + + getMaxCharacterStamina() + "\t" + currentState); + if (currentState != MotionState.MOTION_STATE_SWIM_IDLE) { + killAvatar(cachedSession, cachedEntity, PlayerDieType.PLAYER_DIE_TYPE_DRAWN); + } + } + } + + // Consumption Calculators + + // Stamina Consumption Reduction: https://genshin-impact.fandom.com/wiki/Stamina + + private Consumption getFightConsumption(int skillCasting) { + // Talent moving + if (TalentMovements.contains(skillCasting)) { + // TODO: recover 1000 if kamisato hits an enemy at the end of dashing + return getTalentMovingSustainedCost(skillCasting); + } + // Bow avatar charged attack + Avatar currentAvatar = player.getTeamManager().getCurrentAvatarEntity().getAvatar(); + + switch (currentAvatar.getAvatarData().getWeaponType()) { + case WEAPON_BOW: + return getBowSustainedCost(skillCasting); + case WEAPON_CLAYMORE: + return getClaymoreSustainedCost(skillCasting); + case WEAPON_CATALYST: + return getCatalystCost(skillCasting); + case WEAPON_POLE: + return getPolearmCost(skillCasting); + case WEAPON_SWORD_ONE_HAND: + return getSwordCost(skillCasting); + } + + return new Consumption(); + } + + private Consumption getClimbConsumption() { + Consumption consumption = new Consumption(); + if (currentState == MotionState.MOTION_STATE_CLIMB && isPlayerMoving()) { + consumption.type = ConsumptionType.CLIMBING; + consumption.amount = ConsumptionType.CLIMBING.amount; + } + // Climbing specific reductions + consumption.amount *= getFoodCostReductionFactor(ClimbFoodReductionMap); + consumption.amount *= getTalentCostReductionFactor(ClimbTalentReductionMap); + return consumption; + } + + private Consumption getSwimConsumptions() { + handleDrowning(); + Consumption consumption = new Consumption(); + if (currentState == MotionState.MOTION_STATE_SWIM_MOVE) { + consumption.type = ConsumptionType.SWIMMING; + consumption.amount = ConsumptionType.SWIMMING.amount; + } + if (currentState == MotionState.MOTION_STATE_SWIM_DASH) { + consumption.type = ConsumptionType.SWIM_DASH; + consumption.amount = ConsumptionType.SWIM_DASH.amount; + } + // Swimming specific reductions + consumption.amount *= getFoodCostReductionFactor(SwimFoodReductionMap); + consumption.amount *= getTalentCostReductionFactor(SwimTalentReductionMap); + return consumption; + } + + private Consumption getDashConsumption() { + Consumption consumption = new Consumption(); + if (currentState == MotionState.MOTION_STATE_DASH) { + consumption.type = ConsumptionType.DASH; + consumption.amount = ConsumptionType.DASH.amount; + // Dashing specific reductions + consumption.amount *= getFoodCostReductionFactor(DashFoodReductionMap); + } + return consumption; + } + + private Consumption getFlyConsumption() { + // POWERED_FLY, e.g. wind tunnel + if (currentState == MotionState.MOTION_STATE_POWERED_FLY) { + return new Consumption(ConsumptionType.POWERED_FLY); + } + Consumption consumption = new Consumption(ConsumptionType.FLY); + // Flying specific reductions + consumption.amount *= getFoodCostReductionFactor(FlyFoodReductionMap); + consumption.amount *= getTalentCostReductionFactor(FlyTalentReductionMap); + return consumption; + } + + private Consumption getSkiffConsumption() { + // No known reduction for skiffing. + return switch (currentState) { + case MOTION_STATE_SKIFF_DASH -> new Consumption(ConsumptionType.SKIFF_DASH); + case MOTION_STATE_SKIFF_POWERED_DASH -> new Consumption(ConsumptionType.POWERED_SKIFF); + case MOTION_STATE_SKIFF_NORMAL -> new Consumption(ConsumptionType.SKIFF); + default -> new Consumption(); + }; + } + + private Consumption getOtherConsumptions() { + switch (currentState) { + case MOTION_STATE_NOTIFY: +// if (BowSkills.contains(lastSkillId)) { +// return new Consumption(ConsumptionType.FIGHT, 500); +// } + break; + case MOTION_STATE_FIGHT: + // TODO: what if charged attack + return new Consumption(ConsumptionType.FIGHT, 500); + } + + return new Consumption(); + } + + // Reduction getter + + private float getTalentCostReductionFactor(HashMap talentReductionMap) { + // All known talents reductions are not stackable + float reduction = 1; + for (EntityAvatar entity : cachedSession.getPlayer().getTeamManager().getActiveTeam()) { + for (int skillId : entity.getAvatar().getProudSkillList()) { + if (talentReductionMap.containsKey(skillId)) { + float potentialLowerReduction = talentReductionMap.get(skillId); + if (potentialLowerReduction < reduction) { + reduction = potentialLowerReduction; + } + } + } + } + return reduction; + } + + private float getFoodCostReductionFactor(HashMap foodReductionMap) { + // All known food reductions are not stackable + // TODO: Check consumed food (buff?) and return proper factor + float reduction = 1; + return reduction; + } + + private Consumption getTalentMovingSustainedCost(int skillId) { + if (lastSkillFirstTick) { + lastSkillFirstTick = false; + return new Consumption(ConsumptionType.TALENT_DASH, -1000); + } else { + return new Consumption(ConsumptionType.TALENT_DASH, -500); + } + } + + private Consumption getBowSustainedCost(int skillId) { + // Note that bow skills actually recovers stamina + // Character specific handling + // switch (skillId) { + // // No known bow skills cost stamina + // } + return new Consumption(ConsumptionType.FIGHT, +500); + } + + private Consumption getCatalystCost(int skillId) { + Consumption consumption = new Consumption(ConsumptionType.FIGHT, -5000); + // Character specific handling + switch (skillId) { + // TODO: + } + return consumption; + } + + private Consumption getClaymoreSustainedCost(int skillId) { + Consumption consumption = new Consumption(ConsumptionType.FIGHT, -1333); // 4000 / 3 = 1333 + // Character specific handling + switch (skillId) { + case 10571: + case 10532: + consumption.amount = 0; + break; + case 10160: + if (player.getTeamManager().getCurrentAvatarEntity().getAvatar().getProudSkillList().contains(162101)) { + consumption.amount /= 2; + } + break; + } + return consumption; + } + + private Consumption getPolearmCost(int skillId) { + Consumption consumption = new Consumption(ConsumptionType.FIGHT, -2500); + // Character specific handling + switch (skillId) { + // TODO: + } + return consumption; + } + + private Consumption getSwordCost(int skillId) { + Consumption consumption = new Consumption(ConsumptionType.FIGHT, -2000); + // Character specific handling + switch (skillId) { + case 10421: + consumption.amount = -2500; + break; + } + return consumption; + } +} diff --git a/src/main/java/emu/grasscutter/game/player/InvokeHandler.java b/src/main/java/emu/grasscutter/game/player/InvokeHandler.java index edfcbfc83..a266c7411 100644 --- a/src/main/java/emu/grasscutter/game/player/InvokeHandler.java +++ b/src/main/java/emu/grasscutter/game/player/InvokeHandler.java @@ -21,16 +21,16 @@ public class InvokeHandler { public synchronized void addEntry(ForwardType forward, T entry) { switch (forward) { - case FORWARD_TO_ALL -> entryListForwardAll.add(entry); - case FORWARD_TO_ALL_EXCEPT_CUR, FORWARD_TO_ALL_EXIST_EXCEPT_CUR -> entryListForwardAllExceptCur.add(entry); - case FORWARD_TO_HOST -> entryListForwardHost.add(entry); + case FORWARD_TYPE_TO_ALL -> entryListForwardAll.add(entry); + case FORWARD_TYPE_TO_ALL_EXCEPT_CUR, FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR -> entryListForwardAllExceptCur.add(entry); + case FORWARD_TYPE_TO_HOST -> entryListForwardHost.add(entry); default -> { } } } public synchronized void update(Player player) { - if (player.getWorld() == null) { + if (player.getWorld() == null || player.getScene() == null) { this.entryListForwardAll.clear(); this.entryListForwardAllExceptCur.clear(); this.entryListForwardHost.clear(); diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 1eb5e3526..ac22900dd 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -4,13 +4,17 @@ import dev.morphia.annotations.*; import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.PlayerLevelData; +import emu.grasscutter.data.excels.PlayerLevelData; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; import emu.grasscutter.game.CoopRequest; +import emu.grasscutter.game.ability.AbilityManager; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.avatar.AvatarProfileData; import emu.grasscutter.game.avatar.AvatarStorage; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.managers.DeforestationManager.DeforestationManager; import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.entity.GameEntity; @@ -22,12 +26,15 @@ import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.MailHandler; -import emu.grasscutter.game.managers.MovementManager.MovementManager; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.game.managers.InsectCaptureManager; +import emu.grasscutter.game.managers.StaminaManager.StaminaManager; +import emu.grasscutter.game.managers.SotSManager; +import emu.grasscutter.game.managers.EnergyManager.EnergyManager; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.SceneType; +import emu.grasscutter.game.quest.QuestManager; import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.managers.MapMarkManager.*; import emu.grasscutter.game.tower.TowerManager; @@ -44,10 +51,12 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; + import emu.grasscutter.server.event.player.PlayerJoinEvent; import emu.grasscutter.server.event.player.PlayerQuitEvent; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.game.GameSession.SessionState; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.DateHelper; import emu.grasscutter.utils.Position; @@ -59,12 +68,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; +import static emu.grasscutter.Configuration.*; + @Entity(value = "players", useDiscriminator = false) public class Player { - @Transient private static int GlobalMaximumSpringVolume = 8500000; - @Transient private static int GlobalMaximumStamina = 24000; - @Id private int id; @Indexed(options = @IndexOptions(unique = true)) private String accountId; @@ -76,11 +84,18 @@ public class Player { private Position pos; private Position rotation; private PlayerBirthday birthday; + private PlayerCodex codex; private Map properties; private Set nameCardList; private Set flyCloakList; private Set costumeList; + private Set unlockedForgingBlueprints; + + private Integer widgetId; + + private Set realmList; + private Integer currentRealmId; @Transient private long nextGuid = 0; @Transient private int peerId; @@ -92,8 +107,11 @@ public class Player { @Transient private FriendsList friendsList; @Transient private MailHandler mailHandler; @Transient private MessageHandler messageHandler; - + @Transient private AbilityManager abilityManager; + @Transient private QuestManager questManager; + @Transient private SotSManager sotsManager; + @Transient private InsectCaptureManager insectCaptureManager; private TeamManager teamManager; @@ -111,6 +129,7 @@ public class Player { private int mainCharacterId; private boolean godmode; + private boolean stamina; private boolean moonCard; private Date moonCardStartTime; private int moonCardDuration; @@ -131,11 +150,13 @@ public class Player { @Transient private final InvokeHandler abilityInvokeHandler; @Transient private final InvokeHandler clientAbilityInitFinishHandler; - private MapMarksManager mapMarksManager; - @Transient private MovementManager movementManager; + @Transient private MapMarksManager mapMarksManager; + @Transient private StaminaManager staminaManager; + @Transient private EnergyManager energyManager; + @Transient private DeforestationManager deforestationManager; private long springLastUsed; - + private HashMap mapMarks; @Deprecated @SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only! @@ -145,6 +166,11 @@ public class Player { this.friendsList = new FriendsList(this); this.mailHandler = new MailHandler(this); this.towerManager = new TowerManager(this); + this.abilityManager = new AbilityManager(this); + this.deforestationManager = new DeforestationManager(this); + this.insectCaptureManager = new InsectCaptureManager(this); + + this.setQuestManager(new QuestManager(this)); this.pos = new Position(); this.rotation = new Position(); this.properties = new HashMap<>(); @@ -159,6 +185,7 @@ public class Player { this.nameCardList = new HashSet<>(); this.flyCloakList = new HashSet<>(); this.costumeList = new HashSet<>(); + this.unlockedForgingBlueprints = new HashSet<>(); this.setSceneId(3); this.setRegionId(1); @@ -173,13 +200,15 @@ public class Player { this.birthday = new PlayerBirthday(); this.rewardedLevels = new HashSet<>(); this.moonCardGetTimes = new HashSet<>(); + this.codex = new PlayerCodex(this); this.shopLimit = new ArrayList<>(); this.expeditionInfo = new HashMap<>(); this.messageHandler = null; - this.mapMarksManager = new MapMarksManager(); - this.movementManager = new MovementManager(this); + this.mapMarksManager = new MapMarksManager(this); + this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); + this.energyManager = new EnergyManager(this); } // On player creation @@ -192,6 +221,7 @@ public class Player { this.signature = ""; this.teamManager = new TeamManager(this); this.birthday = new PlayerBirthday(); + this.codex = new PlayerCodex(this); this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1); this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1); this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50); @@ -205,9 +235,11 @@ public class Player { this.getPos().set(GameConstants.START_POSITION); this.getRotation().set(0, 307, 0); this.messageHandler = null; - this.mapMarksManager = new MapMarksManager(); - this.movementManager = new MovementManager(this); + this.mapMarksManager = new MapMarksManager(this); + this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); + this.energyManager = new EnergyManager(this); + this.deforestationManager = new DeforestationManager(this); } public int getUid() { @@ -229,7 +261,6 @@ public class Player { public void setAccount(Account account) { this.account = account; - this.account.setPlayerId(getUid()); } public GameSession getSession() { @@ -295,6 +326,39 @@ public class Player { this.updateProfile(); } + public Integer getWidgetId() { + return widgetId; + } + + public void setWidgetId(Integer widgetId) { + this.widgetId = widgetId; + } + + public Set getRealmList() { + return realmList; + } + + public void setRealmList(Set realmList) { + this.realmList = realmList; + } + + public void addRealmList(int realmId) { + if (this.realmList == null) { + this.realmList = new HashSet<>(); + } else if (this.realmList.contains(realmId)) { + return; + } + this.realmList.add(realmId); + } + + public Integer getCurrentRealmId() { + return currentRealmId; + } + + public void setCurrentRealmId(Integer currentRealmId) { + this.currentRealmId = currentRealmId; + } + public Position getPos() { return pos; } @@ -353,7 +417,7 @@ public class Player { } private float getExpModifier() { - return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE; + return GAME_OPTIONS.rates.adventureExp; } // Affected by exp rate @@ -409,6 +473,14 @@ public class Player { return towerManager; } + public QuestManager getQuestManager() { + return questManager; + } + + public void setQuestManager(QuestManager questManager) { + this.questManager = questManager; + } + public PlayerGachaInfo getGachaInfo() { return gachaInfo; } @@ -446,8 +518,12 @@ public class Player { return this.nameCardList; } + public Set getUnlockedForgingBlueprints() { + return unlockedForgingBlueprints; + } + public MpSettingType getMpSetting() { - return MpSettingType.MP_SETTING_ENTER_AFTER_APPLY; // TEMP + return MpSettingType.MP_SETTING_TYPE_ENTER_AFTER_APPLY; // TEMP } public Queue getAttackResults() { @@ -699,7 +775,6 @@ public class Player { return expeditionInfo.get(avaterGuid); } - public List getShopLimit() { return shopLimit; } @@ -727,7 +802,14 @@ public class Player { } this.save(); } - + public boolean getStamina() { + // Get Stamina + return stamina; + } + public void setStamina(boolean stamina) { + // Set Stamina + this.stamina = stamina; + } public boolean inGodmode() { return godmode; } @@ -744,7 +826,7 @@ public class Player { this.hasSentAvatarDataNotify = hasSentAvatarDataNotify; } - public void addAvatar(Avatar avatar) { + public void addAvatar(Avatar avatar, boolean addToCurrentTeam) { boolean result = getAvatars().addAvatar(avatar); if (result) { @@ -755,14 +837,22 @@ public class Player { if (hasSentAvatarDataNotify()) { // Recalc stats avatar.recalcStats(); - // Packet - sendPacket(new PacketAvatarAddNotify(avatar, false)); + // Packet, show notice on left if the avatar will be added to the team + sendPacket(new PacketAvatarAddNotify(avatar, addToCurrentTeam && this.getTeamManager().canAddAvatarToCurrentTeam())); + if (addToCurrentTeam) { + // If space in team, add + this.getTeamManager().addAvatarToCurrentTeam(avatar); + } } } else { // Failed adding avatar } } + public void addAvatar(Avatar avatar) { + addAvatar(avatar, true); + } + public void addFlycloak(int flycloakId) { this.getFlyCloakList().add(flycloakId); this.sendPacket(new PacketAvatarGainFlycloakNotify(flycloakId)); @@ -830,62 +920,58 @@ public class Player { public void interactWith(int gadgetEntityId) { GameEntity entity = getScene().getEntityById(gadgetEntityId); - if (entity == null) { return; } // Handle - if (entity instanceof EntityItem) { + if (entity instanceof EntityItem drop) { // Pick item - EntityItem drop = (EntityItem) entity; if (!drop.isShare()) // check drop owner to avoid someone picked up item in others' world { int dropOwner = (int)(drop.getGuid() >> 32); - if (dropOwner != getUid()) + if (dropOwner != getUid()) { return; + } } entity.getScene().removeEntity(entity); GameItem item = new GameItem(drop.getItemData(), drop.getCount()); // Add to inventory boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop); if (success) { - - if (!drop.isShare()) // not shared drop - this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM)); - else - this.getScene().broadcastPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM)); + if (!drop.isShare()) { // not shared drop + this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_TYPE_PICK_ITEM)); + }else{ + this.getScene().broadcastPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_TYPE_PICK_ITEM)); + } } - } else if (entity instanceof EntityGadget) { - EntityGadget gadget = (EntityGadget) entity; - + } else if (entity instanceof EntityGadget gadget) { if (gadget.getGadgetData().getType() == EntityType.RewardStatue) { if (scene.getChallenge() != null) { scene.getChallenge().getStatueDrops(this); } - - this.sendPacket(new PacketGadgetInteractRsp(gadget, InteractType.INTERACT_OPEN_STATUE)); + this.sendPacket(new PacketGadgetInteractRsp(gadget, InteractType.INTERACT_TYPE_OPEN_STATUE)); } + } else if (entity instanceof EntityMonster monster) { + insectCaptureManager.arrestSmallCreature(monster); + } else if (entity instanceof EntityVehicle vehicle) {// try to arrest it, example: glowworm + insectCaptureManager.arrestSmallCreature(vehicle); } else { // Delete directly entity.getScene().removeEntity(entity); } - - return; } public void onPause() { - + getStaminaManager().stopSustainedStaminaHandler(); } public void onUnpause() { - + getStaminaManager().startSustainedStaminaHandler(); } public void sendPacket(BasePacket packet) { - if (this.hasSentAvatarDataNotify) { - this.getSession().send(packet); - } + this.getSession().send(packet); } public OnlinePlayerInfo getOnlinePlayerInfo() { @@ -920,6 +1006,8 @@ public class Player { return this.birthday.getDay() > 0; } + public PlayerCodex getCodex(){ return this.codex; } + public Set getRewardedLevels() { return rewardedLevels; } @@ -944,8 +1032,8 @@ public class Player { } } } else { - List showAvatarList = DatabaseHelper.getPlayerById(id).getShowAvatarList(); - AvatarStorage avatars = DatabaseHelper.getPlayerById(id).getAvatars(); + List showAvatarList = DatabaseHelper.getPlayerByUid(id).getShowAvatarList(); + AvatarStorage avatars = DatabaseHelper.getPlayerByUid(id).getAvatars(); avatars.loadFromDatabase(); if (showAvatarList != null) { for (int avatarId : showAvatarList) { @@ -985,7 +1073,7 @@ public class Player { player = this; shouldRecalc = false; } else { - player = DatabaseHelper.getPlayerById(id); + player = DatabaseHelper.getPlayerByUid(id); player.getAvatars().loadFromDatabase(); player.getInventory().loadFromDatabase(); shouldRecalc = true; @@ -1024,10 +1112,26 @@ public class Player { return mapMarksManager; } - public MovementManager getMovementManager() { return movementManager; } + public StaminaManager getStaminaManager() { return staminaManager; } public SotSManager getSotSManager() { return sotsManager; } + public EnergyManager getEnergyManager() { + return this.energyManager; + } + + public AbilityManager getAbilityManager() { + return abilityManager; + } + + public DeforestationManager getDeforestationManager() { + return deforestationManager; + } + + public HashMap getMapMarks() { return mapMarks; } + + public void setMapMarks(HashMap newMarks) { mapMarks = newMarks; } + public synchronized void onTick() { // Check ping if (this.getLastPingTime() > System.currentTimeMillis() + 60000) { @@ -1039,7 +1143,10 @@ public class Player { while (it.hasNext()) { CoopRequest req = it.next(); if (req.isExpired()) { - req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.SYSTEM_JUDGE)); + req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify( + this, + false, + PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.REASON_SYSTEM_JUDGE)); it.remove(); } } @@ -1083,6 +1190,7 @@ public class Player { @PostLoad private void onLoad() { + this.getCodex().setPlayer(this); this.getTeamManager().setPlayer(this); this.getTowerManager().setPlayer(this); } @@ -1090,23 +1198,20 @@ public class Player { public void save() { DatabaseHelper.savePlayer(this); } - - public void onLogin() { + + // Called from tokenrsp + public void loadFromDatabase() { // Make sure these exist if (this.getTeamManager() == null) { this.teamManager = new TeamManager(this); } + if (this.getCodex() == null) { + this.codex = new PlayerCodex(this); + } if (this.getProfile().getUid() == 0) { this.getProfile().syncWithCharacter(this); } - // Check if player object exists in server - // TODO - optimize - Player exists = this.getServer().getPlayerByUid(getUid()); - if (exists != null) { - exists.getSession().close(); - } - // Load from db this.getAvatars().loadFromDatabase(); this.getInventory().loadFromDatabase(); @@ -1114,17 +1219,36 @@ public class Player { this.getFriendsList().loadFromDatabase(); this.getMailHandler().loadFromDatabase(); + this.getQuestManager().loadFromDatabase(); - // Create world - World world = new World(this); - world.addPlayer(this); - - // Add to gameserver + // Add to gameserver (Always handle last) if (getSession().isActive()) { getServer().registerPlayer(this); getProfile().setPlayer(this); // Set online } + } + + public void onLogin() { + // Quest - Commented out because a problem is caused if you log out while this quest is active + /* + if (getQuestManager().getMainQuestById(351) == null) { + GameQuest quest = getQuestManager().addQuest(35104); + if (quest != null) { + quest.finish(); + } + + getQuestManager().addQuest(35101); + + this.setSceneId(3); + this.getPos().set(GameConstants.START_POSITION); + } + */ + + // Create world + World world = new World(this); + world.addPlayer(this); + // Multiplayer setting this.setProperty(PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE, this.getMpSetting().getNumber()); this.setProperty(PlayerProperty.PROP_IS_MP_MODE_AVAILABLE, 1); @@ -1134,6 +1258,14 @@ public class Player { session.send(new PacketStoreWeightLimitNotify()); session.send(new PacketPlayerStoreNotify(this)); session.send(new PacketAvatarDataNotify(this)); + session.send(new PacketFinishedParentQuestNotify(this)); + session.send(new PacketQuestListNotify(this)); + session.send(new PacketCodexDataFullNotify(this)); + session.send(new PacketAllWidgetDataNotify(this)); + session.send(new PacketWidgetGadgetAllDataNotify()); + session.send(new PacketPlayerHomeCompInfoNotify(this)); + session.send(new PacketHomeComfortInfoNotify(this)); + session.send(new PacketForgeDataNotify(this)); getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward. @@ -1143,6 +1275,9 @@ public class Player { // First notify packets sent this.setHasSentAvatarDataNotify(true); + + // Set session state + session.setState(SessionState.ACTIVE); // Call join event. PlayerJoinEvent event = new PlayerJoinEvent(this); event.call(); @@ -1151,31 +1286,48 @@ public class Player { } public void onLogout() { - // stop stamina calculation - getMovementManager().resetTimer(); + try{ + // stop stamina calculation + getStaminaManager().stopSustainedStaminaHandler(); - // force to leave the dungeon - if (getScene().getSceneType() == SceneType.SCENE_DUNGEON) { + // force to leave the dungeon (inside has a "if") this.getServer().getDungeonManager().exitDungeon(this); + + // Leave world + if (this.getWorld() != null) { + this.getWorld().removePlayer(this); + } + + // Status stuff + this.getProfile().syncWithCharacter(this); + this.getProfile().setPlayer(null); // Set offline + + this.getCoopRequests().clear(); + + // Save to db + this.save(); + this.getTeamManager().saveAvatars(); + this.getFriendsList().save(); + + // Call quit event. + PlayerQuitEvent event = new PlayerQuitEvent(this); event.call(); + + //reset wood + getDeforestationManager().resetWood(); + + }catch (Throwable e){ + e.printStackTrace(); + Grasscutter.getLogger().warn("Player (UID {}) save failure", getUid()); + }finally { + removeFromServer(); } - // Leave world - if (this.getWorld() != null) { - this.getWorld().removePlayer(this); - } + } - // Status stuff - this.getProfile().syncWithCharacter(this); - this.getProfile().setPlayer(null); // Set offline - - this.getCoopRequests().clear(); - - // Save to db - this.save(); - this.getTeamManager().saveAvatars(); - this.getFriendsList().save(); - - // Call quit event. - PlayerQuitEvent event = new PlayerQuitEvent(this); event.call(); + public void removeFromServer() { + // Remove from server. + //Note: DON'T DELETE BY UID,BECAUSE THERE ARE MULTIPLE SAME UID PLAYERS WHEN DUPLICATED LOGIN! + //so I decide to delete by object rather than uid + getServer().getPlayers().values().removeIf(player1 -> player1 == this); } public enum SceneLoadState { @@ -1214,7 +1366,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_LAST_CHANGE_AVATAR_TIME) { // 10001 // TODO: implement sanity check } else if (prop == PlayerProperty.PROP_MAX_SPRING_VOLUME) { // 10002 - if (!(value >= 0 && value <= GlobalMaximumSpringVolume)) { return false; } + if (!(value >= 0 && value <= SotSManager.GlobalMaximumSpringVolume)) { return false; } } else if (prop == PlayerProperty.PROP_CUR_SPRING_VOLUME) { // 10003 int playerMaximumSpringVolume = getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); if (!(value >= 0 && value <= playerMaximumSpringVolume)) { return false; } @@ -1231,7 +1383,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_IS_TRANSFERABLE) { // 10009 if (!(0 <= value && value <= 1)) { return false; } } else if (prop == PlayerProperty.PROP_MAX_STAMINA) { // 10010 - if (!(value >= 0 && value <= GlobalMaximumStamina)) { return false; } + if (!(value >= 0 && value <= StaminaManager.GlobalCharacterMaximumStamina)) { return false; } } else if (prop == PlayerProperty.PROP_CUR_PERSIST_STAMINA) { // 10011 int playerMaximumStamina = getProperty(PlayerProperty.PROP_MAX_STAMINA); if (!(value >= 0 && value <= playerMaximumStamina)) { return false; } @@ -1242,7 +1394,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_PLAYER_EXP) { // 10014 if (!(0 <= value)) { return false; } } else if (prop == PlayerProperty.PROP_PLAYER_HCOIN) { // 10015 - // see 10015 + // see PlayerProperty.PROP_PLAYER_HCOIN comments } else if (prop == PlayerProperty.PROP_PLAYER_SCOIN) { // 10016 // See 10015 } else if (prop == PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE) { // 10017 diff --git a/src/main/java/emu/grasscutter/game/player/PlayerCodex.java b/src/main/java/emu/grasscutter/game/player/PlayerCodex.java new file mode 100644 index 000000000..191fc4112 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/player/PlayerCodex.java @@ -0,0 +1,165 @@ +package emu.grasscutter.game.player; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.CodexAnimalData; +import emu.grasscutter.data.excels.CodexReliquaryData; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.inventory.MaterialType; +import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; + +import java.util.*; + +@Entity +public class PlayerCodex { + @Transient private Player player; + + //itemId is not codexId! + private Set unlockedWeapon; + private Map unlockedAnimal; + private Set unlockedMaterial; + private Set unlockedBook; + private Set unlockedTip; + private Set unlockedView; + private Set unlockedReliquary; + private Set unlockedReliquarySuitCodex; + + public PlayerCodex(){ + this.unlockedWeapon = new HashSet<>(); + this.unlockedAnimal = new HashMap<>(); + this.unlockedMaterial = new HashSet<>(); + this.unlockedBook = new HashSet<>(); + this.unlockedTip = new HashSet<>(); + this.unlockedView = new HashSet<>(); + this.unlockedReliquary = new HashSet<>(); + this.unlockedReliquarySuitCodex = new HashSet<>(); + } + + public PlayerCodex(Player player){ + this(); + this.player = player; + } + + public void setPlayer(Player player) { + this.player = player; + } + + public void checkAddedItem(GameItem item){ + ItemType type = item.getItemData().getItemType(); + if (type == ItemType.ITEM_WEAPON){ + if(!getUnlockedWeapon().contains(item.getItemId())){ + getUnlockedWeapon().add(item.getItemId()); + var codexItem = GameData.getCodexWeaponDataIdMap().get(item.getItemId()); + if(codexItem != null){ + player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(2, codexItem.getId())); + } + } + } + else if(type == ItemType.ITEM_MATERIAL){ + if( item.getItemData().getMaterialType() == MaterialType.MATERIAL_FOOD || + item.getItemData().getMaterialType() == MaterialType.MATERIAL_WIDGET|| + item.getItemData().getMaterialType() == MaterialType.MATERIAL_EXCHANGE|| + item.getItemData().getMaterialType() == MaterialType.MATERIAL_AVATAR_MATERIAL|| + item.getItemData().getMaterialType() == MaterialType.MATERIAL_NOTICE_ADD_HP){ + if (!getUnlockedMaterial().contains(item.getItemId())) { + var codexMaterial = GameData.getCodexMaterialDataIdMap().get(item.getItemId()); + if (codexMaterial != null) { + getUnlockedMaterial().add(item.getItemId()); + player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(4, codexMaterial.getId())); + } + } + } + } + else if(type == ItemType.ITEM_RELIQUARY) { + if(!getUnlockedReliquary().contains(item.getItemId())){ + getUnlockedReliquary().add(item.getItemId()); + checkUnlockedSuits(item); + } + } + } + + public void checkAnimal(GameEntity target, CodexAnimalData.CodexAnimalUnlockCondition condition){ + if(target instanceof EntityMonster){ + var monsterId = ((EntityMonster)target).getMonsterData().getId(); + var codexAnimal = GameData.getCodexAnimalDataMap().get(monsterId); + + if(!getUnlockedAnimal().containsKey(monsterId)) { + if (codexAnimal != null) { + if(codexAnimal.getUnlockCondition() == condition || codexAnimal.getUnlockCondition() == null){ + getUnlockedAnimal().put(monsterId, 1); + } + } + }else{ + getUnlockedAnimal().put(monsterId, getUnlockedAnimal().get(monsterId) + 1); + } + player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(3, monsterId)); + } + } + + public void checkUnlockedSuits(GameItem item){ + int reliquaryId = item.getItemId(); + Optional excelReliquarySuitList = GameData.getcodexReliquaryArrayList().stream().filter( + x -> x.getCupId() == reliquaryId + || x.getLeatherId() == reliquaryId + || x.getCapId() == reliquaryId + || x.getFlowerId() == reliquaryId + || x.getSandId() == reliquaryId + ).findFirst(); + if(excelReliquarySuitList.isPresent()) { + var excelReliquarySuit = excelReliquarySuitList.get(); + if(!getUnlockedReliquarySuitCodex().contains(excelReliquarySuit.getId())){ + if( + getUnlockedReliquary().contains(excelReliquarySuit.getCupId()) && + getUnlockedReliquary().contains(excelReliquarySuit.getLeatherId()) && + getUnlockedReliquary().contains(excelReliquarySuit.getCapId()) && + getUnlockedReliquary().contains(excelReliquarySuit.getFlowerId()) && + getUnlockedReliquary().contains(excelReliquarySuit.getSandId()) + ){ + getUnlockedReliquarySuitCodex().add(excelReliquarySuit.getId()); + player.save(); + this.player.sendPacket(new PacketCodexDataUpdateNotify(8, excelReliquarySuit.getId())); + } + } + } + } + + public Set getUnlockedWeapon() { + return unlockedWeapon; + } + + public Map getUnlockedAnimal() { + return unlockedAnimal; + } + + public Set getUnlockedMaterial() { + return unlockedMaterial; + } + + public Set getUnlockedBook() { + return unlockedBook; + } + + public Set getUnlockedTip() { + return unlockedTip; + } + + public Set getUnlockedView() { + return unlockedView; + } + + public Set getUnlockedReliquary() { + return unlockedReliquary; + } + + public Set getUnlockedReliquarySuitCodex() { + return unlockedReliquarySuitCodex; + } + +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/player/TeamInfo.java b/src/main/java/emu/grasscutter/game/player/TeamInfo.java index 5794a7913..89383e486 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamInfo.java +++ b/src/main/java/emu/grasscutter/game/player/TeamInfo.java @@ -4,10 +4,10 @@ import java.util.ArrayList; import java.util.List; import dev.morphia.annotations.Entity; -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; import emu.grasscutter.game.avatar.Avatar; +import static emu.grasscutter.Configuration.*; + @Entity public class TeamInfo { private String name; @@ -15,7 +15,7 @@ public class TeamInfo { public TeamInfo() { this.name = ""; - this.avatars = new ArrayList<>(Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam); + this.avatars = new ArrayList<>(GAME_OPTIONS.avatarLimits.singlePlayerTeam); } public TeamInfo(List avatars) { @@ -44,7 +44,7 @@ public class TeamInfo { } public boolean addAvatar(Avatar avatar) { - if (size() >= Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam || contains(avatar)) { + if (contains(avatar)) { return false; } @@ -64,7 +64,7 @@ public class TeamInfo { } public void copyFrom(TeamInfo team) { - copyFrom(team, Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam); + copyFrom(team, GAME_OPTIONS.avatarLimits.singlePlayerTeam); } public void copyFrom(TeamInfo team, int maxTeamSize) { diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 16e8942ad..f969e694e 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -5,8 +5,7 @@ import java.util.*; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.def.AvatarSkillDepotData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityBaseGadget; @@ -39,6 +38,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; +import static emu.grasscutter.Configuration.*; + @Entity public class TeamManager { @Transient private Player player; @@ -103,6 +104,20 @@ public class TeamManager { this.mpTeam = mpTeam; } + /** + * Search through all teams and if the team matches, return that index. + * Otherwise, return -1. + * No match could mean that the team does not currently belong to the player. + */ + public int getTeamId(TeamInfo team) { + for (int i = 1; i <= this.teams.size(); i++) { + if (this.teams.get(i).equals(team)) { + return i; + } + } + return -1; + } + public int getCurrentTeamId() { // Starts from 1 return currentTeamIndex; @@ -173,17 +188,119 @@ public class TeamManager { public int getMaxTeamSize() { if (getPlayer().isInMultiplayer()) { - int max = Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeamMultiplayer; + int max = GAME_OPTIONS.avatarLimits.multiplayerTeam; if (getPlayer().getWorld().getHost() == this.getPlayer()) { return Math.max(1, (int) Math.ceil(max / (double) getWorld().getPlayerCount())); } return Math.max(1, (int) Math.floor(max / (double) getWorld().getPlayerCount())); } - return Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam; + + return GAME_OPTIONS.avatarLimits.singlePlayerTeam; } // Methods - + + /** + * Returns true if there is space to add the number of avatars to the team. + */ + public boolean canAddAvatarsToTeam(TeamInfo team, int avatars) { + return team.size() + avatars <= getMaxTeamSize(); + } + + /** + * Returns true if there is space to add to the team. + */ + public boolean canAddAvatarToTeam(TeamInfo team) { + return canAddAvatarsToTeam(team, 1); + } + + /** + * Returns true if there is space to add the number of avatars to the current team. + * If the current team is temporary, returns false. + */ + public boolean canAddAvatarsToCurrentTeam(int avatars) { + if (this.useTemporarilyTeamIndex != -1){ + return false; + } + return canAddAvatarsToTeam(this.getCurrentTeamInfo(), avatars); + } + + /** + * Returns true if there is space to add to the current team. + * If the current team is temporary, returns false. + */ + public boolean canAddAvatarToCurrentTeam() { + return canAddAvatarsToCurrentTeam(1); + } + + /** + * Try to add the collection of avatars to the team. + * Returns true if all were successfully added. + * If some can not be added, returns false and does not add any. + */ + public boolean addAvatarsToTeam(TeamInfo team, Collection avatars) { + if (!canAddAvatarsToTeam(team, avatars.size())) { + return false; + } + + // Convert avatars into a collection of avatar IDs, then add + team.getAvatars().addAll(avatars.stream().map(a -> a.getAvatarId()).toList()); + + // Update team + if (this.getPlayer().isInMultiplayer()) { + if (team.equals(this.getMpTeam())) { + // MP team Packet + this.updateTeamEntities(new PacketChangeMpTeamAvatarRsp(getPlayer(), team)); + } + } else { + // SP team update packet + getPlayer().sendPacket(new PacketAvatarTeamUpdateNotify(getPlayer())); + + int teamId = this.getTeamId(team); + if (teamId != -1) { + // This is one of the player's teams + // Update entites + if (teamId == this.getCurrentTeamId()) { + this.updateTeamEntities(new PacketSetUpAvatarTeamRsp(getPlayer(), teamId, team)); + } else { + getPlayer().sendPacket(new PacketSetUpAvatarTeamRsp(getPlayer(), teamId, team)); + } + } + } + + return true; + } + + /** + * Try to add an avatar to a team. + * Returns true if successful. + */ + public boolean addAvatarToTeam(TeamInfo team, Avatar avatar){ + return addAvatarsToTeam(team, Collections.singleton(avatar)); + } + + /** + * Try to add the collection of avatars to the current team. + * Will not modify a temporary team. + * Returns true if all were successfully added. + * If some can not be added, returns false and does not add any. + */ + public boolean addAvatarsToCurrentTeam(Collection avatars) { + if (this.useTemporarilyTeamIndex != -1){ + return false; + } + return addAvatarsToTeam(this.getCurrentTeamInfo(), avatars); + } + + /** + * Try to add an avatar to the current team. + * Will not modify a temporary team. + * Returns true if successful. + */ + public boolean addAvatarToCurrentTeam(Avatar avatar) { + return addAvatarsToCurrentTeam(Collections.singleton(avatar)); + } + private void updateTeamResonances() { Int2IntOpenHashMap map = new Int2IntOpenHashMap(); @@ -235,7 +352,7 @@ public class TeamManager { // Add back entities into team for (int i = 0; i < this.getCurrentTeamInfo().getAvatars().size(); i++) { int avatarId = this.getCurrentTeamInfo().getAvatars().get(i); - EntityAvatar entity = null; + EntityAvatar entity; if (existingAvatars.containsKey(avatarId)) { entity = existingAvatars.get(avatarId); @@ -302,8 +419,8 @@ public class TeamManager { // Set team data LinkedHashSet newTeam = new LinkedHashSet<>(); - for (int i = 0; i < list.size(); i++) { - Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); + for (Long aLong : list) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(aLong); if (avatar == null || newTeam.contains(avatar)) { // Should never happen return; @@ -313,19 +430,7 @@ public class TeamManager { // Clear current team info and add avatars from our new team teamInfo.getAvatars().clear(); - for (Avatar avatar : newTeam) { - teamInfo.addAvatar(avatar); - } - - // Update packet - getPlayer().sendPacket(new PacketAvatarTeamUpdateNotify(getPlayer())); - - // Update entites - if (teamId == this.getCurrentTeamId()) { - this.updateTeamEntities(new PacketSetUpAvatarTeamRsp(getPlayer(), teamId, teamInfo)); - } else { - getPlayer().sendPacket(new PacketSetUpAvatarTeamRsp(getPlayer(), teamId, teamInfo)); - } + this.addAvatarsToTeam(teamInfo, newTeam); } public void setupMpTeam(List list) { @@ -338,8 +443,8 @@ public class TeamManager { // Set team data LinkedHashSet newTeam = new LinkedHashSet<>(); - for (int i = 0; i < list.size(); i++) { - Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); + for (Long aLong : list) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(aLong); if (avatar == null || newTeam.contains(avatar)) { // Should never happen return; @@ -349,16 +454,11 @@ public class TeamManager { // Clear current team info and add avatars from our new team teamInfo.getAvatars().clear(); - for (Avatar avatar : newTeam) { - teamInfo.addAvatar(avatar); - } - - // Packet - this.updateTeamEntities(new PacketChangeMpTeamAvatarRsp(getPlayer(), teamInfo)); + this.addAvatarsToTeam(teamInfo, newTeam); } public void setupTemporaryTeam(List> guidList) { - var team = guidList.stream().map(list -> { + this.temporaryTeam = guidList.stream().map(list -> { // Sanity checks if (list.size() == 0 || list.size() > getMaxTeamSize()) { return null; @@ -366,8 +466,8 @@ public class TeamManager { // Set team data LinkedHashSet newTeam = new LinkedHashSet<>(); - for (int i = 0; i < list.size(); i++) { - Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); + for (Long aLong : list) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(aLong); if (avatar == null || newTeam.contains(avatar)) { // Should never happen return null; @@ -383,7 +483,6 @@ public class TeamManager { .filter(Objects::nonNull) .map(TeamInfo::new) .toList(); - this.temporaryTeam = team; } public void useTemporaryTeam(int index) { @@ -455,7 +554,7 @@ public class TeamManager { this.setCurrentCharacterIndex(index); // Old entity motion state - oldEntity.setMotionState(MotionState.MOTION_STANDBY); + oldEntity.setMotionState(MotionState.MOTION_STATE_STANDBY); // Remove and Add getPlayer().getScene().replaceEntity(oldEntity, newEntity); @@ -472,7 +571,7 @@ public class TeamManager { PlayerDieType dieType = deadAvatar.getKilledType(); int killedBy = deadAvatar.getKilledBy(); - if (dieType == PlayerDieType.PLAYER_DIE_DRAWN) { + if (dieType == PlayerDieType.PLAYER_DIE_TYPE_DRAWN) { // Died in water. Do not replace // The official server has skipped this notify and will just respawn the team immediately after the animation. // TODO: Perhaps find a way to get vanilla experience? @@ -557,7 +656,7 @@ public class TeamManager { // return; // } // } - player.getMovementManager().resetTimer(); // prevent drowning immediately after respawn + player.getStaminaManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn // Revive all team members for (EntityAvatar entity : getActiveTeam()) { @@ -570,7 +669,7 @@ public class TeamManager { } // Teleport player - getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.ENTER_SELF, EnterReason.Revival, 3, GameConstants.START_POSITION)); + getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.ENTER_TYPE_SELF, EnterReason.Revival, 3, GameConstants.START_POSITION)); // Set player position player.setSceneId(3); diff --git a/src/main/java/emu/grasscutter/game/props/ElementType.java b/src/main/java/emu/grasscutter/game/props/ElementType.java index 23362c39f..12a30f6fc 100644 --- a/src/main/java/emu/grasscutter/game/props/ElementType.java +++ b/src/main/java/emu/grasscutter/game/props/ElementType.java @@ -9,21 +9,22 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; public enum ElementType { - None (0, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), - Fire (1, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2"), - Water (2, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2"), - Grass (3, FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY), - Electric (4, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2"), - Ice (5, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2"), - Frozen (6, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), - Wind (7, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2"), - Rock (8, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2"), - AntiFire (9, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), - Default (255, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10801, "TeamResonance_AllDifferent"); + None (0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), + Fire (1, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2"), + Water (2, FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2"), + Grass (3, FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY), + Electric (4, FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2"), + Ice (5, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2"), + Frozen (6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), + Wind (7, FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2"), + Rock (8, FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2"), + AntiFire (9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), + Default (255, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10801, "TeamResonance_AllDifferent"); private final int value; private final int teamResonanceId; - private final FightProperty energyProperty; + private final FightProperty curEnergyProp; + private final FightProperty maxEnergyProp; private final int configHash; private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); private static final Map stringMap = new HashMap<>(); @@ -35,13 +36,14 @@ public enum ElementType { }); } - private ElementType(int value, FightProperty energyProperty) { - this(value, energyProperty, 0, null); + private ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp) { + this(value, curEnergyProp, maxEnergyProp, 0, null); } - private ElementType(int value, FightProperty energyProperty, int teamResonanceId, String configName) { + private ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName) { this.value = value; - this.energyProperty = energyProperty; + this.curEnergyProp = curEnergyProp; + this.maxEnergyProp = maxEnergyProp; this.teamResonanceId = teamResonanceId; if (configName != null) { this.configHash = Utils.abilityHash(configName); @@ -54,8 +56,12 @@ public enum ElementType { return value; } - public FightProperty getEnergyProperty() { - return energyProperty; + public FightProperty getCurEnergyProp() { + return curEnergyProp; + } + + public FightProperty getMaxEnergyProp() { + return maxEnergyProp; } public int getTeamResonanceId() { diff --git a/src/main/java/emu/grasscutter/game/props/MonsterType.java b/src/main/java/emu/grasscutter/game/props/MonsterType.java new file mode 100644 index 000000000..abbc33ba0 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/props/MonsterType.java @@ -0,0 +1,44 @@ +package emu.grasscutter.game.props; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public enum MonsterType { + MONSTER_NONE (0), + MONSTER_ORDINARY (1), + MONSTER_BOSS (2), + MONSTER_ENV_ANIMAL (3), + MONSTER_LITTLE_MONSTER (4), + MONSTER_FISH (5); + + private final int value; + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()).forEach(e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private MonsterType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static MonsterType getTypeByValue(int value) { + return map.getOrDefault(value, MONSTER_NONE); + } + + public static MonsterType getTypeByName(String name) { + return stringMap.getOrDefault(name, MONSTER_NONE); + } +} diff --git a/src/main/java/emu/grasscutter/game/props/OpenState.java b/src/main/java/emu/grasscutter/game/props/OpenState.java index 7cba2fcf3..d566e9051 100644 --- a/src/main/java/emu/grasscutter/game/props/OpenState.java +++ b/src/main/java/emu/grasscutter/game/props/OpenState.java @@ -94,6 +94,7 @@ public enum OpenState { OPEN_STATE_GUIDE_RELICRESOLVE(84), OPEN_STATE_GUIDE_GGUIDE(85), OPEN_STATE_GUIDE_GGUIDE_HINT(86), + OPEN_STATE_GUIDE_RIGHT_TEAM(90), // mobile phone only! OPEN_STATE_CITY_REPUATION_MENGDE(800), OPEN_STATE_CITY_REPUATION_LIYUE(801), OPEN_STATE_CITY_REPUATION_UI_HINT(802), diff --git a/src/main/java/emu/grasscutter/game/props/PlayerProperty.java b/src/main/java/emu/grasscutter/game/props/PlayerProperty.java index 3cb67d9bb..85a9456cf 100644 --- a/src/main/java/emu/grasscutter/game/props/PlayerProperty.java +++ b/src/main/java/emu/grasscutter/game/props/PlayerProperty.java @@ -30,7 +30,7 @@ public enum PlayerProperty { // his gems and then got a money refund, so negative is allowed. PROP_PLAYER_SCOIN (10016), // Mora [0, +inf) PROP_PLAYER_MP_SETTING_TYPE (10017), // Do you allow other players to join your game? [0=no 1=direct 2=approval] - PROP_IS_MP_MODE_AVAILABLE (10018), // Are you not in a quest or something that disables MP? [0, 1] + PROP_IS_MP_MODE_AVAILABLE (10018), // 0 if in quest or something that disables MP [0, 1] PROP_PLAYER_WORLD_LEVEL (10019), // [0, 8] PROP_PLAYER_RESIN (10020), // Original Resin [0, +inf) PROP_PLAYER_WAIT_SUB_HCOIN (10022), diff --git a/src/main/java/emu/grasscutter/game/props/WeaponType.java b/src/main/java/emu/grasscutter/game/props/WeaponType.java new file mode 100644 index 000000000..11654464f --- /dev/null +++ b/src/main/java/emu/grasscutter/game/props/WeaponType.java @@ -0,0 +1,69 @@ +package emu.grasscutter.game.props; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public enum WeaponType { + WEAPON_NONE (0), + WEAPON_SWORD_ONE_HAND (1, 10, 5), + WEAPON_CROSSBOW (2), + WEAPON_STAFF (3), + WEAPON_DOUBLE_DAGGER (4), + WEAPON_KATANA (5), + WEAPON_SHURIKEN (6), + WEAPON_STICK (7), + WEAPON_SPEAR (8), + WEAPON_SHIELD_SMALL (9), + WEAPON_CATALYST (10, 0, 10), + WEAPON_CLAYMORE (11, 0, 10), + WEAPON_BOW (12, 0, 5), + WEAPON_POLE (13, 0, 4); + + private final int value; + private int energyGainInitialProbability; + private int energyGainIncreaseProbability; + + private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); + private static final Map stringMap = new HashMap<>(); + + static { + Stream.of(values()).forEach(e -> { + map.put(e.getValue(), e); + stringMap.put(e.name(), e); + }); + } + + private WeaponType(int value) { + this.value = value; + } + + private WeaponType(int value, int energyGainInitialProbability, int energyGainIncreaseProbability) { + this.value = value; + this.energyGainInitialProbability = energyGainInitialProbability; + this.energyGainIncreaseProbability = energyGainIncreaseProbability; + } + + public int getValue() { + return value; + } + + public int getEnergyGainInitialProbability() { + return energyGainInitialProbability; + } + + public int getEnergyGainIncreaseProbability() { + return energyGainIncreaseProbability; + } + + public static WeaponType getTypeByValue(int value) { + return map.getOrDefault(value, WEAPON_NONE); + } + + public static WeaponType getTypeByName(String name) { + return stringMap.getOrDefault(name, WEAPON_NONE); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java new file mode 100644 index 000000000..4dc31a5ae --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/GameMainQuest.java @@ -0,0 +1,143 @@ +package emu.grasscutter.game.quest; + +import java.util.HashMap; +import java.util.Map; + +import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; +import org.bson.types.ObjectId; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.Indexed; +import dev.morphia.annotations.Transient; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.RewardData; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ActionReason; +import emu.grasscutter.game.quest.enums.ParentQuestState; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.net.proto.ChildQuestOuterClass.ChildQuest; +import emu.grasscutter.net.proto.ParentQuestOuterClass.ParentQuest; +import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +@Entity(value = "quests", useDiscriminator = false) +public class GameMainQuest { + @Id private ObjectId id; + + @Indexed private int ownerUid; + @Transient private Player owner; + + private Map childQuests; + + private int parentQuestId; + private int[] questVars; + private ParentQuestState state; + private boolean isFinished; + + @Deprecated // Morphia only. Do not use. + public GameMainQuest() {} + + public GameMainQuest(Player player, int parentQuestId) { + this.owner = player; + this.ownerUid = player.getUid(); + this.parentQuestId = parentQuestId; + this.childQuests = new HashMap<>(); + this.questVars = new int[5]; + this.state = ParentQuestState.PARENT_QUEST_STATE_NONE; + } + + public int getParentQuestId() { + return parentQuestId; + } + + public int getOwnerUid() { + return ownerUid; + } + + public Player getOwner() { + return owner; + } + + public void setOwner(Player player) { + if (player.getUid() != this.getOwnerUid()) return; + this.owner = player; + } + + public Map getChildQuests() { + return childQuests; + } + + public GameQuest getChildQuestById(int id) { + return this.getChildQuests().get(id); + } + + public int[] getQuestVars() { + return questVars; + } + + public ParentQuestState getState() { + return state; + } + + public boolean isFinished() { + return isFinished; + } + + public void finish() { + this.isFinished = true; + this.state = ParentQuestState.PARENT_QUEST_STATE_FINISHED; + + this.getOwner().getSession().send(new PacketFinishedParentQuestUpdateNotify(this)); + this.getOwner().getSession().send(new PacketCodexDataUpdateNotify(this)); + + this.save(); + + // Add rewards + MainQuestData mainQuestData = GameData.getMainQuestDataMap().get(this.getParentQuestId()); + for (int rewardId : mainQuestData.getRewardIdList()) { + RewardData rewardData = GameData.getRewardDataMap().get(rewardId); + + if (rewardData == null) { + continue; + } + + getOwner().getInventory().addItemParamDatas(rewardData.getRewardItemList(), ActionReason.QuestReward); + } + } + + public void save() { + DatabaseHelper.saveQuest(this); + } + + public ParentQuest toProto() { + ParentQuest.Builder proto = ParentQuest.newBuilder() + .setParentQuestId(getParentQuestId()) + .setIsFinished(isFinished()) + .setParentQuestState(getState().getValue()); + + for (GameQuest quest : this.getChildQuests().values()) { + ChildQuest childQuest = ChildQuest.newBuilder() + .setQuestId(quest.getQuestId()) + .setState(quest.getState().getValue()) + .build(); + + proto.addChildQuestList(childQuest); + } + + if (getQuestVars() != null) { + for (int i : getQuestVars()) { + proto.addQuestVar(i); + } + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/GameQuest.java b/src/main/java/emu/grasscutter/game/quest/GameQuest.java new file mode 100644 index 000000000..57d8655fb --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/GameQuest.java @@ -0,0 +1,226 @@ +package emu.grasscutter.game.quest; + +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.binout.MainQuestData.SubQuestData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.net.proto.QuestOuterClass.Quest; +import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.utils.Utils; + +@Entity +public class GameQuest { + @Transient private GameMainQuest mainQuest; + @Transient private QuestData questData; + + private int questId; + private int mainQuestId; + private QuestState state; + + private int startTime; + private int acceptTime; + private int finishTime; + + private int[] finishProgressList; + private int[] failProgressList; + + @Deprecated // Morphia only. Do not use. + public GameQuest() {} + + public GameQuest(GameMainQuest mainQuest, QuestData questData) { + this.mainQuest = mainQuest; + this.questId = questData.getId(); + this.mainQuestId = questData.getMainId(); + this.questData = questData; + this.acceptTime = Utils.getCurrentSeconds(); + this.startTime = this.acceptTime; + this.state = QuestState.QUEST_STATE_UNFINISHED; + + if (questData.getFinishCond() != null && questData.getAcceptCond().length != 0) { + this.finishProgressList = new int[questData.getFinishCond().length]; + } + + if (questData.getFailCond() != null && questData.getFailCond().length != 0) { + this.failProgressList = new int[questData.getFailCond().length]; + } + + this.mainQuest.getChildQuests().put(this.questId, this); + } + + public GameMainQuest getMainQuest() { + return mainQuest; + } + + public void setMainQuest(GameMainQuest mainQuest) { + this.mainQuest = mainQuest; + } + + public Player getOwner() { + return getMainQuest().getOwner(); + } + + public int getQuestId() { + return questId; + } + + public int getMainQuestId() { + return mainQuestId; + } + + public QuestData getData() { + return questData; + } + + public void setConfig(QuestData config) { + if (this.getQuestId() != config.getId()) return; + this.questData = config; + } + + public QuestState getState() { + return state; + } + + public void setState(QuestState state) { + this.state = state; + } + + public int getStartTime() { + return startTime; + } + + public void setStartTime(int startTime) { + this.startTime = startTime; + } + + public int getAcceptTime() { + return acceptTime; + } + + public void setAcceptTime(int acceptTime) { + this.acceptTime = acceptTime; + } + + public int getFinishTime() { + return finishTime; + } + + public void setFinishTime(int finishTime) { + this.finishTime = finishTime; + } + + public int[] getFinishProgressList() { + return finishProgressList; + } + + public void setFinishProgress(int index, int value) { + finishProgressList[index] = value; + } + + public int[] getFailProgressList() { + return failProgressList; + } + + public void setFailProgress(int index, int value) { + failProgressList[index] = value; + } + + public void finish() { + this.state = QuestState.QUEST_STATE_FINISHED; + this.finishTime = Utils.getCurrentSeconds(); + + if (this.getFinishProgressList() != null) { + for (int i = 0 ; i < getFinishProgressList().length; i++) { + getFinishProgressList()[i] = 1; + } + } + + this.getOwner().getSession().send(new PacketQuestProgressUpdateNotify(this)); + this.getOwner().getSession().send(new PacketQuestListUpdateNotify(this)); + + if (this.getData().finishParent()) { + // This quest finishes the questline - the main quest will also save the quest to db so we dont have to call save() here + this.getMainQuest().finish(); + } else { + // Try and accept other quests if possible + this.tryAcceptQuestLine(); + this.save(); + } + } + + public boolean tryAcceptQuestLine() { + try { + MainQuestData questConfig = GameData.getMainQuestDataMap().get(this.getMainQuestId()); + + for (SubQuestData subQuest : questConfig.getSubQuests()) { + GameQuest quest = getMainQuest().getChildQuestById(subQuest.getSubId()); + + if (quest == null) { + QuestData questData = GameData.getQuestDataMap().get(subQuest.getSubId()); + + if (questData == null || questData.getAcceptCond() == null + || questData.getAcceptCond().length == 0) { + continue; + } + + int[] accept = new int[questData.getAcceptCond().length]; + + // TODO + for (int i = 0; i < questData.getAcceptCond().length; i++) { + QuestCondition condition = questData.getAcceptCond()[i]; + boolean result = getOwner().getServer().getQuestHandler().triggerCondition(this, condition, + condition.getParam()); + + accept[i] = result ? 1 : 0; + } + + boolean shouldAccept = LogicType.calculate(questData.getAcceptCondComb(), accept); + + if (shouldAccept) { + this.getOwner().getQuestManager().addQuest(questData.getId()); + } + } + } + } catch (Exception e) { + Grasscutter.getLogger().error("An error occurred while trying to accept quest.", e); + } + + return false; + } + + public void save() { + getMainQuest().save(); + } + + public Quest toProto() { + Quest.Builder proto = Quest.newBuilder() + .setQuestId(this.getQuestId()) + .setState(this.getState().getValue()) + .setParentQuestId(this.getMainQuestId()) + .setStartTime(this.getStartTime()) + .setStartGameTime(438) + .setAcceptTime(this.getAcceptTime()); + + if (this.getFinishProgressList() != null) { + for (int i : this.getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (this.getFailProgressList() != null) { + for (int i : this.getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + return proto.build(); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java new file mode 100644 index 000000000..838cb301f --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java @@ -0,0 +1,186 @@ +package emu.grasscutter.game.quest; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.enums.LogicType; +import emu.grasscutter.game.quest.enums.QuestState; +import emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify; +import emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify; +import emu.grasscutter.server.packet.send.PacketServerCondMeetQuestListUpdateNotify; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public class QuestManager { + private final Player player; + private final Int2ObjectMap quests; + + public QuestManager(Player player) { + this.player = player; + this.quests = new Int2ObjectOpenHashMap<>(); + } + + public Player getPlayer() { + return player; + } + + public Int2ObjectMap getQuests() { + return quests; + } + + public GameMainQuest getMainQuestById(int mainQuestId) { + return getQuests().get(mainQuestId); + } + + public GameQuest getQuestById(int questId) { + QuestData questConfig = GameData.getQuestDataMap().get(questId); + if (questConfig == null) { + return null; + } + + GameMainQuest mainQuest = getQuests().get(questConfig.getMainId()); + + if (mainQuest == null) { + return null; + } + + return mainQuest.getChildQuests().get(questId); + } + + public void forEachQuest(Consumer callback) { + for (GameMainQuest mainQuest : getQuests().values()) { + for (GameQuest quest : mainQuest.getChildQuests().values()) { + callback.accept(quest); + } + } + } + + public void forEachMainQuest(Consumer callback) { + for (GameMainQuest mainQuest : getQuests().values()) { + callback.accept(mainQuest); + } + } + + // TODO + public void forEachActiveQuest(Consumer callback) { + for (GameMainQuest mainQuest : getQuests().values()) { + for (GameQuest quest : mainQuest.getChildQuests().values()) { + if (quest.getState() != QuestState.QUEST_STATE_FINISHED) { + callback.accept(quest); + } + } + } + } + + public GameMainQuest addMainQuest(QuestData questConfig) { + GameMainQuest mainQuest = new GameMainQuest(getPlayer(), questConfig.getMainId()); + getQuests().put(mainQuest.getParentQuestId(), mainQuest); + + getPlayer().sendPacket(new PacketFinishedParentQuestUpdateNotify(mainQuest)); + + return mainQuest; + } + + public GameQuest addQuest(int questId) { + QuestData questConfig = GameData.getQuestDataMap().get(questId); + if (questConfig == null) { + return null; + } + + // Main quest + GameMainQuest mainQuest = this.getMainQuestById(questConfig.getMainId()); + + // Create main quest if it doesnt exist + if (mainQuest == null) { + mainQuest = addMainQuest(questConfig); + } + + // Sub quest + GameQuest quest = mainQuest.getChildQuestById(questId); + + if (quest != null) { + return null; + } + + // Create + quest = new GameQuest(mainQuest, questConfig); + + // Save main quest + mainQuest.save(); + + // Send packet + getPlayer().sendPacket(new PacketQuestListUpdateNotify(quest)); + + return quest; + } + + public void triggerEvent(QuestTrigger condType, int... params) { + Set changedQuests = new HashSet<>(); + + this.forEachActiveQuest(quest -> { + QuestData data = quest.getData(); + + for (int i = 0; i < data.getFinishCond().length; i++) { + if (quest.getFinishProgressList() == null + || quest.getFinishProgressList().length == 0 + || quest.getFinishProgressList()[i] == 1) { + continue; + } + + QuestCondition condition = data.getFinishCond()[i]; + + if (condition.getType() != condType) { + continue; + } + + boolean result = getPlayer().getServer().getQuestHandler().triggerContent(quest, condition, params); + + if (result) { + quest.getFinishProgressList()[i] = 1; + + changedQuests.add(quest); + } + } + }); + + for (GameQuest quest : changedQuests) { + LogicType logicType = quest.getData().getFailCondComb(); + int[] progress = quest.getFinishProgressList(); + + // Handle logical comb + boolean finish = LogicType.calculate(logicType, progress); + + // Finish + if (finish) { + quest.finish(); + } else { + getPlayer().sendPacket(new PacketQuestProgressUpdateNotify(quest)); + quest.save(); + } + } + } + + public void loadFromDatabase() { + List quests = DatabaseHelper.getAllQuests(getPlayer()); + + for (GameMainQuest mainQuest : quests) { + mainQuest.setOwner(this.getPlayer()); + + for (GameQuest quest : mainQuest.getChildQuests().values()) { + quest.setMainQuest(mainQuest); + quest.setConfig(GameData.getQuestDataMap().get(quest.getQuestId())); + } + + this.getQuests().put(mainQuest.getParentQuestId(), mainQuest); + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/QuestValue.java b/src/main/java/emu/grasscutter/game/quest/QuestValue.java new file mode 100644 index 000000000..42b868fc8 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/QuestValue.java @@ -0,0 +1,11 @@ +package emu.grasscutter.game.quest; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import emu.grasscutter.game.quest.enums.QuestTrigger; + +@Retention(RetentionPolicy.RUNTIME) +public @interface QuestValue { + QuestTrigger value(); +} diff --git a/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java new file mode 100644 index 000000000..b48194dd9 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/ServerQuestHandler.java @@ -0,0 +1,89 @@ +package emu.grasscutter.game.quest; + +import java.util.Set; + +import org.reflections.Reflections; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +@SuppressWarnings("unchecked") +public class ServerQuestHandler { + private final Int2ObjectMap condHandlers; + private final Int2ObjectMap contHandlers; + private final Int2ObjectMap execHandlers; + + public ServerQuestHandler() { + this.condHandlers = new Int2ObjectOpenHashMap<>(); + this.contHandlers = new Int2ObjectOpenHashMap<>(); + this.execHandlers = new Int2ObjectOpenHashMap<>(); + + this.registerHandlers(); + } + + public void registerHandlers() { + this.registerHandlers(this.condHandlers, "emu.grasscutter.game.quest.conditions"); + this.registerHandlers(this.contHandlers, "emu.grasscutter.game.quest.content"); + this.registerHandlers(this.execHandlers, "emu.grasscutter.game.quest.exec"); + } + + public void registerHandlers(Int2ObjectMap map, String packageName) { + Reflections reflections = new Reflections(packageName); + Set handlerClasses = reflections.getSubTypesOf(QuestBaseHandler.class); + + for (Object obj : handlerClasses) { + this.registerPacketHandler(map, (Class) obj); + } + } + + public void registerPacketHandler(Int2ObjectMap map, Class handlerClass) { + try { + QuestValue opcode = handlerClass.getAnnotation(QuestValue.class); + + if (opcode == null || opcode.value().getValue() <= 0) { + return; + } + + QuestBaseHandler packetHandler = (QuestBaseHandler) handlerClass.newInstance(); + + map.put(opcode.value().getValue(), packetHandler); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // TODO make cleaner + + public boolean triggerCondition(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = condHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getData() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } + + public boolean triggerContent(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = contHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getData() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } + + public boolean triggerExec(GameQuest quest, QuestCondition condition, int... params) { + QuestBaseHandler handler = execHandlers.get(condition.getType().getValue()); + + if (handler == null || quest.getData() == null) { + return false; + } + + return handler.execute(quest, condition, params); + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java new file mode 100644 index 000000000..86df72b34 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/BaseCondition.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) +public class BaseCondition extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java new file mode 100644 index 000000000..e15ce8ed7 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionPlayerLevelEqualGreater.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER) +public class ConditionPlayerLevelEqualGreater extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return quest.getOwner().getLevel() >= params[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java new file mode 100644 index 000000000..bcf90145b --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/conditions/ConditionStateEqual.java @@ -0,0 +1,23 @@ +package emu.grasscutter.game.quest.conditions; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_COND_STATE_EQUAL) +public class ConditionStateEqual extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]); + + if (checkQuest != null) { + return checkQuest.getState().getValue() == params[1]; + } + + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java new file mode 100644 index 000000000..e2c7abdc8 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/BaseContent.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_NONE) +public class BaseContent extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java new file mode 100644 index 000000000..3c17bccde --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentCompleteTalk.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK) +public class ContentCompleteTalk extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return condition.getParam()[0] == params[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java new file mode 100644 index 000000000..e331f48e0 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentEnterDungeon.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON) +public class ContentEnterDungeon extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return condition.getParam()[0] == params[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java b/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java new file mode 100644 index 000000000..305808112 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/content/ContentFinishPlot.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.content; + +import emu.grasscutter.game.quest.QuestValue; +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.game.quest.enums.QuestTrigger; +import emu.grasscutter.game.quest.handlers.QuestBaseHandler; + +@QuestValue(QuestTrigger.QUEST_CONTENT_FINISH_PLOT) +public class ContentFinishPlot extends QuestBaseHandler { + + @Override + public boolean execute(GameQuest quest, QuestCondition condition, int... params) { + return condition.getParam()[0] == params[0]; + } + +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java new file mode 100644 index 000000000..12677ee0d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/LogicType.java @@ -0,0 +1,43 @@ +package emu.grasscutter.game.quest.enums; + +import java.util.Arrays; + +public enum LogicType { + LOGIC_NONE (0), + LOGIC_AND (1), + LOGIC_OR (2), + LOGIC_NOT (3), + LOGIC_A_AND_ETCOR (4), + LOGIC_A_AND_B_AND_ETCOR (5), + LOGIC_A_OR_ETCAND (6), + LOGIC_A_OR_B_OR_ETCAND (7), + LOGIC_A_AND_B_OR_ETCAND (8); + + private final int value; + + LogicType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } + + public static boolean calculate(LogicType logicType, int[] progress) { + if (logicType == null) { + return progress[0] == 1; + } + + switch (logicType) { + case LOGIC_AND -> { + return Arrays.stream(progress).allMatch(i -> i == 1); + } + case LOGIC_OR -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + default -> { + return Arrays.stream(progress).anyMatch(i -> i == 1); + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java new file mode 100644 index 000000000..6c7805f8d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/ParentQuestState.java @@ -0,0 +1,18 @@ +package emu.grasscutter.game.quest.enums; + +public enum ParentQuestState { + PARENT_QUEST_STATE_NONE (0), + PARENT_QUEST_STATE_FINISHED (1), + PARENT_QUEST_STATE_FAILED (2), + PARENT_QUEST_STATE_CANCELED (3); + + private final int value; + + ParentQuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java new file mode 100644 index 000000000..45915c6b7 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestGuideType.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestGuideType { + QUEST_GUIDE_NONE (0), + QUEST_GUIDE_LOCATION (1), + QUEST_GUIDE_NPC (2); + + private final int value; + + QuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java new file mode 100644 index 000000000..014c1ee06 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestShowType.java @@ -0,0 +1,16 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestShowType { + QUEST_SHOW (0), + QUEST_HIDDEN (1); + + private final int value; + + QuestShowType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java new file mode 100644 index 000000000..d258a2582 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestState.java @@ -0,0 +1,19 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestState { + QUEST_STATE_NONE (0), + QUEST_STATE_UNSTARTED (1), + QUEST_STATE_UNFINISHED (2), + QUEST_STATE_FINISHED (3), + QUEST_STATE_FAILED (4); + + private final int value; + + QuestState(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java new file mode 100644 index 000000000..def3a399d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestTrigger.java @@ -0,0 +1,235 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestTrigger { + QUEST_COND_NONE (0), + QUEST_COND_STATE_EQUAL (1), + QUEST_COND_STATE_NOT_EQUAL (2), + QUEST_COND_PACK_HAVE_ITEM (3), + QUEST_COND_AVATAR_ELEMENT_EQUAL (4), + QUEST_COND_AVATAR_ELEMENT_NOT_EQUAL (5), + QUEST_COND_AVATAR_CAN_CHANGE_ELEMENT (6), + QUEST_COND_CITY_LEVEL_EQUAL_GREATER (7), + QUEST_COND_ITEM_NUM_LESS_THAN (8), + QUEST_COND_DAILY_TASK_START (9), + QUEST_COND_OPEN_STATE_EQUAL (10), + QUEST_COND_DAILY_TASK_OPEN (11), + QUEST_COND_DAILY_TASK_REWARD_CAN_GET (12), + QUEST_COND_DAILY_TASK_REWARD_RECEIVED (13), + QUEST_COND_PLAYER_LEVEL_REWARD_CAN_GET (14), + QUEST_COND_EXPLORATION_REWARD_CAN_GET (15), + QUEST_COND_IS_WORLD_OWNER (16), + QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER (17), + QUEST_COND_SCENE_AREA_UNLOCKED (18), + QUEST_COND_ITEM_GIVING_ACTIVED (19), + QUEST_COND_ITEM_GIVING_FINISHED (20), + QUEST_COND_IS_DAYTIME (21), + QUEST_COND_CURRENT_AVATAR (22), + QUEST_COND_CURRENT_AREA (23), + QUEST_COND_QUEST_VAR_EQUAL (24), + QUEST_COND_QUEST_VAR_GREATER (25), + QUEST_COND_QUEST_VAR_LESS (26), + QUEST_COND_FORGE_HAVE_FINISH (27), + QUEST_COND_DAILY_TASK_IN_PROGRESS (28), + QUEST_COND_DAILY_TASK_FINISHED (29), + QUEST_COND_ACTIVITY_COND (30), + QUEST_COND_ACTIVITY_OPEN (31), + QUEST_COND_DAILY_TASK_VAR_GT (32), + QUEST_COND_DAILY_TASK_VAR_EQ (33), + QUEST_COND_DAILY_TASK_VAR_LT (34), + QUEST_COND_BARGAIN_ITEM_GT (35), + QUEST_COND_BARGAIN_ITEM_EQ (36), + QUEST_COND_BARGAIN_ITEM_LT (37), + QUEST_COND_COMPLETE_TALK (38), + QUEST_COND_NOT_HAVE_BLOSSOM_TALK (39), + QUEST_COND_IS_CUR_BLOSSOM_TALK (40), + QUEST_COND_QUEST_NOT_RECEIVE (41), + QUEST_COND_QUEST_SERVER_COND_VALID (42), + QUEST_COND_ACTIVITY_CLIENT_COND (43), + QUEST_COND_QUEST_GLOBAL_VAR_EQUAL (44), + QUEST_COND_QUEST_GLOBAL_VAR_GREATER (45), + QUEST_COND_QUEST_GLOBAL_VAR_LESS (46), + QUEST_COND_PERSONAL_LINE_UNLOCK (47), + QUEST_COND_CITY_REPUTATION_REQUEST (48), + QUEST_COND_MAIN_COOP_START (49), + QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT (50), + QUEST_COND_CITY_REPUTATION_LEVEL (51), + QUEST_COND_CITY_REPUTATION_UNLOCK (52), + QUEST_COND_LUA_NOTIFY (53), + QUEST_COND_CUR_CLIMATE (54), + QUEST_COND_ACTIVITY_END (55), + QUEST_COND_COOP_POINT_RUNNING (56), + QUEST_COND_GADGET_TALK_STATE_EQUAL (57), + QUEST_COND_AVATAR_FETTER_GT (58), + QUEST_COND_AVATAR_FETTER_EQ (59), + QUEST_COND_AVATAR_FETTER_LT (60), + QUEST_COND_NEW_HOMEWORLD_MOUDLE_UNLOCK (61), + QUEST_COND_NEW_HOMEWORLD_LEVEL_REWARD (62), + QUEST_COND_NEW_HOMEWORLD_MAKE_FINISH (63), + QUEST_COND_HOMEWORLD_NPC_EVENT (64), + QUEST_COND_TIME_VAR_GT_EQ (65), + QUEST_COND_TIME_VAR_PASS_DAY (66), + QUEST_COND_HOMEWORLD_NPC_NEW_TALK (67), + QUEST_COND_PLAYER_CHOOSE_MALE (68), + QUEST_COND_HISTORY_GOT_ANY_ITEM (69), + QUEST_COND_LEARNED_RECIPE (70), + QUEST_COND_LUNARITE_REGION_UNLOCKED (71), + QUEST_COND_LUNARITE_HAS_REGION_HINT_COUNT (72), + QUEST_COND_LUNARITE_COLLECT_FINISH (73), + QUEST_COND_LUNARITE_MARK_ALL_FINISH (74), + QUEST_COND_NEW_HOMEWORLD_SHOP_ITEM (75), + QUEST_COND_SCENE_POINT_UNLOCK (76), + QUEST_COND_SCENE_LEVEL_TAG_EQ (77), + + QUEST_CONTENT_NONE (0), + QUEST_CONTENT_KILL_MONSTER (1), + QUEST_CONTENT_COMPLETE_TALK (2), + QUEST_CONTENT_MONSTER_DIE (3), + QUEST_CONTENT_FINISH_PLOT (4), + QUEST_CONTENT_OBTAIN_ITEM (5), + QUEST_CONTENT_TRIGGER_FIRE (6), + QUEST_CONTENT_CLEAR_GROUP_MONSTER (7), + QUEST_CONTENT_NOT_FINISH_PLOT (8), + QUEST_CONTENT_ENTER_DUNGEON (9), + QUEST_CONTENT_ENTER_MY_WORLD (10), + QUEST_CONTENT_FINISH_DUNGEON (11), + QUEST_CONTENT_DESTROY_GADGET (12), + QUEST_CONTENT_OBTAIN_MATERIAL_WITH_SUBTYPE (13), + QUEST_CONTENT_NICK_NAME (14), + QUEST_CONTENT_WORKTOP_SELECT (15), + QUEST_CONTENT_SEAL_BATTLE_RESULT (16), + QUEST_CONTENT_ENTER_ROOM (17), + QUEST_CONTENT_GAME_TIME_TICK (18), + QUEST_CONTENT_FAIL_DUNGEON (19), + QUEST_CONTENT_LUA_NOTIFY (20), + QUEST_CONTENT_TEAM_DEAD (21), + QUEST_CONTENT_COMPLETE_ANY_TALK (22), + QUEST_CONTENT_UNLOCK_TRANS_POINT (23), + QUEST_CONTENT_ADD_QUEST_PROGRESS (24), + QUEST_CONTENT_INTERACT_GADGET (25), + QUEST_CONTENT_DAILY_TASK_COMP_FINISH (26), + QUEST_CONTENT_FINISH_ITEM_GIVING (27), + QUEST_CONTENT_SKILL (107), + QUEST_CONTENT_CITY_LEVEL_UP (109), + QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER (110), + QUEST_CONTENT_ITEM_LESS_THAN (111), + QUEST_CONTENT_PLAYER_LEVEL_UP (112), + QUEST_CONTENT_DUNGEON_OPEN_STATUE (113), + QUEST_CONTENT_UNLOCK_AREA (114), + QUEST_CONTENT_OPEN_CHEST_WITH_GADGET_ID (115), + QUEST_CONTENT_UNLOCK_TRANS_POINT_WITH_TYPE (116), + QUEST_CONTENT_FINISH_DAILY_DUNGEON (117), + QUEST_CONTENT_FINISH_WEEKLY_DUNGEON (118), + QUEST_CONTENT_QUEST_VAR_EQUAL (119), + QUEST_CONTENT_QUEST_VAR_GREATER (120), + QUEST_CONTENT_QUEST_VAR_LESS (121), + QUEST_CONTENT_OBTAIN_VARIOUS_ITEM (122), + QUEST_CONTENT_FINISH_TOWER_LEVEL (123), + QUEST_CONTENT_BARGAIN_SUCC (124), + QUEST_CONTENT_BARGAIN_FAIL (125), + QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN (126), + QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED (127), + QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT (128), + QUEST_CONTENT_ANY_MANUAL_TRANSPORT (129), + QUEST_CONTENT_USE_ITEM (130), + QUEST_CONTENT_MAIN_COOP_ENTER_ANY_SAVE_POINT (131), + QUEST_CONTENT_ENTER_MY_HOME_WORLD (132), + QUEST_CONTENT_ENTER_MY_WORLD_SCENE (133), + QUEST_CONTENT_TIME_VAR_GT_EQ (134), + QUEST_CONTENT_TIME_VAR_PASS_DAY (135), + QUEST_CONTENT_QUEST_STATE_EQUAL (136), + QUEST_CONTENT_QUEST_STATE_NOT_EQUAL (137), + QUEST_CONTENT_UNLOCKED_RECIPE (138), + QUEST_CONTENT_NOT_UNLOCKED_RECIPE (139), + QUEST_CONTENT_FISHING_SUCC (140), + QUEST_CONTENT_ENTER_ROGUE_DUNGEON (141), + QUEST_CONTENT_USE_WIDGET (142), + QUEST_CONTENT_CAPTURE_SUCC (143), + QUEST_CONTENT_CAPTURE_USE_CAPTURETAG_LIST (144), + QUEST_CONTENT_CAPTURE_USE_MATERIAL_LIST (145), + QUEST_CONTENT_ENTER_VEHICLE (147), + QUEST_CONTENT_SCENE_LEVEL_TAG_EQ (148), + QUEST_CONTENT_LEAVE_SCENE (149), + QUEST_CONTENT_LEAVE_SCENE_RANGE (150), + QUEST_CONTENT_IRODORI_FINISH_FLOWER_COMBINATION (151), + QUEST_CONTENT_IRODORI_POETRY_REACH_MIN_PROGRESS (152), + QUEST_CONTENT_IRODORI_POETRY_FINISH_FILL_POETRY (153), + + QUEST_EXEC_NONE (0), + QUEST_EXEC_DEL_PACK_ITEM (1), + QUEST_EXEC_UNLOCK_POINT (2), + QUEST_EXEC_UNLOCK_AREA (3), + QUEST_EXEC_UNLOCK_FORCE (4), + QUEST_EXEC_LOCK_FORCE (5), + QUEST_EXEC_CHANGE_AVATAR_ELEMET (6), + QUEST_EXEC_REFRESH_GROUP_MONSTER (7), + QUEST_EXEC_SET_IS_FLYABLE (8), + QUEST_EXEC_SET_IS_WEATHER_LOCKED (9), + QUEST_EXEC_SET_IS_GAME_TIME_LOCKED (10), + QUEST_EXEC_SET_IS_TRANSFERABLE (11), + QUEST_EXEC_GRANT_TRIAL_AVATAR (12), + QUEST_EXEC_OPEN_BORED (13), + QUEST_EXEC_ROLLBACK_QUEST (14), + QUEST_EXEC_NOTIFY_GROUP_LUA (15), + QUEST_EXEC_SET_OPEN_STATE (16), + QUEST_EXEC_LOCK_POINT (17), + QUEST_EXEC_DEL_PACK_ITEM_BATCH (18), + QUEST_EXEC_REFRESH_GROUP_SUITE (19), + QUEST_EXEC_REMOVE_TRIAL_AVATAR (20), + QUEST_EXEC_SET_GAME_TIME (21), + QUEST_EXEC_SET_WEATHER_GADGET (22), + QUEST_EXEC_ADD_QUEST_PROGRESS (23), + QUEST_EXEC_NOTIFY_DAILY_TASK (24), + QUEST_EXEC_CREATE_PATTERN_GROUP (25), + QUEST_EXEC_REMOVE_PATTERN_GROUP (26), + QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM (27), + QUEST_EXEC_ACTIVE_ITEM_GIVING (28), + QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM (29), + QUEST_EXEC_ROLLBACK_PARENT_QUEST (30), + QUEST_EXEC_LOCK_AVATAR_TEAM (31), + QUEST_EXEC_UNLOCK_AVATAR_TEAM (32), + QUEST_EXEC_UPDATE_PARENT_QUEST_REWARD_INDEX (33), + QUEST_EXEC_SET_DAILY_TASK_VAR (34), + QUEST_EXEC_INC_DAILY_TASK_VAR (35), + QUEST_EXEC_DEC_DAILY_TASK_VAR (36), + QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE (37), + QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE (38), + QUEST_EXEC_ADD_CUR_AVATAR_ENERGY (39), + QUEST_EXEC_START_BARGAIN (41), + QUEST_EXEC_STOP_BARGAIN (42), + QUEST_EXEC_SET_QUEST_GLOBAL_VAR (43), + QUEST_EXEC_INC_QUEST_GLOBAL_VAR (44), + QUEST_EXEC_DEC_QUEST_GLOBAL_VAR (45), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP (46), + QUEST_EXEC_UNREGISTER_DYNAMIC_GROUP (47), + QUEST_EXEC_SET_QUEST_VAR (48), + QUEST_EXEC_INC_QUEST_VAR (49), + QUEST_EXEC_DEC_QUEST_VAR (50), + QUEST_EXEC_RANDOM_QUEST_VAR (51), + QUEST_EXEC_ACTIVATE_SCANNING_PIC (52), + QUEST_EXEC_RELOAD_SCENE_TAG (53), + QUEST_EXEC_REGISTER_DYNAMIC_GROUP_ONLY (54), + QUEST_EXEC_CHANGE_SKILL_DEPOT (55), + QUEST_EXEC_ADD_SCENE_TAG (56), + QUEST_EXEC_DEL_SCENE_TAG (57), + QUEST_EXEC_INIT_TIME_VAR (58), + QUEST_EXEC_CLEAR_TIME_VAR (59), + QUEST_EXEC_MODIFY_CLIMATE_AREA (60), + QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM (61), + QUEST_EXEC_CHANGE_MAP_AREA_STATE (62), + QUEST_EXEC_DEACTIVE_ITEM_GIVING (63), + QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG (64), + QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE (65), + QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE (66), + QUEST_EXEC_FAIL_MAINCOOP (67), + QUEST_EXEC_MODIFY_WEATHER_AREA (68); + + private final int value; + + QuestTrigger(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java new file mode 100644 index 000000000..fbbac2ae0 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/QuestType.java @@ -0,0 +1,22 @@ +package emu.grasscutter.game.quest.enums; + +public enum QuestType { + AQ (0), + FQ (1), + LQ (2), + EQ (3), + DQ (4), + IQ (5), + VQ (6), + WQ (7); + + private final int value; + + QuestType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java new file mode 100644 index 000000000..d4e985592 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/enums/ShowQuestGuideType.java @@ -0,0 +1,17 @@ +package emu.grasscutter.game.quest.enums; + +public enum ShowQuestGuideType { + QUEST_GUIDE_ITEM_ENABLE (0), + QUEST_GUIDE_ITEM_DISABLE (1), + QUEST_GUIDE_ITEM_MOVE_HIDE (2); + + private final int value; + + ShowQuestGuideType(int id) { + this.value = id; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java new file mode 100644 index 000000000..815906f81 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/quest/handlers/QuestBaseHandler.java @@ -0,0 +1,10 @@ +package emu.grasscutter.game.quest.handlers; + +import emu.grasscutter.data.excels.QuestData.QuestCondition; +import emu.grasscutter.game.quest.GameQuest; + +public abstract class QuestBaseHandler { + + public abstract boolean execute(GameQuest quest, QuestCondition condition, int... params); + +} diff --git a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java index ebbeea2cd..4902dbb65 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopInfo.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopInfo.java @@ -1,7 +1,7 @@ package emu.grasscutter.game.shop; import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.def.ShopGoodsData; +import emu.grasscutter.data.excels.ShopGoodsData; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/emu/grasscutter/game/shop/ShopManager.java b/src/main/java/emu/grasscutter/game/shop/ShopManager.java index 2c5d014f5..1010e14a8 100644 --- a/src/main/java/emu/grasscutter/game/shop/ShopManager.java +++ b/src/main/java/emu/grasscutter/game/shop/ShopManager.java @@ -2,20 +2,25 @@ package emu.grasscutter.game.shop; import com.google.gson.reflect.TypeToken; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; -import emu.grasscutter.data.def.ShopGoodsData; +import emu.grasscutter.data.excels.ShopGoodsData; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import static emu.grasscutter.Configuration.*; + public class ShopManager { private final GameServer server; @@ -56,7 +61,7 @@ public class ShopManager { } private void loadShop() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Shop.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("Shop.json"))) { getShopData().clear(); List banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType()); if(banners.size() > 0) { @@ -84,7 +89,7 @@ public class ShopManager { Grasscutter.getLogger().error("Unable to load shop data. Shop data size is 0."); } - if (Grasscutter.getConfig().getGameServerOptions().EnableOfficialShop) { + if (GAME_OPTIONS.enableShopItems) { GameData.getShopGoodsDataEntries().forEach((k, v) -> { if (!getShopData().containsKey(k.intValue())) getShopData().put(k.intValue(), new ArrayList<>()); @@ -100,7 +105,7 @@ public class ShopManager { } private void loadShopChest() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChest.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("ShopChest.json"))) { getShopChestData().clear(); List shopChestTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestTable.class).getType()); if (shopChestTableList.size() > 0) { @@ -115,7 +120,7 @@ public class ShopManager { } private void loadShopChestBatchUse() { - try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChestBatchUse.json")) { + try (Reader fileReader = new InputStreamReader(DataLoader.load("ShopChestBatchUse.json"))) { getShopChestBatchUseData().clear(); List shopChestBatchUseTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestBatchUseTable.class).getType()); if (shopChestBatchUseTableList.size() > 0) { diff --git a/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java new file mode 100644 index 000000000..5a65f63ed --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java @@ -0,0 +1,64 @@ +package emu.grasscutter.game.tower; + +import dev.morphia.annotations.Entity; + +import java.util.HashMap; +import java.util.Map; + +@Entity +public class TowerLevelRecord { + /** + * floorId in config + */ + private int floorId; + /** + * LevelId - Stars + */ + private Map passedLevelMap; + + private int floorStarRewardProgress; + + public TowerLevelRecord setLevelStars(int levelId, int stars){ + passedLevelMap.put(levelId, stars); + return this; + } + + public int getStarCount() { + return passedLevelMap.values().stream().mapToInt(Integer::intValue).sum(); + } + + public TowerLevelRecord(){ + + } + + public TowerLevelRecord(int floorId){ + this.floorId = floorId; + this.passedLevelMap = new HashMap<>(); + this.floorStarRewardProgress = 0; + } + + public int getFloorId() { + return floorId; + } + + public void setFloorId(int floorId) { + this.floorId = floorId; + } + + public Map getPassedLevelMap() { + return passedLevelMap; + } + + public void setPassedLevelMap(Map passedLevelMap) { + this.passedLevelMap = passedLevelMap; + } + + public int getFloorStarRewardProgress() { + return floorStarRewardProgress; + } + + public void setFloorStarRewardProgress(int floorStarRewardProgress) { + this.floorStarRewardProgress = floorStarRewardProgress; + } + +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index 51f840663..ab5e1cf0c 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -3,15 +3,15 @@ package emu.grasscutter.game.tower; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.TowerLevelData; +import emu.grasscutter.data.excels.TowerLevelData; import emu.grasscutter.game.dungeons.DungeonSettleListener; import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify; - -import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp; +import emu.grasscutter.server.packet.send.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Entity public class TowerManager { @@ -25,11 +25,19 @@ public class TowerManager { this.player = player; } + /** + * the floor players chose + */ private int currentFloorId; private int currentLevel; @Transient private int currentLevelId; + /** + * floorId - Record + */ + private Map recordMap; + @Transient private int entryScene; @@ -37,66 +45,114 @@ public class TowerManager { return currentFloorId; } + public int getCurrentLevelId(){ + return this.currentLevelId + currentLevel; + } + + /** + * form 1-3 + */ + public int getCurrentLevel(){ + return currentLevel + 1; + } private static final List towerDungeonSettleListener = List.of(new TowerDungeonSettleListener()); + + public Map getRecordMap() { + if(recordMap == null){ + recordMap = new HashMap<>(); + recordMap.put(1001, new TowerLevelRecord(1001)); + } + return recordMap; + } + public void teamSelect(int floor, List> towerTeams) { var floorData = GameData.getTowerFloorDataMap().get(floor); this.currentFloorId = floorData.getFloorId(); this.currentLevel = 0; this.currentLevelId = GameData.getTowerLevelDataMap().values().stream() - .filter(x -> x.getLevelId() == floorData.getLevelId() && x.getLevelIndex() == 1) + .filter(x -> x.getLevelGroupId() == floorData.getLevelGroupId() && x.getLevelIndex() == 1) .findFirst() - .map(TowerLevelData::getID) + .map(TowerLevelData::getId) .orElse(0); if (entryScene == 0){ entryScene = player.getSceneId(); } - player.getTeamManager().setupTemporaryTeam(towerTeams); } public void enterLevel(int enterPointId) { - var levelData = GameData.getTowerLevelDataMap().get(currentLevelId + currentLevel); + var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId()); - this.currentLevel++; - var id = levelData.getDungeonId(); + var dungeonId = levelData.getDungeonId(); notifyCurLevelRecordChange(); // use team user choose player.getTeamManager().useTemporaryTeam(0); - player.getServer().getDungeonManager().handoffDungeon(player, id, + player.getServer().getDungeonManager().handoffDungeon(player, dungeonId, towerDungeonSettleListener); // make sure user can exit dungeon correctly player.getScene().setPrevScene(entryScene); player.getScene().setPrevScenePoint(enterPointId); - player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel)); - + player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, getCurrentLevel())); + // stop using skill + player.getSession().send(new PacketCanUseSkillNotify(false)); + // notify the cond of stars + player.getSession().send(new PacketTowerLevelStarCondNotify(currentFloorId, getCurrentLevel())); } public void notifyCurLevelRecordChange(){ - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel)); + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); } - public void notifyCurLevelRecordChangeWhenDone(){ - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel + 1)); + public void notifyCurLevelRecordChangeWhenDone(int stars){ + if(!recordMap.containsKey(currentFloorId)){ + recordMap.put(currentFloorId, + new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(),stars)); + }else{ + recordMap.put(currentFloorId, + recordMap.get(currentFloorId).setLevelStars(getCurrentLevelId(),stars)); + } + + this.currentLevel++; + + if(!hasNextLevel()){ + // set up the next floor + recordMap.putIfAbsent(getNextFloorId(), new TowerLevelRecord(getNextFloorId())); + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(getNextFloorId(), 1)); + }else{ + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); + } } public boolean hasNextLevel(){ return this.currentLevel < 3; } - public int getNextFloorId() { - if(hasNextLevel()){ - return 0; - } - this.currentFloorId++; - return this.currentFloorId; + return player.getServer().getTowerScheduleManager().getNextFloorId(this.currentFloorId); + } + public boolean hasNextFloor(){ + return player.getServer().getTowerScheduleManager().getNextFloorId(this.currentFloorId) > 0; } public void clearEntry() { this.entryScene = 0; } + + public boolean canEnterScheduleFloor(){ + if(!recordMap.containsKey(player.getServer().getTowerScheduleManager().getLastEntranceFloor())){ + return false; + } + return recordMap.get(player.getServer().getTowerScheduleManager().getLastEntranceFloor()) + .getStarCount() >= 6; + } + + public void mirrorTeamSetUp(int teamId) { + // use team user choose + player.getTeamManager().useTemporaryTeam(teamId); + player.sendPacket(new PacketTowerMiddleLevelChangeTeamNotify()); + } } diff --git a/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java new file mode 100644 index 000000000..35afbc7ba --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java @@ -0,0 +1,35 @@ +package emu.grasscutter.game.tower; + +import java.util.Date; + +public class TowerScheduleConfig { + private int scheduleId; + + private Date scheduleStartTime; + private Date nextScheduleChangeTime; + + + public int getScheduleId() { + return scheduleId; + } + + public void setScheduleId(int scheduleId) { + this.scheduleId = scheduleId; + } + + public Date getScheduleStartTime() { + return scheduleStartTime; + } + + public void setScheduleStartTime(Date scheduleStartTime) { + this.scheduleStartTime = scheduleStartTime; + } + + public Date getNextScheduleChangeTime() { + return nextScheduleChangeTime; + } + + public void setNextScheduleChangeTime(Date nextScheduleChangeTime) { + this.nextScheduleChangeTime = nextScheduleChangeTime; + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java b/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java new file mode 100644 index 000000000..a2b8c0396 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java @@ -0,0 +1,87 @@ +package emu.grasscutter.game.tower; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.TowerScheduleData; +import emu.grasscutter.server.game.GameServer; + +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.List; + +import static emu.grasscutter.Configuration.*; + +public class TowerScheduleManager { + private final GameServer gameServer; + + public GameServer getGameServer() { + return gameServer; + } + + public TowerScheduleManager(GameServer gameServer) { + this.gameServer = gameServer; + this.load(); + } + + private TowerScheduleConfig towerScheduleConfig; + + public synchronized void load(){ + try (Reader fileReader = new InputStreamReader(DataLoader.load("TowerSchedule.json"))) { + towerScheduleConfig = Grasscutter.getGsonFactory().fromJson(fileReader, TowerScheduleConfig.class); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load tower schedule config.", e); + } + } + + public TowerScheduleConfig getTowerScheduleConfig() { + return towerScheduleConfig; + } + + public TowerScheduleData getCurrentTowerScheduleData(){ + var data = GameData.getTowerScheduleDataMap().get(towerScheduleConfig.getScheduleId()); + if(data == null){ + Grasscutter.getLogger().error("Could not get current tower schedule data by schedule id {}, please check your resource files", + towerScheduleConfig.getScheduleId()); + } + + return data; + } + + public List getScheduleFloors() { + return getCurrentTowerScheduleData().getSchedules().get(0).getFloorList(); + } + + public int getNextFloorId(int floorId){ + var entranceFloors = getCurrentTowerScheduleData().getEntranceFloorId(); + var scheduleFloors = getScheduleFloors(); + var nextId = 0; + + // find in entrance floors first + for(int i=0;i x.getConfigId() == configId) + .findFirst() + .orElse(null); + } /** * @return the autoCloseTime */ @@ -281,7 +284,7 @@ public class Scene { private void removePlayerAvatars(Player player) { Iterator it = player.getTeamManager().getActiveTeam().iterator(); while (it.hasNext()) { - this.removeEntity(it.next(), VisionType.VISION_REMOVE); + this.removeEntity(it.next(), VisionType.VISION_TYPE_REMOVE); it.remove(); } } @@ -324,7 +327,7 @@ public class Scene { this.addEntityDirectly(entity); } - this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_BORN)); + this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_BORN)); } private GameEntity removeEntityDirectly(GameEntity entity) { @@ -332,7 +335,7 @@ public class Scene { } public void removeEntity(GameEntity entity) { - this.removeEntity(entity, VisionType.VISION_DIE); + this.removeEntity(entity, VisionType.VISION_TYPE_DIE); } public synchronized void removeEntity(GameEntity entity, VisionType visionType) { @@ -345,8 +348,8 @@ public class Scene { public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { this.removeEntityDirectly(oldEntity); this.addEntityDirectly(newEntity); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_REPLACE)); - this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_REPLACE, oldEntity.getId())); + this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_TYPE_REPLACE)); + this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_TYPE_REPLACE, oldEntity.getId())); } public void showOtherEntities(Player player) { @@ -360,7 +363,7 @@ public class Scene { entities.add(entity); } - player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET)); + player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET)); } public void handleAttack(AttackResult result) { @@ -379,30 +382,23 @@ public class Scene { } // Sanity check - if (target.getFightProperties() == null) { - return; - } - - // Lose hp - target.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -result.getDamage()); - - // Check if dead - boolean isDead = false; - if (target.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) { - target.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f); - isDead = true; - } - - // Packets - this.broadcastPacket(new PacketEntityFightPropUpdateNotify(target, FightProperty.FIGHT_PROP_CUR_HP)); - - // Check if dead - if (isDead) { - this.killEntity(target, result.getAttackerId()); - } + target.damage(result.getDamage(), result.getAttackerId()); } public void killEntity(GameEntity target, int attackerId) { + GameEntity attacker = getEntityById(attackerId); + + //Check codex + if (attacker instanceof EntityClientGadget) { + var clientGadgetOwner = getEntityById(((EntityClientGadget) attacker).getOwnerEntityId()); + if(clientGadgetOwner instanceof EntityAvatar) { + ((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL); + } + } + else if (attacker instanceof EntityAvatar) { + ((EntityAvatar) attacker).getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL); + } + // Packet this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD)); @@ -469,7 +465,11 @@ public class Scene { continue; } - EntityMonster entity = new EntityMonster(this, data, entry.getPos(), worldLevelOverride > 0 ? worldLevelOverride : entry.getLevel()); + int level = worldLevelOverride > 0 ? worldLevelOverride + entry.getLevel() - 22 : entry.getLevel(); + level = level >= 100 ? 100 : level; + level = level <= 0 ? 1 : level; + + EntityMonster entity = new EntityMonster(this, data, entry.getPos(), level); entity.getRotation().set(entry.getRot()); entity.setGroupId(entry.getGroup().getGroupId()); entity.setPoseId(entry.getPoseId()); @@ -491,11 +491,11 @@ public class Scene { if (toAdd.size() > 0) { toAdd.stream().forEach(this::addEntityDirectly); - this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN)); + this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_TYPE_BORN)); } if (toRemove.size() > 0) { toRemove.stream().forEach(this::removeEntityDirectly); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE)); + this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); } } @@ -568,7 +568,7 @@ public class Scene { if (toRemove.size() > 0) { toRemove.stream().forEach(this::removeEntityDirectly); - this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE)); + this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); } for (SceneGroup group : block.groups) { @@ -613,7 +613,7 @@ public class Scene { return; } - this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_DIE)); + this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_TYPE_DIE)); } // Broadcasting diff --git a/src/main/java/emu/grasscutter/game/world/World.java b/src/main/java/emu/grasscutter/game/world/World.java index 46c80cd25..ac6ab4a72 100644 --- a/src/main/java/emu/grasscutter/game/world/World.java +++ b/src/main/java/emu/grasscutter/game/world/World.java @@ -1,39 +1,25 @@ package emu.grasscutter.game.world; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; -import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player.SceneLoadState; -import emu.grasscutter.game.props.ClimateType; import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.EntityIdType; -import emu.grasscutter.game.props.FightProperty; -import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.game.props.SceneType; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.DungeonData; -import emu.grasscutter.data.def.SceneData; -import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.EntityClientGadget; -import emu.grasscutter.game.entity.EntityBaseGadget; +import emu.grasscutter.data.excels.DungeonData; +import emu.grasscutter.data.excels.SceneData; import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; -import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.scripts.data.SceneConfig; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.packet.send.PacketDelTeamEntityNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify; import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify; -import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; -import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify; import emu.grasscutter.server.packet.send.PacketScenePlayerInfoNotify; import emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify; import emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify; @@ -207,7 +193,7 @@ public class World implements Iterable { World world = new World(victim); world.addPlayer(victim); - victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPos())); + victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_TYPE_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPos())); } } } @@ -274,14 +260,17 @@ public class World implements Iterable { } // Get enter types - EnterType enterType = EnterType.ENTER_JUMP; + EnterType enterType = EnterType.ENTER_TYPE_JUMP; EnterReason enterReason = EnterReason.TransPoint; if (dungeonData != null) { - enterType = EnterType.ENTER_DUNGEON; + enterType = EnterType.ENTER_TYPE_DUNGEON; enterReason = EnterReason.DungeonEnter; } else if (oldScene == newScene) { - enterType = EnterType.ENTER_GOTO; + enterType = EnterType.ENTER_TYPE_GOTO; + } else if (newScene.getSceneType() == SceneType.SCENE_HOME_WORLD) { + // Home + enterType = EnterType.ENTER_TYPE_SELF_HOME; } // Teleport packet diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java index 8e77504d6..ec737b22f 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java @@ -1,1574 +1,1522 @@ package emu.grasscutter.net.packet; -import java.util.Arrays; -import java.util.List; +import java.util.HashSet; public class PacketOpcodes { // Empty public static final int NONE = 0; // Opcodes - public static final int AbilityChangeNotify = 1179; - public static final int AbilityInvocationFailNotify = 1137; - public static final int AbilityInvocationFixedNotify = 1160; - public static final int AbilityInvocationsNotify = 1133; - public static final int AcceptCityReputationRequestReq = 2845; - public static final int AcceptCityReputationRequestRsp = 2875; - public static final int AchievementAllDataNotify = 1155; - public static final int AchievementUpdateNotify = 1146; - public static final int ActivityCoinInfoNotify = 2056; - public static final int ActivityCondStateChangeNotify = 2162; - public static final int ActivityDisableTransferPointInteractionNotify = 8295; - public static final int ActivityInfoNotify = 2023; - public static final int ActivityPlayOpenAnimNotify = 2164; - public static final int ActivitySaleChangeNotify = 2043; - public static final int ActivityScheduleInfoNotify = 2180; - public static final int ActivityScheduleInfoNotify_1 = 2187; - public static final int ActivitySelectAvatarCardReq = 2153; - public static final int ActivitySelectAvatarCardRsp = 2069; - public static final int ActivityTakeAllScoreRewardReq = 8708; - public static final int ActivityTakeAllScoreRewardRsp = 8836; - public static final int ActivityTakeScoreRewardReq = 8767; - public static final int ActivityTakeScoreRewardRsp = 8445; - public static final int ActivityTakeWatcherRewardBatchReq = 2027; - public static final int ActivityTakeWatcherRewardBatchRsp = 2036; - public static final int ActivityTakeWatcherRewardReq = 2074; - public static final int ActivityTakeWatcherRewardRsp = 2180; - public static final int ActivityTakeWatcherRewardRsp_1 = 2187; - public static final int ActivityUpdateWatcherNotify = 2101; - public static final int AddBlacklistReq = 4067; + public static final int AbilityChangeNotify = 1155; + public static final int AbilityInvocationFailNotify = 1132; + public static final int AbilityInvocationFixedNotify = 1109; + public static final int AbilityInvocationsNotify = 1131; + public static final int AcceptCityReputationRequestReq = 2835; + public static final int AcceptCityReputationRequestRsp = 2849; + public static final int AchievementAllDataNotify = 2668; + public static final int AchievementUpdateNotify = 2659; + public static final int ActivityCoinInfoNotify = 2094; + public static final int ActivityCondStateChangeNotify = 2120; + public static final int ActivityDisableTransferPointInteractionNotify = 8686; + public static final int ActivityInfoNotify = 2125; + public static final int ActivityPlayOpenAnimNotify = 2146; + public static final int ActivitySaleChangeNotify = 2109; + public static final int ActivityScheduleInfoNotify = 2033; + public static final int ActivitySelectAvatarCardReq = 2030; + public static final int ActivitySelectAvatarCardRsp = 2127; + public static final int ActivityTakeAllScoreRewardReq = 8424; + public static final int ActivityTakeAllScoreRewardRsp = 8692; + public static final int ActivityTakeScoreRewardReq = 8321; + public static final int ActivityTakeScoreRewardRsp = 8218; + public static final int ActivityTakeWatcherRewardBatchReq = 2079; + public static final int ActivityTakeWatcherRewardBatchRsp = 2150; + public static final int ActivityTakeWatcherRewardReq = 2090; + public static final int ActivityTakeWatcherRewardRsp = 2025; + public static final int ActivityUpdateWatcherNotify = 2172; + public static final int AddBlacklistReq = 4050; public static final int AddBlacklistRsp = 4020; - public static final int AddFriendNotify = 4026; - public static final int AddNoGachaAvatarCardNotify = 1740; - public static final int AddQuestContentProgressReq = 493; - public static final int AddQuestContentProgressRsp = 444; - public static final int AddRandTaskInfoNotify = 147; - public static final int AddSeenMonsterNotify = 242; - public static final int AdjustWorldLevelReq = 104; - public static final int AdjustWorldLevelRsp = 106; - public static final int AllCoopInfoNotify = 1985; - public static final int AllMarkPointNotify = 3462; - public static final int AllSeenMonsterNotify = 276; - public static final int AllWidgetDataNotify = 4284; - public static final int AnchorPointDataNotify = 4285; - public static final int AnchorPointOpReq = 4298; - public static final int AnchorPointOpRsp = 4263; - public static final int AnimatorForceSetAirMoveNotify = 308; - public static final int AntiAddictNotify = 177; - public static final int ArenaChallengeFinishNotify = 2083; - public static final int AskAddFriendNotify = 4062; - public static final int AskAddFriendReq = 4037; - public static final int AskAddFriendRsp = 4093; - public static final int AsterLargeInfoNotify = 2133; - public static final int AsterLittleInfoNotify = 2058; - public static final int AsterMidCampInfoNotify = 2115; - public static final int AsterMidInfoNotify = 2151; - public static final int AsterMiscInfoNotify = 2098; - public static final int AsterProgressInfoNotify = 2065; - public static final int AvatarAddNotify = 1759; - public static final int AvatarBuffAddNotify = 367; + public static final int AddFriendNotify = 4024; + public static final int AddNoGachaAvatarCardNotify = 1648; + public static final int AddQuestContentProgressReq = 417; + public static final int AddQuestContentProgressRsp = 485; + public static final int AddRandTaskInfoNotify = 116; + public static final int AddSeenMonsterNotify = 251; + public static final int AdjustWorldLevelReq = 195; + public static final int AdjustWorldLevelRsp = 115; + public static final int AllCoopInfoNotify = 1968; + public static final int AllMarkPointNotify = 3195; + public static final int AllSeenMonsterNotify = 226; + public static final int AllWidgetDataNotify = 4273; + public static final int AnchorPointDataNotify = 4268; + public static final int AnchorPointOpReq = 4254; + public static final int AnchorPointOpRsp = 4278; + public static final int AnimatorForceSetAirMoveNotify = 346; + public static final int AntiAddictNotify = 148; + public static final int ArenaChallengeFinishNotify = 2082; + public static final int AskAddFriendNotify = 4038; + public static final int AskAddFriendReq = 4032; + public static final int AskAddFriendRsp = 4017; + public static final int AsterLargeInfoNotify = 2192; + public static final int AsterLittleInfoNotify = 2188; + public static final int AsterMidCampInfoNotify = 2020; + public static final int AsterMidInfoNotify = 2121; + public static final int AsterMiscInfoNotify = 2187; + public static final int AsterProgressInfoNotify = 2193; + public static final int AvatarAddNotify = 1757; + public static final int AvatarBuffAddNotify = 350; public static final int AvatarBuffDelNotify = 320; - public static final int AvatarCardChangeReq = 667; + public static final int AvatarCardChangeReq = 650; public static final int AvatarCardChangeRsp = 620; - public static final int AvatarChangeAnimHashReq = 1630; - public static final int AvatarChangeAnimHashRsp = 1747; - public static final int AvatarChangeCostumeNotify = 1748; - public static final int AvatarChangeCostumeReq = 1650; - public static final int AvatarChangeCostumeRsp = 1632; - public static final int AvatarChangeElementTypeReq = 1741; - public static final int AvatarChangeElementTypeRsp = 1626; - public static final int AvatarDataNotify = 1757; - public static final int AvatarDelNotify = 1624; - public static final int AvatarDieAnimationEndReq = 1635; - public static final int AvatarDieAnimationEndRsp = 1638; - public static final int AvatarEnterElementViewNotify = 366; - public static final int AvatarEquipAffixStartNotify = 1734; - public static final int AvatarEquipChangeNotify = 674; - public static final int AvatarExpeditionAllDataReq = 1721; - public static final int AvatarExpeditionAllDataRsp = 1800; - public static final int AvatarExpeditionCallBackReq = 1607; - public static final int AvatarExpeditionCallBackRsp = 1783; - public static final int AvatarExpeditionDataNotify = 1777; - public static final int AvatarExpeditionGetRewardReq = 1604; - public static final int AvatarExpeditionGetRewardRsp = 1731; - public static final int AvatarExpeditionStartReq = 1788; - public static final int AvatarExpeditionStartRsp = 1786; - public static final int AvatarFetterDataNotify = 1718; - public static final int AvatarFetterLevelRewardReq = 1717; - public static final int AvatarFetterLevelRewardRsp = 1690; - public static final int AvatarFightPropNotify = 1237; - public static final int AvatarFightPropUpdateNotify = 1293; - public static final int AvatarFlycloakChangeNotify = 1761; - public static final int AvatarFollowRouteNotify = 3210; - public static final int AvatarGainCostumeNotify = 1778; - public static final int AvatarGainFlycloakNotify = 1676; - public static final int AvatarLifeStateChangeNotify = 1245; - public static final int AvatarPromoteGetRewardReq = 1784; - public static final int AvatarPromoteGetRewardRsp = 1776; - public static final int AvatarPromoteReq = 1661; - public static final int AvatarPromoteRsp = 1712; - public static final int AvatarPropChangeReasonNotify = 1275; - public static final int AvatarPropNotify = 1279; - public static final int AvatarSatiationDataNotify = 1639; - public static final int AvatarSkillChangeNotify = 1088; - public static final int AvatarSkillDepotChangeNotify = 1015; - public static final int AvatarSkillInfoNotify = 1045; - public static final int AvatarSkillMaxChargeCountNotify = 1044; - public static final int AvatarSkillUpgradeReq = 1091; - public static final int AvatarSkillUpgradeRsp = 1097; - public static final int AvatarTeamUpdateNotify = 1649; - public static final int AvatarUnlockTalentNotify = 1010; - public static final int AvatarUpgradeReq = 1660; - public static final int AvatarUpgradeRsp = 1735; - public static final int AvatarWearFlycloakReq = 1677; - public static final int AvatarWearFlycloakRsp = 1782; - public static final int BackMyWorldReq = 219; - public static final int BackMyWorldRsp = 269; - public static final int BargainOfferPriceReq = 409; - public static final int BargainOfferPriceRsp = 465; - public static final int BargainStartNotify = 489; - public static final int BargainTerminateNotify = 403; - public static final int BattlePassAllDataNotify = 2635; - public static final int BattlePassBuySuccNotify = 2612; - public static final int BattlePassCurScheduleUpdateNotify = 2648; - public static final int BattlePassMissionDelNotify = 2645; - public static final int BattlePassMissionUpdateNotify = 2625; - public static final int BeginCameraSceneLookNotify = 261; - public static final int BigTalentPointConvertReq = 1037; - public static final int BigTalentPointConvertRsp = 1093; - public static final int BlessingAcceptAllGivePicReq = 2176; - public static final int BlessingAcceptAllGivePicRsp = 2050; - public static final int BlessingAcceptGivePicReq = 2134; - public static final int BlessingAcceptGivePicRsp = 2117; - public static final int BlessingGetAllRecvPicRecordListReq = 2090; - public static final int BlessingGetAllRecvPicRecordListRsp = 2140; - public static final int BlessingGetFriendPicListReq = 2077; - public static final int BlessingGetFriendPicListRsp = 2182; - public static final int BlessingGiveFriendPicReq = 2161; - public static final int BlessingGiveFriendPicRsp = 2076; - public static final int BlessingRecvFriendPicNotify = 2184; - public static final int BlessingRedeemRewardReq = 2172; - public static final int BlessingRedeemRewardRsp = 2039; - public static final int BlessingScanReq = 2186; - public static final int BlessingScanRsp = 2007; - public static final int BlitzRushParkourRestartReq = 8212; - public static final int BlitzRushParkourRestartRsp = 8962; - public static final int BlossomBriefInfoNotify = 2710; - public static final int BlossomChestCreateNotify = 2793; - public static final int BlossomChestInfoNotify = 845; - public static final int BonusActivityInfoReq = 2597; - public static final int BonusActivityInfoRsp = 2588; - public static final int BonusActivityUpdateNotify = 2591; - public static final int BossChestActivateNotify = 844; - public static final int BounceConjuringSettleNotify = 8339; - public static final int BuoyantCombatSettleNotify = 9000; - public static final int BuyBattlePassLevelReq = 2639; - public static final int BuyBattlePassLevelRsp = 2621; - public static final int BuyGoodsReq = 710; - public static final int BuyGoodsRsp = 715; - public static final int BuyResinReq = 630; - public static final int BuyResinRsp = 647; - public static final int CalcWeaponUpgradeReturnItemsReq = 643; - public static final int CalcWeaponUpgradeReturnItemsRsp = 686; - public static final int CancelCityReputationRequestReq = 2834; - public static final int CancelCityReputationRequestRsp = 2879; - public static final int CancelCoopTaskReq = 1989; - public static final int CancelCoopTaskRsp = 1971; - public static final int CancelFinishParentQuestNotify = 492; - public static final int CanUseSkillNotify = 1055; - public static final int CardProductRewardNotify = 4148; - public static final int ChallengeDataNotify = 983; - public static final int ChallengeRecordNotify = 909; - public static final int ChangeAvatarReq = 1743; - public static final int ChangeAvatarRsp = 1672; - public static final int ChangeGameTimeReq = 175; - public static final int ChangeGameTimeRsp = 134; - public static final int ChangeMailStarNotify = 1497; - public static final int ChangeMpTeamAvatarReq = 1794; - public static final int ChangeMpTeamAvatarRsp = 1629; - public static final int ChangeServerGlobalValueNotify = 65; - public static final int ChangeTeamNameReq = 1793; - public static final int ChangeTeamNameRsp = 1707; - public static final int ChangeWorldToSingleModeNotify = 3293; - public static final int ChangeWorldToSingleModeReq = 3174; - public static final int ChangeWorldToSingleModeRsp = 3308; - public static final int ChannelerSlabStageActiveChallengeIndexNotify = 8578; - public static final int ChannelerSlabStageOneoffDungeonNotify = 8137; - public static final int ChannellerSlabCheckEnterLoopDungeonReq = 8684; - public static final int ChannellerSlabCheckEnterLoopDungeonRsp = 8376; - public static final int ChannellerSlabEnterLoopDungeonReq = 8090; - public static final int ChannellerSlabEnterLoopDungeonRsp = 8120; - public static final int ChannellerSlabLoopDungeonChallengeInfoNotify = 8263; - public static final int ChannellerSlabLoopDungeonSelectConditionReq = 8741; - public static final int ChannellerSlabLoopDungeonSelectConditionRsp = 8341; - public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardReq = 8914; - public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardRsp = 8503; - public static final int ChannellerSlabLoopDungeonTakeScoreRewardReq = 8012; - public static final int ChannellerSlabLoopDungeonTakeScoreRewardRsp = 8123; - public static final int ChannellerSlabOneOffDungeonInfoNotify = 8795; - public static final int ChannellerSlabOneOffDungeonInfoReq = 8772; - public static final int ChannellerSlabOneOffDungeonInfoRsp = 8715; - public static final int ChannellerSlabSaveAssistInfoReq = 8518; - public static final int ChannellerSlabSaveAssistInfoRsp = 8773; - public static final int ChannellerSlabTakeoffBuffReq = 8407; - public static final int ChannellerSlabTakeoffBuffRsp = 8260; - public static final int ChannellerSlabWearBuffReq = 8850; - public static final int ChannellerSlabWearBuffRsp = 8203; - public static final int ChapterStateNotify = 455; - public static final int ChatChannelDataNotify = 5047; - public static final int ChatChannelUpdateNotify = 5041; - public static final int ChatHistoryNotify = 3265; - public static final int CheckAddItemExceedLimitNotify = 639; - public static final int CheckSegmentCRCNotify = 56; - public static final int CheckSegmentCRCReq = 83; - public static final int ChessEscapedMonstersNotify = 5394; - public static final int ChessLeftMonstersNotify = 5378; - public static final int ChessManualRefreshCardsReq = 5325; - public static final int ChessManualRefreshCardsRsp = 5349; - public static final int ChessPickCardNotify = 5377; - public static final int ChessPickCardReq = 5343; - public static final int ChessPickCardRsp = 5386; - public static final int ChessPlayerInfoNotify = 5385; - public static final int ChessSelectedCardsNotify = 5339; - public static final int ChooseCurAvatarTeamReq = 1713; - public static final int ChooseCurAvatarTeamRsp = 1608; - public static final int CityReputationDataNotify = 2855; - public static final int CityReputationLevelupNotify = 2837; - public static final int ClearRoguelikeCurseNotify = 8997; - public static final int ClientAbilitiesInitFinishCombineNotify = 1144; - public static final int ClientAbilityChangeNotify = 1191; - public static final int ClientAbilityInitBeginNotify = 1110; - public static final int ClientAbilityInitFinishNotify = 1115; - public static final int ClientAIStateNotify = 1128; - public static final int ClientBulletCreateNotify = 89; - public static final int ClientCollectorDataNotify = 4262; - public static final int ClientHashDebugNotify = 3163; - public static final int ClientLoadingCostumeVerificationNotify = 3133; - public static final int ClientLockGameTimeNotify = 194; - public static final int ClientNewMailNotify = 1434; - public static final int ClientPauseNotify = 278; - public static final int ClientReconnectNotify = 91; - public static final int ClientReportNotify = 28; - public static final int ClientScriptEventNotify = 218; - public static final int ClientTransmitReq = 252; - public static final int ClientTransmitRsp = 292; - public static final int ClientTriggerEventNotify = 197; - public static final int CloseCommonTipsNotify = 3187; - public static final int ClosedItemNotify = 694; - public static final int CodexDataFullNotify = 4204; - public static final int CodexDataUpdateNotify = 4205; - public static final int CombatInvocationsNotify = 347; - public static final int CombineDataNotify = 649; - public static final int CombineFormulaDataNotify = 685; - public static final int CombineReq = 663; - public static final int CombineRsp = 608; - public static final int CommonPlayerTipsNotify = 8928; - public static final int CompoundDataNotify = 181; - public static final int CompoundUnlockNotify = 199; - public static final int CookDataNotify = 164; - public static final int CookGradeDataNotify = 166; + public static final int AvatarChangeAnimHashReq = 1798; + public static final int AvatarChangeAnimHashRsp = 1622; + public static final int AvatarChangeCostumeNotify = 1780; + public static final int AvatarChangeCostumeReq = 1734; + public static final int AvatarChangeCostumeRsp = 1723; + public static final int AvatarChangeElementTypeReq = 1706; + public static final int AvatarChangeElementTypeRsp = 1708; + public static final int AvatarDataNotify = 1695; + public static final int AvatarDelNotify = 1608; + public static final int AvatarDieAnimationEndReq = 1616; + public static final int AvatarDieAnimationEndRsp = 1765; + public static final int AvatarEnterElementViewNotify = 311; + public static final int AvatarEquipAffixStartNotify = 1609; + public static final int AvatarEquipChangeNotify = 690; + public static final int AvatarExpeditionAllDataReq = 1659; + public static final int AvatarExpeditionAllDataRsp = 1636; + public static final int AvatarExpeditionCallBackReq = 1655; + public static final int AvatarExpeditionCallBackRsp = 1642; + public static final int AvatarExpeditionDataNotify = 1698; + public static final int AvatarExpeditionGetRewardReq = 1603; + public static final int AvatarExpeditionGetRewardRsp = 1646; + public static final int AvatarExpeditionStartReq = 1675; + public static final int AvatarExpeditionStartRsp = 1688; + public static final int AvatarFetterDataNotify = 1777; + public static final int AvatarFetterLevelRewardReq = 1704; + public static final int AvatarFetterLevelRewardRsp = 1606; + public static final int AvatarFightPropNotify = 1232; + public static final int AvatarFightPropUpdateNotify = 1217; + public static final int AvatarFlycloakChangeNotify = 1681; + public static final int AvatarFollowRouteNotify = 3353; + public static final int AvatarGainCostumeNotify = 1670; + public static final int AvatarGainFlycloakNotify = 1615; + public static final int AvatarLifeStateChangeNotify = 1235; + public static final int AvatarPromoteGetRewardReq = 1676; + public static final int AvatarPromoteGetRewardRsp = 1613; + public static final int AvatarPromoteReq = 1711; + public static final int AvatarPromoteRsp = 1668; + public static final int AvatarPropChangeReasonNotify = 1249; + public static final int AvatarPropNotify = 1255; + public static final int AvatarSatiationDataNotify = 1632; + public static final int AvatarSkillChangeNotify = 1030; + public static final int AvatarSkillDepotChangeNotify = 1037; + public static final int AvatarSkillInfoNotify = 1035; + public static final int AvatarSkillMaxChargeCountNotify = 1085; + public static final int AvatarSkillUpgradeReq = 1027; + public static final int AvatarSkillUpgradeRsp = 1007; + public static final int AvatarTeamUpdateNotify = 1713; + public static final int AvatarUnlockTalentNotify = 1041; + public static final int AvatarUpgradeReq = 1680; + public static final int AvatarUpgradeRsp = 1779; + public static final int AvatarWearFlycloakReq = 1728; + public static final int AvatarWearFlycloakRsp = 1770; + public static final int BackMyWorldReq = 221; + public static final int BackMyWorldRsp = 223; + public static final int BargainOfferPriceReq = 419; + public static final int BargainOfferPriceRsp = 412; + public static final int BargainStartNotify = 406; + public static final int BargainTerminateNotify = 458; + public static final int BattlePassAllDataNotify = 2618; + public static final int BattlePassBuySuccNotify = 2614; + public static final int BattlePassCurScheduleUpdateNotify = 2604; + public static final int BattlePassMissionDelNotify = 2643; + public static final int BattlePassMissionUpdateNotify = 2609; + public static final int BeginCameraSceneLookNotify = 203; + public static final int BigTalentPointConvertReq = 1032; + public static final int BigTalentPointConvertRsp = 1017; + public static final int BlessingAcceptAllGivePicReq = 2123; + public static final int BlessingAcceptAllGivePicRsp = 2180; + public static final int BlessingAcceptGivePicReq = 2006; + public static final int BlessingAcceptGivePicRsp = 2048; + public static final int BlessingGetAllRecvPicRecordListReq = 2076; + public static final int BlessingGetAllRecvPicRecordListRsp = 2013; + public static final int BlessingGetFriendPicListReq = 2081; + public static final int BlessingGetFriendPicListRsp = 2015; + public static final int BlessingGiveFriendPicReq = 2009; + public static final int BlessingGiveFriendPicRsp = 2104; + public static final int BlessingRecvFriendPicNotify = 2134; + public static final int BlessingRedeemRewardReq = 2128; + public static final int BlessingRedeemRewardRsp = 2170; + public static final int BlessingScanReq = 2012; + public static final int BlessingScanRsp = 2032; + public static final int BlitzRushParkourRestartReq = 8355; + public static final int BlitzRushParkourRestartRsp = 8943; + public static final int BlossomBriefInfoNotify = 2741; + public static final int BlossomChestCreateNotify = 2717; + public static final int BlossomChestInfoNotify = 835; + public static final int BonusActivityInfoReq = 2507; + public static final int BonusActivityInfoRsp = 2530; + public static final int BonusActivityUpdateNotify = 2527; + public static final int BossChestActivateNotify = 885; + public static final int BounceConjuringSettleNotify = 8313; + public static final int BuoyantCombatSettleNotify = 8347; + public static final int BuyBattlePassLevelReq = 2612; + public static final int BuyBattlePassLevelRsp = 2646; + public static final int BuyGoodsReq = 741; + public static final int BuyGoodsRsp = 737; + public static final int BuyResinReq = 602; + public static final int BuyResinRsp = 616; + public static final int CalcWeaponUpgradeReturnItemsReq = 610; + public static final int CalcWeaponUpgradeReturnItemsRsp = 666; + public static final int CancelCityReputationRequestReq = 2882; + public static final int CancelCityReputationRequestRsp = 2855; + public static final int CancelCoopTaskReq = 1962; + public static final int CancelCoopTaskRsp = 1996; + public static final int CancelFinishParentQuestNotify = 459; + public static final int CanUseSkillNotify = 1098; + public static final int CardProductRewardNotify = 4104; + public static final int ChallengeDataNotify = 963; + public static final int ChallengeRecordNotify = 919; + public static final int ChangeAvatarReq = 1662; + public static final int ChangeAvatarRsp = 1710; + public static final int ChangeGameTimeReq = 149; + public static final int ChangeGameTimeRsp = 182; + public static final int ChangeMailStarNotify = 1407; + public static final int ChangeMpTeamAvatarReq = 1689; + public static final int ChangeMpTeamAvatarRsp = 1617; + public static final int ChangeServerGlobalValueNotify = 12; + public static final int ChangeTeamNameReq = 1762; + public static final int ChangeTeamNameRsp = 1789; + public static final int ChangeWorldToSingleModeNotify = 3260; + public static final int ChangeWorldToSingleModeReq = 3140; + public static final int ChangeWorldToSingleModeRsp = 3083; + public static final int ChannelerSlabStageActiveChallengeIndexNotify = 8864; + public static final int ChannelerSlabStageOneoffDungeonNotify = 8522; + public static final int ChannellerSlabCheckEnterLoopDungeonReq = 8304; + public static final int ChannellerSlabCheckEnterLoopDungeonRsp = 8928; + public static final int ChannellerSlabEnterLoopDungeonReq = 8687; + public static final int ChannellerSlabEnterLoopDungeonRsp = 8639; + public static final int ChannellerSlabLoopDungeonChallengeInfoNotify = 8555; + public static final int ChannellerSlabLoopDungeonSelectConditionReq = 8383; + public static final int ChannellerSlabLoopDungeonSelectConditionRsp = 8979; + public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardReq = 8910; + public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardRsp = 8482; + public static final int ChannellerSlabLoopDungeonTakeScoreRewardReq = 8305; + public static final int ChannellerSlabLoopDungeonTakeScoreRewardRsp = 8552; + public static final int ChannellerSlabOneOffDungeonInfoNotify = 8008; + public static final int ChannellerSlabOneOffDungeonInfoReq = 8295; + public static final int ChannellerSlabOneOffDungeonInfoRsp = 8716; + public static final int ChannellerSlabSaveAssistInfoReq = 8860; + public static final int ChannellerSlabSaveAssistInfoRsp = 8320; + public static final int ChannellerSlabTakeoffBuffReq = 8577; + public static final int ChannellerSlabTakeoffBuffRsp = 8689; + public static final int ChannellerSlabWearBuffReq = 8132; + public static final int ChannellerSlabWearBuffRsp = 8315; + public static final int ChapterStateNotify = 498; + public static final int ChatChannelDataNotify = 4957; + public static final int ChatChannelUpdateNotify = 4977; + public static final int ChatHistoryNotify = 3213; + public static final int CheckAddItemExceedLimitNotify = 653; + public static final int CheckSegmentCRCNotify = 86; + public static final int CheckSegmentCRCReq = 63; + public static final int ChessEscapedMonstersNotify = 5374; + public static final int ChessLeftMonstersNotify = 5391; + public static final int ChessManualRefreshCardsReq = 5373; + public static final int ChessManualRefreshCardsRsp = 5361; + public static final int ChessPickCardNotify = 5348; + public static final int ChessPickCardReq = 5310; + public static final int ChessPickCardRsp = 5366; + public static final int ChessPlayerInfoNotify = 5388; + public static final int ChessSelectedCardsNotify = 5353; + public static final int ChooseCurAvatarTeamReq = 1800; + public static final int ChooseCurAvatarTeamRsp = 1673; + public static final int CityReputationDataNotify = 2898; + public static final int CityReputationLevelupNotify = 2832; + public static final int ClearRoguelikeCurseNotify = 8291; + public static final int ClientAbilitiesInitFinishCombineNotify = 1185; + public static final int ClientAbilityChangeNotify = 1127; + public static final int ClientAbilityInitBeginNotify = 1141; + public static final int ClientAbilityInitFinishNotify = 1137; + public static final int ClientAIStateNotify = 1197; + public static final int ClientBulletCreateNotify = 6; + public static final int ClientCollectorDataNotify = 4264; + public static final int ClientHashDebugNotify = 3192; + public static final int ClientLoadingCostumeVerificationNotify = 3488; + public static final int ClientLockGameTimeNotify = 174; + public static final int ClientNewMailNotify = 1482; + public static final int ClientPauseNotify = 291; + public static final int ClientReconnectNotify = 27; + public static final int ClientReportNotify = 97; + public static final int ClientScriptEventNotify = 214; + public static final int ClientTransmitReq = 272; + public static final int ClientTransmitRsp = 259; + public static final int ClientTriggerEventNotify = 107; + public static final int CloseCommonTipsNotify = 3496; + public static final int ClosedItemNotify = 674; + public static final int CodexDataFullNotify = 4201; + public static final int CodexDataUpdateNotify = 4210; + public static final int CombatInvocationsNotify = 316; + public static final int CombineDataNotify = 661; + public static final int CombineFormulaDataNotify = 688; + public static final int CombineReq = 654; + public static final int CombineRsp = 646; + public static final int CommonPlayerTipsNotify = 8490; + public static final int CompoundDataNotify = 136; + public static final int CompoundUnlockNotify = 181; + public static final int CookDataNotify = 142; + public static final int CookGradeDataNotify = 111; public static final int CookRecipeDataNotify = 101; - public static final int CoopCgShowNotify = 1983; - public static final int CoopCgUpdateNotify = 1993; - public static final int CoopChapterUpdateNotify = 1986; - public static final int CoopDataNotify = 1967; + public static final int CoopCgShowNotify = 1989; + public static final int CoopCgUpdateNotify = 1966; + public static final int CoopChapterUpdateNotify = 1997; + public static final int CoopDataNotify = 1976; public static final int CoopPointUpdateNotify = 1987; - public static final int CoopProgressUpdateNotify = 2000; - public static final int CoopRewardUpdateNotify = 1976; - public static final int CreateMassiveEntityNotify = 336; - public static final int CreateMassiveEntityReq = 323; - public static final int CreateMassiveEntityRsp = 313; - public static final int CreateVehicleReq = 809; - public static final int CreateVehicleRsp = 865; - public static final int CutSceneBeginNotify = 241; - public static final int CutSceneEndNotify = 214; - public static final int CutSceneFinishNotify = 248; - public static final int DailyTaskDataNotify = 124; - public static final int DailyTaskFilterCityReq = 159; - public static final int DailyTaskFilterCityRsp = 150; - public static final int DailyTaskProgressNotify = 161; - public static final int DailyTaskScoreRewardNotify = 138; - public static final int DailyTaskUnlockedCitiesNotify = 119; - public static final int DataResVersionNotify = 136; - public static final int DealAddFriendReq = 4044; - public static final int DealAddFriendRsp = 4045; - public static final int DeleteFriendNotify = 4083; - public static final int DeleteFriendReq = 4079; - public static final int DeleteFriendRsp = 4091; - public static final int DelMailReq = 1493; - public static final int DelMailRsp = 1444; - public static final int DelScenePlayTeamEntityNotify = 3117; - public static final int DelTeamEntityNotify = 330; - public static final int DestroyMassiveEntityNotify = 324; - public static final int DestroyMaterialReq = 670; - public static final int DestroyMaterialRsp = 654; - public static final int DigActivityChangeGadgetStateReq = 8283; - public static final int DigActivityChangeGadgetStateRsp = 8609; - public static final int DigActivityMarkPointChangeNotify = 8143; - public static final int DisableRoguelikeTrapNotify = 8029; - public static final int DoGachaReq = 1510; - public static final int DoGachaRsp = 1515; - public static final int DoRoguelikeDungeonCardGachaReq = 8897; - public static final int DoRoguelikeDungeonCardGachaRsp = 8973; - public static final int DoSetPlayerBornDataNotify = 174; - public static final int DraftGuestReplyInviteNotify = 5445; - public static final int DraftGuestReplyInviteReq = 5493; - public static final int DraftGuestReplyInviteRsp = 5444; - public static final int DraftGuestReplyTwiceConfirmNotify = 5488; - public static final int DraftGuestReplyTwiceConfirmReq = 5479; - public static final int DraftGuestReplyTwiceConfirmRsp = 5491; - public static final int DraftInviteResultNotify = 5475; - public static final int DraftOwnerInviteNotify = 5437; - public static final int DraftOwnerStartInviteReq = 5410; - public static final int DraftOwnerStartInviteRsp = 5415; - public static final int DraftOwnerTwiceConfirmNotify = 5434; - public static final int DraftTwiceConfirmResultNotify = 5497; - public static final int DragonSpineChapterFinishNotify = 2196; - public static final int DragonSpineChapterOpenNotify = 2070; - public static final int DragonSpineChapterProgressChangeNotify = 2001; - public static final int DragonSpineCoinChangeNotify = 2189; - public static final int DropHintNotify = 673; - public static final int DropItemReq = 634; - public static final int DropItemRsp = 679; - public static final int DropSubfieldReq = 232; - public static final int DropSubfieldRsp = 251; - public static final int DungeonCandidateTeamChangeAvatarReq = 958; - public static final int DungeonCandidateTeamChangeAvatarRsp = 923; - public static final int DungeonCandidateTeamCreateReq = 964; + public static final int CoopProgressUpdateNotify = 1961; + public static final int CoopRewardUpdateNotify = 1951; + public static final int CreateMassiveEntityNotify = 325; + public static final int CreateMassiveEntityReq = 370; + public static final int CreateMassiveEntityRsp = 329; + public static final int CreateVehicleReq = 819; + public static final int CreateVehicleRsp = 812; + public static final int CutSceneBeginNotify = 300; + public static final int CutSceneEndNotify = 299; + public static final int CutSceneFinishNotify = 294; + public static final int DailyTaskDataNotify = 183; + public static final int DailyTaskFilterCityReq = 192; + public static final int DailyTaskFilterCityRsp = 118; + public static final int DailyTaskProgressNotify = 103; + public static final int DailyTaskScoreRewardNotify = 134; + public static final int DailyTaskUnlockedCitiesNotify = 121; + public static final int DataResVersionNotify = 125; + public static final int DealAddFriendReq = 4085; + public static final int DealAddFriendRsp = 4035; + public static final int DebugNotify = 101; + public static final int DeleteFriendNotify = 4063; + public static final int DeleteFriendReq = 4055; + public static final int DeleteFriendRsp = 4027; + public static final int DelMailReq = 1417; + public static final int DelMailRsp = 1485; + public static final int DelScenePlayTeamEntityNotify = 3087; + public static final int DelTeamEntityNotify = 302; + public static final int DestroyMassiveEntityNotify = 383; + public static final int DestroyMaterialReq = 678; + public static final int DestroyMaterialRsp = 608; + public static final int DigActivityChangeGadgetStateReq = 8155; + public static final int DigActivityChangeGadgetStateRsp = 8851; + public static final int DigActivityMarkPointChangeNotify = 8679; + public static final int DisableRoguelikeTrapNotify = 8250; + public static final int DoGachaReq = 1541; + public static final int DoGachaRsp = 1537; + public static final int DoRoguelikeDungeonCardGachaReq = 8764; + public static final int DoRoguelikeDungeonCardGachaRsp = 8641; + public static final int DoSetPlayerBornDataNotify = 190; + public static final int DraftGuestReplyInviteNotify = 5435; + public static final int DraftGuestReplyInviteReq = 5417; + public static final int DraftGuestReplyInviteRsp = 5485; + public static final int DraftGuestReplyTwiceConfirmNotify = 5430; + public static final int DraftGuestReplyTwiceConfirmReq = 5455; + public static final int DraftGuestReplyTwiceConfirmRsp = 5427; + public static final int DraftInviteResultNotify = 5449; + public static final int DraftOwnerInviteNotify = 5432; + public static final int DraftOwnerStartInviteReq = 5441; + public static final int DraftOwnerStartInviteRsp = 5437; + public static final int DraftOwnerTwiceConfirmNotify = 5482; + public static final int DraftTwiceConfirmResultNotify = 5407; + public static final int DragonSpineChapterFinishNotify = 2135; + public static final int DragonSpineChapterOpenNotify = 2119; + public static final int DragonSpineChapterProgressChangeNotify = 2102; + public static final int DragonSpineCoinChangeNotify = 2031; + public static final int DropHintNotify = 622; + public static final int DropItemReq = 682; + public static final int DropItemRsp = 655; + public static final int DungeonCandidateTeamChangeAvatarReq = 984; + public static final int DungeonCandidateTeamChangeAvatarRsp = 970; + public static final int DungeonCandidateTeamCreateReq = 942; public static final int DungeonCandidateTeamCreateRsp = 901; - public static final int DungeonCandidateTeamDismissNotify = 980; - public static final int DungeonCandidateTeamInfoNotify = 965; - public static final int DungeonCandidateTeamInviteNotify = 903; - public static final int DungeonCandidateTeamInviteReq = 966; - public static final int DungeonCandidateTeamInviteRsp = 973; - public static final int DungeonCandidateTeamKickReq = 963; - public static final int DungeonCandidateTeamKickRsp = 908; - public static final int DungeonCandidateTeamLeaveReq = 917; - public static final int DungeonCandidateTeamLeaveRsp = 981; + public static final int DungeonCandidateTeamDismissNotify = 913; + public static final int DungeonCandidateTeamInfoNotify = 912; + public static final int DungeonCandidateTeamInviteNotify = 958; + public static final int DungeonCandidateTeamInviteReq = 911; + public static final int DungeonCandidateTeamInviteRsp = 922; + public static final int DungeonCandidateTeamKickReq = 954; + public static final int DungeonCandidateTeamKickRsp = 946; + public static final int DungeonCandidateTeamLeaveReq = 933; + public static final int DungeonCandidateTeamLeaveRsp = 936; public static final int DungeonCandidateTeamPlayerLeaveNotify = 920; - public static final int DungeonCandidateTeamRefuseNotify = 967; - public static final int DungeonCandidateTeamReplyInviteReq = 927; - public static final int DungeonCandidateTeamReplyInviteRsp = 902; - public static final int DungeonCandidateTeamSetChangingAvatarReq = 954; - public static final int DungeonCandidateTeamSetChangingAvatarRsp = 935; - public static final int DungeonCandidateTeamSetReadyReq = 952; - public static final int DungeonCandidateTeamSetReadyRsp = 992; - public static final int DungeonChallengeBeginNotify = 974; - public static final int DungeonChallengeFinishNotify = 956; - public static final int DungeonDataNotify = 946; - public static final int DungeonDieOptionReq = 991; - public static final int DungeonDieOptionRsp = 997; - public static final int DungeonEntryInfoReq = 960; - public static final int DungeonEntryInfoRsp = 933; - public static final int DungeonEntryToBeExploreNotify = 3067; - public static final int DungeonFollowNotify = 926; - public static final int DungeonGetStatueDropReq = 962; - public static final int DungeonGetStatueDropRsp = 989; - public static final int DungeonInterruptChallengeReq = 938; - public static final int DungeonInterruptChallengeRsp = 930; - public static final int DungeonPlayerDieNotify = 979; - public static final int DungeonPlayerDieReq = 928; - public static final int DungeonPlayerDieRsp = 955; - public static final int DungeonRestartInviteNotify = 984; - public static final int DungeonRestartInviteReplyNotify = 972; - public static final int DungeonRestartInviteReplyReq = 912; - public static final int DungeonRestartInviteReplyRsp = 953; - public static final int DungeonRestartReq = 932; - public static final int DungeonRestartResultNotify = 970; - public static final int DungeonRestartRsp = 951; - public static final int DungeonReviseLevelNotify = 957; - public static final int DungeonSettleNotify = 934; - public static final int DungeonShowReminderNotify = 988; - public static final int DungeonSlipRevivePointActivateReq = 924; - public static final int DungeonSlipRevivePointActivateRsp = 961; - public static final int DungeonWayPointActivateReq = 945; - public static final int DungeonWayPointActivateRsp = 975; - public static final int DungeonWayPointNotify = 944; - public static final int EchoNotify = 62; - public static final int EchoShellTakeRewardReq = 8801; - public static final int EchoShellTakeRewardRsp = 8888; - public static final int EchoShellUpdateNotify = 8730; - public static final int EffigyChallengeInfoNotify = 2159; - public static final int EffigyChallengeResultNotify = 2024; - public static final int EndCameraSceneLookNotify = 238; - public static final int EnterChessDungeonReq = 8336; - public static final int EnterChessDungeonRsp = 8581; - public static final int EnterFishingReq = 5835; - public static final int EnterFishingRsp = 5825; - public static final int EnterMechanicusDungeonReq = 3979; - public static final int EnterMechanicusDungeonRsp = 3991; - public static final int EnterRoguelikeDungeonNotify = 8330; - public static final int EnterSceneDoneReq = 268; - public static final int EnterSceneDoneRsp = 290; - public static final int EnterScenePeerNotify = 282; - public static final int EnterSceneReadyReq = 298; - public static final int EnterSceneReadyRsp = 296; - public static final int EnterSceneWeatherAreaNotify = 258; - public static final int EnterTransPointRegionNotify = 255; - public static final int EnterTrialAvatarActivityDungeonReq = 2031; - public static final int EnterTrialAvatarActivityDungeonRsp = 2175; - public static final int EnterWorldAreaReq = 273; - public static final int EnterWorldAreaRsp = 263; - public static final int EntityAiKillSelfNotify = 370; - public static final int EntityAiSyncNotify = 312; - public static final int EntityAuthorityChangeNotify = 303; - public static final int EntityConfigHashNotify = 3458; - public static final int EntityFightPropChangeReasonNotify = 1244; - public static final int EntityFightPropNotify = 1210; - public static final int EntityFightPropUpdateNotify = 1215; - public static final int EntityForceSyncReq = 208; - public static final int EntityForceSyncRsp = 217; - public static final int EntityJumpNotify = 226; - public static final int EntityMoveRoomNotify = 3135; - public static final int EntityPropNotify = 1260; - public static final int EntityTagChangeNotify = 3262; - public static final int EquipRoguelikeRuneReq = 8579; - public static final int EquipRoguelikeRuneRsp = 8412; - public static final int EvtAiSyncCombatThreatInfoNotify = 351; - public static final int EvtAiSyncSkillCdNotify = 317; - public static final int EvtAnimatorParameterNotify = 333; - public static final int EvtAnimatorStateChangedNotify = 379; - public static final int EvtAvatarEnterFocusNotify = 389; - public static final int EvtAvatarExitFocusNotify = 309; - public static final int EvtAvatarLockChairReq = 354; - public static final int EvtAvatarLockChairRsp = 335; - public static final int EvtAvatarSitDownNotify = 392; - public static final int EvtAvatarStandUpNotify = 358; - public static final int EvtAvatarUpdateFocusNotify = 365; - public static final int EvtBeingHitNotify = 360; - public static final int EvtBeingHitsCombineNotify = 381; - public static final int EvtBulletDeactiveNotify = 388; - public static final int EvtBulletHitNotify = 397; - public static final int EvtBulletMoveNotify = 362; - public static final int EvtCostStaminaNotify = 375; - public static final int EvtCreateGadgetNotify = 337; - public static final int EvtDestroyGadgetNotify = 393; - public static final int EvtDestroyServerGadgetNotify = 372; - public static final int EvtDoSkillSuccNotify = 315; - public static final int EvtEntityRenderersChangedNotify = 363; - public static final int EvtEntityStartDieEndNotify = 328; - public static final int EvtFaceToDirNotify = 345; - public static final int EvtFaceToEntityNotify = 344; - public static final int EvtRushMoveNotify = 391; - public static final int EvtSetAttackTargetNotify = 334; - public static final int ExclusiveRuleNotify = 169; - public static final int ExecuteGadgetLuaReq = 231; - public static final int ExecuteGadgetLuaRsp = 240; - public static final int ExecuteGroupTriggerReq = 284; - public static final int ExecuteGroupTriggerRsp = 212; - public static final int ExitFishingReq = 5812; - public static final int ExitFishingRsp = 5839; - public static final int ExitSceneWeatherAreaNotify = 223; - public static final int ExitTransPointRegionNotify = 246; - public static final int ExpeditionChallengeEnterRegionNotify = 2095; - public static final int ExpeditionChallengeFinishedNotify = 2197; - public static final int ExpeditionRecallReq = 2114; - public static final int ExpeditionRecallRsp = 2108; - public static final int ExpeditionStartReq = 2032; - public static final int ExpeditionStartRsp = 2148; - public static final int ExpeditionTakeRewardReq = 2053; - public static final int ExpeditionTakeRewardRsp = 2181; - public static final int FindHilichurlAcceptQuestNotify = 8292; - public static final int FindHilichurlFinishSecondQuestNotify = 8799; - public static final int FinishDeliveryNotify = 2126; - public static final int FinishedParentQuestNotify = 415; - public static final int FinishedParentQuestUpdateNotify = 437; - public static final int FinishMainCoopReq = 1963; - public static final int FinishMainCoopRsp = 1951; - public static final int FishAttractNotify = 5821; - public static final int FishBaitGoneNotify = 5846; - public static final int FishBattleBeginReq = 5815; - public static final int FishBattleBeginRsp = 5827; + public static final int DungeonCandidateTeamRefuseNotify = 950; + public static final int DungeonCandidateTeamReplyInviteReq = 928; + public static final int DungeonCandidateTeamReplyInviteRsp = 976; + public static final int DungeonCandidateTeamSetChangingAvatarReq = 908; + public static final int DungeonCandidateTeamSetChangingAvatarRsp = 904; + public static final int DungeonCandidateTeamSetReadyReq = 972; + public static final int DungeonCandidateTeamSetReadyRsp = 959; + public static final int DungeonChallengeBeginNotify = 990; + public static final int DungeonChallengeFinishNotify = 986; + public static final int DungeonDataNotify = 945; + public static final int DungeonDieOptionReq = 927; + public static final int DungeonDieOptionRsp = 907; + public static final int DungeonEntryInfoReq = 909; + public static final int DungeonEntryInfoRsp = 931; + public static final int DungeonEntryToBeExploreNotify = 3414; + public static final int DungeonFollowNotify = 924; + public static final int DungeonGetStatueDropReq = 938; + public static final int DungeonGetStatueDropRsp = 906; + public static final int DungeonInterruptChallengeReq = 934; + public static final int DungeonInterruptChallengeRsp = 902; + public static final int DungeonPlayerDieNotify = 955; + public static final int DungeonPlayerDieReq = 997; + public static final int DungeonPlayerDieRsp = 998; + public static final int DungeonRestartInviteNotify = 977; + public static final int DungeonRestartInviteReplyNotify = 989; + public static final int DungeonRestartInviteReplyReq = 943; + public static final int DungeonRestartInviteReplyRsp = 987; + public static final int DungeonRestartReq = 993; + public static final int DungeonRestartResultNotify = 978; + public static final int DungeonRestartRsp = 960; + public static final int DungeonReviseLevelNotify = 905; + public static final int DungeonSettleNotify = 982; + public static final int DungeonShowReminderNotify = 930; + public static final int DungeonSlipRevivePointActivateReq = 983; + public static final int DungeonSlipRevivePointActivateRsp = 903; + public static final int DungeonWayPointActivateReq = 935; + public static final int DungeonWayPointActivateRsp = 949; + public static final int DungeonWayPointNotify = 985; + public static final int EchoNotify = 38; + public static final int EchoShellTakeRewardReq = 8074; + public static final int EchoShellTakeRewardRsp = 8446; + public static final int EchoShellUpdateNotify = 8077; + public static final int EffigyChallengeInfoNotify = 2153; + public static final int EffigyChallengeResultNotify = 2064; + public static final int EndCameraSceneLookNotify = 234; + public static final int EnterChessDungeonReq = 8571; + public static final int EnterChessDungeonRsp = 8819; + public static final int EnterFishingReq = 5818; + public static final int EnterFishingRsp = 5809; + public static final int EnterMechanicusDungeonReq = 3955; + public static final int EnterMechanicusDungeonRsp = 3927; + public static final int EnterRoguelikeDungeonNotify = 8646; + public static final int EnterSceneDoneReq = 279; + public static final int EnterSceneDoneRsp = 269; + public static final int EnterScenePeerNotify = 257; + public static final int EnterSceneReadyReq = 244; + public static final int EnterSceneReadyRsp = 252; + public static final int EnterSceneWeatherAreaNotify = 284; + public static final int EnterTransPointRegionNotify = 298; + public static final int EnterTrialAvatarActivityDungeonReq = 2057; + public static final int EnterTrialAvatarActivityDungeonRsp = 2021; + public static final int EnterWorldAreaReq = 222; + public static final int EnterWorldAreaRsp = 254; + public static final int EntityAiKillSelfNotify = 378; + public static final int EntityAiSyncNotify = 343; + public static final int EntityAuthorityChangeNotify = 358; + public static final int EntityConfigHashNotify = 3271; + public static final int EntityFightPropChangeReasonNotify = 1285; + public static final int EntityFightPropNotify = 1241; + public static final int EntityFightPropUpdateNotify = 1237; + public static final int EntityForceSyncReq = 246; + public static final int EntityForceSyncRsp = 233; + public static final int EntityJumpNotify = 224; + public static final int EntityMoveRoomNotify = 3209; + public static final int EntityPropNotify = 1209; + public static final int EntityTagChangeNotify = 3273; + public static final int EquipRoguelikeRuneReq = 8510; + public static final int EquipRoguelikeRuneRsp = 8516; + public static final int EvtAiSyncCombatThreatInfoNotify = 360; + public static final int EvtAiSyncSkillCdNotify = 333; + public static final int EvtAnimatorParameterNotify = 331; + public static final int EvtAnimatorStateChangedNotify = 355; + public static final int EvtAvatarEnterFocusNotify = 306; + public static final int EvtAvatarExitFocusNotify = 319; + public static final int EvtAvatarLockChairReq = 308; + public static final int EvtAvatarLockChairRsp = 304; + public static final int EvtAvatarSitDownNotify = 359; + public static final int EvtAvatarStandUpNotify = 384; + public static final int EvtAvatarUpdateFocusNotify = 312; + public static final int EvtBeingHitNotify = 309; + public static final int EvtBeingHitsCombineNotify = 336; + public static final int EvtBulletDeactiveNotify = 330; + public static final int EvtBulletHitNotify = 307; + public static final int EvtBulletMoveNotify = 338; + public static final int EvtCostStaminaNotify = 349; + public static final int EvtCreateGadgetNotify = 332; + public static final int EvtDestroyGadgetNotify = 317; + public static final int EvtDestroyServerGadgetNotify = 389; + public static final int EvtDoSkillSuccNotify = 337; + public static final int EvtEntityRenderersChangedNotify = 354; + public static final int EvtEntityStartDieEndNotify = 397; + public static final int EvtFaceToDirNotify = 335; + public static final int EvtFaceToEntityNotify = 385; + public static final int EvtRushMoveNotify = 327; + public static final int EvtSetAttackTargetNotify = 382; + public static final int ExclusiveRuleNotify = 123; + public static final int ExecuteGadgetLuaReq = 267; + public static final int ExecuteGadgetLuaRsp = 271; + public static final int ExecuteGroupTriggerReq = 277; + public static final int ExecuteGroupTriggerRsp = 243; + public static final int ExitFishingReq = 5814; + public static final int ExitFishingRsp = 5812; + public static final int ExitSceneWeatherAreaNotify = 270; + public static final int ExitTransPointRegionNotify = 245; + public static final int ExpeditionChallengeEnterRegionNotify = 2050; + public static final int ExpeditionChallengeFinishedNotify = 2034; + public static final int ExpeditionRecallReq = 2122; + public static final int ExpeditionRecallRsp = 2156; + public static final int ExpeditionStartReq = 2026; + public static final int ExpeditionStartRsp = 2163; + public static final int ExpeditionTakeRewardReq = 2173; + public static final int ExpeditionTakeRewardRsp = 2196; + public static final int FindHilichurlAcceptQuestNotify = 8465; + public static final int FindHilichurlFinishSecondQuestNotify = 8981; + public static final int FinishDeliveryNotify = 2158; + public static final int FinishedParentQuestNotify = 437; + public static final int FinishedParentQuestUpdateNotify = 432; + public static final int FinishMainCoopReq = 1978; + public static final int FinishMainCoopRsp = 1953; + public static final int FishAttractNotify = 5846; + public static final int FishBaitGoneNotify = 5827; + public static final int FishBattleBeginReq = 5802; + public static final int FishBattleBeginRsp = 5813; public static final int FishBattleEndReq = 5837; - public static final int FishBattleEndRsp = 5806; - public static final int FishBiteReq = 5843; - public static final int FishBiteRsp = 5826; - public static final int FishCastRodReq = 5813; - public static final int FishCastRodRsp = 5801; - public static final int FishChosenNotify = 5817; - public static final int FishEscapeNotify = 5836; - public static final int FishingGallerySettleNotify = 8870; - public static final int FishPoolDataNotify = 5850; - public static final int FleurFairBalloonSettleNotify = 2192; - public static final int FleurFairBuffEnergyNotify = 5392; - public static final int FleurFairFallSettleNotify = 2015; - public static final int FleurFairFinishGalleryStageNotify = 5323; - public static final int FleurFairMusicGameSettleReq = 2064; - public static final int FleurFairMusicGameSettleRsp = 2040; - public static final int FleurFairMusicGameStartReq = 2105; - public static final int FleurFairMusicGameStartRsp = 2179; - public static final int FleurFairReplayMiniGameReq = 2146; - public static final int FleurFairReplayMiniGameRsp = 2089; - public static final int FleurFairStageSettleNotify = 5358; - public static final int FlightActivityRestartReq = 2073; - public static final int FlightActivityRestartRsp = 2045; - public static final int FlightActivitySettleNotify = 2195; - public static final int FocusAvatarReq = 1710; - public static final int FocusAvatarRsp = 1772; - public static final int ForceAddPlayerFriendReq = 4084; - public static final int ForceAddPlayerFriendRsp = 4012; - public static final int ForceDragAvatarNotify = 3056; - public static final int ForceDragBackTransferNotify = 3171; - public static final int ForgeDataNotify = 677; - public static final int ForgeFormulaDataNotify = 625; - public static final int ForgeGetQueueDataReq = 681; - public static final int ForgeGetQueueDataRsp = 627; - public static final int ForgeQueueDataNotify = 617; - public static final int ForgeQueueManipulateReq = 692; - public static final int ForgeQueueManipulateRsp = 658; - public static final int ForgeStartReq = 602; - public static final int ForgeStartRsp = 652; - public static final int FoundationNotify = 874; - public static final int FoundationReq = 855; - public static final int FoundationRsp = 846; - public static final int FriendInfoChangeNotify = 4085; - public static final int FunitureMakeMakeInfoChangeNotify = 4523; - public static final int FurnitureCurModuleArrangeCountNotify = 4770; - public static final int FurnitureMakeBeHelpedNotify = 4825; - public static final int FurnitureMakeCancelReq = 4495; - public static final int FurnitureMakeCancelRsp = 4814; - public static final int FurnitureMakeFinishNotify = 4707; - public static final int FurnitureMakeHelpReq = 4779; - public static final int FurnitureMakeHelpRsp = 4455; - public static final int FurnitureMakeReq = 4885; - public static final int FurnitureMakeRsp = 4819; - public static final int FurnitureMakeStartReq = 4518; - public static final int FurnitureMakeStartRsp = 4521; - public static final int GachaOpenWishNotify = 1544; - public static final int GachaSimpleInfoNotify = 1545; - public static final int GachaWishReq = 1537; - public static final int GachaWishRsp = 1593; - public static final int GadgetAutoPickDropInfoNotify = 888; - public static final int GadgetChainLevelChangeNotify = 826; - public static final int GadgetChainLevelUpdateNotify = 883; - public static final int GadgetCustomTreeInfoNotify = 873; - public static final int GadgetGeneralRewardInfoNotify = 897; - public static final int GadgetInteractReq = 860; - public static final int GadgetInteractRsp = 833; - public static final int GadgetPlayDataNotify = 879; - public static final int GadgetPlayStartNotify = 875; - public static final int GadgetPlayStopNotify = 834; - public static final int GadgetPlayUidOpNotify = 891; - public static final int GadgetStateNotify = 810; - public static final int GadgetTalkChangeNotify = 856; - public static final int GalleryBalloonScoreNotify = 5510; - public static final int GalleryBalloonShootNotify = 5533; - public static final int GalleryBounceConjuringHitNotify = 5555; - public static final int GalleryBrokenFloorFallNotify = 5591; - public static final int GalleryBulletHitNotify = 5579; - public static final int GalleryFallCatchNotify = 5537; - public static final int GalleryFallScoreNotify = 5593; - public static final int GalleryFlowerCatchNotify = 5575; - public static final int GalleryPreStartNotify = 5534; - public static final int GalleryStartNotify = 5560; - public static final int GalleryStopNotify = 5515; - public static final int GallerySumoKillMonsterNotify = 5546; - public static final int GetActivityInfoReq = 2011; - public static final int GetActivityInfoRsp = 2170; - public static final int GetActivityScheduleReq = 2663; - public static final int GetActivityScheduleRsp = 2651; - public static final int GetActivityShopSheetInfoReq = 744; - public static final int GetActivityShopSheetInfoRsp = 745; - public static final int GetAllActivatedBargainDataReq = 480; - public static final int GetAllActivatedBargainDataRsp = 464; - public static final int GetAllH5ActivityInfoReq = 5675; - public static final int GetAllH5ActivityInfoRsp = 5685; - public static final int GetAllMailReq = 1479; - public static final int GetAllMailRsp = 1491; - public static final int GetAllSceneGalleryInfoReq = 5544; - public static final int GetAllSceneGalleryInfoRsp = 5545; - public static final int GetAllUnlockNameCardReq = 4065; - public static final int GetAllUnlockNameCardRsp = 4003; - public static final int GetAreaExplorePointReq = 227; - public static final int GetAreaExplorePointRsp = 202; - public static final int GetAuthkeyReq = 1445; - public static final int GetAuthkeyRsp = 1475; - public static final int GetAuthSalesmanInfoReq = 2082; - public static final int GetAuthSalesmanInfoRsp = 2173; - public static final int GetBargainDataReq = 467; + public static final int FishBattleEndRsp = 5832; + public static final int FishBiteReq = 5816; + public static final int FishBiteRsp = 5801; + public static final int FishCastRodReq = 5828; + public static final int FishCastRodRsp = 5803; + public static final int FishChosenNotify = 5826; + public static final int FishEscapeNotify = 5847; + public static final int FishingGallerySettleNotify = 8896; + public static final int FishPoolDataNotify = 5811; + public static final int FleurFairBalloonSettleNotify = 2139; + public static final int FleurFairBuffEnergyNotify = 5359; + public static final int FleurFairFallSettleNotify = 2097; + public static final int FleurFairFinishGalleryStageNotify = 5370; + public static final int FleurFairMusicGameSettleReq = 2115; + public static final int FleurFairMusicGameSettleRsp = 2124; + public static final int FleurFairMusicGameStartReq = 2171; + public static final int FleurFairMusicGameStartRsp = 2149; + public static final int FleurFairReplayMiniGameReq = 2152; + public static final int FleurFairReplayMiniGameRsp = 2101; + public static final int FleurFairStageSettleNotify = 5384; + public static final int FlightActivityRestartReq = 2164; + public static final int FlightActivityRestartRsp = 2002; + public static final int FlightActivitySettleNotify = 2084; + public static final int FocusAvatarReq = 1652; + public static final int FocusAvatarRsp = 1612; + public static final int ForceAddPlayerFriendReq = 4077; + public static final int ForceAddPlayerFriendRsp = 4043; + public static final int ForceDragAvatarNotify = 3425; + public static final int ForceDragBackTransferNotify = 3088; + public static final int ForgeDataNotify = 648; + public static final int ForgeFormulaDataNotify = 673; + public static final int ForgeGetQueueDataReq = 636; + public static final int ForgeGetQueueDataRsp = 628; + public static final int ForgeQueueDataNotify = 633; + public static final int ForgeQueueManipulateReq = 659; + public static final int ForgeQueueManipulateRsp = 684; + public static final int ForgeStartReq = 676; + public static final int ForgeStartRsp = 672; + public static final int FoundationNotify = 890; + public static final int FoundationReq = 898; + public static final int FoundationRsp = 845; + public static final int FriendInfoChangeNotify = 4088; + public static final int FunitureMakeMakeInfoChangeNotify = 4488; + public static final int FurnitureCurModuleArrangeCountNotify = 4681; + public static final int FurnitureMakeBeHelpedNotify = 4626; + public static final int FurnitureMakeCancelReq = 4834; + public static final int FurnitureMakeCancelRsp = 4660; + public static final int FurnitureMakeFinishNotify = 4557; + public static final int FurnitureMakeHelpReq = 4580; + public static final int FurnitureMakeHelpRsp = 4722; + public static final int FurnitureMakeReq = 4551; + public static final int FurnitureMakeRsp = 4530; + public static final int FurnitureMakeStartReq = 4582; + public static final int FurnitureMakeStartRsp = 4463; + public static final int GachaOpenWishNotify = 1585; + public static final int GachaSimpleInfoNotify = 1535; + public static final int GachaWishReq = 1532; + public static final int GachaWishRsp = 1517; + public static final int GadgetAutoPickDropInfoNotify = 830; + public static final int GadgetChainLevelChangeNotify = 824; + public static final int GadgetChainLevelUpdateNotify = 863; + public static final int GadgetCustomTreeInfoNotify = 822; + public static final int GadgetGeneralRewardInfoNotify = 807; + public static final int GadgetInteractReq = 809; + public static final int GadgetInteractRsp = 831; + public static final int GadgetPlayDataNotify = 855; + public static final int GadgetPlayStartNotify = 849; + public static final int GadgetPlayStopNotify = 882; + public static final int GadgetPlayUidOpNotify = 827; + public static final int GadgetStateNotify = 841; + public static final int GadgetTalkChangeNotify = 886; + public static final int GalleryBalloonScoreNotify = 5541; + public static final int GalleryBalloonShootNotify = 5531; + public static final int GalleryBounceConjuringHitNotify = 5598; + public static final int GalleryBrokenFloorFallNotify = 5527; + public static final int GalleryBulletHitNotify = 5555; + public static final int GalleryFallCatchNotify = 5532; + public static final int GalleryFallScoreNotify = 5517; + public static final int GalleryFlowerCatchNotify = 5549; + public static final int GalleryPreStartNotify = 5582; + public static final int GalleryStartNotify = 5509; + public static final int GalleryStopNotify = 5537; + public static final int GallerySumoKillMonsterNotify = 5545; + public static final int GetActivityInfoReq = 2067; + public static final int GetActivityInfoRsp = 2144; + public static final int GetActivityScheduleReq = 2049; + public static final int GetActivityScheduleRsp = 2044; + public static final int GetActivityShopSheetInfoReq = 785; + public static final int GetActivityShopSheetInfoRsp = 735; + public static final int GetAllActivatedBargainDataReq = 413; + public static final int GetAllActivatedBargainDataRsp = 442; + public static final int GetAllH5ActivityInfoReq = 5659; + public static final int GetAllH5ActivityInfoRsp = 5668; + public static final int GetAllMailReq = 1455; + public static final int GetAllMailRsp = 1427; + public static final int GetAllSceneGalleryInfoReq = 5585; + public static final int GetAllSceneGalleryInfoRsp = 5535; + public static final int GetAllUnlockNameCardReq = 4012; + public static final int GetAllUnlockNameCardRsp = 4058; + public static final int GetAreaExplorePointReq = 228; + public static final int GetAreaExplorePointRsp = 276; + public static final int GetAuthkeyReq = 1435; + public static final int GetAuthkeyRsp = 1449; + public static final int GetAuthSalesmanInfoReq = 2161; + public static final int GetAuthSalesmanInfoRsp = 2039; + public static final int GetBargainDataReq = 450; public static final int GetBargainDataRsp = 420; - public static final int GetBattlePassProductReq = 2643; - public static final int GetBattlePassProductRsp = 2626; - public static final int GetBlossomBriefInfoListReq = 2760; - public static final int GetBlossomBriefInfoListRsp = 2733; - public static final int GetBonusActivityRewardReq = 2528; - public static final int GetBonusActivityRewardRsp = 2555; - public static final int GetChatEmojiCollectionReq = 4057; - public static final int GetChatEmojiCollectionRsp = 4043; - public static final int GetCityHuntingOfferReq = 4456; - public static final int GetCityHuntingOfferRsp = 4747; - public static final int GetCityReputationInfoReq = 2860; - public static final int GetCityReputationInfoRsp = 2833; - public static final int GetCityReputationMapInfoReq = 2891; - public static final int GetCityReputationMapInfoRsp = 2897; - public static final int GetCompoundDataReq = 127; - public static final int GetCompoundDataRsp = 102; - public static final int GetDailyDungeonEntryInfoReq = 913; - public static final int GetDailyDungeonEntryInfoRsp = 936; - public static final int GetDungeonEntryExploreConditionReq = 3208; - public static final int GetDungeonEntryExploreConditionRsp = 3391; - public static final int GetExpeditionAssistInfoListReq = 2124; - public static final int GetExpeditionAssistInfoListRsp = 2168; - public static final int GetFriendShowAvatarInfoReq = 4061; - public static final int GetFriendShowAvatarInfoRsp = 4038; - public static final int GetFriendShowNameCardInfoReq = 4032; - public static final int GetFriendShowNameCardInfoRsp = 4051; - public static final int GetFurnitureCurModuleArrangeCountReq = 4618; - public static final int GetGachaInfoReq = 1560; - public static final int GetGachaInfoRsp = 1533; - public static final int GetHomeLevelUpRewardReq = 4508; - public static final int GetHomeLevelUpRewardRsp = 4864; - public static final int GetHuntingOfferRewardReq = 4769; - public static final int GetHuntingOfferRewardRsp = 4860; - public static final int GetInvestigationMonsterReq = 1928; - public static final int GetInvestigationMonsterRsp = 1921; - public static final int GetMailItemReq = 1415; - public static final int GetMailItemRsp = 1437; - public static final int GetMapAreaReq = 3269; - public static final int GetMapAreaRsp = 3366; - public static final int GetMapMarkTipsReq = 3307; - public static final int GetMapMarkTipsRsp = 3040; - public static final int GetMechanicusInfoReq = 3960; - public static final int GetMechanicusInfoRsp = 3933; - public static final int GetNextResourceInfoReq = 139; - public static final int GetNextResourceInfoRsp = 187; - public static final int GetOnlinePlayerInfoReq = 46; - public static final int GetOnlinePlayerInfoRsp = 74; - public static final int GetOnlinePlayerListReq = 45; - public static final int GetOnlinePlayerListRsp = 75; - public static final int GetOpActivityInfoReq = 5160; - public static final int GetOpActivityInfoRsp = 5133; - public static final int GetPlayerAskFriendListReq = 4054; - public static final int GetPlayerAskFriendListRsp = 4035; - public static final int GetPlayerBlacklistReq = 4002; - public static final int GetPlayerBlacklistRsp = 4052; - public static final int GetPlayerFriendListReq = 4060; - public static final int GetPlayerFriendListRsp = 4033; - public static final int GetPlayerHomeCompInfoReq = 4540; - public static final int GetPlayerMpModeAvailabilityReq = 1843; - public static final int GetPlayerMpModeAvailabilityRsp = 1826; - public static final int GetPlayerSocialDetailReq = 4075; - public static final int GetPlayerSocialDetailRsp = 4034; - public static final int GetPlayerTokenReq = 160; - public static final int GetPlayerTokenRsp = 133; - public static final int GetPushTipsRewardReq = 2265; - public static final int GetPushTipsRewardRsp = 2203; - public static final int GetQuestTalkHistoryReq = 445; - public static final int GetQuestTalkHistoryRsp = 475; - public static final int GetRecentMpPlayerListReq = 4066; - public static final int GetRecentMpPlayerListRsp = 4073; - public static final int GetRegionSearchReq = 5613; - public static final int GetReunionMissionInfoReq = 5093; - public static final int GetReunionMissionInfoRsp = 5076; - public static final int GetReunionPrivilegeInfoReq = 5089; - public static final int GetReunionPrivilegeInfoRsp = 5071; - public static final int GetReunionSignInInfoReq = 5063; - public static final int GetReunionSignInInfoRsp = 5051; - public static final int GetSceneAreaReq = 262; - public static final int GetSceneAreaRsp = 289; - public static final int GetSceneNpcPositionReq = 515; - public static final int GetSceneNpcPositionRsp = 537; - public static final int GetScenePerformanceReq = 3217; - public static final int GetScenePerformanceRsp = 3319; - public static final int GetScenePointReq = 288; - public static final int GetScenePointRsp = 228; - public static final int GetShopmallDataReq = 737; - public static final int GetShopmallDataRsp = 793; - public static final int GetShopReq = 760; - public static final int GetShopRsp = 733; - public static final int GetSignInRewardReq = 2537; - public static final int GetSignInRewardRsp = 2593; - public static final int GetWidgetSlotReq = 4258; - public static final int GetWidgetSlotRsp = 4294; - public static final int GetWorldMpInfoReq = 3439; - public static final int GetWorldMpInfoRsp = 3424; - public static final int GiveUpRoguelikeDungeonCardReq = 8425; - public static final int GiveUpRoguelikeDungeonCardRsp = 8976; - public static final int GivingRecordChangeNotify = 172; - public static final int GivingRecordNotify = 153; - public static final int GMShowNavMeshReq = 2384; - public static final int GMShowNavMeshRsp = 2312; - public static final int GMShowObstacleReq = 2332; - public static final int GMShowObstacleRsp = 2351; - public static final int GmTalkNotify = 3; - public static final int GmTalkReq = 33; - public static final int GmTalkRsp = 10; - public static final int GrantRewardNotify = 680; - public static final int GroupLinkAllNotify = 5785; - public static final int GroupLinkChangeNotify = 5775; - public static final int GroupLinkDeleteNotify = 5795; - public static final int GroupSuiteNotify = 3368; - public static final int GroupUnloadNotify = 3019; - public static final int GuestBeginEnterSceneNotify = 3033; - public static final int GuestPostEnterSceneNotify = 3198; - public static final int H5ActivityIdsNotify = 5695; - public static final int HideAndSeekPlayerReadyNotify = 5330; - public static final int HideAndSeekPlayerSetAvatarNotify = 5347; - public static final int HideAndSeekSelectAvatarReq = 5313; - public static final int HideAndSeekSelectAvatarRsp = 5336; - public static final int HideAndSeekSelectSkillReq = 8689; - public static final int HideAndSeekSelectSkillRsp = 8948; - public static final int HideAndSeekSetReadyReq = 5324; - public static final int HideAndSeekSetReadyRsp = 5361; - public static final int HideAndSeekSettleNotify = 5338; - public static final int HitClientTrivialNotify = 250; - public static final int HitTreeNotify = 3432; - public static final int HomeAvatarAllFinishRewardNotify = 4612; - public static final int HomeAvatarCostumeChangeNotify = 4888; - public static final int HomeAvatarRewardEventGetReq = 4568; - public static final int HomeAvatarRewardEventGetRsp = 4453; - public static final int HomeAvatarRewardEventNotify = 4801; - public static final int HomeAvatarSummonAllEventNotify = 4575; - public static final int HomeAvatarSummonEventReq = 4871; - public static final int HomeAvatarSummonEventRsp = 4895; - public static final int HomeAvatarSummonFinishReq = 4654; - public static final int HomeAvatarSummonFinishRsp = 4503; - public static final int HomeAvatarTalkFinishInfoNotify = 4800; - public static final int HomeAvatarTalkReq = 4610; - public static final int HomeAvatarTalkRsp = 4507; - public static final int HomeAvtarAllFinishRewardNotify = 4546; - public static final int HomeBasicInfoNotify = 4869; - public static final int HomeBlockNotify = 4784; - public static final int HomeChangeEditModeReq = 4483; - public static final int HomeChangeEditModeRsp = 4880; - public static final int HomeChangeModuleReq = 4604; - public static final int HomeChangeModuleRsp = 4631; - public static final int HomeChooseModuleReq = 4567; - public static final int HomeChooseModuleRsp = 4633; + public static final int GetBattlePassProductReq = 2616; + public static final int GetBattlePassProductRsp = 2601; + public static final int GetBlossomBriefInfoListReq = 2709; + public static final int GetBlossomBriefInfoListRsp = 2731; + public static final int GetBonusActivityRewardReq = 2597; + public static final int GetBonusActivityRewardRsp = 2598; + public static final int GetChatEmojiCollectionReq = 4005; + public static final int GetChatEmojiCollectionRsp = 4010; + public static final int GetCityHuntingOfferReq = 4343; + public static final int GetCityHuntingOfferRsp = 4304; + public static final int GetCityReputationInfoReq = 2809; + public static final int GetCityReputationInfoRsp = 2831; + public static final int GetCityReputationMapInfoReq = 2827; + public static final int GetCityReputationMapInfoRsp = 2807; + public static final int GetCompoundDataReq = 128; + public static final int GetCompoundDataRsp = 176; + public static final int GetDailyDungeonEntryInfoReq = 929; + public static final int GetDailyDungeonEntryInfoRsp = 925; + public static final int GetDungeonEntryExploreConditionReq = 3136; + public static final int GetDungeonEntryExploreConditionRsp = 3099; + public static final int GetExpeditionAssistInfoListReq = 2181; + public static final int GetExpeditionAssistInfoListRsp = 2045; + public static final int GetFriendShowAvatarInfoReq = 4003; + public static final int GetFriendShowAvatarInfoRsp = 4034; + public static final int GetFriendShowNameCardInfoReq = 4093; + public static final int GetFriendShowNameCardInfoRsp = 4060; + public static final int GetFurnitureCurModuleArrangeCountReq = 4603; + public static final int GetGachaInfoReq = 1509; + public static final int GetGachaInfoRsp = 1531; + public static final int GetHomeLevelUpRewardReq = 4747; + public static final int GetHomeLevelUpRewardRsp = 4517; + public static final int GetHuntingOfferRewardReq = 4328; + public static final int GetHuntingOfferRewardRsp = 4303; + public static final int GetInvestigationMonsterReq = 1902; + public static final int GetInvestigationMonsterRsp = 1911; + public static final int GetMailItemReq = 1437; + public static final int GetMailItemRsp = 1432; + public static final int GetMapAreaReq = 3466; + public static final int GetMapAreaRsp = 3012; + public static final int GetMapMarkTipsReq = 3329; + public static final int GetMapMarkTipsRsp = 3118; + public static final int GetMechanicusInfoReq = 3909; + public static final int GetMechanicusInfoRsp = 3931; + public static final int GetNextResourceInfoReq = 153; + public static final int GetNextResourceInfoRsp = 139; + public static final int GetOnlinePlayerInfoReq = 45; + public static final int GetOnlinePlayerInfoRsp = 90; + public static final int GetOnlinePlayerListReq = 35; + public static final int GetOnlinePlayerListRsp = 49; + public static final int GetOpActivityInfoReq = 5109; + public static final int GetOpActivityInfoRsp = 5131; + public static final int GetPlayerAskFriendListReq = 4008; + public static final int GetPlayerAskFriendListRsp = 4004; + public static final int GetPlayerBlacklistReq = 4076; + public static final int GetPlayerBlacklistRsp = 4072; + public static final int GetPlayerFriendListReq = 4009; + public static final int GetPlayerFriendListRsp = 4031; + public static final int GetPlayerHomeCompInfoReq = 4845; + public static final int GetPlayerMpModeAvailabilityReq = 1816; + public static final int GetPlayerMpModeAvailabilityRsp = 1801; + public static final int GetPlayerSocialDetailReq = 4049; + public static final int GetPlayerSocialDetailRsp = 4082; + public static final int GetPlayerTokenReq = 109; + public static final int GetPlayerTokenRsp = 131; + public static final int GetPushTipsRewardReq = 2212; + public static final int GetPushTipsRewardRsp = 2258; + public static final int GetQuestTalkHistoryReq = 435; + public static final int GetQuestTalkHistoryRsp = 449; + public static final int GetRecentMpPlayerListReq = 4011; + public static final int GetRecentMpPlayerListRsp = 4022; + public static final int GetRegionSearchReq = 5628; + public static final int GetReunionMissionInfoReq = 5066; + public static final int GetReunionMissionInfoRsp = 5051; + public static final int GetReunionPrivilegeInfoReq = 5062; + public static final int GetReunionPrivilegeInfoRsp = 5096; + public static final int GetReunionSignInInfoReq = 5078; + public static final int GetReunionSignInInfoRsp = 5053; + public static final int GetSceneAreaReq = 238; + public static final int GetSceneAreaRsp = 206; + public static final int GetSceneNpcPositionReq = 537; + public static final int GetSceneNpcPositionRsp = 532; + public static final int GetScenePerformanceReq = 3340; + public static final int GetScenePerformanceRsp = 3447; + public static final int GetScenePointReq = 230; + public static final int GetScenePointRsp = 297; + public static final int GetShopmallDataReq = 732; + public static final int GetShopmallDataRsp = 717; + public static final int GetShopReq = 709; + public static final int GetShopRsp = 731; + public static final int GetSignInRewardReq = 2532; + public static final int GetSignInRewardRsp = 2517; + public static final int GetWidgetSlotReq = 4267; + public static final int GetWidgetSlotRsp = 4300; + public static final int GetWorldMpInfoReq = 3264; + public static final int GetWorldMpInfoRsp = 3179; + public static final int GiveUpRoguelikeDungeonCardReq = 8977; + public static final int GiveUpRoguelikeDungeonCardRsp = 8583; + public static final int GivingRecordChangeNotify = 189; + public static final int GivingRecordNotify = 187; + public static final int GMShowNavMeshReq = 2377; + public static final int GMShowNavMeshRsp = 2343; + public static final int GMShowObstacleReq = 2393; + public static final int GMShowObstacleRsp = 2360; + public static final int GmTalkNotify = 58; + public static final int GmTalkReq = 31; + public static final int GmTalkRsp = 41; + public static final int GrantRewardNotify = 613; + public static final int GroupLinkAllNotify = 5768; + public static final int GroupLinkChangeNotify = 5759; + public static final int GroupLinkDeleteNotify = 5793; + public static final int GroupSuiteNotify = 3476; + public static final int GroupUnloadNotify = 3416; + public static final int GuestBeginEnterSceneNotify = 3125; + public static final int GuestPostEnterSceneNotify = 3379; + public static final int H5ActivityIdsNotify = 5693; + public static final int HideAndSeekPlayerReadyNotify = 5302; + public static final int HideAndSeekPlayerSetAvatarNotify = 5316; + public static final int HideAndSeekSelectAvatarReq = 5329; + public static final int HideAndSeekSelectAvatarRsp = 5325; + public static final int HideAndSeekSelectSkillReq = 8307; + public static final int HideAndSeekSelectSkillRsp = 8227; + public static final int HideAndSeekSetReadyReq = 5383; + public static final int HideAndSeekSetReadyRsp = 5303; + public static final int HideAndSeekSettleNotify = 5334; + public static final int HitClientTrivialNotify = 218; + public static final int HitTreeNotify = 3222; + public static final int HomeAvatarAllFinishRewardNotify = 4648; + public static final int HomeAvatarCostumeChangeNotify = 4685; + public static final int HomeAvatarRewardEventGetReq = 4775; + public static final int HomeAvatarRewardEventGetRsp = 4873; + public static final int HomeAvatarRewardEventNotify = 4789; + public static final int HomeAvatarSummonAllEventNotify = 4617; + public static final int HomeAvatarSummonEventReq = 4615; + public static final int HomeAvatarSummonEventRsp = 4498; + public static final int HomeAvatarSummonFinishReq = 4748; + public static final int HomeAvatarSummonFinishRsp = 4782; + public static final int HomeAvatarTalkFinishInfoNotify = 4502; + public static final int HomeAvatarTalkReq = 4712; + public static final int HomeAvatarTalkRsp = 4700; + public static final int HomeAvtarAllFinishRewardNotify = 4849; + public static final int HomeBasicInfoNotify = 4872; + public static final int HomeBlockNotify = 4542; + public static final int HomeChangeEditModeReq = 4625; + public static final int HomeChangeEditModeRsp = 4885; + public static final int HomeChangeModuleReq = 4688; + public static final int HomeChangeModuleRsp = 4821; + public static final int HomeChooseModuleReq = 4479; + public static final int HomeChooseModuleRsp = 4745; public static final int HomeComfortInfoNotify = 4649; - public static final int HomeCustomFurnitureInfoNotify = 4636; - public static final int HomeEditCustomFurnitureReq = 4621; - public static final int HomeEditCustomFurnitureRsp = 4804; - public static final int HomeFishFarmingInfoNotify = 4893; - public static final int HomeGetArrangementInfoReq = 4480; - public static final int HomeGetArrangementInfoRsp = 4781; - public static final int HomeGetBasicInfoReq = 4839; - public static final int HomeGetFishFarmingInfoReq = 4848; - public static final int HomeGetFishFarmingInfoRsp = 4451; - public static final int HomeGetOnlineStatusReq = 4673; - public static final int HomeGetOnlineStatusRsp = 4626; - public static final int HomeKickPlayerReq = 4547; - public static final int HomeKickPlayerRsp = 4897; - public static final int HomeLimitedShopBuyGoodsReq = 4620; - public static final int HomeLimitedShopBuyGoodsRsp = 4667; - public static final int HomeLimitedShopGoodsListReq = 4706; - public static final int HomeLimitedShopGoodsListRsp = 4587; - public static final int HomeLimitedShopInfoChangeNotify = 4691; - public static final int HomeLimitedShopInfoNotify = 4679; - public static final int HomeLimitedShopInfoReq = 4715; - public static final int HomeLimitedShopInfoRsp = 4808; - public static final int HomeMarkPointNotify = 4764; - public static final int HomeModuleSeenReq = 4642; - public static final int HomeModuleSeenRsp = 4688; - public static final int HomeModuleUnlockNotify = 4778; - public static final int HomePlantFieldNotify = 4529; - public static final int HomePlantInfoNotify = 4832; - public static final int HomePlantInfoReq = 4771; - public static final int HomePlantInfoRsp = 4806; - public static final int HomePlantSeedReq = 4730; - public static final int HomePlantSeedRsp = 4857; - public static final int HomePlantWeedReq = 4760; - public static final int HomePlantWeedRsp = 4463; - public static final int HomePriorCheckNotify = 4601; - public static final int HomeResourceNotify = 4513; - public static final int HomeResourceTakeFetterExpReq = 4884; - public static final int HomeResourceTakeFetterExpRsp = 4608; - public static final int HomeResourceTakeHomeCoinReq = 4812; - public static final int HomeResourceTakeHomeCoinRsp = 4481; - public static final int HomeSceneInitFinishReq = 4520; - public static final int HomeSceneInitFinishRsp = 4605; - public static final int HomeSceneJumpReq = 4862; - public static final int HomeSceneJumpRsp = 4663; - public static final int HomeTransferReq = 4656; - public static final int HomeTransferRsp = 4669; - public static final int HomeUpdateArrangementInfoReq = 4632; - public static final int HomeUpdateArrangementInfoRsp = 4820; - public static final int HomeUpdateFishFarmingInfoReq = 4810; - public static final int HomeUpdateFishFarmingInfoRsp = 4500; - public static final int HostPlayerNotify = 310; - public static final int HuntingFailNotify = 4345; - public static final int HuntingGiveUpReq = 4313; - public static final int HuntingGiveUpRsp = 4301; - public static final int HuntingOngoingNotify = 4348; - public static final int HuntingRevealClueNotify = 4564; - public static final int HuntingRevealFinalNotify = 4335; - public static final int HuntingStartNotify = 4694; - public static final int HuntingSuccessNotify = 4325; - public static final int InBattleMechanicusBuildingPointsNotify = 5344; - public static final int InBattleMechanicusCardResultNotify = 5388; - public static final int InBattleMechanicusConfirmCardNotify = 5397; - public static final int InBattleMechanicusConfirmCardReq = 5379; - public static final int InBattleMechanicusConfirmCardRsp = 5391; - public static final int InBattleMechanicusExcapeMonsterNotify = 5337; - public static final int InBattleMechanicusLeftMonsterNotify = 5393; - public static final int InBattleMechanicusPickCardNotify = 5334; - public static final int InBattleMechanicusPickCardReq = 5345; - public static final int InBattleMechanicusPickCardRsp = 5375; - public static final int InBattleMechanicusSettleNotify = 5355; - public static final int InteractDailyDungeonInfoNotify = 947; - public static final int InterruptGalleryReq = 5597; - public static final int InterruptGalleryRsp = 5588; - public static final int InvestigationMonsterUpdateNotify = 1918; - public static final int ItemAddHintNotify = 637; - public static final int ItemCdGroupTimeNotify = 666; - public static final int ItemExceedLimitNotify = 639; - public static final int ItemGivingReq = 170; - public static final int ItemGivingRsp = 154; - public static final int JoinHomeWorldFailNotify = 4502; - public static final int JoinPlayerFailNotify = 295; - public static final int JoinPlayerSceneReq = 239; - public static final int JoinPlayerSceneRsp = 287; - public static final int KeepAliveNotify = 60; - public static final int LeaveSceneReq = 233; - public static final int LeaveSceneRsp = 210; - public static final int LeaveWorldNotify = 3203; - public static final int LevelupCityReq = 253; - public static final int LevelupCityRsp = 272; - public static final int LifeStateChangeNotify = 1233; + public static final int HomeCustomFurnitureInfoNotify = 4482; + public static final int HomeEditCustomFurnitureReq = 4516; + public static final int HomeEditCustomFurnitureRsp = 4871; + public static final int HomeFishFarmingInfoNotify = 4682; + public static final int HomeGetArrangementInfoReq = 4848; + public static final int HomeGetArrangementInfoRsp = 4456; + public static final int HomeGetBasicInfoReq = 4535; + public static final int HomeGetFishFarmingInfoReq = 4455; + public static final int HomeGetFishFarmingInfoRsp = 4889; + public static final int HomeGetOnlineStatusReq = 4796; + public static final int HomeGetOnlineStatusRsp = 4554; + public static final int HomeKickPlayerReq = 4809; + public static final int HomeKickPlayerRsp = 4752; + public static final int HomeLimitedShopBuyGoodsReq = 4638; + public static final int HomeLimitedShopBuyGoodsRsp = 4790; + public static final int HomeLimitedShopGoodsListReq = 4579; + public static final int HomeLimitedShopGoodsListRsp = 4846; + public static final int HomeLimitedShopInfoChangeNotify = 4814; + public static final int HomeLimitedShopInfoNotify = 4621; + public static final int HomeLimitedShopInfoReq = 4616; + public static final int HomeLimitedShopInfoRsp = 4585; + public static final int HomeMarkPointNotify = 4746; + public static final int HomeModuleSeenReq = 4546; + public static final int HomeModuleSeenRsp = 4526; + public static final int HomeModuleUnlockNotify = 4781; + public static final int HomePlantFieldNotify = 4466; + public static final int HomePlantInfoNotify = 4835; + public static final int HomePlantInfoReq = 4833; + public static final int HomePlantInfoRsp = 4859; + public static final int HomePlantSeedReq = 4614; + public static final int HomePlantSeedRsp = 4804; + public static final int HomePlantWeedReq = 4877; + public static final int HomePlantWeedRsp = 4575; + public static final int HomePriorCheckNotify = 4690; + public static final int HomeResourceNotify = 4806; + public static final int HomeResourceTakeFetterExpReq = 4840; + public static final int HomeResourceTakeFetterExpRsp = 4500; + public static final int HomeResourceTakeHomeCoinReq = 4763; + public static final int HomeResourceTakeHomeCoinRsp = 4658; + public static final int HomeSceneInitFinishReq = 4552; + public static final int HomeSceneInitFinishRsp = 4592; + public static final int HomeSceneJumpReq = 4659; + public static final int HomeSceneJumpRsp = 4570; + public static final int HomeTransferReq = 4880; + public static final int HomeTransferRsp = 4767; + public static final int HomeUpdateArrangementInfoReq = 4472; + public static final int HomeUpdateArrangementInfoRsp = 4822; + public static final int HomeUpdateFishFarmingInfoReq = 4604; + public static final int HomeUpdateFishFarmingInfoRsp = 4856; + public static final int HostPlayerNotify = 341; + public static final int HuntingFailNotify = 4302; + public static final int HuntingGiveUpReq = 4337; + public static final int HuntingGiveUpRsp = 4332; + public static final int HuntingOngoingNotify = 4313; + public static final int HuntingRevealClueNotify = 4347; + public static final int HuntingRevealFinalNotify = 4316; + public static final int HuntingStartNotify = 4326; + public static final int HuntingSuccessNotify = 4301; + public static final int InBattleMechanicusBuildingPointsNotify = 5385; + public static final int InBattleMechanicusCardResultNotify = 5330; + public static final int InBattleMechanicusConfirmCardNotify = 5307; + public static final int InBattleMechanicusConfirmCardReq = 5355; + public static final int InBattleMechanicusConfirmCardRsp = 5327; + public static final int InBattleMechanicusExcapeMonsterNotify = 5332; + public static final int InBattleMechanicusLeftMonsterNotify = 5317; + public static final int InBattleMechanicusPickCardNotify = 5382; + public static final int InBattleMechanicusPickCardReq = 5335; + public static final int InBattleMechanicusPickCardRsp = 5349; + public static final int InBattleMechanicusSettleNotify = 5398; + public static final int InteractDailyDungeonInfoNotify = 916; + public static final int InterruptGalleryReq = 5507; + public static final int InterruptGalleryRsp = 5530; + public static final int InvestigationMonsterUpdateNotify = 1922; + public static final int ItemAddHintNotify = 632; + public static final int ItemCdGroupTimeNotify = 611; + public static final int ItemGivingReq = 178; + public static final int ItemGivingRsp = 108; + public static final int JoinHomeWorldFailNotify = 4863; + public static final int JoinPlayerFailNotify = 268; + public static final int JoinPlayerSceneReq = 253; + public static final int JoinPlayerSceneRsp = 239; + public static final int KeepAliveNotify = 9; + public static final int LeaveSceneReq = 231; + public static final int LeaveSceneRsp = 241; + public static final int LeaveWorldNotify = 3420; + public static final int LevelupCityReq = 287; + public static final int LevelupCityRsp = 289; + public static final int LifeStateChangeNotify = 1231; public static final int LiveEndNotify = 801; public static final int LiveStartNotify = 820; - public static final int LoadActivityTerrainNotify = 2152; - public static final int LuaEnvironmentEffectNotify = 3175; - public static final int LuaSetOptionNotify = 353; - public static final int LunaRiteAreaFinishNotify = 8822; - public static final int LunaRiteGroupBundleRegisterNotify = 8956; - public static final int LunaRiteHintPointRemoveNotify = 8544; - public static final int LunaRiteHintPointReq = 8173; - public static final int LunaRiteHintPointRsp = 8129; - public static final int LunaRiteSacrificeReq = 8364; - public static final int LunaRiteSacrificeRsp = 8328; - public static final int LunaRiteTakeSacrificeRewardReq = 8987; - public static final int LunaRiteTakeSacrificeRewardRsp = 8352; - public static final int MailChangeNotify = 1433; - public static final int MainCoopUpdateNotify = 1975; - public static final int MapAreaChangeNotify = 3055; - public static final int MarkEntityInMinMapNotify = 230; - public static final int MarkMapReq = 3053; - public static final int MarkMapRsp = 3139; - public static final int MarkNewNotify = 1291; - public static final int MarkTargetInvestigationMonsterNotify = 1924; - public static final int MassiveEntityElementOpBatchNotify = 384; - public static final int MassiveEntityStateChangedNotify = 361; - public static final int MaterialDeleteReturnNotify = 632; - public static final int MaterialDeleteUpdateNotify = 612; - public static final int McoinExchangeHcoinReq = 653; - public static final int McoinExchangeHcoinRsp = 672; - public static final int MechanicusCandidateTeamCreateReq = 3928; - public static final int MechanicusCandidateTeamCreateRsp = 3955; - public static final int MechanicusCloseNotify = 3993; - public static final int MechanicusCoinNotify = 3915; - public static final int MechanicusLevelupGearReq = 3975; - public static final int MechanicusLevelupGearRsp = 3934; - public static final int MechanicusOpenNotify = 3937; - public static final int MechanicusSequenceOpenNotify = 3910; - public static final int MechanicusUnlockGearReq = 3944; - public static final int MechanicusUnlockGearRsp = 3945; - public static final int MeetNpcReq = 544; - public static final int MeetNpcRsp = 545; - public static final int MetNpcIdListNotify = 593; - public static final int MiracleRingDataNotify = 5245; - public static final int MiracleRingDeliverItemReq = 5217; - public static final int MiracleRingDeliverItemRsp = 5236; - public static final int MiracleRingDestroyNotify = 5243; - public static final int MiracleRingDropResultNotify = 5201; - public static final int MiracleRingTakeRewardReq = 5248; - public static final int MiracleRingTakeRewardRsp = 5213; - public static final int MistTrialDunegonFailNotify = 8337; - public static final int MistTrialGetChallengeMissionReq = 8250; - public static final int MistTrialGetChallengeMissionRsp = 8894; - public static final int MistTrialSelectAvatarAndEnterDungeonReq = 8186; - public static final int MistTrialSelectAvatarAndEnterDungeonRsp = 8522; - public static final int MonsterAIConfigHashNotify = 3024; - public static final int MonsterAlertChangeNotify = 380; - public static final int MonsterForceAlertNotify = 364; - public static final int MonsterPointArrayRouteUpdateNotify = 3292; - public static final int MonsterSummonTagNotify = 1360; - public static final int MpBlockNotify = 1824; - public static final int MpPlayGuestReplyInviteReq = 1850; - public static final int MpPlayGuestReplyInviteRsp = 1822; - public static final int MpPlayGuestReplyNotify = 1802; - public static final int MpPlayInviteResultNotify = 1830; - public static final int MpPlayOwnerCheckReq = 1812; - public static final int MpPlayOwnerCheckRsp = 1839; - public static final int MpPlayOwnerInviteNotify = 1831; - public static final int MpPlayOwnerStartInviteReq = 1821; - public static final int MpPlayOwnerStartInviteRsp = 1846; - public static final int MpPlayPrepareInterruptNotify = 1838; - public static final int MpPlayPrepareNotify = 1833; - public static final int MultistagePlayEndNotify = 5307; - public static final int MultistagePlayFinishStageReq = 5333; - public static final int MultistagePlayFinishStageRsp = 5328; - public static final int MultistagePlayInfoNotify = 5360; - public static final int MultistagePlaySettleNotify = 5318; - public static final int MultistagePlayStageEndNotify = 5321; - public static final int MusicGameSettleReq = 8851; - public static final int MusicGameSettleRsp = 8028; - public static final int MusicGameStartReq = 8760; - public static final int MusicGameStartRsp = 8922; - public static final int NavMeshStatsNotify = 2353; - public static final int NormalUidOpNotify = 5735; - public static final int NpcTalkReq = 560; - public static final int NpcTalkRsp = 533; - public static final int ObstacleModifyNotify = 2310; - public static final int OfferingInteractReq = 2916; - public static final int OfferingInteractRsp = 2912; - public static final int OneoffGatherPointDetectorDataNotify = 4289; - public static final int OpActivityDataNotify = 5110; - public static final int OpActivityStateNotify = 2560; - public static final int OpActivityUpdateNotify = 5115; - public static final int OpenBlossomCircleCampGuideNotify = 2744; - public static final int OpenStateChangeNotify = 165; - public static final int OpenStateUpdateNotify = 109; - public static final int OrderDisplayNotify = 4101; - public static final int OrderFinishNotify = 4145; - public static final int OtherPlayerEnterHomeNotify = 4591; - public static final int PacketHead = 13371337; - public static final int PathfindingEnterSceneReq = 2337; - public static final int PathfindingEnterSceneRsp = 2393; - public static final int PathfindingPingNotify = 2315; - public static final int PersonalLineAllDataReq = 408; - public static final int PersonalLineAllDataRsp = 417; - public static final int PersonalLineNewUnlockNotify = 423; - public static final int PersonalSceneJumpReq = 286; - public static final int PersonalSceneJumpRsp = 277; - public static final int PingReq = 37; - public static final int PingRsp = 93; - public static final int PlantFlowerAcceptAllGiveFlowerReq = 8775; - public static final int PlantFlowerAcceptAllGiveFlowerRsp = 8174; - public static final int PlantFlowerAcceptGiveFlowerReq = 8525; - public static final int PlantFlowerAcceptGiveFlowerRsp = 8957; - public static final int PlantFlowerEditFlowerCombinationReq = 8347; - public static final int PlantFlowerEditFlowerCombinationRsp = 8625; - public static final int PlantFlowerGetCanGiveFriendFlowerReq = 8617; - public static final int PlantFlowerGetCanGiveFriendFlowerRsp = 8091; - public static final int PlantFlowerGetFriendFlowerWishListReq = 8893; - public static final int PlantFlowerGetFriendFlowerWishListRsp = 8476; - public static final int PlantFlowerGetRecvFlowerListReq = 8459; - public static final int PlantFlowerGetRecvFlowerListRsp = 8597; - public static final int PlantFlowerGetSeedInfoReq = 8535; - public static final int PlantFlowerGetSeedInfoRsp = 8584; - public static final int PlantFlowerGiveFriendFlowerReq = 8934; - public static final int PlantFlowerGiveFriendFlowerRsp = 8456; - public static final int PlantFlowerHaveRecvFlowerNotify = 8711; - public static final int PlantFlowerSetFlowerWishReq = 8601; - public static final int PlantFlowerSetFlowerWishRsp = 8550; - public static final int PlantFlowerTakeSeedRewardReq = 8317; - public static final int PlantFlowerTakeSeedRewardRsp = 8152; - public static final int PlatformChangeRouteNotify = 257; - public static final int PlatformStartRouteNotify = 254; - public static final int PlatformStopRouteNotify = 235; - public static final int PlayerAllowEnterMpAfterAgreeMatchNotify = 4176; - public static final int PlayerApplyEnterHomeNotify = 4614; - public static final int PlayerApplyEnterHomeResultNotify = 4580; - public static final int PlayerApplyEnterHomeResultReq = 4603; - public static final int PlayerApplyEnterHomeResultRsp = 4849; - public static final int PlayerApplyEnterMpAfterMatchAgreedNotify = 4177; - public static final int PlayerApplyEnterMpNotify = 1835; - public static final int PlayerApplyEnterMpReq = 1825; - public static final int PlayerApplyEnterMpResultNotify = 1848; - public static final int PlayerApplyEnterMpResultReq = 1813; - public static final int PlayerApplyEnterMpResultRsp = 1801; - public static final int PlayerApplyEnterMpRsp = 1845; - public static final int PlayerCancelMatchReq = 4198; - public static final int PlayerCancelMatchRsp = 4163; - public static final int PlayerChatCDNotify = 3173; - public static final int PlayerChatNotify = 3485; - public static final int PlayerChatReq = 3403; - public static final int PlayerChatRsp = 3045; - public static final int PlayerCompoundMaterialReq = 173; - public static final int PlayerCompoundMaterialRsp = 163; - public static final int PlayerConfirmMatchReq = 4186; - public static final int PlayerConfirmMatchRsp = 4193; - public static final int PlayerCookArgsReq = 135; - public static final int PlayerCookArgsRsp = 157; - public static final int PlayerCookReq = 103; - public static final int PlayerCookRsp = 167; - public static final int PlayerDataNotify = 145; - public static final int PlayerEnterDungeonReq = 910; - public static final int PlayerEnterDungeonRsp = 915; - public static final int PlayerEnterSceneInfoNotify = 294; - public static final int PlayerEnterSceneNotify = 260; - public static final int PlayerEyePointStateNotify = 3461; - public static final int PlayerFishingDataNotify = 5831; - public static final int PlayerForceExitReq = 125; - public static final int PlayerForceExitRsp = 149; - public static final int PlayerGameTimeNotify = 179; - public static final int PlayerGeneralMatchConfirmNotify = 4156; + public static final int LoadActivityTerrainNotify = 2175; + public static final int LuaEnvironmentEffectNotify = 3289; + public static final int LuaSetOptionNotify = 387; + public static final int LunaRiteAreaFinishNotify = 8107; + public static final int LunaRiteGroupBundleRegisterNotify = 8327; + public static final int LunaRiteHintPointRemoveNotify = 8420; + public static final int LunaRiteHintPointReq = 8342; + public static final int LunaRiteHintPointRsp = 8481; + public static final int LunaRiteSacrificeReq = 8062; + public static final int LunaRiteSacrificeRsp = 8401; + public static final int LunaRiteTakeSacrificeRewardReq = 8669; + public static final int LunaRiteTakeSacrificeRewardRsp = 8252; + public static final int MailChangeNotify = 1431; + public static final int MainCoopUpdateNotify = 1959; + public static final int MapAreaChangeNotify = 3103; + public static final int MarkEntityInMinMapNotify = 202; + public static final int MarkMapReq = 3208; + public static final int MarkMapRsp = 3421; + public static final int MarkNewNotify = 1227; + public static final int MarkTargetInvestigationMonsterNotify = 1928; + public static final int MassiveEntityElementOpBatchNotify = 377; + public static final int MassiveEntityStateChangedNotify = 303; + public static final int MaterialDeleteReturnNotify = 693; + public static final int MaterialDeleteUpdateNotify = 643; + public static final int McoinExchangeHcoinReq = 687; + public static final int McoinExchangeHcoinRsp = 689; + public static final int MechanicusCandidateTeamCreateReq = 3997; + public static final int MechanicusCandidateTeamCreateRsp = 3998; + public static final int MechanicusCloseNotify = 3917; + public static final int MechanicusCoinNotify = 3937; + public static final int MechanicusLevelupGearReq = 3949; + public static final int MechanicusLevelupGearRsp = 3982; + public static final int MechanicusOpenNotify = 3932; + public static final int MechanicusSequenceOpenNotify = 3941; + public static final int MechanicusUnlockGearReq = 3985; + public static final int MechanicusUnlockGearRsp = 3935; + public static final int MeetNpcReq = 585; + public static final int MeetNpcRsp = 535; + public static final int MetNpcIdListNotify = 517; + public static final int MiracleRingDataNotify = 5243; + public static final int MiracleRingDeliverItemReq = 5226; + public static final int MiracleRingDeliverItemRsp = 5247; + public static final int MiracleRingDestroyNotify = 5216; + public static final int MiracleRingDropResultNotify = 5203; + public static final int MiracleRingTakeRewardReq = 5204; + public static final int MiracleRingTakeRewardRsp = 5228; + public static final int MistTrialDunegonFailNotify = 8580; + public static final int MistTrialGetChallengeMissionReq = 8668; + public static final int MistTrialGetChallengeMissionRsp = 8385; + public static final int MistTrialSelectAvatarAndEnterDungeonReq = 8318; + public static final int MistTrialSelectAvatarAndEnterDungeonRsp = 8403; + public static final int MonsterAIConfigHashNotify = 3121; + public static final int MonsterAlertChangeNotify = 313; + public static final int MonsterForceAlertNotify = 342; + public static final int MonsterPointArrayRouteUpdateNotify = 3138; + public static final int MonsterSummonTagNotify = 1309; + public static final int MpBlockNotify = 1808; + public static final int MpPlayGuestReplyInviteReq = 1811; + public static final int MpPlayGuestReplyInviteRsp = 1841; + public static final int MpPlayGuestReplyNotify = 1805; + public static final int MpPlayInviteResultNotify = 1806; + public static final int MpPlayOwnerCheckReq = 1814; + public static final int MpPlayOwnerCheckRsp = 1812; + public static final int MpPlayOwnerInviteNotify = 1815; + public static final int MpPlayOwnerStartInviteReq = 1846; + public static final int MpPlayOwnerStartInviteRsp = 1827; + public static final int MpPlayPrepareInterruptNotify = 1848; + public static final int MpPlayPrepareNotify = 1839; + public static final int MultistagePlayEndNotify = 5375; + public static final int MultistagePlayFinishStageReq = 5331; + public static final int MultistagePlayFinishStageRsp = 5397; + public static final int MultistagePlayInfoNotify = 5309; + public static final int MultistagePlaySettleNotify = 5314; + public static final int MultistagePlayStageEndNotify = 5340; + public static final int MusicGameSettleReq = 8745; + public static final int MusicGameSettleRsp = 8288; + public static final int MusicGameStartReq = 8927; + public static final int MusicGameStartRsp = 8101; + public static final int NavMeshStatsNotify = 2387; + public static final int NormalUidOpNotify = 5718; + public static final int NpcTalkReq = 509; + public static final int NpcTalkRsp = 531; + public static final int ObstacleModifyNotify = 2341; + public static final int OfferingInteractReq = 2908; + public static final int OfferingInteractRsp = 2923; + public static final int OneoffGatherPointDetectorDataNotify = 4262; + public static final int OpActivityDataNotify = 5141; + public static final int OpActivityStateNotify = 2509; + public static final int OpActivityUpdateNotify = 5137; + public static final int OpenBlossomCircleCampGuideNotify = 2785; + public static final int OpenStateChangeNotify = 112; + public static final int OpenStateUpdateNotify = 119; + public static final int OrderDisplayNotify = 4103; + public static final int OrderFinishNotify = 4143; + public static final int OtherPlayerEnterHomeNotify = 4609; + public static final int PathfindingEnterSceneReq = 2332; + public static final int PathfindingEnterSceneRsp = 2317; + public static final int PathfindingPingNotify = 2337; + public static final int PersonalLineAllDataReq = 446; + public static final int PersonalLineAllDataRsp = 433; + public static final int PersonalLineNewUnlockNotify = 470; + public static final int PersonalSceneJumpReq = 266; + public static final int PersonalSceneJumpRsp = 248; + public static final int PingReq = 32; + public static final int PingRsp = 17; + public static final int PlantFlowerAcceptAllGiveFlowerReq = 8017; + public static final int PlantFlowerAcceptAllGiveFlowerRsp = 8831; + public static final int PlantFlowerAcceptGiveFlowerReq = 8137; + public static final int PlantFlowerAcceptGiveFlowerRsp = 8431; + public static final int PlantFlowerEditFlowerCombinationReq = 8506; + public static final int PlantFlowerEditFlowerCombinationRsp = 8335; + public static final int PlantFlowerGetCanGiveFriendFlowerReq = 8648; + public static final int PlantFlowerGetCanGiveFriendFlowerRsp = 8507; + public static final int PlantFlowerGetFriendFlowerWishListReq = 8840; + public static final int PlantFlowerGetFriendFlowerWishListRsp = 8553; + public static final int PlantFlowerGetRecvFlowerListReq = 8914; + public static final int PlantFlowerGetRecvFlowerListRsp = 8929; + public static final int PlantFlowerGetSeedInfoReq = 8913; + public static final int PlantFlowerGetSeedInfoRsp = 8932; + public static final int PlantFlowerGiveFriendFlowerReq = 8836; + public static final int PlantFlowerGiveFriendFlowerRsp = 8893; + public static final int PlantFlowerHaveRecvFlowerNotify = 8174; + public static final int PlantFlowerSetFlowerWishReq = 8650; + public static final int PlantFlowerSetFlowerWishRsp = 8588; + public static final int PlantFlowerTakeSeedRewardReq = 8182; + public static final int PlantFlowerTakeSeedRewardRsp = 8386; + public static final int PlatformChangeRouteNotify = 205; + public static final int PlatformStartRouteNotify = 208; + public static final int PlatformStopRouteNotify = 204; + public static final int PlayerAllowEnterMpAfterAgreeMatchNotify = 4151; + public static final int PlayerApplyEnterHomeNotify = 4504; + public static final int PlayerApplyEnterHomeResultNotify = 4766; + public static final int PlayerApplyEnterHomeResultReq = 4568; + public static final int PlayerApplyEnterHomeResultRsp = 4697; + public static final int PlayerApplyEnterMpAfterMatchAgreedNotify = 4163; + public static final int PlayerApplyEnterMpNotify = 1818; + public static final int PlayerApplyEnterMpReq = 1809; + public static final int PlayerApplyEnterMpResultNotify = 1804; + public static final int PlayerApplyEnterMpResultReq = 1828; + public static final int PlayerApplyEnterMpResultRsp = 1803; + public static final int PlayerApplyEnterMpRsp = 1843; + public static final int PlayerCancelMatchReq = 4154; + public static final int PlayerCancelMatchRsp = 4178; + public static final int PlayerChatCDNotify = 3464; + public static final int PlayerChatNotify = 3295; + public static final int PlayerChatReq = 3378; + public static final int PlayerChatRsp = 3321; + public static final int PlayerCompoundMaterialReq = 122; + public static final int PlayerCompoundMaterialRsp = 154; + public static final int PlayerConfirmMatchReq = 4197; + public static final int PlayerConfirmMatchRsp = 4166; + public static final int PlayerCookArgsReq = 104; + public static final int PlayerCookArgsRsp = 105; + public static final int PlayerCookReq = 158; + public static final int PlayerCookRsp = 150; + public static final int PlayerDataNotify = 135; + public static final int PlayerEnterDungeonReq = 941; + public static final int PlayerEnterDungeonRsp = 937; + public static final int PlayerEnterSceneInfoNotify = 274; + public static final int PlayerEnterSceneNotify = 209; + public static final int PlayerEyePointStateNotify = 3376; + public static final int PlayerFishingDataNotify = 5815; + public static final int PlayerForceExitReq = 173; + public static final int PlayerForceExitRsp = 161; + public static final int PlayerGameTimeNotify = 155; + public static final int PlayerGeneralMatchConfirmNotify = 4182; public static final int PlayerGeneralMatchDismissNotify = 4187; - public static final int PlayerGetForceQuitBanInfoReq = 4162; - public static final int PlayerGetForceQuitBanInfoRsp = 4189; - public static final int PlayerHomeCompInfoNotify = 4863; - public static final int PlayerInjectFixNotify = 185; - public static final int PlayerInvestigationAllInfoNotify = 1920; - public static final int PlayerInvestigationNotify = 1901; - public static final int PlayerInvestigationTargetNotify = 1919; - public static final int PlayerLevelRewardUpdateNotify = 112; - public static final int PlayerLoginReq = 110; - public static final int PlayerLoginRsp = 115; - public static final int PlayerLogoutNotify = 144; - public static final int PlayerLogoutReq = 137; - public static final int PlayerLogoutRsp = 193; - public static final int PlayerLuaShellNotify = 143; - public static final int PlayerMatchAgreedResultNotify = 4165; - public static final int PlayerMatchInfoNotify = 4195; - public static final int PlayerMatchStopNotify = 4151; - public static final int PlayerMatchSuccNotify = 4167; - public static final int PlayerOfferingDataNotify = 2915; - public static final int PlayerOfferingReq = 2914; - public static final int PlayerOfferingRsp = 2917; - public static final int PlayerPreEnterMpNotify = 1836; - public static final int PlayerPropChangeNotify = 156; - public static final int PlayerPropChangeReasonNotify = 1234; - public static final int PlayerPropNotify = 191; - public static final int PlayerQuitDungeonReq = 937; - public static final int PlayerQuitDungeonRsp = 993; - public static final int PlayerQuitFromHomeNotify = 4757; - public static final int PlayerQuitFromMpNotify = 1817; + public static final int PlayerGetForceQuitBanInfoReq = 4164; + public static final int PlayerGetForceQuitBanInfoRsp = 4162; + public static final int PlayerHomeCompInfoNotify = 4563; + public static final int PlayerInjectFixNotify = 188; + public static final int PlayerInvestigationAllInfoNotify = 1905; + public static final int PlayerInvestigationNotify = 1927; + public static final int PlayerInvestigationTargetNotify = 1906; + public static final int PlayerLevelRewardUpdateNotify = 143; + public static final int PlayerLoginReq = 141; + public static final int PlayerLoginRsp = 137; + public static final int PlayerLogoutNotify = 185; + public static final int PlayerLogoutReq = 132; + public static final int PlayerLogoutRsp = 117; + public static final int PlayerLuaShellNotify = 110; + public static final int PlayerMatchAgreedResultNotify = 4152; + public static final int PlayerMatchInfoNotify = 4193; + public static final int PlayerMatchStopNotify = 4153; + public static final int PlayerMatchSuccNotify = 4176; + public static final int PlayerOfferingDataNotify = 2901; + public static final int PlayerOfferingReq = 2906; + public static final int PlayerOfferingRsp = 2911; + public static final int PlayerPreEnterMpNotify = 1847; + public static final int PlayerPropChangeNotify = 186; + public static final int PlayerPropChangeReasonNotify = 1282; + public static final int PlayerPropNotify = 127; + public static final int PlayerQuitDungeonReq = 932; + public static final int PlayerQuitDungeonRsp = 917; + public static final int PlayerQuitFromHomeNotify = 4776; + public static final int PlayerQuitFromMpNotify = 1826; public static final int PlayerRandomCookReq = 120; - public static final int PlayerRandomCookRsp = 180; - public static final int PlayerRechargeDataNotify = 4113; - public static final int PlayerReportReq = 4092; - public static final int PlayerReportRsp = 4058; - public static final int PlayerRoutineDataNotify = 3535; - public static final int PlayerSetLanguageReq = 123; - public static final int PlayerSetLanguageRsp = 113; - public static final int PlayerSetOnlyMPWithPSPlayerReq = 1815; - public static final int PlayerSetOnlyMPWithPSPlayerRsp = 1827; - public static final int PlayerSetPauseReq = 192; - public static final int PlayerSetPauseRsp = 158; - public static final int PlayerStartMatchReq = 4185; - public static final int PlayerStartMatchRsp = 4175; - public static final int PlayerStoreNotify = 660; - public static final int PlayerTimeNotify = 152; - public static final int PlayerWorldSceneInfoListNotify = 3386; - public static final int PostEnterSceneReq = 3390; - public static final int PostEnterSceneRsp = 3213; - public static final int PrivateChatNotify = 4960; - public static final int PrivateChatReq = 5010; - public static final int PrivateChatRsp = 4983; - public static final int PrivateChatSetSequenceReq = 4965; - public static final int PrivateChatSetSequenceRsp = 4987; - public static final int ProfilePictureChangeNotify = 4053; - public static final int ProjectorOptionReq = 880; - public static final int ProjectorOptionRsp = 864; - public static final int ProudSkillChangeNotify = 1079; - public static final int ProudSkillExtraLevelNotify = 1028; - public static final int ProudSkillUpgradeReq = 1075; - public static final int ProudSkillUpgradeRsp = 1034; - public static final int PSNBlackListNotify = 4070; - public static final int PSNFriendListNotify = 4072; + public static final int PlayerRandomCookRsp = 113; + public static final int PlayerRechargeDataNotify = 4128; + public static final int PlayerReportReq = 4059; + public static final int PlayerReportRsp = 4084; + public static final int PlayerRoutineDataNotify = 3518; + public static final int PlayerSetLanguageReq = 170; + public static final int PlayerSetLanguageRsp = 129; + public static final int PlayerSetOnlyMPWithPSPlayerReq = 1802; + public static final int PlayerSetOnlyMPWithPSPlayerRsp = 1813; + public static final int PlayerSetPauseReq = 159; + public static final int PlayerSetPauseRsp = 184; + public static final int PlayerStartMatchReq = 4168; + public static final int PlayerStartMatchRsp = 4159; + public static final int PlayerStoreNotify = 609; + public static final int PlayerTimeNotify = 172; + public static final int PlayerWorldSceneInfoListNotify = 3172; + public static final int PostEnterSceneReq = 3097; + public static final int PostEnterSceneRsp = 3344; + public static final int PrivateChatNotify = 4991; + public static final int PrivateChatReq = 4959; + public static final int PrivateChatRsp = 4981; + public static final int PrivateChatSetSequenceReq = 4987; + public static final int PrivateChatSetSequenceRsp = 4982; + public static final int ProfilePictureChangeNotify = 4087; + public static final int ProjectorOptionReq = 813; + public static final int ProjectorOptionRsp = 842; + public static final int ProudSkillChangeNotify = 1055; + public static final int ProudSkillExtraLevelNotify = 1097; + public static final int ProudSkillUpgradeReq = 1049; + public static final int ProudSkillUpgradeRsp = 1082; + public static final int PSNBlackListNotify = 4078; + public static final int PSNFriendListNotify = 4089; public static final int PSPlayerApplyEnterMpReq = 1837; - public static final int PSPlayerApplyEnterMpRsp = 1806; - public static final int PullPrivateChatReq = 5043; - public static final int PullPrivateChatRsp = 4994; - public static final int PullRecentChatReq = 4995; - public static final int PullRecentChatRsp = 5025; - public static final int PushTipsAllDataNotify = 2226; - public static final int PushTipsChangeNotify = 2262; - public static final int PushTipsReadFinishReq = 2289; - public static final int PushTipsReadFinishRsp = 2209; + public static final int PSPlayerApplyEnterMpRsp = 1832; + public static final int PullPrivateChatReq = 4967; + public static final int PullPrivateChatRsp = 5035; + public static final int PullRecentChatReq = 4985; + public static final int PullRecentChatRsp = 4999; + public static final int PushTipsAllDataNotify = 2224; + public static final int PushTipsChangeNotify = 2238; + public static final int PushTipsReadFinishReq = 2206; + public static final int PushTipsReadFinishRsp = 2219; public static final int QueryCodexMonsterBeKilledNumReq = 4207; - public static final int QueryCodexMonsterBeKilledNumRsp = 4208; - public static final int QueryPathReq = 2360; - public static final int QueryPathRsp = 2333; - public static final int QuestCreateEntityReq = 434; - public static final int QuestCreateEntityRsp = 479; - public static final int QuestDelNotify = 410; - public static final int QuestDestroyEntityReq = 491; - public static final int QuestDestroyEntityRsp = 497; - public static final int QuestDestroyNpcReq = 426; - public static final int QuestDestroyNpcRsp = 462; - public static final int QuestGlobalVarNotify = 466; - public static final int QuestListNotify = 460; - public static final int QuestListUpdateNotify = 433; - public static final int QuestProgressUpdateNotify = 446; - public static final int QuestTransmitReq = 473; - public static final int QuestTransmitRsp = 463; - public static final int QuestUpdateQuestTimeVarNotify = 458; - public static final int QuestUpdateQuestVarNotify = 483; - public static final int QuestUpdateQuestVarReq = 474; - public static final int QuestUpdateQuestVarRsp = 456; - public static final int QuickUseWidgetReq = 4276; - public static final int QuickUseWidgetRsp = 4265; - public static final int ReadMailNotify = 1410; - public static final int ReadPrivateChatReq = 4984; - public static final int ReadPrivateChatRsp = 5029; - public static final int ReceivedTrialAvatarActivityRewardReq = 2020; - public static final int ReceivedTrialAvatarActivityRewardRsp = 2087; - public static final int RechargeReq = 4135; - public static final int RechargeRsp = 4125; - public static final int RedeemLegendaryKeyReq = 481; - public static final int RedeemLegendaryKeyRsp = 427; - public static final int RefreshBackgroundAvatarReq = 1744; - public static final int RefreshBackgroundAvatarRsp = 1719; - public static final int RefreshRoguelikeDungeonCardReq = 8433; - public static final int RefreshRoguelikeDungeonCardRsp = 8678; - public static final int RegionSearchChangeRegionNotify = 5625; - public static final int RegionSearchNotify = 5635; - public static final int ReliquaryDecomposeReq = 606; - public static final int ReliquaryDecomposeRsp = 659; - public static final int ReliquaryPromoteReq = 665; - public static final int ReliquaryPromoteRsp = 603; - public static final int ReliquaryUpgradeReq = 689; - public static final int ReliquaryUpgradeRsp = 609; - public static final int RemoveBlacklistReq = 4080; - public static final int RemoveBlacklistRsp = 4064; - public static final int RemoveRandTaskInfoNotify = 132; - public static final int ReportFightAntiCheatNotify = 357; - public static final int ReportTrackingIOInfoNotify = 4117; - public static final int RequestLiveInfoReq = 803; - public static final int RequestLiveInfoRsp = 867; - public static final int ResinCardDataUpdateNotify = 4126; - public static final int ResinChangeNotify = 623; - public static final int RestartEffigyChallengeReq = 2061; - public static final int RestartEffigyChallengeRsp = 2112; - public static final int ReunionActivateNotify = 5081; - public static final int ReunionBriefInfoReq = 5085; - public static final int ReunionBriefInfoRsp = 5075; - public static final int ReunionDailyRefreshNotify = 5072; - public static final int ReunionPrivilegeChangeNotify = 5100; - public static final int ReunionSettleNotify = 5096; - public static final int RobotPushPlayerDataNotify = 88; - public static final int RogueCellUpdateNotify = 8074; - public static final int RogueDungeonPlayerCellChangeNotify = 8784; - public static final int RogueHealAvatarsReq = 8959; - public static final int RogueHealAvatarsRsp = 8473; - public static final int RoguelikeCardGachaNotify = 8079; - public static final int RoguelikeEffectDataNotify = 8529; - public static final int RoguelikeEffectViewReq = 8396; - public static final int RoguelikeEffectViewRsp = 8040; - public static final int RoguelikeGiveUpReq = 8716; - public static final int RoguelikeGiveUpRsp = 8728; - public static final int RoguelikeMistClearNotify = 8471; - public static final int RoguelikeRefreshCardCostUpdateNotify = 8304; - public static final int RoguelikeResourceBonusPropUpdateNotify = 8312; - public static final int RoguelikeRuneRecordUpdateNotify = 8985; - public static final int RoguelikeSelectAvatarAndEnterDungeonReq = 8697; - public static final int RoguelikeSelectAvatarAndEnterDungeonRsp = 8377; - public static final int RoguelikeTakeStageFirstPassRewardReq = 8667; - public static final int RoguelikeTakeStageFirstPassRewardRsp = 8101; - public static final int RogueResumeDungeonReq = 8496; - public static final int RogueResumeDungeonRsp = 8759; - public static final int RogueSwitchAvatarReq = 8856; - public static final int RogueSwitchAvatarRsp = 8141; - public static final int SalesmanDeliverItemReq = 2103; - public static final int SalesmanDeliverItemRsp = 2198; - public static final int SalesmanTakeRewardReq = 2091; - public static final int SalesmanTakeRewardRsp = 2171; - public static final int SalesmanTakeSpecialRewardReq = 2156; - public static final int SalesmanTakeSpecialRewardRsp = 2102; - public static final int SaveCoopDialogReq = 1972; - public static final int SaveCoopDialogRsp = 1952; - public static final int SaveMainCoopReq = 1995; - public static final int SaveMainCoopRsp = 1998; - public static final int SceneAreaUnlockNotify = 209; - public static final int SceneAreaWeatherNotify = 213; - public static final int SceneAudioNotify = 3260; - public static final int SceneAvatarStaminaStepReq = 234; - public static final int SceneAvatarStaminaStepRsp = 279; - public static final int SceneCreateEntityReq = 267; + public static final int QueryCodexMonsterBeKilledNumRsp = 4205; + public static final int QueryPathReq = 2309; + public static final int QueryPathRsp = 2331; + public static final int QuestCreateEntityReq = 482; + public static final int QuestCreateEntityRsp = 455; + public static final int QuestDelNotify = 441; + public static final int QuestDestroyEntityReq = 427; + public static final int QuestDestroyEntityRsp = 407; + public static final int QuestDestroyNpcReq = 424; + public static final int QuestDestroyNpcRsp = 438; + public static final int QuestGlobalVarNotify = 411; + public static final int QuestListNotify = 409; + public static final int QuestListUpdateNotify = 431; + public static final int QuestProgressUpdateNotify = 445; + public static final int QuestTransmitReq = 422; + public static final int QuestTransmitRsp = 454; + public static final int QuestUpdateQuestTimeVarNotify = 484; + public static final int QuestUpdateQuestVarNotify = 463; + public static final int QuestUpdateQuestVarReq = 490; + public static final int QuestUpdateQuestVarRsp = 486; + public static final int QuickUseWidgetReq = 4251; + public static final int QuickUseWidgetRsp = 4252; + public static final int ReadMailNotify = 1441; + public static final int ReadPrivateChatReq = 5032; + public static final int ReadPrivateChatRsp = 5005; + public static final int ReceivedTrialAvatarActivityRewardReq = 2054; + public static final int ReceivedTrialAvatarActivityRewardRsp = 2199; + public static final int RechargeReq = 4118; + public static final int RechargeRsp = 4109; + public static final int RedeemLegendaryKeyReq = 436; + public static final int RedeemLegendaryKeyRsp = 428; + public static final int RefreshBackgroundAvatarReq = 1660; + public static final int RefreshBackgroundAvatarRsp = 1751; + public static final int RefreshRoguelikeDungeonCardReq = 8072; + public static final int RefreshRoguelikeDungeonCardRsp = 8644; + public static final int RegionSearchChangeRegionNotify = 5609; + public static final int RegionSearchNotify = 5618; + public static final int ReliquaryDecomposeReq = 615; + public static final int ReliquaryDecomposeRsp = 692; + public static final int ReliquaryPromoteReq = 612; + public static final int ReliquaryPromoteRsp = 658; + public static final int ReliquaryUpgradeReq = 606; + public static final int ReliquaryUpgradeRsp = 619; + public static final int RemoveBlacklistReq = 4013; + public static final int RemoveBlacklistRsp = 4042; + public static final int RemoveRandTaskInfoNotify = 193; + public static final int ReportFightAntiCheatNotify = 305; + public static final int ReportTrackingIOInfoNotify = 4126; + public static final int RequestLiveInfoReq = 858; + public static final int RequestLiveInfoRsp = 850; + public static final int ResinCardDataUpdateNotify = 4101; + public static final int ResinChangeNotify = 670; + public static final int RestartEffigyChallengeReq = 2023; + public static final int RestartEffigyChallengeRsp = 2133; + public static final int ReunionActivateNotify = 5065; + public static final int ReunionBriefInfoReq = 5068; + public static final int ReunionBriefInfoRsp = 5059; + public static final int ReunionDailyRefreshNotify = 5091; + public static final int ReunionPrivilegeChangeNotify = 5061; + public static final int ReunionSettleNotify = 5077; + public static final int RobotPushPlayerDataNotify = 30; + public static final int RogueCellUpdateNotify = 8022; + public static final int RogueDungeonPlayerCellChangeNotify = 8832; + public static final int RogueHealAvatarsReq = 8331; + public static final int RogueHealAvatarsRsp = 8937; + public static final int RoguelikeCardGachaNotify = 8618; + public static final int RoguelikeEffectDataNotify = 8606; + public static final int RoguelikeEffectViewReq = 8377; + public static final int RoguelikeEffectViewRsp = 8770; + public static final int RoguelikeGiveUpReq = 8988; + public static final int RoguelikeGiveUpRsp = 8009; + public static final int RoguelikeMistClearNotify = 8198; + public static final int RoguelikeRefreshCardCostUpdateNotify = 8912; + public static final int RoguelikeResourceBonusPropUpdateNotify = 8823; + public static final int RoguelikeRuneRecordUpdateNotify = 8497; + public static final int RoguelikeSelectAvatarAndEnterDungeonReq = 8975; + public static final int RoguelikeSelectAvatarAndEnterDungeonRsp = 8471; + public static final int RoguelikeTakeStageFirstPassRewardReq = 8205; + public static final int RoguelikeTakeStageFirstPassRewardRsp = 8409; + public static final int RogueResumeDungeonReq = 8417; + public static final int RogueResumeDungeonRsp = 8565; + public static final int RogueSwitchAvatarReq = 8930; + public static final int RogueSwitchAvatarRsp = 8556; + public static final int SalesmanDeliverItemReq = 2118; + public static final int SalesmanDeliverItemRsp = 2038; + public static final int SalesmanTakeRewardReq = 2007; + public static final int SalesmanTakeRewardRsp = 2100; + public static final int SalesmanTakeSpecialRewardReq = 2065; + public static final int SalesmanTakeSpecialRewardRsp = 2107; + public static final int SaveCoopDialogReq = 1991; + public static final int SaveCoopDialogRsp = 1955; + public static final int SaveMainCoopReq = 1993; + public static final int SaveMainCoopRsp = 1954; + public static final int SceneAreaUnlockNotify = 219; + public static final int SceneAreaWeatherNotify = 229; + public static final int SceneAudioNotify = 3430; + public static final int SceneAvatarStaminaStepReq = 282; + public static final int SceneAvatarStaminaStepRsp = 255; + public static final int SceneCreateEntityReq = 250; public static final int SceneCreateEntityRsp = 220; - public static final int SceneDataNotify = 3179; - public static final int SceneDestroyEntityReq = 280; - public static final int SceneDestroyEntityRsp = 264; - public static final int SceneEntitiesMoveCombineNotify = 3312; - public static final int SceneEntitiesMovesReq = 221; - public static final int SceneEntitiesMovesRsp = 207; - public static final int SceneEntityAppearNotify = 293; - public static final int SceneEntityDisappearNotify = 244; - public static final int SceneEntityDrownReq = 265; - public static final int SceneEntityDrownRsp = 203; - public static final int SceneEntityMoveNotify = 291; - public static final int SceneEntityMoveReq = 245; - public static final int SceneEntityMoveRsp = 275; - public static final int SceneEntityUpdateNotify = 3423; - public static final int SceneForceLockNotify = 266; + public static final int SceneDataNotify = 3117; + public static final int SceneDestroyEntityReq = 213; + public static final int SceneDestroyEntityRsp = 242; + public static final int SceneEntitiesMoveCombineNotify = 3298; + public static final int SceneEntitiesMovesReq = 240; + public static final int SceneEntitiesMovesRsp = 275; + public static final int SceneEntityAppearNotify = 217; + public static final int SceneEntityDisappearNotify = 285; + public static final int SceneEntityDrownReq = 212; + public static final int SceneEntityDrownRsp = 258; + public static final int SceneEntityMoveNotify = 227; + public static final int SceneEntityMoveReq = 235; + public static final int SceneEntityMoveRsp = 249; + public static final int SceneEntityUpdateNotify = 3089; + public static final int SceneForceLockNotify = 211; public static final int SceneForceUnlockNotify = 201; - public static final int SceneGalleryInfoNotify = 5528; - public static final int SceneInitFinishReq = 215; - public static final int SceneInitFinishRsp = 237; - public static final int SceneKickPlayerNotify = 259; - public static final int SceneKickPlayerReq = 204; - public static final int SceneKickPlayerRsp = 206; - public static final int ScenePlayBattleInfoListNotify = 4378; - public static final int ScenePlayBattleInfoNotify = 4410; - public static final int ScenePlayBattleInterruptNotify = 4441; - public static final int ScenePlayBattleResultNotify = 4447; - public static final int ScenePlayBattleUidOpNotify = 4438; - public static final int ScenePlayerInfoNotify = 236; - public static final int ScenePlayerLocationNotify = 297; - public static final int ScenePlayerSoundNotify = 243; - public static final int ScenePlayGuestReplyInviteReq = 4394; - public static final int ScenePlayGuestReplyInviteRsp = 4395; - public static final int ScenePlayGuestReplyNotify = 4425; - public static final int ScenePlayInfoListNotify = 4429; - public static final int ScenePlayInviteResultNotify = 4384; - public static final int ScenePlayOutofRegionNotify = 4405; - public static final int ScenePlayOwnerCheckReq = 4383; - public static final int ScenePlayOwnerCheckRsp = 4360; - public static final int ScenePlayOwnerInviteNotify = 4443; - public static final int ScenePlayOwnerStartInviteReq = 4365; - public static final int ScenePlayOwnerStartInviteRsp = 4387; - public static final int ScenePointUnlockNotify = 274; - public static final int SceneRouteChangeNotify = 270; - public static final int SceneTeamUpdateNotify = 1696; - public static final int SceneTimeNotify = 229; - public static final int SceneTransToPointReq = 256; - public static final int SceneTransToPointRsp = 283; - public static final int SceneUnlockInfoNotify = 3386; - public static final int SceneWeatherForcastReq = 3167; - public static final int SceneWeatherForcastRsp = 3023; - public static final int SeaLampCoinNotify = 2028; - public static final int SeaLampContributeItemReq = 2122; - public static final int SeaLampContributeItemRsp = 2084; - public static final int SeaLampFlyLampNotify = 2075; - public static final int SeaLampFlyLampReq = 2174; - public static final int SeaLampFlyLampRsp = 2080; - public static final int SeaLampPopularityNotify = 2062; - public static final int SeaLampTakeContributionRewardReq = 2052; - public static final int SeaLampTakeContributionRewardRsp = 2057; - public static final int SeaLampTakePhaseRewardReq = 2109; - public static final int SeaLampTakePhaseRewardRsp = 2132; - public static final int SealBattleBeginNotify = 225; - public static final int SealBattleEndNotify = 249; - public static final int SealBattleProgressNotify = 285; - public static final int SeeMonsterReq = 299; - public static final int SeeMonsterRsp = 300; - public static final int SelectAsterMidDifficultyReq = 2019; - public static final int SelectAsterMidDifficultyRsp = 2003; - public static final int SelectEffigyChallengeConditionReq = 2143; - public static final int SelectEffigyChallengeConditionRsp = 2072; - public static final int SelectRoguelikeDungeonCardReq = 8964; - public static final int SelectRoguelikeDungeonCardRsp = 8572; - public static final int SelectWorktopOptionReq = 837; - public static final int SelectWorktopOptionRsp = 893; - public static final int ServerAnnounceNotify = 2199; - public static final int ServerAnnounceRevokeNotify = 2129; - public static final int ServerBuffChangeNotify = 332; + public static final int SceneGalleryInfoNotify = 5597; + public static final int SceneInitFinishReq = 237; + public static final int SceneInitFinishRsp = 232; + public static final int SceneKickPlayerNotify = 292; + public static final int SceneKickPlayerReq = 295; + public static final int SceneKickPlayerRsp = 215; + public static final int ScenePlayBattleInfoListNotify = 4447; + public static final int ScenePlayBattleInfoNotify = 4359; + public static final int ScenePlayBattleInterruptNotify = 4377; + public static final int ScenePlayBattleResultNotify = 4357; + public static final int ScenePlayBattleUidOpNotify = 4380; + public static final int ScenePlayerInfoNotify = 225; + public static final int ScenePlayerLocationNotify = 207; + public static final int ScenePlayerSoundNotify = 210; + public static final int ScenePlayGuestReplyInviteReq = 4435; + public static final int ScenePlayGuestReplyInviteRsp = 4385; + public static final int ScenePlayGuestReplyNotify = 4399; + public static final int ScenePlayInfoListNotify = 4405; + public static final int ScenePlayInviteResultNotify = 4432; + public static final int ScenePlayOutofRegionNotify = 4448; + public static final int ScenePlayOwnerCheckReq = 4381; + public static final int ScenePlayOwnerCheckRsp = 4391; + public static final int ScenePlayOwnerInviteNotify = 4367; + public static final int ScenePlayOwnerStartInviteReq = 4387; + public static final int ScenePlayOwnerStartInviteRsp = 4382; + public static final int ScenePointUnlockNotify = 290; + public static final int SceneRouteChangeNotify = 278; + public static final int SceneTeamUpdateNotify = 1699; + public static final int SceneTimeNotify = 262; + public static final int SceneTransToPointReq = 286; + public static final int SceneTransToPointRsp = 263; + public static final int SceneWeatherForcastReq = 3190; + public static final int SceneWeatherForcastRsp = 3063; + public static final int SeaLampCoinNotify = 2096; + public static final int SeaLampContributeItemReq = 2168; + public static final int SeaLampContributeItemRsp = 2159; + public static final int SeaLampFlyLampNotify = 2051; + public static final int SeaLampFlyLampReq = 2071; + public static final int SeaLampFlyLampRsp = 2019; + public static final int SeaLampPopularityNotify = 2112; + public static final int SeaLampTakeContributionRewardReq = 2069; + public static final int SeaLampTakeContributionRewardRsp = 2103; + public static final int SeaLampTakePhaseRewardReq = 2092; + public static final int SeaLampTakePhaseRewardRsp = 2160; + public static final int SealBattleBeginNotify = 273; + public static final int SealBattleEndNotify = 261; + public static final int SealBattleProgressNotify = 288; + public static final int SeeMonsterReq = 281; + public static final int SeeMonsterRsp = 264; + public static final int SelectAsterMidDifficultyReq = 2190; + public static final int SelectAsterMidDifficultyRsp = 2010; + public static final int SelectEffigyChallengeConditionReq = 2111; + public static final int SelectEffigyChallengeConditionRsp = 2068; + public static final int SelectRoguelikeDungeonCardReq = 8070; + public static final int SelectRoguelikeDungeonCardRsp = 8040; + public static final int SelectWorktopOptionReq = 832; + public static final int SelectWorktopOptionRsp = 817; + public static final int ServerAnnounceNotify = 2029; + public static final int ServerAnnounceRevokeNotify = 2141; + public static final int ServerBuffChangeNotify = 393; public static final int ServerCondMeetQuestListUpdateNotify = 401; - public static final int ServerDisconnectClientNotify = 186; - public static final int ServerGlobalValueChangeNotify = 1188; - public static final int ServerLogNotify = 79; - public static final int ServerMessageNotify = 5725; - public static final int ServerTimeNotify = 34; - public static final int ServerUpdateGlobalValueNotify = 1197; + public static final int ServerDisconnectClientNotify = 166; + public static final int ServerGlobalValueChangeNotify = 1130; + public static final int ServerLogNotify = 55; + public static final int ServerMessageNotify = 5709; + public static final int ServerTimeNotify = 82; + public static final int ServerUpdateGlobalValueNotify = 1107; public static final int SetBattlePassViewedReq = 2637; - public static final int SetBattlePassViewedRsp = 2606; - public static final int SetChatEmojiCollectionReq = 4086; - public static final int SetChatEmojiCollectionRsp = 4077; - public static final int SetCoopChapterViewedReq = 1980; - public static final int SetCoopChapterViewedRsp = 1988; - public static final int SetCurExpeditionChallengeIdReq = 2017; - public static final int SetCurExpeditionChallengeIdRsp = 2099; - public static final int SetEntityClientDataNotify = 3303; - public static final int SetEquipLockStateReq = 635; - public static final int SetEquipLockStateRsp = 657; - public static final int SetFriendEnterHomeOptionReq = 4613; - public static final int SetFriendEnterHomeOptionRsp = 4724; - public static final int SetFriendRemarkNameReq = 4023; - public static final int SetFriendRemarkNameRsp = 4013; - public static final int SetH5ActivityRedDotTimestampReq = 5698; - public static final int SetH5ActivityRedDotTimestampRsp = 5663; - public static final int SetIsAutoUnlockSpecificEquipReq = 687; - public static final int SetIsAutoUnlockSpecificEquipRsp = 604; - public static final int SetLimitOptimizationNotify = 8189; - public static final int SetNameCardReq = 4089; - public static final int SetNameCardRsp = 4009; - public static final int SetOpenStateReq = 162; - public static final int SetOpenStateRsp = 189; - public static final int SetPlayerBirthdayReq = 4097; - public static final int SetPlayerBirthdayRsp = 4088; - public static final int SetPlayerBornDataReq = 155; - public static final int SetPlayerBornDataRsp = 146; - public static final int SetPlayerHeadImageReq = 4046; - public static final int SetPlayerHeadImageRsp = 4074; - public static final int SetPlayerNameReq = 183; - public static final int SetPlayerNameRsp = 126; - public static final int SetPlayerPropReq = 188; - public static final int SetPlayerPropRsp = 128; - public static final int SetPlayerSignatureReq = 4028; - public static final int SetPlayerSignatureRsp = 4055; - public static final int SetSceneWeatherAreaReq = 271; - public static final int SetSceneWeatherAreaRsp = 205; - public static final int SetUpAvatarTeamReq = 1671; - public static final int SetUpAvatarTeamRsp = 1634; - public static final int SetUpLunchBoxWidgetReq = 4286; - public static final int SetUpLunchBoxWidgetRsp = 4293; - public static final int SetWidgetSlotReq = 4266; - public static final int SetWidgetSlotRsp = 4279; - public static final int ShowClientGuideNotify = 3190; - public static final int ShowClientTutorialNotify = 3374; - public static final int ShowCommonTipsNotify = 3277; - public static final int ShowMessageNotify = 15; - public static final int ShowTemplateReminderNotify = 3164; - public static final int SignInInfoReq = 2510; - public static final int SignInInfoRsp = 2515; - public static final int SocialDataNotify = 4063; - public static final int SpringUseReq = 1720; - public static final int SpringUseRsp = 1727; - public static final int StartArenaChallengeLevelReq = 2022; - public static final int StartArenaChallengeLevelRsp = 2033; - public static final int StartBuoyantCombatGalleryReq = 8313; - public static final int StartBuoyantCombatGalleryRsp = 8754; - public static final int StartCoopPointReq = 1956; - public static final int StartCoopPointRsp = 1962; - public static final int StartEffigyChallengeReq = 2123; - public static final int StartEffigyChallengeRsp = 2166; - public static final int StartFishingReq = 5845; - public static final int StartFishingRsp = 5848; - public static final int StartRogueEliteCellChallengeReq = 8620; - public static final int StartRogueEliteCellChallengeRsp = 8198; - public static final int StartRogueNormalCellChallengeReq = 8748; - public static final int StartRogueNormalCellChallengeRsp = 8630; - public static final int StoreItemChangeNotify = 610; - public static final int StoreItemDelNotify = 615; - public static final int StoreWeightLimitNotify = 633; - public static final int SummerTimeFloatSignalPositionNotify = 8389; - public static final int SummerTimeFloatSignalUpdateNotify = 8763; - public static final int SummerTimeSprintBoatRestartReq = 8682; - public static final int SummerTimeSprintBoatRestartRsp = 8562; - public static final int SummerTimeSprintBoatSettleNotify = 8150; - public static final int SumoDungeonSettleNotify = 8946; - public static final int SumoEnterDungeonNotify = 8540; - public static final int SumoLeaveDungeonNotify = 8460; - public static final int SumoRestartDungeonReq = 8602; - public static final int SumoRestartDungeonRsp = 8498; - public static final int SumoSaveTeamReq = 8874; - public static final int SumoSaveTeamRsp = 8287; - public static final int SumoSelectTeamAndEnterDungeonReq = 8605; - public static final int SumoSelectTeamAndEnterDungeonRsp = 8998; - public static final int SumoSetNoSwitchPunishTimeNotify = 8804; - public static final int SumoSwitchTeamReq = 8718; - public static final int SumoSwitchTeamRsp = 8356; - public static final int SyncScenePlayTeamEntityNotify = 3296; - public static final int SyncTeamEntityNotify = 338; - public static final int TakeAchievementGoalRewardReq = 2695; - public static final int TakeAchievementGoalRewardRsp = 2698; - public static final int TakeAchievementRewardReq = 2685; - public static final int TakeAchievementRewardRsp = 2675; - public static final int TakeAsterSpecialRewardReq = 2051; - public static final int TakeAsterSpecialRewardRsp = 2041; - public static final int TakeBattlePassMissionPointReq = 2617; - public static final int TakeBattlePassMissionPointRsp = 2636; - public static final int TakeBattlePassRewardReq = 2613; - public static final int TakeBattlePassRewardRsp = 2601; - public static final int TakeCityReputationExploreRewardReq = 2888; - public static final int TakeCityReputationExploreRewardRsp = 2828; - public static final int TakeCityReputationLevelRewardReq = 2810; - public static final int TakeCityReputationLevelRewardRsp = 2815; - public static final int TakeCityReputationParentQuestReq = 2893; - public static final int TakeCityReputationParentQuestRsp = 2844; - public static final int TakeCompoundOutputReq = 108; - public static final int TakeCompoundOutputRsp = 117; - public static final int TakeCoopRewardReq = 1996; - public static final int TakeCoopRewardRsp = 1981; - public static final int TakeDeliveryDailyRewardReq = 2055; - public static final int TakeDeliveryDailyRewardRsp = 2104; - public static final int TakeEffigyFirstPassRewardReq = 2071; - public static final int TakeEffigyFirstPassRewardRsp = 2034; - public static final int TakeEffigyRewardReq = 2113; - public static final int TakeEffigyRewardRsp = 2008; - public static final int TakeFirstShareRewardReq = 4008; - public static final int TakeFirstShareRewardRsp = 4017; - public static final int TakeFurnitureMakeReq = 4751; - public static final int TakeFurnitureMakeRsp = 4457; - public static final int TakeHuntingOfferReq = 4750; - public static final int TakeHuntingOfferRsp = 4782; - public static final int TakeInvestigationRewardReq = 1926; - public static final int TakeInvestigationRewardRsp = 1925; - public static final int TakeInvestigationTargetRewardReq = 1915; - public static final int TakeInvestigationTargetRewardRsp = 1929; - public static final int TakeMaterialDeleteReturnReq = 651; - public static final int TakeMaterialDeleteReturnRsp = 684; - public static final int TakeoffEquipReq = 655; - public static final int TakeoffEquipRsp = 646; - public static final int TakeOfferingLevelRewardReq = 2921; - public static final int TakeOfferingLevelRewardRsp = 2910; - public static final int TakePlayerLevelRewardReq = 151; - public static final int TakePlayerLevelRewardRsp = 184; - public static final int TakeRegionSearchRewardReq = 5645; - public static final int TakeRegionSearchRewardRsp = 5648; - public static final int TakeResinCardDailyRewardReq = 4136; - public static final int TakeResinCardDailyRewardRsp = 4143; - public static final int TakeReunionFirstGiftRewardReq = 5095; - public static final int TakeReunionFirstGiftRewardRsp = 5098; - public static final int TakeReunionMissionRewardReq = 5056; - public static final int TakeReunionMissionRewardRsp = 5062; - public static final int TakeReunionSignInRewardReq = 5067; - public static final int TakeReunionSignInRewardRsp = 5086; - public static final int TakeReunionWatcherRewardReq = 5065; - public static final int TakeReunionWatcherRewardRsp = 5077; - public static final int TaskVarNotify = 178; - public static final int TeamResonanceChangeNotify = 1046; - public static final int TowerAllDataReq = 2445; - public static final int TowerAllDataRsp = 2475; - public static final int TowerBriefDataNotify = 2460; - public static final int TowerBuffSelectReq = 2497; - public static final int TowerBuffSelectRsp = 2488; - public static final int TowerCurLevelRecordChangeNotify = 2410; - public static final int TowerDailyRewardProgressChangeNotify = 2415; - public static final int TowerEnterLevelReq = 2479; - public static final int TowerEnterLevelRsp = 2491; - public static final int TowerFloorRecordChangeNotify = 2433; - public static final int TowerGetFloorStarRewardReq = 2489; - public static final int TowerGetFloorStarRewardRsp = 2409; - public static final int TowerLevelEndNotify = 2464; + public static final int SetBattlePassViewedRsp = 2632; + public static final int SetChatEmojiCollectionReq = 4066; + public static final int SetChatEmojiCollectionRsp = 4048; + public static final int SetCoopChapterViewedReq = 1956; + public static final int SetCoopChapterViewedRsp = 1998; + public static final int SetCurExpeditionChallengeIdReq = 2130; + public static final int SetCurExpeditionChallengeIdRsp = 2093; + public static final int SetEntityClientDataNotify = 3375; + public static final int SetEquipLockStateReq = 604; + public static final int SetEquipLockStateRsp = 605; + public static final int SetFriendEnterHomeOptionReq = 4761; + public static final int SetFriendEnterHomeOptionRsp = 4590; + public static final int SetFriendRemarkNameReq = 4070; + public static final int SetFriendRemarkNameRsp = 4029; + public static final int SetH5ActivityRedDotTimestampReq = 5654; + public static final int SetH5ActivityRedDotTimestampRsp = 5678; + public static final int SetIsAutoUnlockSpecificEquipReq = 639; + public static final int SetIsAutoUnlockSpecificEquipRsp = 695; + public static final int SetLimitOptimizationNotify = 8194; + public static final int SetNameCardReq = 4006; + public static final int SetNameCardRsp = 4019; + public static final int SetOpenStateReq = 138; + public static final int SetOpenStateRsp = 106; + public static final int SetPlayerBirthdayReq = 4007; + public static final int SetPlayerBirthdayRsp = 4030; + public static final int SetPlayerBornDataReq = 198; + public static final int SetPlayerBornDataRsp = 145; + public static final int SetPlayerHeadImageReq = 4045; + public static final int SetPlayerHeadImageRsp = 4090; + public static final int SetPlayerNameReq = 163; + public static final int SetPlayerNameRsp = 124; + public static final int SetPlayerPropReq = 130; + public static final int SetPlayerPropRsp = 197; + public static final int SetPlayerSignatureReq = 4097; + public static final int SetPlayerSignatureRsp = 4098; + public static final int SetSceneWeatherAreaReq = 256; + public static final int SetSceneWeatherAreaRsp = 265; + public static final int SetUpAvatarTeamReq = 1753; + public static final int SetUpAvatarTeamRsp = 1664; + public static final int SetUpLunchBoxWidgetReq = 4297; + public static final int SetUpLunchBoxWidgetRsp = 4266; + public static final int SetWidgetSlotReq = 4269; + public static final int SetWidgetSlotRsp = 4260; + public static final int ShowClientGuideNotify = 3241; + public static final int ShowClientTutorialNotify = 3079; + public static final int ShowCommonTipsNotify = 3357; + public static final int ShowMessageNotify = 37; + public static final int ShowTemplateReminderNotify = 3011; + public static final int SignInInfoReq = 2541; + public static final int SignInInfoRsp = 2537; + public static final int SocialDataNotify = 4054; + public static final int SpringUseReq = 1623; + public static final int SpringUseRsp = 1733; + public static final int StartArenaChallengeLevelReq = 2154; + public static final int StartArenaChallengeLevelRsp = 2191; + public static final int StartBuoyantCombatGalleryReq = 9000; + public static final int StartBuoyantCombatGalleryRsp = 8364; + public static final int StartCoopPointReq = 1982; + public static final int StartCoopPointRsp = 1964; + public static final int StartEffigyChallengeReq = 2157; + public static final int StartEffigyChallengeRsp = 2008; + public static final int StartFishingReq = 5843; + public static final int StartFishingRsp = 5804; + public static final int StartRogueEliteCellChallengeReq = 8722; + public static final int StartRogueEliteCellChallengeRsp = 8876; + public static final int StartRogueNormalCellChallengeReq = 8456; + public static final int StartRogueNormalCellChallengeRsp = 8156; + public static final int StoreItemChangeNotify = 641; + public static final int StoreItemDelNotify = 637; + public static final int StoreWeightLimitNotify = 631; + public static final int SummerTimeFloatSignalPositionNotify = 8622; + public static final int SummerTimeFloatSignalUpdateNotify = 8333; + public static final int SummerTimeSprintBoatRestartReq = 8175; + public static final int SummerTimeSprintBoatRestartRsp = 8563; + public static final int SummerTimeSprintBoatSettleNotify = 8117; + public static final int SumoDungeonSettleNotify = 8426; + public static final int SumoEnterDungeonNotify = 8727; + public static final int SumoLeaveDungeonNotify = 8440; + public static final int SumoRestartDungeonReq = 8585; + public static final int SumoRestartDungeonRsp = 8628; + public static final int SumoSaveTeamReq = 8970; + public static final int SumoSaveTeamRsp = 8890; + public static final int SumoSelectTeamAndEnterDungeonReq = 8030; + public static final int SumoSelectTeamAndEnterDungeonRsp = 8915; + public static final int SumoSetNoSwitchPunishTimeNotify = 8269; + public static final int SumoSwitchTeamReq = 8400; + public static final int SumoSwitchTeamRsp = 8442; + public static final int SyncScenePlayTeamEntityNotify = 3096; + public static final int SyncTeamEntityNotify = 334; + public static final int TakeAchievementGoalRewardReq = 2678; + public static final int TakeAchievementGoalRewardRsp = 2653; + public static final int TakeAchievementRewardReq = 2693; + public static final int TakeAchievementRewardRsp = 2654; + public static final int TakeAsterSpecialRewardReq = 2174; + public static final int TakeAsterSpecialRewardRsp = 2035; + public static final int TakeBattlePassMissionPointReq = 2626; + public static final int TakeBattlePassMissionPointRsp = 2647; + public static final int TakeBattlePassRewardReq = 2628; + public static final int TakeBattlePassRewardRsp = 2603; + public static final int TakeCityReputationExploreRewardReq = 2830; + public static final int TakeCityReputationExploreRewardRsp = 2897; + public static final int TakeCityReputationLevelRewardReq = 2841; + public static final int TakeCityReputationLevelRewardRsp = 2837; + public static final int TakeCityReputationParentQuestReq = 2817; + public static final int TakeCityReputationParentQuestRsp = 2885; + public static final int TakeCompoundOutputReq = 146; + public static final int TakeCompoundOutputRsp = 133; + public static final int TakeCoopRewardReq = 1977; + public static final int TakeCoopRewardRsp = 1965; + public static final int TakeDeliveryDailyRewardReq = 2037; + public static final int TakeDeliveryDailyRewardRsp = 2083; + public static final int TakeEffigyFirstPassRewardReq = 2200; + public static final int TakeEffigyFirstPassRewardRsp = 2073; + public static final int TakeEffigyRewardReq = 2062; + public static final int TakeEffigyRewardRsp = 2110; + public static final int TakeFirstShareRewardReq = 4046; + public static final int TakeFirstShareRewardRsp = 4033; + public static final int TakeFurnitureMakeReq = 4768; + public static final int TakeFurnitureMakeRsp = 4599; + public static final int TakeHuntingOfferReq = 4318; + public static final int TakeHuntingOfferRsp = 4309; + public static final int TakeInvestigationRewardReq = 1925; + public static final int TakeInvestigationRewardRsp = 1903; + public static final int TakeInvestigationTargetRewardReq = 1901; + public static final int TakeInvestigationTargetRewardRsp = 1908; + public static final int TakeMaterialDeleteReturnReq = 660; + public static final int TakeMaterialDeleteReturnRsp = 677; + public static final int TakeoffEquipReq = 698; + public static final int TakeoffEquipRsp = 645; + public static final int TakeOfferingLevelRewardReq = 2903; + public static final int TakeOfferingLevelRewardRsp = 2902; + public static final int TakePlayerLevelRewardReq = 160; + public static final int TakePlayerLevelRewardRsp = 177; + public static final int TakeRegionSearchRewardReq = 5643; + public static final int TakeRegionSearchRewardRsp = 5604; + public static final int TakeResinCardDailyRewardReq = 4147; + public static final int TakeResinCardDailyRewardRsp = 4116; + public static final int TakeReunionFirstGiftRewardReq = 5093; + public static final int TakeReunionFirstGiftRewardRsp = 5054; + public static final int TakeReunionMissionRewardReq = 5082; + public static final int TakeReunionMissionRewardRsp = 5064; + public static final int TakeReunionSignInRewardReq = 5076; + public static final int TakeReunionSignInRewardRsp = 5097; + public static final int TakeReunionWatcherRewardReq = 5052; + public static final int TakeReunionWatcherRewardRsp = 5063; + public static final int TaskVarNotify = 191; + public static final int TeamResonanceChangeNotify = 1045; + public static final int TowerAllDataReq = 2435; + public static final int TowerAllDataRsp = 2449; + public static final int TowerBriefDataNotify = 2409; + public static final int TowerBuffSelectReq = 2407; + public static final int TowerBuffSelectRsp = 2430; + public static final int TowerCurLevelRecordChangeNotify = 2441; + public static final int TowerDailyRewardProgressChangeNotify = 2437; + public static final int TowerEnterLevelReq = 2455; + public static final int TowerEnterLevelRsp = 2427; + public static final int TowerFloorRecordChangeNotify = 2431; + public static final int TowerGetFloorStarRewardReq = 2406; + public static final int TowerGetFloorStarRewardRsp = 2419; + public static final int TowerLevelEndNotify = 2442; public static final int TowerLevelStarCondNotify = 2401; - public static final int TowerMiddleLevelChangeTeamNotify = 2466; - public static final int TowerRecordHandbookReq = 2473; - public static final int TowerRecordHandbookRsp = 2463; - public static final int TowerSurrenderReq = 2426; - public static final int TowerSurrenderRsp = 2462; - public static final int TowerTeamSelectReq = 2493; - public static final int TowerTeamSelectRsp = 2444; - public static final int TreasureMapBonusChallengeNotify = 2121; - public static final int TreasureMapCurrencyNotify = 2127; - public static final int TreasureMapDetectorDataNotify = 4272; - public static final int TreasureMapGuideTaskDoneNotify = 2200; - public static final int TreasureMapHostInfoNotify = 8960; - public static final int TreasureMapMpChallengeNotify = 2177; - public static final int TreasureMapPreTaskDoneNotify = 2188; - public static final int TreasureMapRegionActiveNotify = 2141; - public static final int TreasureMapRegionInfoNotify = 2120; - public static final int TrialAvatarFirstPassDungeonNotify = 2093; - public static final int TrialAvatarInDungeonIndexNotify = 2138; - public static final int TriggerCreateGadgetToEquipPartNotify = 373; - public static final int TriggerRoguelikeCurseNotify = 8878; - public static final int TriggerRoguelikeRuneReq = 8607; - public static final int TriggerRoguelikeRuneRsp = 8246; - public static final int TryEnterHomeReq = 4622; - public static final int TryEnterHomeRsp = 4731; - public static final int UnfreezeGroupLimitNotify = 3401; - public static final int UnionCmdNotify = 55; - public static final int UnlockAvatarTalentReq = 1060; - public static final int UnlockAvatarTalentRsp = 1033; - public static final int UnlockCoopChapterReq = 1965; - public static final int UnlockCoopChapterRsp = 1977; - public static final int UnlockedFurnitureFormulaDataNotify = 4700; - public static final int UnlockedFurnitureSuiteDataNotify = 4788; + public static final int TowerMiddleLevelChangeTeamNotify = 2411; + public static final int TowerRecordHandbookReq = 2422; + public static final int TowerRecordHandbookRsp = 2454; + public static final int TowerSurrenderReq = 2424; + public static final int TowerSurrenderRsp = 2438; + public static final int TowerTeamSelectReq = 2417; + public static final int TowerTeamSelectRsp = 2485; + public static final int TreasureMapBonusChallengeNotify = 2075; + public static final int TreasureMapCurrencyNotify = 2098; + public static final int TreasureMapDetectorDataNotify = 4291; + public static final int TreasureMapGuideTaskDoneNotify = 2088; + public static final int TreasureMapHostInfoNotify = 8206; + public static final int TreasureMapMpChallengeNotify = 2036; + public static final int TreasureMapPreTaskDoneNotify = 2055; + public static final int TreasureMapRegionActiveNotify = 2059; + public static final int TreasureMapRegionInfoNotify = 2106; + public static final int TrialAvatarFirstPassDungeonNotify = 2137; + public static final int TrialAvatarInDungeonIndexNotify = 2024; + public static final int TriggerCreateGadgetToEquipPartNotify = 322; + public static final int TriggerRoguelikeCurseNotify = 8235; + public static final int TriggerRoguelikeRuneReq = 8138; + public static final int TriggerRoguelikeRuneRsp = 8781; + public static final int TryEnterHomeReq = 4553; + public static final int TryEnterHomeRsp = 4610; + public static final int UnfreezeGroupLimitNotify = 3253; + public static final int UnionCmdNotify = 98; + public static final int UnlockAvatarTalentReq = 1009; + public static final int UnlockAvatarTalentRsp = 1031; + public static final int UnlockCoopChapterReq = 1952; + public static final int UnlockCoopChapterRsp = 1963; + public static final int UnlockedFurnitureFormulaDataNotify = 4680; + public static final int UnlockedFurnitureSuiteDataNotify = 4717; public static final int UnlockNameCardNotify = 4001; - public static final int UnlockPersonalLineReq = 402; - public static final int UnlockPersonalLineRsp = 452; - public static final int UnlockTransPointReq = 3421; - public static final int UnlockTransPointRsp = 3073; - public static final int UnmarkEntityInMinMapNotify = 247; - public static final int UpdateAbilityCreatedMovingPlatformNotify = 828; - public static final int UpdatePlayerShowAvatarListReq = 4036; - public static final int UpdatePlayerShowAvatarListRsp = 4024; - public static final int UpdatePlayerShowNameCardListReq = 4030; - public static final int UpdatePlayerShowNameCardListRsp = 4047; - public static final int UpdatePS4BlockListReq = 4081; - public static final int UpdatePS4BlockListRsp = 4027; - public static final int UpdatePS4FriendListNotify = 4056; - public static final int UpdatePS4FriendListReq = 4025; - public static final int UpdatePS4FriendListRsp = 4049; - public static final int UpdateRedPointNotify = 9; + public static final int UnlockPersonalLineReq = 476; + public static final int UnlockPersonalLineRsp = 472; + public static final int UnlockTransPointReq = 3228; + public static final int UnlockTransPointRsp = 3101; + public static final int UnmarkEntityInMinMapNotify = 216; + public static final int UpdateAbilityCreatedMovingPlatformNotify = 897; + public static final int UpdatePlayerShowAvatarListReq = 4025; + public static final int UpdatePlayerShowAvatarListRsp = 4083; + public static final int UpdatePlayerShowNameCardListReq = 4002; + public static final int UpdatePlayerShowNameCardListRsp = 4016; + public static final int UpdatePS4BlockListReq = 4036; + public static final int UpdatePS4BlockListRsp = 4028; + public static final int UpdatePS4FriendListNotify = 4086; + public static final int UpdatePS4FriendListReq = 4073; + public static final int UpdatePS4FriendListRsp = 4061; + public static final int UpdateRedPointNotify = 19; public static final int UpdateReunionWatcherNotify = 5087; - public static final int UpgradeRoguelikeShikigamiReq = 8575; - public static final int UpgradeRoguelikeShikigamiRsp = 8440; - public static final int UseItemReq = 645; - public static final int UseItemRsp = 675; - public static final int UseMiracleRingReq = 5235; - public static final int UseMiracleRingRsp = 5225; - public static final int UseWidgetCreateGadgetReq = 4278; - public static final int UseWidgetCreateGadgetRsp = 4290; - public static final int UseWidgetRetractGadgetReq = 4255; - public static final int UseWidgetRetractGadgetRsp = 4297; - public static final int VehicleInteractReq = 862; - public static final int VehicleInteractRsp = 889; - public static final int VehicleSpawnReq = 809; - public static final int VehicleSpawnRsp = 865; - public static final int VehicleStaminaNotify = 866; - public static final int ViewCodexReq = 4210; - public static final int ViewCodexRsp = 4209; - public static final int WatcherAllDataNotify = 2260; - public static final int WatcherChangeNotify = 2233; - public static final int WatcherEventNotify = 2210; - public static final int WatcherEventTypeNotify = 2215; - public static final int WaterSpritePhaseFinishNotify = 2097; - public static final int WeaponAwakenReq = 664; + public static final int UpgradeRoguelikeShikigamiReq = 8422; + public static final int UpgradeRoguelikeShikigamiRsp = 8671; + public static final int UseItemReq = 635; + public static final int UseItemRsp = 649; + public static final int UseMiracleRingReq = 5218; + public static final int UseMiracleRingRsp = 5209; + public static final int UseWidgetCreateGadgetReq = 4283; + public static final int UseWidgetCreateGadgetRsp = 4279; + public static final int UseWidgetRetractGadgetReq = 4290; + public static final int UseWidgetRetractGadgetRsp = 4271; + public static final int VehicleInteractReq = 838; + public static final int VehicleInteractRsp = 806; + public static final int VehicleStaminaNotify = 811; + public static final int ViewCodexReq = 4203; + public static final int ViewCodexRsp = 4202; + public static final int WatcherAllDataNotify = 2209; + public static final int WatcherChangeNotify = 2231; + public static final int WatcherEventNotify = 2241; + public static final int WatcherEventTypeNotify = 2237; + public static final int WaterSpritePhaseFinishNotify = 2028; + public static final int WeaponAwakenReq = 642; public static final int WeaponAwakenRsp = 601; - public static final int WeaponPromoteReq = 626; - public static final int WeaponPromoteRsp = 662; - public static final int WeaponUpgradeReq = 656; - public static final int WeaponUpgradeRsp = 683; - public static final int WearEquipReq = 688; - public static final int WearEquipRsp = 628; - public static final int WidgetActiveChangeNotify = 4273; - public static final int WidgetCoolDownNotify = 4277; - public static final int WidgetDoBagReq = 4269; - public static final int WidgetDoBagRsp = 4270; - public static final int WidgetGadgetAllDataNotify = 4260; - public static final int WidgetGadgetDataNotify = 4268; - public static final int WidgetGadgetDestroyNotify = 4282; + public static final int WeaponPromoteReq = 624; + public static final int WeaponPromoteRsp = 638; + public static final int WeaponUpgradeReq = 686; + public static final int WeaponUpgradeRsp = 663; + public static final int WearEquipReq = 630; + public static final int WearEquipRsp = 697; + public static final int WidgetActiveChangeNotify = 4295; + public static final int WidgetCoolDownNotify = 4263; + public static final int WidgetDoBagReq = 4284; + public static final int WidgetDoBagRsp = 4286; + public static final int WidgetGadgetAllDataNotify = 4285; + public static final int WidgetGadgetDataNotify = 4292; + public static final int WidgetGadgetDestroyNotify = 4275; public static final int WidgetReportReq = 4287; - public static final int WidgetReportRsp = 4256; - public static final int WidgetSlotChangeNotify = 4299; - public static final int WidgetUseAttachAbilityGroupChangeNotify = 4257; - public static final int WindSeedClientNotify = 1134; - public static final int WorktopOptionNotify = 815; - public static final int WorldAllRoutineTypeNotify = 3525; - public static final int WorldDataNotify = 3330; - public static final int WorldOwnerBlossomBriefInfoNotify = 2715; - public static final int WorldOwnerBlossomScheduleInfoNotify = 2737; - public static final int WorldOwnerDailyTaskNotify = 130; - public static final int WorldPlayerDieNotify = 211; - public static final int WorldPlayerInfoNotify = 3088; - public static final int WorldPlayerLocationNotify = 224; - public static final int WorldPlayerReviveReq = 216; - public static final int WorldPlayerReviveRsp = 222; - public static final int WorldPlayerRTTNotify = 26; - public static final int WorldRoutineChangeNotify = 3548; - public static final int WorldRoutineTypeCloseNotify = 3513; - public static final int WorldRoutineTypeRefreshNotify = 3545; + public static final int WidgetReportRsp = 4282; + public static final int WidgetSlotChangeNotify = 4274; + public static final int WidgetUseAttachAbilityGroupChangeNotify = 4299; + public static final int WindSeedClientNotify = 1182; + public static final int WorktopOptionNotify = 837; + public static final int WorldAllRoutineTypeNotify = 3509; + public static final int WorldDataNotify = 3131; + public static final int WorldOwnerBlossomBriefInfoNotify = 2737; + public static final int WorldOwnerBlossomScheduleInfoNotify = 2732; + public static final int WorldOwnerDailyTaskNotify = 102; + public static final int WorldPlayerDieNotify = 296; + public static final int WorldPlayerInfoNotify = 3304; + public static final int WorldPlayerLocationNotify = 283; + public static final int WorldPlayerReviveReq = 247; + public static final int WorldPlayerReviveRsp = 280; + public static final int WorldPlayerRTTNotify = 24; + public static final int WorldRoutineChangeNotify = 3504; + public static final int WorldRoutineTypeCloseNotify = 3528; + public static final int WorldRoutineTypeRefreshNotify = 3543; // Unknown - public static final int UNKNOWN = 2013; - public static final int UNKNOWN_1 = 2042; - public static final int UNKNOWN_2 = 343; - public static final int UNKNOWN_3 = 4259; - public static final int UNKNOWN_4 = 4261; - public static final int UNKNOWN_5 = 4306; - public static final int UNKNOWN_6 = 4315; - public static final int UNKNOWN_7 = 4317; - public static final int UNKNOWN_8 = 4326; - public static final int UNKNOWN_9 = 4327; - public static final int UNKNOWN_10 = 4336; - public static final int UNKNOWN_11 = 4337; - public static final int UNKNOWN_12 = 4343; - public static final int UNKNOWN_13 = 5932; - public static final int UNKNOWN_14 = 5959; - public static final int UNKNOWN_15 = 67; - public static final int UNKNOWN_16 = 8010; - public static final int UNKNOWN_17 = 8024; - public static final int UNKNOWN_18 = 8050; - public static final int UNKNOWN_19 = 8077; - public static final int UNKNOWN_20 = 8083; - public static final int UNKNOWN_21 = 8114; - public static final int UNKNOWN_22 = 8154; - public static final int UNKNOWN_23 = 8157; - public static final int UNKNOWN_24 = 8188; - public static final int UNKNOWN_25 = 8190; - public static final int UNKNOWN_26 = 8210; - public static final int UNKNOWN_27 = 8385; - public static final int UNKNOWN_28 = 8405; - public static final int UNKNOWN_29 = 8420; - public static final int UNKNOWN_30 = 8421; - public static final int UNKNOWN_31 = 8429; - public static final int UNKNOWN_32 = 8437; - public static final int UNKNOWN_33 = 8439; - public static final int UNKNOWN_34 = 8461; - public static final int UNKNOWN_35 = 8502; - public static final int UNKNOWN_36 = 8559; - public static final int UNKNOWN_37 = 8580; - public static final int UNKNOWN_38 = 8604; - public static final int UNKNOWN_39 = 8710; - public static final int UNKNOWN_40 = 8761; - public static final int UNKNOWN_41 = 8787; - public static final int UNKNOWN_42 = 8830; - public static final int UNKNOWN_43 = 8877; - public static final int UNKNOWN_44 = 8983; - public static final int UNKNOWN_45 = 943; - public static final List BANNED_PACKETS = Arrays.asList(PacketOpcodes.WindSeedClientNotify, PacketOpcodes.PlayerLuaShellNotify); + public static final HashSet BANNED_PACKETS = new HashSet() {{ + add(PacketOpcodes.WindSeedClientNotify); + add(PacketOpcodes.PlayerLuaShellNotify); + }}; } diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java index 6395a7d4d..ff7be1e45 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java @@ -17,10 +17,12 @@ public class PacketOpcodesUtil { Field[] fields = PacketOpcodes.class.getFields(); for (Field f : fields) { - try { - opcodeMap.put(f.getInt(null), f.getName()); - } catch (Exception e) { - e.printStackTrace(); + if(f.getType().equals(int.class)) { + try { + opcodeMap.put(f.getInt(null), f.getName()); + } catch (Exception e) { + e.printStackTrace(); + } } } } diff --git a/src/main/java/emu/grasscutter/plugin/Plugin.java b/src/main/java/emu/grasscutter/plugin/Plugin.java index 97fc5fd77..f322adc93 100644 --- a/src/main/java/emu/grasscutter/plugin/Plugin.java +++ b/src/main/java/emu/grasscutter/plugin/Plugin.java @@ -3,11 +3,15 @@ package emu.grasscutter.plugin; import emu.grasscutter.Grasscutter; import emu.grasscutter.plugin.api.ServerHook; import emu.grasscutter.server.game.GameServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.InputStream; import java.net.URLClassLoader; +import static emu.grasscutter.Configuration.*; + /** * The base class for all plugins to extend. */ @@ -17,6 +21,7 @@ public abstract class Plugin { private PluginIdentifier identifier; private URLClassLoader classLoader; private File dataFolder; + private Logger logger; /** * This method is reflected into. @@ -32,7 +37,8 @@ public abstract class Plugin { this.identifier = identifier; this.classLoader = classLoader; - this.dataFolder = new File(Grasscutter.getConfig().PLUGINS_FOLDER, identifier.name); + this.dataFolder = new File(PLUGIN(), identifier.name); + this.logger = LoggerFactory.getLogger(identifier.name); if(!this.dataFolder.exists() && !this.dataFolder.mkdirs()) { Grasscutter.getLogger().warn("Failed to create plugin data folder for " + this.identifier.name); @@ -101,6 +107,14 @@ public abstract class Plugin { public final ServerHook getHandle() { return this.server; } + + /** + * Returns the plugin's logger. + * @return A SLF4J logger. + */ + public final Logger getLogger() { + return this.logger; + } /* Called when the plugin is first loaded. */ public void onLoad() { } diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index bc78d12eb..f6f1cfbf7 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -7,6 +7,7 @@ import emu.grasscutter.server.event.HandlerPriority; import emu.grasscutter.utils.Utils; import java.io.File; +import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -16,6 +17,8 @@ import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import static emu.grasscutter.Configuration.*; + /** * Manages the server's plugins and the event system. */ @@ -31,8 +34,7 @@ public final class PluginManager { * Loads plugins from the config-specified directory. */ private void loadPlugins() { - String directory = Grasscutter.getConfig().PLUGINS_FOLDER; - File pluginsDir = new File(Utils.toFilePath(directory)); + File pluginsDir = new File(Utils.toFilePath(PLUGIN())); if(!pluginsDir.exists() && !pluginsDir.mkdirs()) { Grasscutter.getLogger().error("Failed to create plugins directory: " + pluginsDir.getAbsolutePath()); return; @@ -89,6 +91,8 @@ public final class PluginManager { fileReader.close(); // Close the file reader. } catch (ClassNotFoundException ignored) { Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " has an invalid main class."); + } catch (FileNotFoundException ignored) { + Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " lacks a valid config file."); } } catch (Exception exception) { Grasscutter.getLogger().error("Failed to load plugin: " + plugin.getName(), exception); diff --git a/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java b/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java index 6b68b7622..0252b860d 100644 --- a/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java +++ b/src/main/java/emu/grasscutter/plugin/api/PlayerHook.java @@ -83,7 +83,7 @@ public final class PlayerHook { public void teleport(Position position) { this.player.getPos().set(position); this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player, - EnterType.ENTER_JUMP, EnterReason.TransPoint, + EnterType.ENTER_TYPE_JUMP, EnterReason.TransPoint, this.player.getSceneId(), position )); } diff --git a/src/main/java/emu/grasscutter/plugin/api/ServerHook.java b/src/main/java/emu/grasscutter/plugin/api/ServerHook.java index a37abfb62..ffa19110d 100644 --- a/src/main/java/emu/grasscutter/plugin/api/ServerHook.java +++ b/src/main/java/emu/grasscutter/plugin/api/ServerHook.java @@ -1,10 +1,13 @@ package emu.grasscutter.plugin.api; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.dispatch.DispatchServer; import emu.grasscutter.server.game.GameServer; +import emu.grasscutter.server.http.HttpServer; +import emu.grasscutter.server.http.Router; import java.util.LinkedList; import java.util.List; @@ -15,7 +18,7 @@ import java.util.List; public final class ServerHook { private static ServerHook instance; private final GameServer gameServer; - private final DispatchServer dispatchServer; + private final HttpServer httpServer; /** * Gets the server hook instance. @@ -28,11 +31,11 @@ public final class ServerHook { /** * Hooks into a server. * @param gameServer The game server to hook into. - * @param dispatchServer The dispatch server to hook into. + * @param httpServer The HTTP server to hook into. */ - public ServerHook(GameServer gameServer, DispatchServer dispatchServer) { + public ServerHook(GameServer gameServer, HttpServer httpServer) { this.gameServer = gameServer; - this.dispatchServer = dispatchServer; + this.httpServer = httpServer; instance = this; } @@ -45,10 +48,10 @@ public final class ServerHook { } /** - * @return The dispatch server. + * @return The HTTP server. */ - public DispatchServer getDispatchServer() { - return this.dispatchServer; + public HttpServer getHttpServer() { + return this.httpServer; } /** @@ -70,4 +73,28 @@ public final class ServerHook { Command commandData = clazz.getAnnotation(Command.class); this.gameServer.getCommandMap().registerCommand(commandData.label(), handler); } + + /** + * Adds a router using an instance of a class. + * @param router A router instance. + */ + public void addRouter(Router router) { + this.addRouter(router.getClass()); + } + + /** + * Adds a router using a class. + * @param router The class of the router. + */ + public void addRouter(Class router) { + this.httpServer.addRouter(router); + } + + /** + * Sets the server's authentication system. + * @param authSystem An instance of the authentication system. + */ + public void setAuthSystem(AuthenticationSystem authSystem) { + Grasscutter.setAuthenticationSystem(authSystem); + } } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java index 5f6a1b7e6..6ba0098a1 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java @@ -1,34 +1,22 @@ package emu.grasscutter.scripts; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import javax.script.Bindings; import javax.script.CompiledScript; import javax.script.ScriptException; -import org.luaj.vm2.LuaTable; +import emu.grasscutter.scripts.service.ScriptMonsterSpawnService; +import emu.grasscutter.scripts.service.ScriptMonsterTideService; +import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.jse.CoerceJavaToLua; import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.MonsterData; -import emu.grasscutter.data.def.WorldLevelData; import emu.grasscutter.game.entity.EntityGadget; -import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.world.Scene; import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.constants.ScriptGadgetState; -import emu.grasscutter.scripts.constants.ScriptRegionShape; import emu.grasscutter.scripts.data.SceneBlock; import emu.grasscutter.scripts.data.SceneConfig; import emu.grasscutter.scripts.data.SceneGadget; @@ -43,28 +31,43 @@ import emu.grasscutter.scripts.data.ScriptArgs; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import static emu.grasscutter.Configuration.*; + public class SceneScriptManager { private final Scene scene; private final ScriptLib scriptLib; private final LuaValue scriptLibLua; private final Map variables; - private Bindings bindings; private SceneConfig config; private List blocks; private boolean isInit; - - private final Int2ObjectOpenHashMap> triggers; + /** + * SceneTrigger Set + */ + private final Map triggers; + /** + * current triggers controlled by RefreshGroup + */ + private final Int2ObjectOpenHashMap> currentTriggers; private final Int2ObjectOpenHashMap regions; - + private Map sceneGroups; + private SceneGroup currentGroup; + private ScriptMonsterTideService scriptMonsterTideService; + private ScriptMonsterSpawnService scriptMonsterSpawnService; + public SceneScriptManager(Scene scene) { this.scene = scene; this.scriptLib = new ScriptLib(this); this.scriptLibLua = CoerceJavaToLua.coerce(this.scriptLib); - this.triggers = new Int2ObjectOpenHashMap<>(); + this.triggers = new HashMap<>(); + this.currentTriggers = new Int2ObjectOpenHashMap<>(); + this.regions = new Int2ObjectOpenHashMap<>(); this.variables = new HashMap<>(); - + this.sceneGroups = new HashMap<>(); + this.scriptMonsterSpawnService = new ScriptMonsterSpawnService(this); + // TEMPORARY if (this.getScene().getId() < 10) { return; @@ -94,6 +97,10 @@ public class SceneScriptManager { return config; } + public SceneGroup getCurrentGroup() { + return currentGroup; + } + public List getBlocks() { return blocks; } @@ -103,17 +110,35 @@ public class SceneScriptManager { } public Set getTriggersByEvent(int eventId) { - return triggers.computeIfAbsent(eventId, e -> new HashSet<>()); + return currentTriggers.computeIfAbsent(eventId, e -> new HashSet<>()); } - public void registerTrigger(SceneTrigger trigger) { + this.triggers.put(trigger.name, trigger); getTriggersByEvent(trigger.event).add(trigger); } public void deregisterTrigger(SceneTrigger trigger) { + this.triggers.remove(trigger.name); getTriggersByEvent(trigger.event).remove(trigger); } - + public void resetTriggers(List triggerNames) { + for(var name : triggerNames){ + var instance = triggers.get(name); + this.currentTriggers.get(instance.event).clear(); + this.currentTriggers.get(instance.event).add(instance); + } + } + public void refreshGroup(SceneGroup group, int suiteIndex){ + var suite = group.getSuiteByIndex(suiteIndex); + if(suite == null){ + return; + } + if(suite.triggers.size() > 0){ + resetTriggers(suite.triggers); + } + spawnMonstersInGroup(group, suite); + spawnGadgetsInGroup(group, suite); + } public SceneRegion getRegionById(int id) { return regions.get(id); } @@ -141,7 +166,7 @@ public class SceneScriptManager { private void init() { // Get compiled script if cached CompiledScript cs = ScriptLoader.getScriptByPath( - Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "." + ScriptLoader.getScriptType()); + SCRIPT("Scene/" + getScene().getId() + "/scene" + getScene().getId() + "." + ScriptLoader.getScriptType())); if (cs == null) { Grasscutter.getLogger().warn("No script found for scene " + getScene().getId()); @@ -188,7 +213,7 @@ public class SceneScriptManager { private void loadBlockFromScript(SceneBlock block) { CompiledScript cs = ScriptLoader.getScriptByPath( - Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_block" + block.id + "." + ScriptLoader.getScriptType()); + SCRIPT("Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_block" + block.id + "." + ScriptLoader.getScriptType())); if (cs == null) { return; @@ -211,7 +236,7 @@ public class SceneScriptManager { group.setLoaded(true); CompiledScript cs = ScriptLoader.getScriptByPath( - Grasscutter.getConfig().SCRIPTS_FOLDER + "Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_group" + group.id + "." + ScriptLoader.getScriptType()); + SCRIPT("Scene/" + getScene().getId() + "/scene" + getScene().getId() + "_group" + group.id + "." + ScriptLoader.getScriptType())); if (cs == null) { return; @@ -222,7 +247,8 @@ public class SceneScriptManager { cs.eval(getBindings()); // Set - group.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, bindings.get("monsters")); + group.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, bindings.get("monsters")).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y)); group.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, bindings.get("gadgets")); group.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, bindings.get("triggers")); group.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites")); @@ -235,21 +261,21 @@ public class SceneScriptManager { // Add monsters to suite TODO optimize Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - group.monsters.forEach(m -> map.put(m.config_id, m)); + group.monsters.entrySet().forEach(m -> map.put(m.getValue().config_id, m)); group.gadgets.forEach(m -> map.put(m.config_id, m)); for (SceneSuite suite : group.suites) { suite.sceneMonsters = new ArrayList<>(suite.monsters.size()); - for (int id : suite.monsters) { - try { - SceneMonster monster = (SceneMonster) map.get(id); - if (monster != null) { - suite.sceneMonsters.add(monster); + suite.monsters.forEach(id -> { + Object objEntry = map.get(id.intValue()); + if (objEntry instanceof Map.Entry monsterEntry) { + Object monster = monsterEntry.getValue(); + if(monster instanceof SceneMonster sceneMonster){ + suite.sceneMonsters.add(sceneMonster); } - } catch (Exception e) { - continue; } - } + }); + suite.sceneGadgets = new ArrayList<>(suite.gadgets.size()); for (int id : suite.gadgets) { try { @@ -257,11 +283,10 @@ public class SceneScriptManager { if (gadget != null) { suite.sceneGadgets.add(gadget); } - } catch (Exception e) { - continue; - } + } catch (Exception ignored) { } } } + this.sceneGroups.put(group.id, group); } catch (ScriptException e) { Grasscutter.getLogger().error("Error loading group " + group.id + " in scene " + getScene().getId(), e); } @@ -321,62 +346,43 @@ public class SceneScriptManager { this.callEvent(EventType.EVENT_GADGET_CREATE, new ScriptArgs(entity.getConfigId())); } } - + public void spawnMonstersInGroup(SceneGroup group, int suiteIndex) { - spawnMonstersInGroup(group, group.getSuiteByIndex(suiteIndex)); + var suite = group.getSuiteByIndex(suiteIndex); + if(suite == null){ + return; + } + spawnMonstersInGroup(group, suite); + } + public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { + if(suite == null || suite.sceneMonsters.size() <= 0){ + return; + } + this.currentGroup = group; + suite.sceneMonsters.forEach(mob -> this.scriptMonsterSpawnService.spawnMonster(group.id, mob)); } public void spawnMonstersInGroup(SceneGroup group) { - spawnMonstersInGroup(group, null); + this.currentGroup = group; + group.monsters.values().forEach(mob -> this.scriptMonsterSpawnService.spawnMonster(group.id, mob)); } - - public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { - List monsters = group.monsters; - - if (suite != null) { - monsters = suite.sceneMonsters; - } - List toAdd = new ArrayList<>(); - - for (SceneMonster monster : monsters) { - MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); - - if (data == null) { - continue; - } - - // Calculate level - int level = monster.level; - - if (getScene().getDungeonData() != null) { - level = getScene().getDungeonData().getShowLevel(); - } else if (getScene().getWorld().getWorldLevel() > 0) { - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); - - if (worldLevelData != null) { - level = worldLevelData.getMonsterLevel(); - } - } - - // Spawn mob - EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level); - entity.getRotation().set(monster.rot); - entity.setGroupId(group.id); - entity.setConfigId(monster.config_id); - - toAdd.add(entity); - } - - if (toAdd.size() > 0) { - getScene().addEntities(toAdd); - - for (GameEntity entity : toAdd) { - callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(entity.getConfigId())); - } - } + public void startMonsterTideInGroup(SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) { + this.currentGroup = group; + this.scriptMonsterTideService = + new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId); + + } + public void unloadCurrentMonsterTide(){ + if(this.getScriptMonsterTideService() == null){ + return; + } + this.getScriptMonsterTideService().unload(); + } + public void spawnMonstersByConfigId(int configId, int delayTime) { + // TODO delay + this.scriptMonsterSpawnService.spawnMonster(this.currentGroup.id, this.currentGroup.monsters.get(configId)); } - // Events public void callEvent(int eventType, ScriptArgs params) { @@ -395,14 +401,39 @@ public class SceneScriptManager { if (params != null) { args = CoerceJavaToLua.coerce(params); } - - ret = condition.call(this.getScriptLibLua(), args); + + ScriptLib.logger.trace("Call Condition Trigger {}", trigger); + ret = safetyCall(trigger.condition, condition, args); } - if (ret.checkboolean() == true) { + if (ret.isboolean() && ret.checkboolean()) { + ScriptLib.logger.trace("Call Action Trigger {}", trigger); LuaValue action = (LuaValue) this.getBindings().get(trigger.action); - action.call(this.getScriptLibLua(), LuaValue.NIL); + // TODO impl the param of SetGroupVariableValueByGroup + var arg = new ScriptArgs(); + arg.param2 = 100; + var args = CoerceJavaToLua.coerce(arg); + safetyCall(trigger.action, action, args); } + //TODO some ret may not bool } } + + public LuaValue safetyCall(String name, LuaValue func, LuaValue args){ + try{ + return func.call(this.getScriptLibLua(), args); + }catch (LuaError error){ + ScriptLib.logger.error("[LUA] call trigger failed {},{}",name,args,error); + return LuaValue.valueOf(-1); + } + } + + public ScriptMonsterTideService getScriptMonsterTideService() { + return scriptMonsterTideService; + } + + public ScriptMonsterSpawnService getScriptMonsterSpawnService() { + return scriptMonsterSpawnService; + } + } diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 941b00b60..b7fb5939f 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1,28 +1,24 @@ package emu.grasscutter.scripts; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.game.dungeons.DungeonChallenge; import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.SceneRegion; -import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; public class ScriptLib { + public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class); private final SceneScriptManager sceneScriptManager; public ScriptLib(SceneScriptManager sceneScriptManager) { @@ -32,8 +28,20 @@ public class ScriptLib { public SceneScriptManager getSceneScriptManager() { return sceneScriptManager; } - + + private String printTable(LuaTable table){ + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for(var meta : table.keys()){ + sb.append(meta).append(":").append(table.get(meta)).append(","); + } + sb.append("}"); + return sb.toString(); + } + public int SetGadgetStateByConfigId(int configId, int gadgetState) { + logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}", + configId,gadgetState); Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId).findFirst(); @@ -53,6 +61,8 @@ public class ScriptLib { } public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) { + logger.debug("[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}", + groupId,configId,gadgetState); List list = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getGroupId() == groupId).toList(); @@ -71,6 +81,8 @@ public class ScriptLib { } public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) { + logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}", + groupId,configId,options); Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); @@ -90,6 +102,8 @@ public class ScriptLib { } public int DelWorktopOptionByGroupId(int groupId, int configId, int option) { + logger.debug("[LUA] Call DelWorktopOptionByGroupId with {},{},{}",groupId,configId,option); + Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); @@ -109,72 +123,110 @@ public class ScriptLib { } // Some fields are guessed - public int AutoMonsterTide(int challengeIndex, int groupId, int[] config_ids, int param4, int param5, int param6) { + public int AutoMonsterTide(int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6) { + logger.debug("[LUA] Call AutoMonsterTide with {},{},{},{},{},{}", + challengeIndex,groupId,ordersConfigId,tideCount,sceneLimit,param6); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); - + if (group == null || group.monsters == null) { return 1; } - - // TODO just spawn all from group for now - this.getSceneScriptManager().spawnMonstersInGroup(group); + + this.getSceneScriptManager().startMonsterTideInGroup(group, ordersConfigId, tideCount, sceneLimit); return 0; } public int AddExtraGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call AddExtraGroupSuite with {},{}", + groupId,suite); SceneGroup group = getSceneScriptManager().getGroupById(groupId); if (group == null || group.monsters == null) { return 1; } - - // TODO just spawn all from group for now + + // avoid spawn wrong monster + if(getSceneScriptManager().getScene().getChallenge() != null) + if(!getSceneScriptManager().getScene().getChallenge().inProgress() || + getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId){ + return 0; + } this.getSceneScriptManager().spawnMonstersInGroup(group, suite); return 0; } // param3 (probably time limit for timed dungeons) - public int ActiveChallenge(int challengeId, int challengeIndex, int param3, int groupId, int objectiveKills, int param5) { + public int ActiveChallenge(int challengeId, int challengeIndex, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5) { + logger.debug("[LUA] Call ActiveChallenge with {},{},{},{},{},{}", + challengeId,challengeIndex,timeLimitOrGroupId,groupId,objectiveKills,param5); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + var objective = objectiveKills; + + if(group == null){ + group = getSceneScriptManager().getGroupById(timeLimitOrGroupId); + objective = groupId; + } if (group == null || group.monsters == null) { return 1; } - - DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), group); - challenge.setChallengeId(challengeId); - challenge.setChallengeIndex(challengeIndex); - challenge.setObjective(objectiveKills); - + + if(getSceneScriptManager().getScene().getChallenge() != null && + getSceneScriptManager().getScene().getChallenge().inProgress()) + { + return 0; + } + + DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), + group, challengeId, challengeIndex, objective); + // set if tower first stage (6-1) + challenge.setStage(getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0); + getSceneScriptManager().getScene().setChallenge(challenge); - + challenge.start(); return 0; } public int GetGroupMonsterCountByGroupId(int groupId) { + logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}", + groupId); return (int) getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId) .count(); } public int GetGroupVariableValue(String var) { + logger.debug("[LUA] Call GetGroupVariableValue with {}", + var); return getSceneScriptManager().getVariables().getOrDefault(var, 0); } public int SetGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call SetGroupVariableValue with {},{}", + var, value); getSceneScriptManager().getVariables().put(var, value); return 0; } public LuaValue ChangeGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}", + var, value); + getSceneScriptManager().getVariables().put(var, getSceneScriptManager().getVariables().get(var) + value); return LuaValue.ZERO; } - + + /** + * Set the actions and triggers to designated group + */ public int RefreshGroup(LuaTable table) { + logger.debug("[LUA] Call RefreshGroup with {}", + printTable(table)); // Kill and Respawn? int groupId = table.get("group_id").toint(); int suite = table.get("suite").toint(); @@ -185,13 +237,14 @@ public class ScriptLib { return 1; } - this.getSceneScriptManager().spawnMonstersInGroup(group, suite); - this.getSceneScriptManager().spawnGadgetsInGroup(group, suite); + getSceneScriptManager().refreshGroup(group, suite); return 0; } public int GetRegionEntityCount(LuaTable table) { + logger.debug("[LUA] Call GetRegionEntityCount with {}", + table); int regionId = table.get("region_eid").toint(); int entityType = table.get("entity_type").toint(); @@ -205,21 +258,103 @@ public class ScriptLib { } public void PrintContextLog(String msg) { - Grasscutter.getLogger().info("[LUA] " + msg); + logger.info("[LUA] " + msg); } - public int TowerCountTimeStatus(int var1, int var2){ + public int TowerCountTimeStatus(int isDone, int var2){ + logger.debug("[LUA] Call TowerCountTimeStatus with {},{}", + isDone,var2); + // TODO record time return 0; } public int GetGroupMonsterCount(int var1){ - // Maybe... - return GetGroupMonsterCountByGroupId(var1); + logger.debug("[LUA] Call GetGroupMonsterCount with {}", + var1); + + return (int) getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityMonster && e.getGroupId() == getSceneScriptManager().getCurrentGroup().id) + .count(); } public int SetMonsterBattleByGroup(int var1, int var2, int var3){ + logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}", + var1,var2,var3); + // TODO return 0; } public int CauseDungeonFail(int var1){ + logger.debug("[LUA] Call CauseDungeonFail with {}", + var1); + + return 0; + } + + public int GetGroupVariableValueByGroup(String name, int groupId){ + logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}", + name,groupId); + + return getSceneScriptManager().getVariables().getOrDefault(name, 0); + } + + public int SetIsAllowUseSkill(int canUse, int var2){ + logger.debug("[LUA] Call SetIsAllowUseSkill with {},{}", + canUse,var2); + + getSceneScriptManager().getScene().broadcastPacket(new PacketCanUseSkillNotify(canUse == 1)); + return 0; + } + + public int KillEntityByConfigId(LuaTable table){ + logger.debug("[LUA] Call KillEntityByConfigId with {}", + printTable(table)); + var configId = table.get("config_id"); + if(configId == LuaValue.NIL){ + return 1; + } + + var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint()); + if(entity == null){ + return 1; + } + getSceneScriptManager().getScene().killEntity(entity, 0); + return 0; + } + + public int SetGroupVariableValueByGroup(String key, int value, int groupId){ + logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}", + key,value,groupId); + + getSceneScriptManager().getVariables().put(key, value); + return 0; + } + + public int CreateMonster(LuaTable table){ + logger.debug("[LUA] Call CreateMonster with {}", + printTable(table)); + var configId = table.get("config_id").toint(); + var delayTime = table.get("delay_time").toint(); + + getSceneScriptManager().spawnMonstersByConfigId(configId, delayTime); + return 0; + } + + public int TowerMirrorTeamSetUp(int team, int var1) { + logger.debug("[LUA] Call TowerMirrorTeamSetUp with {},{}", + team,var1); + + getSceneScriptManager().unloadCurrentMonsterTide(); + getSceneScriptManager().getScene().getPlayers().get(0).getTowerManager().mirrorTeamSetUp(team-1); + + return 0; + } + + public int CreateGadget(LuaTable table){ + logger.debug("[LUA] Call CreateGadget with {}", + printTable(table)); + var configId = table.get("config_id").toint(); + + //TODO + return 0; } } diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java index a13db7b68..690cd3d0d 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java @@ -1,17 +1,21 @@ package emu.grasscutter.scripts.data; -import java.util.List; - import emu.grasscutter.utils.Position; +import java.util.List; +import java.util.Map; + public class SceneGroup { public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference public int id; public int refresh_id; public Position pos; - - public List monsters; + + /** + * ConfigId - Monster + */ + public Map monsters; public List gadgets; public List triggers; public List regions; diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java index a1603b1e6..301fdb8e0 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java @@ -7,4 +7,29 @@ public class SceneTrigger { public String source; public String condition; public String action; + + @Override + public boolean equals(Object obj) { + if(obj instanceof SceneTrigger sceneTrigger){ + return this.name.equals(sceneTrigger.name); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return "SceneTrigger{" + + "name='" + name + '\'' + + ", config_id=" + config_id + + ", event=" + event + + ", source='" + source + '\'' + + ", condition='" + condition + '\'' + + ", action='" + action + '\'' + + '}'; + } } diff --git a/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java b/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java new file mode 100644 index 000000000..b3b99fd61 --- /dev/null +++ b/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java @@ -0,0 +1,8 @@ +package emu.grasscutter.scripts.listener; + +import emu.grasscutter.game.entity.EntityMonster; + +public interface ScriptMonsterListener { + + void onNotify(EntityMonster sceneMonster); +} diff --git a/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java b/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java index a63328b55..c476b150f 100644 --- a/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java +++ b/src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java @@ -70,16 +70,14 @@ public class LuaSerializer implements Serializer { } try { - object = type.getDeclaredConstructor().newInstance(null); + //noinspection ConfusingArgumentToVarargsMethod + object = type.getDeclaredConstructor().newInstance(); LuaValue[] keys = table.keys(); for (LuaValue k : keys) { try { Field field = object.getClass().getDeclaredField(k.checkjstring()); - if (field == null) { - continue; - } - + field.setAccessible(true); LuaValue keyValue = table.get(k); diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java new file mode 100644 index 000000000..e8e0d0668 --- /dev/null +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java @@ -0,0 +1,78 @@ +package emu.grasscutter.scripts.service; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.WorldLevelData; +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.scripts.SceneScriptManager; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneMonster; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.scripts.listener.ScriptMonsterListener; + +import java.util.ArrayList; +import java.util.List; + +public class ScriptMonsterSpawnService { + + private final SceneScriptManager sceneScriptManager; + private final List onMonsterCreatedListener = new ArrayList<>(); + + private final List onMonsterDeadListener = new ArrayList<>(); + + public ScriptMonsterSpawnService(SceneScriptManager sceneScriptManager){ + this.sceneScriptManager = sceneScriptManager; + } + + public void addMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterCreatedListener.add(scriptMonsterListener); + } + public void addMonsterDeadListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterDeadListener.add(scriptMonsterListener); + } + public void removeMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterCreatedListener.remove(scriptMonsterListener); + } + public void removeMonsterDeadListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterDeadListener.remove(scriptMonsterListener); + } + public void onMonsterDead(EntityMonster entityMonster){ + onMonsterDeadListener.forEach(l -> l.onNotify(entityMonster)); + } + public void spawnMonster(int groupId, SceneMonster monster) { + if(monster == null){ + return; + } + + MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); + + if (data == null) { + return; + } + + // Calculate level + int level = monster.level; + + if (sceneScriptManager.getScene().getDungeonData() != null) { + level = sceneScriptManager.getScene().getDungeonData().getShowLevel(); + } else if (sceneScriptManager.getScene().getWorld().getWorldLevel() > 0) { + WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(sceneScriptManager.getScene().getWorld().getWorldLevel()); + + if (worldLevelData != null) { + level = worldLevelData.getMonsterLevel(); + } + } + + // Spawn mob + EntityMonster entity = new EntityMonster(sceneScriptManager.getScene(), data, monster.pos, level); + entity.getRotation().set(monster.rot); + entity.setGroupId(groupId); + entity.setConfigId(monster.config_id); + + onMonsterCreatedListener.forEach(action -> action.onNotify(entity)); + + sceneScriptManager.getScene().addEntity(entity); + + sceneScriptManager.callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(entity.getConfigId())); + } +} diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java new file mode 100644 index 000000000..57d4735ba --- /dev/null +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java @@ -0,0 +1,89 @@ +package emu.grasscutter.scripts.service; + +import emu.grasscutter.game.entity.EntityMonster; +import emu.grasscutter.scripts.SceneScriptManager; +import emu.grasscutter.scripts.constants.EventType; +import emu.grasscutter.scripts.data.SceneGroup; +import emu.grasscutter.scripts.data.SceneMonster; +import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.scripts.listener.ScriptMonsterListener; + +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; + +public class ScriptMonsterTideService { + private final SceneScriptManager sceneScriptManager; + private final SceneGroup currentGroup; + private final AtomicInteger monsterAlive; + private final AtomicInteger monsterTideCount; + private final AtomicInteger monsterKillCount; + private final int monsterSceneLimit; + private final ConcurrentLinkedQueue monsterConfigOrders; + private final OnMonsterCreated onMonsterCreated= new OnMonsterCreated(); + private final OnMonsterDead onMonsterDead= new OnMonsterDead(); + + public ScriptMonsterTideService(SceneScriptManager sceneScriptManager, + SceneGroup group, int tideCount, int monsterSceneLimit, Integer[] ordersConfigId){ + this.sceneScriptManager = sceneScriptManager; + this.currentGroup = group; + this.monsterSceneLimit = monsterSceneLimit; + this.monsterTideCount = new AtomicInteger(tideCount); + this.monsterKillCount = new AtomicInteger(0); + this.monsterAlive = new AtomicInteger(0); + this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); + + this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(onMonsterDead); + // spawn the first turn + for (int i = 0; i < this.monsterSceneLimit; i++) { + this.sceneScriptManager.getScriptMonsterSpawnService().spawnMonster(group.id, getNextMonster()); + } + } + + public class OnMonsterCreated implements ScriptMonsterListener{ + @Override + public void onNotify(EntityMonster sceneMonster) { + if(monsterSceneLimit > 0){ + monsterAlive.incrementAndGet(); + monsterTideCount.decrementAndGet(); + } + } + } + + public SceneMonster getNextMonster(){ + var nextId = this.monsterConfigOrders.poll(); + if(currentGroup.monsters.containsKey(nextId)){ + return currentGroup.monsters.get(nextId); + } + // TODO some monster config_id do not exist in groups, so temporarily set it to the first + return currentGroup.monsters.values().stream().findFirst().orElse(null); + } + + public class OnMonsterDead implements ScriptMonsterListener { + @Override + public void onNotify(EntityMonster sceneMonster) { + if (monsterSceneLimit <= 0) { + return; + } + if (monsterAlive.decrementAndGet() >= monsterSceneLimit) { + // maybe not happen + return; + } + monsterKillCount.incrementAndGet(); + if (monsterTideCount.get() > 0) { + // add more + sceneScriptManager.getScriptMonsterSpawnService().spawnMonster(currentGroup.id, getNextMonster()); + } + // spawn the last turn of monsters + // fix the 5-2 + sceneScriptManager.callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(monsterKillCount.get())); + } + + } + + public void unload(){ + this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead); + } +} diff --git a/src/main/java/emu/grasscutter/server/dispatch/AnnouncementHandler.java b/src/main/java/emu/grasscutter/server/dispatch/AnnouncementHandler.java deleted file mode 100644 index 333d8ea21..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/AnnouncementHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package emu.grasscutter.server.dispatch; - -import emu.grasscutter.Grasscutter; -import express.http.HttpContextHandler; -import express.http.Request; -import express.http.Response; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Objects; - -public final class AnnouncementHandler implements HttpContextHandler { - @Override - public void handle(Request request, Response response) throws IOException {//event - if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnContent")) { - response.send("{\"retcode\":0,\"message\":\"OK\",\"data\":" + readToString(new File(Grasscutter.getConfig().DATA_FOLDER + "GameAnnouncement.json")) +"}"); - } else if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnList")) { - String data = readToString(new File(Grasscutter.getConfig().DATA_FOLDER + "GameAnnouncementList.json")).replace("System.currentTimeMillis()",String.valueOf(System.currentTimeMillis())); - response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": "+data +"}"); - } - } - private static String readToString(File file) { - Long filelength = file.length(); - byte[] filecontent = new byte[filelength.intValue()]; - try { - FileInputStream in = new FileInputStream(file); - in.read(filecontent); - in.close(); - } catch (IOException fileNotFoundException) { - fileNotFoundException.printStackTrace(); - } - return new String(filecontent); - } -} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/dispatch/ClientLogHandler.java b/src/main/java/emu/grasscutter/server/dispatch/ClientLogHandler.java deleted file mode 100644 index b3d48dbbb..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/ClientLogHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package emu.grasscutter.server.dispatch; - -import express.http.HttpContextHandler; -import express.http.Request; -import express.http.Response; - -import java.io.IOException; - -/** - * Used for processing crash dumps and logs generated by the game. - * Logs are in JSON, and are sent to the server for logging. - */ -public final class ClientLogHandler implements HttpContextHandler { - @Override - public void handle(Request request, Response response) throws IOException { - // TODO: Figure out how to dump request body and log to file. - response.send("{\"code\":0}"); - } -} diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java deleted file mode 100644 index 7e4b1655e..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java +++ /dev/null @@ -1,538 +0,0 @@ -package emu.grasscutter.server.dispatch; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.protobuf.ByteString; - -import emu.grasscutter.Config; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerDebugMode; -import emu.grasscutter.Grasscutter.ServerRunMode; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp; -import emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp; -import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; -import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo; -import emu.grasscutter.server.dispatch.authentication.AuthenticationHandler; -import emu.grasscutter.server.dispatch.authentication.DefaultAuthenticationHandler; -import emu.grasscutter.server.dispatch.http.GachaRecordHandler; -import emu.grasscutter.server.dispatch.json.*; -import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData; -import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent; -import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent; -import emu.grasscutter.tools.Tools; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; -import express.Express; -import io.javalin.http.staticfiles.Location; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -import java.io.*; -import java.net.URLDecoder; -import java.util.*; - -import static emu.grasscutter.utils.Language.translate; - -public final class DispatchServer { - public static String query_region_list = ""; - public static String query_cur_region = ""; - - private final Gson gson; - private final String defaultServerName = "os_usa"; - - public String regionListBase64; - public Map regions; - private AuthenticationHandler authHandler; - private Express httpServer; - - public DispatchServer() { - this.regions = new HashMap<>(); - this.gson = new GsonBuilder().create(); - - this.loadQueries(); - this.initRegion(); - } - - public Express getServer() { - return httpServer; - } - - public void setHttpServer(Express httpServer) { - this.httpServer.stop(); - this.httpServer = httpServer; - this.httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port); - } - - public Gson getGsonFactory() { - return gson; - } - - public QueryCurrRegionHttpRsp getCurrRegion() { - // Needs to be fixed by having the game servers connect to the dispatch server. - if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) { - return regions.get(defaultServerName).parsedRegionQuery; - } - - Grasscutter.getLogger().warn("[Dispatch] Unsupported run mode for getCurrRegion()"); - return null; - } - - public void loadQueries() { - File file; - - file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_region_list.txt"); - if (file.exists()) { - query_region_list = new String(FileUtils.read(file)); - } else { - Grasscutter.getLogger().warn("[Dispatch] query_region_list not found! Using default region list."); - } - - file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt"); - if (file.exists()) { - query_cur_region = new String(FileUtils.read(file)); - } else { - Grasscutter.getLogger().warn("[Dispatch] query_cur_region not found! Using default current region."); - } - } - - private void initRegion() { - try { - byte[] decoded = Base64.getDecoder().decode(query_region_list); - QueryRegionListHttpRsp rl = QueryRegionListHttpRsp.parseFrom(decoded); - - byte[] decoded2 = Base64.getDecoder().decode(query_cur_region); - QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2); - - List servers = new ArrayList<>(); - List usedNames = new ArrayList<>(); // List to check for potential naming conflicts - if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) { // Automatically add the game server if in - // hybrid mode - RegionSimpleInfo server = RegionSimpleInfo.newBuilder() - .setName("os_usa") - .setTitle(Grasscutter.getConfig().getGameServerOptions().Name) - .setType("DEV_PUBLIC") - .setDispatchUrl( - "http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" - + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() - ? Grasscutter.getConfig().getDispatchOptions().Ip - : Grasscutter.getConfig().getDispatchOptions().PublicIp) - + ":" - + (Grasscutter.getConfig().getDispatchOptions().PublicPort != 0 - ? Grasscutter.getConfig().getDispatchOptions().PublicPort - : Grasscutter.getConfig().getDispatchOptions().Port) - + "/query_cur_region/" + defaultServerName) - .build(); - usedNames.add(defaultServerName); - servers.add(server); - - RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() - .setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() - ? Grasscutter.getConfig().getGameServerOptions().Ip - : Grasscutter.getConfig().getGameServerOptions().PublicIp)) - .setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 - ? Grasscutter.getConfig().getGameServerOptions().PublicPort - : Grasscutter.getConfig().getGameServerOptions().Port) - .setSecretKey(ByteString - .copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) - .build(); - - QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); - regions.put(defaultServerName, new RegionData(parsedRegionQuery, - Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray()))); - - } else { - if (Grasscutter.getConfig().getDispatchOptions().getGameServers().length == 0) { - Grasscutter.getLogger() - .error("[Dispatch] There are no game servers available. Exiting due to unplayable state."); - System.exit(1); - } - } - - for (Config.DispatchServerOptions.RegionInfo regionInfo : Grasscutter.getConfig().getDispatchOptions() - .getGameServers()) { - if (usedNames.contains(regionInfo.Name)) { - Grasscutter.getLogger().error("Region name already in use."); - continue; - } - RegionSimpleInfo server = RegionSimpleInfo.newBuilder() - .setName(regionInfo.Name) - .setTitle(regionInfo.Title) - .setType("DEV_PUBLIC") - .setDispatchUrl( - "http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" - + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() - ? Grasscutter.getConfig().getDispatchOptions().Ip - : Grasscutter.getConfig().getDispatchOptions().PublicIp) - + ":" + (Grasscutter.getConfig().getDispatchOptions().PublicPort != 0 - ? Grasscutter.getConfig().getDispatchOptions().PublicPort - : Grasscutter.getConfig().getDispatchOptions().Port) + "/query_cur_region/" + regionInfo.Name) - .build(); - usedNames.add(regionInfo.Name); - servers.add(server); - - RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() - .setGateserverIp(regionInfo.Ip) - .setGateserverPort(regionInfo.Port) - .setSecretKey(ByteString - .copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) - .build(); - - QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); - regions.put(regionInfo.Name, new RegionData(parsedRegionQuery, - Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray()))); - } - - QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder() - .addAllRegionList(servers) - .setClientSecretKey(rl.getClientSecretKey()) - .setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted()) - .setEnableLoginPc(true) - .build(); - - this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray()); - } catch (Exception e) { - Grasscutter.getLogger().error("[Dispatch] Error while initializing region info!", e); - } - } - - public void start() throws Exception { - httpServer = new Express(config -> { - config.server(() -> { - Server server = new Server(); - ServerConnector serverConnector; - - if(Grasscutter.getConfig().getDispatchOptions().UseSSL) { - SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); - File keystoreFile = new File(Grasscutter.getConfig().getDispatchOptions().KeystorePath); - - if(keystoreFile.exists()) { - try { - sslContextFactory.setKeyStorePath(keystoreFile.getPath()); - sslContextFactory.setKeyStorePassword(Grasscutter.getConfig().getDispatchOptions().KeystorePassword); - } catch (Exception e) { - e.printStackTrace(); - Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.password_error")); - - try { - sslContextFactory.setKeyStorePath(keystoreFile.getPath()); - sslContextFactory.setKeyStorePassword("123456"); - Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.default_password")); - } catch (Exception e2) { - Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.general_error")); - e2.printStackTrace(); - } - } - - serverConnector = new ServerConnector(server, sslContextFactory); - } else { - Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.no_keystore_error")); - Grasscutter.getConfig().getDispatchOptions().UseSSL = false; - - serverConnector = new ServerConnector(server); - } - } else { - serverConnector = new ServerConnector(server); - } - - serverConnector.setPort(Grasscutter.getConfig().getDispatchOptions().Port); - server.setConnectors(new Connector[]{serverConnector}); - return server; - }); - - config.enforceSsl = Grasscutter.getConfig().getDispatchOptions().UseSSL; - if(Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { - config.enableDevLogging(); - } - if (Grasscutter.getConfig().getDispatchOptions().CORS){ - if (Grasscutter.getConfig().getDispatchOptions().CORSAllowedOrigins.length > 0) config.enableCorsForOrigin(Grasscutter.getConfig().getDispatchOptions().CORSAllowedOrigins); - else config.enableCorsForAllOrigins(); - } - }); - httpServer.get("/", (req, res) -> res.send(translate("messages.status.welcome"))); - - httpServer.raw().error(404, ctx -> { - if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) { - Grasscutter.getLogger().info(translate("messages.dispatch.unhandled_request_error", ctx.method(), ctx.url())); - } - ctx.contentType("text/html"); - ctx.result(""); // I'm like 70% sure this won't break anything. - }); - - // Authentication Handler - // These routes are so that authentication routes are always the same no matter what auth system is used. - httpServer.get("/authentication/type", (req, res) -> { - res.send(this.getAuthHandler().getClass().getName()); - }); - - httpServer.post("/authentication/login", (req, res) -> this.getAuthHandler().handleLogin(req, res)); - httpServer.post("/authentication/register", (req, res) -> this.getAuthHandler().handleRegister(req, res)); - httpServer.post("/authentication/change_password", (req, res) -> this.getAuthHandler().handleChangePassword(req, res)); - - // Dispatch - httpServer.get("/query_region_list", (req, res) -> { - // Log - Grasscutter.getLogger().info(String.format("[Dispatch] Client %s request: query_region_list", req.ip())); - - // Invoke event. - QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListBase64); event.call(); - // Respond with event result. - res.send(event.getRegionList()); - }); - - httpServer.get("/query_cur_region/:id", (req, res) -> { - String regionName = req.params("id"); - // Log - Grasscutter.getLogger().info( - String.format("Client %s request: query_cur_region/%s", req.ip(), regionName)); - // Create a response form the request query parameters - String response = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="; - if (req.query().values().size() > 0) { - response = regions.get(regionName).Base64; - } - - // Invoke event. - QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(response); event.call(); - // Respond with event result. - res.send(event.getRegionInfo()); - }); - - // Login - - httpServer.post("/hk4e_global/mdk/shield/api/login", (req, res) -> { - // Get post data - LoginAccountRequestJson requestData = null; - try { - String body = req.ctx().body(); - requestData = getGsonFactory().fromJson(body, LoginAccountRequestJson.class); - } catch (Exception ignored) { } - - // Create response json - if (requestData == null) { - return; - } - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", req.ip())); - - res.send(this.getAuthHandler().handleGameLogin(req, requestData)); - }); - - // Login via token - httpServer.post("/hk4e_global/mdk/shield/api/verify", (req, res) -> { - // Get post data - LoginTokenRequestJson requestData = null; - try { - String body = req.ctx().body(); - requestData = getGsonFactory().fromJson(body, LoginTokenRequestJson.class); - } catch (Exception ignored) { - } - - // Create response json - if (requestData == null) { - return; - } - LoginResultJson responseData = new LoginResultJson(); - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", req.ip())); - - // Login - Account account = DatabaseHelper.getAccountById(requestData.uid); - - // Test - if (account == null || !account.getSessionKey().equals(requestData.token)) { - responseData.retcode = -111; - responseData.message = translate("messages.dispatch.account.account_cache_error"); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_error", req.ip())); - } else { - responseData.message = "OK"; - responseData.data.account.uid = requestData.uid; - responseData.data.account.token = requestData.token; - responseData.data.account.email = account.getEmail(); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_success", req.ip(), requestData.uid)); - } - - res.send(responseData); - }); - - // Exchange for combo token - httpServer.post("/hk4e_global/combo/granter/login/v2/login", (req, res) -> { - // Get post data - ComboTokenReqJson requestData = null; - try { - String body = req.ctx().body(); - requestData = getGsonFactory().fromJson(body, ComboTokenReqJson.class); - } catch (Exception ignored) { - } - - // Create response json - if (requestData == null || requestData.data == null) { - return; - } - LoginTokenData loginData = getGsonFactory().fromJson(requestData.data, LoginTokenData.class); // Get login - // data - ComboTokenResJson responseData = new ComboTokenResJson(); - - // Login - Account account = DatabaseHelper.getAccountById(loginData.uid); - - // Test - if (account == null || !account.getSessionKey().equals(loginData.token)) { - responseData.retcode = -201; - responseData.message = translate("messages.dispatch.account.session_key_error"); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.combo_token_error", req.ip())); - } else { - responseData.message = "OK"; - responseData.data.open_id = loginData.uid; - responseData.data.combo_id = "157795300"; - responseData.data.combo_token = account.generateLoginToken(); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.combo_token_success", req.ip())); - } - - res.send(responseData); - }); - - // TODO: There are some missing route request types here (You can tell if they are missing if they are .all and not anything else) - // When http requests for theses routes are found please remove it from the list in DispatchHttpJsonHandler and update the route request types here - - // Agreement and Protocol - // hk4e-sdk-os.hoyoverse.com - httpServer.get("/hk4e_global/mdk/agreement/api/getAgreementInfos", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}")); - // hk4e-sdk-os.hoyoverse.com - // this could be either GET or POST based on the observation of different clients - httpServer.all("/hk4e_global/combo/granter/api/compareProtocolVersion", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}")); - - // Game data - // hk4e-api-os.hoyoverse.com - httpServer.all("/common/hk4e_global/announcement/api/getAlertPic", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")); - // hk4e-api-os.hoyoverse.com - httpServer.all("/common/hk4e_global/announcement/api/getAlertAnn", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}")); - // hk4e-api-os.hoyoverse.com - httpServer.all("/common/hk4e_global/announcement/api/getAnnList", new AnnouncementHandler()); - // hk4e-api-os-static.hoyoverse.com - httpServer.all("/common/hk4e_global/announcement/api/getAnnContent", new AnnouncementHandler()); - // hk4e-sdk-os.hoyoverse.com - httpServer.all("/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")); - - // Captcha - // api-account-os.hoyoverse.com - httpServer.post("/account/risky/api/check", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}")); - - // Config - // sdk-os-static.hoyoverse.com - httpServer.get("/combo/box/api/config/sdk/combo", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}")); - // hk4e-sdk-os-static.hoyoverse.com - httpServer.get("/hk4e_global/combo/granter/api/getConfig", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")); - // hk4e-sdk-os-static.hoyoverse.com - httpServer.get("/hk4e_global/mdk/shield/api/loadConfig", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")); - // Test api? - // abtest-api-data-sg.hoyoverse.com - httpServer.post("/data_abtest_api/config/experiment/list", new DispatchHttpJsonHandler("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")); - - // log-upload-os.mihoyo.com - httpServer.all("/log/sdk/upload", new DispatchHttpJsonHandler("{\"code\":0}")); - httpServer.all("/sdk/upload", new DispatchHttpJsonHandler("{\"code\":0}")); - httpServer.post("/sdk/dataUpload", new DispatchHttpJsonHandler("{\"code\":0}")); - // /perf/config/verify?device_id=xxx&platform=x&name=xxx - httpServer.all("/perf/config/verify", new DispatchHttpJsonHandler("{\"code\":0}")); - - // Logging servers - // overseauspider.yuanshen.com - httpServer.all("/log", new ClientLogHandler()); - // log-upload-os.mihoyo.com - httpServer.all("/crash/dataUpload", new ClientLogHandler()); - - // webstatic-sea.hoyoverse.com - httpServer.get("/admin/mi18n/plat_oversea/m202003048/m202003048-version.json", new DispatchHttpJsonHandler("{\"version\":51}")); - - // gacha record. - String gachaMappingsPath = Utils.toFilePath(Grasscutter.getConfig().DATA_FOLDER + "/gacha_mappings.js"); - // TODO: Only serve the html page and have a subsequent request to fetch the gacha data. - httpServer.get("/gacha", new GachaRecordHandler()); - if(!(new File(gachaMappingsPath).exists())) { - Tools.createGachaMapping(gachaMappingsPath); - } - - httpServer.raw().config.addSinglePageRoot("/gacha/mappings", gachaMappingsPath, Location.EXTERNAL); - - // static file support for plugins - httpServer.raw().config.precompressStaticFiles = false; // If this isn't set to false, files such as images may appear corrupted when serving static files - - httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port); - Grasscutter.getLogger().info(translate("messages.dispatch.port_bind", Integer.toString(httpServer.raw().port()))); - } - - private Map parseQueryString(String qs) { - Map result = new HashMap<>(); - if (qs == null) { - return result; - } - - int last = 0, next, l = qs.length(); - while (last < l) { - next = qs.indexOf('&', last); - if (next == -1) { - next = l; - } - - if (next > last) { - int eqPos = qs.indexOf('=', last); - try { - if (eqPos < 0 || eqPos > next) { - result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), ""); - } else { - result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), - URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8")); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java - } - } - last = next + 1; - } - return result; - } - - public AuthenticationHandler getAuthHandler() { - if(authHandler == null) { - return new DefaultAuthenticationHandler(); - } - return authHandler; - } - - public boolean registerAuthHandler(AuthenticationHandler authHandler) { - if(this.authHandler != null) { - Grasscutter.getLogger().error(String.format("[Dispatch] Unable to register '%s' authentication handler. \n" + - "The '%s' authentication handler has already been registered", authHandler.getClass().getName(), this.authHandler.getClass().getName())); - return false; - } - this.authHandler = authHandler; - return true; - } - - public void resetAuthHandler() { - this.authHandler = null; - } - - public static class RegionData { - QueryCurrRegionHttpRsp parsedRegionQuery; - String Base64; - - public RegionData(QueryCurrRegionHttpRsp prq, String b64) { - this.parsedRegionQuery = prq; - this.Base64 = b64; - } - - public QueryCurrRegionHttpRsp getParsedRegionQuery() { - return parsedRegionQuery; - } - - public String getBase64() { - return Base64; - } - } -} diff --git a/src/main/java/emu/grasscutter/server/dispatch/authentication/AuthenticationHandler.java b/src/main/java/emu/grasscutter/server/dispatch/authentication/AuthenticationHandler.java deleted file mode 100644 index 92a2961ea..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/authentication/AuthenticationHandler.java +++ /dev/null @@ -1,16 +0,0 @@ -package emu.grasscutter.server.dispatch.authentication; - -import emu.grasscutter.server.dispatch.json.LoginAccountRequestJson; -import emu.grasscutter.server.dispatch.json.LoginResultJson; -import express.http.Request; -import express.http.Response; - -public interface AuthenticationHandler { - - // This is in case plugins also want some sort of authentication - void handleLogin(Request req, Response res); - void handleRegister(Request req, Response res); - void handleChangePassword(Request req, Response res); - - LoginResultJson handleGameLogin(Request req, LoginAccountRequestJson requestData); -} diff --git a/src/main/java/emu/grasscutter/server/dispatch/authentication/DefaultAuthenticationHandler.java b/src/main/java/emu/grasscutter/server/dispatch/authentication/DefaultAuthenticationHandler.java deleted file mode 100644 index e5a4ca055..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/authentication/DefaultAuthenticationHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -package emu.grasscutter.server.dispatch.authentication; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.server.dispatch.json.LoginAccountRequestJson; -import emu.grasscutter.server.dispatch.json.LoginResultJson; -import express.http.Request; -import express.http.Response; - -import static emu.grasscutter.utils.Language.translate; - -public class DefaultAuthenticationHandler implements AuthenticationHandler { - - @Override - public void handleLogin(Request req, Response res) { - res.send("Authentication is not available with the default authentication method"); - } - - @Override - public void handleRegister(Request req, Response res) { - res.send("Authentication is not available with the default authentication method"); - } - - @Override - public void handleChangePassword(Request req, Response res) { - res.send("Authentication is not available with the default authentication method"); - } - - @Override - public LoginResultJson handleGameLogin(Request req, LoginAccountRequestJson requestData) { - LoginResultJson responseData = new LoginResultJson(); - - // Login - Account account = DatabaseHelper.getAccountByName(requestData.account); - - // Check if account exists, else create a new one. - if (account == null) { - // Account doesn't exist, so we can either auto create it if the config value is set. - if (Grasscutter.getConfig().getDispatchOptions().AutomaticallyCreateAccounts) { - // This account has been created AUTOMATICALLY. There will be no permissions added. - account = DatabaseHelper.createAccountWithId(requestData.account, 0); - - for (String permission : Grasscutter.getConfig().getDispatchOptions().defaultPermissions) { - account.addPermission(permission); - } - - if (account != null) { - responseData.message = "OK"; - responseData.data.account.uid = account.getId(); - responseData.data.account.token = account.generateSessionKey(); - responseData.data.account.email = account.getEmail(); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_success", req.ip(), responseData.data.account.uid)); - } else { - responseData.retcode = -201; - responseData.message = translate("messages.dispatch.account.username_create_error"); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_error", req.ip())); - } - } else { - responseData.retcode = -201; - responseData.message = translate("messages.dispatch.account.username_error"); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_exist_error", req.ip())); - } - } else { - // Account was found, log the player in - responseData.message = "OK"; - responseData.data.account.uid = account.getId(); - responseData.data.account.token = account.generateSessionKey(); - responseData.data.account.email = account.getEmail(); - - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_success", req.ip(), responseData.data.account.uid)); - } - - return responseData; - } -} diff --git a/src/main/java/emu/grasscutter/server/dispatch/http/GachaRecordHandler.java b/src/main/java/emu/grasscutter/server/dispatch/http/GachaRecordHandler.java deleted file mode 100644 index 8676574bb..000000000 --- a/src/main/java/emu/grasscutter/server/dispatch/http/GachaRecordHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -package emu.grasscutter.server.dispatch.http; - -import java.io.File; -import java.io.IOException; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.database.DatabaseHelper; -import emu.grasscutter.game.Account; -import emu.grasscutter.utils.FileUtils; -import emu.grasscutter.utils.Utils; -import express.http.HttpContextHandler; -import express.http.Request; -import express.http.Response; - -public final class GachaRecordHandler implements HttpContextHandler { - String render_template; - public GachaRecordHandler() { - File template = new File(Utils.toFilePath(Grasscutter.getConfig().DATA_FOLDER + "/gacha_records.html")); - if (template.exists()) { - // Load from cache - render_template = new String(FileUtils.read(template)); - } else { - render_template = "{{REPLACE_RECORD}}"; - } - } - - @Override - public void handle(Request req, Response res) throws IOException { - // Grasscutter.getLogger().info( req.query().toString() ); - String sessionKey = req.query("s"); - int page = 0; - int gachaType = 0; - if (req.query("p") != null) { - page = Integer.valueOf(req.query("p")); - } - - if (req.query("gachaType") != null) { - gachaType = Integer.valueOf(req.query("gachaType")); - } - - Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); - if (account != null) { - String records = DatabaseHelper.getGachaRecords(account.getPlayerUid(), page, gachaType).toString(); - // Grasscutter.getLogger().info(records); - String response = render_template.replace("{{REPLACE_RECORD}}", records) - .replace("{{REPLACE_MAXPAGE}}", String.valueOf(DatabaseHelper.getGachaRecordsMaxPage(account.getPlayerUid(), page, gachaType))); - - res.send(response); - } else { - res.send("No account found."); - } - } -} diff --git a/src/main/java/emu/grasscutter/server/event/game/CommandResponseEvent.java b/src/main/java/emu/grasscutter/server/event/game/CommandResponseEvent.java new file mode 100644 index 000000000..c3c8fd89a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/event/game/CommandResponseEvent.java @@ -0,0 +1,24 @@ +package emu.grasscutter.server.event.game; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.event.types.GameEvent; +import emu.grasscutter.server.event.types.ServerEvent; + +public class CommandResponseEvent extends ServerEvent { + private String message; + private Player player; + + public CommandResponseEvent(Type type, Player player,String message) { + super(type); + this.message = message; + this.player = player; + } + + public String getMessage() { + return message; + } + + public Player getPlayer() { + return player; + } +} diff --git a/src/main/java/emu/grasscutter/server/event/internal/ServerLogEvent.java b/src/main/java/emu/grasscutter/server/event/internal/ServerLogEvent.java new file mode 100644 index 000000000..5903d4021 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/event/internal/ServerLogEvent.java @@ -0,0 +1,22 @@ +package emu.grasscutter.server.event.internal; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import emu.grasscutter.server.event.types.ServerEvent; + +public class ServerLogEvent extends ServerEvent { + ILoggingEvent loggingEvent; + String consoleMessage; + + public ServerLogEvent(Type type, ILoggingEvent loggingEvent, String consoleMessage) { + super(type); + this.loggingEvent = loggingEvent; + this.consoleMessage = consoleMessage; + } + + public ILoggingEvent getLoggingEvent() { return loggingEvent; } + + public String getConsoleMessage() { + return consoleMessage; + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 7ce8488ef..c0560fcc0 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -10,11 +10,14 @@ import emu.grasscutter.game.drop.DropManager; import emu.grasscutter.game.dungeons.DungeonManager; import emu.grasscutter.game.expedition.ExpeditionManager; import emu.grasscutter.game.gacha.GachaManager; -import emu.grasscutter.game.managers.ChatManager; +import emu.grasscutter.game.managers.ChatManager.ChatManager; +import emu.grasscutter.game.managers.ChatManager.ChatManagerHandler; import emu.grasscutter.game.managers.InventoryManager; import emu.grasscutter.game.managers.MultiplayerManager; import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.ServerQuestHandler; import emu.grasscutter.game.shop.ShopManager; +import emu.grasscutter.game.tower.TowerScheduleManager; import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; @@ -24,25 +27,25 @@ import emu.grasscutter.server.event.game.ServerTickEvent; import emu.grasscutter.server.event.internal.ServerStartEvent; import emu.grasscutter.server.event.internal.ServerStopEvent; import emu.grasscutter.task.TaskMap; +import emu.grasscutter.BuildConfig; import java.net.InetSocketAddress; import java.time.OffsetDateTime; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; public final class GameServer extends KcpServer { private final InetSocketAddress address; private final GameServerPacketHandler packetHandler; - + private final ServerQuestHandler questHandler; + private final Map players; private final Set worlds; - private final ChatManager chatManager; + private ChatManagerHandler chatManager; private final InventoryManager inventoryManager; private final GachaManager gachaManager; private final ShopManager shopManager; @@ -54,20 +57,30 @@ public final class GameServer extends KcpServer { private final DropManager dropManager; private final CombineManger combineManger; + private final TowerScheduleManager towerScheduleManager; - public GameServer() { - this(new InetSocketAddress( - Grasscutter.getConfig().getGameServerOptions().Ip, - Grasscutter.getConfig().getGameServerOptions().Port - )); + private static InetSocketAddress getAdapterInetSocketAddress(){ + InetSocketAddress inetSocketAddress = null; + if(GAME_INFO.bindAddress.equals("")){ + inetSocketAddress=new InetSocketAddress(GAME_INFO.bindPort); + }else{ + inetSocketAddress=new InetSocketAddress( + GAME_INFO.bindAddress, + GAME_INFO.bindPort + ); + } + return inetSocketAddress; + } + public GameServer() { + this(getAdapterInetSocketAddress()); } - public GameServer(InetSocketAddress address) { super(address); this.setServerInitializer(new GameServerInitializer(this)); this.address = address; this.packetHandler = new GameServerPacketHandler(PacketHandler.class); + this.questHandler = new ServerQuestHandler(); this.players = new ConcurrentHashMap<>(); this.worlds = Collections.synchronizedSet(new HashSet<>()); @@ -82,7 +95,7 @@ public final class GameServer extends KcpServer { this.dropManager = new DropManager(this); this.expeditionManager = new ExpeditionManager(this); this.combineManger = new CombineManger(this); - + this.towerScheduleManager = new TowerScheduleManager(this); // Hook into shutdown event. Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown)); } @@ -91,6 +104,10 @@ public final class GameServer extends KcpServer { return packetHandler; } + public ServerQuestHandler getQuestHandler() { + return questHandler; + } + public Map getPlayers() { return players; } @@ -99,9 +116,13 @@ public final class GameServer extends KcpServer { return worlds; } - public ChatManager getChatManager() { + public ChatManagerHandler getChatManager() { return chatManager; } + + public void setChatManager(ChatManagerHandler chatManager) { + this.chatManager = chatManager; + } public InventoryManager getInventoryManager() { return inventoryManager; @@ -139,6 +160,10 @@ public final class GameServer extends KcpServer { return this.combineManger; } + public TowerScheduleManager getTowerScheduleManager() { + return towerScheduleManager; + } + public TaskMap getTaskMap() { return this.taskMap; } @@ -166,12 +191,17 @@ public final class GameServer extends KcpServer { // Check database if character isnt here if (player == null) { - player = DatabaseHelper.getPlayerById(id); + player = DatabaseHelper.getPlayerByUid(id); } return player; } + public Player getPlayerByAccountId(String accountId) { + Optional playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getId().equals(accountId)).findFirst(); + return playerOpt.orElse(null); + } + public SocialDetail.Builder getSocialDetailByUid(int id) { // Get from online players Player player = this.getPlayerByUid(id, true); diff --git a/src/main/java/emu/grasscutter/server/game/GameServerInitializer.java b/src/main/java/emu/grasscutter/server/game/GameServerInitializer.java index 1c5f51388..6c48e30c1 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServerInitializer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServerInitializer.java @@ -13,8 +13,10 @@ public class GameServerInitializer extends KcpServerInitializer { @Override protected void initChannel(UkcpChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - GameSession session = new GameSession(server); - pipeline.addLast(session); + ChannelPipeline pipeline=null; + if(ch!=null){ + pipeline = ch.pipeline(); + } + new GameSession(server,pipeline); } } diff --git a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java index 88e7fa17f..4bba854ef 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java +++ b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java @@ -14,6 +14,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import static emu.grasscutter.Configuration.*; + @SuppressWarnings("unchecked") public class GameServerPacketHandler { private final Int2ObjectMap handlers; @@ -92,7 +94,7 @@ public class GameServerPacketHandler { } // Log unhandled packets - if (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) { + if (SERVER.debugLevel == ServerDebugMode.MISSING) { Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode)); } } diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index d1d7eef01..397d5ba6f 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -3,7 +3,8 @@ package emu.grasscutter.server.game; import java.io.File; import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; import java.util.Set; import emu.grasscutter.Grasscutter; @@ -18,14 +19,17 @@ import emu.grasscutter.server.event.game.SendPacketEvent; import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.Utils; +import io.jpower.kcp.netty.UkcpChannel; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; public class GameSession extends KcpChannel { - private GameServer server; + private final GameServer server; private Account account; private Player player; @@ -36,11 +40,30 @@ public class GameSession extends KcpChannel { private int clientTime; private long lastPingTime; private int lastClientSeq = 10; - + + private final ChannelPipeline pipeline; + @Override + public void close() { + setState(SessionState.INACTIVE); + //send disconnection pack in case of reconnection + try { + send(new BasePacket(PacketOpcodes.ServerDisconnectClientNotify)); + }catch (Throwable ignore){ + + } + super.close(); + } public GameSession(GameServer server) { + this(server,null); + } + public GameSession(GameServer server, ChannelPipeline pipeline) { this.server = server; this.state = SessionState.WAITING_FOR_TOKEN; this.lastPingTime = System.currentTimeMillis(); + this.pipeline = pipeline; + if(pipeline!=null) { + pipeline.addLast(this); + } } public GameServer getServer() { @@ -124,13 +147,17 @@ public class GameSession extends KcpChannel { // Set state so no more packets can be handled this.setState(SessionState.INACTIVE); - + // Save after disconnecting if (this.isLoggedIn()) { + Player player = getPlayer(); // Call logout event. - getPlayer().onLogout(); - // Remove from server. - getServer().getPlayers().remove(getPlayer().getUid()); + player.onLogout(); + } + try { + pipeline.remove(this); + } catch (Throwable ignore) { + } } @@ -140,7 +167,7 @@ public class GameSession extends KcpChannel { } public void replayPacket(int opcode, String name) { - String filePath = Grasscutter.getConfig().PACKETS_FOLDER + name; + String filePath = PACKET(name); File p = new File(filePath); if (!p.exists()) return; @@ -172,7 +199,7 @@ public class GameSession extends KcpChannel { } // Log - if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { + if (SERVER.debugLevel == ServerDebugMode.ALL) { logPacket(packet); } @@ -239,7 +266,7 @@ public class GameSession extends KcpChannel { } // Log packet - if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) { + if (SERVER.debugLevel == ServerDebugMode.ALL) { if (!loopPacket.contains(opcode)) { Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")"); System.out.println(Utils.bytesToHex(payload)); @@ -252,6 +279,7 @@ public class GameSession extends KcpChannel { } catch (Exception e) { e.printStackTrace(); } finally { + data.release(); packet.release(); } } diff --git a/src/main/java/emu/grasscutter/server/http/HttpServer.java b/src/main/java/emu/grasscutter/server/http/HttpServer.java new file mode 100644 index 000000000..bcc020ed7 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/HttpServer.java @@ -0,0 +1,202 @@ +package emu.grasscutter.server.http; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerDebugMode; +import emu.grasscutter.utils.FileUtils; +import express.Express; +import express.http.MediaType; +import io.javalin.Javalin; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +import java.io.File; +import java.io.IOException; + +import static emu.grasscutter.Configuration.*; +import static emu.grasscutter.utils.Language.translate; + +/** + * Manages all HTTP-related classes. + * (including dispatch, announcements, gacha, etc.) + */ +public final class HttpServer { + private final Express express; + + /** + * Configures the Express application. + */ + public HttpServer() { + this.express = new Express(config -> { + // Set the Express HTTP server. + config.server(HttpServer::createServer); + + // Configure encryption/HTTPS/SSL. + config.enforceSsl = HTTP_ENCRYPTION.useEncryption; + + // Configure HTTP policies. + if(HTTP_POLICIES.cors.enabled) { + var allowedOrigins = HTTP_POLICIES.cors.allowedOrigins; + if (allowedOrigins.length > 0) + config.enableCorsForOrigin(allowedOrigins); + else config.enableCorsForAllOrigins(); + } + + // Configure debug logging. + if(SERVER.debugLevel == ServerDebugMode.ALL) + config.enableDevLogging(); + + // Disable compression on static files. + config.precompressStaticFiles = false; + }); + } + + /** + * Creates an HTTP(S) server. + * @return A server instance. + */ + @SuppressWarnings("resource") + private static Server createServer() { + Server server = new Server(); + ServerConnector serverConnector + = new ServerConnector(server); + + if(HTTP_ENCRYPTION.useEncryption) { + var sslContextFactory = new SslContextFactory.Server(); + var keystoreFile = new File(HTTP_ENCRYPTION.keystore); + + if(!keystoreFile.exists()) { + HTTP_ENCRYPTION.useEncryption = false; + HTTP_ENCRYPTION.useInRouting = false; + + Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.no_keystore_error")); + } else try { + sslContextFactory.setKeyStorePath(keystoreFile.getPath()); + sslContextFactory.setKeyStorePassword(HTTP_ENCRYPTION.keystorePassword); + } catch (Exception ignored) { + Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.password_error")); + + try { + sslContextFactory.setKeyStorePath(keystoreFile.getPath()); + sslContextFactory.setKeyStorePassword("123456"); + + Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.default_password")); + } catch (Exception exception) { + Grasscutter.getLogger().warn(translate("messages.dispatch.keystore.general_error"), exception); + } + } finally { + serverConnector = new ServerConnector(server, sslContextFactory); + } + } + + serverConnector.setPort(HTTP_INFO.bindPort); + server.setConnectors(new ServerConnector[]{serverConnector}); + + return server; + } + + /** + * Returns the handle for the Express application. + * @return A Javalin instance. + */ + public Javalin getHandle() { + return this.express.raw(); + } + + /** + * Initializes the provided class. + * @param router The router class. + * @return Method chaining. + */ + @SuppressWarnings("UnusedReturnValue") + public HttpServer addRouter(Class router, Object... args) { + // Get all constructor parameters. + Class[] types = new Class[args.length]; + for(var argument : args) + types[args.length - 1] = argument.getClass(); + + try { // Create a router instance & apply routes. + var constructor = router.getDeclaredConstructor(types); // Get the constructor. + var routerInstance = constructor.newInstance(args); // Create instance. + routerInstance.applyRoutes(this.express, this.getHandle()); // Apply routes. + } catch (Exception exception) { + Grasscutter.getLogger().warn(translate("messages.dispatch.router_error"), exception); + } return this; + } + + /** + * Starts listening on the HTTP server. + */ + public void start() { + // Attempt to start the HTTP server. + if(HTTP_INFO.bindAddress.equals("")){ + this.express.listen(HTTP_INFO.bindPort); + }else{ + this.express.listen(HTTP_INFO.bindAddress, HTTP_INFO.bindPort); + } + + // Log bind information. + Grasscutter.getLogger().info(translate("messages.dispatch.port_bind", Integer.toString(this.express.raw().port()))); + } + + /** + * Handles the '/' (index) endpoint on the Express application. + */ + public static class DefaultRequestRouter implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + express.get("/", (request, response) -> { + File file = new File(HTTP_STATIC_FILES.indexFile); + if(!file.exists()) + response.send(""" + + + + + + %s + + """.formatted(translate("messages.status.welcome"))); + else { + final var filePath = file.getPath(); + final MediaType fromExtension = MediaType.getByExtension(filePath.substring(filePath.lastIndexOf(".") + 1)); + response.type((fromExtension != null) ? fromExtension.getMIME() : "text/plain") + .send(FileUtils.read(filePath)); + } + }); + } + } + + /** + * Handles unhandled endpoints on the Express application. + */ + public static class UnhandledRequestRouter implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + handle.error(404, context -> { + if(SERVER.debugLevel == ServerDebugMode.MISSING) + Grasscutter.getLogger().info(translate("messages.dispatch.unhandled_request_error", context.method(), context.url())); + context.contentType("text/html"); + + File file = new File(HTTP_STATIC_FILES.errorFile); + if(!file.exists()) + context.result(""" + + + + + + + + + + + """); + else { + final var filePath = file.getPath(); + final MediaType fromExtension = MediaType.getByExtension(filePath.substring(filePath.lastIndexOf(".") + 1)); + context.contentType((fromExtension != null) ? fromExtension.getMIME() : "text/plain") + .result(FileUtils.read(filePath)); + } + }); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/http/Router.java b/src/main/java/emu/grasscutter/server/http/Router.java new file mode 100644 index 000000000..1720d7ca0 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/Router.java @@ -0,0 +1,16 @@ +package emu.grasscutter.server.http; + +import express.Express; +import io.javalin.Javalin; + +/** + * Defines routes for an {@link Express} instance. + */ +public interface Router { + + /** + * Called when the router is initialized by Express. + * @param express An Express instance. + */ + void applyRoutes(Express express, Javalin handle); +} diff --git a/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java b/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java new file mode 100644 index 000000000..a5545877f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java @@ -0,0 +1,121 @@ +package emu.grasscutter.server.http.dispatch; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.auth.AuthenticationSystem; +import emu.grasscutter.auth.OAuthAuthenticator; +import emu.grasscutter.auth.OAuthAuthenticator.ClientType; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.*; +import emu.grasscutter.server.http.objects.ComboTokenReqJson.LoginTokenData; +import emu.grasscutter.utils.Utils; +import express.Express; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; + +import static emu.grasscutter.utils.Language.translate; + +/** + * Handles requests related to authentication. (aka dispatch) + */ +public final class DispatchHandler implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + // Username & Password login (from client). + express.post("/hk4e_global/mdk/shield/api/login", DispatchHandler::clientLogin); + // Cached token login (from registry). + express.post("/hk4e_global/mdk/shield/api/verify", DispatchHandler::tokenLogin); + // Combo token login (from session key). + express.post("/hk4e_global/combo/granter/login/v2/login", DispatchHandler::sessionKeyLogin); + + // External login (from other clients). + express.get("/authentication/type", (request, response) -> response.send(Grasscutter.getAuthenticationSystem().getClass().getSimpleName())); + express.post("/authentication/login", (request, response) -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() + .handleLogin(AuthenticationSystem.fromExternalRequest(request, response))); + express.post("/authentication/register", (request, response) -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() + .handleAccountCreation(AuthenticationSystem.fromExternalRequest(request, response))); + express.post("/authentication/change_password", (request, response) -> Grasscutter.getAuthenticationSystem().getExternalAuthenticator() + .handlePasswordReset(AuthenticationSystem.fromExternalRequest(request, response))); + + // External login (from OAuth2). + express.post("/hk4e_global/mdk/shield/api/loginByThirdparty", (request, response) -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() + .handleLogin(AuthenticationSystem.fromExternalRequest(request, response))); + express.get("/authentication/openid/redirect", (request, response) -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() + .handleTokenProcess(AuthenticationSystem.fromExternalRequest(request, response))); + express.get("/Api/twitter_login", (request, response) -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() + .handleRedirection(AuthenticationSystem.fromExternalRequest(request, response), ClientType.DESKTOP)); + express.get("/sdkTwitterLogin.html", (request, response) -> Grasscutter.getAuthenticationSystem().getOAuthAuthenticator() + .handleRedirection(AuthenticationSystem.fromExternalRequest(request, response), ClientType.MOBILE)); + } + + /** + * @route /hk4e_global/mdk/shield/api/login + */ + private static void clientLogin(Request request, Response response) { + // Parse body data. + String rawBodyData = request.ctx().body(); + var bodyData = Utils.jsonDecode(rawBodyData, LoginAccountRequestJson.class); + + // Validate body data. + if(bodyData == null) + return; + + // Pass data to authentication handler. + var responseData = Grasscutter.getAuthenticationSystem() + .getPasswordAuthenticator() + .authenticate(AuthenticationSystem.fromPasswordRequest(request, bodyData)); + // Send response. + response.send(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", request.ip())); + } + + /** + * @route /hk4e_global/mdk/shield/api/verify + */ + private static void tokenLogin(Request request, Response response) { + // Parse body data. + String rawBodyData = request.ctx().body(); + var bodyData = Utils.jsonDecode(rawBodyData, LoginTokenRequestJson.class); + + // Validate body data. + if(bodyData == null) + return; + + // Pass data to authentication handler. + var responseData = Grasscutter.getAuthenticationSystem() + .getTokenAuthenticator() + .authenticate(AuthenticationSystem.fromTokenRequest(request, bodyData)); + // Send response. + response.send(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", request.ip())); + } + + /** + * @route /hk4e_global/combo/granter/login/v2/login + */ + private static void sessionKeyLogin(Request request, Response response) { + // Parse body data. + String rawBodyData = request.ctx().body(); + var bodyData = Utils.jsonDecode(rawBodyData, ComboTokenReqJson.class); + + // Validate body data. + if(bodyData == null || bodyData.data == null) + return; + + // Decode additional body data. + var tokenData = Utils.jsonDecode(bodyData.data, LoginTokenData.class); + + // Pass data to authentication handler. + var responseData = Grasscutter.getAuthenticationSystem() + .getSessionKeyAuthenticator() + .authenticate(AuthenticationSystem.fromComboTokenRequest(request, bodyData, tokenData)); + // Send response. + response.send(responseData); + + // Log to console. + Grasscutter.getLogger().info(translate("messages.dispatch.account.login_attempt", request.ip())); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java b/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java new file mode 100644 index 000000000..f2d1cc4ca --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java @@ -0,0 +1,175 @@ +package emu.grasscutter.server.http.dispatch; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerRunMode; +import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.*; +import emu.grasscutter.net.proto.RegionInfoOuterClass; +import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; +import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo; +import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent; +import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.utils.Crypto; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.Express; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; + +import java.io.File; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static emu.grasscutter.Configuration.*; +import static emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.*; + +/** + * Handles requests related to region queries. + */ +public final class RegionHandler implements Router { + private static final Map regions = new ConcurrentHashMap<>(); + private static String regionListResponse; + + public RegionHandler() { + try { // Read & initialize region data. + this.initialize(); + } catch (Exception exception) { + Grasscutter.getLogger().error("Failed to initialize region data.", exception); + } + } + + /** + * Configures region data according to configuration. + */ + private void initialize() { + String dispatchDomain = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); + + // Create regions. + List servers = new ArrayList<>(); + List usedNames = new ArrayList<>(); // List to check for potential naming conflicts. + + var configuredRegions = new ArrayList<>(List.of(DISPATCH_INFO.regions)); + if(SERVER.runMode != ServerRunMode.HYBRID && configuredRegions.size() == 0) { + Grasscutter.getLogger().error("[Dispatch] There are no game servers available. Exiting due to unplayable state."); + System.exit(1); + } else if (configuredRegions.size() == 0) + configuredRegions.add(new Region("os_usa", DISPATCH_INFO.defaultName, + lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress), + lr(GAME_INFO.accessPort, GAME_INFO.bindPort))); + + configuredRegions.forEach(region -> { + if (usedNames.contains(region.Name)) { + Grasscutter.getLogger().error("Region name already in use."); + return; + } + + // Create a region identifier. + var identifier = RegionSimpleInfo.newBuilder() + .setName(region.Name).setTitle(region.Title).setType("DEV_PUBLIC") + .setDispatchUrl(dispatchDomain + "/query_cur_region/" + region.Name) + .build(); + usedNames.add(region.Name); servers.add(identifier); + + // Create a region info object. + var regionInfo = RegionInfo.newBuilder() + .setGateserverIp(region.Ip).setGateserverPort(region.Port) + .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .build(); + // Create an updated region query. + var updatedQuery = QueryCurrRegionHttpRsp.newBuilder().setRegionInfo(regionInfo).build(); + regions.put(region.Name, new RegionData(updatedQuery, Utils.base64Encode(updatedQuery.toByteString().toByteArray()))); + }); + + // Create a config object. + byte[] customConfig = "{\"sdkenv\":\"2\",\"checkdevice\":\"false\",\"loadPatch\":\"false\",\"showexception\":\"false\",\"regionConfig\":\"pm|fk|add\",\"downloadMode\":\"0\"}".getBytes(); + Crypto.xor(customConfig, Crypto.DISPATCH_KEY); // XOR the config with the key. + + // Create an updated region list. + QueryRegionListHttpRsp updatedRegionList = QueryRegionListHttpRsp.newBuilder() + .addAllRegionList(servers) + .setClientSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) + .setClientCustomConfigEncrypted(ByteString.copyFrom(customConfig)) + .setEnableLoginPc(true).build(); + + // Set the region list response. + regionListResponse = Utils.base64Encode(updatedRegionList.toByteString().toByteArray()); + } + + @Override public void applyRoutes(Express express, Javalin handle) { + express.get("/query_region_list", RegionHandler::queryRegionList); + express.get("/query_cur_region/:region", RegionHandler::queryCurrentRegion ); + } + + /** + * @route /query_region_list + */ + private static void queryRegionList(Request request, Response response) { + // Invoke event. + QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListResponse); event.call(); + // Respond with event result. + response.send(event.getRegionList()); + + // Log to console. + Grasscutter.getLogger().info(String.format("[Dispatch] Client %s request: query_region_list", request.ip())); + } + + /** + * @route /query_cur_region/:region + */ + private static void queryCurrentRegion(Request request, Response response) { + // Get region to query. + String regionName = request.params("region"); + + // Get region data. + String regionData = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="; + if (request.query().values().size() > 0) { + var region = regions.get(regionName); + if(region != null) regionData = region.getBase64(); + } + + // Invoke event. + QueryCurrentRegionEvent event = new QueryCurrentRegionEvent(regionData); event.call(); + // Respond with event result. + response.send(event.getRegionInfo()); + + // Log to console. + Grasscutter.getLogger().info(String.format("Client %s request: query_cur_region/%s", request.ip(), regionName)); + } + + /** + * Region data container. + */ + public static class RegionData { + private final QueryCurrRegionHttpRsp regionQuery; + private final String base64; + + public RegionData(QueryCurrRegionHttpRsp prq, String b64) { + this.regionQuery = prq; + this.base64 = b64; + } + + public QueryCurrRegionHttpRsp getRegionQuery() { + return this.regionQuery; + } + + public String getBase64() { + return this.base64; + } + } + + /** + * Gets the current region query. + * @return A {@link QueryCurrRegionHttpRsp} object. + */ + public static QueryCurrRegionHttpRsp getCurrentRegion() { + return SERVER.runMode == ServerRunMode.HYBRID ? regions.get("os_usa").getRegionQuery() : null; + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/DocumentationHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationHandler.java new file mode 100644 index 000000000..de7f543a3 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationHandler.java @@ -0,0 +1,9 @@ +package emu.grasscutter.server.http.documentation; + +import express.http.Request; +import express.http.Response; + +interface DocumentationHandler { + + void handle(Request request, Response response); +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java new file mode 100644 index 000000000..24c8236de --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.http.documentation; + +import emu.grasscutter.server.http.Router; +import express.Express; +import io.javalin.Javalin; + +public final class DocumentationServerHandler implements Router { + + @Override + public void applyRoutes(Express express, Javalin handle) { + final RootRequestHandler root = new RootRequestHandler(); + final HandbookRequestHandler handbook = new HandbookRequestHandler(); + final GachaMappingRequestHandler gachaMapping = new GachaMappingRequestHandler(); + + express.get("/documentation/handbook", handbook::handle); + express.get("/documentation/gachamapping", gachaMapping::handle); + express.get("/documentation", root::handle); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java new file mode 100644 index 000000000..4810978ad --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java @@ -0,0 +1,153 @@ +package emu.grasscutter.server.http.documentation; + +import static emu.grasscutter.Configuration.RESOURCE; + +import com.google.gson.reflect.TypeToken; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.utils.Utils; +import static emu.grasscutter.Configuration.DOCUMENT_LANGUAGE; +import express.http.Request; +import express.http.Response; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +final class GachaMappingRequestHandler implements DocumentationHandler { + + private Map map; + + GachaMappingRequestHandler() { + final String textMapFile = "TextMap/TextMap" + DOCUMENT_LANGUAGE + ".json"; + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream( + Utils.toFilePath(RESOURCE(textMapFile))), StandardCharsets.UTF_8)) { + map = Grasscutter.getGsonFactory().fromJson(fileReader, + new TypeToken>() { + }.getType()); + } catch (IOException e) { + Grasscutter.getLogger().warn("Resource does not exist: " + textMapFile); + map = new HashMap<>(); + } + } + + @Override + public void handle(Request request, Response response) { + if (map.isEmpty()) { + response.status(500); + } else { + response.set("Content-Type", "application/json") + .ctx() + .result(createGachaMappingJson()); + } + } + + private String createGachaMappingJson() { + List list; + + final StringBuilder sb = new StringBuilder(); + list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); + Collections.sort(list); + + final String newLine = System.lineSeparator(); + + // if the user made choices for language, I assume it's okay to assign his/her selected language to "en-us" + // since it's the fallback language and there will be no difference in the gacha record page. + // The enduser can still modify the `gacha_mappings.js` directly to enable multilingual for the gacha record system. + sb.append("{").append(newLine); + + // Avatars + boolean first = true; + for (Integer id : list) { + AvatarData data = GameData.getAvatarDataMap().get(id); + int avatarID = data.getId(); + if (avatarID >= 11000000) { // skip test avatar + continue; + } + if (first) { // skip adding comma for the first element + first = false; + } else { + sb.append(","); + } + String color; + switch (data.getQualityType()) { + case "QUALITY_PURPLE": + color = "purple"; + break; + case "QUALITY_ORANGE": + color = "yellow"; + break; + case "QUALITY_BLUE": + default: + color = "blue"; + } + // Got the magic number 4233146695 from manually search in the json file + sb.append("\"") + .append(avatarID % 1000 + 1000) + .append("\" : [\"") + .append(map.get(data.getNameTextMapHash())) + .append("(") + .append(map.get(4233146695L)) + .append(")\", \"") + .append(color) + .append("\"]") + .append(newLine); + } + + list = new ArrayList<>(GameData.getItemDataMap().keySet()); + Collections.sort(list); + + // Weapons + for (Integer id : list) { + ItemData data = GameData.getItemDataMap().get(id); + if (data.getId() <= 11101 || data.getId() >= 20000) { + continue; //skip non weapon items + } + String color; + + switch (data.getRankLevel()) { + case 3: + color = "blue"; + break; + case 4: + color = "purple"; + break; + case 5: + color = "yellow"; + break; + default: + continue; // skip unnecessary entries + } + + // Got the magic number 4231343903 from manually search in the json file + + sb.append(",\"") + .append(data.getId()) + .append("\" : [\"") + .append(map.get(data.getNameTextMapHash()).replaceAll("\"", "")) + .append("(") + .append(map.get(4231343903L)) + .append(")\",\"") + .append(color) + .append("\"]") + .append(newLine); + } + sb.append(",\"200\": \"") + .append(map.get(332935371L)) + .append("\", \"301\": \"") + .append(map.get(2272170627L)) + .append("\", \"302\": \"") + .append(map.get(2864268523L)) + .append("\"") + .append("}\n}") + .append(newLine); + return sb.toString(); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java new file mode 100644 index 000000000..8153368a0 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java @@ -0,0 +1,123 @@ +package emu.grasscutter.server.http.documentation; + +import static emu.grasscutter.Configuration.*; +import static emu.grasscutter.utils.Language.translate; + +import com.google.gson.reflect.TypeToken; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.CommandMap; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.SceneData; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.http.Request; +import express.http.Response; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +final class HandbookRequestHandler implements DocumentationHandler { + + private final String template; + private Map map; + + + public HandbookRequestHandler() { + final File templateFile = new File(Utils.toFilePath(DATA("documentation/handbook.html"))); + if (templateFile.exists()) { + template = new String(FileUtils.read(templateFile), StandardCharsets.UTF_8); + } else { + Grasscutter.getLogger().warn("File does not exist: " + templateFile); + template = null; + } + + final String textMapFile = "TextMap/TextMap" + DOCUMENT_LANGUAGE + ".json"; + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream( + Utils.toFilePath(RESOURCE(textMapFile))), StandardCharsets.UTF_8)) { + map = Grasscutter.getGsonFactory() + .fromJson(fileReader, new TypeToken>() { + }.getType()); + } catch (IOException e) { + Grasscutter.getLogger().warn("Resource does not exist: " + textMapFile); + map = new HashMap<>(); + } + } + + @Override + public void handle(Request request, Response response) { + if (template == null) { + response.status(500); + return; + } + + final CommandMap cmdMap = new CommandMap(true); + final Int2ObjectMap avatarMap = GameData.getAvatarDataMap(); + final Int2ObjectMap itemMap = GameData.getItemDataMap(); + final Int2ObjectMap sceneMap = GameData.getSceneDataMap(); + final Int2ObjectMap monsterMap = GameData.getMonsterDataMap(); + + // Add translated title etc. to the page. + String content = template.replace("{{TITLE}}", translate("documentation.handbook.title")) + .replace("{{TITLE_COMMANDS}}", translate("documentation.handbook.title_commands")) + .replace("{{TITLE_AVATARS}}", translate("documentation.handbook.title_avatars")) + .replace("{{TITLE_ITEMS}}", translate("documentation.handbook.title_items")) + .replace("{{TITLE_SCENES}}", translate("documentation.handbook.title_scenes")) + .replace("{{TITLE_MONSTERS}}", translate("documentation.handbook.title_monsters")) + .replace("{{HEADER_ID}}", translate("documentation.handbook.header_id")) + .replace("{{HEADER_COMMAND}}", translate("documentation.handbook.header_command")) + .replace("{{HEADER_DESCRIPTION}}", + translate("documentation.handbook.header_description")) + .replace("{{HEADER_AVATAR}}", translate("documentation.handbook.header_avatar")) + .replace("{{HEADER_ITEM}}", translate("documentation.handbook.header_item")) + .replace("{{HEADER_SCENE}}", translate("documentation.handbook.header_scene")) + .replace("{{HEADER_MONSTER}}", translate("documentation.handbook.header_monster")) + // Commands table + .replace("{{COMMANDS_TABLE}}", cmdMap.getAnnotationsAsList() + .stream() + .map(cmd -> "" + cmd.label() + "" + + cmd.description() + "") + .collect(Collectors.joining("\n"))) + // Avatars table + .replace("{{AVATARS_TABLE}}", GameData.getAvatarDataMap().keySet() + .intStream() + .sorted() + .mapToObj(avatarMap::get) + .map(data -> "" + data.getId() + "" + + map.get(data.getNameTextMapHash()) + "") + .collect(Collectors.joining("\n"))) + // Items table + .replace("{{ITEMS_TABLE}}", GameData.getItemDataMap().keySet() + .intStream() + .sorted() + .mapToObj(itemMap::get) + .map(data -> "" + data.getId() + "" + + map.get(data.getNameTextMapHash()) + "") + .collect(Collectors.joining("\n"))) + // Scenes table + .replace("{{SCENES_TABLE}}", GameData.getSceneDataMap().keySet() + .intStream() + .sorted() + .mapToObj(sceneMap::get) + .map(data -> "" + data.getId() + "" + + data.getScriptData() + "") + .collect(Collectors.joining("\n"))) + .replace("{{MONSTERS_TABLE}}", GameData.getMonsterDataMap().keySet() + .intStream() + .sorted() + .mapToObj(monsterMap::get) + .map(data -> "" + data.getId() + "" + + map.get(data.getNameTextMapHash()) + "") + .collect(Collectors.joining("\n"))); + + response.send(content); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java b/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java new file mode 100644 index 000000000..12b738bf3 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java @@ -0,0 +1,41 @@ +package emu.grasscutter.server.http.documentation; + +import static emu.grasscutter.Configuration.DATA; +import static emu.grasscutter.utils.Language.translate; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.ResourceLoader; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.http.Request; +import express.http.Response; +import java.io.File; +import java.nio.charset.StandardCharsets; + +final class RootRequestHandler implements DocumentationHandler { + + private final String template; + + public RootRequestHandler() { + final File templateFile = new File(Utils.toFilePath(DATA("documentation/index.html"))); + if (templateFile.exists()) { + template = new String(FileUtils.read(templateFile), StandardCharsets.UTF_8); + } else { + Grasscutter.getLogger().warn("File does not exist: " + templateFile); + template = null; + } + } + + @Override + public void handle(Request request, Response response) { + if (template == null) { + response.status(500); + return; + } + + String content = template.replace("{{TITLE}}", translate("documentation.index.title")) + .replace("{{ITEM_HANDBOOK}}", translate("documentation.index.handbook")) + .replace("{{ITEM_GACHA_MAPPING}}", translate("documentation.index.gacha_mapping")); + response.send(content); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java new file mode 100644 index 000000000..07790a641 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java @@ -0,0 +1,92 @@ +package emu.grasscutter.server.http.handlers; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.server.http.objects.HttpJsonResponse; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.Express; +import express.http.MediaType; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import static emu.grasscutter.Configuration.*; + +/** + * Handles requests related to the announcements page. + */ +public final class AnnouncementsHandler implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + // hk4e-api-os.hoyoverse.com + express.all("/common/hk4e_global/announcement/api/getAlertPic", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")); + // hk4e-api-os.hoyoverse.com + express.all("/common/hk4e_global/announcement/api/getAlertAnn", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}")); + // hk4e-api-os.hoyoverse.com + express.all("/common/hk4e_global/announcement/api/getAnnList", AnnouncementsHandler::getAnnouncement); + // hk4e-api-os-static.hoyoverse.com + express.all("/common/hk4e_global/announcement/api/getAnnContent", AnnouncementsHandler::getAnnouncement); + // hk4e-sdk-os.hoyoverse.com + express.all("/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")); + + express.get("/hk4e/announcement/*", AnnouncementsHandler::getPageResources); + } + + private static void getAnnouncement(Request request, Response response) { + String data = ""; + if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnContent")) { + try { + data = FileUtils.readToString(DataLoader.load("GameAnnouncement.json")); + } catch (Exception e) { + if(e.getClass() == IOException.class) { + Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); + } + } + } else if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnList")) { + try { + data = FileUtils.readToString(DataLoader.load("GameAnnouncementList.json")); + } catch (Exception e) { + if(e.getClass() == IOException.class) { + Grasscutter.getLogger().info("Unable to read file 'GameAnnouncementList.json'. \n" + e); + } + } + } else { + response.send("{\"retcode\":404,\"message\":\"Unknown request path\"}"); + } + + if (data.isEmpty()) { + response.send("{\"retcode\":500,\"message\":\"Unable to fetch requsted content\"}"); + return; + } + + String dispatchDomain = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); + + data = data + .replace("{{DISPATCH_PUBLIC}}", dispatchDomain) + .replace("{{SYSTEM_TIME}}", String.valueOf(System.currentTimeMillis())); + response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": " + data + "}"); + } + + private static void getPageResources(Request request, Response response) { + try(InputStream filestream = DataLoader.load(request.path())) { + String possibleFilename = Utils.toFilePath(DATA(request.path())); + + MediaType fromExtension = MediaType.getByExtension(possibleFilename.substring(possibleFilename.lastIndexOf(".") + 1)); + response.type((fromExtension != null) ? fromExtension.getMIME() : "application/octet-stream"); + response.send(filestream.readAllBytes()); + } catch (Exception e) { + Grasscutter.getLogger().warn("File does not exist: " + request.path()); + response.status(404); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java new file mode 100644 index 000000000..3acb5a106 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java @@ -0,0 +1,137 @@ +package emu.grasscutter.server.http.handlers; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.gacha.GachaBanner; +import emu.grasscutter.game.gacha.GachaManager; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.tools.Tools; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.Express; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; +import io.javalin.http.staticfiles.Location; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +import static emu.grasscutter.Configuration.DATA; +import static emu.grasscutter.utils.Language.translate; + +/** + * Handles all gacha-related HTTP requests. + */ +public final class GachaHandler implements Router { + public static final String gachaMappings = DATA(Utils.toFilePath("gacha/mappings.js")); + + @Override public void applyRoutes(Express express, Javalin handle) { + express.get("/gacha", GachaHandler::gachaRecords); + express.get("/gacha/details", GachaHandler::gachaDetails); + + express.useStaticFallback("/gacha/mappings", gachaMappings, Location.EXTERNAL); + } + + private static void gachaRecords(Request request, Response response) { + File recordsTemplate = new File(Utils.toFilePath(DATA("gacha/records.html"))); + if (!recordsTemplate.exists()) { + Grasscutter.getLogger().warn("File does not exist: " + recordsTemplate); + response.status(500); + return; + } + + String sessionKey = request.query("s"); + Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); + if(account == null) { + response.status(403).send("Requested account was not found"); + return; + } + Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (player == null) { + response.status(403).send("No player associated with requested account"); + return; + } + + int page = 0, gachaType = 0; + if(request.query("p") != null) + page = Integer.parseInt(request.query("p")); + if(request.query("gachaType") != null) + gachaType = Integer.parseInt(request.query("gachaType")); + + String records = DatabaseHelper.getGachaRecords(player.getUid(), page, gachaType).toString(); + long maxPage = DatabaseHelper.getGachaRecordsMaxPage(player.getUid(), page, gachaType); + + String template = new String(FileUtils.read(recordsTemplate), StandardCharsets.UTF_8) + .replace("{{REPLACE_RECORDS}}", records) + .replace("{{REPLACE_MAXPAGE}}", String.valueOf(maxPage)) + .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); + response.send(template); + } + + private static void gachaDetails(Request request, Response response) { + File detailsTemplate = new File(Utils.toFilePath(DATA("gacha/details.html"))); + if (!detailsTemplate.exists()) { + Grasscutter.getLogger().warn("File does not exist: " + detailsTemplate); + response.status(500); + return; + } + + String sessionKey = request.query("s"); + Account account = DatabaseHelper.getAccountBySessionKey(sessionKey); + if(account == null) { + response.status(403).send("Requested account was not found"); + return; + } + Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (player == null) { + response.status(403).send("No player associated with requested account"); + return; + } + + String template = new String(FileUtils.read(detailsTemplate), StandardCharsets.UTF_8); + + // Add translated title etc. to the page. + template = template.replace("{{TITLE}}", translate(player, "gacha.details.title")) + .replace("{{AVAILABLE_FIVE_STARS}}", translate(player, "gacha.details.available_five_stars")) + .replace("{{AVAILABLE_FOUR_STARS}}", translate(player, "gacha.details.available_four_stars")) + .replace("{{AVAILABLE_THREE_STARS}}", translate(player, "gacha.details.available_three_stars")) + .replace("{{LANGUAGE}}", Utils.getLanguageCode(account.getLocale())); + + // Get the banner info for the banner we want. + int scheduleId = Integer.parseInt(request.query("scheduleId")); + GachaManager manager = Grasscutter.getGameServer().getGachaManager(); + GachaBanner banner = manager.getGachaBanners().get(scheduleId); + + // Add 5-star items. + Set fiveStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems5()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems5Pool1()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems5Pool2()).forEach(i -> fiveStarItems.add(Integer.toString(i))); + + template = template.replace("{{FIVE_STARS}}", "[" + String.join(",", fiveStarItems) + "]"); + + // Add 4-star items. + Set fourStarItems = new LinkedHashSet<>(); + + Arrays.stream(banner.getRateUpItems4()).forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems4Pool1()).forEach(i -> fourStarItems.add(Integer.toString(i))); + Arrays.stream(banner.getFallbackItems4Pool2()).forEach(i -> fourStarItems.add(Integer.toString(i))); + + template = template.replace("{{FOUR_STARS}}", "[" + String.join(",", fourStarItems) + "]"); + + // Add 3-star items. + Set threeStarItems = new LinkedHashSet<>(); + Arrays.stream(banner.getFallbackItems3()).forEach(i -> threeStarItems.add(Integer.toString(i))); + template = template.replace("{{THREE_STARS}}", "[" + String.join(",", threeStarItems) + "]"); + + // Done. + response.send(template); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java new file mode 100644 index 000000000..5b3be8d8b --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java @@ -0,0 +1,59 @@ +package emu.grasscutter.server.http.handlers; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.server.http.objects.HttpJsonResponse; +import emu.grasscutter.server.http.Router; +import emu.grasscutter.server.http.objects.WebStaticVersionResponse; +import express.Express; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; + +import static emu.grasscutter.Configuration.ACCOUNT; + +/** + * Handles all generic, hard-coded responses. + */ +public final class GenericHandler implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + // hk4e-sdk-os.hoyoverse.com + express.get("/hk4e_global/mdk/agreement/api/getAgreementInfos", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}")); + // hk4e-sdk-os.hoyoverse.com + // this could be either GET or POST based on the observation of different clients + express.all("/hk4e_global/combo/granter/api/compareProtocolVersion", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}")); + + // api-account-os.hoyoverse.com + express.post("/account/risky/api/check", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"none\",\"action\":\"ACTION_NONE\",\"geetest\":null}}")); + + // sdk-os-static.hoyoverse.com + express.get("/combo/box/api/config/sdk/combo", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}")); + // hk4e-sdk-os-static.hoyoverse.com + express.get("/hk4e_global/combo/granter/api/getConfig", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")); + // hk4e-sdk-os-static.hoyoverse.com + express.get("/hk4e_global/mdk/shield/api/loadConfig", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")); + // Test api? + // abtest-api-data-sg.hoyoverse.com + express.post("/data_abtest_api/config/experiment/list", new HttpJsonResponse("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")); + + // log-upload-os.mihoyo.com + express.all("/log/sdk/upload", new HttpJsonResponse("{\"code\":0}")); + express.all("/sdk/upload", new HttpJsonResponse("{\"code\":0}")); + express.post("/sdk/dataUpload", new HttpJsonResponse("{\"code\":0}")); + // /perf/config/verify?device_id=xxx&platform=x&name=xxx + express.all("/perf/config/verify", new HttpJsonResponse("{\"code\":0}")); + + // webstatic-sea.hoyoverse.com + express.get("/admin/mi18n/plat_oversea/*", new WebStaticVersionResponse()); + + express.get("/status/server", GenericHandler::serverStatus); + } + + private static void serverStatus(Request request, Response response) { + int playerCount = Grasscutter.getGameServer().getPlayers().size(); + int maxPlayer = ACCOUNT.maxPlayer; + String version = GameConstants.VERSION; + + response.send("{\"retcode\":0,\"status\":{\"playerCount\":" + playerCount + ",\"maxPlayer\":" + maxPlayer + ",\"version\":\"" + version + "\"}}"); + } +} diff --git a/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java new file mode 100644 index 000000000..08025d365 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/handlers/LogHandler.java @@ -0,0 +1,24 @@ +package emu.grasscutter.server.http.handlers; + +import emu.grasscutter.server.http.Router; +import express.Express; +import express.http.Request; +import express.http.Response; +import io.javalin.Javalin; + +/** + * Handles logging requests made to the server. + */ +public final class LogHandler implements Router { + @Override public void applyRoutes(Express express, Javalin handle) { + // overseauspider.yuanshen.com + express.post("/log", LogHandler::log); + // log-upload-os.mihoyo.com + express.post("/crash/dataUpload", LogHandler::log); + } + + private static void log(Request request, Response response) { + // TODO: Figure out how to dump request body and log to file. + response.send("{\"code\":0}"); + } +} diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java similarity index 84% rename from src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java rename to src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java index b3497f8d4..5642f159a 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenReqJson.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch.json; +package emu.grasscutter.server.http.objects; public class ComboTokenReqJson { public int app_id; diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java similarity index 89% rename from src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java rename to src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java index 7c49d1278..b592fa163 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/ComboTokenResJson.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch.json; +package emu.grasscutter.server.http.objects; public class ComboTokenResJson { public String message; diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchHttpJsonHandler.java b/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java similarity index 73% rename from src/main/java/emu/grasscutter/server/dispatch/DispatchHttpJsonHandler.java rename to src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java index 54ee38988..35ca9b006 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/DispatchHttpJsonHandler.java +++ b/src/main/java/emu/grasscutter/server/http/objects/HttpJsonResponse.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch; +package emu.grasscutter.server.http.objects; import java.io.IOException; import java.util.Arrays; @@ -11,8 +11,9 @@ import express.http.Request; import express.http.Response; import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; -public final class DispatchHttpJsonHandler implements HttpContextHandler { +public final class HttpJsonResponse implements HttpContextHandler { private final String response; private final String[] missingRoutes = { // TODO: When http requests for theses routes are found please remove it from this list and update the route request type in the DispatchServer "/common/hk4e_global/announcement/api/getAlertPic", @@ -27,15 +28,15 @@ public final class DispatchHttpJsonHandler implements HttpContextHandler { "/crash/dataUpload" }; - public DispatchHttpJsonHandler(String response) { + public HttpJsonResponse(String response) { this.response = response; } @Override public void handle(Request req, Response res) throws IOException { // Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled - if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> Objects.equals(x, req.baseUrl()))) { - Grasscutter.getLogger().info(translate("messages.dispatch.request", req.ip(), req.method(), req.baseUrl()) + (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING ? "(MISSING)" : "")); + if(SERVER.debugLevel == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> Objects.equals(x, req.baseUrl()))) { + Grasscutter.getLogger().info(translate("messages.dispatch.request", req.ip(), req.method(), req.baseUrl()) + (SERVER.debugLevel == ServerDebugMode.MISSING ? "(MISSING)" : "")); } res.send(response); } diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/LoginAccountRequestJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java similarity index 71% rename from src/main/java/emu/grasscutter/server/dispatch/json/LoginAccountRequestJson.java rename to src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java index cb3aff349..3a8193a97 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/json/LoginAccountRequestJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginAccountRequestJson.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch.json; +package emu.grasscutter.server.http.objects; public class LoginAccountRequestJson { public String account; diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java similarity index 96% rename from src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java rename to src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java index 1f4dcd4b4..5601c1c29 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginResultJson.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch.json; +package emu.grasscutter.server.http.objects; public class LoginResultJson { public String message; diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/LoginTokenRequestJson.java b/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java similarity index 64% rename from src/main/java/emu/grasscutter/server/dispatch/json/LoginTokenRequestJson.java rename to src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java index 12fed8f09..d01c60401 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/json/LoginTokenRequestJson.java +++ b/src/main/java/emu/grasscutter/server/http/objects/LoginTokenRequestJson.java @@ -1,4 +1,4 @@ -package emu.grasscutter.server.dispatch.json; +package emu.grasscutter.server.http.objects; public class LoginTokenRequestJson { public String uid; diff --git a/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java b/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java new file mode 100644 index 000000000..40a08ebd8 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/http/objects/WebStaticVersionResponse.java @@ -0,0 +1,41 @@ +package emu.grasscutter.server.http.objects; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.Utils; +import express.http.HttpContextHandler; +import express.http.MediaType; +import express.http.Request; +import express.http.Response; +import io.javalin.core.util.FileUtil; + +import java.io.IOException; +import java.io.InputStream; + +import static emu.grasscutter.Configuration.DATA; + +public class WebStaticVersionResponse implements HttpContextHandler { + + @Override + public void handle(Request request, Response response) throws IOException { + String requestFor = request.path().substring(request.path().lastIndexOf("-") + 1); + + getPageResources("/webstatic/" + requestFor, response); + return; + } + + private static void getPageResources(String path, Response response) { + try(InputStream filestream = FileUtils.readResourceAsStream(path)) { + + MediaType fromExtension = MediaType.getByExtension(path.substring(path.lastIndexOf(".") + 1)); + response.type((fromExtension != null) ? fromExtension.getMIME() : "application/octet-stream"); + response.send(filestream.readAllBytes()); + } catch (Exception e) { + if(Grasscutter.getConfig().server.debugLevel.equals(Grasscutter.ServerDebugMode.MISSING)) { + Grasscutter.getLogger().warn("Webstatic File Missing: " + path); + } + response.status(404); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java index 710ea0fea..a5d4c7f36 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java @@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvoc import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Utils; @Opcodes(PacketOpcodes.AbilityInvocationsNotify) public class HandlerAbilityInvocationsNotify extends PacketHandler { @@ -15,13 +16,9 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler { AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload); for (AbilityInvokeEntry entry : notif.getInvokesList()) { - //System.out.println(entry.getArgumentType() + ": " + Utils.bytesToHex(entry.getAbilityData().toByteArray())); + session.getPlayer().getAbilityManager().onAbilityInvoke(entry); session.getPlayer().getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry); } - - if (notif.getInvokesList().size() > 0) { - session.getPlayer().getAbilityInvokeHandler().update(session.getPlayer()); - } } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java index fa760a7a8..5ce8d74cf 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java @@ -1,7 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.RewardData; +import emu.grasscutter.data.excels.RewardData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.props.ActionReason; diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java index 0a2c30802..7e8a9d8a0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java @@ -18,9 +18,10 @@ import emu.grasscutter.server.packet.send.PacketBuyGoodsRsp; import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify; import emu.grasscutter.utils.Utils; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; @Opcodes(PacketOpcodes.BuyGoodsReq) public class HandlerBuyGoodsReq extends PacketHandler { @@ -33,7 +34,7 @@ public class HandlerBuyGoodsReq extends PacketHandler { return; // Don't trust your users' input - List targetShopGoodsId = buyGoodsReq.getGoodsListList().stream().map(ShopGoodsOuterClass.ShopGoods::getGoodsId).toList(); + List targetShopGoodsId = List.of(buyGoodsReq.getGoods().getGoodsId()); for (int goodsId : targetShopGoodsId) { Optional sg2 = configShop.stream().filter(x -> x.getGoodsId() == goodsId).findFirst(); if (sg2.isEmpty()) @@ -52,46 +53,23 @@ public class HandlerBuyGoodsReq extends PacketHandler { session.getPlayer().save(); } - if ((bought + buyGoodsReq.getBoughtNum() > sg.getBuyLimit()) && sg.getBuyLimit() != 0) { + if ((bought + buyGoodsReq.getBuyCount() > sg.getBuyLimit()) && sg.getBuyLimit() != 0) { return; } - if (sg.getScoin() > 0 && session.getPlayer().getMora() < buyGoodsReq.getBoughtNum() * sg.getScoin()) { - return; - } - if (sg.getHcoin() > 0 && session.getPlayer().getPrimogems() < buyGoodsReq.getBoughtNum() * sg.getHcoin()) { - return; - } - if (sg.getMcoin() > 0 && session.getPlayer().getCrystals() < buyGoodsReq.getBoughtNum() * sg.getMcoin()) { + List costs = new ArrayList(sg.getCostItemList()); // Can this even be null? + costs.add(new ItemParamData(202, sg.getScoin())); + costs.add(new ItemParamData(201, sg.getHcoin())); + costs.add(new ItemParamData(203, sg.getMcoin())); + if (!session.getPlayer().getInventory().payItems(costs.toArray(new ItemParamData[0]), buyGoodsReq.getBuyCount())) { return; } - HashMap itemsCache = new HashMap<>(); - if (sg.getCostItemList() != null) { - for (ItemParamData p : sg.getCostItemList()) { - Optional invItem = session.getPlayer().getInventory().getItems().values().stream().filter(x -> x.getItemId() == p.getId()).findFirst(); - if (invItem.isEmpty() || invItem.get().getCount() < p.getCount()) - return; - itemsCache.put(invItem.get(), p.getCount() * buyGoodsReq.getBoughtNum()); - } - } - - session.getPlayer().setMora(session.getPlayer().getMora() - buyGoodsReq.getBoughtNum() * sg.getScoin()); - session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() - buyGoodsReq.getBoughtNum() * sg.getHcoin()); - session.getPlayer().setCrystals(session.getPlayer().getCrystals() - buyGoodsReq.getBoughtNum() * sg.getMcoin()); - - if (!itemsCache.isEmpty()) { - for (GameItem gi : itemsCache.keySet()) { - session.getPlayer().getInventory().removeItem(gi, itemsCache.get(gi)); - } - itemsCache.clear(); - } - - session.getPlayer().addShopLimit(sg.getGoodsId(), buyGoodsReq.getBoughtNum(), ShopManager.getShopNextRefreshTime(sg)); + session.getPlayer().addShopLimit(sg.getGoodsId(), buyGoodsReq.getBuyCount(), ShopManager.getShopNextRefreshTime(sg)); GameItem item = new GameItem(GameData.getItemDataMap().get(sg.getGoodsItem().getId())); - item.setCount(buyGoodsReq.getBoughtNum() * sg.getGoodsItem().getCount()); + item.setCount(buyGoodsReq.getBuyCount() * sg.getGoodsItem().getCount()); session.getPlayer().getInventory().addItem(item, ActionReason.Shop, true); // fix: not notify when got virtual item from shop - session.send(new PacketBuyGoodsRsp(buyGoodsReq.getShopType(), session.getPlayer().getGoodsLimit(sg.getGoodsId()).getHasBoughtInPeriod(), buyGoodsReq.getGoodsListList().stream().filter(x -> x.getGoodsId() == goodsId).findFirst().get())); + session.send(new PacketBuyGoodsRsp(buyGoodsReq.getShopType(), session.getPlayer().getGoodsLimit(sg.getGoodsId()).getHasBoughtInPeriod(), Stream.of(buyGoodsReq.getGoods()).filter(x -> x.getGoodsId() == goodsId).findFirst().get())); } session.getPlayer().save(); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java index cfe697b91..a1035af85 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java @@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Utils; @Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify) public class HandlerClientAbilityInitFinishNotify extends PacketHandler { @@ -15,6 +16,7 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler { ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload); for (AbilityInvokeEntry entry : notif.getInvokesList()) { + session.getPlayer().getAbilityManager().onAbilityInvoke(entry); session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java index 27e4ca6ff..54bdad3b6 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java @@ -1,6 +1,8 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; @@ -8,27 +10,63 @@ import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; @Opcodes(PacketOpcodes.CombatInvocationsNotify) public class HandlerCombatInvocationsNotify extends PacketHandler { + private float cachedLandingSpeed = 0; + private long cachedLandingTimeMillisecond = 0; + private boolean monitorLandingEvent = false; + @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); for (CombatInvokeEntry entry : notif.getInvokeListList()) { switch (entry.getArgumentType()) { - case COMBAT_EVT_BEING_HIT: + case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: // Handle damage EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); session.getPlayer().getAttackResults().add(hitInfo.getAttackResult()); + session.getPlayer().getEnergyManager().handleAttackHit(hitInfo); break; - case ENTITY_MOVE: + case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE: // Handle movement EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); if (entity != null) { - session.getPlayer().getMovementManager().handle(session, moveInfo, entity); + // Move player + MotionInfo motionInfo = moveInfo.getMotionInfo(); + entity.getPosition().set(motionInfo.getPos()); + entity.getRotation().set(motionInfo.getRot()); + entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); + entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); + MotionState motionState = motionInfo.getState(); + entity.setMotionState(motionState); + + session.getPlayer().getStaminaManager().handleCombatInvocationsNotify(session, moveInfo, entity); + + // TODO: handle MOTION_FIGHT landing which has a different damage factor + // Also, for plunge attacks, LAND_SPEED is always -30 and is not useful. + // May need the height when starting plunge attack. + + // MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets. + // Cache land speed for later use. + if (motionState == MotionState.MOTION_STATE_LAND_SPEED) { + cachedLandingSpeed = motionInfo.getSpeed().getY(); + cachedLandingTimeMillisecond = System.currentTimeMillis(); + monitorLandingEvent = true; + } + if (monitorLandingEvent) { + if (motionState == MotionState.MOTION_STATE_FALL_ON_GROUND) { + monitorLandingEvent = false; + handleFallOnGround(session, entity, motionState); + } + } } break; default: @@ -37,15 +75,53 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); } - - if (notif.getInvokeListList().size() > 0) { - session.getPlayer().getCombatInvokeHandler().update(session.getPlayer()); - } - // Handle attack results last - while (!session.getPlayer().getAttackResults().isEmpty()) { - session.getPlayer().getScene().handleAttack(session.getPlayer().getAttackResults().poll()); - } } - + private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) { + if (session.getPlayer().inGodmode()) { + return; + } + // People have reported that after plunge attack (client sends a FIGHT instead of FALL_ON_GROUND) they will die + // if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping again. + // A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet. + // 200ms seems to be a reasonable delay. + int maxDelay = 200; + long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond; + Grasscutter.getLogger().trace("MOTION_FALL_ON_GROUND received after " + actualDelay + "/" + maxDelay + "ms." + (actualDelay > maxDelay ? " Discard" : "")); + if (actualDelay > maxDelay) { + return; + } + float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + float damageFactor = 0; + if (cachedLandingSpeed < -23.5) { + damageFactor = 0.33f; + } + if (cachedLandingSpeed < -25) { + damageFactor = 0.5f; + } + if (cachedLandingSpeed < -26.5) { + damageFactor = 0.66f; + } + if (cachedLandingSpeed < -28) { + damageFactor = 1f; + } + float damage = maxHP * damageFactor; + float newHP = currentHP - damage; + if (newHP < 0) { + newHP = 0; + } + if (damageFactor > 0) { + Grasscutter.getLogger().debug(currentHP + "/" + maxHP + "\tLandingSpeed: " + cachedLandingSpeed + + "\tDamageFactor: " + damageFactor + "\tDamage: " + damage + "\tNewHP: " + newHP); + } else { + Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage"); + } + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); + entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + if (newHP == 0) { + session.getPlayer().getStaminaManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_TYPE_FALL); + } + cachedLandingSpeed = 0; + } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java index 23a522b25..c5b52fab0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.data.def.CombineData; +import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CombineData; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; @@ -35,7 +36,7 @@ public class HandlerCombineReq extends PacketHandler { toItemParamList(result.getBack()))); } - private List toItemParamList(List list){ + private List toItemParamList(List list){ return list.stream() .map(item -> ItemParamOuterClass.ItemParam.newBuilder() .setItemId(item.getId()) diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java new file mode 100644 index 000000000..367d46677 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java @@ -0,0 +1,21 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CreateVehicleReqOuterClass; + +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCreateVehicleRsp; + +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.CreateVehicleReq) +public class HandlerCreateVehicleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CreateVehicleReqOuterClass.CreateVehicleReq req = CreateVehicleReqOuterClass.CreateVehicleReq.parseFrom(payload); + session.send(new PacketCreateVehicleRsp(session.getPlayer(), req.getVehicleId(), req.getScenePointId(), new Position(req.getPos()), new Position(req.getRot()))); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java index 0aa680a18..1c06dbbfa 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDoGachaReq.java @@ -12,6 +12,6 @@ public class HandlerDoGachaReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { DoGachaReq req = DoGachaReq.parseFrom(payload); - session.getServer().getGachaManager().doPulls(session.getPlayer(), req.getGachaType(), req.getGachaTimes()); + session.getServer().getGachaManager().doPulls(session.getPlayer(), req.getGachaScheduleId(), req.getGachaTimes()); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java index 5591607fe..9a5872033 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java @@ -1,31 +1,16 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; - -import java.util.List; @Opcodes(PacketOpcodes.EnterTransPointRegionNotify) public class HandlerEnterTransPointRegionNotify extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{ - Player player = session.getPlayer(); - SotSManager sotsManager = player.getSotSManager(); - - sotsManager.refillSpringVolume(); - sotsManager.autoRevive(session); - sotsManager.scheduleAutoRecover(session); - // TODO: allow interaction with the SotS? + session.getPlayer().getSotSManager().handleEnterTransPointRegionNotify(); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java index 9b1cdb0fb..92229d400 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java @@ -14,11 +14,6 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { EvtCreateGadgetNotify notify = EvtCreateGadgetNotify.parseFrom(payload); - // Dont handle in singleplayer - if (!session.getPlayer().getWorld().isMultiplayer()) { - return; - } - // Sanity check - dont add duplicate entities if (session.getPlayer().getScene().getEntityById(notify.getEntityId()) != null) { return; diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java index 608215d0a..7d1abe8ea 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java @@ -12,11 +12,6 @@ public class HandlerEvtDestroyGadgetNotify extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { EvtDestroyGadgetNotify notify = EvtDestroyGadgetNotify.parseFrom(payload); - - // Dont handle in singleplayer - if (!session.getPlayer().getWorld().isMultiplayer()) { - return; - } session.getPlayer().getScene().onPlayerDestroyGadget(notify.getEntityId()); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java index a57ae9665..a714d936b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java @@ -1,6 +1,5 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.Grasscutter; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; @@ -13,12 +12,10 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload); - // TODO: Will be used for deducting stamina for charged skills. - - int caster = notify.getCasterId(); int skillId = notify.getSkillId(); + int casterId = notify.getCasterId(); - session.getPlayer().getMovementManager().notifySkill(caster, skillId); + session.getPlayer().getStaminaManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); + session.getPlayer().getEnergyManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); } - } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java index 35ec957cb..03fcd4e3c 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; @@ -11,8 +12,6 @@ import emu.grasscutter.server.game.GameSession; public class HandlerExitTransPointRegionNotify extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{ - Player player = session.getPlayer(); - SotSManager sotsManager = player.getSotSManager(); - sotsManager.cancelAutoRecover(); + session.getPlayer().getSotSManager().handleExitTransPointRegionNotify(); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java index 899ba6d95..2a7fdc295 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetAllMailReq.java @@ -16,6 +16,6 @@ public class HandlerGetAllMailReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { GetAllMailReqOuterClass.GetAllMailReq req = GetAllMailReqOuterClass.GetAllMailReq.parseFrom(payload); - session.send(new PacketGetAllMailRsp(session.getPlayer(), req.getIsGiftMail())); + session.send(new PacketGetAllMailRsp(session.getPlayer(), req.getANKKGPJCINB())); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java index 5034fb01a..6546b6f1b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java @@ -1,11 +1,17 @@ package emu.grasscutter.server.packet.recv; +import static emu.grasscutter.Configuration.ACCOUNT; + +import emu.grasscutter.Grasscutter; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; +import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.GetPlayerTokenReqOuterClass.GetPlayerTokenReq; import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.server.event.game.PlayerCreationEvent; +import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession.SessionState; import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp; @@ -15,42 +21,73 @@ public class HandlerGetPlayerTokenReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + GetPlayerTokenReq req = GetPlayerTokenReq.parseFrom(payload); // Authenticate Account account = DatabaseHelper.getAccountById(req.getAccountUid()); - if (account == null) { - return; - } - - // Check token - if (!account.getToken().equals(req.getAccountToken())) { + if (account == null || !account.getToken().equals(req.getAccountToken())) { return; } // Set account session.setAccount(account); - session.setUseSecretKey(true); - session.setState(SessionState.WAITING_FOR_LOGIN); - - // Has character - boolean doesPlayerExist = false; - if (account.getPlayerUid() > 0) { - // Set flag for player existing - doesPlayerExist = DatabaseHelper.checkPlayerExists(account.getPlayerUid()); - } - - // Set reserve player id if account doesnt exist - if (!doesPlayerExist) { - int id = DatabaseHelper.getNextPlayerId(session.getAccount().getPlayerUid()); - if (id != session.getAccount().getPlayerUid()) { - session.getAccount().setPlayerId(id); - session.getAccount().save(); + + + // Check if player object exists in server + // NOTE: CHECKING MUST SITUATED HERE (BEFORE getPlayerByUid)! because to save firstly ,to load secondly !!! + // TODO - optimize + boolean kicked = false; + Player exists = Grasscutter.getGameServer().getPlayerByAccountId(account.getId()); + if (exists != null) { + GameSession existsSession = exists.getSession(); + if (existsSession != session) {// No self-kicking + exists.onLogout();//must save immediately , or the below will load old data + existsSession.close(); + Grasscutter.getLogger().warn("Player {} was kicked due to duplicated login", account.getUsername()); + kicked = true; } } + //NOTE: If there are 5 online players, max count of player is 5, + // a new client want to login by kicking one of them , + // I think it should be allowed + if(!kicked) { + // Max players limit + if (ACCOUNT.maxPlayer > -1 && Grasscutter.getGameServer().getPlayers().size() >= ACCOUNT.maxPlayer) { + session.close(); + return; + } + } + + // Get player + Player player = DatabaseHelper.getPlayerByAccount(account); + + if (player == null) { + int nextPlayerUid = DatabaseHelper.getNextPlayerId(session.getAccount().getReservedPlayerUid()); + + // Call creation event. + PlayerCreationEvent event = new PlayerCreationEvent(session, Player.class); event.call(); + + // Create player instance from event. + player = event.getPlayerClass().getDeclaredConstructor(GameSession.class).newInstance(session); + + // Save to db + DatabaseHelper.generatePlayerUid(player, nextPlayerUid); + } + + // Set player object for session + session.setPlayer(player); + + // Load player from database + player.loadFromDatabase(); + + // Set session state + session.setUseSecretKey(true); + session.setState(SessionState.WAITING_FOR_LOGIN); + // Send packet - session.send(new PacketGetPlayerTokenRsp(session, doesPlayerExist)); + session.send(new PacketGetPlayerTokenRsp(session)); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java index b41a6cc1d..e7b352122 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetWidgetSlotReq.java @@ -1,16 +1,20 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketGetShopRsp; +import emu.grasscutter.server.packet.send.PacketGetWidgetSlotRsp; @Opcodes(PacketOpcodes.GetWidgetSlotReq) public class HandlerGetWidgetSlotReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - // Unhandled + Player player = session.getPlayer(); + session.send(new PacketGetWidgetSlotRsp(player)); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java new file mode 100644 index 000000000..222116d56 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHitTreeNotify.java @@ -0,0 +1,21 @@ +package emu.grasscutter.server.packet.recv; + +import java.math.BigInteger; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HitTreeNotifyOuterClass.HitTreeNotify; +import emu.grasscutter.server.game.GameSession; + +/** + * Implement Deforestation Function + */ +@Opcodes(PacketOpcodes.HitTreeNotify) +public class HandlerHitTreeNotify extends PacketHandler { + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + HitTreeNotify hit = HitTreeNotify.parseFrom(payload); + session.getPlayer().getDeforestationManager().onDeforestationInvoke(hit); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java new file mode 100644 index 000000000..5a7c0dbe5 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerHomeChooseModuleReq.java @@ -0,0 +1,26 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChooseModuleReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketHomeChooseModuleRsp; +import emu.grasscutter.server.packet.send.PacketHomeComfortInfoNotify; +import emu.grasscutter.server.packet.send.PacketPlayerHomeCompInfoNotify; + + +@Opcodes(PacketOpcodes.HomeChooseModuleReq) +public class HandlerHomeChooseModuleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + HomeChooseModuleReqOuterClass.HomeChooseModuleReq req = + HomeChooseModuleReqOuterClass.HomeChooseModuleReq.parseFrom(payload); + session.getPlayer().addRealmList(req.getModuleId()); + session.getPlayer().setCurrentRealmId(req.getModuleId()); + session.send(new PacketHomeChooseModuleRsp(req.getModuleId())); + session.send(new PacketPlayerHomeCompInfoNotify(session.getPlayer())); + session.send(new PacketHomeComfortInfoNotify(session.getPlayer())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java index fc5d0a602..58348a2e0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMarkMapReq.java @@ -1,84 +1,17 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.game.managers.MapMarkManager.MapMark; -import emu.grasscutter.game.managers.MapMarkManager.MapMarksManager; -import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.*; import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketMarkMapRsp; -import emu.grasscutter.server.packet.send.PacketMarkNewNotify; -import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; -import emu.grasscutter.utils.Position; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; @Opcodes(PacketOpcodes.MarkMapReq) public class HandlerMarkMapReq extends PacketHandler { - private static boolean isInt(String str) { - - try { - @SuppressWarnings("unused") - int x = Integer.parseInt(str); - return true; // String is an Integer - } catch (NumberFormatException e) { - return false; // String is not an Integer - } - - } - @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { MarkMapReq req = MarkMapReq.parseFrom(payload); - MarkMapReq.Operation op = req.getOp(); - Player player = session.getPlayer(); - MapMarksManager mapMarksManager = player.getMapMarksManager(); - if (op == MarkMapReq.Operation.ADD) { - MapMark newMapMark = new MapMark(req.getMark()); - // keep teleporting functionality on fishhook mark. - if (newMapMark.getMapMarkPointType() == MapMarkPointTypeOuterClass.MapMarkPointType.MAP_MARK_POINT_TYPE_FISH_POOL) { - teleport(player, newMapMark); - return; - } - if (mapMarksManager.addMapMark(newMapMark)) { - player.save(); - } - } else if (op == MarkMapReq.Operation.MOD) { - MapMark newMapMark = new MapMark(req.getMark()); - if (mapMarksManager.removeMapMark(newMapMark.getPosition())) { - if (mapMarksManager.addMapMark(newMapMark)) { - player.save(); - } - } - } else if (op == MarkMapReq.Operation.DEL) { - MapMark newMapMark = new MapMark(req.getMark()); - if (mapMarksManager.removeMapMark(newMapMark.getPosition())) { - player.save(); - } - } else if (op == MarkMapReq.Operation.GET) { - // no-op - } - // send all marks to refresh client map view. - HashMap mapMarks = mapMarksManager.getAllMapMarks(); - session.send(new PacketMarkMapRsp(player, mapMarks)); - } - - private void teleport(Player player, MapMark mapMark) { - float y = isInt(mapMark.getName()) ? Integer.parseInt(mapMark.getName()) : 300; - float x = mapMark.getPosition().getX(); - float z = mapMark.getPosition().getZ(); - player.getPos().set(x, y, z); - if (mapMark.getSceneId() != player.getSceneId()) { - player.getWorld().transferPlayerToScene(player, mapMark.getSceneId(), - player.getPos()); - } else { - player.getScene().broadcastPacket(new PacketSceneEntityAppearNotify(player)); - } + session.getPlayer().getMapMarksManager().handleMapMarkReq(req); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java index 37dc0fcc7..21acbfe21 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerMcoinExchangeHcoinReq.java @@ -15,13 +15,13 @@ public class HandlerMcoinExchangeHcoinReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq exchangeReq = McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq.parseFrom(payload); - if (session.getPlayer().getCrystals() < exchangeReq.getMCoinNum() && exchangeReq.getMCoinNum() == exchangeReq.getHCoinNum()) { + if (session.getPlayer().getCrystals() < exchangeReq.getMcoinCost() && exchangeReq.getMcoinCost() == exchangeReq.getHcoin()) { session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_UNKNOWN_ERROR_VALUE)); return; } - session.getPlayer().setCrystals(session.getPlayer().getCrystals() - exchangeReq.getMCoinNum()); - session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() + exchangeReq.getHCoinNum()); + session.getPlayer().setCrystals(session.getPlayer().getCrystals() - exchangeReq.getMcoinCost()); + session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() + exchangeReq.getHcoin()); session.getPlayer().save(); session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java index 309d7e2e2..3dae7fe10 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerNpcTalkReq.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq; @@ -14,6 +15,10 @@ public class HandlerNpcTalkReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { NpcTalkReq req = NpcTalkReq.parseFrom(payload); + + // Why are there 2 quest triggers that do the same thing... + session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_COMPLETE_TALK, req.getTalkId()); + session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_FINISH_PLOT, req.getTalkId()); session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId())); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java index 98c6984ee..246dcbaa5 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java @@ -1,7 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.ScenePointEntry; +import emu.grasscutter.data.binout.ScenePointEntry; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java index cfdce5b59..d5aea0db1 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java @@ -1,5 +1,6 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.Grasscutter; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; @@ -12,6 +13,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp; import emu.grasscutter.server.packet.send.PacketTakeAchievementRewardReq; +import static emu.grasscutter.Configuration.ACCOUNT; + @Opcodes(PacketOpcodes.PlayerLoginReq) // Sends initial data packets public class HandlerPlayerLoginReq extends PacketHandler { @@ -19,31 +22,30 @@ public class HandlerPlayerLoginReq extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { // Check if (session.getAccount() == null) { + session.close(); return; } - + // Parse request PlayerLoginReq req = PlayerLoginReq.parseFrom(payload); // Authenticate session if (!req.getToken().equals(session.getAccount().getToken())) { + session.close(); return; } // Load character from db - Player player = DatabaseHelper.getPlayerById(session.getAccount().getPlayerUid()); + Player player = session.getPlayer(); - if (player == null) { - // Send packets + // Show opening cutscene if player has no avatars + if (player.getAvatars().getAvatarCount() == 0) { + // Pick character session.setState(SessionState.PICKING_CHARACTER); session.send(new BasePacket(PacketOpcodes.DoSetPlayerBornDataNotify)); } else { - // Set character - session.setPlayer(player); - // Login done session.getPlayer().onLogin(); - session.setState(SessionState.ACTIVE); } // Final packet to tell client logging in is done diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java new file mode 100644 index 000000000..dca38dcdb --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQueryCodexMonsterBeKilledNumReq.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumReqOuterClass; +import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumReqOuterClass.QueryCodexMonsterBeKilledNumReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketQueryCodexMonsterBeKilledNumRsp; + +@Opcodes(PacketOpcodes.QueryCodexMonsterBeKilledNumReq) +public class HandlerQueryCodexMonsterBeKilledNumReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + QueryCodexMonsterBeKilledNumReq req = QueryCodexMonsterBeKilledNumReq.parseFrom(payload); + session.send(new PacketQueryCodexMonsterBeKilledNumRsp(session.getPlayer(), req.getCodexIdListList())); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java new file mode 100644 index 000000000..6e0149649 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerQuickUseWidgetReq.java @@ -0,0 +1,54 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.Inventory; +import emu.grasscutter.game.inventory.InventoryTab; +import emu.grasscutter.game.inventory.ItemType; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuickUseWidgetRspOuterClass.QuickUseWidgetRsp; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPullRecentChatRsp; + +@Opcodes(PacketOpcodes.QuickUseWidgetReq) +public class HandlerQuickUseWidgetReq extends PacketHandler { + /* + * WARNING: with the consuming of material widget ( Example: bomb ), + * this is just a implement designed to the decreasing of count + * + * ### Known Bug: No effects after using item but decrease. ### + * + * If you know which Packet could make the effects, feel free to contribute! + * */ + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + QuickUseWidgetRsp.Builder proto = QuickUseWidgetRsp.newBuilder(); + Player pl = session.getPlayer(); + synchronized (pl) { + int materialId = pl.getWidgetId(); + Inventory inventory = session.getPlayer().getInventory(); + InventoryTab inventoryTab = inventory.getInventoryTab(ItemType.ITEM_MATERIAL); + GameItem item = inventoryTab.getItemById(materialId); + int remain = item.getCount(); + if (remain > 0) { + remain--; + if (remain <= 0) { + proto.setRetcode(1); + } else { + proto.setRetcode(0); + } + proto.setMaterialId(materialId); + inventory.removeItem(item,1);// decrease count + BasePacket rsp = new BasePacket(PacketOpcodes.QuickUseWidgetRsp); + rsp.setData(proto); + session.send(rsp); + Grasscutter.getLogger().warn("class has no effects in the game, feel free to implement it"); + // but no effects in the game, feel free to implement it! + } + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java index 587cf7ce1..9d7dc8443 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java @@ -9,12 +9,12 @@ import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketHostPlayerNotify; import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneInfoNotify; import emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify; +import emu.grasscutter.server.packet.send.PacketPlayerWorldSceneInfoListNotify; import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify; import emu.grasscutter.server.packet.send.PacketSceneInitFinishRsp; import emu.grasscutter.server.packet.send.PacketScenePlayerInfoNotify; import emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify; import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; -import emu.grasscutter.server.packet.send.PacketSceneUnlockInfoNotify; import emu.grasscutter.server.packet.send.PacketServerTimeNotify; import emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify; import emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify; @@ -30,7 +30,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler { session.send(new PacketServerTimeNotify()); session.send(new PacketWorldPlayerInfoNotify(session.getPlayer().getWorld())); session.send(new PacketWorldDataNotify(session.getPlayer().getWorld())); - session.send(new PacketSceneUnlockInfoNotify()); + session.send(new PacketPlayerWorldSceneInfoListNotify()); session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); session.send(new PacketHostPlayerNotify(session.getPlayer().getWorld())); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java index 65783d01b..209dacdbb 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java @@ -1,7 +1,7 @@ package emu.grasscutter.server.packet.recv; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.ScenePointEntry; +import emu.grasscutter.data.binout.ScenePointEntry; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq; diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java index 5151034f2..6c4d86f7e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java @@ -23,7 +23,7 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler { BasePacket packet = new BasePacket(PacketOpcodes.SetEntityClientDataNotify, true); packet.setData(notif); - session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), packet); + session.getPlayer().getScene().broadcastPacket(packet); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java index 2487df063..ddb2e8948 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java @@ -19,6 +19,8 @@ import emu.grasscutter.server.game.GameSession.SessionState; import java.util.Arrays; +import static emu.grasscutter.Configuration.*; + @Opcodes(PacketOpcodes.SetPlayerBornDataReq) public class HandlerSetPlayerBornDataReq extends PacketHandler { @@ -44,58 +46,39 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler { return; } - String nickname = req.getNickName(); - if (nickname == null) { - nickname = "Traveler"; - } - - // Call creation event. - PlayerCreationEvent event = new PlayerCreationEvent(session, Player.class); event.call(); - // Create player instance from event. - Player player = event.getPlayerClass().getDeclaredConstructor(GameSession.class).newInstance(session); - player.setNickname(nickname); - - try { - // Save to db - DatabaseHelper.createPlayer(player, session.getAccount().getPlayerUid()); - - // Create avatar - if (player.getAvatars().getAvatarCount() == 0) { - Avatar mainCharacter = new Avatar(avatarId); - mainCharacter.setSkillDepot(GameData.getAvatarSkillDepotDataMap().get(startingSkillDepot)); - player.addAvatar(mainCharacter); - player.setMainCharacterId(avatarId); - player.setHeadImage(avatarId); - player.getTeamManager().getCurrentSinglePlayerTeamInfo().getAvatars().add(mainCharacter.getAvatarId()); - player.save(); // TODO save player team in different object - } - - // Save account - session.getAccount().setPlayerId(player.getUid()); - session.getAccount().save(); - - // Set character - session.setPlayer(player); - - // Login done - session.getPlayer().onLogin(); - session.setState(SessionState.ACTIVE); - - // Born resp packet - session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp)); + // Get player object + Player player = session.getPlayer(); + player.setNickname(req.getNickName()); - // Default mail - MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail()); - mailBuilder.mail.mailContent.title = Grasscutter.getConfig().GameServer.WelcomeMailTitle; - mailBuilder.mail.mailContent.sender = Grasscutter.getConfig().GameServer.WelcomeMailSender; - // Please credit Grasscutter if changing something here. We don't condone commercial use of the project. - mailBuilder.mail.mailContent.content = Grasscutter.getConfig().GameServer.WelcomeMailContent + "\n"; - mailBuilder.mail.itemList.addAll(Arrays.asList(Grasscutter.getConfig().GameServer.WelcomeMailItems)); - mailBuilder.mail.importance = 1; - player.sendMail(mailBuilder.mail); - } catch (Exception e) { - Grasscutter.getLogger().error("Error creating player object: ", e); - session.close(); + // Create avatar + if (player.getAvatars().getAvatarCount() == 0) { + Avatar mainCharacter = new Avatar(avatarId); + mainCharacter.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(startingSkillDepot)); + // Manually handle adding to team + player.addAvatar(mainCharacter, false); + player.setMainCharacterId(avatarId); + player.setHeadImage(avatarId); + player.getTeamManager().getCurrentSinglePlayerTeamInfo().getAvatars().add(mainCharacter.getAvatarId()); + player.save(); // TODO save player team in different object + } else { + return; } + + // Login done + session.getPlayer().onLogin(); + + // Born resp packet + session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp)); + + // Default mail + var welcomeMail = GAME_INFO.joinOptions.welcomeMail; + MailBuilder mailBuilder = new MailBuilder(player.getUid(), new Mail()); + mailBuilder.mail.mailContent.title = welcomeMail.title; + mailBuilder.mail.mailContent.sender = welcomeMail.sender; + // Please credit Grasscutter if changing something here. We don't condone commercial use of the project. + mailBuilder.mail.mailContent.content = welcomeMail.content + "\n"; + mailBuilder.mail.itemList.addAll(Arrays.asList(welcomeMail.items)); + mailBuilder.mail.importance = 1; + player.sendMail(mailBuilder.mail); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java new file mode 100644 index 000000000..9b478ff23 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetWidgetSlotReq.java @@ -0,0 +1,37 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetWidgetSlotReqOuterClass; +import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSetWidgetSlotRsp; +import emu.grasscutter.server.packet.send.PacketWidgetSlotChangeNotify; + +@Opcodes(PacketOpcodes.SetWidgetSlotReq) +public class HandlerSetWidgetSlotReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + SetWidgetSlotReqOuterClass.SetWidgetSlotReq req = SetWidgetSlotReqOuterClass.SetWidgetSlotReq.parseFrom(payload); + + Player player = session.getPlayer(); + player.setWidgetId(req.getMaterialId()); + + // WidgetSlotChangeNotify op & slot key + session.send(new PacketWidgetSlotChangeNotify(WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_DETACH)); + + //only attaching the widget can set it + if(req.getOp() == WidgetSlotOpOuterClass.WidgetSlotOp.WIDGET_SLOT_OP_ATTACH){ + // WidgetSlotChangeNotify slot + session.send(new PacketWidgetSlotChangeNotify(req.getMaterialId())); + } + + // SetWidgetSlotRsp + session.send(new PacketSetWidgetSlotRsp(req.getMaterialId())); + } + +} + diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java index 8ee2d934b..8701a7479 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTakePlayerLevelRewardReq.java @@ -1,48 +1,40 @@ package emu.grasscutter.server.packet.recv; -import java.util.LinkedList; import java.util.List; import java.util.Set; -import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.common.RewardItemData; -import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.data.common.ItemParamData; + +import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.TakePlayerLevelRewardReqOuterClass.TakePlayerLevelRewardReq; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; import emu.grasscutter.server.packet.send.PacketTakePlayerLevelRewardRsp; @Opcodes(PacketOpcodes.TakePlayerLevelRewardReq) public class HandlerTakePlayerLevelRewardReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - TakePlayerLevelRewardReq req = TakePlayerLevelRewardReq.parseFrom(payload); - - int level = req.getLevel(); - int rewardId = GameData.getPlayerLevelDataMap().get(level).getRewardId(); - - if (rewardId != 0) { - List rewardItems = GameData.getRewardDataMap().get(rewardId).getRewardItemList(); - List items = new LinkedList<>(); - for (RewardItemData rewardItem : rewardItems) { - if (rewardItem != null) { - if (rewardItem.getItemId() != 0) { - items.add(new GameItem(rewardItem.getItemId(), rewardItem.getItemCount())); - } + Player pl = session.getPlayer(); + synchronized (pl) { + TakePlayerLevelRewardReq req = TakePlayerLevelRewardReq.parseFrom(payload); + int level = req.getLevel(); + Set rewardedLevels = session.getPlayer().getRewardedLevels(); + if (!rewardedLevels.contains(level)) {// No duplicated reward + int rewardId = GameData.getPlayerLevelDataMap().get(level).getRewardId(); + if (rewardId != 0) { + List rewardItems = GameData.getRewardDataMap().get(rewardId).getRewardItemList(); + pl.getInventory().addItemParamDatas(rewardItems, ActionReason.PlayerUpgradeReward); + rewardedLevels.add(level); + pl.setRewardedLevels(rewardedLevels); + pl.save(); + session.send(new PacketTakePlayerLevelRewardRsp(level, rewardId)); } } - session.getPlayer().getInventory().addItems(items); - session.getPlayer().sendPacket(new PacketItemAddHintNotify(items, ActionReason.PlayerUpgradeReward)); - Set rewardedLevels = session.getPlayer().getRewardedLevels(); - rewardedLevels.add(level); - session.getPlayer().setRewardedLevels(rewardedLevels); } - - session.send(new PacketTakePlayerLevelRewardRsp(level, rewardId)); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java index 2a9ef2004..38462882f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java @@ -11,7 +11,10 @@ public class HandlerTowerAllDataReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketTowerAllDataRsp()); + session.send(new PacketTowerAllDataRsp( + session.getServer().getTowerScheduleManager(), + session.getPlayer().getTowerManager() + )); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java new file mode 100644 index 000000000..5df106df2 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTryEnterHomeReq.java @@ -0,0 +1,42 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TryEnterHomeReqOuterClass; +import emu.grasscutter.scripts.data.SceneConfig; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTryEnterHomeRsp; +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.TryEnterHomeReq) +public class HandlerTryEnterHomeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TryEnterHomeReqOuterClass.TryEnterHomeReq req = + TryEnterHomeReqOuterClass.TryEnterHomeReq.parseFrom(payload); + + if (req.getTargetUid() != session.getPlayer().getUid()) { + // I hope that tomorrow there will be a hero who can support multiplayer mode and write code like a poem + session.send(new PacketTryEnterHomeRsp()); + return; + } + + int realmId = 2000 + session.getPlayer().getCurrentRealmId(); + + Scene scene = session.getPlayer().getWorld().getSceneById(realmId); + Position pos = scene.getScriptManager().getConfig().born_pos; + + session.getPlayer().getWorld().transferPlayerToScene( + session.getPlayer(), + realmId, + pos + ); + + + session.send(new PacketTryEnterHomeRsp(req.getTargetUid())); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java index 1f4a9e7f3..2468f675f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerUnionCmdNotify.java @@ -15,5 +15,14 @@ public class HandlerUnionCmdNotify extends PacketHandler { for (UnionCmd cmd : req.getCmdListList()) { session.getServer().getPacketHandler().handle(session, cmd.getMessageId(), EMPTY_BYTE_ARRAY, cmd.getBody().toByteArray()); } + + // Update + session.getPlayer().getCombatInvokeHandler().update(session.getPlayer()); + session.getPlayer().getAbilityInvokeHandler().update(session.getPlayer()); + + // Handle attack results last + while (!session.getPlayer().getAttackResults().isEmpty()) { + session.getPlayer().getScene().handleAttack(session.getPlayer().getAttackResults().poll()); + } } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java index 3baba9c5b..d45befa89 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleInteractReq.java @@ -14,6 +14,7 @@ public class HandlerVehicleInteractReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { VehicleInteractReqOuterClass.VehicleInteractReq req = VehicleInteractReqOuterClass.VehicleInteractReq.parseFrom(payload); + session.getPlayer().getStaminaManager().handleVehicleInteractReq(session, req.getEntityId(), req.getInteractType()); session.send(new PacketVehicleInteractRsp(session.getPlayer(), req.getEntityId(), req.getInteractType())); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java deleted file mode 100644 index 2d259f738..000000000 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java +++ /dev/null @@ -1,21 +0,0 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.VehicleSpawnReqOuterClass; - -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketVehicleSpawnRsp; - -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.VehicleSpawnReq) -public class HandlerVehicleSpawnReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - VehicleSpawnReqOuterClass.VehicleSpawnReq req = VehicleSpawnReqOuterClass.VehicleSpawnReq.parseFrom(payload); - session.send(new PacketVehicleSpawnRsp(session.getPlayer(), req.getVehicleId(), req.getPointId(), new Position(req.getPos()), new Position(req.getRot()))); - } -} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java new file mode 100644 index 000000000..c73f98fbd --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerWidgetDoBagReq.java @@ -0,0 +1,57 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.GadgetData; +import emu.grasscutter.game.entity.EntityVehicle; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.LifeState; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.*; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; +import emu.grasscutter.server.packet.send.PacketWidgetCoolDownNotify; +import emu.grasscutter.server.packet.send.PacketWidgetDoBagRsp; +import emu.grasscutter.server.packet.send.PacketWidgetGadgetDataNotify; +import emu.grasscutter.utils.Position; + +import java.util.List; + +@Opcodes(PacketOpcodes.WidgetDoBagReq) +public class HandlerWidgetDoBagReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + WidgetDoBagReqOuterClass.WidgetDoBagReq req = WidgetDoBagReqOuterClass.WidgetDoBagReq.parseFrom(payload); + switch (req.getMaterialId()) { + case 220026 -> { + GadgetData gadgetData = GameData.getGadgetDataMap().get(70500025); + Position pos = new Position(req.getWidgetCreatorInfo().getLocationInfo().getPos()); + Position rot = new Position(req.getWidgetCreatorInfo().getLocationInfo().getRot()); + GameEntity entity = new EntityVehicle( + session.getPlayer().getScene(), + session.getPlayer(), + gadgetData.getId(), + 0, + pos, + rot + ); + + session.getPlayer().getScene().addEntity(entity); + + session.send(new PacketWidgetGadgetDataNotify(70500025, List.of(entity.getId()))); // ??? + session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); + session.send(new PacketWidgetCoolDownNotify(15, System.currentTimeMillis() + 5000L, true)); + // Send twice, and I don't know why, Ask mhy + session.send(new PacketWidgetDoBagRsp()); + } + default -> { + session.send(new PacketWidgetDoBagRsp()); + } + + } + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java new file mode 100644 index 000000000..8d3d42261 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAllWidgetDataNotify.java @@ -0,0 +1,59 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AllWidgetDataNotifyOuterClass.AllWidgetDataNotify; +import emu.grasscutter.net.proto.LunchBoxDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; + +import java.util.List; +import java.util.Map; + +public class PacketAllWidgetDataNotify extends BasePacket { + + public PacketAllWidgetDataNotify(Player player) { + super(PacketOpcodes.AllWidgetDataNotify); + + // TODO: Implement this + + AllWidgetDataNotify.Builder proto = AllWidgetDataNotify.newBuilder() + // If you want to implement this, feel free to do so. :) + .setLunchBoxData( + LunchBoxDataOuterClass.LunchBoxData.newBuilder().build() + ) + // Maybe it's a little difficult, or it makes you upset :( + .addAllOneoffGatherPointDetectorDataList(List.of()) + // So, goodbye, and hopefully sometime in the future o(* ̄▽ ̄*)ブ + .addAllCoolDownGroupDataList(List.of()) + // I'll see your PR with a title that says (・∀・(・∀・(・∀・*) + .addAllAnchorPointList(List.of()) + // "Complete implementation of widget functionality" b( ̄▽ ̄)d  + .addAllClientCollectorDataList(List.of()) + // Good luck, my boy. + .addAllNormalCoolDownDataList(List.of()); + + if (player.getWidgetId() == null) { + proto.addAllSlotList(List.of()); + } else { + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(player.getWidgetId()) + .build() + ); + + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) + .build() + ); + } + + AllWidgetDataNotify protoData = proto.build(); + + this.setData(protoData); + } +} + diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java index 07371440d..2d9a5f597 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketBuyGoodsRsp.java @@ -11,7 +11,7 @@ public class PacketBuyGoodsRsp extends BasePacket { BuyGoodsRspOuterClass.BuyGoodsRsp buyGoodsRsp = BuyGoodsRspOuterClass.BuyGoodsRsp.newBuilder() .setShopType(shopType) - .setBoughtNum(boughtNum) + .setBuyCount(boughtNum) .addGoodsList(ShopGoodsOuterClass.ShopGoods.newBuilder() .mergeFrom(sg) .setBoughtNum(boughtNum) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java new file mode 100644 index 000000000..f8fe1314a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CanUseSkillNotifyOuterClass; + +public class PacketCanUseSkillNotify extends BasePacket { + + public PacketCanUseSkillNotify(boolean canUseSkill) { + super(PacketOpcodes.CanUseSkillNotify); + + CanUseSkillNotifyOuterClass.CanUseSkillNotify proto = CanUseSkillNotifyOuterClass.CanUseSkillNotify.newBuilder() + .setIsCanUseSkill(canUseSkill) + .build(); + + this.setData(proto); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java new file mode 100644 index 000000000..771a0f581 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataFullNotify.java @@ -0,0 +1,94 @@ +package emu.grasscutter.server.packet.send; + +import java.util.Collections; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CodexDataFullNotifyOuterClass.CodexDataFullNotify; +import emu.grasscutter.net.proto.CodexTypeDataOuterClass.CodexTypeData; + +public class PacketCodexDataFullNotify extends BasePacket { + public PacketCodexDataFullNotify(Player player) { + super(PacketOpcodes.CodexDataFullNotify, true); + + //Quests + CodexTypeData.Builder questTypeData = CodexTypeData.newBuilder() + .setTypeValue(1); + + //Weapons + CodexTypeData.Builder weaponTypeData = CodexTypeData.newBuilder() + .setTypeValue(2); + + //Animals + CodexTypeData.Builder animalTypeData = CodexTypeData.newBuilder() + .setTypeValue(3); + + //Materials + CodexTypeData.Builder materialTypeData = CodexTypeData.newBuilder() + .setTypeValue(4); + + //Books + CodexTypeData.Builder bookTypeData = CodexTypeData.newBuilder() + .setTypeValue(5); + + //Tips + CodexTypeData.Builder pushTipsTypeData = CodexTypeData.newBuilder() + .setTypeValue(6); + + //Views + CodexTypeData.Builder viewTypeData = CodexTypeData.newBuilder() + .setTypeValue(7); + + //Reliquary + CodexTypeData.Builder reliquaryData = CodexTypeData.newBuilder() + .setTypeValue(8); + + player.getQuestManager().forEachMainQuest(mainQuest -> { + if(mainQuest.isFinished()){ + var codexQuest = GameData.getCodexQuestDataIdMap().get(mainQuest.getParentQuestId()); + if(codexQuest != null){ + questTypeData.addCodexIdList(codexQuest.getId()).addAllHaveViewedList(Collections.singleton(true)); + } + } + }); + + player.getCodex().getUnlockedWeapon().forEach(weapon -> { + var codexWeapon = GameData.getCodexWeaponDataIdMap().get(weapon); + if(codexWeapon != null){ + weaponTypeData.addCodexIdList(codexWeapon.getId()).addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player.getCodex().getUnlockedAnimal().forEach((animal, amount) -> { + var codexAnimal = GameData.getCodexAnimalDataMap().get(animal); + if(codexAnimal != null){ + animalTypeData.addCodexIdList(codexAnimal.getId()).addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player.getCodex().getUnlockedMaterial().forEach(material -> { + var codexMaterial = GameData.getCodexMaterialDataIdMap().get(material); + if(codexMaterial != null){ + materialTypeData.addCodexIdList(codexMaterial.getId()).addAllHaveViewedList(Collections.singleton(true)); + } + }); + + player.getCodex().getUnlockedReliquarySuitCodex().forEach(reliquarySuit -> { + reliquaryData.addCodexIdList(reliquarySuit).addAllHaveViewedList(Collections.singleton(true)); + }); + + CodexDataFullNotify.Builder proto = CodexDataFullNotify.newBuilder() + .addTypeDataList(questTypeData.build()) + .addTypeDataList(weaponTypeData) + .addTypeDataList(animalTypeData) + .addTypeDataList(materialTypeData) + .addTypeDataList(bookTypeData) + .addTypeDataList(pushTipsTypeData.build()) + .addTypeDataList(viewTypeData.build()) + .addTypeDataList(reliquaryData); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java new file mode 100644 index 000000000..e2c0045f7 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCodexDataUpdateNotify.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CodexDataUpdateNotifyOuterClass.CodexDataUpdateNotify; + +public class PacketCodexDataUpdateNotify extends BasePacket { + public PacketCodexDataUpdateNotify(GameMainQuest quest) { + super(PacketOpcodes.CodexDataUpdateNotify, true); + var codexQuest = GameData.getCodexQuestDataIdMap().get(quest.getParentQuestId()); + if(codexQuest != null){ + CodexDataUpdateNotify proto = CodexDataUpdateNotify.newBuilder() + .setTypeValue(1) + .setId(codexQuest.getId()) + .build(); + this.setData(proto); + } + } + + public PacketCodexDataUpdateNotify(int typeValue, int codexId){ + super(PacketOpcodes.CodexDataUpdateNotify, true); + CodexDataUpdateNotify proto = CodexDataUpdateNotify.newBuilder() + .setTypeValue(typeValue) + .setId(codexId) + .build(); + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java similarity index 79% rename from src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java rename to src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java index fe8b2a1f1..8ff65c260 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java @@ -1,6 +1,5 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.Grasscutter; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.entity.EntityVehicle; import emu.grasscutter.game.props.FightProperty; @@ -9,21 +8,19 @@ import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VehicleInteractTypeOuterClass; import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; -import emu.grasscutter.net.proto.VehicleSpawnRspOuterClass.VehicleSpawnRsp; +import emu.grasscutter.net.proto.CreateVehicleRspOuterClass.CreateVehicleRsp; import emu.grasscutter.utils.Position; import java.util.List; +public class PacketCreateVehicleRsp extends BasePacket { -import static emu.grasscutter.net.proto.VehicleInteractTypeOuterClass.VehicleInteractType.VEHICLE_INTERACT_OUT; - -public class PacketVehicleSpawnRsp extends BasePacket { - - public PacketVehicleSpawnRsp(Player player, int vehicleId, int pointId, Position pos, Position rot) { - super(PacketOpcodes.VehicleSpawnRsp); - VehicleSpawnRsp.Builder proto = VehicleSpawnRsp.newBuilder(); + public PacketCreateVehicleRsp(Player player, int vehicleId, int pointId, Position pos, Position rot) { + super(PacketOpcodes.CreateVehicleRsp); + CreateVehicleRsp.Builder proto = CreateVehicleRsp.newBuilder(); // Eject vehicle members and Kill previous vehicles if there are any List previousVehicles = player.getScene().getEntities().values().stream() @@ -36,7 +33,7 @@ public class PacketVehicleSpawnRsp extends BasePacket { List vehicleMembers = ((EntityVehicle) entity).getVehicleMembers().stream().toList(); vehicleMembers.stream().forEach(vehicleMember -> { - player.getScene().broadcastPacket(new PacketVehicleInteractRsp(((EntityVehicle) entity), vehicleMember, VEHICLE_INTERACT_OUT)); + player.getScene().broadcastPacket(new PacketVehicleInteractRsp(((EntityVehicle) entity), vehicleMember, VehicleInteractTypeOuterClass.VehicleInteractType.VEHICLE_INTERACT_TYPE_OUT)); }); player.getScene().killEntity(entity, 0); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java index 9144c0d8e..6d8b9ddd9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDoGachaRsp.java @@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.send; import java.util.List; +import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.game.gacha.GachaBanner; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; @@ -14,16 +15,18 @@ public class PacketDoGachaRsp extends BasePacket { public PacketDoGachaRsp(GachaBanner banner, List list) { super(PacketOpcodes.DoGachaRsp); + ItemParamData costItem = banner.getCost(1); + ItemParamData costItem10 = banner.getCost(10); DoGachaRsp p = DoGachaRsp.newBuilder() .setGachaType(banner.getGachaType()) .setGachaScheduleId(banner.getScheduleId()) .setGachaTimes(list.size()) .setNewGachaRandom(12345) .setLeftGachaTimes(Integer.MAX_VALUE) - .setCostItemId(banner.getCostItem()) - .setCostItemNum(1) - .setTenCostItemId(banner.getCostItem()) - .setTenCostItemNum(10) + .setCostItemId(costItem.getId()) + .setCostItemNum(costItem.getCount()) + .setTenCostItemId(costItem10.getId()) + .setTenCostItemNum(costItem10.getCount()) .addAllGachaItemList(list) .build(); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java index a44c16778..1036b564c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonChallengeFinishNotify.java @@ -13,7 +13,7 @@ public class PacketDungeonChallengeFinishNotify extends BasePacket { DungeonChallengeFinishNotify proto = DungeonChallengeFinishNotify.newBuilder() .setChallengeIndex(challenge.getChallengeIndex()) .setIsSuccess(challenge.isSuccess()) - .setUnk1(2) + .setChallengeRecordType(2) .build(); this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java index 479029243..ff860289b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java @@ -29,10 +29,10 @@ public class PacketDungeonSettleNotify extends BasePacket { ) { super(PacketOpcodes.DungeonSettleNotify); - var continueStatus = TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_NOT_CONTINUE_VALUE; + var continueStatus = TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_NOT_CONTINUE_VALUE; if(challenge.isSuccess() && canJump){ - continueStatus = hasNextLevel ? TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_ENTER_NEXT_LEVEL_VALUE - : TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_ENTER_NEXT_FLOOR_VALUE; + continueStatus = hasNextLevel ? TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_LEVEL_VALUE + : TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_TYPE_CAN_ENTER_NEXT_FLOOR_VALUE; } var towerLevelEndNotify = TowerLevelEndNotify.newBuilder() @@ -46,7 +46,7 @@ public class PacketDungeonSettleNotify extends BasePacket { .setCount(1000) .build()) ; - if(nextFloorId > 0){ + if(nextFloorId > 0 && canJump){ towerLevelEndNotify.setNextFloorId(nextFloorId); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java index a3e300c25..d78c4016b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityAiSyncNotify.java @@ -13,7 +13,7 @@ public class PacketEntityAiSyncNotify extends BasePacket { EntityAiSyncNotify.Builder proto = EntityAiSyncNotify.newBuilder(); for (int monsterId : notify.getLocalAvatarAlertedMonsterListList()) { - proto.addInfoList(AiSyncInfo.newBuilder().setEntityId(monsterId)); + proto.addInfoList(AiSyncInfo.newBuilder().setEntityId(monsterId).setHasPathToTarget(true)); } this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java index 5778f711a..366354a40 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java @@ -11,21 +11,27 @@ import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; import java.util.List; public class PacketEntityFightPropChangeReasonNotify extends BasePacket { + public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, List param, PropChangeReason reason, ChangeHpReason changeHpReason) { super(PacketOpcodes.EntityFightPropChangeReasonNotify); + EntityFightPropChangeReasonNotify.Builder proto = EntityFightPropChangeReasonNotify.newBuilder() .setEntityId(entity.getId()) .setPropType(prop.getId()) .setPropDelta(value) .setReason(reason) .setChangeHpReason(changeHpReason); - for(int p: param){ + + for(int p : param){ proto.addParamList(p); } + this.setData(proto); } + public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, PropChangeReason reason, ChangeHpReason changeHpReason) { super(PacketOpcodes.EntityFightPropChangeReasonNotify); + EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() .setEntityId(entity.getId()) .setPropType(prop.getId()) @@ -33,6 +39,20 @@ public class PacketEntityFightPropChangeReasonNotify extends BasePacket { .setReason(reason) .setChangeHpReason(changeHpReason) .build(); + + this.setData(proto); + } + + public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, PropChangeReason reason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + + EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .build(); + this.setData(proto); } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java index 07cdf9054..da23def9a 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEvtAvatarStandUpNotify.java @@ -12,7 +12,7 @@ public class PacketEvtAvatarStandUpNotify extends BasePacket { EvtAvatarStandUpNotify proto = EvtAvatarStandUpNotify.newBuilder() .setEntityId(notify.getEntityId()) .setDirection(notify.getDirection()) - .setPerformID(notify.getPerformID()) + .setPerformId(notify.getPerformId()) .setChairId(notify.getChairId()) .build(); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java new file mode 100644 index 000000000..7d64da48f --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestNotify.java @@ -0,0 +1,22 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestNotifyOuterClass.FinishedParentQuestNotify; + +public class PacketFinishedParentQuestNotify extends BasePacket { + + public PacketFinishedParentQuestNotify(Player player) { + super(PacketOpcodes.FinishedParentQuestNotify, true); + + FinishedParentQuestNotify.Builder proto = FinishedParentQuestNotify.newBuilder(); + + for (GameMainQuest mainQuest : player.getQuestManager().getQuests().values()) { + proto.addParentQuestList(mainQuest.toProto()); + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java new file mode 100644 index 000000000..68eab7222 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketFinishedParentQuestUpdateNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; + +public class PacketFinishedParentQuestUpdateNotify extends BasePacket { + + public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { + super(PacketOpcodes.FinishedParentQuestUpdateNotify); + + FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder() + .addParentQuestList(quest.toProto()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java new file mode 100644 index 000000000..48ea79ba4 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeDataNotify.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeDataNotifyOuterClass.ForgeDataNotify; + +public class PacketForgeDataNotify extends BasePacket { + + public PacketForgeDataNotify(Player player) { + super(PacketOpcodes.ForgeDataNotify); + + int adventureRank = player.getLevel(); + int numQueues = + (adventureRank >= 15) ? 4 + : (adventureRank >= 10) ? 3 + : (adventureRank >= 5) ? 2 + : 1; + + ForgeDataNotify proto = ForgeDataNotify.newBuilder() + .addAllForgeIdList(player.getUnlockedForgingBlueprints()) + .setMaxQueueNum(numQueues) + .build(); + + // ToDo: Add the information for the actual forging queues + // and ongoing forges. + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java new file mode 100644 index 000000000..46f180280 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketForgeFormulaDataNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ForgeFormulaDataNotifyOuterClass.ForgeFormulaDataNotify; + +public class PacketForgeFormulaDataNotify extends BasePacket { + + public PacketForgeFormulaDataNotify(int itemId) { + super(PacketOpcodes.ForgeFormulaDataNotify); + + ForgeFormulaDataNotify proto = ForgeFormulaDataNotify.newBuilder() + .setForgeId(itemId) + .setIsLocked(false) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java index 59af30f42..ff7f83721 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java @@ -5,6 +5,7 @@ import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.EquipParamOuterClass; import emu.grasscutter.net.proto.GetAllMailRspOuterClass.GetAllMailRsp; import emu.grasscutter.net.proto.ItemParamOuterClass; import emu.grasscutter.net.proto.MailDataOuterClass; @@ -23,9 +24,9 @@ public class PacketGetAllMailRsp extends BasePacket { GetAllMailRsp.Builder proto = GetAllMailRsp.newBuilder(); if (isGiftMail) { - proto.setIsGiftMail(true); + proto.setANKKGPJCINB(true); } else { - proto.setIsGiftMail(false); + proto.setANKKGPJCINB(false); if (player.getAllMail().size() != 0) { // Make sure the player has mail List mailDataList = new ArrayList(); @@ -43,10 +44,10 @@ public class PacketGetAllMailRsp extends BasePacket { for (Mail.MailItem item : message.itemList) { MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); - ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); + EquipParamOuterClass.EquipParam.Builder itemParam = EquipParamOuterClass.EquipParam.newBuilder(); itemParam.setItemId(item.itemId); - itemParam.setCount(item.itemCount); - mailItem.setItemParam(itemParam.build()); + itemParam.setItemNum(item.itemCount); + mailItem.setEquipParam(itemParam.build()); mailItems.add(mailItem.build()); } @@ -60,7 +61,7 @@ public class PacketGetAllMailRsp extends BasePacket { mailData.setImportance(message.importance); mailData.setIsRead(message.isRead); mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setStateValue(1); + mailData.setBHCAHLJIKFFValue(1); mailDataList.add(mailData.build()); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java index 37f753c17..cdf2e2349 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java @@ -18,52 +18,60 @@ public class PacketGetMailItemRsp extends BasePacket { public PacketGetMailItemRsp(Player player, List mailList) { super(PacketOpcodes.GetMailItemRsp); - List claimedMessages = new ArrayList<>(); List claimedItems = new ArrayList<>(); GetMailItemRsp.Builder proto = GetMailItemRsp.newBuilder(); - for (int mailId : mailList) { - Mail message = player.getMail(mailId); + synchronized (player) { + boolean modified = false; + for (int mailId : mailList) { + Mail message = player.getMail(mailId); + if (!message.isAttachmentGot) {//No duplicated item + for (Mail.MailItem mailItem : message.itemList) { + EquipParamOuterClass.EquipParam.Builder item = EquipParamOuterClass.EquipParam.newBuilder(); + int promoteLevel = 0; - for(Mail.MailItem mailItem : message.itemList) { - EquipParamOuterClass.EquipParam.Builder item = EquipParamOuterClass.EquipParam.newBuilder(); - int promoteLevel = 0; - if (mailItem.itemLevel > 20) { // 20/40 - promoteLevel = 1; - } else if (mailItem.itemLevel > 40) { // 40/50 - promoteLevel = 2; - } else if (mailItem.itemLevel > 50) { // 50/60 - promoteLevel = 3; - } else if (mailItem.itemLevel > 60) { // 60/70 - promoteLevel = 4; - } else if (mailItem.itemLevel > 70) { // 70/80 - promoteLevel = 5; - } else if (mailItem.itemLevel > 80) { // 80/90 - promoteLevel = 6; + if (mailItem.itemLevel > 80) { // 80/90 + promoteLevel = 6; + } else if (mailItem.itemLevel > 70) { // 70/80 + promoteLevel = 5; + } else if (mailItem.itemLevel > 60) { // 60/70 + promoteLevel = 4; + } else if (mailItem.itemLevel > 50) { // 50/60 + promoteLevel = 3; + } else if (mailItem.itemLevel > 40) { // 40/50 + promoteLevel = 2; + } else if (mailItem.itemLevel > 20) { // 20/40 + promoteLevel = 1; + } + + item.setItemId(mailItem.itemId); + item.setItemNum(mailItem.itemCount); + item.setItemLevel(mailItem.itemLevel); + item.setPromoteLevel(promoteLevel); + claimedItems.add(item.build()); + + GameItem gameItem = new GameItem(GameData.getItemDataMap().get(mailItem.itemId)); + gameItem.setCount(mailItem.itemCount); + gameItem.setLevel(mailItem.itemLevel); + gameItem.setPromoteLevel(promoteLevel); + player.getInventory().addItem(gameItem, ActionReason.MailAttachment); + } + + message.isAttachmentGot = true; + claimedMessages.add(message); + + player.replaceMailByIndex(mailId, message); + modified = true; } - - item.setItemId(mailItem.itemId); - item.setItemNum(mailItem.itemCount); - item.setItemLevel(mailItem.itemLevel); - item.setPromoteLevel(promoteLevel); - claimedItems.add(item.build()); - - GameItem gameItem = new GameItem(GameData.getItemDataMap().get(mailItem.itemId)); - gameItem.setCount(mailItem.itemCount); - gameItem.setLevel(mailItem.itemLevel); - gameItem.setPromoteLevel(promoteLevel); - player.getInventory().addItem(gameItem, ActionReason.MailAttachment); } - - message.isAttachmentGot = true; - claimedMessages.add(message); - - player.replaceMailByIndex(mailId, message); + if(modified) { + player.save(); + } } - proto.addAllMailIdList(claimedMessages.stream().map(message -> player.getMailId(message)).collect(Collectors.toList())); + proto.addAllMailIdList(claimedMessages.stream().map(player::getMailId).collect(Collectors.toList())); proto.addAllItemList(claimedItems); this.setData(proto.build()); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java index ff373140b..1ca159d57 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java @@ -1,7 +1,6 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; import emu.grasscutter.game.friends.Friendship; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; @@ -12,24 +11,27 @@ import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFrien import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; import emu.grasscutter.net.proto.PlatformTypeOuterClass; +import static emu.grasscutter.Configuration.*; + public class PacketGetPlayerFriendListRsp extends BasePacket { public PacketGetPlayerFriendListRsp(Player player) { super(PacketOpcodes.GetPlayerFriendListRsp); + var serverAccount = GAME_INFO.serverAccount; FriendBrief serverFriend = FriendBrief.newBuilder() .setUid(GameConstants.SERVER_CONSOLE_UID) - .setNickname(Grasscutter.getConfig().getGameServerOptions().ServerNickname) - .setLevel(Grasscutter.getConfig().getGameServerOptions().ServerLevel) - .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(Grasscutter.getConfig().getGameServerOptions().ServerAvatarId)) - .setWorldLevel(Grasscutter.getConfig().getGameServerOptions().ServerWorldLevel) - .setSignature(Grasscutter.getConfig().getGameServerOptions().ServerSignature) + .setNickname(serverAccount.nickName) + .setLevel(serverAccount.adventureRank) + .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(serverAccount.avatarId)) + .setWorldLevel(serverAccount.worldLevel) + .setSignature(serverAccount.signature) .setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) - .setNameCardId(Grasscutter.getConfig().getGameServerOptions().ServerNameCardId) - .setOnlineState(FriendOnlineState.FRIEND_ONLINE) + .setNameCardId(serverAccount.nameCardId) + .setOnlineState(FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE) .setParam(1) .setIsGameSource(true) - .setPlatformType(PlatformTypeOuterClass.PlatformType.PC) + .setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC) .build(); GetPlayerFriendListRsp.Builder proto = GetPlayerFriendListRsp.newBuilder().addFriendList(serverFriend); @@ -37,10 +39,12 @@ public class PacketGetPlayerFriendListRsp extends BasePacket { for (Friendship friendship : player.getFriendsList().getFriends().values()) { proto.addFriendList(friendship.toProto()); } + for (Friendship friendship : player.getFriendsList().getPendingFriends().values()) { if (friendship.getAskerId() == player.getUid()) { continue; } + proto.addAskFriendList(friendship.toProto()); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java index 3a5e0f08c..f48c40873 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java @@ -10,16 +10,16 @@ import emu.grasscutter.utils.Crypto; public class PacketGetPlayerTokenRsp extends BasePacket { - public PacketGetPlayerTokenRsp(GameSession session, boolean doesPlayerExist) { + public PacketGetPlayerTokenRsp(GameSession session) { super(PacketOpcodes.GetPlayerTokenRsp, true); this.setUseDispatchKey(true); GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() - .setUid(session.getAccount().getPlayerUid()) + .setUid(session.getPlayer().getUid()) .setToken(session.getAccount().getToken()) .setAccountType(1) - .setIsProficientPlayer(doesPlayerExist) // Not sure where this goes + .setIsProficientPlayer(session.getPlayer().getAvatars().getAvatarCount() > 0) // Not sure where this goes .setSecretKeySeed(Crypto.ENCRYPT_SEED) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setPlatformType(3) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java new file mode 100644 index 000000000..8df189c94 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetWidgetSlotRsp.java @@ -0,0 +1,41 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.GetWidgetSlotRspOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotTagOuterClass; + +import java.util.List; + +public class PacketGetWidgetSlotRsp extends BasePacket { + + public PacketGetWidgetSlotRsp(Player player) { + super(PacketOpcodes.GetWidgetSlotRsp); + + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.Builder proto = + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp.newBuilder(); + + if (player.getWidgetId() == null) { + proto.addAllSlotList(List.of()); + } else { + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(player.getWidgetId()) + .build() + ); + + proto.addSlotList( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setTag(WidgetSlotTagOuterClass.WidgetSlotTag.WIDGET_SLOT_TAG_ATTACH_AVATAR) + .build() + ); + } + + GetWidgetSlotRspOuterClass.GetWidgetSlotRsp protoData = proto.build(); + + this.setData(protoData); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java new file mode 100644 index 000000000..e7b3ff1ea --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeChooseModuleRsp.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeChooseModuleRspOuterClass; + +public class PacketHomeChooseModuleRsp extends BasePacket { + + public PacketHomeChooseModuleRsp(int moduleId) { + super(PacketOpcodes.HomeChooseModuleRsp); + + HomeChooseModuleRspOuterClass.HomeChooseModuleRsp proto = HomeChooseModuleRspOuterClass.HomeChooseModuleRsp.newBuilder() + .setRetcode(0) + .setModuleId(moduleId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java new file mode 100644 index 000000000..47e46dfdb --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeComfortInfoNotify.java @@ -0,0 +1,40 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.HomeComfortInfoNotifyOuterClass; +import emu.grasscutter.net.proto.HomeModuleComfortInfoOuterClass; + +import java.util.ArrayList; +import java.util.List; + +public class PacketHomeComfortInfoNotify extends BasePacket { + + public PacketHomeComfortInfoNotify(Player player) { + super(PacketOpcodes.HomeComfortInfoNotify); + + if (player.getRealmList() == null) { + // Do not send + return; + } + + List comfortInfoList = new ArrayList<>(); + + for (int moduleId : player.getRealmList()) { + comfortInfoList.add( + HomeModuleComfortInfoOuterClass.HomeModuleComfortInfo.newBuilder() + .setModuleId(moduleId) + .build() + ); + } + + HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify proto = HomeComfortInfoNotifyOuterClass.HomeComfortInfoNotify + .newBuilder() + .addAllModuleInfoList(comfortInfoList) + .build(); + + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java index c4b2b229e..0a43a1c61 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java @@ -37,10 +37,10 @@ public class PacketMailChangeNotify extends BasePacket { for (Mail.MailItem item : message.itemList) { MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); - ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); + EquipParamOuterClass.EquipParam.Builder itemParam = EquipParamOuterClass.EquipParam.newBuilder(); itemParam.setItemId(item.itemId); - itemParam.setCount(item.itemCount); - mailItem.setItemParam(itemParam.build()); + itemParam.setItemNum(item.itemCount); + mailItem.setEquipParam(itemParam.build()); mailItems.add(mailItem.build()); } @@ -54,7 +54,7 @@ public class PacketMailChangeNotify extends BasePacket { mailData.setImportance(message.importance); mailData.setIsRead(message.isRead); mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setStateValue(message.stateValue); + mailData.setBHCAHLJIKFFValue(message.stateValue); proto.addMailList(mailData.build()); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java index d7ee20d61..21ccbe74e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java @@ -10,7 +10,7 @@ import java.util.*; public class PacketMarkMapRsp extends BasePacket { - public PacketMarkMapRsp(Player player, HashMap mapMarks) { + public PacketMarkMapRsp(HashMap mapMarks) { super(PacketOpcodes.MarkMapRsp); MarkMapRspOuterClass.MarkMapRsp.Builder proto = MarkMapRspOuterClass.MarkMapRsp.newBuilder(); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java index 42fe3a12f..953bb679c 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java @@ -23,7 +23,7 @@ public class PacketPlayerEnterSceneNotify extends BasePacket { .setSceneId(player.getSceneId()) .setPos(player.getPos().toProto()) .setSceneBeginTime(System.currentTimeMillis()) - .setType(EnterType.ENTER_SELF) + .setType(EnterType.ENTER_TYPE_SELF) .setTargetUid(player.getUid()) .setEnterSceneToken(player.getEnterSceneToken()) .setWorldLevel(player.getWorldLevel()) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java new file mode 100644 index 000000000..29a6964b5 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerHomeCompInfoNotify.java @@ -0,0 +1,32 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerHomeCompInfoNotifyOuterClass; +import emu.grasscutter.net.proto.PlayerHomeCompInfoOuterClass; + +import java.util.List; + +public class PacketPlayerHomeCompInfoNotify extends BasePacket { + + public PacketPlayerHomeCompInfoNotify(Player player) { + super(PacketOpcodes.PlayerHomeCompInfoNotify); + + if (player.getRealmList() == null) { + // Do not send + return; + } + + PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify proto = PlayerHomeCompInfoNotifyOuterClass.PlayerHomeCompInfoNotify.newBuilder() + .setCompInfo( + PlayerHomeCompInfoOuterClass.PlayerHomeCompInfo.newBuilder() + .addAllUnlockedModuleIdList(player.getRealmList()) + .addAllLevelupRewardGotLevelList(List.of(1)) // Hardcoded + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java index 6407e9412..52a487d55 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java @@ -2,7 +2,6 @@ package emu.grasscutter.server.packet.send; import com.google.protobuf.ByteString; import emu.grasscutter.Grasscutter; -import emu.grasscutter.Grasscutter.ServerDebugMode; import emu.grasscutter.Grasscutter.ServerRunMode; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; @@ -10,11 +9,15 @@ import emu.grasscutter.net.proto.PlayerLoginRspOuterClass.PlayerLoginRsp; import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass; import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.http.dispatch.RegionHandler; +import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.FileUtils; import java.io.File; -import java.net.URL; import java.util.Base64; +import java.util.Objects; + +import static emu.grasscutter.Configuration.*; public class PacketPlayerLoginRsp extends BasePacket { @@ -27,27 +30,17 @@ public class PacketPlayerLoginRsp extends BasePacket { RegionInfo info; - if (Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) { + if (SERVER.runMode == ServerRunMode.GAME_ONLY) { if (regionCache == null) { try { - File file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt"); - String query_cur_region = ""; - if (file.exists()) { - query_cur_region = new String(FileUtils.read(file)); - } else { - Grasscutter.getLogger().warn("query_cur_region not found! Using default current region."); - } - - byte[] decodedCurRegion = Base64.getDecoder().decode(query_cur_region); - QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion); - - RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() - .setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp)) - .setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 ? Grasscutter.getConfig().getGameServerOptions().PublicPort : Grasscutter.getConfig().getGameServerOptions().Port) - .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) + // todo: we might want to push custom config to client + RegionInfo serverRegion = RegionInfo.newBuilder() + .setGateserverIp(lr(GAME_INFO.accessAddress, GAME_INFO.bindAddress)) + .setGateserverPort(lr(GAME_INFO.accessPort, GAME_INFO.bindPort)) + .setSecretKey(ByteString.copyFrom(Crypto.DISPATCH_SEED)) .build(); - regionCache = regionQuery.toBuilder().setRegionInfo(serverRegion).build(); + regionCache = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.newBuilder().setRegionInfo(serverRegion).build(); } catch (Exception e) { Grasscutter.getLogger().error("Error while initializing region cache!", e); } @@ -55,7 +48,7 @@ public class PacketPlayerLoginRsp extends BasePacket { info = regionCache.getRegionInfo(); } else { - info = Grasscutter.getDispatchServer().getCurrRegion().getRegionInfo(); + info = Objects.requireNonNull(RegionHandler.getCurrentRegion()).getRegionInfo(); } PlayerLoginRsp p = PlayerLoginRsp.newBuilder() diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java index a3a6ff7b8..2a61aeda9 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java @@ -1,7 +1,5 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; @@ -10,6 +8,8 @@ import emu.grasscutter.net.proto.ItemOuterClass.Item; import emu.grasscutter.net.proto.PlayerStoreNotifyOuterClass.PlayerStoreNotify; import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; +import static emu.grasscutter.Configuration.*; + public class PacketPlayerStoreNotify extends BasePacket { public PacketPlayerStoreNotify(Player player) { @@ -18,8 +18,8 @@ public class PacketPlayerStoreNotify extends BasePacket { this.buildHeader(2); PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK) - .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll); + .setStoreType(StoreType.STORE_TYPE_PACK) + .setWeightLimit(GAME_OPTIONS.inventoryLimits.all); for (GameItem item : player.getInventory()) { Item itemProto = item.toProto(); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java new file mode 100644 index 000000000..bf9b029a7 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java @@ -0,0 +1,63 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; +import emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass; +import emu.grasscutter.net.proto.SceneUnlockInfoOuterClass.SceneUnlockInfo; + +import static emu.grasscutter.net.proto.PlayerWorldSceneInfoOuterClass.*; + +public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { + + public PacketPlayerWorldSceneInfoListNotify() { + super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later + + PlayerWorldSceneInfoListNotify proto = PlayerWorldSceneInfoListNotify.newBuilder() + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(1) + .setIsLocked(false) + .build() + ) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(3) + .setIsLocked(false) + .addSceneTagIdList(102) + .addSceneTagIdList(113) + .addSceneTagIdList(117) + .build() + ) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(4) + .setIsLocked(false) + .addSceneTagIdList(106) + .addSceneTagIdList(109) + .addSceneTagIdList(117) + .build() + ) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(5) + .setIsLocked(false) + .build() + ) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(6) + .setIsLocked(false) + .build() + ) + .addInfoList( + PlayerWorldSceneInfo.newBuilder() + .setSceneId(7) + .setIsLocked(false) + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java index 871534b53..0e757d11b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java @@ -1,42 +1,41 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.Config.GameServerOptions; import emu.grasscutter.game.player.Player; import emu.grasscutter.GameConstants; -import emu.grasscutter.Grasscutter; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo; import emu.grasscutter.net.proto.PullRecentChatRspOuterClass.PullRecentChatRsp; import emu.grasscutter.utils.Utils; +import static emu.grasscutter.Configuration.*; + public class PacketPullRecentChatRsp extends BasePacket { public PacketPullRecentChatRsp(Player player) { super(PacketOpcodes.PullRecentChatRsp); - GameServerOptions serverOptions = Grasscutter.getConfig().getGameServerOptions(); + var joinOptions = GAME_INFO.joinOptions; PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder(); - if (serverOptions.WelcomeEmotes != null && serverOptions.WelcomeEmotes.length > 0) { + if (joinOptions.welcomeEmotes != null && joinOptions.welcomeEmotes.length > 0) { ChatInfo welcomeEmote = ChatInfo.newBuilder() .setTime((int) (System.currentTimeMillis() / 1000)) .setUid(GameConstants.SERVER_CONSOLE_UID) .setToUid(player.getUid()) - .setIcon(serverOptions.WelcomeEmotes[Utils.randomRange(0, serverOptions.WelcomeEmotes.length - 1)]) + .setIcon(joinOptions.welcomeEmotes[Utils.randomRange(0, joinOptions.welcomeEmotes.length - 1)]) .build(); proto.addChatInfo(welcomeEmote); } - if (serverOptions.WelcomeMotd != null && serverOptions.WelcomeMotd.length() > 0) { - ChatInfo welcomeMotd = ChatInfo.newBuilder() + if (joinOptions.welcomeMessage != null && joinOptions.welcomeMessage.length() > 0) { + ChatInfo welcomeMessage = ChatInfo.newBuilder() .setTime((int) (System.currentTimeMillis() / 1000)) .setUid(GameConstants.SERVER_CONSOLE_UID) .setToUid(player.getUid()) - .setText(Grasscutter.getConfig().getGameServerOptions().WelcomeMotd) + .setText(joinOptions.welcomeMessage) .build(); - - proto.addChatInfo(welcomeMotd); + proto.addChatInfo(welcomeMessage); } this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java new file mode 100644 index 000000000..8da5c4fe2 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQueryCodexMonsterBeKilledNumRsp.java @@ -0,0 +1,26 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QueryCodexMonsterBeKilledNumRspOuterClass.QueryCodexMonsterBeKilledNumRsp; + +import java.util.List; + +public class PacketQueryCodexMonsterBeKilledNumRsp extends BasePacket { + + public PacketQueryCodexMonsterBeKilledNumRsp(Player player, List codexList) { + super(PacketOpcodes.QueryCodexMonsterBeKilledNumRsp); + QueryCodexMonsterBeKilledNumRsp.Builder proto = QueryCodexMonsterBeKilledNumRsp.newBuilder(); + + codexList.forEach(animal -> { + if(player.getCodex().getUnlockedAnimal().containsKey(animal)){ + proto.addCodexIdList(animal) + .addBeKilledNumList(player.getCodex().getUnlockedAnimal().get(animal)) + .addCHPBKCLKPCJ(0); + } + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java new file mode 100644 index 000000000..ccf0d765a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListNotify.java @@ -0,0 +1,23 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.QuestManager; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListNotifyOuterClass.QuestListNotify; + +public class PacketQuestListNotify extends BasePacket { + + public PacketQuestListNotify(Player player) { + super(PacketOpcodes.QuestListNotify, true); + + QuestListNotify.Builder proto = QuestListNotify.newBuilder(); + + player.getQuestManager().forEachQuest(quest -> { + proto.addQuestList(quest.toProto()); + }); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java new file mode 100644 index 000000000..adc0767a8 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestListUpdateNotify.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestListUpdateNotifyOuterClass.QuestListUpdateNotify; + +public class PacketQuestListUpdateNotify extends BasePacket { + + public PacketQuestListUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestListUpdateNotify); + + QuestListUpdateNotify proto = QuestListUpdateNotify.newBuilder() + .addQuestList(quest.toProto()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java new file mode 100644 index 000000000..76ee56316 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketQuestProgressUpdateNotify.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.quest.GameMainQuest; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.QuestProgressUpdateNotifyOuterClass.QuestProgressUpdateNotify; + +public class PacketQuestProgressUpdateNotify extends BasePacket { + + public PacketQuestProgressUpdateNotify(GameQuest quest) { + super(PacketOpcodes.QuestProgressUpdateNotify); + + QuestProgressUpdateNotify.Builder proto = QuestProgressUpdateNotify.newBuilder().setQuestId(quest.getQuestId()); + + if (quest.getFinishProgressList() != null) { + for (int i : quest.getFinishProgressList()) { + proto.addFinishProgressList(i); + } + } + + if (quest.getFailProgressList() != null) { + for (int i : quest.getFailProgressList()) { + proto.addFailProgressList(i); + } + } + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java index 78c17a5d5..5e8bfa58e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityAppearNotify.java @@ -15,7 +15,7 @@ public class PacketSceneEntityAppearNotify extends BasePacket { super(PacketOpcodes.SceneEntityAppearNotify, true); SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder() - .setAppearType(VisionType.VISION_BORN) + .setAppearType(VisionType.VISION_TYPE_BORN) .addEntityList(entity.toProto()); this.setData(proto.build()); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java index b421dfe40..17350c628 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java @@ -1,7 +1,7 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.data.GameData; -import emu.grasscutter.data.custom.ScenePointEntry; +import emu.grasscutter.data.binout.ScenePointEntry; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java deleted file mode 100644 index 223efc776..000000000 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java +++ /dev/null @@ -1,24 +0,0 @@ -package emu.grasscutter.server.packet.send; - -import emu.grasscutter.net.packet.BasePacket; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneUnlockInfoNotifyOuterClass.SceneUnlockInfoNotify; -import emu.grasscutter.net.proto.SceneUnlockInfoOuterClass.SceneUnlockInfo; - -public class PacketSceneUnlockInfoNotify extends BasePacket { - - public PacketSceneUnlockInfoNotify() { - super(PacketOpcodes.SceneUnlockInfoNotify); // Rename opcode later - - SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder() - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1)) - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3).addSceneTagIdList(102).addSceneTagIdList(113).addSceneTagIdList(117)) - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4).addSceneTagIdList(106).addSceneTagIdList(109)) - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(5)) - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(6)) - .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(7)) - .build(); - - this.setData(proto); - } -} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java new file mode 100644 index 000000000..278d4b04b --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketServerCondMeetQuestListUpdateNotify.java @@ -0,0 +1,36 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.quest.GameQuest; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ServerCondMeetQuestListUpdateNotifyOuterClass.ServerCondMeetQuestListUpdateNotify; + +public class PacketServerCondMeetQuestListUpdateNotify extends BasePacket { + + public PacketServerCondMeetQuestListUpdateNotify(Player player) { + super(PacketOpcodes.ServerCondMeetQuestListUpdateNotify); + + ServerCondMeetQuestListUpdateNotify.Builder proto = ServerCondMeetQuestListUpdateNotify.newBuilder(); + + /* + player.getQuestManager().forEachQuest(quest -> { + if (quest.getState().getValue() <= 2) { + proto.addAddQuestIdList(quest.getQuestId()); + } + }); + */ + + this.setData(proto); + } + + public PacketServerCondMeetQuestListUpdateNotify(GameQuest quest) { + super(PacketOpcodes.ServerCondMeetQuestListUpdateNotify); + + ServerCondMeetQuestListUpdateNotify proto = ServerCondMeetQuestListUpdateNotify.newBuilder() + //.addAddQuestIdList(quest.getQuestId()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java new file mode 100644 index 000000000..0f81afa85 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSetWidgetSlotRsp.java @@ -0,0 +1,18 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.SetWidgetSlotRspOuterClass; + +public class PacketSetWidgetSlotRsp extends BasePacket { + + public PacketSetWidgetSlotRsp(int materialId) { + super(PacketOpcodes.SetWidgetSlotRsp); + + SetWidgetSlotRspOuterClass.SetWidgetSlotRsp proto = SetWidgetSlotRspOuterClass.SetWidgetSlotRsp.newBuilder() + .setMaterialId(materialId) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java index 4d951c0d6..4ad82c1b4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemChangeNotify.java @@ -18,7 +18,7 @@ public class PacketStoreItemChangeNotify extends BasePacket { this(); StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK) + .setStoreType(StoreType.STORE_TYPE_PACK) .addItemList(item.toProto()); this.setData(proto); @@ -28,7 +28,7 @@ public class PacketStoreItemChangeNotify extends BasePacket { this(); StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK); + .setStoreType(StoreType.STORE_TYPE_PACK); items.forEach(item -> proto.addItemList(item.toProto())); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java index 197d4a32a..04a62ebf4 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreItemDelNotify.java @@ -18,7 +18,7 @@ public class PacketStoreItemDelNotify extends BasePacket { this(); StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK) + .setStoreType(StoreType.STORE_TYPE_PACK) .addGuidList(item.getGuid()); this.setData(proto); @@ -28,7 +28,7 @@ public class PacketStoreItemDelNotify extends BasePacket { this(); StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK); + .setStoreType(StoreType.STORE_TYPE_PACK); items.stream().forEach(item -> proto.addGuidList(item.getGuid())); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java index 61b51948b..17600932b 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java @@ -1,23 +1,24 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.Grasscutter; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.StoreTypeOuterClass.StoreType; import emu.grasscutter.net.proto.StoreWeightLimitNotifyOuterClass.StoreWeightLimitNotify; +import static emu.grasscutter.Configuration.*; + public class PacketStoreWeightLimitNotify extends BasePacket { public PacketStoreWeightLimitNotify() { super(PacketOpcodes.StoreWeightLimitNotify); StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder() - .setStoreType(StoreType.STORE_PACK) - .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll) - .setWeaponCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon) - .setReliquaryCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic) - .setMaterialCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial) - .setFurnitureCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture) + .setStoreType(StoreType.STORE_TYPE_PACK) + .setWeightLimit(INVENTORY_LIMITS.all) + .setWeaponCountLimit(INVENTORY_LIMITS.weapons) + .setReliquaryCountLimit(INVENTORY_LIMITS.relics) + .setMaterialCountLimit(INVENTORY_LIMITS.materials) + .setFurnitureCountLimit(INVENTORY_LIMITS.furniture) .build(); this.setData(p); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java index d2d2376e6..654aa4a07 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java @@ -1,37 +1,64 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.TowerFloorData; +import emu.grasscutter.game.tower.TowerManager; +import emu.grasscutter.game.tower.TowerScheduleManager; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.TowerAllDataRspOuterClass.TowerAllDataRsp; import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; +import emu.grasscutter.net.proto.TowerLevelRecordOuterClass; +import emu.grasscutter.utils.DateHelper; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.IntStream; public class PacketTowerAllDataRsp extends BasePacket { - public PacketTowerAllDataRsp() { + public PacketTowerAllDataRsp(TowerScheduleManager towerScheduleManager, TowerManager towerManager) { super(PacketOpcodes.TowerAllDataRsp); - var list = GameData.getTowerFloorDataMap().values().stream() - .map(TowerFloorData::getFloorId) - .map(id -> TowerFloorRecord.newBuilder().setFloorId(id).build()) - .collect(Collectors.toList()); + var recordList = towerManager.getRecordMap().values().stream() + .map(rec -> TowerFloorRecord.newBuilder() + .setFloorId(rec.getFloorId()) + .setFloorStarRewardProgress(rec.getFloorStarRewardProgress()) + .putAllPassedLevelMap(rec.getPassedLevelMap()) + .addAllPassedLevelRecordList(buildFromPassedLevelMap(rec.getPassedLevelMap())) + .build() + ) + .toList(); + + var openTimeMap = towerScheduleManager.getScheduleFloors().stream() + .collect(Collectors.toMap(x -> x, + y -> DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getScheduleStartTime())) + ); TowerAllDataRsp proto = TowerAllDataRsp.newBuilder() - .setTowerScheduleId(29) - .addAllTowerFloorRecordList(list) + .setTowerScheduleId(towerScheduleManager.getCurrentTowerScheduleData().getScheduleId()) + .addAllTowerFloorRecordList(recordList) .setCurLevelRecord(TowerCurLevelRecord.newBuilder().setIsEmpty(true)) - .setNextScheduleChangeTime(Integer.MAX_VALUE) - .putFloorOpenTimeMap(1024, 1630486800) - .putFloorOpenTimeMap(1025, 1630486800) - .putFloorOpenTimeMap(1026, 1630486800) - .putFloorOpenTimeMap(1027, 1630486800) - .setScheduleStartTime(1630486800) + .setScheduleStartTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getScheduleStartTime())) + .setNextScheduleChangeTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getNextScheduleChangeTime())) + .putAllFloorOpenTimeMap(openTimeMap) + .setIsFinishedEntranceFloor(towerManager.canEnterScheduleFloor()) .build(); this.setData(proto); } + + private List buildFromPassedLevelMap(Map map){ + return map.entrySet().stream() + .map(item -> TowerLevelRecordOuterClass.TowerLevelRecord.newBuilder() + .setLevelId(item.getKey()) + .addAllSatisfiedCondList(IntStream.range(1, item.getValue() + 1).boxed().toList()) + .build()) + .toList(); + + } + } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java index c0ed414a8..5ab091901 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java @@ -8,13 +8,13 @@ import emu.grasscutter.net.proto.TowerLevelRecordOuterClass.TowerLevelRecord; public class PacketTowerFloorRecordChangeNotify extends BasePacket { - public PacketTowerFloorRecordChangeNotify(int floorId) { + public PacketTowerFloorRecordChangeNotify(int floorId, int stars, boolean canEnterScheduleFloor) { super(PacketOpcodes.TowerFloorRecordChangeNotify); TowerFloorRecordChangeNotify proto = TowerFloorRecordChangeNotify.newBuilder() .addTowerFloorRecordList(TowerFloorRecord.newBuilder() .setFloorId(floorId) - .setFloorStarRewardProgress(3) + .setFloorStarRewardProgress(stars) .addPassedLevelRecordList(TowerLevelRecord.newBuilder() .setLevelId(1) .addSatisfiedCondList(1) @@ -22,7 +22,7 @@ public class PacketTowerFloorRecordChangeNotify extends BasePacket { .addSatisfiedCondList(3) .build()) .build()) - .setIsFinishedEntranceFloor(true) + .setIsFinishedEntranceFloor(canEnterScheduleFloor) .build(); this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java new file mode 100644 index 000000000..c2c301e4e --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java @@ -0,0 +1,32 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerLevelStarCondDataOuterClass.TowerLevelStarCondData; +import emu.grasscutter.net.proto.TowerLevelStarCondNotifyOuterClass.TowerLevelStarCondNotify; + +public class PacketTowerLevelStarCondNotify extends BasePacket { + + public PacketTowerLevelStarCondNotify(int floorId, int levelIndex) { + super(PacketOpcodes.TowerLevelStarCondNotify); + + TowerLevelStarCondNotify proto = TowerLevelStarCondNotify.newBuilder() + .setFloorId(floorId) + .setLevelIndex(levelIndex) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(1) + .build() + ) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(2) + .build() + ) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(3) + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java new file mode 100644 index 000000000..f778c68aa --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerMiddleLevelChangeTeamNotify.java @@ -0,0 +1,18 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerMiddleLevelChangeTeamNotifyOuterClass; + +public class PacketTowerMiddleLevelChangeTeamNotify extends BasePacket { + + public PacketTowerMiddleLevelChangeTeamNotify() { + super(PacketOpcodes.TowerMiddleLevelChangeTeamNotify); + + TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify proto = + TowerMiddleLevelChangeTeamNotifyOuterClass.TowerMiddleLevelChangeTeamNotify.newBuilder() + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java new file mode 100644 index 000000000..369c44140 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTryEnterHomeRsp.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.RetcodeOuterClass; +import emu.grasscutter.net.proto.TryEnterHomeRspOuterClass; + +public class PacketTryEnterHomeRsp extends BasePacket { + + public PacketTryEnterHomeRsp() { + super(PacketOpcodes.TryEnterHomeRsp); + + TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() + .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) + .build(); + + this.setData(proto); + } + + public PacketTryEnterHomeRsp(int uid) { + super(PacketOpcodes.TryEnterHomeRsp); + + TryEnterHomeRspOuterClass.TryEnterHomeRsp proto = TryEnterHomeRspOuterClass.TryEnterHomeRsp.newBuilder() + .setRetcode(0) + .setTargetUid(uid) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java index 989aa3876..d6863cc4e 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleInteractRsp.java @@ -31,10 +31,10 @@ public class PacketVehicleInteractRsp extends BasePacket { proto.setMember(vehicleMember); switch(interactType){ - case VEHICLE_INTERACT_IN -> { + case VEHICLE_INTERACT_TYPE_IN -> { ((EntityVehicle) vehicle).getVehicleMembers().add(vehicleMember); } - case VEHICLE_INTERACT_OUT -> { + case VEHICLE_INTERACT_TYPE_OUT -> { ((EntityVehicle) vehicle).getVehicleMembers().remove(vehicleMember); } default -> {} @@ -53,10 +53,10 @@ public class PacketVehicleInteractRsp extends BasePacket { proto.setMember(vehicleMember); switch(interactType){ - case VEHICLE_INTERACT_IN -> { + case VEHICLE_INTERACT_TYPE_IN -> { vehicle.getVehicleMembers().add(vehicleMember); } - case VEHICLE_INTERACT_OUT -> { + case VEHICLE_INTERACT_TYPE_OUT -> { vehicle.getVehicleMembers().remove(vehicleMember); } default -> {} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java new file mode 100644 index 000000000..0a6a315e3 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleStaminaNotify.java @@ -0,0 +1,18 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.VehicleStaminaNotifyOuterClass.VehicleStaminaNotify; + +public class PacketVehicleStaminaNotify extends BasePacket { + + public PacketVehicleStaminaNotify(int vehicleId, float newStamina) { + super(PacketOpcodes.VehicleStaminaNotify); + VehicleStaminaNotify.Builder proto = VehicleStaminaNotify.newBuilder(); + + proto.setEntityId(vehicleId); + proto.setCurStamina(newStamina); + + this.setData(proto.build()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java new file mode 100644 index 000000000..a73187020 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetCoolDownNotify.java @@ -0,0 +1,25 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetCoolDownDataOuterClass; +import emu.grasscutter.net.proto.WidgetCoolDownNotifyOuterClass; + +public class PacketWidgetCoolDownNotify extends BasePacket { + + public PacketWidgetCoolDownNotify(int id, long coolDownTime, boolean isSuccess) { + super(PacketOpcodes.WidgetCoolDownNotify); + + WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify proto = WidgetCoolDownNotifyOuterClass.WidgetCoolDownNotify.newBuilder() + .addGroupCoolDownDataList( + WidgetCoolDownDataOuterClass.WidgetCoolDownData.newBuilder() + .setId(id) + .setCoolDownTime(coolDownTime) + .setIsSuccess(isSuccess) + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java new file mode 100644 index 000000000..7ce5065ea --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetDoBagRsp.java @@ -0,0 +1,28 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetDoBagRspOuterClass; + +public class PacketWidgetDoBagRsp extends BasePacket { + + public PacketWidgetDoBagRsp(int materialId) { + super(PacketOpcodes.WidgetDoBagRsp); + + WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder() + .setMaterialId(materialId) + .setRetcode(0) + .build(); + + this.setData(proto); + } + + public PacketWidgetDoBagRsp() { + super(PacketOpcodes.WidgetDoBagRsp); + + WidgetDoBagRspOuterClass.WidgetDoBagRsp proto = WidgetDoBagRspOuterClass.WidgetDoBagRsp.newBuilder() + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetAllDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetAllDataNotify.java new file mode 100644 index 000000000..b0000efb7 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetAllDataNotify.java @@ -0,0 +1,16 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetGadgetAllDataNotifyOuterClass.WidgetGadgetAllDataNotify; + +public class PacketWidgetGadgetAllDataNotify extends BasePacket { + + public PacketWidgetGadgetAllDataNotify() { + super(PacketOpcodes.AllWidgetDataNotify); + + WidgetGadgetAllDataNotify proto = WidgetGadgetAllDataNotify.newBuilder().build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java new file mode 100644 index 000000000..f94c6c10e --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetGadgetDataNotify.java @@ -0,0 +1,26 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetGadgetDataNotifyOuterClass; +import emu.grasscutter.net.proto.WidgetGadgetDataOuterClass; + +import java.io.IOException; +import java.util.List; + +public class PacketWidgetGadgetDataNotify extends BasePacket { + public PacketWidgetGadgetDataNotify(int gadgetId, List gadgetEntityIdList) throws IOException { + super(PacketOpcodes.WidgetGadgetDataNotify); + + WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify proto = WidgetGadgetDataNotifyOuterClass.WidgetGadgetDataNotify.newBuilder() + .setWidgetGadgetData( + WidgetGadgetDataOuterClass.WidgetGadgetData.newBuilder() + .setGadgetId(gadgetId) + .addAllGadgetEntityIdList(gadgetEntityIdList) + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java new file mode 100644 index 000000000..ab0ace7eb --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWidgetSlotChangeNotify.java @@ -0,0 +1,47 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.WidgetSlotChangeNotifyOuterClass; +import emu.grasscutter.net.proto.WidgetSlotDataOuterClass; +import emu.grasscutter.net.proto.WidgetSlotOpOuterClass; + +public class PacketWidgetSlotChangeNotify extends BasePacket { + + public PacketWidgetSlotChangeNotify(WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + this.setData(proto); + } + + public PacketWidgetSlotChangeNotify(WidgetSlotOpOuterClass.WidgetSlotOp op) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() + .setOp(op) + .setSlot( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .build() + ) + .build(); + + this.setData(proto); + } + + public PacketWidgetSlotChangeNotify(int materialId) { + super(PacketOpcodes.WidgetSlotChangeNotify); + + WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify proto = WidgetSlotChangeNotifyOuterClass.WidgetSlotChangeNotify.newBuilder() + .setSlot( + WidgetSlotDataOuterClass.WidgetSlotData.newBuilder() + .setIsActive(true) + .setMaterialId(materialId) + .build() + ) + .build(); + + this.setData(proto); + } + +} diff --git a/src/main/java/emu/grasscutter/task/Task.java b/src/main/java/emu/grasscutter/task/Task.java index 1f35d16ce..2c930c0e3 100644 --- a/src/main/java/emu/grasscutter/task/Task.java +++ b/src/main/java/emu/grasscutter/task/Task.java @@ -1,7 +1,5 @@ package emu.grasscutter.task; -import org.quartz.JobDataMap; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/src/main/java/emu/grasscutter/task/TaskMap.java b/src/main/java/emu/grasscutter/task/TaskMap.java index fe067e795..a4b2ff02f 100644 --- a/src/main/java/emu/grasscutter/task/TaskMap.java +++ b/src/main/java/emu/grasscutter/task/TaskMap.java @@ -67,6 +67,40 @@ public final class TaskMap { return this; } + public boolean pauseTask(String taskName) { + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.pauseJob(new JobKey(taskName)); + } catch (SchedulerException e) { + e.printStackTrace(); + return false; + } + return true; + } + + public boolean resumeTask(String taskName) { + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + scheduler.resumeJob(new JobKey(taskName)); + } catch (SchedulerException e) { + e.printStackTrace(); + return false; + } + return true; + } + + public boolean cancelTask(String taskName) { + Task task = this.annotations.get(taskName); + if (task == null) return false; + try { + this.unregisterTask(this.tasks.get(taskName)); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + public TaskMap registerTask(String taskName, TaskHandler task) { Task annotation = task.getClass().getAnnotation(Task.class); this.annotations.put(taskName, annotation); @@ -116,7 +150,7 @@ public final class TaskMap { classes.forEach(annotated -> { try { Task taskData = annotated.getAnnotation(Task.class); - Object object = annotated.newInstance(); + Object object = annotated.getDeclaredConstructor().newInstance(); if (object instanceof TaskHandler) { this.registerTask(taskData.taskName(), (TaskHandler) object); if (taskData.executeImmediatelyAfterReset()) { diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index d9923a656..1a1ac2196 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -1,12 +1,8 @@ package emu.grasscutter.tools; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.FilenameFilter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; @@ -14,7 +10,6 @@ import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; -import java.util.stream.Collectors; import com.google.gson.reflect.TypeToken; @@ -24,12 +19,17 @@ import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandMap; import emu.grasscutter.data.GameData; import emu.grasscutter.data.ResourceLoader; -import emu.grasscutter.data.def.AvatarData; -import emu.grasscutter.data.def.ItemData; -import emu.grasscutter.data.def.MonsterData; -import emu.grasscutter.data.def.SceneData; +import emu.grasscutter.data.binout.MainQuestData; +import emu.grasscutter.data.excels.AvatarData; +import emu.grasscutter.data.excels.ItemData; +import emu.grasscutter.data.excels.MonsterData; +import emu.grasscutter.data.excels.QuestData; +import emu.grasscutter.data.excels.SceneData; import emu.grasscutter.utils.Utils; +import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; + public final class Tools { public static void createGmHandbook() throws Exception { ToolsWithLanguageOption.createGmHandbook(getLanguageOption()); @@ -39,50 +39,45 @@ public final class Tools { ToolsWithLanguageOption.createGachaMapping(location, getLanguageOption()); } - public static List getAvailableLanguage() throws Exception { - File textMapFolder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap"); - List availableLangList = new ArrayList(); - for (String textMapFileName : textMapFolder.list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - if (name.startsWith("TextMap") && name.endsWith(".json")){ - return true; - } - return false; - } - })) { - availableLangList.add(textMapFileName.replace("TextMap","").replace(".json","").toLowerCase()); - } - return availableLangList; + public static List getAvailableLanguage() { + File textMapFolder = new File(RESOURCE("TextMap")); + List availableLangList = new ArrayList<>(); + for (String textMapFileName : Objects.requireNonNull(textMapFolder.list((dir, name) -> name.startsWith("TextMap") && name.endsWith(".json")))) { + availableLangList.add(textMapFileName.replace("TextMap", "").replace(".json", "").toLowerCase()); + } return availableLangList; } - public static String getLanguageOption() throws Exception { + public static String getLanguageOption() { List availableLangList = getAvailableLanguage(); // Use system out for better format if (availableLangList.size() == 1) { return availableLangList.get(0).toUpperCase(); } - String stagedMessage = ""; - stagedMessage += "The following languages mappings are available, please select one: [default: EN]\n"; - String groupedLangList = ">\t"; + StringBuilder stagedMessage = new StringBuilder(); + stagedMessage.append("The following languages mappings are available, please select one: [default: EN] \n"); + + StringBuilder groupedLangList = new StringBuilder(">\t"); String input; int groupedLangCount = 0; - String input = ""; + for (String availableLanguage: availableLangList){ groupedLangCount++; - groupedLangList = groupedLangList + "" + availableLanguage + "\t"; + groupedLangList.append(availableLanguage).append("\t"); + if (groupedLangCount == 6) { - stagedMessage += groupedLangList + "\n"; + stagedMessage.append(groupedLangList).append("\n"); groupedLangCount = 0; - groupedLangList = ">\t"; + groupedLangList = new StringBuilder(">\t"); } } - if (groupedLangCount > 0) { - stagedMessage += groupedLangList + "\n"; - } - stagedMessage += "\nYour choice:[EN] "; - input = Grasscutter.getConsole().readLine(stagedMessage); + if (groupedLangCount > 0) { + stagedMessage.append(groupedLangList).append("\n"); + } + + stagedMessage.append("\nYour choice:[EN] "); + + input = Grasscutter.getConsole().readLine(stagedMessage.toString()); if (availableLangList.contains(input.toLowerCase())) { return input.toUpperCase(); } @@ -95,10 +90,10 @@ public final class Tools { final class ToolsWithLanguageOption { @SuppressWarnings("deprecation") public static void createGmHandbook(String language) throws Exception { - ResourceLoader.loadResources(); + ResourceLoader.loadAll(); Map map; - try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) { + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(RESOURCE("TextMap/TextMap"+language+".json"))), StandardCharsets.UTF_8)) { map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken>() {}.getType()); } @@ -116,13 +111,12 @@ final class ToolsWithLanguageOption { writer.println("// Commands"); for (Command cmd : cmdList) { - String cmdName = cmd.label(); + StringBuilder cmdName = new StringBuilder(cmd.label()); while (cmdName.length() <= 15) { - cmdName = " " + cmdName; + cmdName.insert(0, " "); } - writer.println(cmdName + " : " + cmd.description()); + writer.println(cmdName + " : " + translate(cmd.description())); } - writer.println(); list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); @@ -158,6 +152,18 @@ final class ToolsWithLanguageOption { writer.println(); + writer.println("// Quests"); + list = new ArrayList<>(GameData.getQuestDataMap().keySet()); + Collections.sort(list); + + for (Integer id : list) { + QuestData data = GameData.getQuestDataMap().get(id); + MainQuestData mainQuest = GameData.getMainQuestDataMap().get(data.getMainId()); + writer.println(data.getId() + " : " + map.get(mainQuest.getTitleTextMapHash()) + " - " + map.get(data.getDescTextMapHash())); + } + + writer.println(); + writer.println("// Monsters"); list = new ArrayList<>(GameData.getMonsterDataMap().keySet()); Collections.sort(list); @@ -176,16 +182,13 @@ final class ToolsWithLanguageOption { ResourceLoader.loadResources(); Map map; - try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8)) { + try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(RESOURCE("TextMap/TextMap" + language + ".json"))), StandardCharsets.UTF_8)) { map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken>() {}.getType()); } List list; - String fileName = location; - - try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8), false)) { - + try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(location), StandardCharsets.UTF_8), false)) { list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); Collections.sort(list); @@ -207,18 +210,11 @@ final class ToolsWithLanguageOption { } else { writer.print(","); } - String color; - switch (data.getQualityType()){ - case "QUALITY_PURPLE": - color = "purple"; - break; - case "QUALITY_ORANGE": - color = "yellow"; - break; - case "QUALITY_BLUE": - default: - color = "blue"; - } + String color = switch (data.getQualityType()) { + case "QUALITY_PURPLE" -> "purple"; + case "QUALITY_ORANGE" -> "yellow"; + default -> "blue"; + }; // Got the magic number 4233146695 from manually search in the json file writer.println( "\"" + (avatarID % 1000 + 1000) + "\" : [\"" diff --git a/src/main/java/emu/grasscutter/utils/ConfigContainer.java b/src/main/java/emu/grasscutter/utils/ConfigContainer.java new file mode 100644 index 000000000..a61f5f42e --- /dev/null +++ b/src/main/java/emu/grasscutter/utils/ConfigContainer.java @@ -0,0 +1,259 @@ +package emu.grasscutter.utils; + +import com.google.gson.JsonObject; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.Grasscutter.ServerDebugMode; +import emu.grasscutter.Grasscutter.ServerRunMode; + +import java.io.FileReader; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Locale; + +import static emu.grasscutter.Grasscutter.config; + +/** + * *when your JVM fails* + */ +public class ConfigContainer { + private static int version() { + return 3; + } + + /** + * Attempts to update the server's existing configuration to the latest + */ + public static void updateConfig() { + try { // Check if the server is using a legacy config. + JsonObject configObject = Grasscutter.getGsonFactory() + .fromJson(new FileReader(Grasscutter.configFile), JsonObject.class); + if(!configObject.has("version")) { + Grasscutter.getLogger().info("Updating legacy .."); + Grasscutter.saveConfig(null); + } + } catch (Exception ignored) { } + + var existing = config.version; + var latest = version(); + + if(existing == latest) + return; + + // Create a new configuration instance. + ConfigContainer updated = new ConfigContainer(); + // Update all configuration fields. + Field[] fields = ConfigContainer.class.getDeclaredFields(); + Arrays.stream(fields).forEach(field -> { + try { + field.set(updated, field.get(config)); + } catch (Exception exception) { + Grasscutter.getLogger().error("Failed to update a configuration field.", exception); + } + }); updated.version = version(); + + try { // Save configuration & reload. + Grasscutter.saveConfig(updated); + Grasscutter.loadConfig(); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to inject the updated ", exception); + } + } + + public Structure folderStructure = new Structure(); + public Database databaseInfo = new Database(); + public Language language = new Language(); + public Account account = new Account(); + public Server server = new Server(); + + // DO NOT. TOUCH. THE VERSION NUMBER. + public int version = version(); + + /* Option containers. */ + + public static class Database { + public DataStore server = new DataStore(); + public DataStore game = new DataStore(); + + public static class DataStore { + public String connectionUri = "mongodb://localhost:27017"; + public String collection = "grasscutter"; + } + } + + public static class Structure { + public String resources = "./resources/"; + public String data = "./data/"; + public String packets = "./packets/"; + public String scripts = "./resources/Scripts/"; + public String plugins = "./plugins/"; + + // UNUSED (potentially added later?) + // public String dumps = "./dumps/"; + } + + public static class Server { + public ServerDebugMode debugLevel = ServerDebugMode.NONE; + public ServerRunMode runMode = ServerRunMode.HYBRID; + + public HTTP http = new HTTP(); + public Game game = new Game(); + + public Dispatch dispatch = new Dispatch(); + } + + public static class Language { + public Locale language = Locale.getDefault(); + public Locale fallback = Locale.US; + public String document = "EN"; + } + + public static class Account { + public boolean autoCreate = false; + public String[] defaultPermissions = {}; + public int maxPlayer = -1; + } + + /* Server options. */ + + public static class HTTP { + public String bindAddress = "0.0.0.0"; + /* This is the address used in URLs. */ + public String accessAddress = "127.0.0.1"; + + public int bindPort = 443; + /* This is the port used in URLs. */ + public int accessPort = 0; + + public Encryption encryption = new Encryption(); + public Policies policies = new Policies(); + public Files files = new Files(); + } + + public static class Game { + public String bindAddress = "0.0.0.0"; + /* This is the address used in the default region. */ + public String accessAddress = "127.0.0.1"; + + public int bindPort = 22102; + /* This is the port used in the default region. */ + public int accessPort = 0; + public boolean enableConsole = true; + public GameOptions gameOptions = new GameOptions(); + public JoinOptions joinOptions = new JoinOptions(); + public ConsoleAccount serverAccount = new ConsoleAccount(); + } + + /* Data containers. */ + + public static class Dispatch { + public Region[] regions = {}; + + public String defaultName = "Grasscutter"; + } + + public static class Encryption { + public boolean useEncryption = true; + /* Should 'https' be appended to URLs? */ + public boolean useInRouting = true; + public String keystore = "./keystore.p12"; + public String keystorePassword = "123456"; + } + + public static class Policies { + public Policies.CORS cors = new Policies.CORS(); + + public static class CORS { + public boolean enabled = false; + public String[] allowedOrigins = new String[]{"*"}; + } + } + + public static class GameOptions { + public InventoryLimits inventoryLimits = new InventoryLimits(); + public AvatarLimits avatarLimits = new AvatarLimits(); + public int sceneEntityLimit = 1000; // Unenforced. TODO: Implement. + + public boolean watchGachaConfig = false; + public boolean enableShopItems = true; + public boolean staminaUsage = true; + public boolean energyUsage = false; + public Rates rates = new Rates(); + + public static class InventoryLimits { + public int weapons = 2000; + public int relics = 2000; + public int materials = 2000; + public int furniture = 2000; + public int all = 30000; + } + + public static class AvatarLimits { + public int singlePlayerTeam = 4; + public int multiplayerTeam = 4; + } + + public static class Rates { + public float adventureExp = 1.0f; + public float mora = 1.0f; + public float leyLines = 1.0f; + } + } + + public static class JoinOptions { + public int[] welcomeEmotes = {2007, 1002, 4010}; + public String welcomeMessage = "Welcome to a Grasscutter server."; + public JoinOptions.Mail welcomeMail = new JoinOptions.Mail(); + + public static class Mail { + public String title = "Welcome to Grasscutter!"; + public String content = """ + Hi there!\r + First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r + \r + Check out our:\r + + """; + public String sender = "Lawnmower"; + public emu.grasscutter.game.mail.Mail.MailItem[] items = { + new emu.grasscutter.game.mail.Mail.MailItem(13509, 1, 1), + new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1) + }; + } + } + + public static class ConsoleAccount { + public int avatarId = 10000007; + public int nameCardId = 210001; + public int adventureRank = 1; + public int worldLevel = 0; + + public String nickName = "Server"; + public String signature = "Welcome to Grasscutter!"; + } + + public static class Files { + public String indexFile = "./index.html"; + public String errorFile = "./404.html"; + } + + /* Objects. */ + + public static class Region { + public Region() { } + + public Region( + String name, String title, + String address, int port + ) { + this.Name = name; + this.Title = title; + this.Ip = address; + this.Port = port; + } + + public String Name = "os_usa"; + public String Title = "Grasscutter"; + public String Ip = "127.0.0.1"; + public int Port = 22102; + } +} diff --git a/src/main/java/emu/grasscutter/utils/Crypto.java b/src/main/java/emu/grasscutter/utils/Crypto.java index e6d260e94..3bde63aa7 100644 --- a/src/main/java/emu/grasscutter/utils/Crypto.java +++ b/src/main/java/emu/grasscutter/utils/Crypto.java @@ -7,18 +7,24 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp; import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp; +import static emu.grasscutter.Configuration.*; + public final class Crypto { private static final SecureRandom secureRandom = new SecureRandom(); - public static final long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968"); - public static byte[] ENCRYPT_SEED_BUFFER = new byte[0]; public static byte[] DISPATCH_KEY; + public static byte[] DISPATCH_SEED; + public static byte[] ENCRYPT_KEY; + public static long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968"); + public static byte[] ENCRYPT_SEED_BUFFER = new byte[0]; public static void loadKeys() { - DISPATCH_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchKey.bin"); - ENCRYPT_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKey.bin"); - ENCRYPT_SEED_BUFFER = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin"); + DISPATCH_KEY = FileUtils.readResource("/keys/dispatchKey.bin"); + DISPATCH_SEED = FileUtils.readResource("/keys/dispatchSeed.bin"); + + ENCRYPT_KEY = FileUtils.readResource("/keys/secretKey.bin"); + ENCRYPT_SEED_BUFFER = FileUtils.readResource("/keys/secretKeyBuffer.bin"); } public static void xor(byte[] packet, byte[] key) { @@ -31,28 +37,9 @@ public final class Crypto { } } - public static void extractSecretKeyBuffer(byte[] data) { - try { - GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data); - FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin", p.getSecretKeyBytes().toByteArray()); - Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey()); - } catch (Exception e) { - Grasscutter.getLogger().error("Crypto error.", e); - } - } - - public static void extractDispatchSeed(String data) { - try { - QueryCurrRegionHttpRsp p = QueryCurrRegionHttpRsp.parseFrom(Base64.getDecoder().decode(data)); - FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin", p.getRegionInfo().getSecretKey().toByteArray()); - } catch (Exception e) { - Grasscutter.getLogger().error("Crypto error.", e); - } - } - public static byte[] createSessionKey(int length) { byte[] bytes = new byte[length]; secureRandom.nextBytes(bytes); - return bytes; + return bytes; } } diff --git a/src/main/java/emu/grasscutter/utils/DateHelper.java b/src/main/java/emu/grasscutter/utils/DateHelper.java index 7005d9457..1f1393760 100644 --- a/src/main/java/emu/grasscutter/utils/DateHelper.java +++ b/src/main/java/emu/grasscutter/utils/DateHelper.java @@ -1,7 +1,7 @@ package emu.grasscutter.utils; -import java.util.Date; import java.util.Calendar; +import java.util.Date; public final class DateHelper { public static Date onlyYearMonthDay(Date now) { @@ -13,4 +13,8 @@ public final class DateHelper { calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } + + public static int getUnixTime(Date localDateTime){ + return (int)(localDateTime.getTime() / 1000L); + } } diff --git a/src/main/java/emu/grasscutter/utils/FileUtils.java b/src/main/java/emu/grasscutter/utils/FileUtils.java index 06e6087b3..ae0be71ca 100644 --- a/src/main/java/emu/grasscutter/utils/FileUtils.java +++ b/src/main/java/emu/grasscutter/utils/FileUtils.java @@ -4,9 +4,15 @@ import emu.grasscutter.Grasscutter; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; public final class FileUtils { public static void write(String dest, byte[] bytes) { @@ -32,10 +38,34 @@ public final class FileUtils { return new byte[0]; } + + public static InputStream readResourceAsStream(String resourcePath) { + return Grasscutter.class.getResourceAsStream(resourcePath); + } + + public static byte[] readResource(String resourcePath) { + try (InputStream is = Grasscutter.class.getResourceAsStream(resourcePath)) { + return is.readAllBytes(); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to read resource: " + resourcePath); + exception.printStackTrace(); + } + + return new byte[0]; + } public static byte[] read(File file) { return read(file.getPath()); } + + public static void copyResource(String resourcePath, String destination) { + try { + byte[] resource = FileUtils.readResource(resourcePath); + FileUtils.write(destination, resource); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to copy resource: " + resourcePath + "\n" + exception); + } + } public static String getFilenameWithoutPath(String fileName) { if (fileName.indexOf(".") > 0) { @@ -44,4 +74,43 @@ public final class FileUtils { return fileName; } } + + // From https://mkyong.com/java/java-read-a-file-from-resources-folder/ + public static List getPathsFromResource(String folder) throws URISyntaxException { + List result = null; + + // Get pathUri of the current running JAR + URI pathUri = Grasscutter.class.getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI(); + + try { + // file walks JAR + URI uri = URI.create("jar:file:" + pathUri.getRawPath()); + try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) { + result = Files.walk(fs.getPath(folder)) + .filter(Files::isRegularFile) + .collect(Collectors.toList()); + } + } catch (Exception e) { + // Eclipse puts resources in its bin folder + File f = new File(System.getProperty("user.dir") + folder); + + if (!f.exists() || f.listFiles().length == 0) { + return null; + } + + result = Arrays.stream(f.listFiles()).map(File::toPath).toList(); + } + + return result; + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static String readToString(InputStream file) throws IOException { + byte[] content = file.readAllBytes(); + + return new String(content, StandardCharsets.UTF_8); + } } diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index 70e32e658..c343e949e 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -3,15 +3,21 @@ package emu.grasscutter.utils; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import emu.grasscutter.Grasscutter; +import emu.grasscutter.game.player.Player; import javax.annotation.Nullable; import java.io.InputStream; -import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.Map; +import static emu.grasscutter.Configuration.*; + public final class Language { + private static final Map cachedLanguages = new ConcurrentHashMap<>(); + private final JsonObject languageData; - private final Map cachedTranslations = new HashMap<>(); + private final String languageCode; + private final Map cachedTranslations = new ConcurrentHashMap<>(); /** * Creates a language instance from a code. @@ -19,7 +25,24 @@ public final class Language { * @return A language instance. */ public static Language getLanguage(String langCode) { - return new Language(langCode + ".json", Grasscutter.getConfig().DefaultLanguage.toLanguageTag() + ".json"); + if (cachedLanguages.containsKey(langCode)) { + return cachedLanguages.get(langCode); + } + + var fallbackLanguageCode = Utils.getLanguageCode(FALLBACK_LANGUAGE); + var description = getLanguageFileDescription(langCode, fallbackLanguageCode); + var actualLanguageCode = description.getLanguageCode(); + + Language languageInst; + if (description.getLanguageFile() != null) { + languageInst = new Language(description); + cachedLanguages.put(actualLanguageCode, languageInst); + } else { + languageInst = cachedLanguages.get(actualLanguageCode); + cachedLanguages.put(langCode, languageInst); + } + + return languageInst; } /** @@ -40,33 +63,89 @@ public final class Language { } /** - * Reads a file and creates a language instance. - * @param fileName The name of the language file. + * Returns the translated value from the key while substituting arguments. + * @param player Target player + * @param key The key of the translated value to return. + * @param args The arguments to substitute. + * @return A translated value with arguments substituted. */ - private Language(String fileName, String fallback) { - @Nullable JsonObject languageData = null; + public static String translate(Player player, String key, Object... args) { + if (player == null) { + return translate(key, args); + } - InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName); - if (file == null) { // Provided fallback language. - file = Grasscutter.class.getResourceAsStream("/languages/" + fallback); - Grasscutter.getLogger().warn("Failed to load language file: " + fileName + ", falling back to: " + fallback); - } - if(file == null) { // Fallback the fallback language. - file = Grasscutter.class.getResourceAsStream("/languages/en-US.json"); - Grasscutter.getLogger().warn("Failed to load language file: " + fallback + ", falling back to: en-US.json"); - } - if(file == null) - throw new RuntimeException("Unable to load the primary, fallback, and 'en-US' language files."); + var langCode = Utils.getLanguageCode(player.getAccount().getLocale()); + String translated = Grasscutter.getLanguage(langCode).get(key); try { - languageData = Grasscutter.getGsonFactory().fromJson(Utils.readFromInputStream(file), JsonObject.class); + return translated.formatted(args); } catch (Exception exception) { - Grasscutter.getLogger().warn("Failed to load language file: " + fileName, exception); + Grasscutter.getLogger().error("Failed to format string: " + key, exception); + return translated; + } + } + + /** + * get language code + */ + public String getLanguageCode() { + return languageCode; + } + + /** + * Reads a file and creates a language instance. + */ + private Language(LanguageStreamDescription description) { + @Nullable JsonObject languageData = null; + languageCode = description.getLanguageCode(); + + try { + languageData = Grasscutter.getGsonFactory().fromJson(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class); + } catch (Exception exception) { + Grasscutter.getLogger().warn("Failed to load language file: " + description.getLanguageCode(), exception); } this.languageData = languageData; } + /** + * create a LanguageStreamDescription + * @param languageCode The name of the language code. + * @param fallbackLanguageCode The name of the fallback language code. + */ + private static LanguageStreamDescription getLanguageFileDescription(String languageCode, String fallbackLanguageCode) { + var fileName = languageCode + ".json"; + var fallback = fallbackLanguageCode + ".json"; + + String actualLanguageCode = languageCode; + InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName); + + if (file == null) { // Provided fallback language. + Grasscutter.getLogger().warn("Failed to load language file: " + fileName + ", falling back to: " + fallback); + actualLanguageCode = fallbackLanguageCode; + if (cachedLanguages.containsKey(actualLanguageCode)) { + return new LanguageStreamDescription(actualLanguageCode, null); + } + + file = Grasscutter.class.getResourceAsStream("/languages/" + fallback); + } + + if(file == null) { // Fallback the fallback language. + Grasscutter.getLogger().warn("Failed to load language file: " + fallback + ", falling back to: en-US.json"); + actualLanguageCode = "en-US"; + if (cachedLanguages.containsKey(actualLanguageCode)) { + return new LanguageStreamDescription(actualLanguageCode, null); + } + + file = Grasscutter.class.getResourceAsStream("/languages/en-US.json"); + } + + if(file == null) + throw new RuntimeException("Unable to load the primary, fallback, and 'en-US' language files."); + + return new LanguageStreamDescription(actualLanguageCode, file); + } + /** * Returns the value (as a string) from a nested key. * @param key The key to look for. @@ -81,7 +160,9 @@ public final class Language { JsonObject object = this.languageData; int index = 0; - String result = "This value does not exist. Please report this to the Discord: " + key; + String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: "; + String result = valueNotFoundPattern + key; + boolean isValueFound = false; while (true) { if(index == keys.length) break; @@ -92,11 +173,37 @@ public final class Language { if(element.isJsonObject()) object = element.getAsJsonObject(); else { + isValueFound = true; result = element.getAsString(); break; } } else break; } + + if (!isValueFound && !languageCode.equals("en-US")) { + var englishValue = Grasscutter.getLanguage("en-US").get(key); + if (!englishValue.contains(valueNotFoundPattern)) { + result += "\nhere is english version:\n" + englishValue; + } + } this.cachedTranslations.put(key, result); return result; } + + private static class LanguageStreamDescription { + private final String languageCode; + private final InputStream languageFile; + + public LanguageStreamDescription(String languageCode, InputStream languageFile) { + this.languageCode = languageCode; + this.languageFile = languageFile; + } + + public String getLanguageCode() { + return languageCode; + } + + public InputStream getLanguageFile() { + return languageFile; + } + } } diff --git a/src/main/java/emu/grasscutter/utils/Position.java b/src/main/java/emu/grasscutter/utils/Position.java index f2ecb6915..b9b75e25b 100644 --- a/src/main/java/emu/grasscutter/utils/Position.java +++ b/src/main/java/emu/grasscutter/utils/Position.java @@ -2,6 +2,8 @@ package emu.grasscutter.utils; import java.io.Serializable; +import com.google.gson.annotations.SerializedName; + import dev.morphia.annotations.Entity; import emu.grasscutter.net.proto.VectorOuterClass.Vector; @@ -9,8 +11,13 @@ import emu.grasscutter.net.proto.VectorOuterClass.Vector; public class Position implements Serializable { private static final long serialVersionUID = -2001232313615923575L; + @SerializedName(value="x", alternate={"_x", "X"}) private float x; + + @SerializedName(value="y", alternate={"_y", "Y"}) private float y; + + @SerializedName(value="z", alternate={"_z", "Z"}) private float z; public Position() { diff --git a/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java b/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java new file mode 100644 index 000000000..a64ecd5ad --- /dev/null +++ b/src/main/java/emu/grasscutter/utils/ServerLogEventAppender.java @@ -0,0 +1,31 @@ +package emu.grasscutter.utils; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.encoder.Encoder; +import ch.qos.logback.core.spi.DeferredProcessingAware; +import ch.qos.logback.core.status.ErrorStatus; +import emu.grasscutter.server.event.internal.ServerLogEvent; +import emu.grasscutter.server.event.types.ServerEvent; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class ServerLogEventAppender extends AppenderBase { + protected Encoder encoder; + + @Override + protected void append(E event) { + byte[] byteArray = this.encoder.encode(event); + ServerLogEvent sle = new ServerLogEvent(ServerEvent.Type.GAME, (ILoggingEvent) event, new String(byteArray, StandardCharsets.UTF_8)); + sle.call(); + } + + public Encoder getEncoder() { + return encoder; + } + + public void setEncoder(Encoder encoder) { + this.encoder = encoder; + } +} diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index 6d11822f0..80449ea0f 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -6,18 +6,20 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.time.*; import java.time.temporal.TemporalAdjusters; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; +import java.util.*; -import emu.grasscutter.Config; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.DataLoader; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import org.slf4j.Logger; +import javax.annotation.Nullable; + import static emu.grasscutter.utils.Language.translate; @SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) @@ -172,12 +174,12 @@ public final class Utils { * Checks for required files and folders before startup. */ public static void startupCheck() { - Config config = Grasscutter.getConfig(); + ConfigContainer config = Grasscutter.getConfig(); Logger logger = Grasscutter.getLogger(); boolean exit = false; - String resourcesFolder = config.RESOURCE_FOLDER; - String dataFolder = config.DATA_FOLDER; + String resourcesFolder = config.folderStructure.resources; + String dataFolder = config.folderStructure.data; // Check for resources folder. if(!fileExists(resourcesFolder)) { @@ -197,6 +199,9 @@ public final class Utils { if(!fileExists(dataFolder)) createFolder(dataFolder); + // Make sure the data folder is populated, if there are any missing files copy them from resources + DataLoader.CheckAllFiles(); + if(exit) System.exit(1); } @@ -253,7 +258,9 @@ public final class Utils { * @param stream The input stream. * @return The string. */ - public static String readFromInputStream(InputStream stream) { + public static String readFromInputStream(@Nullable InputStream stream) { + if(stream == null) return "empty"; + StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { @@ -261,43 +268,113 @@ public final class Utils { } stream.close(); } catch (IOException e) { Grasscutter.getLogger().warn("Failed to read from input stream."); + } catch (NullPointerException ignored) { + return "empty"; } return stringBuilder.toString(); } /** - * Switch properties from upper case to lower case? + * Performs a linear interpolation using a table of fixed points to create an effective piecewise f(x) = y function. + * @param x + * @param xyArray Array of points in [[x0,y0], ... [xN, yN]] format + * @return f(x) = y */ - public static Map switchPropertiesUpperLowerCase(Map objMap, Class cls) { - Map map = new HashMap<>(objMap.size()); - for (String key : objMap.keySet()) { - try { - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') { - try { - cls.getDeclaredField(key); - map.put(key, objMap.get(key)); - } catch (NoSuchFieldException e) { - String s1 = String.valueOf(c).toUpperCase(); - String after = key.length() > 1 ? s1 + key.substring(1) : s1; - cls.getDeclaredField(after); - map.put(after, objMap.get(key)); - } - } else if (c >= 'A' && c <= 'Z') { - try { - cls.getDeclaredField(key); - map.put(key, objMap.get(key)); - } catch (NoSuchFieldException e) { - String s1 = String.valueOf(c).toLowerCase(); - String after = key.length() > 1 ? s1 + key.substring(1) : s1; - cls.getDeclaredField(after); - map.put(after, objMap.get(key)); - } + public static int lerp(int x, int[][] xyArray) { + try { + if (x <= xyArray[0][0]){ // Clamp to first point + return xyArray[0][1]; + } else if (x >= xyArray[xyArray.length-1][0]) { // Clamp to last point + return xyArray[xyArray.length-1][1]; + } + // At this point we're guaranteed to have two lerp points, and pity be somewhere between them. + for (int i=0; i < xyArray.length-1; i++) { + if (x == xyArray[i+1][0]) { + return xyArray[i+1][1]; } - } catch (NoSuchFieldException e) { - map.put(key, objMap.get(key)); + if (x < xyArray[i+1][0]) { + // We are between [i] and [i+1], interpolation time! + // Using floats would be slightly cleaner but we can just as easily use ints if we're careful with order of operations. + int position = x - xyArray[i][0]; + int fullDist = xyArray[i+1][0] - xyArray[i][0]; + int prevValue = xyArray[i][1]; + int fullDelta = xyArray[i+1][1] - prevValue; + return prevValue + ( (position * fullDelta) / fullDist ); + } + } + } catch (IndexOutOfBoundsException e) { + Grasscutter.getLogger().error("Malformed lerp point array. Must be of form [[x0, y0], ..., [xN, yN]]."); + } + return 0; + } + + /** + * Checks if an int is in an int[] + * @param key int to look for + * @param array int[] to look in + * @return key in array + */ + public static boolean intInArray(int key, int[] array) { + for (int i : array) { + if (i == key) { + return true; } } + return false; + } - return map; + /** + * Return a copy of minuend without any elements found in subtrahend. + * @param minuend The array we want elements from + * @param subtrahend The array whose elements we don't want + * @return The array with only the elements we want, in the order that minuend had them + */ + public static int[] setSubtract(int[] minuend, int[] subtrahend) { + IntList temp = new IntArrayList(); + for (int i : minuend) { + if (!intInArray(i, subtrahend)) { + temp.add(i); + } + } + return temp.toIntArray(); + } + + /** + * Gets the language code from a given locale. + * @param locale A locale. + * @return A string in the format of 'XX-XX'. + */ + public static String getLanguageCode(Locale locale) { + return String.format("%s-%s", locale.getLanguage(), locale.getCountry()); + } + + /** + * Base64 encodes a given byte array. + * @param toEncode An array of bytes. + * @return A base64 encoded string. + */ + public static String base64Encode(byte[] toEncode) { + return Base64.getEncoder().encodeToString(toEncode); + } + + /** + * Base64 decodes a given string. + * @param toDecode A base64 encoded string. + * @return An array of bytes. + */ + public static byte[] base64Decode(String toDecode) { + return Base64.getDecoder().decode(toDecode); + } + + /** + * Safely JSON decodes a given string. + * @param jsonData The JSON-encoded data. + * @return JSON decoded data, or null if an exception occurred. + */ + public static T jsonDecode(String jsonData, Class classType) { + try { + return Grasscutter.getGsonFactory().fromJson(jsonData, classType); + } catch (Exception ignored) { + return null; + } } } diff --git a/src/main/resources/defaults/data/Banners.json b/src/main/resources/defaults/data/Banners.json new file mode 100644 index 000000000..0242cae54 --- /dev/null +++ b/src/main/resources/defaults/data/Banners.json @@ -0,0 +1,71 @@ +[ + { + "gachaType": 200, + "scheduleId": 893, + "bannerType": "STANDARD", + "prefabPath": "GachaShowPanel_A022", + "previewPrefabPath": "UI_Tab_GachaShowPanel_A022", + "titlePath": "UI_GACHA_SHOW_PANEL_A022_TITLE", + "costItemId": 224, + "costItemAmount": 1, + "costItemAmount10": 10, + "beginTime": 0, + "endTime": 1924992000, + "sortId": 1000, + "fallbackItems4Pool1": [1006, 1014, 1015, 1020, 1021, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1064], + "weights4": [[1,510], [8,510], [10,10000]], + "weights5": [[1,75], [73,150], [90,10000]] + }, + { + "gachaType": 301, + "scheduleId": 903, + "bannerType": "EVENT", + "prefabPath": "GachaShowPanel_A081", + "previewPrefabPath": "UI_Tab_GachaShowPanel_A081", + "titlePath": "UI_GACHA_SHOW_PANEL_A081_TITLE", + "costItemId": 223, + "beginTime": 0, + "endTime": 1924992000, + "sortId": 9998, + "rateUpItems4": [1034, 1014, 1048], + "rateUpItems5": [1060], + "fallbackItems5Pool2": [], + "weights5": [[1,80], [73,80], [90,10000]] + }, + { + "gachaType": 400, + "scheduleId": 923, + "bannerType": "EVENT", + "prefabPath": "GachaShowPanel_A082", + "previewPrefabPath": "UI_Tab_GachaShowPanel_A082", + "titlePath": "UI_GACHA_SHOW_PANEL_A031_TITLE", + "costItemId": 223, + "beginTime": 0, + "endTime": 1924992000, + "sortId": 9998, + "rateUpItems4": [1034, 1014, 1048], + "rateUpItems5": [1026], + "fallbackItems5Pool2": [], + "weights5": [[1,80], [73,80], [90,10000]] + }, + { + "gachaType": 302, + "scheduleId": 913, + "bannerType": "WEAPON", + "prefabPath": "GachaShowPanel_A083", + "previewPrefabPath": "UI_Tab_GachaShowPanel_A083", + "titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE", + "costItemId": 223, + "beginTime": 0, + "endTime": 1924992000, + "sortId": 9997, + "eventChance": 75, + "softPity": 80, + "hardPity": 80, + "rateUpItems4": [11403, 12401, 13406, 14409, 15403], + "rateUpItems5": [15508, 13505], + "fallbackItems5Pool1": [], + "weights4": [[1,600], [7,600], [8, 6600], [10,12600]], + "weights5": [[1,100], [62,100], [73, 7800], [80,10000]] + } +] diff --git a/data/Drop.json b/src/main/resources/defaults/data/Drop.json similarity index 99% rename from data/Drop.json rename to src/main/resources/defaults/data/Drop.json index d1600aae2..9e002c95e 100644 --- a/data/Drop.json +++ b/src/main/resources/defaults/data/Drop.json @@ -1,4 +1,44 @@ [ + {"monsterId":28040101,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040102,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040103,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040104,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040105,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040106,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040107,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28040108,"dropDataList":[{"itemId":100084,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020301,"dropDataList":[{"itemId":100061,"minCount":2,"maxCount":2,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020302,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020101,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020102,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020103,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020104,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020105,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020106,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020701,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020702,"dropDataList":[{"itemId":100061,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020303,"dropDataList":[{"itemId":100094,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28020304,"dropDataList":[{"itemId":100094,"minCount":2,"maxCount":3,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030401,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030402,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030403,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030404,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030405,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030406,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030407,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030408,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030409,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030301,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030302,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030303,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030304,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030305,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030306,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030307,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030308,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030309,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030310,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, + {"monsterId":28030311,"dropDataList":[{"itemId":100064,"minCount":1,"maxCount":1,"minWeight":0,"maxWeight":10000}]}, { "monsterId": 21010101, "dropDataList": [ @@ -132754,21 +132794,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, @@ -132815,21 +132855,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, @@ -132876,21 +132916,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, @@ -132937,21 +132977,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, @@ -132998,21 +133038,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, @@ -133059,21 +133099,21 @@ "maxWeight": 1 }, { - "itemId": 112047, + "itemId": 112023, "minCount": 1, "maxCount": 3, "minWeight": 2000, "maxWeight": 6000 }, { - "itemId": 112048, + "itemId": 112024, "minCount": 1, "maxCount": 1, "minWeight": 8001, "maxWeight": 9500 }, { - "itemId": 112049, + "itemId": 112025, "minCount": 1, "maxCount": 1, "minWeight": 9501, diff --git a/src/main/resources/defaults/data/EnergyDrop.json b/src/main/resources/defaults/data/EnergyDrop.json new file mode 100644 index 000000000..6cd7e8d85 --- /dev/null +++ b/src/main/resources/defaults/data/EnergyDrop.json @@ -0,0 +1,185 @@ +[ + { + "dropId": 22010010, + "dropList": [ + { "ballId": 2024, "count": 1 } + ] + }, + { + "dropId": 22010030, + "dropList": [ + { "ballId": 2008, "count": 1 } + ] + }, + { + "dropId": 22010050, + "dropList": [ + { "ballId": 2024, "count": 3 }, + { "ballId": 2008, "count": 1 } + ] + }, + { + "dropId": 22010013, + "dropList": [ + { "ballId": 2019, "count": 1 } + ] + }, + { + "dropId": 22010033, + "dropList": [ + { "ballId": 2003, "count": 1 } + ] + }, + { + "dropId": 22010015, + "dropList": [ + { "ballId": 2021, "count": 1 } + ] + }, + { + "dropId": 22010035, + "dropList": [ + { "ballId": 2005, "count": 1 } + ] + }, + { + "dropId": 22010034, + "dropList": [ + { "ballId": 2004, "count": 1 } + ] + }, + { + "dropId": 22010037, + "dropList": [ + { "ballId": 2007, "count": 1 } + ] + }, + { + "dropId": 22010032, + "dropList": [ + { "ballId": 2002, "count": 1 } + ] + }, + { + "dropId": 22010022, + "dropList": [ + { "ballId": 2018, "count": 1 } + ] + }, + { + "dropId": 22010036, + "dropList": [ + { "ballId": 2006, "count": 1 } + ] + }, + { + "dropId": 22010026, + "dropList": [ + { "ballId": 2022, "count": 1 } + ] + }, + { + "dropId": 22010031, + "dropList": [ + { "ballId": 2001, "count": 1 } + ] + }, + + { + "dropId": 22010014, + "dropList": [ + { "ballId": 2020, "count": 1 } + ] + }, + { + "dropId": 22010016, + "dropList": [ + { "ballId": 2022, "count": 1 } + ] + }, + { + "dropId": 22010012, + "dropList": [ + { "ballId": 2018, "count": 1 } + ] + }, + { + "dropId": 22010024, + "dropList": [ + { "ballId": 2004, "count": 1 } + ] + }, + { + "dropId": 22010011, + "dropList": [ + { "ballId": 2017, "count": 1 } + ] + }, + { + "dropId": 22010017, + "dropList": [ + { "ballId": 2023, "count": 1 } + ] + }, + { + "dropId": 22010021, + "dropList": [ + { "ballId": 2017, "count": 1 } + ] + }, + { + "dropId": 22010027, + "dropList": [ + { "ballId": 2007, "count": 1 } + ] + }, + { + "dropId": 22010040, + "dropList": [ + { "ballId": 2024, "count": 1 }, + { "ballId": 2008, "count": 1 } + ] + }, + { + "dropId": 22010025, + "dropList": [ + { "ballId": 2021, "count": 2 } + ] + }, + { + "dropId": 22010020, + "dropList": [ + { "ballId": 2024, "count": 1 } + ] + }, + { + "dropId": 22003100, + "dropList": [ + ] + }, + { + "dropId": 22001000, + "dropList": [ + ] + }, + { + "dropId": 22000100, + "dropList": [ + ] + }, + { + "dropId": 22003000, + "dropList": [ + ] + }, + { + "dropId": 22001100, + "dropList": [ + ] + }, + { + "dropId": 22000000, + "dropList": [ + ] + } +] \ No newline at end of file diff --git a/data/ExpeditionReward.json b/src/main/resources/defaults/data/ExpeditionReward.json similarity index 100% rename from data/ExpeditionReward.json rename to src/main/resources/defaults/data/ExpeditionReward.json diff --git a/src/main/resources/defaults/data/GameAnnouncement.json b/src/main/resources/defaults/data/GameAnnouncement.json new file mode 100644 index 000000000..57cd72c8e --- /dev/null +++ b/src/main/resources/defaults/data/GameAnnouncement.json @@ -0,0 +1,22 @@ +{ + "t": "{{SYSTEM_TIME}}", + "list": [ + { + "ann_id": 1, + "title": "Welcome to Grasscutter!", + "subtitle": "Welcome!", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/1.jpg", + "content": "

Hi there!

First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you!


〓Discord〓

https://discord.gg/T5vZU6UyeG

〓GitHub〓https://github.com/Grasscutters/Grasscutter", + "lang": "en-US" + }, + { + "ann_id": 2, + "title": "How to use announcements", + "subtitle": "How to use announcements", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/2.jpg", + "content": "

Announcement content uses HTML. The specific content of the announcement is stored in the program directory GameAnnouncement.json, while GameAnnouncementList.json stores the announcement list data.

GameAnnouncement

ParameterDescription
ann_idUnique ID
titleTitle shown at the top of the content
subtitleShort title shown on the left
bannerImage to display between content and title
contentContent body in HTML
langLanguage code for this entry

GameAnnouncementList

If you want to add an announcement, please add the list data in the announcement type corresponding to GameAnnouncementList, and finally add the announcement content in GameAnnouncement.

", + "lang": "en-US" + } + ], + "total": 2 +} \ No newline at end of file diff --git a/src/main/resources/defaults/data/GameAnnouncementList.json b/src/main/resources/defaults/data/GameAnnouncementList.json new file mode 100644 index 000000000..3697703a3 --- /dev/null +++ b/src/main/resources/defaults/data/GameAnnouncementList.json @@ -0,0 +1,62 @@ +{ + "t": "{{SYSTEM_TIME}}", + "list": [ + { + "list": [ + { + "ann_id": 1, + "title": "Welcome to Grasscutter!", + "subtitle": "Welcome!", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/1.jpg", + "tag_icon": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/tag_icon.png", + "type": 2, + "type_label": "System", + "lang": "en-US", + "start_time": "2020-09-25 04:05:30", + "end_time": "2030-10-30 11:00:00", + "content": "", + "has_content": true + }, + { + "ann_id": 2, + "title": "How to use announcements", + "subtitle": "How to use announcements", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/2.jpg", + "tag_icon": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/tag_icon.png", + "type": 2, + "type_label": "System", + "lang": "en-US", + "start_time": "2020-09-25 04:05:30", + "end_time": "2030-10-30 11:00:00", + "content": "", + "has_content": true + } + ], + "type_id": 2, + "type_label": "System" + }, + { + "list": [ + {} + ], + "type_id": 3, + "type_label": "Events" + } + ], + "total": 2, + "type_list": [ + { + "id": 2, + "name": "游戏系统公告", + "mi18n_name": "System" + }, + { + "id": 1, + "name": "活动公告", + "mi18n_name": "Activity" + } + ], + "timezone": -5, + "alert": false, + "alert_id": 0 +} \ No newline at end of file diff --git a/data/Shop.json b/src/main/resources/defaults/data/Shop.json similarity index 77% rename from data/Shop.json rename to src/main/resources/defaults/data/Shop.json index 9670b0bfc..0d7c37fc1 100644 --- a/data/Shop.json +++ b/src/main/resources/defaults/data/Shop.json @@ -5,8 +5,8 @@ { "goodsId": 1004202, "goodsItem": { - "Id": 202, - "Count": 1000000 + "id": 202, + "count": 1000000 }, "scoin": 1, "buyLimit": 500, @@ -16,17 +16,18 @@ "maxLevel": 99, "costItemList": [ { - "Id": 223, - "Count": 100 + "id": 223, + "count": 100 } ] }, { "goodsId": 10048006, "goodsItem": { - "Id": 108006, - "Count": 20 + "id": 108006, + "count": 20 }, + "costItemList": [], "scoin": 100, "hcoin": 100, "mcoin": 100, @@ -39,9 +40,10 @@ { "goodsId": 10048033, "goodsItem": { - "Id": 108033, - "Count": 20 + "id": 108033, + "count": 20 }, + "costItemList": [], "scoin": 1, "buyLimit": 50000, "beginTime": 1575129600, diff --git a/data/ShopChest.json b/src/main/resources/defaults/data/ShopChest.json similarity index 100% rename from data/ShopChest.json rename to src/main/resources/defaults/data/ShopChest.json diff --git a/data/ShopChestBatchUse.json b/src/main/resources/defaults/data/ShopChestBatchUse.json similarity index 100% rename from data/ShopChestBatchUse.json rename to src/main/resources/defaults/data/ShopChestBatchUse.json diff --git a/src/main/resources/defaults/data/SkillParticleGeneration.json b/src/main/resources/defaults/data/SkillParticleGeneration.json new file mode 100644 index 000000000..f6610ac88 --- /dev/null +++ b/src/main/resources/defaults/data/SkillParticleGeneration.json @@ -0,0 +1,576 @@ +[ + { + "avatarId": 10000002, + "name": "Kamisato Ayaka", + "amountList": [ + { + "value": 4, + "chance": 50 + }, + { + "value": 5, + "chance": 50 + } + ] + }, + { + "avatarId": 10000003, + "name": "Jean", + "amountList": [ + { + "value": 2, + "chance": 33 + }, + { + "value": 3, + "chance": 67 + } + ] + }, + { + "avatarId": 10000005, + "name": "Traveler", + "amountList": [ + { + "value": 3, + "chance": 67 + }, + { + "value": 4, + "chance": 33 + } + ] + }, + { + "avatarId": 10000006, + "name": "Lisa", + "amountList": [ + { + "value": 5, + "chance": 100 + } + ] + }, + { + "avatarId": 10000007, + "name": "Traveler", + "amountList": [ + { + "value": 3, + "chance": 67 + }, + { + "value": 4, + "chance": 33 + } + ] + }, + { + "avatarId": 10000014, + "name": "Barbara", + "amountList": [ + { + "value": 0, + "chance": 100 + } + ] + }, + { + "avatarId": 10000015, + "name": "Kaeya", + "amountList": [ + { + "value": 2, + "chance": 33 + }, + { + "value": 3, + "chance": 67 + } + ] + }, + { + "avatarId": 10000016, + "name": "Diluc", + "amountList": [ + { + "value": 1, + "chance": 33 + }, + { + "value": 2, + "chance": 67 + } + ] + }, + { + "avatarId": 10000020, + "name": "Razor", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000021, + "name": "Amber", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000022, + "name": "Venti", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000023, + "name": "Xiangling", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000024, + "name": "Beidou", + "amountList": [ + { + "value": 2, + "chance": 100 + } + ] + }, + { + "avatarId": 10000025, + "name": "Xingqiu", + "amountList": [ + { + "value": 5, + "chance": 100 + } + ] + }, + { + "avatarId": 10000026, + "name": "Xiao", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000027, + "name": "Ningguang", + "amountList": [ + { + "value": 3, + "chance": 33 + }, + { + "value": 4, + "chance": 67 + } + ] + }, + { + "avatarId": 10000029, + "name": "Klee", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000030, + "name": "Zhongli", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000031, + "name": "Fischl", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000032, + "name": "Bennett", + "amountList": [ + { + "value": 2, + "chance": 75 + }, + { + "value": 3, + "chance": 25 + } + ] + }, + { + "avatarId": 10000033, + "name": "Tartaglia", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000034, + "name": "Noelle", + "amountList": [ + { + "value": 0, + "chance": 100 + } + ] + }, + { + "avatarId": 10000035, + "name": "Qiqi", + "amountList": [ + { + "value": 0, + "chance": 100 + } + ] + }, + { + "avatarId": 10000036, + "name": "Chongyun", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000037, + "name": "Ganyu", + "amountList": [ + { + "value": 2, + "chance": 100 + } + ] + }, + { + "avatarId": 10000038, + "name": "Albedo", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000039, + "name": "Diona", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000041, + "name": "Mona", + "amountList": [ + { + "value": 3, + "chance": 67 + }, + { + "value": 4, + "chance": 33 + } + ] + }, + { + "avatarId": 10000042, + "name": "Keqing", + "amountList": [ + { + "value": 2, + "chance": 50 + }, + { + "value": 3, + "chance": 50 + } + ] + }, + { + "avatarId": 10000043, + "name": "Sucrose", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000044, + "name": "Xinyan", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000045, + "name": "Rosaria", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000046, + "name": "Hu Tao", + "amountList": [ + { + "value": 2, + "chance": 50 + }, + { + "value": 3, + "chance": 50 + } + ] + }, + { + "avatarId": 10000047, + "name": "Kaedehara Kazuha", + "amountList": [ + { + "value": 3, + "chance": 50 + }, + { + "value": 4, + "chance": 50 + } + ] + }, + { + "avatarId": 10000048, + "name": "Yanfei", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000049, + "name": "Yoimiya", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000050, + "name": "Thoma", + "amountList": [ + { + "value": 3, + "chance": 50 + }, + { + "value": 4, + "chance": 50 + } + ] + }, + { + "avatarId": 10000051, + "name": "Eula", + "amountList": [ + { + "value": 1, + "chance": 50 + }, + { + "value": 2, + "chance": 50 + } + ] + }, + { + "avatarId": 10000052, + "name": "Raiden Shogun", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000053, + "name": "Sayu", + "amountList": [ + { + "value": 2, + "chance": 100 + } + ] + }, + { + "avatarId": 10000054, + "name": "Sangonomiya Kokomi", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000055, + "name": "Gorou", + "amountList": [ + { + "value": 2, + "chance": 100 + } + ] + }, + { + "avatarId": 10000056, + "name": "Kujou Sara", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000057, + "name": "Arataki Itto", + "amountList": [ + { + "value": 3, + "chance": 50 + }, + { + "value": 4, + "chance": 50 + } + ] + }, + { + "avatarId": 10000058, + "name": "Yae Miko", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000060, + "name": "Yelan", + "amountList": [ + { + "value": 4, + "chance": 100 + } + ] + }, + { + "avatarId": 10000062, + "name": "Aloy", + "amountList": [ + { + "value": 5, + "chance": 100 + } + ] + }, + { + "avatarId": 10000063, + "name": "Shenhe", + "amountList": [ + { + "value": 3, + "chance": 100 + } + ] + }, + { + "avatarId": 10000064, + "name": "Yun Jin", + "amountList": [ + { + "value": 2, + "chance": 100 + } + ] + }, + { + "avatarId": 10000065, + "name": "Kuki Shinobu", + "amountList": [ + { + "value": 1, + "chance": 100 + } + ] + }, + { + "avatarId": 10000066, + "name": "Kamisato Ayato", + "amountList": [ + { + "value": 1, + "chance": 50 + }, + { + "value": 2, + "chance": 50 + } + ] + } +] diff --git a/data/Spawns.json b/src/main/resources/defaults/data/Spawns.json similarity index 100% rename from data/Spawns.json rename to src/main/resources/defaults/data/Spawns.json diff --git a/src/main/resources/defaults/data/TowerSchedule.json b/src/main/resources/defaults/data/TowerSchedule.json new file mode 100644 index 000000000..e10416a20 --- /dev/null +++ b/src/main/resources/defaults/data/TowerSchedule.json @@ -0,0 +1,5 @@ +{ + "scheduleId" : 45, + "scheduleStartTime" : "2022-05-01T00:00:00+08:00", + "nextScheduleChangeTime" : "2022-05-30T00:00:00+08:00" +} \ No newline at end of file diff --git a/src/main/resources/defaults/data/documentation/handbook.html b/src/main/resources/defaults/data/documentation/handbook.html new file mode 100644 index 000000000..6a77d3806 --- /dev/null +++ b/src/main/resources/defaults/data/documentation/handbook.html @@ -0,0 +1,162 @@ + + + + + + + + + GM Handbook + + +
+
+

{{TITLE}}

+ +

{{TITLE_COMMANDS}}

+
+ + + + + + + + {{COMMANDS_TABLE}} +
{{HEADER_COMMAND}}{{HEADER_DESCRIPTION}}
+ +

{{TITLE_AVATARS}}

+
+ + + + + + + + {{AVATARS_TABLE}} +
{{HEADER_ID}}{{HEADER_AVATAR}}
+ +

{{TITLE_ITEMS}}

+
+ + + + + + + + {{ITEMS_TABLE}} +
{{HEADER_ID}}{{HEADER_ITEM}}
+ + +

{{TITLE_SCENES}}

+
+ + + + + + + + {{SCENES_TABLE}} +
{{HEADER_ID}}{{HEADER_SCENE}}
+ +

{{TITLE_MONSTERS}}

+
+ + + + + + + + {{MONSTERS_TABLE}} +
{{HEADER_ID}}{{HEADER_MONSTER}}
+
+
+
+ +
+ + diff --git a/src/main/resources/defaults/data/documentation/index.html b/src/main/resources/defaults/data/documentation/index.html new file mode 100644 index 000000000..f89dbe258 --- /dev/null +++ b/src/main/resources/defaults/data/documentation/index.html @@ -0,0 +1,106 @@ + + + + + + + + + Documentation + + +
+
+

{{TITLE}}

+ + +
+
+
+ +
+ + diff --git a/src/main/resources/defaults/data/gacha/details.html b/src/main/resources/defaults/data/gacha/details.html new file mode 100644 index 000000000..85443d532 --- /dev/null +++ b/src/main/resources/defaults/data/gacha/details.html @@ -0,0 +1,121 @@ + + + + + + + + + Banner Details + + + +
+
+

{{TITLE}}

+ +

{{AVAILABLE_FIVE_STARS}}

+
+
    +
+ +

{{AVAILABLE_FOUR_STARS}}

+
+
    +
+ +

{{AVAILABLE_THREE_STARS}}

+
+
    +
+
+
+
+ +
+ + + + diff --git a/data/gacha_records.html b/src/main/resources/defaults/data/gacha/records.html similarity index 67% rename from data/gacha_records.html rename to src/main/resources/defaults/data/gacha/records.html index 5ce8e660f..cad1c89d5 100644 --- a/data/gacha_records.html +++ b/src/main/resources/defaults/data/gacha/records.html @@ -53,47 +53,14 @@ } Gacha Records - @@ -144,7 +111,8 @@