135 Commits

Author SHA1 Message Date
175e7f5f09 Format code [skip actions] 2023-08-01 04:23:23 +00:00
665263d9ba Fix account list subcommand 2023-07-31 17:26:30 -04:00
a4ad781d61 Format code [skip actions] 2023-07-31 16:54:59 +00:00
465582b8da Handle Dungeons with null config (#2279) 2023-07-31 12:52:42 -04:00
4320bc7d29 Format code [skip actions] 2023-07-29 15:40:10 +00:00
98fbc4e512 Improve Platforms (#2275)
* Improve Platforms

* add this.
2023-07-29 11:38:34 -04:00
f3277dee9f Fix Forging (#2278) 2023-07-29 11:37:32 -04:00
0005fcf96f Format code [skip actions] 2023-07-23 03:19:10 +00:00
f065b2b16f Format code [skip actions] 2023-07-23 03:18:53 +00:00
e9d68936f6 Format code [skip actions] 2023-07-23 03:18:29 +00:00
47971dc931 various small bug fixes (#2270)
* various small bug fixes

* Upgrade warning to error

* A few more state changes to match the others in this pull
2023-07-22 23:17:59 -04:00
fe169398ec Gadgets can be picked up too (#2272)
* Gadgets can be picked up too

* put in a warning
2023-07-22 23:17:39 -04:00
ddc082fc97 Everything triggers regions (#2271)
* Everything triggers regions

* hotfix
2023-07-22 23:17:33 -04:00
0b806e21cf Fix talks that have a quest id of 4 digits or more (#2268) 2023-07-22 23:17:18 -04:00
49ba0e55e8 make xxGroupVariableValueByGroup the same as xxGroupVariableValue (#2266) 2023-07-22 23:17:11 -04:00
ae2ab20b5b add support for 3.8 teapot binout files (scene 2005, 2204) (#2265) 2023-07-22 23:17:02 -04:00
27d495742d Format code [skip actions] 2023-07-15 03:05:16 +00:00
f17339f1b6 Send global value packet after the scene host has finished initializing the scene 2023-07-14 23:03:49 -04:00
f0775f70f3 Send packet after scene load & Directly send back entity ID to clients 2023-07-14 21:22:45 -04:00
fecf83cfa4 Revert AvatarUpgradeRsp 2023-07-14 21:09:57 -04:00
dfbe4022f3 Merge remote-tracking branch 'origin/development' into development 2023-07-14 19:47:56 -04:00
e859d87ae3 Implement SetEntityServerGlobalValueByEntityId 2023-07-14 19:46:30 -04:00
acb3575c77 update zh-TW.json (#2260) 2023-07-14 19:37:54 -04:00
f725d9203d Fix QUEST_CONTENT_LEAVE_SCENE (#2262) 2023-07-14 19:37:29 -04:00
d62394e35e Remove obsolete code in ScriptLib.java (#2263) 2023-07-14 19:37:08 -04:00
a4d5de06d1 Fix starting wrong quest for story quests (#2264) 2023-07-14 19:36:50 -04:00
73acfa1178 Update README_zh-TW (#2261)
* Update README_zh-TW.md

添加繁體版快速開始

* Update README_zh-TW.md
2023-07-12 22:01:20 -04:00
0d71d29932 fix first entering teapot failure (#2259) 2023-07-12 22:00:55 -04:00
d0a4da8a1f Update languages [skip actions] 2023-07-09 06:04:19 +00:00
d332861ed8 add italian support (italian translation fix) (#2249)
* Updated IT Readme

* Update it-IT.json

* Update it-IT.json (2)

* fixed a couple errors while reviewing
2023-07-09 02:03:54 -04:00
47186a47b2 It now can bind on correct addr (#2254)
Now Grasscutter will bind on address specified in config.json (bindAddress), instead of 0.0.0.0
2023-07-08 12:27:12 -04:00
5090b17b80 Update ru-RU.json (#2247)
ty Scaldy for help♥♥♥
2023-07-03 23:32:15 -04:00
5b9508d7a4 Update French translations (#2246) 2023-07-03 23:30:22 -04:00
df7941bc1b Format code [skip actions] 2023-07-03 11:03:03 +00:00
9cac0953fa Add alternate val name (#2245) 2023-07-03 07:01:50 -04:00
7cdb774b1f Merge remote-tracking branch 'origin/development' into development 2023-07-01 01:29:40 -04:00
f40cdfd23d Update protocol definition for AvatarUpgradeRsp 2023-07-01 01:29:30 -04:00
4e71a15479 Move unknown condition handler message to debug 2023-07-01 01:29:14 -04:00
6afa1bf276 Bump to 1.6.2 & Fix handbook generation error 2023-07-01 01:28:35 -04:00
8c2d00fcd3 fix README.md build badge (#2243)
* fix README.md build badge

* fix README_XXX.md build badge
2023-07-01 01:17:03 -04:00
308686d9e7 Format code [skip actions] 2023-06-27 05:51:09 +00:00
83d447cfc2 Update region logic (#2240) 2023-06-27 01:49:24 -04:00
4ec274f5c5 Set event source for group variable changes to the variable name (#2231) 2023-06-25 10:45:37 -04:00
30d093f348 Update ScriptLib.java (#2227) 2023-06-24 00:37:13 -04:00
9fd5f7665c Fix unlogging quests (#2226) 2023-06-23 23:03:14 -04:00
55840bcdb6 Synchronize the Chinese README with the English version (#2224)
* Synchronize the Chinese README with the English version

* Update Chinese README translation

Better formatting and fixing several words that were not translated.
2023-06-22 16:42:35 -04:00
e706cce802 Format code [skip actions] 2023-06-20 20:38:14 +00:00
b58caf0632 Fix Librarian Story Quest (#2218)
* Fix Librarian Story Quest

* People die if they are killed

You want to die people instead of remove them so they play their sweet death animations.

* Nope. I take it back. Scriptlib is the wierd one to think removeEntity removes the entity.

* One must stop editing the code directly.

* Update EntityType.java

* Add warnings per Hartie

* Per Hartie, change getEntityType to EntityType
2023-06-20 16:37:00 -04:00
97b28b13fe Format code [skip actions] 2023-06-17 19:58:14 +00:00
4ebe6fbf63 dungeon drop implementation (#2215)
* dungeon drop implementation

* Update src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2023-06-17 15:56:47 -04:00
06d5bf7098 Temporary fix to scene reference 2023-06-17 11:24:46 -04:00
9d94888da3 Fix race condition with worktops (#2216)
* Fix race condition with worktops

* Update ScriptLib.java

* Update ScriptLib.java

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2023-06-17 11:00:10 -04:00
86036682d7 Format code [skip actions] 2023-06-17 03:00:10 +00:00
762e7ae301 Fix ContentNotFinishPlot 2023-06-16 22:58:49 -04:00
31cef88ef7 Format code [skip actions] 2023-06-16 18:28:59 +00:00
c3339de184 Resume the app token exchanger (#2209) 2023-06-16 14:27:14 -04:00
e382c6d691 Format code [skip actions] 2023-06-16 18:06:43 +00:00
6b3f19e588 fix giveall doesn't give everything (#2210)
* fix giveall doesn't give everything

* avoid unnecessary failure to add items by catching exception earlier

* switch to use grasscutter logger

* use debug()
2023-06-16 14:05:33 -04:00
47172c995f Format code [skip actions] 2023-06-16 18:05:28 +00:00
6da5343df0 Do not unload groups asked for by quests (#2212) 2023-06-16 14:04:58 -04:00
89376d58bf Change method of not ticking empty scenes (#2211) 2023-06-16 14:04:16 -04:00
248af4abfb Update VisionLevelType.java (#2207) 2023-06-13 11:27:24 -04:00
a7f78c7759 Skip invalid plugins (#2206) 2023-06-13 11:24:02 -04:00
baac48c4a0 Format code [skip actions] 2023-06-11 20:26:35 +00:00
6c89998759 Fix KillSelf 2023-06-11 16:24:42 -04:00
3cc5e6b4e8 Disclaimer 2023-06-11 16:15:15 -04:00
0f43e18d70 Fix some affixes not working 2023-06-11 16:14:38 -04:00
1c9f32cbef Fix a bit of un-researched action handling 2023-06-11 16:12:57 -04:00
d933ca6d02 Format code [skip actions] 2023-06-11 03:33:37 +00:00
3d62e72aa0 Format code [skip actions] 2023-06-11 03:32:55 +00:00
15699e562a Fix lock clock (#2201)
* Fix lock clock

* Update src/main/java/emu/grasscutter/game/world/World.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update src/main/java/emu/grasscutter/server/packet/recv/HandlerClientLockGameTimeNotify.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update src/main/java/emu/grasscutter/server/packet/recv/HandlerClientLockGameTimeNotify.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2023-06-10 23:32:23 -04:00
2788206934 Almost fully fix Chasing Shadows (#2202) 2023-06-10 23:31:57 -04:00
9dbeb2172d fix description of command quest and list (#2203)
* fix description of command `quest` and `list`

* Update src/main/java/emu/grasscutter/command/commands/QuestCommand.java

Co-authored-by: Der Chien <b03902015@ntu.edu.tw>

* Update QuestCommand.java

---------

Co-authored-by: Der Chien <b03902015@ntu.edu.tw>
2023-06-10 23:31:39 -04:00
55cb7ab967 Repair README.md 2023-06-10 23:31:12 -04:00
944db42762 Update quick start guide (#2198)
* Update quick start guide

Co-Authored-By: Nazrin <1877986+scooterboo@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update README.md

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

---------

Co-authored-by: Nazrin <1877986+scooterboo@users.noreply.github.com>
Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2023-06-10 23:30:28 -04:00
1ed89598ff Add option "all" for UnlockMap and change the default behavior for "/prop unlockmap on" (#2196)
* Do not unlock unnecessary scene points during '/prop unlockmap on'

* Format code [skip actions]

* Backup scenePoints since we might modify it

* Format code [skip actions]

* Add 'all' for UnlockMap

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-09 13:31:11 -04:00
4093420c90 Format code [skip actions] 2023-06-09 17:29:36 +00:00
a1f75e1537 Format code [skip actions] 2023-06-09 17:29:26 +00:00
e6d32f5599 Make ice dude show up (#2200)
* Make ice dude show up

* replace contains with equals

Might as well fix this while I'm here.
"leave" and "enter" have the same number of letters, so it works.

* empty strings suck

* Update SceneTrigger.java

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2023-06-09 13:28:28 -04:00
b412a24657 Smarter NPC loading (#2199) 2023-06-09 13:27:34 -04:00
b4b0b8d2a8 Fix cutscene and sound permissions (#2197) 2023-06-07 11:57:59 -04:00
d8d31f3afe Update AvatarUpgradeRspOuterClass.java (#2193) 2023-06-06 16:39:46 -04:00
7fb9913c4f Format code [skip actions] 2023-06-06 03:28:38 +00:00
8472c36490 Implement SET_KILLED_STATE 2023-06-05 23:27:14 -04:00
ddb76a0c2a Format code [skip actions] 2023-06-04 21:57:29 +00:00
c40213affc Action id mapping fix 2023-06-04 17:55:19 -04:00
f389d2fb28 Handle SetRandomOverrideMapValue 2023-06-04 17:53:48 -04:00
b5595c3fab Fix dropType de-serialization
enum edition
2023-06-04 17:53:30 -04:00
ecb6145e54 Revert "Fix dropType de-serialization" 2023-06-04 17:52:12 -04:00
eb17d65330 Revert "Format code [skip actions]"
This reverts commit 22e953b636.
2023-06-04 17:50:55 -04:00
22e953b636 Format code [skip actions] 2023-06-04 19:56:38 +00:00
6080297be9 Fix dropType de-serialization 2023-06-04 15:55:06 -04:00
6d6e6a041d Format code [skip actions] 2023-06-04 05:01:54 +00:00
b09c0d48bf Fix ActionGenerateElemBall 2023-06-04 01:00:27 -04:00
b050337216 Format code [skip actions] 2023-06-04 04:29:25 +00:00
ac3ccf93f3 Little fix 2023-06-04 00:27:15 -04:00
0167709070 Implement GenerateElemBall action 2023-06-04 00:27:01 -04:00
63ccff8755 Shut down the game server when Grasscutter is about to shut down 2023-06-04 00:26:06 -04:00
494cd3b28c Format code [skip actions] 2023-06-03 19:37:54 +00:00
f9dffba27a Merge remote-tracking branch 'origin/development' into development 2023-06-03 15:36:05 -04:00
f85070abdc Make subfield & drop classes final 2023-06-03 15:36:00 -04:00
4de21d4a40 Remove redundant script event calling when changing the time 2023-06-03 15:35:04 -04:00
56f09e87a1 Fix ore dropping and implement subfields 2023-06-03 15:29:45 -04:00
9dae3cbcc7 Added localid missing actions (needs testing) 2023-06-03 15:27:02 -04:00
d18a8c31a6 Add SystemHintType enum 2023-06-03 15:23:27 -04:00
f977679c1c Fix handbook generation being performed when all conditions weren't met 2023-06-03 15:23:05 -04:00
8fc17ede99 Format code [skip actions] 2023-06-03 16:43:21 +00:00
73e181df9b Merge remote-tracking branch 'origin/development' into development 2023-06-03 12:41:51 -04:00
5441094e47 Fix NullPointerException when trying to find gadgets in a group suite 2023-06-03 12:41:20 -04:00
7fc7b5087c Format code [skip actions] 2023-06-03 14:55:55 +00:00
e28575c80f Fix battle in front of glowy stag god (#2188)
* Fix battle in front of glowy stag god

* Don't do a rollback when starting a quest. We're better than that.
2023-06-03 10:54:46 -04:00
853a67d48e Format code [skip actions] 2023-06-03 01:43:44 +00:00
e8bfdc3c01 Send system hint when a player joins/leaves a world in multiplayer 2023-06-02 21:41:47 -04:00
8870675dcd Remove dead entities on scene tick 2023-06-02 21:41:10 -04:00
43fa6efec9 Format code [skip actions] 2023-06-02 18:26:45 +00:00
d9e8810a5c Fix invalid JSON exception when querying gacha records 2023-06-02 14:15:39 -04:00
82189e03ed Add debug command for checking triggers on a group 2023-06-01 21:28:46 -04:00
cef8b53dd6 Fix quest chests not having drop data 2023-06-01 21:28:12 -04:00
43f3494073 Check for an invalid avatar in a team 2023-06-01 20:00:17 -04:00
20f0cda3e0 Fix chasing shadows (mostly) 2023-06-01 19:59:36 -04:00
8692405363 Wait for thread executors to shut down 2023-06-01 18:17:48 -04:00
9dd514a73b Catch exception when unable to write to KCP client 2023-06-01 18:17:15 -04:00
1940b22dc5 Fix statue unlocks, and probably other quests involving talks 2023-06-01 18:13:41 -04:00
bb1729c227 Bump version to 1.6.1 2023-06-01 14:35:01 -04:00
4870871b2c Move rewind data logger call to debug 2023-06-01 14:27:38 -04:00
2c7c8bf4fd Add option for enabling costumes on trial avatars 2023-06-01 14:23:12 -04:00
deaa13c2af Add check for legacy API method calls on plugins 2023-06-01 14:19:05 -04:00
fd40575cb4 Fix issue with time when a player reconnects without a world 2023-06-01 14:18:34 -04:00
3c0e834348 Fix FieldFetch not getting fields from superclasses 2023-06-01 14:18:12 -04:00
27be6c31e6 Fix a typo I left in Player.java (#2180)
ENTER_REGION_ ->LEAVE_REGION_
Took the opportunity to refactor it so that we only calculate the string once.
2023-06-01 12:30:19 -04:00
87269e9ded README.md (#2181)
Remove mention of unstable branch in README.md
2023-06-01 12:29:42 -04:00
46fee38217 Fix ability modifiers NullPointerException 2023-06-01 03:30:00 -04:00
6e5971df62 Fix stamina casting exception 2023-06-01 03:27:48 -04:00
98375deac9 Downgrade development version to 1.6.0 2023-06-01 02:37:01 -04:00
97c70f7877 Fix issues with regions (#2179)
Luckily, SceneRegion and TriggerExcelConfigData both have group numbers, so we can use those to differentiate regions!
2023-06-01 02:04:18 -04:00
130 changed files with 4665 additions and 2652 deletions

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
@ -22,51 +22,23 @@
**Note**: For support please join our [Discord](https://discord.gg/T5vZU6UyeG).
### Requirements
### Quick Start (automatic)
* [Java SE - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) or higher
- Get Java 17: https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- Get [MongoDB Community Server](https://www.mongodb.com/try/download/community)
- Get game version REL3.7 (3.7 client can be found here if you don't have it): https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/3.7.0.md)
**Note:** If you just want to **run it**, then **jre** only is fine.
- Download the [latest Cultivation version](https://github.com/Grasscutters/Cultivation/releases/latest). Use the `.msi` installer.
- After opening Culivation (as admin), press the download button in the upper right corner.
- Click `Download All-in-One`
- Click the gear in the upper right corner
- Set the game Install path to where your game is located.
- Set the Custom Java Path to `C:\Program Files\Java\jdk-17\bin\java.exe`
- Leave all other settings on default
* [MongoDB](https://www.mongodb.com/try/download/community) (recommended 4.0+)
* Proxy Daemon: [mitmproxy](https://mitmproxy.org/) (mitmdump, recommended), [Fiddler Classic](https://telerik-fiddler.s3.amazonaws.com/fiddler/FiddlerSetup.exe), etc.
### Running
**Note:** If you updated from an older version, delete `config.json` to regenerate it.
1. Get `grasscutter.jar`
- Download from [releases](https://github.com/Grasscutters/Grasscutter/releases/latest) or [actions](https://github.com/Grasscutters/Grasscutter/actions/workflows/build.yml) or [build the server by yourself](#building).
2. Create a `resources` folder in the directory where grasscutter.jar is located and move your `BinOutput, ExcelBinOutput, Readables, Scripts, Subtitle, TextMap` folders there *(Check the [wiki](https://github.com/Grasscutters/Grasscutter/wiki) for more details how to get those.)*
3. Run Grasscutter with `java -jar grasscutter.jar`. **Make sure mongodb service is running as well.**
### Connecting with the client
½. Create an account in the server console using this [command](https://github.com/Grasscutters/Grasscutter/wiki/Commands#:~:text=account%20%3Ccreate|delete%3E%20%3Cusername%3E%20[UID]).
1. Redirect traffic: (choose one only)
- mitmdump: `mitmdump -s proxy.py -k`
- Trust CA certificate:
- The CA certificate is usually stored in `%USERPROFILE%\.mitmproxy`, double click `mitmproxy-ca-cert.cer` to [install](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) or...
- Via command line *(needs administration privileges)*
```shell
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic: Run Fiddler Classic, turn on `Decrypt HTTPS traffic` in (Tools -> Options -> HTTPS) and change the default port in (Tools -> Options -> Connections) to anything other than `8888`, load [this script](https://github.com/Grasscutters/Grasscutter/wiki/Resources#fiddler-classic-jscript) (copy and paste the script in the `FiddlerScript` tab) and click the `Save Script` button.
- [Hosts file](https://github.com/Grasscutters/Grasscutter/wiki/Resources#hosts-file)
2. Set network proxy to `127.0.0.1:8080` or the proxy port you specified.
- For mitmproxy: After setting up the network proxy and installing the certificate, check http://mitm.it/ if traffic is passing through mitmproxy.
**You can also use `start.cmd` to start servers and proxy daemons automatically, but you have to set up `JAVA_HOME` environment and configure the `start_config.cmd` file.**
- Click the small button next to launch.
- Click the launch button.
- Log in with whatever username you want. Password doesn't matter.
### Building
@ -80,7 +52,7 @@ Grasscutter uses Gradle to handle dependencies & building.
##### Windows
```shell
git clone --recurse-submodules -b unstable https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
.\gradlew.bat # Setting up environments
.\gradlew jar # Compile
@ -89,7 +61,7 @@ cd Grasscutter
##### Linux (GNU)
```bash
git clone --recurse-submodules -b unstable https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
chmod +x gradlew
./gradlew jar # Compile

View File

@ -57,7 +57,7 @@ sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
group = 'io.grasscutter'
version = '2.0.0-unstable'
version = '1.6.2'
java {
withJavadocJar()
@ -335,23 +335,55 @@ tasks.register('generateHandbook') {
return
}
def nodeVersion = {
// Resolve the NPM command.
var npm = 'npm'
if (Os.isFamily(Os.FAMILY_WINDOWS))
npm = 'npm.cmd'
def npmVersion = {
try {
return 'node --version'.execute().text.trim()
return "${npm} --version".execute()
} catch (ignored) {
return 'NODE_NOT_FOUND'
ignored.printStackTrace()
return 'NPM_NOT_FOUND'
}
}
// Check if Node is installed.
if (nodeVersion() == 'NODE_NOT_FOUND') {
println('Node is not installed. Skipping handbook generation.')
if (npmVersion() == 'NPM_NOT_FOUND') {
println('NPM is not installed. Skipping handbook generation.')
} else {
// Build the handbook.
var npm = 'npm'
if (Os.isFamily(Os.FAMILY_WINDOWS))
npm = 'npm.cmd'
// Check if the handbook resources are present.
if (!file('src/handbook/data/commands.json')) {
println('Command data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/avatars.csv')) {
println('Avatar data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/entities.csv')) {
println('Entity data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/items.csv')) {
println('Item data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/mainquests.csv')) {
println('Main quest data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/quests.csv')) {
println('Quest data was not found. Skipping handbook generation.')
return
}
if (!file('src/handbook/data/scenes.csv')) {
println('Scene data was not found. Skipping handbook generation.')
return
}
// Build the handbook.
exec {
workingDir 'src/handbook'
commandLine npm, 'run', 'build'

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
@ -18,90 +18,57 @@
* Apparition de monstres via la console
* Inventaire (obtention d'objets/de personnages, amélioration d'objets/personnages, etc)
## Guide de démarrage rapide
## Guide d'installation rapide
**Note:** Pour obtenir un support, rejoignez notre serveur [Discord](https://discord.gg/T5vZU6UyeG) (en anglais).
### Logiciels requis
### Démarage rapide (Automatique)
* Java SE - 17 ([link](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html))
- Téléchargez Java 17: https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- Téléchargez [MongoDB Community Server](https://www.mongodb.com/try/download/community)
- Téléchargez la version du jeu REL3.7 (Le client de jeut peut être obtenu ici si vous ne l'avez pas): https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/3.7.0.md
**Note:** Si vous voulez juste **l'exécuter**, Alors vous pouvez télécharger seulement le **jre**
- Téléchargez la [dernière version de Cultivation](https://github.com/Grasscutters/Cultivation/releases/latest). Ulilisez l'installateur en `.msi`.
- Après avoir ouvert Cultivation (en administrateur), appuyez sur le bouton de téléchargement en haut a droite.
- Cliquez sur le bouton `Téléchargez tout-en-un`
- Cliquez sur l'engrenage dans le coin en haut a droite.
- Définisez l'emplacement d'installation du jeu.
- Définisez le chemin Java personnalisé à `C:\Program Files\Java\jdk-17\bin\java.exe`
- Laissez tous les autres paramètes par défauts
* MongoDB (4.0+ recommandé)
- Appuyez sur le bouton a coté de Lancer.
- Appuyez sur le bouton Lancer.
- Connectez vous avec le nom d'utilisateur que vous voulez. Le mot de passe n'a pas d'importance.
* Proxy daemon: mitmproxy (mitmdump, recommended), Fiddler Classic, etc.
### Compilation
### Lancement
Grasscutter utilise Gradle pour la gestion des dépendances et la compilation.
**Note:** Si vous avez mis à jour depuis une ancienne version, supprimez `config.json` pour le regénérer.
**Prérequis**
1. Obtenez `grasscutter.jar`
- Téléchargez le depuis les [actions](https://github.com/Grasscutters/Grasscutter/suites/6895963598/artifacts/267483297)
- [Buildez le par vous-même](#Building)
2. Créez un dossier `resources` dans le dossier où grasscutter.jar est situé et déplacez vos dossiers `BinOutput` et `ExcelBinOutput` ici *(Vérifiez le [wiki](https://github.com/Grasscutters/Grasscutter/wiki) pour plus de détails sur comment les obtenir.)*
3. Exécutez Grasscutter avec `java -jar grasscutter.jar`. **Soyez sûr que le service MongoDB est en cours d'exécution.**
### Connection avec le client
½. Créez un compte avec la [console de commande du serveur](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting).
1. Redirection du traffic: (Choisissez-en un)
- mitmdump: `mitmdump -s proxy.py -k`
Approuvez le certificat CA:
**Note:**Le certificat CA est généralement stocké sous `%USERPROFILE%\ .mitmproxy`, ou vous pouvez le télécharger depuis `http://mitm.it`
Double-cliquez pour [installer](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) oo ...
- Via la ligne de commande
```shell
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic: Exécutez Fiddler Classic, Activez `Decrypt https traffic` dans les paramètres et changez le port par défaut ici (Tools -> Options -> Connections) à autre chose que `8888`, et chargez [ce script](https://github.lunatic.moe/fiddlerscript).
- [Fichier hosts](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
2. Définissez le proxy du réseau comme `127.0.0.1:8080` ou le port du proxy que vous avez spécifié.
**Vous pouvez aussi utiliser `start.cmd` to démarrer les serveurs et le proxy automatiquement, mais vous devez mettre en place la variable d'environnement JAVA_HOME**
### Building
Grasscutter utilise Gradle pour gérer les dépendances et la construction.
**Logiciels requis:**
- [Java SE Development Kits - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
- [Java SE Development Kits - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) ou plus récent
- [Git](https://git-scm.com/downloads)
##### Windows
```shell
git clone https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
.\gradlew.bat # Mettre en place l'environnement
.\gradlew jar # Compiler
.\gradlew.bat # Setting up environments
.\gradlew jar # Compile
```
##### Linux
##### Linux (GNU)
```bash
git clone https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
chmod +x gradlew
./gradlew jar # Compiler
./gradlew jar # Compile
```
Vous trouverez le fichier jar compilé à la racine du dossier du projet.
Vous pouvez trouver le jar de sortie dans la racine du dossier du projet.
### Les commandes ont été déplacé vers le [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)! (en anglais)
### Dépanage
# Dépannage rapide
* Si la compilation a échoué, veuillez vérifier votre installation de votre JDK (JDK 17 et le bon dossier bin du JDK dans la variable PATH)
* Mon client ne se connecte pas au serveur, impossible de se connecter a mon compte, 4206, etc... - La plupart du temps, *le problème* vient de la configuration de votre proxy. Si vous utilisez Fiddler, vérifiez s'il est exécuté sur un port autre que 8888
* Séquence de démarrage : MongoDB > Grasscutter > Proxy (mitmdump, fiddler, etc...) > Jeu
Pour une liste des problèmes communs et leur solution et pour demander de l'aide, veuillez rejoindre [notre serveur Discord](https://discord.gg/T5vZU6UyeG) (en anglais) et dirigez vous vers le salon de support.

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,11 +1,11 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
[EN](../README.md) | [简中](README_zh-CN.md) | [繁中](README_zh-TW.md) | [FR](README_fr-FR.md) | [ES](README_es-ES.md) | [HE](README_HE.md) | [RU](README_ru-RU.md) | [PL](README_pl-PL.md) | [ID](README_id-ID.md) | [KR](README_ko-KR.md) | [FIL/PH](README_fil-PH.md) | [NL](README_NL.md) | [JP](README_ja-JP.md) | [IT](README_it-IT.md) | [VI](README_vi-VN.md)
**Attenzione:** Diamo sempre il benvenuto ai contributori del progetto. Prima di aggiungere il tuo contributo, leggi attentamente il nostro [Codice di condotta](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md).
**Attenzione:** Diamo sempre il benvenuto ai contributori del progetto. Prima di contribuire, leggi attentamente il nostro [Codice di condotta](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md).
## Funzionalità attuali
@ -15,12 +15,12 @@
* Teletrasporto
* Sistema Gacha
* Cooperativa *parzialmente* funzionale
* Evoca mostri dalla console
* Funzionalità dell'inventario (ricevi oggetti/personaggi, aggiorna oggetti/personaggi, ecc.)
* Evocazione nemici usando la console
* Inventario (ricevi e aggiorna oggetti/personaggi, ecc.)
## Guida rapida all'installazione
**Nota:** Per il supporto, unisciti al nostro [Discord](https://discord.gg/T5vZU6UyeG).
**Nota:** Se hai bisogno di aiuto, unisciti al nostro [Discord](https://discord.gg/T5vZU6UyeG).
### Requisiti
@ -30,30 +30,30 @@
* [MongoDB](https://www.mongodb.com/try/download/community) (consigliato 4.0+)
* Servizio proxy: mitmproxy (mitmdump, consigliato), Fiddler Classic, ecc.
* Servizi proxy: mitmproxy (mitmdump, consigliato), Fiddler Classic, ecc.
### Esecuzione
**Nota:** Se hai eseguito l'aggiornamento da una versione precedente, rimuovi `config.json` in modo che venga generato di nuovo.
**Nota:** Se hai aggiornato da una versione precedente, elimina `config.json` in modo che venga generato di nuovo.
1. Ottieni "grasscutter.jar".
- Scarica da [azioni](https://github.com/Grasscutters/Grasscutter/suites/6895963598/artifacts/267483297)
- [Compilalo tu stesso](#Compilazione)
2. Crea una cartella `resources` nella directory in cui si trova grasscutter.jar e sposta lì le cartelle `BinOutput` ed `ExcelBinOutput` *(Vedi il [wiki](https://github.com/Grasscutters/Grasscutter/wiki ) per maggiori dettagli su come ottenerli.)*
3. Eseguire Grasscutter con `java -jar grasscutter.jar`. **Assicurati che il servizio mongodb sia attivo.**
2. Crea una cartella chiamata `resources` nella directory in cui si trova grasscutter.jar e sposta lì le cartelle `BinOutput` ed `ExcelBinOutput` *(Vedi il [wiki](https://github.com/Grasscutters/Grasscutter/wiki ) per maggiori dettagli su come ottenerli.)*
3. Esegui Grasscutter con `java -jar grasscutter.jar`. **Assicurati che il servizio mongodb sia attivo.**
### Connessione client
### Connessione al client
½. Crea un account usando [il comando corrispondente nella console del server](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting).
1. Reindirizza il traffico: (scegli uno)
- mitmdump: `mitmdump -s proxy.py -k`
- Con mitmdump: `mitmdump -s proxy.py -k`
Autorizza il certificato CA:
**Nota:**Il certificato CA si trova solitamente in `%USERPROFILE%\ .mitmproxy`, oppure puoi scaricarlo da `http://mitm.it`
Fare doppio clic su [installa](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) o ...
Fai doppio clic su [installa](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) o ...
- Con riga di comando
@ -61,11 +61,11 @@
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic: esegui Fiddler Classic, abilita `Decrypt https traffic` nelle opzioni e cambia la porta predefinita in (Strumenti -> Opzioni -> Connessioni) in qualcosa di diverso da `8888`, e carica [questo script](https :/ /github.lunatic.moe/fiddlerscript).
- Con Fiddler Classic: esegui Fiddler Classic, abilita `Decrypt https traffic` nelle opzioni e cambia la porta predefinita in (Strumenti -> Opzioni -> Connessioni) in qualcosa di diverso da `8888`, e carica [questo script](https://github.lunatic.moe/fiddlerscript).
- [File host](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
2. Impostare il proxy di rete su `127.0.0.1:8080` o la porta proxy impostata.
2. Imposta il proxy di rete a `127.0.0.1:8080` o la porta proxy impostata.
**Puoi anche usare `start.cmd` per avviare automaticamente il server e il servizio proxy, ma devi impostare l'ambiente JAVA_HOME**
@ -98,11 +98,11 @@ chmod +x gradlew
Puoi trovare il jar generato nella cartella principale del progetto.
### I comandi sono stati spostati nel [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)!
### I comandi sono stati spostati al [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)!
# Soluzioni agli errori comuni
* Se la compilazione non riesce, controlla l'installazione di JDK (JDK 17 e convalida la variabile JDK bin PATH)
* Il mio client non si connette, non accede, 4206, ecc... - Probabilmente le tue impostazioni proxy sono *il problema*, se usi
* Se il tuo client non si connette, non accede, da errore 4206, ecc... - Probabilmente *il problema* sono le tue impostazioni proxy, se usi
Fiddler assicurati di utilizzare una porta diversa da 8888
* Sequenza di avvio: MongoDB > Grasscutter > Servizio proxy (mitmdump, fiddler, ecc.) > Gioco

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>

View File

@ -1,11 +1,11 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documentation" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
[EN](../README.md) | [简中](README_zh-CN.md) | [繁中](README_zh-TW.md) | [FR](README_fr-FR.md) | [ES](README_es-ES.md) | [HE](README_HE.md) | [RU](README_ru-RU.md) | [PL](README_pl-PL.md) | [ID](README_id-ID.md) | [KR](README_ko-KR.md) | [FIL/PH](README_fil-PH.md) | [NL](README_NL.md) | [JP](README_ja-JP.md) | [IT](README_it-IT.md) | [VI](README_vi-VN.md)
**注意:** 欢迎成为本项目的贡献者。但在提交 PR 之前, 请仔细阅读 [代码规范](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)。
**注意:** 我们始终欢迎项目的贡献者。但在做贡献之前,请仔细阅读我们的[代码规范](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)。
## 当前功能
@ -16,92 +16,59 @@
* 祈愿
* 多人游戏 *部分* 可用
* 从控制台生成魔物
* 物品 (接收或升级角色、武器等)
* 背包功能(接收或升级物品、角色等)。
## 快速安装指南
## 快速设置指南
**注意:** 如需帮助,请加入我们的[Discord](https://discord.gg/T5vZU6UyeG)。
**注意:** 如需帮助请加入 [Discord](https://discord.gg/T5vZU6UyeG)
### 快速开始(全自动)
### 环境需求
- 获取Java 17https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- 获取[MongoDB社区版](https://www.mongodb.com/try/download/community)
- 获取游戏3.7正式版 (如果你没有3.7的客户端可以在这里找到https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/3.7.0.md)
* [Java SE - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
- 下载[最新的Cultivation版本](https://github.com/Grasscutters/Cultivation/releases/latest)(使用以“.msi”为后缀的安装包
- 以管理员身份打开Culivation按右上角的下载按钮。
- 点击“下载 Grasscutter 一体化”
- 点击右上角的齿轮
- 将游戏安装路径设置为你游戏所在的位置。
- 将自定义Java路径设置为`C:\Program Files\Java\jdk-17\bin\java.exe`
- 保持所有其它设置为默认值
**注意:** 如果想仅**运行服务端**, 只下载 **jre** 即可
* [MongoDB](https://www.mongodb.com/try/download/community) (推荐 4.0+)
* 代理程序: [mitmproxy](https://mitmproxy.org/) (仅需 mitmdump推荐使用), [Fiddler Classic](https://telerik-fiddler.s3.amazonaws.com/fiddler/FiddlerSetup.exe) 等
### 运行服务端
**注意:** 从旧版本升级到新版本, 需要删除 `config.json` 使其重新生成
1. 获取 `grasscutter.jar`
- 从 [actions](https://github.com/Grasscutters/Grasscutter/actions) 下载,或 [自行编译](#构建)
2. 在 JAR 文件根目录中创建 `resources` 文件夹并复制 `BinOutput``ExcelBinOutput` *(查看 [Wiki](https://github.com/Grasscutters/Grasscutter/wiki) 了解更多)*
3. **确认 MongoDB 服务运行正常后**,使用命令行 `java -jar grasscutter.jar` 运行 Grasscutter。
### 客户端连接
½. 在服务器控制台 [创建账户](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting)
1. 重定向流量: (选择其中一个)
- mitmdump: `mitmdump -s proxy.py -k`
信任 CA 证书:
**注意:** mitmproxy 的 CA 证书通常存放在 `%USERPROFILE%\ .mitmproxy`, 或者从 `http://mitm.it` 下载证书
双击 [安装根证书](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate)或者...
- 使用命令行
```shell
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic: 运行 Fiddler Classic, 在设置中开启 `解密 https 通信` 并将端口设为除 `8888` 以外的任意端口 (工具 -> 选项 -> 连接) 并加载 [此脚本](https://github.lunatic.moe/fiddlerscript)
- [Hosts 文件](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
2. 设置代理为 `127.0.0.1:8080` 或你设置的端口
**也可直接运行 `start.cmd` 一键启动服务端并设置代理, 但设置 `JAVA_HOME` 环境变量并配置 `start_config.cmd`**
- 点击“启动”按钮旁边的小按钮。
- 点击“启动”按钮。
- 随便想一个用户名登录,不需要密码。
### 构建
Grasscutter 使用 Gradle 来处理依赖及编译
Grasscutter使用Gradle来处理依赖和构建
**前置依赖:**
**前置**
- [Java SE Development Kits - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
- [Java SE Development Kits - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)或更高版本
- [Git](https://git-scm.com/downloads)
##### Windows
```shell
git clone https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
.\gradlew.bat # 建立开发环境
.\gradlew.bat # 设置开发环境
.\gradlew jar # 编译
```
##### Linux
##### LinuxGNU
```bash
git clone https://github.com/Grasscutters/Grasscutter.git
git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
chmod +x gradlew
./gradlew jar # 编译
```
* 编译后的 JAR 文件会在源码根目录生成
你可以在项目的根目录找到输出的jar。
### 命令列表请到 [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands) 查看
### 故障排除
# 快速问题排除
* 如果编译失败, 请检查 JDK 安装是否正确 (需要 JDK 17 并确认 JDK 的 bin 文件夹处于环境变量 `PATH` 中)
* 客户端无法登录、连接、错误 4206 等其他问题... - 大部分情况是因为代理设置出现了*问题*。
如果使用 Fiddler请确认 Fiddler 监听端口不是 `8888`
* 启动顺序: MongoDB > Grasscutter > 代理程序 (mitmdump, Fiddler 等) > 客户端
获取常见问题的解决方案或寻求帮助,请加入[我们的Discord服务器](https://discord.gg/T5vZU6UyeG)并进入“support”频道。

View File

@ -1,5 +1,5 @@
![Grasscutter](https://socialify.git.ci/Grasscutters/Grasscutter/image?description=1&forks=1&issues=1&language=1&logo=https%3A%2F%2Fs2.loli.net%2F2022%2F04%2F25%2FxOiJn7lCdcT5Mw1.png&name=1&owner=1&pulls=1&stargazers=1&theme=Light)
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/Grasscutters/Grasscutter/Build?logo=github&style=for-the-badge"></div>
<div align="center"><img alt="Documention" src="https://img.shields.io/badge/Wiki-Grasscutter-blue?style=for-the-badge&link=https://github.com/Grasscutters/Grasscutter/wiki&link=https://github.com/Grasscutters/Grasscutter/wiki"> <img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Grasscutters/Grasscutter?logo=java&style=for-the-badge"> <img alt="GitHub" src="https://img.shields.io/github/license/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Grasscutters/Grasscutter?style=for-the-badge"> <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/Grasscutters/Grasscutter/build.yml?branch=development&logo=github&style=for-the-badge"></div>
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
@ -22,52 +22,23 @@
**注意:** 如需幫助請加入 [Discord](https://discord.gg/T5vZU6UyeG)
### 環境需求
### 快速開始(全自動)
* Java SE - 17 ([連結](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html))
- 下載 Java 17https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- 下載 [MongoDB 社區伺服器](https://www.mongodb.com/try/download/community)
- 下載遊戲版本 REL3.7(如果你沒有的話,可以在[這裡](https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/3.7.0.md)找到 3.7 客戶端)
**注意:** 如果僅想**執行服務端**, 使用 **jre** 即可
- 下載 [最新的 Cultivation 版本](https://github.com/Grasscutters/Cultivation/releases/latest)。使用 `.msi` 安裝程式。
- 以管理員身分打開 Culivation按右上角的下載按鈕。
- 點擊 `Download All-in-One`
- 點擊右上角的齒輪
- 將遊戲安裝路徑設置為你的遊戲所在的位置。
- 將自定義 Java 路徑設置為 `C:\Program Files\Java\jdk-17\bin\java.exe`
- 其他設置保持預設
* [MongoDB](https://www.mongodb.com/try/download/community) (推薦 4.0+)
* 代理程式: mitmproxy (推薦 mitmdump), Fiddler Classic 等
### 執行
**注意:** 從舊版本升級到新版本, 需要刪除 `config.json`
1. 獲取 `grasscutter.jar`
- 從 [actions](https://github.com/Grasscutters/Grasscutter/suites/6895963598/artifacts/267483297) 下載
- [自行編譯](#編譯)
2. 在 JAR 檔案根目錄中建立 `resources` 資料夾並複製 `BinOutput``ExcelBinOutput` *(查看 [wiki](https://github.com/Grasscutters/Grasscutter/wiki) 瞭解更多)*
3. 命令列 `java -jar grasscutter.jar` 執行 Grasscutter。**在此之前請確認 MongoDB 服務執行正常**
### 客戶端連線
½. 在伺服器控制台[建立賬戶](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting)
1. 重定向流量: (選擇其中一個)
- mitmdump: `mitmdump -s proxy.py -k`
信任 CA 證書:
**注意:** mitmproxy 的 CA 證書通常存放在 `%USERPROFILE%\ .mitmproxy`, 或者在 `http://mitm.it` 下載證書
雙擊[安裝根證書](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate)或者...
- 使用命令列
```shell
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic: 執行 Fiddler Classic, 在設定中開啟 `解密 https 通訊` 並將通訊埠設為除 `8888` 以外的任意通訊埠 (工具 -> 選項 -> 連線) 並載入[此指令碼](https://github.lunatic.moe/fiddlerscript)
- [Hosts 檔案](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
2. 設定代理為 `127.0.0.1:8080` 或你設定的通訊埠
**也可直接執行 `start.cmd` 一鍵啟動服務端並設定代理, 但必須設定 `JAVA_HOME` 環境變數**
- 點擊啟動旁邊的小按鈕。
- 點擊啟動按鈕。
- 用你想要的用戶名登錄,密碼無所謂。
### 編譯

View File

@ -0,0 +1,539 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: AbilityActionSetRandomOverrideMapValue.proto
package emu.grasscutter.net.proto;
public final class AbilityActionSetRandomOverrideMapValueOuterClass {
private AbilityActionSetRandomOverrideMapValueOuterClass() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface AbilityActionSetRandomOverrideMapValueOrBuilder extends
// @@protoc_insertion_point(interface_extends:AbilityActionSetRandomOverrideMapValue)
com.google.protobuf.MessageOrBuilder {
/**
* <code>float random_value = 1;</code>
* @return The randomValue.
*/
float getRandomValue();
}
/**
* Protobuf type {@code AbilityActionSetRandomOverrideMapValue}
*/
public static final class AbilityActionSetRandomOverrideMapValue extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:AbilityActionSetRandomOverrideMapValue)
AbilityActionSetRandomOverrideMapValueOrBuilder {
private static final long serialVersionUID = 0L;
// Use AbilityActionSetRandomOverrideMapValue.newBuilder() to construct.
private AbilityActionSetRandomOverrideMapValue(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private AbilityActionSetRandomOverrideMapValue() {
}
@java.lang.Override
@SuppressWarnings({"unused"})
protected java.lang.Object newInstance(
UnusedPrivateParameter unused) {
return new AbilityActionSetRandomOverrideMapValue();
}
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private AbilityActionSetRandomOverrideMapValue(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 13: {
randomValue_ = input.readFloat();
break;
}
default: {
if (!parseUnknownField(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.internal_static_AbilityActionSetRandomOverrideMapValue_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.internal_static_AbilityActionSetRandomOverrideMapValue_fieldAccessorTable
.ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.class, emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.Builder.class);
}
public static final int RANDOM_VALUE_FIELD_NUMBER = 1;
private float randomValue_;
/**
* <code>float random_value = 1;</code>
* @return The randomValue.
*/
@java.lang.Override
public float getRandomValue() {
return randomValue_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (randomValue_ != 0F) {
output.writeFloat(1, randomValue_);
}
unknownFields.writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (randomValue_ != 0F) {
size += com.google.protobuf.CodedOutputStream
.computeFloatSize(1, randomValue_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue)) {
return super.equals(obj);
}
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue other = (emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue) obj;
if (java.lang.Float.floatToIntBits(getRandomValue())
!= java.lang.Float.floatToIntBits(
other.getRandomValue())) return false;
if (!unknownFields.equals(other.unknownFields)) return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + RANDOM_VALUE_FIELD_NUMBER;
hash = (53 * hash) + java.lang.Float.floatToIntBits(
getRandomValue());
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code AbilityActionSetRandomOverrideMapValue}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:AbilityActionSetRandomOverrideMapValue)
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValueOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.internal_static_AbilityActionSetRandomOverrideMapValue_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.internal_static_AbilityActionSetRandomOverrideMapValue_fieldAccessorTable
.ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.class, emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.Builder.class);
}
// Construct using emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
@java.lang.Override
public Builder clear() {
super.clear();
randomValue_ = 0F;
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.internal_static_AbilityActionSetRandomOverrideMapValue_descriptor;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue getDefaultInstanceForType() {
return emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.getDefaultInstance();
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue build() {
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue buildPartial() {
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue result = new emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue(this);
result.randomValue_ = randomValue_;
onBuilt();
return result;
}
@java.lang.Override
public Builder clone() {
return super.clone();
}
@java.lang.Override
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return super.setField(field, value);
}
@java.lang.Override
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return super.clearField(field);
}
@java.lang.Override
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return super.clearOneof(oneof);
}
@java.lang.Override
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, java.lang.Object value) {
return super.setRepeatedField(field, index, value);
}
@java.lang.Override
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return super.addRepeatedField(field, value);
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue) {
return mergeFrom((emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue other) {
if (other == emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue.getDefaultInstance()) return this;
if (other.getRandomValue() != 0F) {
setRandomValue(other.getRandomValue());
}
this.mergeUnknownFields(other.unknownFields);
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private float randomValue_ ;
/**
* <code>float random_value = 1;</code>
* @return The randomValue.
*/
@java.lang.Override
public float getRandomValue() {
return randomValue_;
}
/**
* <code>float random_value = 1;</code>
* @param value The randomValue to set.
* @return This builder for chaining.
*/
public Builder setRandomValue(float value) {
randomValue_ = value;
onChanged();
return this;
}
/**
* <code>float random_value = 1;</code>
* @return This builder for chaining.
*/
public Builder clearRandomValue() {
randomValue_ = 0F;
onChanged();
return this;
}
@java.lang.Override
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.setUnknownFields(unknownFields);
}
@java.lang.Override
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.mergeUnknownFields(unknownFields);
}
// @@protoc_insertion_point(builder_scope:AbilityActionSetRandomOverrideMapValue)
}
// @@protoc_insertion_point(class_scope:AbilityActionSetRandomOverrideMapValue)
private static final emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue();
}
public static emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<AbilityActionSetRandomOverrideMapValue>
PARSER = new com.google.protobuf.AbstractParser<AbilityActionSetRandomOverrideMapValue>() {
@java.lang.Override
public AbilityActionSetRandomOverrideMapValue parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new AbilityActionSetRandomOverrideMapValue(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<AbilityActionSetRandomOverrideMapValue> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<AbilityActionSetRandomOverrideMapValue> getParserForType() {
return PARSER;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_AbilityActionSetRandomOverrideMapValue_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_AbilityActionSetRandomOverrideMapValue_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n,AbilityActionSetRandomOverrideMapValue" +
".proto\">\n&AbilityActionSetRandomOverride" +
"MapValue\022\024\n\014random_value\030\001 \001(\002B\033\n\031emu.gr" +
"asscutter.net.protob\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_AbilityActionSetRandomOverrideMapValue_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_AbilityActionSetRandomOverrideMapValue_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_AbilityActionSetRandomOverrideMapValue_descriptor,
new java.lang.String[] { "RandomValue", });
}
// @@protoc_insertion_point(outer_class_scope)
}

View File

@ -0,0 +1,545 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: AbilityMetaSetKilledState.proto
package emu.grasscutter.net.proto;
public final class AbilityMetaSetKilledStateOuterClass {
private AbilityMetaSetKilledStateOuterClass() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface AbilityMetaSetKilledStateOrBuilder extends
// @@protoc_insertion_point(interface_extends:AbilityMetaSetKilledState)
com.google.protobuf.MessageOrBuilder {
/**
* <code>bool killed = 6;</code>
* @return The killed.
*/
boolean getKilled();
}
/**
* <pre>
* Handcrafted by Magix!
* </pre>
*
* Protobuf type {@code AbilityMetaSetKilledState}
*/
public static final class AbilityMetaSetKilledState extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:AbilityMetaSetKilledState)
AbilityMetaSetKilledStateOrBuilder {
private static final long serialVersionUID = 0L;
// Use AbilityMetaSetKilledState.newBuilder() to construct.
private AbilityMetaSetKilledState(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private AbilityMetaSetKilledState() {
}
@java.lang.Override
@SuppressWarnings({"unused"})
protected java.lang.Object newInstance(
UnusedPrivateParameter unused) {
return new AbilityMetaSetKilledState();
}
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private AbilityMetaSetKilledState(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 48: {
killed_ = input.readBool();
break;
}
default: {
if (!parseUnknownField(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.internal_static_AbilityMetaSetKilledState_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.internal_static_AbilityMetaSetKilledState_fieldAccessorTable
.ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.class, emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.Builder.class);
}
public static final int KILLED_FIELD_NUMBER = 6;
private boolean killed_;
/**
* <code>bool killed = 6;</code>
* @return The killed.
*/
@java.lang.Override
public boolean getKilled() {
return killed_;
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (killed_ != false) {
output.writeBool(6, killed_);
}
unknownFields.writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (killed_ != false) {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(6, killed_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState)) {
return super.equals(obj);
}
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState other = (emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState) obj;
if (getKilled()
!= other.getKilled()) return false;
if (!unknownFields.equals(other.unknownFields)) return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + KILLED_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
getKilled());
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* <pre>
* Handcrafted by Magix!
* </pre>
*
* Protobuf type {@code AbilityMetaSetKilledState}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:AbilityMetaSetKilledState)
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledStateOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.internal_static_AbilityMetaSetKilledState_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.internal_static_AbilityMetaSetKilledState_fieldAccessorTable
.ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.class, emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.Builder.class);
}
// Construct using emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
@java.lang.Override
public Builder clear() {
super.clear();
killed_ = false;
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.internal_static_AbilityMetaSetKilledState_descriptor;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState getDefaultInstanceForType() {
return emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.getDefaultInstance();
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState build() {
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState buildPartial() {
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState result = new emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState(this);
result.killed_ = killed_;
onBuilt();
return result;
}
@java.lang.Override
public Builder clone() {
return super.clone();
}
@java.lang.Override
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return super.setField(field, value);
}
@java.lang.Override
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return super.clearField(field);
}
@java.lang.Override
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return super.clearOneof(oneof);
}
@java.lang.Override
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, java.lang.Object value) {
return super.setRepeatedField(field, index, value);
}
@java.lang.Override
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return super.addRepeatedField(field, value);
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState) {
return mergeFrom((emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState other) {
if (other == emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState.getDefaultInstance()) return this;
if (other.getKilled() != false) {
setKilled(other.getKilled());
}
this.mergeUnknownFields(other.unknownFields);
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private boolean killed_ ;
/**
* <code>bool killed = 6;</code>
* @return The killed.
*/
@java.lang.Override
public boolean getKilled() {
return killed_;
}
/**
* <code>bool killed = 6;</code>
* @param value The killed to set.
* @return This builder for chaining.
*/
public Builder setKilled(boolean value) {
killed_ = value;
onChanged();
return this;
}
/**
* <code>bool killed = 6;</code>
* @return This builder for chaining.
*/
public Builder clearKilled() {
killed_ = false;
onChanged();
return this;
}
@java.lang.Override
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.setUnknownFields(unknownFields);
}
@java.lang.Override
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.mergeUnknownFields(unknownFields);
}
// @@protoc_insertion_point(builder_scope:AbilityMetaSetKilledState)
}
// @@protoc_insertion_point(class_scope:AbilityMetaSetKilledState)
private static final emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState();
}
public static emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<AbilityMetaSetKilledState>
PARSER = new com.google.protobuf.AbstractParser<AbilityMetaSetKilledState>() {
@java.lang.Override
public AbilityMetaSetKilledState parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new AbilityMetaSetKilledState(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<AbilityMetaSetKilledState> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<AbilityMetaSetKilledState> getParserForType() {
return PARSER;
}
@java.lang.Override
public emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_AbilityMetaSetKilledState_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_AbilityMetaSetKilledState_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\037AbilityMetaSetKilledState.proto\"+\n\031Abi" +
"lityMetaSetKilledState\022\016\n\006killed\030\006 \001(\010B\033" +
"\n\031emu.grasscutter.net.protob\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
});
internal_static_AbilityMetaSetKilledState_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_AbilityMetaSetKilledState_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_AbilityMetaSetKilledState_descriptor,
new java.lang.String[] { "Killed", });
}
// @@protoc_insertion_point(outer_class_scope)
}

View File

@ -224,6 +224,123 @@ public final class ChatInfoOuterClass {
emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.class, emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.Builder.class);
}
/**
* Protobuf enum {@code ChatInfo.SystemHintType}
*/
public enum SystemHintType
implements com.google.protobuf.ProtocolMessageEnum {
/**
* <code>SYSTEM_HINT_TYPE_CHAT_NONE = 0;</code>
*/
SYSTEM_HINT_TYPE_CHAT_NONE(0),
/**
* <code>SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD = 1;</code>
*/
SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD(1),
/**
* <code>SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD = 2;</code>
*/
SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD(2),
UNRECOGNIZED(-1),
;
/**
* <code>SYSTEM_HINT_TYPE_CHAT_NONE = 0;</code>
*/
public static final int SYSTEM_HINT_TYPE_CHAT_NONE_VALUE = 0;
/**
* <code>SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD = 1;</code>
*/
public static final int SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD_VALUE = 1;
/**
* <code>SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD = 2;</code>
*/
public static final int SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD_VALUE = 2;
public final int getNumber() {
if (this == UNRECOGNIZED) {
throw new java.lang.IllegalArgumentException(
"Can't get the number of an unknown enum value.");
}
return value;
}
/**
* @param value The numeric wire value of the corresponding enum entry.
* @return The enum associated with the given numeric wire value.
* @deprecated Use {@link #forNumber(int)} instead.
*/
@java.lang.Deprecated
public static SystemHintType valueOf(int value) {
return forNumber(value);
}
/**
* @param value The numeric wire value of the corresponding enum entry.
* @return The enum associated with the given numeric wire value.
*/
public static SystemHintType forNumber(int value) {
switch (value) {
case 0: return SYSTEM_HINT_TYPE_CHAT_NONE;
case 1: return SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD;
case 2: return SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD;
default: return null;
}
}
public static com.google.protobuf.Internal.EnumLiteMap<SystemHintType>
internalGetValueMap() {
return internalValueMap;
}
private static final com.google.protobuf.Internal.EnumLiteMap<
SystemHintType> internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<SystemHintType>() {
public SystemHintType findValueByNumber(int number) {
return SystemHintType.forNumber(number);
}
};
public final com.google.protobuf.Descriptors.EnumValueDescriptor
getValueDescriptor() {
if (this == UNRECOGNIZED) {
throw new java.lang.IllegalStateException(
"Can't get the descriptor of an unrecognized enum value.");
}
return getDescriptor().getValues().get(ordinal());
}
public final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptorForType() {
return getDescriptor();
}
public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
return emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.getDescriptor().getEnumTypes().get(0);
}
private static final SystemHintType[] VALUES = values();
public static SystemHintType valueOf(
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
if (desc.getType() != getDescriptor()) {
throw new java.lang.IllegalArgumentException(
"EnumValueDescriptor is not for this type.");
}
if (desc.getIndex() == -1) {
return UNRECOGNIZED;
}
return VALUES[desc.getIndex()];
}
private final int value;
private SystemHintType(int value) {
this.value = value;
}
// @@protoc_insertion_point(enum_scope:ChatInfo.SystemHintType)
}
public interface SystemHintOrBuilder extends
// @@protoc_insertion_point(interface_extends:ChatInfo.SystemHint)
com.google.protobuf.MessageOrBuilder {
@ -1907,13 +2024,16 @@ public final class ChatInfoOuterClass {
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\016ChatInfo.proto\"\317\001\n\010ChatInfo\022\014\n\004time\030\007 " +
"\n\016ChatInfo.proto\"\317\002\n\010ChatInfo\022\014\n\004time\030\007 " +
"\001(\r\022\016\n\006to_uid\030\006 \001(\r\022\017\n\007is_read\030\004 \001(\010\022\013\n\003" +
"uid\030\005 \001(\r\022\020\n\010sequence\030\014 \001(\r\022\017\n\004text\030\230\003 \001" +
"(\tH\000\022\017\n\004icon\030\234\n \001(\rH\000\022,\n\013system_hint\030\246\001 " +
"\001(\0132\024.ChatInfo.SystemHintH\000\032\032\n\nSystemHin" +
"t\022\014\n\004type\030\r \001(\rB\t\n\007contentB\033\n\031emu.grassc" +
"utter.net.protob\006proto3"
"t\022\014\n\004type\030\r \001(\r\"~\n\016SystemHintType\022\036\n\032SYS" +
"TEM_HINT_TYPE_CHAT_NONE\020\000\022%\n!SYSTEM_HINT" +
"_TYPE_CHAT_ENTER_WORLD\020\001\022%\n!SYSTEM_HINT_" +
"TYPE_CHAT_LEAVE_WORLD\020\002B\t\n\007contentB\033\n\031em" +
"u.grasscutter.net.protob\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,

View File

@ -25,23 +25,23 @@ public final class ForgeQueueDataOuterClass {
int getAvatarId();
/**
* <code>uint32 unfinish_count = 15;</code>
* @return The unfinishCount.
*/
int getUnfinishCount();
/**
* <code>uint32 next_finish_timestamp = 13;</code>
* @return The nextFinishTimestamp.
*/
int getNextFinishTimestamp();
/**
* <code>uint32 finish_count = 4;</code>
* <code>uint32 finish_count = 15;</code>
* @return The finishCount.
*/
int getFinishCount();
/**
* <code>uint32 total_finish_timestamp = 13;</code>
* @return The totalFinishTimestamp.
*/
int getTotalFinishTimestamp();
/**
* <code>uint32 queue_id = 4;</code>
* @return The queueId.
*/
int getQueueId();
/**
* <code>uint32 forge_id = 1;</code>
* @return The forgeId.
@ -49,16 +49,16 @@ public final class ForgeQueueDataOuterClass {
int getForgeId();
/**
* <code>uint32 total_finish_timestamp = 8;</code>
* @return The totalFinishTimestamp.
* <code>uint32 next_finish_timestamp = 8;</code>
* @return The nextFinishTimestamp.
*/
int getTotalFinishTimestamp();
int getNextFinishTimestamp();
/**
* <code>uint32 queue_id = 9;</code>
* @return The queueId.
* <code>uint32 unfinish_count = 9;</code>
* @return The unfinishCount.
*/
int getQueueId();
int getUnfinishCount();
}
/**
* <pre>
@ -116,22 +116,22 @@ public final class ForgeQueueDataOuterClass {
}
case 32: {
finishCount_ = input.readUInt32();
queueId_ = input.readUInt32();
break;
}
case 64: {
totalFinishTimestamp_ = input.readUInt32();
nextFinishTimestamp_ = input.readUInt32();
break;
}
case 72: {
queueId_ = input.readUInt32();
unfinishCount_ = input.readUInt32();
break;
}
case 104: {
nextFinishTimestamp_ = input.readUInt32();
totalFinishTimestamp_ = input.readUInt32();
break;
}
case 112: {
@ -141,7 +141,7 @@ public final class ForgeQueueDataOuterClass {
}
case 120: {
unfinishCount_ = input.readUInt32();
finishCount_ = input.readUInt32();
break;
}
default: {
@ -187,32 +187,10 @@ public final class ForgeQueueDataOuterClass {
return avatarId_;
}
public static final int UNFINISH_COUNT_FIELD_NUMBER = 15;
private int unfinishCount_;
/**
* <code>uint32 unfinish_count = 15;</code>
* @return The unfinishCount.
*/
@java.lang.Override
public int getUnfinishCount() {
return unfinishCount_;
}
public static final int NEXT_FINISH_TIMESTAMP_FIELD_NUMBER = 13;
private int nextFinishTimestamp_;
/**
* <code>uint32 next_finish_timestamp = 13;</code>
* @return The nextFinishTimestamp.
*/
@java.lang.Override
public int getNextFinishTimestamp() {
return nextFinishTimestamp_;
}
public static final int FINISH_COUNT_FIELD_NUMBER = 4;
public static final int FINISH_COUNT_FIELD_NUMBER = 15;
private int finishCount_;
/**
* <code>uint32 finish_count = 4;</code>
* <code>uint32 finish_count = 15;</code>
* @return The finishCount.
*/
@java.lang.Override
@ -220,6 +198,28 @@ public final class ForgeQueueDataOuterClass {
return finishCount_;
}
public static final int TOTAL_FINISH_TIMESTAMP_FIELD_NUMBER = 13;
private int totalFinishTimestamp_;
/**
* <code>uint32 total_finish_timestamp = 13;</code>
* @return The totalFinishTimestamp.
*/
@java.lang.Override
public int getTotalFinishTimestamp() {
return totalFinishTimestamp_;
}
public static final int QUEUE_ID_FIELD_NUMBER = 4;
private int queueId_;
/**
* <code>uint32 queue_id = 4;</code>
* @return The queueId.
*/
@java.lang.Override
public int getQueueId() {
return queueId_;
}
public static final int FORGE_ID_FIELD_NUMBER = 1;
private int forgeId_;
/**
@ -231,26 +231,26 @@ public final class ForgeQueueDataOuterClass {
return forgeId_;
}
public static final int TOTAL_FINISH_TIMESTAMP_FIELD_NUMBER = 8;
private int totalFinishTimestamp_;
public static final int NEXT_FINISH_TIMESTAMP_FIELD_NUMBER = 8;
private int nextFinishTimestamp_;
/**
* <code>uint32 total_finish_timestamp = 8;</code>
* @return The totalFinishTimestamp.
* <code>uint32 next_finish_timestamp = 8;</code>
* @return The nextFinishTimestamp.
*/
@java.lang.Override
public int getTotalFinishTimestamp() {
return totalFinishTimestamp_;
public int getNextFinishTimestamp() {
return nextFinishTimestamp_;
}
public static final int QUEUE_ID_FIELD_NUMBER = 9;
private int queueId_;
public static final int UNFINISH_COUNT_FIELD_NUMBER = 9;
private int unfinishCount_;
/**
* <code>uint32 queue_id = 9;</code>
* @return The queueId.
* <code>uint32 unfinish_count = 9;</code>
* @return The unfinishCount.
*/
@java.lang.Override
public int getQueueId() {
return queueId_;
public int getUnfinishCount() {
return unfinishCount_;
}
private byte memoizedIsInitialized = -1;
@ -270,23 +270,23 @@ public final class ForgeQueueDataOuterClass {
if (forgeId_ != 0) {
output.writeUInt32(1, forgeId_);
}
if (finishCount_ != 0) {
output.writeUInt32(4, finishCount_);
}
if (totalFinishTimestamp_ != 0) {
output.writeUInt32(8, totalFinishTimestamp_);
}
if (queueId_ != 0) {
output.writeUInt32(9, queueId_);
output.writeUInt32(4, queueId_);
}
if (nextFinishTimestamp_ != 0) {
output.writeUInt32(13, nextFinishTimestamp_);
output.writeUInt32(8, nextFinishTimestamp_);
}
if (unfinishCount_ != 0) {
output.writeUInt32(9, unfinishCount_);
}
if (totalFinishTimestamp_ != 0) {
output.writeUInt32(13, totalFinishTimestamp_);
}
if (avatarId_ != 0) {
output.writeUInt32(14, avatarId_);
}
if (unfinishCount_ != 0) {
output.writeUInt32(15, unfinishCount_);
if (finishCount_ != 0) {
output.writeUInt32(15, finishCount_);
}
unknownFields.writeTo(output);
}
@ -301,29 +301,29 @@ public final class ForgeQueueDataOuterClass {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(1, forgeId_);
}
if (finishCount_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(4, finishCount_);
}
if (totalFinishTimestamp_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(8, totalFinishTimestamp_);
}
if (queueId_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(9, queueId_);
.computeUInt32Size(4, queueId_);
}
if (nextFinishTimestamp_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(13, nextFinishTimestamp_);
.computeUInt32Size(8, nextFinishTimestamp_);
}
if (unfinishCount_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(9, unfinishCount_);
}
if (totalFinishTimestamp_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(13, totalFinishTimestamp_);
}
if (avatarId_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(14, avatarId_);
}
if (unfinishCount_ != 0) {
if (finishCount_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(15, unfinishCount_);
.computeUInt32Size(15, finishCount_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
@ -342,18 +342,18 @@ public final class ForgeQueueDataOuterClass {
if (getAvatarId()
!= other.getAvatarId()) return false;
if (getUnfinishCount()
!= other.getUnfinishCount()) return false;
if (getNextFinishTimestamp()
!= other.getNextFinishTimestamp()) return false;
if (getFinishCount()
!= other.getFinishCount()) return false;
if (getForgeId()
!= other.getForgeId()) return false;
if (getTotalFinishTimestamp()
!= other.getTotalFinishTimestamp()) return false;
if (getQueueId()
!= other.getQueueId()) return false;
if (getForgeId()
!= other.getForgeId()) return false;
if (getNextFinishTimestamp()
!= other.getNextFinishTimestamp()) return false;
if (getUnfinishCount()
!= other.getUnfinishCount()) return false;
if (!unknownFields.equals(other.unknownFields)) return false;
return true;
}
@ -367,18 +367,18 @@ public final class ForgeQueueDataOuterClass {
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + AVATAR_ID_FIELD_NUMBER;
hash = (53 * hash) + getAvatarId();
hash = (37 * hash) + UNFINISH_COUNT_FIELD_NUMBER;
hash = (53 * hash) + getUnfinishCount();
hash = (37 * hash) + NEXT_FINISH_TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + getNextFinishTimestamp();
hash = (37 * hash) + FINISH_COUNT_FIELD_NUMBER;
hash = (53 * hash) + getFinishCount();
hash = (37 * hash) + FORGE_ID_FIELD_NUMBER;
hash = (53 * hash) + getForgeId();
hash = (37 * hash) + TOTAL_FINISH_TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + getTotalFinishTimestamp();
hash = (37 * hash) + QUEUE_ID_FIELD_NUMBER;
hash = (53 * hash) + getQueueId();
hash = (37 * hash) + FORGE_ID_FIELD_NUMBER;
hash = (53 * hash) + getForgeId();
hash = (37 * hash) + NEXT_FINISH_TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + getNextFinishTimestamp();
hash = (37 * hash) + UNFINISH_COUNT_FIELD_NUMBER;
hash = (53 * hash) + getUnfinishCount();
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
@ -518,18 +518,18 @@ public final class ForgeQueueDataOuterClass {
super.clear();
avatarId_ = 0;
unfinishCount_ = 0;
nextFinishTimestamp_ = 0;
finishCount_ = 0;
forgeId_ = 0;
totalFinishTimestamp_ = 0;
queueId_ = 0;
forgeId_ = 0;
nextFinishTimestamp_ = 0;
unfinishCount_ = 0;
return this;
}
@ -557,12 +557,12 @@ public final class ForgeQueueDataOuterClass {
public emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData buildPartial() {
emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData result = new emu.grasscutter.net.proto.ForgeQueueDataOuterClass.ForgeQueueData(this);
result.avatarId_ = avatarId_;
result.unfinishCount_ = unfinishCount_;
result.nextFinishTimestamp_ = nextFinishTimestamp_;
result.finishCount_ = finishCount_;
result.forgeId_ = forgeId_;
result.totalFinishTimestamp_ = totalFinishTimestamp_;
result.queueId_ = queueId_;
result.forgeId_ = forgeId_;
result.nextFinishTimestamp_ = nextFinishTimestamp_;
result.unfinishCount_ = unfinishCount_;
onBuilt();
return result;
}
@ -614,24 +614,24 @@ public final class ForgeQueueDataOuterClass {
if (other.getAvatarId() != 0) {
setAvatarId(other.getAvatarId());
}
if (other.getUnfinishCount() != 0) {
setUnfinishCount(other.getUnfinishCount());
}
if (other.getNextFinishTimestamp() != 0) {
setNextFinishTimestamp(other.getNextFinishTimestamp());
}
if (other.getFinishCount() != 0) {
setFinishCount(other.getFinishCount());
}
if (other.getForgeId() != 0) {
setForgeId(other.getForgeId());
}
if (other.getTotalFinishTimestamp() != 0) {
setTotalFinishTimestamp(other.getTotalFinishTimestamp());
}
if (other.getQueueId() != 0) {
setQueueId(other.getQueueId());
}
if (other.getForgeId() != 0) {
setForgeId(other.getForgeId());
}
if (other.getNextFinishTimestamp() != 0) {
setNextFinishTimestamp(other.getNextFinishTimestamp());
}
if (other.getUnfinishCount() != 0) {
setUnfinishCount(other.getUnfinishCount());
}
this.mergeUnknownFields(other.unknownFields);
onChanged();
return this;
@ -692,71 +692,9 @@ public final class ForgeQueueDataOuterClass {
return this;
}
private int unfinishCount_ ;
/**
* <code>uint32 unfinish_count = 15;</code>
* @return The unfinishCount.
*/
@java.lang.Override
public int getUnfinishCount() {
return unfinishCount_;
}
/**
* <code>uint32 unfinish_count = 15;</code>
* @param value The unfinishCount to set.
* @return This builder for chaining.
*/
public Builder setUnfinishCount(int value) {
unfinishCount_ = value;
onChanged();
return this;
}
/**
* <code>uint32 unfinish_count = 15;</code>
* @return This builder for chaining.
*/
public Builder clearUnfinishCount() {
unfinishCount_ = 0;
onChanged();
return this;
}
private int nextFinishTimestamp_ ;
/**
* <code>uint32 next_finish_timestamp = 13;</code>
* @return The nextFinishTimestamp.
*/
@java.lang.Override
public int getNextFinishTimestamp() {
return nextFinishTimestamp_;
}
/**
* <code>uint32 next_finish_timestamp = 13;</code>
* @param value The nextFinishTimestamp to set.
* @return This builder for chaining.
*/
public Builder setNextFinishTimestamp(int value) {
nextFinishTimestamp_ = value;
onChanged();
return this;
}
/**
* <code>uint32 next_finish_timestamp = 13;</code>
* @return This builder for chaining.
*/
public Builder clearNextFinishTimestamp() {
nextFinishTimestamp_ = 0;
onChanged();
return this;
}
private int finishCount_ ;
/**
* <code>uint32 finish_count = 4;</code>
* <code>uint32 finish_count = 15;</code>
* @return The finishCount.
*/
@java.lang.Override
@ -764,7 +702,7 @@ public final class ForgeQueueDataOuterClass {
return finishCount_;
}
/**
* <code>uint32 finish_count = 4;</code>
* <code>uint32 finish_count = 15;</code>
* @param value The finishCount to set.
* @return This builder for chaining.
*/
@ -775,7 +713,7 @@ public final class ForgeQueueDataOuterClass {
return this;
}
/**
* <code>uint32 finish_count = 4;</code>
* <code>uint32 finish_count = 15;</code>
* @return This builder for chaining.
*/
public Builder clearFinishCount() {
@ -785,6 +723,68 @@ public final class ForgeQueueDataOuterClass {
return this;
}
private int totalFinishTimestamp_ ;
/**
* <code>uint32 total_finish_timestamp = 13;</code>
* @return The totalFinishTimestamp.
*/
@java.lang.Override
public int getTotalFinishTimestamp() {
return totalFinishTimestamp_;
}
/**
* <code>uint32 total_finish_timestamp = 13;</code>
* @param value The totalFinishTimestamp to set.
* @return This builder for chaining.
*/
public Builder setTotalFinishTimestamp(int value) {
totalFinishTimestamp_ = value;
onChanged();
return this;
}
/**
* <code>uint32 total_finish_timestamp = 13;</code>
* @return This builder for chaining.
*/
public Builder clearTotalFinishTimestamp() {
totalFinishTimestamp_ = 0;
onChanged();
return this;
}
private int queueId_ ;
/**
* <code>uint32 queue_id = 4;</code>
* @return The queueId.
*/
@java.lang.Override
public int getQueueId() {
return queueId_;
}
/**
* <code>uint32 queue_id = 4;</code>
* @param value The queueId to set.
* @return This builder for chaining.
*/
public Builder setQueueId(int value) {
queueId_ = value;
onChanged();
return this;
}
/**
* <code>uint32 queue_id = 4;</code>
* @return This builder for chaining.
*/
public Builder clearQueueId() {
queueId_ = 0;
onChanged();
return this;
}
private int forgeId_ ;
/**
* <code>uint32 forge_id = 1;</code>
@ -816,64 +816,64 @@ public final class ForgeQueueDataOuterClass {
return this;
}
private int totalFinishTimestamp_ ;
private int nextFinishTimestamp_ ;
/**
* <code>uint32 total_finish_timestamp = 8;</code>
* @return The totalFinishTimestamp.
* <code>uint32 next_finish_timestamp = 8;</code>
* @return The nextFinishTimestamp.
*/
@java.lang.Override
public int getTotalFinishTimestamp() {
return totalFinishTimestamp_;
public int getNextFinishTimestamp() {
return nextFinishTimestamp_;
}
/**
* <code>uint32 total_finish_timestamp = 8;</code>
* @param value The totalFinishTimestamp to set.
* <code>uint32 next_finish_timestamp = 8;</code>
* @param value The nextFinishTimestamp to set.
* @return This builder for chaining.
*/
public Builder setTotalFinishTimestamp(int value) {
public Builder setNextFinishTimestamp(int value) {
totalFinishTimestamp_ = value;
nextFinishTimestamp_ = value;
onChanged();
return this;
}
/**
* <code>uint32 total_finish_timestamp = 8;</code>
* <code>uint32 next_finish_timestamp = 8;</code>
* @return This builder for chaining.
*/
public Builder clearTotalFinishTimestamp() {
public Builder clearNextFinishTimestamp() {
totalFinishTimestamp_ = 0;
nextFinishTimestamp_ = 0;
onChanged();
return this;
}
private int queueId_ ;
private int unfinishCount_ ;
/**
* <code>uint32 queue_id = 9;</code>
* @return The queueId.
* <code>uint32 unfinish_count = 9;</code>
* @return The unfinishCount.
*/
@java.lang.Override
public int getQueueId() {
return queueId_;
public int getUnfinishCount() {
return unfinishCount_;
}
/**
* <code>uint32 queue_id = 9;</code>
* @param value The queueId to set.
* <code>uint32 unfinish_count = 9;</code>
* @param value The unfinishCount to set.
* @return This builder for chaining.
*/
public Builder setQueueId(int value) {
public Builder setUnfinishCount(int value) {
queueId_ = value;
unfinishCount_ = value;
onChanged();
return this;
}
/**
* <code>uint32 queue_id = 9;</code>
* <code>uint32 unfinish_count = 9;</code>
* @return This builder for chaining.
*/
public Builder clearQueueId() {
public Builder clearUnfinishCount() {
queueId_ = 0;
unfinishCount_ = 0;
onChanged();
return this;
}
@ -945,10 +945,10 @@ public final class ForgeQueueDataOuterClass {
static {
java.lang.String[] descriptorData = {
"\n\024ForgeQueueData.proto\"\264\001\n\016ForgeQueueDat" +
"a\022\021\n\tavatar_id\030\016 \001(\r\022\026\n\016unfinish_count\030\017" +
" \001(\r\022\035\n\025next_finish_timestamp\030\r \001(\r\022\024\n\014f" +
"inish_count\030\004 \001(\r\022\020\n\010forge_id\030\001 \001(\r\022\036\n\026t" +
"otal_finish_timestamp\030\010 \001(\r\022\020\n\010queue_id\030" +
"a\022\021\n\tavatar_id\030\016 \001(\r\022\024\n\014finish_count\030\017 \001" +
"(\r\022\036\n\026total_finish_timestamp\030\r \001(\r\022\020\n\010qu" +
"eue_id\030\004 \001(\r\022\020\n\010forge_id\030\001 \001(\r\022\035\n\025next_f" +
"inish_timestamp\030\010 \001(\r\022\026\n\016unfinish_count\030" +
"\t \001(\rB\033\n\031emu.grasscutter.net.protob\006prot" +
"o3"
};
@ -961,7 +961,7 @@ public final class ForgeQueueDataOuterClass {
internal_static_ForgeQueueData_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_ForgeQueueData_descriptor,
new java.lang.String[] { "AvatarId", "UnfinishCount", "NextFinishTimestamp", "FinishCount", "ForgeId", "TotalFinishTimestamp", "QueueId", });
new java.lang.String[] { "AvatarId", "FinishCount", "TotalFinishTimestamp", "QueueId", "ForgeId", "NextFinishTimestamp", "UnfinishCount", });
}
// @@protoc_insertion_point(outer_class_scope)

View File

@ -8,7 +8,7 @@ import emu.grasscutter.auth.*;
import emu.grasscutter.command.*;
import emu.grasscutter.config.ConfigContainer;
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.database.DatabaseManager;
import emu.grasscutter.database.*;
import emu.grasscutter.plugin.PluginManager;
import emu.grasscutter.plugin.api.ServerHelper;
import emu.grasscutter.server.dispatch.DispatchServer;
@ -183,6 +183,25 @@ public final class Grasscutter {
private static void onShutdown() {
// Disable all plugins.
if (pluginManager != null) pluginManager.disablePlugins();
// Shutdown the game server.
if (gameServer != null) gameServer.onServerShutdown();
try {
// Wait for Grasscutter's thread pool to finish.
var executor = Grasscutter.getThreadPool();
executor.shutdown();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
// Wait for database operations to finish.
var dbExecutor = DatabaseHelper.getEventExecutor();
dbExecutor.shutdown();
if (!dbExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
dbExecutor.shutdownNow();
}
} catch (InterruptedException ignored) {
}
}
/*

View File

@ -5,8 +5,7 @@ import static emu.grasscutter.config.Configuration.SERVER;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.*;
import java.util.*;
import org.reflections.Reflections;

View File

@ -4,11 +4,9 @@ import static emu.grasscutter.utils.lang.Language.translate;
import at.favre.lib.crypto.bcrypt.BCrypt;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.command.*;
import emu.grasscutter.config.Configuration;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.database.DatabaseManager;
import emu.grasscutter.database.*;
import emu.grasscutter.game.Account;
import emu.grasscutter.game.player.Player;
import java.util.List;
@ -31,17 +29,17 @@ public final class AccountCommand implements CommandHandler {
return;
}
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
String action = args.get(0);
String username = args.get(1);
switch (action) {
default -> this.sendUsageMessage(sender);
case "create" -> {
if (args.size() < 2) {
this.sendUsageMessage(sender);
return;
}
var username = args.get(1);
int uid = 0;
String password = "";
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
@ -94,6 +92,12 @@ public final class AccountCommand implements CommandHandler {
}
}
case "delete" -> {
if (args.size() < 2) {
this.sendUsageMessage(sender);
return;
}
var username = args.get(1);
// Get the account we want to delete.
Account toDelete = DatabaseHelper.getAccountByName(username);
if (toDelete == null) {
@ -104,6 +108,12 @@ public final class AccountCommand implements CommandHandler {
CommandHandler.sendMessage(sender, translate(sender, "commands.account.delete"));
}
case "resetpass" -> {
if (args.size() < 2) {
this.sendUsageMessage(sender);
return;
}
var username = args.get(1);
if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
CommandHandler.sendMessage(
sender, "resetpass requires EXPERIMENTAL_RealPassword to be true.");

View File

@ -11,8 +11,8 @@ import lombok.val;
label = "cutscene",
aliases = {"c"},
usage = {"[<cutsceneId>]"},
permission = "player.group",
permissionTargeted = "player.group.others")
permission = "player.cutscene",
permissionTargeted = "player.cutscene.others")
public final class CutsceneCommand implements CommandHandler {
@Override

View File

@ -12,7 +12,7 @@ import java.util.Map;
@Command(
label = "list",
aliases = {"players"},
usage = {"[<UID>]"},
usage = {"[uid]"},
targetRequirement = Command.TargetRequirement.NONE)
public final class ListCommand implements CommandHandler {

View File

@ -2,23 +2,23 @@ package emu.grasscutter.command.commands;
import static emu.grasscutter.utils.lang.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.command.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameQuest;
import java.util.List;
import java.util.stream.Collectors;
@Command(
label = "quest",
aliases = {"q"},
usage = {"(add|finish) [<questId>]"},
usage = {"(add|finish|running|talking|debug|triggers|grouptriggers) [<questId>]", "dungeons"},
permission = "player.quest",
permissionTargeted = "player.quest.others")
public final class QuestCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() != 2) {
if (args.size() != 2 || (args.size() == 1 && !args.get(0).toLowerCase().equals("dungeons"))) {
sendUsageMessage(sender);
return;
}
@ -112,7 +112,7 @@ public final class QuestCommand implements CommandHandler {
var shouldAdd = !loggedQuests.contains(questId);
if (shouldAdd) loggedQuests.add(questId);
else loggedQuests.remove(questId);
else loggedQuests.remove(loggedQuests.indexOf(questId));
CommandHandler.sendMessage(
sender,
@ -131,6 +131,22 @@ public final class QuestCommand implements CommandHandler {
"Triggers registered for %s: %s."
.formatted(questId, String.join(", ", quest.getTriggers().keySet())));
}
case "grouptriggers" -> {
var scene = targetPlayer.getScene();
var scriptManager = scene.getScriptManager();
var group = scriptManager.getGroupById(questId);
if (group == null) {
CommandHandler.sendMessage(sender, "The group does not exist.");
return;
}
CommandHandler.sendMessage(
sender,
group.triggers.entrySet().stream()
.map(entry -> "%s: %s".formatted(entry.getKey(), entry.getValue()))
.collect(Collectors.joining(", ")));
}
default -> this.sendUsageMessage(sender);
}
}

View File

@ -12,6 +12,7 @@ import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.IntStream;
@Command(
@ -107,6 +108,7 @@ public final class SetPropCommand implements CommandHandler {
case "on", "true" -> 1;
case "off", "false" -> 0;
case "toggle" -> -1;
case "all" -> -2;
default -> Integer.parseInt(valueStr);
};
} catch (NumberFormatException ignored) {
@ -126,7 +128,7 @@ public final class SetPropCommand implements CommandHandler {
sender, targetPlayer, prop.pseudoProp, value);
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
case UNLOCK_MAP -> unlockMap(targetPlayer);
case UNLOCK_MAP -> unlockMap(targetPlayer, value);
default -> targetPlayer.setProperty(prop.prop, value);
};
@ -217,13 +219,30 @@ public final class SetPropCommand implements CommandHandler {
return true;
}
private boolean unlockMap(Player targetPlayer) {
private boolean unlockMap(Player targetPlayer, int value) {
// Unlock.
GameData.getScenePointsPerScene()
.forEach(
(sceneId, scenePoints) -> {
// Unlock trans points.
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
if (value == -2) {
// Unlock trans points.
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
} else {
var scenePointsBackup = new CopyOnWriteArrayList<>(scenePoints);
for (var p : scenePointsBackup) {
var scenePointEentry = GameData.getScenePointEntryById(sceneId, p);
var pointData = scenePointEentry.getPointData();
boolean forbidSimpleUnlock = pointData.isForbidSimpleUnlock();
boolean sceneBuildingPointLocked =
pointData.getType().equals("SceneBuildingPoint") && !pointData.isUnlocked();
if (forbidSimpleUnlock || sceneBuildingPointLocked) scenePointsBackup.remove(p);
}
// Unlock trans points.
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePointsBackup);
}
// Unlock map areas.
targetPlayer.getUnlockedSceneAreas(sceneId).addAll(sceneAreas);

View File

@ -14,8 +14,8 @@ import lombok.val;
label = "sound",
aliases = {"s", "audio"},
usage = {"[<audioname>] [<x><y><z>]"},
permission = "player.group",
permissionTargeted = "player.group.others")
permission = "player.sound",
permissionTargeted = "player.sound.others")
public final class SoundCommand implements CommandHandler {
@Override

View File

@ -17,19 +17,21 @@ import static emu.grasscutter.Grasscutter.*;
public class ConfigContainer {
/*
* Configuration changes:
* Version 5 - 'questing' has been changed from a boolean
* to a container of options ('questOptions').
* This field will be removed in future versions.
* Version 6 - 'questing' has been fully replaced with 'questOptions'.
* The field for 'legacyResources' has been removed.
* Version 7 - 'regionKey' is being added for authentication
* with the new dispatch server.
* Version 8 - 'server' is being added for enforcing handbook server
* addresses.
* Version 9 - 'limits' was added for handbook requests.
* Version 5 - 'questing' has been changed from a boolean
* to a container of options ('questOptions').
* This field will be removed in future versions.
* Version 6 - 'questing' has been fully replaced with 'questOptions'.
* The field for 'legacyResources' has been removed.
* Version 7 - 'regionKey' is being added for authentication
* with the new dispatch server.
* Version 8 - 'server' is being added for enforcing handbook server
* addresses.
* Version 9 - 'limits' was added for handbook requests.
* Version 10 - 'trialCostumes' was added for enabling costumes
* on trial avatars.
*/
private static int version() {
return 9;
return 10;
}
/**
@ -255,6 +257,8 @@ public class ConfigContainer {
public boolean staminaUsage = true;
public boolean energyUsage = true;
public boolean fishhookTeleport = true;
public boolean trialCostumes = false;
@SerializedName(value = "questing", alternate = "questOptions")
public Questing questing = new Questing();
public ResinOptions resinOptions = new ResinOptions();

View File

@ -37,8 +37,11 @@ import emu.grasscutter.data.excels.world.WeatherData;
import emu.grasscutter.data.excels.world.WorldAreaData;
import emu.grasscutter.data.excels.world.WorldLevelData;
import emu.grasscutter.data.server.ActivityCondGroup;
import emu.grasscutter.data.server.DropSubfieldMapping;
import emu.grasscutter.data.server.DropTableExcelConfigData;
import emu.grasscutter.data.server.GadgetMapping;
import emu.grasscutter.data.server.MonsterMapping;
import emu.grasscutter.data.server.SubfieldMapping;
import emu.grasscutter.game.dungeons.DungeonDropEntry;
import emu.grasscutter.game.quest.QuestEncryptionKey;
import emu.grasscutter.game.quest.RewindData;
@ -451,6 +454,18 @@ public final class GameData {
private static final Int2ObjectMap<GadgetMapping> gadgetMappingMap =
new Int2ObjectOpenHashMap<>();
@Getter
private static final Int2ObjectMap<SubfieldMapping> subfieldMappingMap =
new Int2ObjectOpenHashMap<>();
@Getter
private static final Int2ObjectMap<DropSubfieldMapping> dropSubfieldMappingMap =
new Int2ObjectOpenHashMap<>();
@Getter
private static final Int2ObjectMap<DropTableExcelConfigData> dropTableExcelConfigDataMap =
new Int2ObjectOpenHashMap<>();
@Getter
private static final Int2ObjectMap<MonsterMapping> monsterMappingMap =
new Int2ObjectOpenHashMap<>();

View File

@ -9,6 +9,7 @@ import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.*;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.binout.config.*;
import emu.grasscutter.data.binout.routes.*;
import emu.grasscutter.data.common.PointData;
import emu.grasscutter.data.custom.*;
import emu.grasscutter.data.excels.trial.TrialAvatarActivityDataData;
@ -107,6 +108,7 @@ public final class ResourceLoader {
// Load default home layout
loadHomeworldDefaultSaveData();
loadNpcBornData();
loadRoutes();
loadBlossomResources();
cacheTalentLevelSets();
// Load activities.
@ -116,6 +118,7 @@ public final class ResourceLoader {
loadConfigLevelEntityData();
loadQuestShareConfig();
loadGadgetMappings();
loadSubfieldMappings();
loadMonsterMappings();
loadActivityCondGroups();
loadGroupReplacements();
@ -263,6 +266,32 @@ public final class ResourceLoader {
}
}
private static void loadRoutes() {
try {
Files.newDirectoryStream(getResourcePath("BinOutput/LevelDesign/Routes/"), "*.json")
.forEach(
path -> {
try {
val data = JsonUtils.loadToClass(path, SceneRoutes.class);
val routesArray = data.getRoutes();
if (routesArray == null) return;
val routesMap =
GameData.getSceneRouteData()
.getOrDefault(data.getSceneId(), new Int2ObjectOpenHashMap<>());
for (Route route : routesArray) {
routesMap.put(route.getLocalId(), route);
}
GameData.getSceneRouteData().put(data.getSceneId(), routesMap);
} catch (IOException ignored) {
}
});
Grasscutter.getLogger()
.debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneRouteDatas.");
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to load SceneRouteData folder.");
}
}
private static void cacheTalentLevelSets() {
// All known levels, keyed by proudSkillGroupId
GameData.getProudSkillDataMap()
@ -805,6 +834,51 @@ public final class ResourceLoader {
}
}
private static void loadSubfieldMappings() {
try {
val subfieldMap = GameData.getSubfieldMappingMap();
try {
JsonUtils.loadToList(getResourcePath("Server/SubfieldMapping.json"), SubfieldMapping.class)
.forEach(entry -> subfieldMap.put(entry.getEntityId(), entry));
;
} catch (IOException | NullPointerException ignored) {
}
Grasscutter.getLogger().debug("Loaded {} subfield mappings.", subfieldMap.size());
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load subfield mappings.", e);
}
try {
val dropSubfieldMap = GameData.getDropSubfieldMappingMap();
try {
JsonUtils.loadToList(
getResourcePath("Server/DropSubfieldMapping.json"), DropSubfieldMapping.class)
.forEach(entry -> dropSubfieldMap.put(entry.getDropId(), entry));
;
} catch (IOException | NullPointerException ignored) {
}
Grasscutter.getLogger().debug("Loaded {} drop subfield mappings.", dropSubfieldMap.size());
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load drop subfield mappings.", e);
}
try {
val dropTableExcelConfigDataMap = GameData.getDropTableExcelConfigDataMap();
try {
JsonUtils.loadToList(
getResourcePath("Server/DropTableExcelConfigData.json"),
DropTableExcelConfigData.class)
.forEach(entry -> dropTableExcelConfigDataMap.put(entry.getId(), entry));
;
} catch (IOException | NullPointerException ignored) {
}
Grasscutter.getLogger()
.debug("Loaded {} drop table configs.", dropTableExcelConfigDataMap.size());
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load drop table config data.", e);
}
}
private static void loadMonsterMappings() {
try {
var monsterMap = GameData.getMonsterMappingMap();

View File

@ -87,7 +87,10 @@ public class AbilityData {
}
private void initializeModifiers() {
if (modifiers == null) return;
if (modifiers == null) {
this.modifiers = new HashMap<>();
return;
}
var _modifiers =
modifiers.entrySet().stream()

View File

@ -323,9 +323,28 @@ public class AbilityModifier implements Serializable {
public int skillID;
public AbilityModifierAction[] actions;
public AbilityModifierAction[] successActions;
public AbilityModifierAction[] failActions;
public DropType dropType = DropType.LevelControl;
public DynamicFloat baseEnergy;
public DynamicFloat ratio = DynamicFloat.ONE;
public int configID;
public DynamicFloat valueRangeMin;
public DynamicFloat valueRangeMax;
public String overrideMapKey;
public int param1;
public int param2;
public int param3;
public enum DropType {
LevelControl,
BigWorldOnly,
ForceDrop
}
}
// The following should be implemented into DynamicFloat if older resource formats need to be

View File

@ -11,38 +11,58 @@ import lombok.experimental.FieldDefaults;
@FieldDefaults(level = AccessLevel.PRIVATE)
public class HomeworldDefaultSaveData {
@SerializedName(value = "KFHBFNPDJBE", alternate = "PKACPHDGGEI")
@SerializedName(
value = "KFHBFNPDJBE",
alternate = {"PKACPHDGGEI", "AKOLOBLHDFK"})
List<HomeBlock> homeBlockLists;
@SerializedName(value = "IJNPADKGNKE", alternate = "MINCKHBNING")
@SerializedName(
value = "IJNPADKGNKE",
alternate = {"MINCKHBNING", "MBICDPDEKDM"})
Position bornPos;
@SerializedName("IPIIGEMFLHK")
@SerializedName(
value = "IPIIGEMFLHK",
alternate = {"EJJIOJKFKCO"})
Position bornRot;
@SerializedName("HHOLBNPIHEM")
@SerializedName(
value = "HHOLBNPIHEM",
alternate = {"CJAKHCIFHNP"})
Position djinPos;
@SerializedName("KNHCJKHCOAN")
@SerializedName(
value = "KNHCJKHCOAN",
alternate = {"AMDNOHPGKMI"})
HomeFurniture mainhouse;
@SerializedName("NIHOJFEKFPG")
@SerializedName(
value = "NIHOJFEKFPG",
alternate = {"BHCPEAOPIDC"})
List<HomeFurniture> doorLists;
@SerializedName("EPGELGEFJFK")
@SerializedName(
value = "EPGELGEFJFK",
alternate = {"AABEPENIFLN"})
List<HomeFurniture> stairLists;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class HomeBlock {
@SerializedName(value = "FGIJCELCGFI", alternate = "PGDPDIDJEEL")
@SerializedName(
value = "FGIJCELCGFI",
alternate = {"PGDPDIDJEEL", "ANICBLBOBKD"})
int blockId;
@SerializedName("BEAPOFELABD")
@SerializedName(
value = "BEAPOFELABD",
alternate = {"NCIMIKKFLOH"})
List<HomeFurniture> furnitures;
@SerializedName("MLIODLGDFHJ")
@SerializedName(
value = "MLIODLGDFHJ",
alternate = {"GJGNLIINBGB"})
List<HomeFurniture> persistentFurnitures;
}
@ -50,10 +70,14 @@ public class HomeworldDefaultSaveData {
@FieldDefaults(level = AccessLevel.PRIVATE)
public static class HomeFurniture {
@SerializedName(value = "ENHNGKJBJAB", alternate = "KMAAJJHPNBA")
@SerializedName(
value = "ENHNGKJBJAB",
alternate = {"KMAAJJHPNBA", "FFLCGFGGGND"})
int id;
@SerializedName(value = "NGIEEIOLPPO", alternate = "JFKAHNCPDME")
@SerializedName(
value = "NGIEEIOLPPO",
alternate = {"JFKAHNCPDME", "BPCGGBKIAMG"})
Position pos;
// @SerializedName(value = "HEOCEHKEBFM", alternate = "LKCKOOGFDBM")
Position rot;

View File

@ -11,4 +11,6 @@ public class ConfigLevelEntity {
@Getter private List<ConfigAbilityData> avatarAbilities;
@Getter private List<ConfigAbilityData> teamAbilities;
@Getter private List<Integer> preloadMonsterEntityIDs;
@Getter private String dropElemControlType;
}

View File

@ -19,6 +19,8 @@ public final class PointData {
@Getter private Position pos;
@Getter private Position rot;
@Getter private Position size;
@Getter private boolean forbidSimpleUnlock;
@Getter private boolean unlocked;
@SerializedName(
value = "dungeonIds",

View File

@ -89,7 +89,14 @@ public class ItemData extends GameResource {
@SerializedName(
value = "roomSceneId",
alternate = {"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK", "MFGACDIOHGF"})
alternate = {
"BMEPAMCNABE",
"DANFGGLKLNO",
"JFDLJGDFIGL",
"OHIANNAEEAK",
"MFGACDIOHGF",
"roomSceneID"
})
private int roomSceneId;
// Custom

View File

@ -1,12 +1,10 @@
package emu.grasscutter.data.excels;
import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.*;
import emu.grasscutter.game.talk.TalkExec;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
@ResourceType(name = "TalkExcelConfigData.json")
@EqualsAndHashCode(callSuper = false)
@ -38,6 +36,11 @@ public final class TalkConfigData extends GameResource {
this.finishExec == null
? List.of()
: this.finishExec.stream().filter(x -> x.getType() != null).toList();
if (this.questId <= 0) {
var id = String.valueOf(this.getId());
this.questId = Integer.parseInt(id.length() < 5 ? "0" : id.substring(0, id.length() - 2));
}
}
@Data

View File

@ -32,6 +32,7 @@ public class DungeonData extends GameResource {
@Getter private int passRewardPreviewID;
@Getter private int statueCostID;
@Getter private int statueCostCount;
@Getter private int statueDrop;
// not part of DungeonExcelConfigData
@Getter private RewardPreviewData rewardPreviewData;

View File

@ -6,12 +6,13 @@ import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
import emu.grasscutter.game.quest.enums.LogicType;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@ResourceType(name = "DungeonPassExcelConfigData.json")
public class DungeonPassConfigData extends GameResource {
@Getter private int id;
@Getter private LogicType logicType;
@Getter private List<DungeonPassCondition> conds;
@Getter @Setter private List<DungeonPassCondition> conds;
public static class DungeonPassCondition {
@Getter private DungeonPassConditionType condType;

View File

@ -0,0 +1,10 @@
package emu.grasscutter.data.server;
import lombok.Data;
@Data
public final class DropSubfieldMapping {
private int dropId;
private int levelLimit;
private int itemId;
}

View File

@ -0,0 +1,24 @@
package emu.grasscutter.data.server;
import lombok.Data;
@Data
public final class DropTableExcelConfigData {
private int id;
private int randomType;
private int dropLevel;
private DropVectorEntry[] dropVec;
private int nodeType;
private boolean fallToGround;
private int sourceType;
private int everydayLimit;
private int historyLimit;
private int activityLimit;
@Data
public static class DropVectorEntry {
private int itemId;
private String countRange;
private int weight;
}
}

View File

@ -0,0 +1,15 @@
package emu.grasscutter.data.server;
import lombok.Data;
@Data
public final class SubfieldMapping {
private int entityId;
private SubfieldMappingEntry[] subfields;
@Data
public static class SubfieldMappingEntry {
private String subfieldName;
private int drop_id;
}
}

View File

@ -2,11 +2,9 @@ package emu.grasscutter.database;
import static com.mongodb.client.model.Filters.eq;
import dev.morphia.query.FindOptions;
import dev.morphia.query.Sort;
import dev.morphia.query.*;
import dev.morphia.query.experimental.filters.Filters;
import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.*;
import emu.grasscutter.game.Account;
import emu.grasscutter.game.achievement.Achievements;
import emu.grasscutter.game.activity.PlayerActivityData;
@ -26,8 +24,10 @@ import io.netty.util.concurrent.FastThreadLocalThread;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Stream;
import lombok.Getter;
public final class DatabaseHelper {
@Getter
private static final ExecutorService eventExecutor =
new ThreadPoolExecutor(
6,

View File

@ -30,30 +30,50 @@ public class AbilityLocalIdGenerator {
}
public void initializeActionLocalIds(
AbilityModifierAction[] actions, Map<Integer, AbilityModifierAction> localIdToAction) {
AbilityModifierAction actions[], Map<Integer, AbilityModifierAction> localIdToAction) {
this.initializeActionLocalIds(actions, localIdToAction, false);
}
public void initializeActionLocalIds(
AbilityModifierAction[] actions,
Map<Integer, AbilityModifierAction> localIdToAction,
boolean preserveActionIndex) {
if (actions == null) return;
actionIndex = 0;
for (AbilityModifierAction action : actions) {
actionIndex++;
long id = GetLocalId();
localIdToAction.put((int) id, action);
if (!preserveActionIndex) this.actionIndex = 0;
for (int i = 0; i < actions.length; i++) {
this.actionIndex++;
var id = GetLocalId();
localIdToAction.put((int) id, actions[i]);
if (actions[i].actions != null)
this.initializeActionLocalIds(actions[i].actions, localIdToAction, true);
else {
if (actions[i].successActions != null)
this.initializeActionLocalIds(
actions[i].successActions,
localIdToAction,
true); // Need to check this specific order
if (actions[i].failActions != null)
this.initializeActionLocalIds(actions[i].failActions, localIdToAction, true);
}
}
actionIndex = 0;
if (!preserveActionIndex) actionIndex = 0;
}
public void initializeMixinsLocalIds(
AbilityMixinData[] mixins, Map<Integer, AbilityMixinData> localIdToAction) {
if (mixins == null) return;
mixinIndex = 0;
for (AbilityMixinData mixin : mixins) {
long id = GetLocalId();
this.mixinIndex = 0;
for (var mixin : mixins) {
var id = GetLocalId();
localIdToAction.put((int) id, mixin);
mixinIndex++;
this.mixinIndex++;
}
mixinIndex = 0;
this.mixinIndex = 0;
}
public long GetLocalId() {

View File

@ -9,10 +9,12 @@ import emu.grasscutter.game.ability.actions.*;
import emu.grasscutter.game.ability.mixins.*;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.*;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.AbilityMetaAddAbilityOuterClass.AbilityMetaAddAbility;
import emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange;
import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap;
import emu.grasscutter.net.proto.AbilityMetaSetKilledStateOuterClass.AbilityMetaSetKilledState;
import emu.grasscutter.net.proto.AbilityScalarTypeOuterClass.AbilityScalarType;
import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry;
import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction;
@ -174,6 +176,7 @@ public final class AbilityManager extends BasePlayerManager {
case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_DURABILITY_CHANGE -> this
.handleModifierDurabilityChange(invoke);
case ABILITY_INVOKE_ARGUMENT_META_ADD_NEW_ABILITY -> this.handleAddNewAbility(invoke);
case ABILITY_INVOKE_ARGUMENT_META_SET_KILLED_SETATE -> this.handleKillState(invoke);
default -> {}
}
}
@ -535,6 +538,25 @@ public final class AbilityManager extends BasePlayerManager {
entity.getInstancedAbilities().size());
}
private void handleKillState(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException {
var scene = this.getPlayer().getScene();
var entity = scene.getEntityById(invoke.getEntityId());
if (entity == null) {
Grasscutter.getLogger()
.trace("Entity of ID {} was not found in the scene.", invoke.getEntityId());
return;
}
var killState = AbilityMetaSetKilledState.parseFrom(invoke.getAbilityData());
if (killState.getKilled()) {
scene.killEntity(entity);
} else if (!entity.isAlive()) {
entity.setFightProperty(
FightProperty.FIGHT_PROP_CUR_HP,
entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP));
}
}
public void addAbilityToEntity(GameEntity entity, String name) {
AbilityData data = GameData.getAbilityData(name);
if (data != null) addAbilityToEntity(entity, data);

View File

@ -3,7 +3,7 @@ package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.entity.*;
@AbilityAction(AbilityModifierAction.Type.ExecuteGadgetLua)
public class ActionExecuteGadgetLua extends AbilityActionHandler {

View File

@ -0,0 +1,100 @@
package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction.DropType;
import emu.grasscutter.data.binout.config.ConfigLevelEntity;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.game.world.Position;
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
@AbilityAction(AbilityModifierAction.Type.GenerateElemBall)
public final class ActionGenerateElemBall extends AbilityActionHandler {
@Override
public boolean execute(
Ability ability, AbilityModifierAction action, ByteString abilityData, GameEntity target) {
GameEntity owner = ability.getOwner();
AbilityActionGenerateElemBall generateElemBall;
try {
generateElemBall = AbilityActionGenerateElemBall.parseFrom(abilityData);
} catch (InvalidProtocolBufferException e) {
return false;
}
// Check if we should allow elem ball generation
if (action.dropType == DropType.LevelControl) {
String levelEntityConfig = owner.getScene().getSceneData().getLevelEntityConfig();
ConfigLevelEntity config = GameData.getConfigLevelEntityDataMap().get(levelEntityConfig);
if (config != null
&& config.getDropElemControlType() != null
&& config.getDropElemControlType().compareTo("None") == 0) {
Grasscutter.getLogger().warn("This level config don't allow element balls");
return true;
}
} else if (action.dropType == DropType.BigWorldOnly) {
if (owner.getScene().getSceneData().getSceneType() != SceneType.SCENE_WORLD) {
Grasscutter.getLogger().warn("This level config only allows element balls on big world");
return true;
}
} // Else the drop is forced
var energy = action.baseEnergy.get(ability) * action.ratio.get(ability);
if (energy <= 0.0) return true;
var itemData = GameData.getItemDataMap().get(action.configID);
if (itemData == null) {
Grasscutter.getLogger().warn("configID {} not found", action.configID);
return false;
}
if (itemData.getItemUse() == null || itemData.getItemUse().isEmpty()) {
Grasscutter.getLogger().warn("Item {} has no item use array", action.configID);
return true;
}
var itemUse = itemData.getItemUse().get(0);
double requiredEnergy;
switch (itemUse.getUseOp()) {
case ITEM_USE_ADD_ELEM_ENERGY:
requiredEnergy = Integer.parseInt(itemUse.getUseParam()[1]);
break;
case ITEM_USE_ADD_ALL_ENERGY:
requiredEnergy = Integer.parseInt(itemUse.getUseParam()[0]);
break;
default:
Grasscutter.getLogger().warn("UseOp not implemented", itemUse.getUseOp());
return false;
}
var amountGenerated = (int) Math.ceil(energy / requiredEnergy);
if (amountGenerated >= 21) {
Grasscutter.getLogger()
.warn("Attempt to generate more than 20 element balls {}", amountGenerated);
return false;
}
Grasscutter.getLogger()
.debug("Generating {} of {} element balls", amountGenerated, action.configID);
for (int i = 0; i < amountGenerated; i++) {
EntityItem energyBall =
new EntityItem(
owner.getScene(),
(owner instanceof EntityAvatar avatar) ? avatar.getPlayer() : null,
itemData,
new Position(generateElemBall.getPos()),
new Position(generateElemBall.getRot()),
1);
owner.getScene().addEntity(energyBall);
}
return true;
}
}

View File

@ -1,6 +1,7 @@
package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.GameEntity;
@ -10,9 +11,14 @@ public final class ActionKillSelf extends AbilityActionHandler {
@Override
public boolean execute(
Ability ability, AbilityModifierAction action, ByteString abilityData, GameEntity target) {
GameEntity owner = ability.getOwner();
owner.getScene().killEntity(owner);
// KillSelf should not have a target field, so target it's the actual entity to be applied.
// TODO: Check if this is always true.
if (target == null) {
Grasscutter.getLogger().warn("Tried killing null target");
return false;
}
target.getScene().killEntity(target);
return true;
}
}

View File

@ -1,11 +1,10 @@
package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.EntityClientGadget;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.entity.*;
@AbilityAction(AbilityModifierAction.Type.SetGlobalValueToOverrideMap)
public class ActionSetGlobalValueToOverrideMap extends AbilityActionHandler {
@ -23,15 +22,20 @@ public class ActionSetGlobalValueToOverrideMap extends AbilityActionHandler {
var globalValueKey = action.globalValueKey;
var abilityFormula = action.abilityFormula;
if (!entity.getGlobalAbilityValues().containsKey(globalValueKey)) return false;
if (!entity.getGlobalAbilityValues().containsKey(globalValueKey)) {
Grasscutter.getLogger().debug("Action does not contains {} global key", globalValueKey);
return true;
}
var globalValue = entity.getGlobalAbilityValues().getOrDefault(globalValueKey, 0.0f);
if (abilityFormula.compareTo("DummyThrowSpeed") == 0) {
globalValue = ((globalValue * 30.0f) / ((float) Math.sin(0.9424778) * 100.0f)) - 1.0f;
}
entity.getGlobalAbilityValues().put(globalValueKey, globalValue);
entity.onAbilityValueUpdate();
entity.getGlobalAbilityValues().put(globalValueKey, globalValue); // Research if this is needed.
ability
.getAbilitySpecials()
.put(action.overrideMapKey, globalValue.floatValue()); // Override our own.
// TODO: ChangeServerGlobalValueNotify

View File

@ -0,0 +1,41 @@
package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.net.proto.AbilityActionSetRandomOverrideMapValueOuterClass.AbilityActionSetRandomOverrideMapValue;
@AbilityAction(AbilityModifierAction.Type.SetRandomOverrideMapValue)
public class ActionSetRandomOverrideMapValue extends AbilityActionHandler {
@Override
public boolean execute(
Ability ability, AbilityModifierAction action, ByteString abilityData, GameEntity target) {
AbilityActionSetRandomOverrideMapValue valueProto;
try {
valueProto = AbilityActionSetRandomOverrideMapValue.parseFrom(abilityData);
} catch (InvalidProtocolBufferException e) {
return false;
}
float value = valueProto.getRandomValue();
float valueRangeMin = action.valueRangeMin.get(ability);
float valueRangeMax = action.valueRangeMax.get(ability);
if (value < valueRangeMin || value > valueRangeMax) {
Grasscutter.getLogger()
.warn(
"Tried setting value out of range: {} inside [{}, {}]",
value,
valueRangeMin,
valueRangeMax);
return true;
}
ability.getAbilitySpecials().put(action.overrideMapKey, value);
return true;
}
}

View File

@ -15,7 +15,7 @@ public class UnknownActivityConditionHandler extends ActivityConditionBaseHandle
@Override
public boolean execute(
PlayerActivityData activityData, ActivityConfigItem activityConfig, int... params) {
Grasscutter.getLogger().error("Called unknown condition handler {}.", conditions.name());
Grasscutter.getLogger().debug("Called unknown condition handler {}.", conditions.name());
return false;
}
}

View File

@ -1243,13 +1243,15 @@ public class Avatar {
});
// Add costume if avatar has a costume.
GameData.getAvatarCostumeDataItemIdMap()
.values()
.forEach(
costumeData -> {
if (costumeData.getCharacterId() != this.getAvatarId()) return;
this.setCostume(costumeData.getId());
});
if (GAME_OPTIONS.trialCostumes) {
GameData.getAvatarCostumeDataItemIdMap()
.values()
.forEach(
costumeData -> {
if (costumeData.getCharacterId() != this.getAvatarId()) return;
this.setCostume(costumeData.getId());
});
}
}
/** Equips the items applied from {@link Avatar#applyTrialItems()}. */

View File

@ -80,6 +80,14 @@ public final class DropSystem extends BaseGameSystem {
return dropData.getDropId();
}
public List<GameItem> handleDungeonRewardDrop(int dropId, boolean doubleReward) {
if (!dropTable.containsKey(dropId)) return List.of();
var dropData = dropTable.get(dropId);
List<GameItem> items = new ArrayList<>();
processDrop(dropData, doubleReward ? 2 : 1, items);
return items;
}
public boolean handleMonsterDrop(EntityMonster monster) {
int dropId;
int level = monster.getLevel();

View File

@ -53,8 +53,13 @@ public final class DungeonManager {
public DungeonManager(@NonNull Scene scene, @NonNull DungeonData dungeonData) {
this.scene = scene;
this.dungeonData = dungeonData;
this.passConfigData = GameData.getDungeonPassConfigDataMap().get(dungeonData.getPassCond());
this.finishedConditions = new int[passConfigData.getConds().size()];
if (dungeonData.getPassCond() == 0) {
this.passConfigData = new DungeonPassConfigData();
this.passConfigData.setConds(new ArrayList<>());
} else {
this.passConfigData = GameData.getDungeonPassConfigDataMap().get(dungeonData.getPassCond());
}
this.finishedConditions = new int[this.passConfigData.getConds().size()];
}
public void triggerEvent(DungeonPassConditionType conditionType, int... params) {
@ -76,6 +81,7 @@ public final class DungeonManager {
}
public boolean isFinishedSuccessfully() {
if (passConfigData.getLogicType() == null) return false;
return LogicType.calculate(passConfigData.getLogicType(), finishedConditions);
}
@ -134,7 +140,16 @@ public final class DungeonManager {
}
// Get and roll rewards.
List<GameItem> rewards = new ArrayList<>(this.rollRewards(useCondensed));
List<GameItem> rewards =
player
.getServer()
.getDropSystem()
.handleDungeonRewardDrop(dungeonData.getStatueDrop(), useCondensed);
if (rewards.isEmpty()) {
// fallback to legacy drop system
Grasscutter.getLogger().debug("dungeon drop failed for {}", dungeonData.getId());
rewards = new ArrayList<>(this.rollRewards(useCondensed));
}
// Add rewards to player and send notification.
player.getInventory().addItems(rewards, ActionReason.DungeonStatueDrop);
player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(rewards));
@ -187,7 +202,7 @@ public final class DungeonManager {
amount += Utils.drawRandomListElement(candidateAmounts, entry.getProbabilities());
}
// Double rewards in multiplay mode, if specified.
// Double rewards in multiply mode, if specified.
if (entry.isMpDouble() && this.getScene().getPlayerCount() > 1) {
amount *= 2;
}

View File

@ -70,7 +70,7 @@ public abstract class EntityBaseGadget extends GameEntity {
getGadgetId())
.setSourceEntityId(getId())
.setParam3((int) this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP))
.setEventSource(Integer.toString(getConfigId())));
.setEventSource(getConfigId()));
}
protected void fillFightProps(ConfigEntityGadget configGadget) {

View File

@ -7,12 +7,11 @@ import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.game.entity.gadget.*;
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Position;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.SceneGroupInstance;
import emu.grasscutter.game.props.*;
import emu.grasscutter.game.world.*;
import emu.grasscutter.net.proto.*;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
@ -20,31 +19,21 @@ import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.net.proto.VisionTypeOuterClass;
import emu.grasscutter.scripts.EntityControllerScriptManager;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.SceneGadget;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
import emu.grasscutter.server.packet.send.PacketPlatformStartRouteNotify;
import emu.grasscutter.server.packet.send.PacketPlatformStopRouteNotify;
import emu.grasscutter.server.packet.send.PacketSceneTimeNotify;
import emu.grasscutter.scripts.data.*;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.helpers.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import java.util.ArrayList;
import java.util.List;
import it.unimi.dsi.fastutil.ints.*;
import java.util.*;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.*;
@ToString(callSuper = true)
public class EntityGadget extends EntityBaseGadget {
@ -258,6 +247,62 @@ public class EntityGadget extends EntityBaseGadget {
if (routeConfig.isStarted()) {
return true;
}
if (routeConfig instanceof ConfigRoute configRoute) {
var route = this.getScene().getSceneRouteById(configRoute.getRouteId());
if (route != null) {
var points = route.getPoints();
val currIndex = configRoute.getStartIndex();
Position prevpos;
if (currIndex == 0) {
prevpos = getPosition();
this.getScene()
.getScriptManager()
.callEvent(
new ScriptArgs(
this.getGroupId(),
EventType.EVENT_PLATFORM_REACH_POINT,
this.getConfigId(),
configRoute.getRouteId())
.setParam3(0)
.setEventSource(this.getConfigId()));
} else {
prevpos = points[currIndex].getPos();
}
double time = 0;
for (var i = currIndex; i < points.length; ++i) {
time += points[i].getPos().computeDistance(prevpos) / points[i].getTargetVelocity();
prevpos = points[i].getPos();
val I = i;
configRoute
.getScheduledIndexes()
.add(
this.getScene()
.getScheduler()
.scheduleDelayedTask(
() -> {
if (points[I].isHasReachEvent() && I > currIndex) {
this.getScene()
.getScriptManager()
.callEvent(
new ScriptArgs(
this.getGroupId(),
EventType.EVENT_PLATFORM_REACH_POINT,
this.getConfigId(),
configRoute.getRouteId())
.setParam3(I)
.setEventSource(this.getConfigId()));
}
configRoute.setStartIndex(I);
this.position.set(points[I].getPos());
},
(int) time));
}
}
}
getScene().broadcastPacket(new PacketSceneTimeNotify(getScene()));
routeConfig.startRoute(getScene());
getScene().broadcastPacket(new PacketPlatformStartRouteNotify(this));
@ -273,6 +318,14 @@ public class EntityGadget extends EntityBaseGadget {
if (!routeConfig.isStarted()) {
return true;
}
if (routeConfig instanceof ConfigRoute configRoute) {
for (var task : configRoute.getScheduledIndexes()) {
this.getScene().getScheduler().cancelTask(task);
}
configRoute.getScheduledIndexes().clear();
}
routeConfig.stopRoute(getScene());
getScene().broadcastPacket(new PacketPlatformStopRouteNotify(this));

View File

@ -37,14 +37,30 @@ public class EntityItem extends EntityBaseGadget {
this(scene, player, itemData, pos, count, true);
}
public EntityItem(
Scene scene, Player player, ItemData itemData, Position pos, Position rotation, int count) {
this(scene, player, itemData, pos, rotation, count, true);
}
public EntityItem(
Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
this(scene, player, itemData, pos, null, count, share);
}
// In official game, some drop items are shared to all players, and some other items are
// independent to all players
// For example, if you killed a monster in MP mode, all players could get drops but rarity and
// number of them are different
// but if you broke regional mine, when someone picked up the drop then it disappeared
public EntityItem(
Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
super(scene, pos, null);
Scene scene,
Player player,
ItemData itemData,
Position pos,
Position rotation,
int count,
boolean share) {
super(scene, pos, rotation);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.guid =
player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();

View File

@ -113,7 +113,13 @@ public class EntityMonster extends GameEntity {
if(monster != null) affixes = monster.affix;
}
if (affixes != null) {
if (monsterData != null) {
// TODO: Research if group affixes goes first
if (affixes == null) affixes = monsterData.getAffix();
else affixes.addAll(monsterData.getAffix());
}
if(affixes != null) {
for(var affixId : affixes) {
var affix = GameData.getMonsterAffixDataMap().get(affixId.intValue());
if (!affix.isPreAdd()) continue;
@ -229,7 +235,7 @@ public class EntityMonster extends GameEntity {
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EVENT_SPECIFIC_MONSTER_HP_CHANGE, getConfigId(), monsterData.getId())
.setSourceEntityId(getId())
.setParam3((int) this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP))
.setEventSource(Integer.toString(getConfigId())));
.setEventSource(getConfigId()));
}
@Override

View File

@ -1,5 +1,6 @@
package emu.grasscutter.game.entity;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.ability.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.*;
@ -51,8 +52,8 @@ public abstract class GameEntity {
public abstract void initAbilities();
public int getEntityType() {
return this.getId() >> 24;
public EntityType getEntityType() {
return EntityIdType.toEntityType(this.getId() >> 24);
}
public abstract int getEntityTypeId();
@ -226,6 +227,82 @@ public abstract class GameEntity {
public void onRemoved() {}
private int[] parseCountRange(String range) {
var split = range.split(";");
if (split.length == 1)
return new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[0])};
return new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1])};
}
public boolean dropSubfieldItem(int dropId) {
var drop = GameData.getDropSubfieldMappingMap().get(dropId);
if (drop == null) return false;
var dropTableEntry = GameData.getDropTableExcelConfigDataMap().get(drop.getItemId());
if (dropTableEntry == null) return false;
Int2ObjectMap<Integer> itemsToDrop = new Int2ObjectOpenHashMap<>();
switch (dropTableEntry.getRandomType()) {
case 0: // select one
{
int weightCount = 0;
for (var entry : dropTableEntry.getDropVec()) weightCount += entry.getWeight();
int randomValue = new Random().nextInt(weightCount);
weightCount = 0;
for (var entry : dropTableEntry.getDropVec()) {
if (randomValue >= weightCount && randomValue < (weightCount + entry.getWeight())) {
var countRange = parseCountRange(entry.getCountRange());
itemsToDrop.put(
entry.getItemId(),
Integer.valueOf((new Random().nextBoolean() ? countRange[0] : countRange[1])));
}
}
}
break;
case 1: // Select various
{
for (var entry : dropTableEntry.getDropVec()) {
if (entry.getWeight() < new Random().nextInt(10000)) {
var countRange = parseCountRange(entry.getCountRange());
itemsToDrop.put(
entry.getItemId(),
Integer.valueOf((new Random().nextBoolean() ? countRange[0] : countRange[1])));
}
}
}
break;
}
for (var entry : itemsToDrop.int2ObjectEntrySet()) {
var item =
new EntityItem(
scene,
null,
GameData.getItemDataMap().get(entry.getIntKey()),
getPosition().nearby2d(1f).addY(0.5f),
entry.getValue(),
true);
scene.addEntity(item);
}
return true;
}
public boolean dropSubfield(String subfieldName) {
var subfieldMapping = GameData.getSubfieldMappingMap().get(getEntityTypeId());
if (subfieldMapping == null || subfieldMapping.getSubfields() == null) return false;
for (var entry : subfieldMapping.getSubfields()) {
if (entry.getSubfieldName().compareTo(subfieldName) == 0) {
return dropSubfieldItem(entry.getDrop_id());
}
}
return false;
}
public void onTick(int sceneTime) {
if (entityController != null) {
entityController.onTimer(this, sceneTime);

View File

@ -75,6 +75,7 @@ public class GadgetChest extends GadgetContent {
} else if (chest.chest_drop_id != 0) {
status = dropSystem.handleChestDrop(chest.chest_drop_id, chest.drop_count, getGadget());
}
if (status) {
getGadget().updateState(ScriptGadgetState.ChestOpened);
player.sendPacket(

View File

@ -14,6 +14,8 @@ import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo;
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
import emu.grasscutter.utils.Utils;
@ -57,6 +59,13 @@ public final class GadgetGatherObject extends GadgetContent {
GameItem item = new GameItem(itemData, 1);
player.getInventory().addItem(item, ActionReason.Gather);
var ScriptArgs =
new ScriptArgs(getGadget().getGroupId(), EventType.EVENT_GATHER, getGadget().getConfigId());
if (getGadget().getMetaGadget() != null) {
ScriptArgs.setEventSource(getGadget().getMetaGadget().config_id);
}
getGadget().getScene().getScriptManager().callEvent(ScriptArgs);
getGadget()
.getScene()
.broadcastPacket(

View File

@ -1,18 +1,54 @@
package emu.grasscutter.game.entity.gadget;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.GatherData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass;
import emu.grasscutter.net.proto.InteractTypeOuterClass;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
public class GadgetObject extends GadgetContent {
private int itemId;
public GadgetObject(EntityGadget gadget) {
super(gadget);
GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
if (gatherData != null) {
this.itemId = gatherData.getItemId();
}
}
@Override
public boolean onInteract(Player player, GadgetInteractReqOuterClass.GadgetInteractReq req) {
return false;
// This is a workaround until a proper gadget interaction system can be put in place.
ItemData itemData = GameData.getItemDataMap().get(this.itemId);
if (itemData == null) {
return false;
}
GameItem item = new GameItem(itemData, 1);
player.getInventory().addItem(item, ActionReason.Gather);
var ScriptArgs =
new ScriptArgs(getGadget().getGroupId(), EventType.EVENT_GATHER, getGadget().getConfigId());
if (getGadget().getMetaGadget() != null) {
ScriptArgs.setEventSource(getGadget().getMetaGadget().config_id);
}
getGadget().getScene().getScriptManager().callEvent(ScriptArgs);
getGadget()
.getScene()
.broadcastPacket(
new PacketGadgetInteractRsp(
getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_GATHER));
return true;
}
@Override

View File

@ -4,27 +4,36 @@ import emu.grasscutter.game.world.Position;
import emu.grasscutter.net.proto.MovingPlatformTypeOuterClass;
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
import emu.grasscutter.scripts.data.SceneGadget;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
public class ConfigRoute extends BaseRoute {
@Getter @Setter private int routeId;
@Getter @Setter private int startIndex;
@Getter @Setter private List<Integer> scheduledIndexes;
public ConfigRoute(SceneGadget gadget) {
super(gadget);
this.routeId = gadget.route_id;
this.startIndex = 0;
this.scheduledIndexes = new ArrayList<>();
}
public ConfigRoute(Position startRot, boolean startRoute, boolean isActive, int routeId) {
super(startRot, startRoute, isActive);
this.routeId = routeId;
this.startIndex = 0;
this.scheduledIndexes = new ArrayList<>();
}
@Override
public PlatformInfoOuterClass.PlatformInfo.Builder toProto() {
return super.toProto()
.setRouteId(routeId)
.setRouteId(this.routeId)
.setStartIndex(this.startIndex)
.setMovingPlatformType(
MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_USE_CONFIG);
}

View File

@ -133,13 +133,9 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
for (var item : items) {
if (item.getItemId() == 0) continue;
GameItem result = null;
try {
// putItem might throw exception
// ignore that exception and continue
result = putItem(item);
} catch (Exception e) {
e.printStackTrace();
}
result = putItem(item);
if (result != null) {
this.triggerAddItemEvents(result);
changedItems.add(result);
@ -155,22 +151,33 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
}
private void triggerAddItemEvents(GameItem result) {
getPlayer()
.getBattlePassManager()
.triggerMission(
WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, result.getItemId(), result.getCount());
getPlayer()
.getQuestManager()
.queueEvent(QuestContent.QUEST_CONTENT_OBTAIN_ITEM, result.getItemId(), result.getCount());
try {
getPlayer()
.getBattlePassManager()
.triggerMission(
WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM,
result.getItemId(),
result.getCount());
getPlayer()
.getQuestManager()
.queueEvent(
QuestContent.QUEST_CONTENT_OBTAIN_ITEM, result.getItemId(), result.getCount());
} catch (Exception e) {
Grasscutter.getLogger().debug("triggerAddItemEvents failed", e);
}
}
private void triggerRemItemEvents(GameItem item, int removeCount) {
getPlayer()
.getBattlePassManager()
.triggerMission(WatcherTriggerType.TRIGGER_COST_MATERIAL, item.getItemId(), removeCount);
getPlayer()
.getQuestManager()
.queueEvent(QuestContent.QUEST_CONTENT_ITEM_LESS_THAN, item.getItemId(), item.getCount());
try {
getPlayer()
.getBattlePassManager()
.triggerMission(WatcherTriggerType.TRIGGER_COST_MATERIAL, item.getItemId(), removeCount);
getPlayer()
.getQuestManager()
.queueEvent(QuestContent.QUEST_CONTENT_ITEM_LESS_THAN, item.getItemId(), item.getCount());
} catch (Exception e) {
Grasscutter.getLogger().debug("triggerRemItemEvents failed", e);
}
}
public void addItemParams(Collection<ItemParam> items) {
@ -193,8 +200,11 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
// Dont add items that dont have a valid item definition.
var data = item.getItemData();
if (data == null) return null;
this.player.getProgressManager().addItemObtainedHistory(item.getItemId(), item.getCount());
try {
this.player.getProgressManager().addItemObtainedHistory(item.getItemId(), item.getCount());
} catch (Exception e) {
Grasscutter.getLogger().debug("addItemObtainedHistory failed", e);
}
if (data.isUseOnGain()) {
var params = new UseItemParams(this.player, data.getUseTarget());

View File

@ -317,7 +317,9 @@ public class StaminaManager extends BasePlayerManager {
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);
if (entity instanceof EntityAvatar avatar)
avatar.onDeath(dieType, 0);
}
public void startSustainedStaminaHandler() {

View File

@ -345,16 +345,11 @@ public class Player implements PlayerHook, FieldFetch {
this.playerGameTime = gameTime;
// If the player is the host of the world, update the game time as well.
if (this.getWorld().getHost() == this) {
this.getWorld().changeTime(gameTime);
var world = this.getWorld();
if (world != null && world.getHost() == this) {
world.changeTime(gameTime);
}
// Trigger the script event for game time update.
var questManager = this.getQuestManager();
questManager.queueEvent(QuestCond.QUEST_COND_IS_DAYTIME);
questManager.queueEvent(QuestCond.QUEST_COND_TIME_VAR_GT_EQ);
questManager.queueEvent(QuestCond.QUEST_COND_TIME_VAR_PASS_DAY);
this.save();
}
@ -707,14 +702,16 @@ public class Player implements PlayerHook, FieldFetch {
}
public void onEnterRegion(SceneRegion region) {
var enterRegionName = "ENTER_REGION_" + region.config_id;
this.getQuestManager().forEachActiveQuest(quest -> {
if (quest.getTriggerData() != null &&
quest.getTriggers().containsKey("ENTER_REGION_"+ region.config_id)) {
quest.getTriggers().containsKey(enterRegionName) &&
region.getGroupId() == quest.getTriggerData().get(enterRegionName).getGroupId()) {
// If trigger hasn't been fired yet
if (!Boolean.TRUE.equals(quest.getTriggers().put("ENTER_REGION_" + region.config_id, true))) {
if (!Boolean.TRUE.equals(quest.getTriggers().put(enterRegionName, true))) {
this.getSession().send(new PacketServerCondMeetQuestListUpdateNotify());
this.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_TRIGGER_FIRE,
quest.getTriggerData().get("ENTER_REGION_" + region.config_id).getId(), 0);
quest.getTriggerData().get(enterRegionName).getId(), 0);
}
}
});
@ -722,13 +719,15 @@ public class Player implements PlayerHook, FieldFetch {
}
public void onLeaveRegion(SceneRegion region) {
var leaveRegionName = "LEAVE_REGION_" + region.config_id;
this.getQuestManager().forEachActiveQuest(quest -> {
if (quest.getTriggers().containsKey("LEAVE_REGION_" + region.config_id)) {
if (quest.getTriggers().containsKey(leaveRegionName) &&
region.getGroupId() == quest.getTriggerData().get(leaveRegionName).getGroupId()) {
// If trigger hasn't been fired yet
if (!Boolean.TRUE.equals(quest.getTriggers().put("LEAVE_REGION_" + region.config_id, true))) {
if (!Boolean.TRUE.equals(quest.getTriggers().put(leaveRegionName, true))) {
this.getSession().send(new PacketServerCondMeetQuestListUpdateNotify());
this.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_TRIGGER_FIRE,
quest.getTriggerData().get("LEAVE_REGION_" + region.config_id).getId(), 0);
quest.getTriggerData().get(leaveRegionName).getId(), 0);
}
}
});
@ -1537,6 +1536,12 @@ public class Player implements PlayerHook, FieldFetch {
}
}
@Override
public boolean equals(Object obj) {
return obj instanceof Player otherPlayer &&
this.id == otherPlayer.getUid();
}
public enum SceneLoadState {
NONE(0), LOADING(1), INIT(2), LOADED(3);
@ -1547,5 +1552,4 @@ public class Player implements PlayerHook, FieldFetch {
this.value = value;
}
}
}

View File

@ -4,10 +4,10 @@ import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.quest.enums.QuestContent;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -29,10 +29,10 @@ public class PlayerProgress {
// keep track of EXEC_ADD_QUEST_PROGRESS count, will be used in CONTENT_ADD_QUEST_PROGRESS
// not sure where to put this, this should be saved to DB but not to individual quest, since
// it will be hard to loop and compare
private Map<Integer, Integer> questProgressCountMap;
private Map<String, Integer> questProgressCountMap;
public PlayerProgress() {
this.questProgressCountMap = new Int2IntOpenHashMap();
this.questProgressCountMap = new ConcurrentHashMap<>();
this.completedDungeons = new IntArrayList();
this.itemHistory = new Int2ObjectOpenHashMap<>();
}
@ -70,15 +70,15 @@ public class PlayerProgress {
return itemEntry.addToObtainedCount(count);
}
public int getCurrentProgress(int progressId) {
public int getCurrentProgress(String progressId) {
return questProgressCountMap.getOrDefault(progressId, -1);
}
public int addToCurrentProgress(int progressId, int count) {
public int addToCurrentProgress(String progressId, int count) {
return questProgressCountMap.merge(progressId, count, Integer::sum);
}
public int resetCurrentProgress(int progressId) {
public int resetCurrentProgress(String progressId) {
return questProgressCountMap.merge(progressId, 0, Integer::min);
}

View File

@ -300,7 +300,7 @@ public final class PlayerProgressManager extends BasePlayerDataManager {
/** Quest progress */
public void addQuestProgress(int id, int count) {
var newCount = player.getPlayerProgress().addToCurrentProgress(id, count);
var newCount = player.getPlayerProgress().addToCurrentProgress(String.valueOf(id), count);
player.save();
player
.getQuestManager()

View File

@ -5,8 +5,7 @@ import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
import dev.morphia.annotations.Entity;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.net.proto.AvatarTeamOuterClass.AvatarTeam;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
@Entity
public final class TeamInfo {
@ -87,6 +86,8 @@ public final class TeamInfo {
for (int i = 0; i < this.getAvatars().size(); i++) {
Avatar avatar = player.getAvatars().getAvatarById(this.getAvatars().get(i));
if (avatar == null) continue;
avatarTeam.addAvatarGuidList(avatar.getGuid());
}

View File

@ -1,5 +1,8 @@
package emu.grasscutter.game.props;
import java.util.HashMap;
import java.util.Map;
public enum EntityIdType {
AVATAR(0x01),
MONSTER(0x02),
@ -12,10 +15,27 @@ public enum EntityIdType {
private final int id;
private static final Map<Integer, EntityType> map = new HashMap<>();
static {
map.put(EntityIdType.AVATAR.getId(), EntityType.Avatar);
map.put(EntityIdType.MONSTER.getId(), EntityType.Monster);
map.put(EntityIdType.NPC.getId(), EntityType.NPC);
map.put(EntityIdType.GADGET.getId(), EntityType.Gadget);
map.put(EntityIdType.REGION.getId(), EntityType.Region);
map.put(EntityIdType.WEAPON.getId(), EntityType.Equip);
map.put(EntityIdType.TEAM.getId(), EntityType.Team);
map.put(EntityIdType.MPLEVEL.getId(), EntityType.MPLevel);
}
EntityIdType(int id) {
this.id = id;
}
public static EntityType toEntityType(int entityId) {
return map.getOrDefault(entityId, EntityType.None);
}
public int getId() {
return id;
}

View File

@ -75,6 +75,7 @@ public enum EntityType implements IntValueEnum {
Screen(64),
EchoShell(65),
UIInteractGadget(66),
Region(98),
PlaceHolder(99);
private static final Int2ObjectMap<EntityType> map = new Int2ObjectOpenHashMap<>();

View File

@ -314,7 +314,7 @@ public class GameMainQuest {
0, new Position(avatarPosPos.get(0), avatarPosPos.get(1), avatarPosPos.get(2))); // position
posAndRot.add(
1, new Position(avatarPosRot.get(0), avatarPosRot.get(1), avatarPosRot.get(2))); // rotation
Grasscutter.getLogger().info("Succesfully loaded rewind data for subQuest {}", subId);
Grasscutter.getLogger().debug("Successfully loaded rewind data for quest {}.", subId);
return true;
}

View File

@ -51,10 +51,12 @@ public class GameQuest {
this.state = QuestState.QUEST_STATE_UNSTARTED;
this.triggerData = new HashMap<>();
this.triggers = new HashMap<>();
this.finishProgressList = new int[questData.getFinishCond().size()];
this.failProgressList = new int[questData.getFailCond().size()];
this.finishTime = 0;
}
public void start() {
this.clearProgress(false);
this.acceptTime = Utils.getCurrentSeconds();
this.startTime = this.acceptTime;
this.startGameDay = getOwner().getWorld().getTotalGameTimeDays();
@ -142,7 +144,7 @@ public class GameQuest {
}
public void setFinishProgress(int index, int value) {
finishProgressList[index] = value;
this.finishProgressList[index] = value;
}
public void setFailProgress(int index, int value) {
@ -153,17 +155,30 @@ public class GameQuest {
// TODO improve
var oldState = state;
if (questData.getFinishCond() != null && questData.getFinishCond().size() != 0) {
for (var condition : questData.getFinishCond()) {
if (condition.getType() == QuestContent.QUEST_CONTENT_LUA_NOTIFY) {
this.getOwner().getPlayerProgress().resetCurrentProgress(condition.getParamStr());
}
}
this.finishProgressList = new int[questData.getFinishCond().size()];
}
if (questData.getFailCond() != null && questData.getFailCond().size() != 0) {
for (var condition : questData.getFailCond()) {
if (condition.getType() == QuestContent.QUEST_CONTENT_LUA_NOTIFY) {
this.getOwner().getPlayerProgress().resetCurrentProgress(condition.getParamStr());
}
}
this.failProgressList = new int[questData.getFailCond().size()];
}
this.getOwner().getPlayerProgress().resetCurrentProgress(String.valueOf(this.subQuestId));
setState(QuestState.QUEST_STATE_UNSTARTED);
finishTime = 0;
acceptTime = 0;
startTime = 0;
this.getOwner().getPlayerProgress().resetCurrentProgress(this.subQuestId);
if (oldState == QuestState.QUEST_STATE_UNSTARTED) {
return false;
}

View File

@ -111,7 +111,9 @@ public class QuestManager extends BasePlayerManager {
30700, // Quest which is responsible for unlocking Crash Course.
30800, // Quest which is responsible for unlocking Sparks Amongst the Pages.
47001, 47002, 47003, 47004
47001, 47002, 47003, 47004,
2010103, 2010144 // Prologue Act 2: Chasing Shadows
));
}
}

View File

@ -14,7 +14,8 @@ public class ContentAddQuestProgress extends BaseContent {
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val progressId = condition.getParam()[0];
val currentCount = quest.getOwner().getPlayerProgress().getCurrentProgress(progressId);
val currentCount =
quest.getOwner().getPlayerProgress().getCurrentProgress(String.valueOf(progressId));
// if the condition count is 0 I think it is safe to assume that the
// condition count from EXEC only needs to be 1

View File

@ -3,8 +3,7 @@ package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_TALK;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.*;
import lombok.val;
@QuestValueContent(QUEST_CONTENT_COMPLETE_TALK)

View File

@ -2,20 +2,16 @@ package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_FINISH_PLOT;
import emu.grasscutter.data.binout.MainQuestData;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import emu.grasscutter.game.quest.*;
@QuestValueContent(QUEST_CONTENT_FINISH_PLOT)
public class ContentFinishPlot extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
MainQuestData.TalkData talkData =
quest.getMainQuest().getTalks().get(Integer.valueOf(params[0]));
GameQuest subQuest = quest.getMainQuest().getChildQuestById(params[0]);
var talkData = quest.getMainQuest().getTalks().get(params[0]);
var subQuest = quest.getMainQuest().getChildQuestById(params[0]);
return (talkData != null && subQuest != null || condition.getParamStr().equals(paramStr))
&& condition.getParam()[0] == params[0];
}

View File

@ -12,6 +12,6 @@ public class ContentLeaveScene extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return quest.getOwner().getScene().getPrevScene() == params[0];
return condition.getParam()[0] == params[0];
}
}

View File

@ -12,6 +12,8 @@ public class ContentLuaNotify extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
return condition.getParamStr().equals(paramStr);
return condition.getParamStr().equals(paramStr)
&& condition.getCount()
<= quest.getOwner().getPlayerProgress().getCurrentProgress(paramStr);
}
}

View File

@ -3,22 +3,16 @@ package emu.grasscutter.game.quest.content;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_NOT_FINISH_PLOT;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueContent;
import lombok.val;
import emu.grasscutter.game.quest.*;
@QuestValueContent(QUEST_CONTENT_NOT_FINISH_PLOT)
public class ContentNotFinishPlot extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
val talkId = condition.getParam()[0];
val checkMainQuest = quest.getOwner().getQuestManager().getMainQuestByTalkId(talkId);
if (checkMainQuest == null) {
return true;
}
val talkData = checkMainQuest.getTalks().get(talkId);
return talkData == null;
var talkData = quest.getMainQuest().getTalks().get(params[0]);
var subQuest = quest.getMainQuest().getChildQuestById(params[0]);
return (talkData == null && subQuest != null || condition.getParamStr().equals(paramStr))
&& condition.getParam()[0] == params[0];
}
}

View File

@ -13,9 +13,11 @@ public class ContentQuestStateEqual extends BaseContent {
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]);
if (checkQuest == null) {
return false;
}
return checkQuest.getState().getValue() == params[1];
return checkQuest.getState().getValue() == condition.getParam()[1];
}
}

View File

@ -12,12 +12,12 @@ public class ContentQuestStateNotEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]);
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(condition.getParam()[0]);
if (checkQuest != null) {
return checkQuest.getState().getValue() != params[1];
if (checkQuest == null) {
return false;
}
return false;
return checkQuest.getState().getValue() != condition.getParam()[1];
}
}

View File

@ -13,8 +13,8 @@ public class ContentQuestVarEqual extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue == params[1];
int questVarValue = quest.getMainQuest().getQuestVars()[condition.getParam()[0]];
Grasscutter.getLogger().debug("questVar {} : {}", condition.getParam()[0], questVarValue);
return questVarValue == condition.getParam()[1];
}
}

View File

@ -13,8 +13,8 @@ public class ContentQuestVarGreater extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue > params[1];
int questVarValue = quest.getMainQuest().getQuestVars()[condition.getParam()[0]];
Grasscutter.getLogger().debug("questVar {} : {}", condition.getParam()[0], questVarValue);
return questVarValue > condition.getParam()[1];
}
}

View File

@ -13,8 +13,8 @@ public class ContentQuestVarLess extends BaseContent {
@Override
public boolean execute(
GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0], questVarValue);
return questVarValue < params[1];
int questVarValue = quest.getMainQuest().getQuestVars()[condition.getParam()[0]];
Grasscutter.getLogger().debug("questVar {} : {}", condition.getParam()[0], questVarValue);
return questVarValue < condition.getParam()[1];
}
}

View File

@ -1,6 +1,5 @@
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValueExec;
@ -27,33 +26,16 @@ public class ExecNotifyGroupLua extends QuestExecHandler {
}
scene.runWhenFinished(
() -> {
val groupInstance = scriptManager.getGroupInstanceById(groupId);
if (groupInstance != null) {
// workaround to make sure the triggers are still there todo find better way of trigger
// handling
scriptManager.refreshGroup(groupInstance);
Grasscutter.getLogger()
.trace(
"group: {} \ncondition: {} \nparamStr {}",
groupInstance.getLuaGroup(),
condition,
paramStr);
} else {
Grasscutter.getLogger()
.debug(
"notify, no group instance for:\n group: {} \ncondition: {} \nparamStr {}",
groupId,
condition,
paramStr);
}
val eventType =
quest.getState() == QuestState.QUEST_STATE_FINISHED
? EventType.EVENT_QUEST_FINISH
: EventType.EVENT_QUEST_START;
scriptManager.callEvent(
new ScriptArgs(groupId, eventType, quest.getSubQuestId())
new ScriptArgs(
groupId,
eventType,
quest.getSubQuestId(),
quest.getState() == QuestState.QUEST_STATE_FINISHED ? 1 : 0)
.setEventSource(quest.getSubQuestId()));
});

View File

@ -25,6 +25,7 @@ public class ExecRefreshGroupSuite extends QuestExecHandler {
if (!scriptManager.refreshGroupSuite(groupId, suiteId, quest)) {
result = false;
}
scriptManager.getGroupById(groupId).dontUnload = true;
}
return result;

View File

@ -1,13 +1,11 @@
package emu.grasscutter.game.talk;
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_COMPLETE_TALK;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_ANY_TALK;
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_TALK;
import static emu.grasscutter.game.quest.enums.QuestContent.*;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData.TalkData;
import emu.grasscutter.game.player.BasePlayerManager;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.*;
import lombok.NonNull;
public final class TalkManager extends BasePlayerManager {
@ -22,30 +20,31 @@ public final class TalkManager extends BasePlayerManager {
* @param npcEntityId The entity ID of the NPC being talked to.
*/
public void triggerTalkAction(int talkId, int npcEntityId) {
var talkData = GameData.getTalkConfigDataMap().get(talkId);
if (talkData == null) return;
var player = this.getPlayer();
// Check if the NPC id is valid.
var entity = player.getScene().getEntityById(npcEntityId);
if (entity != null) {
// The config ID of the entity is the NPC's ID.
if (!talkData.getNpcId().contains(entity.getConfigId())) return;
}
// Execute the talk action on associated handlers.
talkData
.getFinishExec()
.forEach(e -> player.getServer().getTalkSystem().triggerExec(player, talkData, e));
var talkData = GameData.getTalkConfigDataMap().get(talkId);
if (talkData != null) {
// Check if the NPC id is valid.
var entity = player.getScene().getEntityById(npcEntityId);
if (entity != null) {
// The config ID of the entity is the NPC's ID.
if (!talkData.getNpcId().contains(entity.getConfigId())) return;
}
// Execute the talk action on associated handlers.
talkData
.getFinishExec()
.forEach(e -> player.getServer().getTalkSystem().triggerExec(player, talkData, e));
// Save the talk value to the quest's data.
this.saveTalkToQuest(talkId, talkData.getQuestId());
}
// Invoke the talking events for quests.
var questManager = player.getQuestManager();
questManager.queueEvent(QUEST_CONTENT_COMPLETE_ANY_TALK, talkId);
questManager.queueEvent(QUEST_CONTENT_COMPLETE_TALK, talkId);
questManager.queueEvent(QUEST_COND_COMPLETE_TALK, talkId);
// Save the talk value to the quest's data.
this.saveTalkToQuest(talkId, talkData.getQuestId());
}
public void saveTalkToQuest(int talkId, int mainQuestId) {

View File

@ -1,54 +1,44 @@
package emu.grasscutter.game.world;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.*;
import emu.grasscutter.data.binout.SceneNpcBornEntry;
import emu.grasscutter.data.binout.routes.Route;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.data.excels.SceneData;
import emu.grasscutter.data.excels.*;
import emu.grasscutter.data.excels.codex.CodexAnimalData;
import emu.grasscutter.data.excels.monster.MonsterData;
import emu.grasscutter.data.excels.world.WorldLevelData;
import emu.grasscutter.data.server.Grid;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.dungeons.DungeonManager;
import emu.grasscutter.game.dungeons.DungeonSettleListener;
import emu.grasscutter.game.dungeons.*;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.managers.blossom.BlossomManager;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.TeamInfo;
import emu.grasscutter.game.player.*;
import emu.grasscutter.game.props.*;
import emu.grasscutter.game.quest.QuestGroupSuite;
import emu.grasscutter.game.world.data.TeleportProperties;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.*;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.EnterTypeOuterClass;
import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.SceneIndexManager;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.*;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.SceneBlock;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.scripts.data.*;
import emu.grasscutter.server.event.entity.EntityCreationEvent;
import emu.grasscutter.server.event.player.PlayerTeleportEvent;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.server.scheduler.ServerTaskScheduler;
import emu.grasscutter.utils.objects.KahnsSort;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.Setter;
import lombok.val;
import lombok.*;
public final class Scene {
@Getter private final World world;
@ -62,7 +52,6 @@ public final class Scene {
@Getter private final Set<SceneGroup> loadedGroups;
@Getter private final BlossomManager blossomManager;
private final HashSet<Integer> unlockedForces;
private final List<Runnable> afterLoadedCallbacks = new ArrayList<>();
private final long startWorldTime;
@Getter @Setter DungeonManager dungeonManager;
@Getter Int2ObjectMap<Route> sceneRoutes;
@ -79,7 +68,11 @@ public final class Scene {
@Getter private int tickCount = 0;
@Getter private boolean isPaused = false;
private final List<Runnable> afterLoadedCallbacks = new ArrayList<>();
private final List<Runnable> afterHostInitCallbacks = new ArrayList<>();
@Getter private GameEntity sceneEntity;
@Getter private final ServerTaskScheduler scheduler;
public Scene(World world, SceneData sceneData) {
this.world = world;
@ -103,6 +96,7 @@ public final class Scene {
this.blossomManager = new BlossomManager(this);
this.unlockedForces = new HashSet<>();
this.sceneEntity = new EntityScene(this);
this.scheduler = new ServerTaskScheduler();
}
public int getId() {
@ -117,6 +111,13 @@ public final class Scene {
return this.getPlayers().size();
}
/**
* @return The scene's world's host.
*/
public Player getHost() {
return this.getWorld().getHost();
}
public GameEntity getEntityById(int id) {
// Check if the scene's entity ID is referenced.
if (id == 0x13800001) return this.sceneEntity;
@ -535,6 +536,10 @@ public final class Scene {
return;
}
if (!isPaused) {
this.getScheduler().runTasks();
}
if (this.getScriptManager().isInit()) {
// this.checkBlocks();
this.checkGroups();
@ -551,19 +556,22 @@ public final class Scene {
}
var sceneTime = getSceneTimeSeconds();
getEntities().forEach((eid, e) -> e.onTick(sceneTime));
var entities = Map.copyOf(this.getEntities());
entities.forEach(
(eid, e) -> {
if (!e.isAlive()) {
this.getEntities().remove(eid);
} else e.onTick(sceneTime);
});
blossomManager.onTick();
checkNpcGroup();
this.checkNpcGroup();
this.finishLoading();
this.checkPlayerRespawn();
if (this.tickCount++ % 10 == 0) this.broadcastPacket(new PacketSceneTimeNotify(this));
if (this.getPlayerCount() <= 0 && !this.dontDestroyWhenEmpty) {
this.getScriptManager().onDestroy();
this.getWorld().deregisterScene(this);
}
}
/** Validates a player's current position. Teleports the player if the player is out of bounds. */
@ -686,6 +694,29 @@ public final class Scene {
this.afterLoadedCallbacks.add(runnable);
}
/**
* Invoked when a player initializes loading the scene.
*
* @param player The player that initialized loading the scene.
*/
public void playerSceneInitialized(Player player) {
// Check if the player is the host.
if (!player.equals(this.getHost())) return;
// Run all callbacks.
this.afterHostInitCallbacks.forEach(Runnable::run);
this.afterHostInitCallbacks.clear();
}
/**
* Run a callback when the host initializes loading the scene.
*
* @param runnable The callback to be executed.
*/
public void runWhenHostInitialized(Runnable runnable) {
this.afterHostInitCallbacks.add(runnable);
}
public int getEntityLevel(int baseLevel, int worldLevelOverride) {
int level = worldLevelOverride > 0 ? worldLevelOverride + baseLevel - 22 : baseLevel;
level = Math.min(level, 100);
@ -700,18 +731,6 @@ public final class Scene {
npcBornEntries.addAll(loadNpcForPlayer(player));
}
// clear the unreachable group for client
var toUnload =
this.npcBornEntrySet.stream()
.filter(i -> !npcBornEntries.contains(i))
.map(SceneNpcBornEntry::getGroupId)
.toList();
if (toUnload.size() > 0) {
broadcastPacket(new PacketGroupUnloadNotify(toUnload));
Grasscutter.getLogger().trace("Unload NPC Group {}", toUnload);
}
// exchange the new npcBornEntry Set
this.npcBornEntrySet = npcBornEntries;
}
@ -858,7 +877,7 @@ public final class Scene {
.collect(Collectors.toSet());
for (var group : this.loadedGroups) {
if (!visible.contains(group.id) && !group.dynamic_load)
if (!visible.contains(group.id) && !group.dynamic_load && !group.dontUnload)
unloadGroup(scriptManager.getBlocks().get(group.block_id), group.id);
}
@ -1164,14 +1183,27 @@ public final class Scene {
pos.toDoubleArray(),
Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange);
var sceneNpcBornEntries =
var sceneNpcBornCanidates =
npcList.stream().filter(i -> !this.npcBornEntrySet.contains(i)).toList();
List<SceneNpcBornEntry> sceneNpcBornEntries = new ArrayList<>();
sceneNpcBornCanidates.forEach(
i -> {
var groupInstance = scriptManager.getGroupInstanceById(i.getGroupId());
if (groupInstance == null) return;
if (i.getSuiteIdList() != null
&& !i.getSuiteIdList().contains(groupInstance.getActiveSuiteId())) return;
sceneNpcBornEntries.add(i);
});
if (sceneNpcBornEntries.size() > 0) {
this.broadcastPacket(new PacketGroupSuiteNotify(sceneNpcBornEntries));
Grasscutter.getLogger().trace("Loaded Npc Group Suite {}", sceneNpcBornEntries);
}
return npcList;
return npcList.stream()
.filter(i -> this.npcBornEntrySet.contains(i) || sceneNpcBornEntries.contains(i))
.toList();
}
public void loadGroupForQuest(List<QuestGroupSuite> sceneGroupSuite) {

View File

@ -4,17 +4,14 @@ import static emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportTy
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.dungeon.DungeonData;
import emu.grasscutter.game.entity.EntityTeam;
import emu.grasscutter.game.entity.EntityWorld;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.Player.SceneLoadState;
import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.game.props.*;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.world.data.TeleportProperties;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.ChatInfoOuterClass.ChatInfo.*;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.scripts.data.SceneConfig;
import emu.grasscutter.server.event.player.PlayerTeleportEvent;
@ -22,15 +19,9 @@ import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.ConversionUtils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import lombok.Getter;
import lombok.val;
import it.unimi.dsi.fastutil.ints.*;
import java.util.*;
import lombok.*;
import org.jetbrains.annotations.NotNull;
public class World implements Iterable<Player> {
@ -44,7 +35,8 @@ public class World implements Iterable<Player> {
private int nextPeerId = 0;
private int worldLevel;
@Getter private boolean isMultiplayer, timeLocked = false;
@Getter private boolean isMultiplayer = false;
@Getter private boolean timeLocked;
private long lastUpdateTime;
@Getter private int tickCount = 0;
@ -65,6 +57,7 @@ public class World implements Iterable<Player> {
this.entity = new EntityWorld(this);
this.worldLevel = player.getWorldLevel();
this.isMultiplayer = isMultiplayer;
this.timeLocked = player.getProperty(PlayerProperty.PROP_IS_GAME_TIME_LOCKED) != 0;
this.lastUpdateTime = System.currentTimeMillis();
this.currentWorldTime = host.getPlayerGameTime();
@ -164,6 +157,16 @@ public class World implements Iterable<Player> {
player.getTeamManager().getCurrentSinglePlayerTeamInfo(),
player.getTeamManager().getMaxTeamSize());
player.getTeamManager().setCurrentCharacterIndex(0);
if (player != this.getHost()) {
this.broadcastPacket(
new PacketPlayerChatNotify(
player,
0,
SystemHint.newBuilder()
.setType(SystemHintType.SYSTEM_HINT_TYPE_CHAT_ENTER_WORLD.getNumber())
.build()));
}
}
// Add to scene
@ -217,6 +220,14 @@ public class World implements Iterable<Player> {
victim.getSceneId(),
victim.getPosition()));
}
} else {
this.broadcastPacket(
new PacketPlayerChatNotify(
player,
0,
SystemHint.newBuilder()
.setType(SystemHintType.SYSTEM_HINT_TYPE_CHAT_LEAVE_WORLD.getNumber())
.build()));
}
}
@ -426,7 +437,11 @@ public class World implements Iterable<Player> {
// Check if there are players in this world.
if (this.getPlayerCount() == 0) return true;
// Tick all associated scenes.
this.getScenes().forEach((k, scene) -> scene.onTick());
this.getScenes()
.forEach(
(k, scene) -> {
if (scene.getPlayerCount() > 0) scene.onTick();
});
// sync time every 10 seconds
if (this.tickCount % 10 == 0) {
@ -512,10 +527,6 @@ public class World implements Iterable<Player> {
*/
public void changeTime(long gameTime) {
this.currentWorldTime = gameTime;
// Trigger script events.
this.players.forEach(
player -> player.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_GAME_TIME_TICK));
}
/**

View File

@ -81,7 +81,7 @@ public final class PluginManager {
if (pluginConfig.api == null) {
Grasscutter.getLogger()
.warn(translate("plugin.invalid_api.not_present", plugin.getName()));
return;
continue;
} else if (pluginConfig.api != API_VERSION) {
Grasscutter.getLogger()
.warn(
@ -90,13 +90,13 @@ public final class PluginManager {
plugin.getName(),
pluginConfig.api,
API_VERSION));
return;
continue;
}
// Check if the plugin config is valid.
if (!pluginConfig.validate()) {
Grasscutter.getLogger().warn(translate("plugin.invalid_config", plugin.getName()));
return;
continue;
}
// Create a JAR file instance from the plugin's URL.
@ -216,9 +216,14 @@ public final class PluginManager {
Grasscutter.getLogger().info(translate("plugin.enabling_plugin", name));
try {
plugin.onEnable();
return;
} catch (NoSuchMethodError ignored) {
Grasscutter.getLogger().error(translate("plugin.invalid_api.outdated", name));
} catch (Throwable exception) {
Grasscutter.getLogger().error(translate("plugin.enabling_failed", name), exception);
}
this.disablePlugin(plugin);
});
}

View File

@ -10,7 +10,7 @@ import emu.grasscutter.data.server.Grid;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.quest.*;
import emu.grasscutter.game.world.*;
import emu.grasscutter.net.proto.VisionTypeOuterClass;
@ -99,7 +99,13 @@ public class SceneScriptManager {
}
public SceneConfig getConfig() {
return this.isInit ? this.meta.config : null;
for (int i = 0; i < 10; ++i) {
if (this.isInit) {
return this.meta.config;
}
Utils.sleep(100);
}
return null;
}
public Map<Integer, SceneBlock> getBlocks() {
@ -209,7 +215,14 @@ public class SceneScriptManager {
var suiteData = group.getSuiteByIndex(suiteIndex);
if (suiteData == null) {
Grasscutter.getLogger().warn("Group {} suite {} not found", group.id, suiteIndex);
return 0;
group.setLoaded(false);
group.load(this.scene.getId());
suiteData = group.getSuiteByIndex(suiteIndex);
if (suiteData == null) {
return 0;
}
Grasscutter.getLogger()
.error("Group {} suite {} nvm, I found it. This is BAD", group.id, suiteIndex);
}
int prevSuiteIndex = groupInstance.getActiveSuiteId();
@ -266,15 +279,15 @@ public class SceneScriptManager {
suiteId,
groupId,
getScene().getId());
} else {
Grasscutter.getLogger().debug("Refreshing group {} suite {}", groupId, suiteId);
suiteId =
refreshGroup(
targetGroupInstance,
suiteId,
false); // If suiteId is zero, the value of suiteId changes
scene.broadcastPacket(new PacketGroupSuiteNotify(groupId, suiteId));
if (targetGroupInstance == null) return false;
}
Grasscutter.getLogger().debug("Refreshing group {} suite {}", groupId, suiteId);
suiteId =
refreshGroup(
targetGroupInstance,
suiteId,
false); // If suiteId is zero, the value of suiteId changes
scene.broadcastPacket(new PacketGroupSuiteNotify(groupId, suiteId));
return true;
}
@ -627,27 +640,25 @@ public class SceneScriptManager {
// add other types of entity
var entities =
getScene().getEntities().values().stream()
.filter(
e ->
e.getEntityType() == EntityType.Avatar.getValue()
&& region.getMetaRegion().contains(e.getPosition()))
.filter(e -> region.getMetaRegion().contains(e.getPosition()))
.toList();
var entitiesIds = entities.stream().map(GameEntity::getId).toList();
var enterEntities =
entitiesIds.stream().filter(e -> !region.getEntities().contains(e)).toList();
var leaveEntities =
region.getEntities().stream().filter(e -> !entitiesIds.contains(e)).toList();
entities.forEach(region::addEntity);
var targetId = 0;
if (entities.size() > 0) {
targetId = entities.get(0).getId();
}
if (region.entityHasEntered()) {
for (var targetId : enterEntities) {
Grasscutter.getLogger()
.trace("Call EVENT_ENTER_REGION_{}", region.getMetaRegion().config_id);
this.callEvent(
new ScriptArgs(region.getGroupId(), EventType.EVENT_ENTER_REGION, region.getConfigId())
.setEventSource(EntityIdType.toEntityType(targetId >> 24).getValue())
.setSourceEntityId(region.getId())
.setTargetEntityId(targetId));
region.resetNewEntities();
}
for (var entityId : region.getEntities()) {
@ -657,13 +668,12 @@ public class SceneScriptManager {
}
}
if (region.entityHasLeft()) {
for (var targetId : leaveEntities) {
this.callEvent(
new ScriptArgs(region.getGroupId(), EventType.EVENT_LEAVE_REGION, region.getConfigId())
.setEventSource(EntityIdType.toEntityType(targetId >> 24).getValue())
.setSourceEntityId(region.getId())
.setTargetEntityId(region.getFirstEntityId()));
region.resetNewEntities();
.setTargetEntityId(targetId));
}
}
}
@ -681,8 +691,8 @@ public class SceneScriptManager {
|| !groupInstance.getDeadEntities().contains(m.config_id));
})
.map(g -> createGadget(group.id, group.block_id, g, groupInstance.getCachedGadgetState(g)))
.peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState()))
.filter(Objects::nonNull)
.peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState()))
.toList();
}
@ -801,26 +811,27 @@ public class SceneScriptManager {
private void realCallEvent(@Nonnull ScriptArgs params) {
try {
ScriptLoader.getScriptLib().setSceneScriptManager(this);
int eventType = params.type;
Set<SceneTrigger> relevantTriggers = new HashSet<>();
if (eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) {
relevantTriggers =
this.getTriggersByEvent(eventType).stream()
var eventType = params.type;
var relevantTriggers =
switch (eventType) {
case EventType.EVENT_ENTER_REGION, EventType.EVENT_LEAVE_REGION -> this
.getTriggersByEvent(eventType)
.stream()
.filter(
t ->
t.getCondition().contains(String.valueOf(params.param1))
t.getName().substring(13).equals(String.valueOf(params.param1))
&& (t.getSource().isEmpty()
|| t.getSource().equals(params.getEventSource())))
.collect(Collectors.toSet());
} else {
relevantTriggers =
this.getTriggersByEvent(eventType).stream()
default -> this.getTriggersByEvent(eventType).stream()
.filter(
t -> params.getGroupId() == 0 || t.getCurrentGroup().id == params.getGroupId())
.filter(
t -> (t.getSource().isEmpty() || t.getSource().equals(params.getEventSource())))
.collect(Collectors.toSet());
}
};
for (SceneTrigger trigger : relevantTriggers) {
handleEventForTrigger(params, trigger);
}
@ -890,7 +901,6 @@ public class SceneScriptManager {
.toList()
.get(0);
this.getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion()));
this.deregisterRegion(region.getMetaRegion());
} else if (trigger.getEvent() == EventType.EVENT_LEAVE_REGION) {
var region =
this.regions.values().stream()
@ -898,7 +908,6 @@ public class SceneScriptManager {
.toList()
.get(0);
this.getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion()));
this.deregisterRegion(region.getMetaRegion());
}
if (trigger.getEvent() == EVENT_TIMER_EVENT) {

View File

@ -8,36 +8,25 @@ import emu.grasscutter.game.dungeons.challenge.enums.FatherChallengeProperty;
import emu.grasscutter.game.dungeons.challenge.factory.ChallengeFactory;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
import emu.grasscutter.game.entity.gadget.platform.PointArrayRoute;
import emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.quest.enums.QuestCond;
import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.game.world.SceneGroupInstance;
import emu.grasscutter.game.entity.gadget.platform.*;
import emu.grasscutter.game.props.*;
import emu.grasscutter.game.quest.enums.*;
import emu.grasscutter.game.world.*;
import emu.grasscutter.net.proto.EnterTypeOuterClass;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.constants.GroupKillPolicy;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.SceneObject;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.constants.*;
import emu.grasscutter.scripts.data.*;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.game.world.Position;
import io.netty.util.concurrent.FastThreadLocal;
import lombok.val;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.luaj.vm2.*;
import org.slf4j.*;
import javax.annotation.Nullable;
import java.util.*;
import static emu.grasscutter.game.props.EnterReason.Lua;
import static emu.grasscutter.scripts.ScriptUtils.luaToPos;
import static emu.grasscutter.scripts.ScriptUtils.posToLua;
import static emu.grasscutter.scripts.ScriptUtils.*;
import static emu.grasscutter.scripts.constants.GroupKillPolicy.*;
@SuppressWarnings("unused")
@ -129,7 +118,7 @@ public class ScriptLib {
public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) {
logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}",
groupId,configId,options);
groupId, configId, options);
val entity = getSceneScriptManager().getScene().getEntityByConfigId(configId, groupId);
@ -152,18 +141,17 @@ public class ScriptLib {
logger.debug("[LUA] Call SetWorktopOptions with {}", printTable(table));
var callParams = this.callParams.getIfExists();
var group = this.currentGroup.getIfExists();
if(callParams == null || group == null){
if (callParams == null || group == null) {
return 1;
}
var configId = callParams.param1;
var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId);
int[] worktopOptions = new int[table.length()];
for(int i = 1 ;i<=table.length() ;i++){
var worktopOptions = new int[table.length()];
for (int i = 1; i<=table.length(); i++) {
worktopOptions[i-1] = table.get(i).optint(-1);
}
if(!(entity instanceof EntityGadget gadget)|| worktopOptions.length == 0){
if (!(entity instanceof EntityGadget gadget) || worktopOptions.length == 0) {
return 2;
}
@ -172,9 +160,11 @@ public class ScriptLib {
}
worktop.addWorktopOptions(worktopOptions);
var scene = getSceneScriptManager().getScene();
scene.broadcastPacket(new PacketWorktopOptionNotify(gadget));
var scene = this.getSceneScriptManager().getScene();
// Done in order to synchronize with addEntities in Scene.class.
synchronized (this.getSceneScriptManager().getScene()) {
scene.broadcastPacket(new PacketWorktopOptionNotify(gadget));
}
return 0;
}
@ -254,12 +244,6 @@ public class ScriptLib {
Grasscutter.getLogger().warn("trying to get suite that doesn't exist: {} {}", groupId, suite);
return 1;
}
// avoid spawn wrong monster
if(getSceneScriptManager().getScene().getChallenge() != null)
if(!getSceneScriptManager().getScene().getChallenge().inProgress() ||
getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId){
return 0;
}
this.getSceneScriptManager().addGroupSuite(groupInstance, suiteData);
return 0;
@ -396,12 +380,12 @@ public class ScriptLib {
logger.debug("[LUA] Call SetGroupVariableValue with {},{}",
var, value);
val groupId= currentGroup.get().id;
val groupId = currentGroup.get().id;
val variables = getSceneScriptManager().getVariables(groupId);
val old = variables.getOrDefault(var, value);
variables.put(var, value);
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, value, old));
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, value, old).setEventSource(var));
return 0;
}
@ -409,17 +393,46 @@ public class ScriptLib {
logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}",
var, value);
val groupId= currentGroup.get().id;
val groupId = currentGroup.get().id;
val variables = getSceneScriptManager().getVariables(groupId);
val old = variables.getOrDefault(var, 0);
variables.put(var, old + value);
logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}",
old, old+value);
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, old+value, old));
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, old+value, old).setEventSource(var));
return LuaValue.ZERO;
}
public int GetGroupVariableValueByGroup(String var, int groupId){
logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}",
var,groupId);
return getSceneScriptManager().getVariables(groupId).getOrDefault(var, 0);
}
public int SetGroupVariableValueByGroup(String var, int value, int groupId){
logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}",
var,value,groupId);
val variables = getSceneScriptManager().getVariables(groupId);
val old = variables.getOrDefault(var, value);
variables.put(var, value);
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, value, old).setEventSource(var));
return 0;
}
public int ChangeGroupVariableValueByGroup(String var, int value, int groupId){
logger.debug("[LUA] Call ChangeGroupVariableValueByGroup with {},{}",
var,groupId);
val variables = getSceneScriptManager().getVariables(groupId);
val old = variables.getOrDefault(var, 0);
variables.put(var, old + value);
getSceneScriptManager().callEvent(new ScriptArgs(groupId, EventType.EVENT_VARIABLE_CHANGE, old+value, old).setEventSource(var));
return 0;
}
/**
* Set the actions and triggers to designated group
*/
@ -530,22 +543,22 @@ public class ScriptLib {
var entity = scene.getEntityByConfigId(cfgId);
if (entity == null) return 2;
scene.broadcastPacket(
new PacketServerGlobalValueChangeNotify(entity, sgvName, value));
scene.runWhenHostInitialized(() -> scene.broadcastPacket(
new PacketServerGlobalValueChangeNotify(entity, sgvName, value)));
return 0;
}
public int GetGroupVariableValueByGroup(String name, int groupId){
logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}",
name,groupId);
public int SetEntityServerGlobalValueByEntityId(int entityId, String sgvName, int value) {
logger.debug("[LUA] Call SetEntityServerGlobalValueByEntityId with {}, {}, {}",
entityId, sgvName, value);
return getSceneScriptManager().getVariables(groupId).getOrDefault(name, 0);
}
public int ChangeGroupVariableValueByGroup(String name, int value, int groupId){
logger.debug("[LUA] Call ChangeGroupVariableValueByGroup with {},{}",
name,groupId);
//TODO test
getSceneScriptManager().getVariables(groupId).put(name, value);
var scriptManager = this.getSceneScriptManager();
if (scriptManager == null) return 1;
var scene = scriptManager.getScene();
scene.runWhenHostInitialized(() -> scene.broadcastPacket(
new PacketServerGlobalValueChangeNotify(entityId, sgvName, value)));
return 0;
}
@ -573,14 +586,6 @@ public class ScriptLib {
return 0;
}
public int SetGroupVariableValueByGroup(String key, int value, int groupId){
logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}",
key,value,groupId);
getSceneScriptManager().getVariables(groupId).put(key, value);
return 0;
}
public int CreateMonster(LuaTable table){
logger.debug("[LUA] Call CreateMonster with {}",
printTable(table));
@ -609,6 +614,11 @@ public class ScriptLib {
logger.debug("[LUA] Call CreateGadget with {}",
printTable(table));
var configId = table.get("config_id").toint();
//TODO: figure out what creating gadget configId 0 does
if (configId == 0){
Grasscutter.getLogger().warn("Tried to CreateGadget with config_id 0: {}", printTable(table));
return 0;
}
var group = getCurrentGroup();
@ -667,6 +677,7 @@ public class ScriptLib {
var1);
for(var player : getSceneScriptManager().getScene().getPlayers()){
player.getPlayerProgress().addToCurrentProgress(var1, 1);
player.getQuestManager().queueEvent(QuestCond.QUEST_COND_LUA_NOTIFY, var1);
player.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_LUA_NOTIFY, var1);
}
@ -702,7 +713,7 @@ public class ScriptLib {
return EntityType.None.getValue();
}
return entity.getEntityType();
return entity.getEntityType().getValue();
}
public int GetQuestState(int entityId, int questId){
@ -737,11 +748,11 @@ public class ScriptLib {
val entity = getSceneScriptManager().getScene().getEntityByConfigId(configId, groupId);
if(entity == null || entity.getEntityType() != entityType){
if(entity == null || entity.getEntityType().getValue() != entityType){
return 1;
}
getSceneScriptManager().getScene().removeEntity(entity);
getSceneScriptManager().getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE);
return 0;
}
@ -815,17 +826,17 @@ public class ScriptLib {
//TODO implement
return 0;
}
public int IsPlayerAllAvatarDie(int sceneUid){
public boolean IsPlayerAllAvatarDie(int sceneUid){
logger.warn("[LUA] Call unimplemented IsPlayerAllAvatarDie {}", sceneUid);
var playerEntities = getSceneScriptManager().getScene().getEntities().values().stream().filter(e -> e.getEntityType() == EntityIdType.AVATAR.getId()).toList();
var playerEntities = getSceneScriptManager().getScene().getEntities().values().stream().filter(e -> e.getEntityType() == EntityType.Avatar).toList();
for (GameEntity p : playerEntities){
var player = (EntityAvatar)p;
if(player.isAlive()){
return 0;
return false;
}
}
//TODO check
return 1;
return true;
}
public int sendShowCommonTipsToClient(String title, String content, int closeTime) {
@ -861,6 +872,11 @@ public class ScriptLib {
//TODO implement var6 object has int success, int fail, bool fail_on_wipe
return 0;
}
public int StopChallenge(int var1, int var2){
logger.warn("[LUA] Call unimplemented StopChallenge with {} {}", var1, var2);
//TODO implement
return 0;
}
public int CreateEffigyChallengeMonster(int var1, int[] var2){
logger.warn("[LUA] Call unimplemented CreateEffigyChallengeMonster with {} {}", var1, var2);
//TODO implement
@ -946,7 +962,7 @@ public class ScriptLib {
return 0;
}
public int EndTimeAxis(String var1){
logger.warn("[LUA] Call unimplemented EndTimeAxis with {} {} {}", var1);
logger.warn("[LUA] Call unimplemented EndTimeAxis with {}", var1);
//TODO implement var1 == name?
return 0;
}
@ -1062,6 +1078,12 @@ public class ScriptLib {
return 0;
}
public int ClearPlayerEyePoint(int var1){
logger.warn("[LUA] Call unimplemented ClearPlayerEyePoint with {}", var1);
//TODO implement
return 0;
}
public int MoveAvatarByPointArray(int uid, int targetId, LuaTable var3, String var4){
logger.warn("[LUA] Call unimplemented MoveAvatarByPointArray with {} {} {} {}", uid, targetId, printTable(var3), var4);
//TODO implement var3 contains int speed, var4 is a json string
@ -1120,7 +1142,7 @@ public class ScriptLib {
}
public int PlayCutSceneWithParam(int cutsceneId, int var2, LuaTable var3){
logger.warn("[LUA] Call unimplemented PlayCutScene with {} {}", cutsceneId, var2, var3);
logger.warn("[LUA] Call unimplemented PlayCutScene with {} {} {}", cutsceneId, var2, var3);
//TODO implement
return 0;
}
@ -1297,6 +1319,13 @@ public class ScriptLib {
}
configRoute.setRouteId(routeId);
configRoute.setStartIndex(0);
configRoute.setStarted(false);
for(var task : configRoute.getScheduledIndexes()) {
sceneScriptManager.get().getScene().getScheduler().cancelTask(task);
}
configRoute.getScheduledIndexes().clear();
sceneScriptManager.get().getScene().broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget));
return 0;
}
@ -1598,6 +1627,16 @@ public class ScriptLib {
return 0;
}
public int DropSubfield(LuaTable table) {
String subfield_name = table.get("subfield_name").toString();
var entity = getCurrentEntity();
if(!entity.isPresent()) return -1;
entity.get().dropSubfield(subfield_name);
return -1;
}
public int[] GetGatherConfigIdList() {
EntityGadget gadget = getCurrentEntityGadget();

View File

@ -3,5 +3,8 @@ package emu.grasscutter.scripts.constants;
public enum VisionLevelType {
VISION_LEVEL_NORMAL,
VISION_LEVEL_LITTLE_REMOTE,
VISION_LEVEL_REMOTE
VISION_LEVEL_REMOTE,
VISION_LEVEL_SUPER,
VISION_LEVEL_NEARBY,
VISION_LEVEL_SUPER_NEARBY
}

View File

@ -40,6 +40,7 @@ public final class SceneGroup {
public SceneGarbage garbages;
public SceneInitConfig init_config;
@Getter public boolean dynamic_load = false;
public boolean dontUnload = false;
public SceneReplaceable is_replaceable;

View File

@ -32,9 +32,9 @@ public class SceneRegion {
public boolean contains(Position position) {
switch (shape) {
case ScriptRegionShape.CUBIC:
return (Math.abs(pos.getX() - position.getX()) <= size.getX())
&& (Math.abs(pos.getY() - position.getY()) <= size.getY())
&& (Math.abs(pos.getZ() - position.getZ()) <= size.getZ());
return (Math.abs(pos.getX() - position.getX()) <= size.getX() / 2f)
&& (Math.abs(pos.getY() - position.getY()) <= size.getY() / 2f)
&& (Math.abs(pos.getZ() - position.getZ()) <= size.getZ() / 2f);
case ScriptRegionShape.SPHERE:
var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 2);

View File

@ -27,7 +27,7 @@ public final class SceneTrigger {
@Override
public int hashCode() {
return name.hashCode();
return (currentGroup.id + name).hashCode();
}
@Override

View File

@ -19,10 +19,10 @@ public class ScriptArgs {
}
public ScriptArgs(int groupId, int eventType, int param1, int param2) {
this.group_id = groupId;
this.type = eventType;
this.param1 = param1;
this.param2 = param2;
this.group_id = groupId;
}
public int getParam1() {

Some files were not shown because too many files have changed in this diff Show More