mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-07-04 05:53:42 +00:00
Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
5c4c62c1ed | |||
e2b59fbd8d | |||
84bf783243 | |||
4d8caf5a8c | |||
a30f16b0e1 | |||
65915b7666 | |||
1ceda2a455 | |||
09f392bb5b | |||
944bfb76f3 | |||
dc7b8d8ca6 | |||
9f00ea3573 | |||
12316b36b1 | |||
0fb7d50acd | |||
c926fe326c | |||
e8930e92e1 | |||
4ed0b90c27 | |||
7bfb35ac39 | |||
47911aa16e | |||
855d3182ab | |||
43b7d7a383 | |||
55928d9154 | |||
6219902e0f | |||
d7af52f94b | |||
c21d216d8d | |||
60657b3b98 | |||
f07ce48b24 | |||
2dd644f28b | |||
229303f934 | |||
a9148e1b66 | |||
d99a50b80f | |||
877f747d01 | |||
18360a6231 | |||
a2c4895c16 | |||
a5579368bb | |||
ae51f4c046 | |||
5b6698f583 | |||
496cd671da | |||
fd6ed2f15f | |||
ceed05cd15 | |||
7d1a7b501b | |||
8b520b3883 | |||
54ad108a14 | |||
ccf182d692 | |||
c51f7610b2 | |||
c331a7f288 | |||
be8fbcbc02 | |||
c5d30c44eb |
2
.github/workflows/protect_files.yml
vendored
2
.github/workflows/protect_files.yml
vendored
@ -20,4 +20,4 @@ jobs:
|
||||
steps:
|
||||
- uses: superbrothers/close-pull-request@v3
|
||||
with:
|
||||
comment: "This PR has been closed for modifying protected files. See `CONTIBUTING.md` for more information."
|
||||
comment: "This PR has been closed for modifying protected files. See `CONTRIBUTING.md` for more information."
|
12
README.md
12
README.md
@ -37,13 +37,13 @@
|
||||
**Note:** If you updated from an older version, delete `config.json` to regenerate it.
|
||||
|
||||
1. Get `grasscutter.jar`
|
||||
- Download from [actions](https://github.com/Grasscutters/Grasscutter/actions/workflows/build.yml) or [build the server by yourself](#building).
|
||||
- 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 using [server console command](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting).
|
||||
½. 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`
|
||||
@ -58,7 +58,6 @@
|
||||
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)
|
||||
@ -67,7 +66,7 @@
|
||||
|
||||
- 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` enviroment and configure the `start_config.cmd` file.**
|
||||
**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.**
|
||||
|
||||
### Building
|
||||
|
||||
@ -102,7 +101,6 @@ You can find the output jar in the root of the project folder.
|
||||
|
||||
# Quick Troubleshooting
|
||||
|
||||
* If compiling wasn't successful, please check your JDK installation (Make sure its JDK 17 or higher and validated JDK's bin PATH variable)
|
||||
* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is *the issue*, if using
|
||||
Fiddler make sure it running on another port except 8888
|
||||
* If compiling wasn't successful, please check your JDK installation (Make sure its JDK 17 or higher and validated JDK's bin PATH variable).
|
||||
* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is *the issue*. If you're using Fiddler, change the default port to anything other than 8888.
|
||||
* Startup sequence: MongoDB > Grasscutter > Proxy Daemon (mitmdump, fiddler, etc.) > Game
|
||||
|
@ -66,7 +66,7 @@ certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
|
||||
|
||||
|
||||
|
||||
-עריכת [קובץ הHosts](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
-עריכת [קובץ הHosts](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. תשנו את שרת בproxy שלכם ל`127.0.0.1:8080`
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- Fiddler Classic: Ejecuta Fiddler Classic, activa `Decrypt https traffic` en las opciones y cambia el puerto por defecto ahí (Herramientas -> Opciones -> Conexiones) a alguno que no sea `8888`, y carga [este script](https://github.lunatic.moe/fiddlerscript).
|
||||
|
||||
- [Archivo Hosts](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [Archivo Hosts](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. Establece el proxy de red a `127.0.0.1:8080` o el puerto de proxy que pusiste.
|
||||
|
||||
|
@ -7,11 +7,9 @@
|
||||
|
||||
**Atensyon:** Ang mga kontributor ay laging welcome sa proyektong ito. Bago mag-bigay ng kontribusyon, basahin muna ng mabuti ang [Code of Conduct](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md).
|
||||
|
||||
<b>(Basahin ha, hindi titingin lang)</b>
|
||||
## Ang mga kasalukuyang features
|
||||
|
||||
## Ang mga current features
|
||||
|
||||
* Login system
|
||||
* Logging in
|
||||
* Combat
|
||||
* Friends list
|
||||
* Teleportation
|
||||
@ -22,62 +20,61 @@
|
||||
|
||||
## Quick setup guide
|
||||
|
||||
**Atensyon:** Kung di mo talaga kaya o hindi mo maintindihan ang wiki, maaari kang sumali sa aming server [Discord](https://discord.gg/T5vZU6UyeG).
|
||||
**Atensyon:** Para sa mga nangangailangan ng suporta, maaari kang sumali sa aming server [Discord](https://discord.gg/T5vZU6UyeG).
|
||||
|
||||
### Ang mga kailangan
|
||||
|
||||
* Java SE - 17 ([link](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html))
|
||||
* [Java SE - 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) or higher
|
||||
|
||||
**Atensyon:** Kung gusto mo lang **paganahin** ang server, then **jre** is pwede naman.
|
||||
**Atensyon:** Kung gusto mo lang **paganahin** ang server, pwede naman ang **jre**.
|
||||
|
||||
* [MongoDB](https://www.mongodb.com/try/download/community) (recommended 4.0+)
|
||||
|
||||
* Proxy daemon: mitmproxy (mitmdump, recommended), Fiddler Classic, etc.
|
||||
* Proxy Daemon: [mitmproxy](https://mitmproxy.org/) (mitmdump, recommended), [Fiddler Classic](https://telerik-fiddler.s3.amazonaws.com/fiddler/FiddlerSetup.exe), etc.
|
||||
|
||||
### Running
|
||||
|
||||
**Atensyon:** Kung nag-update ka galing sa old version, paki-delete ang `config.json` para mag-regenerate ulit.
|
||||
**Atensyon:** Kung nag-update ka galing sa lumang version, paki-delete ang `config.json` para mag-regenerate ulit.
|
||||
|
||||
1. Get `grasscutter.jar`
|
||||
- Download ka from [actions](https://github.com/Grasscutters/Grasscutter/suites/6895963598/artifacts/267483297)
|
||||
- [Build mo ung jar by yourself](#Building)
|
||||
2. Gawa ka ng `resources` folder sa directory kung nasaan ang grasscutter.jar at ilagay ang `BinOutput` at `ExcelBinOutput` sa loob ng resources folder *(Check mo ang [wiki](https://github.com/Grasscutters/Grasscutter/wiki) para malaman mo san mo makukuha yan)*
|
||||
3. Paandarin ang Grasscutter gamit ang command na `java -jar grasscutter.jar`. **Make sure na gumagana ang mongodb (Google mo nalang kung pano mo malalaman)**
|
||||
- I-download mo sa [releases](https://github.com/Grasscutters/Grasscutter/releases/latest) o sa [actions](https://github.com/Grasscutters/Grasscutter/actions/workflows/build.yml) o [bumuo ng iyong sariling server](#building).
|
||||
2. Gawa ka ng `resources` folder sa directory kung nasaan ang grasscutter.jar at ilagay ang `BinOutput, ExcelBinOutput, Readables, Scripts, Subtitle, TextMap` folders sa loob ng resources folder *(Tingnan mo ang [wiki](https://github.com/Grasscutters/Grasscutter/wiki) para malaman mo kung saan mo makukuha yan)*
|
||||
3. Paandarin ang Grasscutter gamit ang command na `java -jar grasscutter.jar`. **Siguraduhin mo na ang mongodb service ay naka-open din.**
|
||||
|
||||
### Connecting with the client
|
||||
|
||||
½. Create ka ng account gamit ang [server console command](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting).
|
||||
½. Gumawa ng account sa server console gamit ang [command](https://github.com/Grasscutters/Grasscutter/wiki/Commands#:~:text=account%20%3Ccreate|delete%3E%20%3Cusername%3E%20[UID]) na ito.
|
||||
|
||||
1. Redirect traffic: (choose one)
|
||||
1. Redirect traffic: (pumili lang dapat ng isa)
|
||||
- mitmdump: `mitmdump -s proxy.py -k`
|
||||
|
||||
Trust CA certificate:
|
||||
- Trust CA certificate:
|
||||
|
||||
**Note:** Usually ang CA certificate ay nakalagay sa `%USERPROFILE%\ .mitmproxy`, o pwede mo naman i-download from `http://mitm.it`
|
||||
- Ang CA certificate ay nasa `%USERPROFILE%\.mitmproxy`, i-double click ang `mitmproxy-ca-cert.cer` para ma-[install](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) o...
|
||||
|
||||
Double click para ma-[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 *(kailangan ng administration privileges)*
|
||||
|
||||
- Gamit ang command line (cmd.exe)
|
||||
```shell
|
||||
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
|
||||
```
|
||||
|
||||
```shell
|
||||
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
|
||||
```
|
||||
- Fiddler Classic: Paadarin ang Fiddler Classic, turn on mo yung `Decrypt https traffic` sa (Tools -> Options -> HTTPS) at baguhin mo ang default port na nakalagay (Tools -> Options -> Connections) sa anumang numero maliban sa `8888`, i-load ang [script](https://github.com/Grasscutters/Grasscutter/wiki/Resources#fiddler-classic-jscript) na ito (copy and paste ang script sa `FiddlerScript` tab) at i-click ang `Save Script` button.
|
||||
|
||||
- Fiddler Classic: Paadarin ang Fiddler Classic, tsaka turn on mo yung `Decrypt https traffic` sa settings at baguhin mo yung default port na nakalagay (Tools -> Options -> Connections) to anything other than `8888`, at saka mo i-load [itong script](https://github.lunatic.moe/fiddlerscript).
|
||||
|
||||
- [Hosts file](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [Hosts file](https://github.com/Grasscutters/Grasscutter/wiki/Resources#hosts-file)
|
||||
|
||||
2. Set mo ung proxy sa `127.0.0.1:8080` or dun sa proxy port na iyong inilagay.
|
||||
|
||||
**pwede mo rin gamitin ang `start.cmd` to start the servers and proxy daemons automatically, pero kailagan mong i-setup ang JAVA_HOME enviroment**
|
||||
- Para sa mitmproxy: Pagkatapos mong i-setup ang network proxy at sa pag-install ng certificate, tingnan mo sa http://mitm.it/ kung ang traffic ay dumadaan sa mitmproxy.
|
||||
|
||||
**Pwede mo rin gamitin ang `start.cmd` to start the servers and proxy daemons automatically, pero kailagan mong i-setup ang JAVA_HOME environment at i-configure ang `start_config.cmd` file.**
|
||||
|
||||
### Building
|
||||
|
||||
Ang Grasscutter ay gumagamit ng gradle for depedencies at building.
|
||||
Ang Grasscutter ay gumagamit ng Gradle para sa depedencies at building.
|
||||
|
||||
**Mga kailangan:**
|
||||
|
||||
- [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) or higher
|
||||
- [Git](https://git-scm.com/downloads)
|
||||
|
||||
##### Windows
|
||||
@ -98,17 +95,12 @@ chmod +x gradlew
|
||||
./gradlew jar # Compile jar
|
||||
```
|
||||
|
||||
Pag-katapos mong i-compile, check mo yung [project](https://github.com/grasscutters/grasscutter) directory at saka makikita mo ung jar na kinompile mo. Usually pag-dev version, ang dapat nakalagay jan ay `grasscutter-<version>-dev.jar`. Bulag ka pag-hindi mo pa yan nakita.
|
||||
Pag-katapos mong i-compile, check mo yung project directory at makikita mo yung jar na kinompile mo. Usually pag-dev version, ang dapat nakalagay diyan ay `grasscutter-<version>-dev.jar`.
|
||||
|
||||
### Atensyon: ang mga server commands ay nasa [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)!
|
||||
### Ang mga server commands ay nasa [wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands) na!
|
||||
|
||||
# Quick Troubleshooting
|
||||
|
||||
* Kung hindi nag-compile, paki-check ung JDK installation mo (JDK 17 at JDK's bin PATH variable). Pag-hindi mo pa rin na-compile o hindi mo ma-gets, isa lang masasabi ko sayo, may skill issue+reading issue ka.
|
||||
* Hindi ako maka-connect, ayaw mag-login, 4206, etc... - `Usually proxy may kasalanan nyan`, ito ung pinaka-malalang skill issue na pwede mong makuha, sa lahat ng problems sa gc. Kung ayaw mo nyan, basahin mo ito.
|
||||
|
||||
Kung <b>Fiddler user</b> ka, paki-sigurado na naka-set ung port sa kahit ano except sa `8888`. (8888 port is for hoyoverse spider logs, in case na hindi mo alam)
|
||||
* Startup sequence: MongoDB > Grasscutter > Proxy daemon o Proxy service (mitmdump, fiddler, etc.)
|
||||
|
||||
<b> KUNG HINDI MO TALAGA MAINTINDIHAN, LUMAYAS KA NA DITO.........
|
||||
PUTANG INA MO, TAGLISH NA NGA YAN. TAS HINDI MO PA MA-GETS LMAO</b>
|
||||
* Kung hindi nag-compile, paki-check ung JDK installation mo (JDK 17 at JDK's bin PATH variable).
|
||||
* Hindi ako maka-connect, ayaw mag-login, 4206, etc... - Mostly ang proxy setup mo ang may kasalanan niyan, kung gamit mo ay Fiddler, paki-sigurado na naka-set ung port sa kahit ano except sa 8888.
|
||||
* Ang pagkakasunud-sunod: MongoDB > Grasscutter > Proxy Daemon (mitmdump, fiddler, etc.) > Game
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- 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/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [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é.
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- Fiddler Classic: Jalankan Fiddler Classic, nyalakan `Decrypt https traffic` dalam setting dan ubah port default di sana (Tools -> Options -> Connections) ke apa pun selain `8888`, dan muat [skrip ini](https://github.lunatic.moe/fiddlerscript).
|
||||
|
||||
- [File host](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [File host](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. Atur proxy jaringan ke `127.0.0.1:8080` atau port proxy yang anda tentukan.
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
[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)
|
||||
|
||||
|
||||
***:** 私たちはプロジェクトへの貢献者をいつでも歓迎します。 貢献を追加する前に、我々の [行動規範](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)をよくお読みください.
|
||||
***:** 私たちはプロジェクトへの貢献者をいつでも歓迎します。貢献を追加する前に、我々の [行動規範](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)をよくお読みください。
|
||||
|
||||
## 現在機能している物
|
||||
|
||||
@ -21,53 +21,52 @@
|
||||
|
||||
## クイックセットアップガイド
|
||||
|
||||
***:** サポートが必要な場合はGrasscutterの[Discord](https://discord.gg/T5vZU6UyeG)に参加してください.
|
||||
***:** サポートが必要な場合はGrasscutterの[Discord](https://discord.gg/T5vZU6UyeG)に参加してください。
|
||||
|
||||
### 動作環境
|
||||
|
||||
* [JAVAのバージョン17以降](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
||||
|
||||
***:** サーバーを動作させるだけならjreのみで十分です。 開発をしたい場合JDKが必要になるかもしれません。
|
||||
***:** サーバーを動作させるだけならjreのみで十分です。 開発をしたい場合JDKが必要になるかもしれません。
|
||||
|
||||
* [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)、 その他。
|
||||
* プロキシツール: [mitmproxy](https://mitmproxy.org/) (mitmdump, 推奨)、[Fiddler Classic](https://telerik-fiddler.s3.amazonaws.com/fiddler/FiddlerSetup.exe)、その他。
|
||||
|
||||
### 起動方法
|
||||
|
||||
***:** もしサーバーをアップデートしたい場合は`config.json`を削除してから再生成してください。
|
||||
***:** もしサーバーをアップデートしたい場合は`config.json`を削除してから再生成してください。
|
||||
|
||||
1. `grasscutter.jar`を入手する
|
||||
- [action](https://github.com/Grasscutters/Grasscutter/actions) からダウンロードするか [自分でビルド](https://github.com/Grasscutters/Grasscutter#building)してください。
|
||||
2. `grasscutter.jar` があるディレクトリに `resources` フォルダーを作成しそこに `BinOutput, ExcelBinOutput, Readables, Scripts, Subtitle, TextMap` を移動してください *(`resources` フォルダの中身の入手方法については [wiki](https://github.com/Grasscutters/Grasscutter/wiki) を参照してください.)*
|
||||
3. コマンドプロンプトに`java -jar grasscutter.jar`を入力しGrasscutterを起動してください。 **このときMongoDBも実行する必要があります。**
|
||||
- [releases](https://github.com/Grasscutters/Grasscutter/releases/latest) か [action](https://github.com/Grasscutters/Grasscutter/actions) からダウンロードするか、[自分でビルド](https://github.com/Grasscutters/Grasscutter#building)してください。
|
||||
2. `grasscutter.jar` があるディレクトリに `resources` フォルダーを作成し、そこに `BinOutput, ExcelBinOutput, Readables, Scripts, Subtitle, TextMap` を移動してください *(`resources` フォルダの中身の入手方法については [wiki](https://github.com/Grasscutters/Grasscutter/wiki) を参照してください.)*
|
||||
3. コマンドプロンプトに`java -jar grasscutter.jar`を入力しGrasscutterを起動してください。**このときMongoDBも実行する必要があります。**
|
||||
|
||||
### クライアントとの接続
|
||||
|
||||
½. [サーバーコンソールコマンド](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting)を使用してアカウントを作成してください。
|
||||
½. [このコマンド](https://github.com/Grasscutters/Grasscutter/wiki/Commands#commands-for-server-admins)をサーバーコンソールから使用してアカウントを作成してください。
|
||||
|
||||
1. 通信内容をリダイレクトする: (どちらか一つを選択してください)
|
||||
- mitmdump: `mitmdump -s proxy.py -k`
|
||||
|
||||
CA証明書を信頼する:
|
||||
- CA証明書を信頼する:
|
||||
|
||||
***:** CA証明書は`%USERPROFILE%\.mitmproxy`に保存されているか、`http://mitm.it`からダウンロードできます。
|
||||
- ***:** CA証明書は`%USERPROFILE%\.mitmproxy`に保存されています。ダブルクリックして[インストール](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate)するか...
|
||||
|
||||
ダブルクリックして[インストール](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を起動し設定から`Decrypt https traffic`をオンにしてください。 (Tools -> Options -> Connections) に有るポート番号の設定を`8888`以外に設定してください、その後この[スクリプト](https://github.com/Grasscutters/Grasscutter/wiki/Resources#fiddler-classic-jscript)をロードします。
|
||||
- Fiddler Classic: Fiddler Classicを起動し(Tools -> Options -> HTTPS)から`Decrypt https traffic`をオンにしてください。 (Tools -> Options -> Connections) に有るポート番号の設定を`8888`以外に設定してください。その後この[スクリプト](https://github.com/Grasscutters/Grasscutter/wiki/Resources#fiddler-classic-jscript)をFiddlerScriptタブにコピペしてロードします。
|
||||
|
||||
- [ホストファイル](https://github.com/Grasscutters/Grasscutter/wiki/Resources#hosts-file)
|
||||
|
||||
2. ネットワークプロキシを `127.0.0.1:(自分で設定したポート番号)` に設定してください。
|
||||
- mitmproxyを使用した場合:プロキシの設定と証明書のインストールが終わった後、http://mitm.it/ でトラフィックがmitmproxyを通過しているか確認しましょう。
|
||||
|
||||
**`start_config.cmd`でJAVAのパスを指定している必要があります。 `start.cmd`でmitmdumpとサーバーをまとめて起動することが出来ます。**
|
||||
**`start.cmd`でmitmdumpとサーバーをまとめて起動することが出来ます。ただ、事前に`start_config.cmd`でJAVAのパスを指定している必要があります。**
|
||||
|
||||
### ビルド
|
||||
|
||||
@ -75,7 +74,7 @@ GrasscutterはGradleを使用して依存関係とビルドを処理していま
|
||||
|
||||
**要件:**
|
||||
|
||||
- [Java SE 開発キット - 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
|
||||
@ -96,13 +95,13 @@ chmod +x gradlew
|
||||
./gradlew jar # コンパイル
|
||||
```
|
||||
|
||||
コンパイルされたjarファイルはプロゼクトフォルダーのルートに有ります。
|
||||
生成されたjarファイルはプロジェクトフォルダのルートに有ります。
|
||||
|
||||
### コマンドリストは[wiki](https://github.com/Grasscutters/Grasscutter/wiki/Commands)へ移動しました。
|
||||
|
||||
# トラブルシューティング
|
||||
|
||||
* コンパイルが失敗した場合JDKがインストールされているか確認してください (JDKの17以降と環境変数でJAVAのパスが設定されている必要があります)
|
||||
* クライアントが接続できない、 ログインできない、 エラーコード4206、 その他... - ほとんどの場合、プロキシ デーモンの設定が問題です。
|
||||
Fiddlerを使用している場合はポートが8888以外に設定されていることを確認してください。
|
||||
* 起動シーケンス(順番): MongoDB > Grasscutter > プロキシツール (mitmdumpかfiddler、その他) > ゲーム
|
||||
* コンパイルが失敗した場合JDKがインストールされているか確認してください。(JDKのバージョンが17以降であることと、環境変数でJDKのパスが設定されている必要があります)
|
||||
* クライアントが接続できない・ログインできない・エラーコード4206・またその他場合、ほとんどは、プロキシデーモンの設定が問題です。Fiddlerを使っている場合はデフォルトポートを8888以外の別のポートに変更してみてください。
|
||||
Fiddlerを使用している場合はポートが8888以外に設定されていることを確認してください。
|
||||
* 起動シーケンス(順番): MongoDB > Grasscutter > プロキシツール (mitmdumpかfiddler、その他) > ゲーム
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- Fiddler Classic : Fiddler Classic을 실행한 후, Setting에서 `Decrypt https traffic` 옵션을 켜고, Tools -> Options -> Connections에 있는 기본 포트를 `8888`을 제외한 다른 포트로 지정합니다. 그리고 [이 스크립트](https://github.lunatic.moe/fiddlerscript)를 불러옵니다.
|
||||
|
||||
- [호스트 파일](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [호스트 파일](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. 네트워크 프록시를 `127.0.0.1:8080` 로 설정하거나 지정한 프록시 포트로 설정합니다.
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- Fiddler Classic: Uruchom Fiddler Classic, włącz `Decrypt https traffic` w ustawieniach oraz zmień domyślny port (Tools -> Options -> Connections) na dowolny inny niż `8888`, i wczytaj [ten skrypt](https://github.lunatic.moe/fiddlerscript) (w polu FiddlerScript).
|
||||
|
||||
- [Plik hosts](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [Plik hosts](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. Ustaw serwer proxy na `127.0.0.1:8080` albo inny wybrany przez ciebie port.
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
- Fiddler Classic: Запустите Fiddler Classic, включите настройку `Decrypt https traffic` в опциях и измените порт по умолчанию (Меню -> Tools -> Options -> Connections) на что-то не равное `8888`, после чего запустите [этот скрипт](https://github.lunatic.moe/fiddlerscript) во вкладке FiddlerSrcipt.
|
||||
|
||||
- [Файл hosts](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
|
||||
- [Файл hosts](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
|
||||
|
||||
2. Установите прокси сети в `127.0.0.1:8080`, либо в тот порт прокси, который вы задали.
|
||||
|
||||
|
@ -43,7 +43,7 @@ sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
group = 'xyz.grasscutters'
|
||||
version = '1.4.1'
|
||||
version = '1.4.3'
|
||||
|
||||
sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
270
gradlew
vendored
270
gradlew
vendored
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -17,78 +17,113 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
@ -105,84 +140,95 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
2
gradlew-jar.bat
Normal file
2
gradlew-jar.bat
Normal file
@ -0,0 +1,2 @@
|
||||
call .\gradlew jar
|
||||
pause
|
189
gradlew.bat
vendored
189
gradlew.bat
vendored
@ -1,100 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
public final class GameConstants {
|
||||
public static String VERSION = "3.1.0";
|
||||
public static String VERSION = "3.2.0";
|
||||
|
||||
public static final int DEFAULT_TEAMS = 4;
|
||||
public static final int MAX_TEAMS = 10;
|
||||
|
@ -48,27 +48,27 @@ import static emu.grasscutter.config.Configuration.SERVER;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
public final class Grasscutter {
|
||||
private static final Logger log = (Logger) LoggerFactory.getLogger(Grasscutter.class);
|
||||
@Getter private static final Logger logger = (Logger) LoggerFactory.getLogger(Grasscutter.class);
|
||||
private static LineReader consoleLineReader = null;
|
||||
|
||||
private static Language language;
|
||||
@Getter @Setter private static Language language;
|
||||
|
||||
public static final File configFile = new File("./config.json");
|
||||
@Setter private static ServerRunMode runModeOverride = null; // Config override for run mode
|
||||
|
||||
private static int day; // Current day of week.
|
||||
@Getter private static int currentDayOfWeek;
|
||||
@Getter @Setter private static String preferredLanguage;
|
||||
|
||||
private static HttpServer httpServer;
|
||||
private static GameServer gameServer;
|
||||
private static PluginManager pluginManager;
|
||||
@Getter private static HttpServer httpServer;
|
||||
@Getter private static GameServer gameServer;
|
||||
@Getter private static PluginManager pluginManager;
|
||||
@Getter private static CommandMap commandMap;
|
||||
|
||||
private static AuthenticationSystem authenticationSystem;
|
||||
private static PermissionHandler permissionHandler;
|
||||
@Getter @Setter private static AuthenticationSystem authenticationSystem;
|
||||
@Getter @Setter private static PermissionHandler permissionHandler;
|
||||
|
||||
public static final Reflections reflector = new Reflections("emu.grasscutter");
|
||||
public static ConfigContainer config;
|
||||
@Getter public static ConfigContainer config;
|
||||
|
||||
static {
|
||||
// Declare logback configuration.
|
||||
@ -230,18 +230,6 @@ public final class Grasscutter {
|
||||
* Getters for the various server components.
|
||||
*/
|
||||
|
||||
public static ConfigContainer getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public static Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public static void setLanguage(Language language) {
|
||||
Grasscutter.language = language;
|
||||
}
|
||||
|
||||
public static Language getLanguage(String langCode) {
|
||||
return Language.getLanguage(langCode);
|
||||
}
|
||||
@ -250,10 +238,6 @@ public final class Grasscutter {
|
||||
return Grasscutter.runModeOverride != null ? Grasscutter.runModeOverride : SERVER.runMode;
|
||||
}
|
||||
|
||||
public static Logger getLogger() {
|
||||
return log;
|
||||
}
|
||||
|
||||
public static LineReader getConsole() {
|
||||
if (consoleLineReader == null) {
|
||||
Terminal terminal = null;
|
||||
@ -274,38 +258,14 @@ public final class Grasscutter {
|
||||
return consoleLineReader;
|
||||
}
|
||||
|
||||
public static HttpServer getHttpServer() {
|
||||
return httpServer;
|
||||
}
|
||||
|
||||
public static GameServer getGameServer() {
|
||||
return gameServer;
|
||||
}
|
||||
|
||||
public static PluginManager getPluginManager() {
|
||||
return pluginManager;
|
||||
}
|
||||
|
||||
public static AuthenticationSystem getAuthenticationSystem() {
|
||||
return authenticationSystem;
|
||||
}
|
||||
|
||||
public static PermissionHandler getPermissionHandler() {
|
||||
return permissionHandler;
|
||||
}
|
||||
|
||||
public static int getCurrentDayOfWeek() {
|
||||
return day;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility methods.
|
||||
*/
|
||||
|
||||
public static void updateDayOfWeek() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
day = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
Grasscutter.getLogger().debug("Set day of week to "+day);
|
||||
Grasscutter.currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
Grasscutter.getLogger().debug("Set day of week to "+currentDayOfWeek);
|
||||
}
|
||||
|
||||
public static void startConsole() {
|
||||
@ -333,8 +293,8 @@ public final class Grasscutter {
|
||||
Grasscutter.getLogger().info("EOF detected.");
|
||||
continue;
|
||||
} catch (IOError e) {
|
||||
Grasscutter.getLogger().error("An IO error occurred.", e);
|
||||
continue;
|
||||
Grasscutter.getLogger().error("An IO error occurred while trying to read from console.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
isLastInterrupted = false;
|
||||
@ -346,24 +306,6 @@ public final class Grasscutter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authentication system for the server.
|
||||
*
|
||||
* @param authenticationSystem The authentication system to use.
|
||||
*/
|
||||
public static void setAuthenticationSystem(AuthenticationSystem authenticationSystem) {
|
||||
Grasscutter.authenticationSystem = authenticationSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission handler for the server.
|
||||
*
|
||||
* @param permissionHandler The permission handler to use.
|
||||
*/
|
||||
public static void setPermissionHandler(PermissionHandler permissionHandler) {
|
||||
Grasscutter.permissionHandler = permissionHandler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enums for the configuration.
|
||||
*/
|
||||
|
@ -33,21 +33,18 @@ public class CommandHelpers {
|
||||
}
|
||||
|
||||
public static <T> List<String> parseIntParameters(List<String> args, @Nonnull T params, Map<Pattern, BiConsumer<T, Integer>> map) {
|
||||
for (int i = args.size() - 1; i >= 0; i--) {
|
||||
String arg = args.get(i).toLowerCase();
|
||||
args.removeIf(arg -> {
|
||||
var argL = arg.toLowerCase();
|
||||
boolean deleteArg = false;
|
||||
int argNum;
|
||||
for (var entry : map.entrySet()) {
|
||||
if ((argNum = matchIntOrNeg(entry.getKey(), arg)) != -1) {
|
||||
int argNum = matchIntOrNeg(entry.getKey(), argL);
|
||||
if (argNum != -1) {
|
||||
entry.getValue().accept(params, argNum);
|
||||
deleteArg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (deleteArg) {
|
||||
args.remove(i);
|
||||
}
|
||||
}
|
||||
return deleteArg;
|
||||
});
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public final class CommandMap {
|
||||
}
|
||||
|
||||
public List<Command> getAnnotationsAsList() {
|
||||
return new LinkedList<>(this.annotations.values());
|
||||
return new ArrayList<>(this.annotations.values());
|
||||
}
|
||||
|
||||
public Map<String, Command> getAnnotations() {
|
||||
@ -102,7 +102,7 @@ public final class CommandMap {
|
||||
* @return All command handlers as a list.
|
||||
*/
|
||||
public List<CommandHandler> getHandlersAsList() {
|
||||
return new LinkedList<>(this.commands.values());
|
||||
return new ArrayList<>(this.commands.values());
|
||||
}
|
||||
|
||||
public Map<String, CommandHandler> getHandlers() {
|
||||
@ -234,8 +234,8 @@ public final class CommandMap {
|
||||
|
||||
// Parse message.
|
||||
String[] split = rawMessage.split(" ");
|
||||
List<String> args = new LinkedList<>(Arrays.asList(split));
|
||||
String label = args.remove(0).toLowerCase();
|
||||
String label = split[0].toLowerCase();
|
||||
List<String> args = new ArrayList<>(Arrays.asList(split).subList(1, split.length));
|
||||
String playerId = (player == null) ? consoleId : player.getAccount().getId();
|
||||
|
||||
// Check for special cases - currently only target command.
|
||||
|
@ -9,7 +9,11 @@ import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "quest", usage = {"(add|finish) [<questId>]"}, permission = "player.quest", permissionTargeted = "player.quest.others")
|
||||
@Command(label = "quest",
|
||||
aliases = {"q"},
|
||||
usage = {"(add|finish) [<questId>]"},
|
||||
permission = "player.quest",
|
||||
permissionTargeted = "player.quest.others")
|
||||
public final class QuestCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@ -78,9 +79,10 @@ public final class SendMailCommand implements CommandHandler {
|
||||
Grasscutter.getGameServer().getPlayerByUid(mailBuilder.recipient, true).sendMail(mailBuilder.mail);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_done", mailBuilder.recipient));
|
||||
} else {
|
||||
for (Player player : DatabaseHelper.getAllPlayers()) {
|
||||
Grasscutter.getGameServer().getPlayerByUid(player.getUid(), true).sendMail(mailBuilder.mail);
|
||||
}
|
||||
DatabaseHelper.getByGameClass(Player.class).forEach(player -> {
|
||||
var onlinePlayer = Grasscutter.getGameServer().getPlayerByUid(player.getUid(), false);
|
||||
Objects.requireNonNullElse(onlinePlayer, player).sendMail(mailBuilder.mail);
|
||||
});
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_all_done"));
|
||||
}
|
||||
mailBeingConstructed.remove(senderId);
|
||||
|
@ -1,10 +1,7 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarTalentData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
@ -12,14 +9,13 @@ import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "setConst",
|
||||
aliases = {"setconstellation"},
|
||||
usage = {"<constellation level>"},
|
||||
usage = {"<constellation level> [all]"},
|
||||
permission = "player.setconstellation",
|
||||
permissionTargeted = "player.setconstellation.others")
|
||||
public final class SetConstCommand implements CommandHandler {
|
||||
@ -29,21 +25,28 @@ public final class SetConstCommand implements CommandHandler {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int constLevel = Integer.parseInt(args.get(0));
|
||||
// Check if level is out of range
|
||||
if (constLevel < -1 || constLevel > 6) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.range_error");
|
||||
return;
|
||||
}
|
||||
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) return;
|
||||
Avatar avatar = entity.getAvatar();
|
||||
|
||||
this.setConstellation(targetPlayer, avatar, constLevel);
|
||||
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.success", avatar.getAvatarData().getName(), constLevel);
|
||||
// If it's either empty or anything else other than "all" just do normal setConstellation
|
||||
if (args.size() == 1) {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) return;
|
||||
Avatar avatar = entity.getAvatar();
|
||||
this.setConstellation(targetPlayer, avatar, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.success", avatar.getAvatarData().getName(), constLevel);
|
||||
return;
|
||||
}
|
||||
// Check if there's an additional argument which is "all", if it does then go setAllConstellation
|
||||
if (args.size() > 1 && args.get(1).equalsIgnoreCase("all")) {
|
||||
this.setAllConstellation(targetPlayer, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.successall", constLevel);
|
||||
}
|
||||
else sendUsageMessage(sender);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.level_error");
|
||||
}
|
||||
@ -55,13 +58,7 @@ public final class SetConstCommand implements CommandHandler {
|
||||
|
||||
// force player to reload scene when necessary
|
||||
if (constLevel < currentConstLevel) {
|
||||
World world = player.getWorld();
|
||||
Scene scene = player.getScene();
|
||||
Position pos = player.getPosition();
|
||||
|
||||
world.transferPlayerToScene(player, 1, pos);
|
||||
world.transferPlayerToScene(player, scene.getId(), pos);
|
||||
scene.broadcastPacket(new PacketSceneEntityAppearNotify(player));
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
// ensure that all changes are visible to the player
|
||||
@ -69,4 +66,24 @@ public final class SetConstCommand implements CommandHandler {
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
}
|
||||
|
||||
private void setAllConstellation(Player player, int constLevel) {
|
||||
player.getAvatars().forEach(avatar -> {
|
||||
avatar.forceConstellationLevel(constLevel);
|
||||
avatar.recalcConstellations();
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
});
|
||||
// Just reload scene once, shorter than having to check for each constLevel < currentConstLevel
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
private void reloadScene(Player player) {
|
||||
World world = player.getWorld();
|
||||
Scene scene = player.getScene();
|
||||
Position pos = player.getPosition();
|
||||
world.transferPlayerToScene(player, 1, pos);
|
||||
world.transferPlayerToScene(player, scene.getId(), pos);
|
||||
scene.broadcastPacket(new PacketSceneEntityAppearNotify(player));
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +67,10 @@ public final class SetStatsCommand implements CommandHandler {
|
||||
|
||||
// Compatibility aliases
|
||||
this.stats.put("mhp", this.stats.get("maxhp"));
|
||||
this.stats.put("hp", new Stat(FightProperty.FIGHT_PROP_CUR_HP)); // Overrides FIGHT_PROP_HP
|
||||
this.stats.put("atk", new Stat(FightProperty.FIGHT_PROP_CUR_ATTACK)); // Overrides FIGHT_PROP_ATTACK
|
||||
this.stats.put("atkb", new Stat(FightProperty.FIGHT_PROP_BASE_ATTACK)); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
|
||||
this.stats.put("hp", this.stats.get("_cur_hp")); // Overrides FIGHT_PROP_HP
|
||||
this.stats.put("atk", this.stats.get("_cur_attack")); // Overrides FIGHT_PROP_ATTACK
|
||||
this.stats.put("def", this.stats.get("_cur_defense")); // Overrides FIGHT_PROP_DEFENSE
|
||||
this.stats.put("atkb", this.stats.get("_base_attack")); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
|
||||
this.stats.put("eanemo", this.stats.get("anemo%"));
|
||||
this.stats.put("ecryo", this.stats.get("cryo%"));
|
||||
this.stats.put("edendro", this.stats.get("dendro%"));
|
||||
|
@ -25,7 +25,7 @@ import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(
|
||||
label = "spawn",
|
||||
aliases = {"drop"},
|
||||
aliases = {"drop", "s"},
|
||||
usage = {
|
||||
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
|
@ -1,5 +1,6 @@
|
||||
package emu.grasscutter.config;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import com.google.gson.JsonObject;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Grasscutter.ServerDebugMode;
|
||||
@ -101,6 +102,7 @@ public class ConfigContainer {
|
||||
public Game game = new Game();
|
||||
|
||||
public Dispatch dispatch = new Dispatch();
|
||||
public DebugMode debugMode = new DebugMode();
|
||||
}
|
||||
|
||||
public static class Language {
|
||||
@ -150,6 +152,10 @@ public class ConfigContainer {
|
||||
public int kcpInterval = 20;
|
||||
/* Controls whether packets should be logged in console or not */
|
||||
public ServerDebugMode logPackets = ServerDebugMode.NONE;
|
||||
/* Show packet payload in console or no (in any case the payload is shown in encrypted view) */
|
||||
public Boolean isShowPacketPayload = false;
|
||||
/* Show annoying loop packets or no */
|
||||
public Boolean isShowLoopPackets = false;
|
||||
|
||||
public GameOptions gameOptions = new GameOptions();
|
||||
public JoinOptions joinOptions = new JoinOptions();
|
||||
@ -163,9 +169,33 @@ public class ConfigContainer {
|
||||
|
||||
public String defaultName = "Grasscutter";
|
||||
|
||||
/* Controls whether http requests should be logged in console or not */
|
||||
public ServerDebugMode logRequests = ServerDebugMode.NONE;
|
||||
}
|
||||
|
||||
/* Debug options container, used when jar launch argument is -debug | -debugall and override default values
|
||||
* (see StartupArguments.enableDebug) */
|
||||
public static class DebugMode {
|
||||
/* Log level of the main server code (works only with -debug arg) */
|
||||
public Level serverLoggerLevel = Level.DEBUG;
|
||||
|
||||
/* Log level of the third-party services (works only with -debug arg):
|
||||
javalin, quartz, reflections, jetty, mongodb.driver*/
|
||||
public Level servicesLoggersLevel = Level.INFO;
|
||||
|
||||
/* Controls whether packets should be logged in console or not */
|
||||
public ServerDebugMode logPackets = ServerDebugMode.ALL;
|
||||
|
||||
/* Show packet payload in console or no (in any case the payload is shown in encrypted view) */
|
||||
public Boolean isShowPacketPayload = false;
|
||||
|
||||
/* Show annoying loop packets or no */
|
||||
public Boolean isShowLoopPackets = false;
|
||||
|
||||
/* Controls whether http requests should be logged in console or not */
|
||||
public ServerDebugMode logRequests = ServerDebugMode.ALL;
|
||||
}
|
||||
|
||||
public static class Encryption {
|
||||
public boolean useEncryption = true;
|
||||
/* Should 'https' be appended to URLs? */
|
||||
|
@ -38,6 +38,7 @@ public final class Configuration extends ConfigContainer {
|
||||
public static final HTTP HTTP_INFO = config.server.http;
|
||||
public static final Game GAME_INFO = config.server.game;
|
||||
public static final Dispatch DISPATCH_INFO = config.server.dispatch;
|
||||
public static final DebugMode DEBUG_MODE_INFO = config.server.debugMode;
|
||||
|
||||
public static final Encryption HTTP_ENCRYPTION = config.server.http.encryption;
|
||||
public static final Policies HTTP_POLICIES = config.server.http.policies;
|
||||
|
@ -13,15 +13,12 @@ import java.util.List;
|
||||
@Getter
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class ActivityWatcherData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
int id;
|
||||
int rewardID;
|
||||
int progress;
|
||||
WatcherTrigger triggerConfig;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
triggerConfig.paramList = triggerConfig.paramList.stream().filter(x -> !x.isBlank()).toList();
|
||||
|
@ -44,6 +44,7 @@ public class AvatarData extends GameResource {
|
||||
private float criticalHurt;
|
||||
|
||||
private List<PropGrowCurve> propGrowCurves;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
// Transient
|
||||
@ -60,11 +61,6 @@ public class AvatarData extends GameResource {
|
||||
@Getter private int nameCardRewardId;
|
||||
@Getter private int nameCardId;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public float getBaseHp(int level) {
|
||||
try {
|
||||
return this.hpBase * this.hpGrowthCurve[level - 1];
|
||||
|
@ -7,26 +7,18 @@ import emu.grasscutter.game.props.ElementType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "AvatarSkillExcelConfigData.json", loadPriority = LoadPriority.HIGHEST)
|
||||
@Getter
|
||||
public class AvatarSkillData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
@Getter private float cdTime;
|
||||
@Getter private int costElemVal;
|
||||
@Getter private int maxChargeNum;
|
||||
@Getter private int triggerID;
|
||||
@Getter private boolean isAttackCameraLock;
|
||||
@Getter private int proudSkillGroupId;
|
||||
@Getter private ElementType costElemType;
|
||||
@Getter private long nameTextMapHash;
|
||||
@Getter private long descTextMapHash;
|
||||
@Getter private String abilityName;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
private float cdTime;
|
||||
private int costElemVal;
|
||||
private int maxChargeNum;
|
||||
private int triggerID;
|
||||
private boolean isAttackCameraLock;
|
||||
private int proudSkillGroupId;
|
||||
private ElementType costElemType;
|
||||
private long nameTextMapHash;
|
||||
private long descTextMapHash;
|
||||
private String abilityName;
|
||||
}
|
||||
|
@ -18,31 +18,27 @@ import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "AvatarSkillDepotExcelConfigData.json", loadPriority = LoadPriority.HIGH)
|
||||
@Getter
|
||||
public class AvatarSkillDepotData extends GameResource {
|
||||
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
@Getter private int energySkill;
|
||||
@Getter private int attackModeSkill;
|
||||
private int energySkill;
|
||||
private int attackModeSkill;
|
||||
|
||||
@Getter private List<Integer> skills;
|
||||
@Getter private List<Integer> subSkills;
|
||||
@Getter private List<String> extraAbilities;
|
||||
@Getter private List<Integer> talents;
|
||||
@Getter private List<InherentProudSkillOpens> inherentProudSkillOpens;
|
||||
private List<Integer> skills;
|
||||
private List<Integer> subSkills;
|
||||
private List<String> extraAbilities;
|
||||
private List<Integer> talents;
|
||||
private List<InherentProudSkillOpens> inherentProudSkillOpens;
|
||||
|
||||
@Getter private String talentStarName;
|
||||
@Getter private String skillDepotAbilityGroup;
|
||||
private String talentStarName;
|
||||
private String skillDepotAbilityGroup;
|
||||
|
||||
// Transient
|
||||
@Getter private AvatarSkillData energySkillData;
|
||||
@Getter private ElementType elementType;
|
||||
@Getter private IntList abilities;
|
||||
@Getter private int talentCostItemId;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
private AvatarSkillData energySkillData;
|
||||
private ElementType elementType;
|
||||
private IntList abilities;
|
||||
private int talentCostItemId;
|
||||
|
||||
public void setAbilities(AbilityEmbryoEntry info) {
|
||||
this.abilities = new IntArrayList(info.getAbilities().length);
|
||||
@ -77,9 +73,10 @@ public class AvatarSkillDepotData extends GameResource {
|
||||
.ifPresent(itemId -> this.talentCostItemId = itemId);
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class InherentProudSkillOpens {
|
||||
@Getter private int proudSkillGroupId;
|
||||
@Getter private int needAvatarPromoteLevel;
|
||||
private int proudSkillGroupId;
|
||||
private int needAvatarPromoteLevel;
|
||||
}
|
||||
|
||||
public IntStream getSkillsAndEnergySkill() {
|
||||
|
@ -9,65 +9,58 @@ import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.game.props.BattlePassMissionRefreshType;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.MissionStatus;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@ResourceType(name = {"BattlePassMissionExcelConfigData.json"})
|
||||
@Getter
|
||||
public class BattlePassMissionData extends GameResource {
|
||||
private int addPoint;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private int addPoint;
|
||||
private int scheduleId;
|
||||
private int progress;
|
||||
private TriggerConfig triggerConfig;
|
||||
private BattlePassMissionRefreshType refreshType;
|
||||
|
||||
|
||||
private transient Set<Integer> mainParams;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public WatcherTriggerType getTriggerType() {
|
||||
return this.getTriggerConfig().getTriggerType();
|
||||
}
|
||||
|
||||
public boolean isCycleRefresh() {
|
||||
return getRefreshType() == null || getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE;
|
||||
}
|
||||
|
||||
public boolean isValidRefreshType() {
|
||||
return getRefreshType() == null ||
|
||||
getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE ||
|
||||
getScheduleId() == 2701;
|
||||
return this.getTriggerConfig().getTriggerType();
|
||||
}
|
||||
|
||||
|
||||
public boolean isCycleRefresh() {
|
||||
return getRefreshType() == null || getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE;
|
||||
}
|
||||
|
||||
public boolean isValidRefreshType() {
|
||||
return getRefreshType() == null ||
|
||||
getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE ||
|
||||
getScheduleId() == 2701;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.getTriggerConfig() != null && getTriggerConfig().getParamList()[0].length() > 0) {
|
||||
this.mainParams = Arrays.stream(getTriggerConfig().getParamList()[0].split("[:;,]")).map(Integer::parseInt).collect(Collectors.toSet());
|
||||
}
|
||||
if (this.getTriggerConfig() != null && getTriggerConfig().getParamList()[0].length() > 0) {
|
||||
this.mainParams = Arrays.stream(getTriggerConfig().getParamList()[0].split("[:;,]")).map(Integer::parseInt).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
public static class TriggerConfig {
|
||||
private WatcherTriggerType triggerType;
|
||||
private String[] paramList;
|
||||
private WatcherTriggerType triggerType;
|
||||
private String[] paramList;
|
||||
}
|
||||
|
||||
|
||||
public emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission toProto() {
|
||||
var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder();
|
||||
|
||||
protoBuilder
|
||||
.setMissionId(getId())
|
||||
.setTotalProgress(this.getProgress())
|
||||
.setRewardBattlePassPoint(this.getAddPoint())
|
||||
.setMissionStatus(MissionStatus.MISSION_STATUS_UNFINISHED)
|
||||
.setMissionType(this.getRefreshType() == null ? 0 : this.getRefreshType().getValue());
|
||||
|
||||
return protoBuilder.build();
|
||||
}
|
||||
var protoBuilder = emu.grasscutter.net.proto.BattlePassMissionOuterClass.BattlePassMission.newBuilder();
|
||||
|
||||
protoBuilder
|
||||
.setMissionId(getId())
|
||||
.setTotalProgress(this.getProgress())
|
||||
.setRewardBattlePassPoint(this.getAddPoint())
|
||||
.setMissionStatus(MissionStatus.MISSION_STATUS_UNFINISHED)
|
||||
.setMissionType(this.getRefreshType() == null ? 0 : this.getRefreshType().getValue());
|
||||
|
||||
return protoBuilder.build();
|
||||
}
|
||||
}
|
||||
|
@ -7,40 +7,39 @@ import emu.grasscutter.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "BlossomRefreshExcelConfigData.json")
|
||||
@Getter
|
||||
public class BlossomRefreshExcelConfigData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
// Map details
|
||||
@Getter private long nameTextMapHash;
|
||||
@Getter private long descTextMapHash;
|
||||
@Getter private String icon;
|
||||
@Getter private String clientShowType; // BLOSSOM_SHOWTYPE_CHALLENGE, BLOSSOM_SHOWTYPE_NPCTALK
|
||||
private long nameTextMapHash;
|
||||
private long descTextMapHash;
|
||||
private String icon;
|
||||
private String clientShowType; // BLOSSOM_SHOWTYPE_CHALLENGE, BLOSSOM_SHOWTYPE_NPCTALK
|
||||
|
||||
// Refresh details
|
||||
@Getter private String refreshType; // Leyline blossoms, magical ore outcrops
|
||||
@Getter private int refreshCount; // Number of entries to spawn at refresh (1 for each leyline type for each city, 4 for magical ore for each city)
|
||||
@Getter private String refreshTime; // Server time-of-day to refresh at
|
||||
@Getter private RefreshCond[] refreshCondVec; // AR requirements etc.
|
||||
private String refreshType; // Leyline blossoms, magical ore outcrops
|
||||
private int refreshCount; // Number of entries to spawn at refresh (1 for each leyline type for each city, 4 for magical ore for each city)
|
||||
private String refreshTime; // Server time-of-day to refresh at
|
||||
private RefreshCond[] refreshCondVec; // AR requirements etc.
|
||||
|
||||
@Getter private int cityId;
|
||||
@Getter private int blossomChestId; // 1 for mora, 2 for exp
|
||||
@Getter private Drop[] dropVec;
|
||||
private int cityId;
|
||||
private int blossomChestId; // 1 for mora, 2 for exp
|
||||
private Drop[] dropVec;
|
||||
|
||||
// Unknown details
|
||||
// @Getter private int reviseLevel;
|
||||
// @Getter private int campUpdateNeedCount; // Always 1 if specified
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class Drop {
|
||||
@Getter int dropId;
|
||||
@Getter int previewReward;
|
||||
int dropId;
|
||||
int previewReward;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class RefreshCond {
|
||||
@Getter String type;
|
||||
@Getter List<Integer> param;
|
||||
String type;
|
||||
List<Integer> param;
|
||||
}
|
||||
}
|
||||
|
@ -8,27 +8,23 @@ import lombok.Setter;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ResourceType(name = "ChapterExcelConfigData.json")
|
||||
@Getter
|
||||
@Setter
|
||||
@Setter // TODO: remove on next API break
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class ChapterData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
int id;
|
||||
int beginQuestId;
|
||||
int endQuestId;
|
||||
int needPlayerLevel;
|
||||
|
||||
// Why public? TODO: privatise next API break
|
||||
public static final Map<Integer, ChapterData> beginQuestChapterMap = new HashMap<>();
|
||||
public static final Map<Integer, ChapterData> endQuestChapterMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
beginQuestChapterMap.put(beginQuestId, this);
|
||||
|
@ -22,9 +22,4 @@ public class CityData extends GameResource {
|
||||
public int getId() {
|
||||
return this.cityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
}
|
||||
|
@ -7,18 +7,15 @@ import emu.grasscutter.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = {"AnimalCodexExcelConfigData.json"})
|
||||
@Getter
|
||||
public class CodexAnimalData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int Id;
|
||||
@Getter private String type;
|
||||
@Getter private int describeId;
|
||||
@Getter private int sortOrder;
|
||||
private String type;
|
||||
private int describeId;
|
||||
private int sortOrder;
|
||||
@SerializedName(value="countType", alternate={"OCCLHPBCDGL"})
|
||||
@Getter private CountType countType;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return Id;
|
||||
}
|
||||
private CountType countType;
|
||||
|
||||
public enum CountType {
|
||||
CODEX_COUNT_TYPE_KILL,
|
||||
|
@ -8,19 +8,15 @@ import lombok.Getter;
|
||||
import java.util.List;
|
||||
|
||||
@ResourceType(name = {"CompoundExcelConfigData.json"},loadPriority = ResourceType.LoadPriority.LOW)
|
||||
@Getter
|
||||
public class CompoundData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
@Override
|
||||
public int getId() {return this.id;}
|
||||
@Getter private int groupId;
|
||||
@Getter private int rankLevel;
|
||||
@Getter private boolean isDefaultUnlocked;
|
||||
@Getter private int costTime;
|
||||
@Getter private int queueSize;
|
||||
@Getter private List<ItemParamData> inputVec;
|
||||
@Getter private List<ItemParamData> outputVec;
|
||||
|
||||
@Override
|
||||
public void onLoad(){}
|
||||
private int groupId;
|
||||
private int rankLevel;
|
||||
private boolean isDefaultUnlocked;
|
||||
private int costTime;
|
||||
private int queueSize;
|
||||
private List<ItemParamData> inputVec;
|
||||
private List<ItemParamData> outputVec;
|
||||
}
|
||||
|
@ -9,21 +9,15 @@ import emu.grasscutter.data.common.ItemParamData;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = {"CookRecipeExcelConfigData.json"}, loadPriority = LoadPriority.LOW)
|
||||
@Getter
|
||||
public class CookRecipeData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
@Getter private int rankLevel;
|
||||
@Getter boolean isDefaultUnlocked;
|
||||
@Getter int maxProficiency;
|
||||
private int rankLevel;
|
||||
private boolean isDefaultUnlocked;
|
||||
private int maxProficiency;
|
||||
|
||||
@Getter List<ItemParamData> qualityOutputVec;
|
||||
@Getter List<ItemParamData> inputVec;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
private List<ItemParamData> qualityOutputVec;
|
||||
private List<ItemParamData> inputVec;
|
||||
}
|
||||
|
@ -7,9 +7,11 @@ import emu.grasscutter.data.ResourceType;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "DailyDungeonConfigData.json")
|
||||
public class DailyDungeonData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private int[] monday;
|
||||
private int[] tuesday;
|
||||
@ -26,11 +28,6 @@ public class DailyDungeonData extends GameResource {
|
||||
this.map = new Int2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int[] getDungeonsByDay(int day) {
|
||||
return map.getOrDefault(day, empty);
|
||||
}
|
||||
|
@ -3,51 +3,28 @@ package emu.grasscutter.data.excels;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "DungeonExcelConfigData.json")
|
||||
public class DungeonData extends GameResource {
|
||||
private int id;
|
||||
private int sceneId;
|
||||
private int showLevel;
|
||||
private int passRewardPreviewID;
|
||||
private String involveType; // TODO enum
|
||||
|
||||
private RewardPreviewData previewData;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
@Getter private int sceneId;
|
||||
@Getter private int showLevel;
|
||||
private int passRewardPreviewID;
|
||||
private String involveType; // TODO enum
|
||||
|
||||
private int statueCostID;
|
||||
private int statueCostCount;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
private RewardPreviewData previewData;
|
||||
|
||||
public int getSceneId() {
|
||||
return sceneId;
|
||||
}
|
||||
|
||||
public int getShowLevel() {
|
||||
return showLevel;
|
||||
}
|
||||
@Getter private int statueCostID;
|
||||
@Getter private int statueCostCount;
|
||||
|
||||
public RewardPreviewData getRewardPreview() {
|
||||
return previewData;
|
||||
}
|
||||
public RewardPreviewData getRewardPreview() {return previewData;}
|
||||
|
||||
public int getStatueCostID() {
|
||||
return statueCostID;
|
||||
}
|
||||
|
||||
public int getStatueCostCount() {
|
||||
return statueCostCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.passRewardPreviewID > 0) {
|
||||
this.previewData = GameData.getRewardPreviewDataMap().get(this.passRewardPreviewID);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.passRewardPreviewID > 0) {
|
||||
this.previewData = GameData.getRewardPreviewDataMap().get(this.passRewardPreviewID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,19 +7,10 @@ import lombok.Setter;
|
||||
|
||||
@ResourceType(name = "DungeonEntryExcelConfigData.json")
|
||||
@Getter
|
||||
@Setter
|
||||
@Setter // TODO: remove this next API break
|
||||
public class DungeonEntryData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private int dungeonEntryId;
|
||||
private int sceneId;
|
||||
private int id;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,12 @@ import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.ResourceType.LoadPriority;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = {"ForgeExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
|
||||
@Getter
|
||||
public class ForgeData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private int playerLevel;
|
||||
private int forgeType;
|
||||
@ -21,57 +24,4 @@ public class ForgeData extends GameResource {
|
||||
private int priority;
|
||||
private int forgePoint;
|
||||
private List<ItemParamData> materialItems;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int getPlayerLevel() {
|
||||
return playerLevel;
|
||||
}
|
||||
|
||||
public int getForgeType() {
|
||||
return forgeType;
|
||||
}
|
||||
|
||||
public int getResultItemId() {
|
||||
return resultItemId;
|
||||
}
|
||||
|
||||
public int getResultItemCount() {
|
||||
return resultItemCount;
|
||||
}
|
||||
|
||||
public int getForgeTime() {
|
||||
return forgeTime;
|
||||
}
|
||||
|
||||
public int getQueueNum() {
|
||||
return queueNum;
|
||||
}
|
||||
|
||||
public int getScoinCost() {
|
||||
return scoinCost;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public int getForgePoint() {
|
||||
return forgePoint;
|
||||
}
|
||||
|
||||
public List<ItemParamData> getMaterialItems() {
|
||||
return materialItems;
|
||||
}
|
||||
|
||||
public int getShowItemId() {
|
||||
return showItemId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,12 @@ package emu.grasscutter.data.excels;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "GadgetExcelConfigData.json")
|
||||
@Getter
|
||||
public class GadgetData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
private EntityType type;
|
||||
@ -15,42 +18,4 @@ public class GadgetData extends GameResource {
|
||||
private String itemJsonName;
|
||||
private long nameTextMapHash;
|
||||
private int campID;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public EntityType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getJsonName() {
|
||||
return jsonName;
|
||||
}
|
||||
|
||||
public boolean isInteractive() {
|
||||
return isInteractive;
|
||||
}
|
||||
|
||||
public String[] getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public String getItemJsonName() {
|
||||
return itemJsonName;
|
||||
}
|
||||
|
||||
public long getNameTextMapHash() {
|
||||
return nameTextMapHash;
|
||||
}
|
||||
|
||||
public int getCampID() {
|
||||
return campID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,4 @@ public class HomeWorldLevelData extends GameResource {
|
||||
public int getId() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@ -14,6 +13,7 @@ import java.util.List;
|
||||
@Getter
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class InvestigationMonsterData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
int id;
|
||||
int cityId;
|
||||
List<Integer> monsterIdList;
|
||||
@ -23,10 +23,6 @@ public class InvestigationMonsterData extends GameResource {
|
||||
String monsterCategory;
|
||||
|
||||
CityData cityData;
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
@ -25,6 +25,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
public class ItemData extends GameResource {
|
||||
// Main
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private int stackLimit = 1;
|
||||
private int maxUseCount;
|
||||
@ -81,17 +82,12 @@ public class ItemData extends GameResource {
|
||||
private List<Integer> furnType;
|
||||
private List<Integer> furnitureGadgetID;
|
||||
|
||||
@SerializedName(value="roomSceneId", alternate={"DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK"})
|
||||
@SerializedName(value="roomSceneId", alternate={"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK"})
|
||||
private int roomSceneId;
|
||||
|
||||
// Custom
|
||||
private transient IntSet addPropLevelSet;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public WeaponProperty[] getWeaponProperties() {
|
||||
return this.weaponProp;
|
||||
}
|
||||
|
@ -1,19 +1,28 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.ResourceType.LoadPriority;
|
||||
import emu.grasscutter.data.common.PropGrowCurve;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.MonsterType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW)
|
||||
@Getter
|
||||
public class MonsterData extends GameResource {
|
||||
private int id;
|
||||
|
||||
private String monsterName;
|
||||
static public Set<FightProperty> definedFightProperties = Set.of(FightProperty.FIGHT_PROP_BASE_HP, FightProperty.FIGHT_PROP_BASE_ATTACK, FightProperty.FIGHT_PROP_BASE_DEFENSE, FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, FightProperty.FIGHT_PROP_FIRE_SUB_HURT, FightProperty.FIGHT_PROP_ELEC_SUB_HURT, FightProperty.FIGHT_PROP_WATER_SUB_HURT, FightProperty.FIGHT_PROP_GRASS_SUB_HURT, FightProperty.FIGHT_PROP_WIND_SUB_HURT, FightProperty.FIGHT_PROP_ROCK_SUB_HURT, FightProperty.FIGHT_PROP_ICE_SUB_HURT);
|
||||
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
private String monsterName;
|
||||
private MonsterType type;
|
||||
private String serverScript;
|
||||
private List<Integer> affix;
|
||||
@ -28,9 +37,14 @@ public class MonsterData extends GameResource {
|
||||
private int describeId;
|
||||
private int combatBGMLevel;
|
||||
private int entityBudgetLevel;
|
||||
private float hpBase;
|
||||
private float attackBase;
|
||||
private float defenseBase;
|
||||
|
||||
@SerializedName("hpBase")
|
||||
private float baseHp;
|
||||
@SerializedName("attackBase")
|
||||
private float baseAttack;
|
||||
@SerializedName("defenseBase")
|
||||
private float baseDefense;
|
||||
|
||||
private float fireSubHurt;
|
||||
private float elecSubHurt;
|
||||
private float grassSubHurt;
|
||||
@ -42,159 +56,49 @@ public class MonsterData extends GameResource {
|
||||
private List<PropGrowCurve> propGrowCurves;
|
||||
private long nameTextMapHash;
|
||||
private int campID;
|
||||
|
||||
|
||||
// Transient
|
||||
private int weaponId;
|
||||
private MonsterDescribeData describeData;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getMonsterName() {
|
||||
return monsterName;
|
||||
}
|
||||
|
||||
public MonsterType getType() {
|
||||
return type;
|
||||
}
|
||||
public float getFightProperty(FightProperty prop) {
|
||||
return switch (prop) {
|
||||
case FIGHT_PROP_BASE_HP -> this.baseHp;
|
||||
case FIGHT_PROP_BASE_ATTACK -> this.baseAttack;
|
||||
case FIGHT_PROP_BASE_DEFENSE -> this.baseDefense;
|
||||
case FIGHT_PROP_PHYSICAL_SUB_HURT -> this.physicalSubHurt;
|
||||
case FIGHT_PROP_FIRE_SUB_HURT -> this.fireSubHurt;
|
||||
case FIGHT_PROP_ELEC_SUB_HURT -> this.elecSubHurt;
|
||||
case FIGHT_PROP_WATER_SUB_HURT -> this.waterSubHurt;
|
||||
case FIGHT_PROP_GRASS_SUB_HURT -> this.grassSubHurt;
|
||||
case FIGHT_PROP_WIND_SUB_HURT -> this.windSubHurt;
|
||||
case FIGHT_PROP_ROCK_SUB_HURT -> this.rockSubHurt;
|
||||
case FIGHT_PROP_ICE_SUB_HURT -> this.iceSubHurt;
|
||||
default -> 0f;
|
||||
};
|
||||
}
|
||||
|
||||
public String getServerScript() {
|
||||
return serverScript;
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.describeData = GameData.getMonsterDescribeDataMap().get(this.getDescribeId());
|
||||
|
||||
public List<Integer> getAffix() {
|
||||
return affix;
|
||||
}
|
||||
for (int id : this.equips) {
|
||||
if (id == 0) {
|
||||
continue;
|
||||
}
|
||||
GadgetData gadget = GameData.getGadgetDataMap().get(id);
|
||||
if (gadget == null) {
|
||||
continue;
|
||||
}
|
||||
if (gadget.getItemJsonName().equals("Default_MonsterWeapon")) {
|
||||
this.weaponId = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getAi() {
|
||||
return ai;
|
||||
}
|
||||
|
||||
public int[] getEquips() {
|
||||
return equips;
|
||||
}
|
||||
|
||||
public List<HpDrops> getHpDrops() {
|
||||
return hpDrops;
|
||||
}
|
||||
|
||||
public int getKillDropId() {
|
||||
return killDropId;
|
||||
}
|
||||
|
||||
public String getExcludeWeathers() {
|
||||
return excludeWeathers;
|
||||
}
|
||||
|
||||
public int getFeatureTagGroupID() {
|
||||
return featureTagGroupID;
|
||||
}
|
||||
|
||||
public int getMpPropID() {
|
||||
return mpPropID;
|
||||
}
|
||||
|
||||
public String getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
public int getDescribeId() {
|
||||
return describeId;
|
||||
}
|
||||
|
||||
public int getCombatBGMLevel() {
|
||||
return combatBGMLevel;
|
||||
}
|
||||
|
||||
public int getEntityBudgetLevel() {
|
||||
return entityBudgetLevel;
|
||||
}
|
||||
|
||||
public float getBaseHp() {
|
||||
return hpBase;
|
||||
}
|
||||
|
||||
public float getBaseAttack() {
|
||||
return attackBase;
|
||||
}
|
||||
|
||||
public float getBaseDefense() {
|
||||
return defenseBase;
|
||||
}
|
||||
|
||||
public float getElecSubHurt() {
|
||||
return elecSubHurt;
|
||||
}
|
||||
|
||||
public float getGrassSubHurt() {
|
||||
return grassSubHurt;
|
||||
}
|
||||
|
||||
public float getWaterSubHurt() {
|
||||
return waterSubHurt;
|
||||
}
|
||||
|
||||
public float getWindSubHurt() {
|
||||
return windSubHurt;
|
||||
}
|
||||
|
||||
public float getIceSubHurt() {
|
||||
return iceSubHurt;
|
||||
}
|
||||
|
||||
public float getPhysicalSubHurt() {
|
||||
return physicalSubHurt;
|
||||
}
|
||||
|
||||
public List<PropGrowCurve> getPropGrowCurves() {
|
||||
return propGrowCurves;
|
||||
}
|
||||
|
||||
public long getNameTextMapHash() {
|
||||
return nameTextMapHash;
|
||||
}
|
||||
|
||||
public int getCampID() {
|
||||
return campID;
|
||||
}
|
||||
|
||||
public MonsterDescribeData getDescribeData() {
|
||||
return describeData;
|
||||
}
|
||||
|
||||
public int getWeaponId() {
|
||||
return weaponId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.describeData = GameData.getMonsterDescribeDataMap().get(this.getDescribeId());
|
||||
|
||||
for (int id : this.equips) {
|
||||
if (id == 0) {
|
||||
continue;
|
||||
}
|
||||
GadgetData gadget = GameData.getGadgetDataMap().get(id);
|
||||
if (gadget == null) {
|
||||
continue;
|
||||
}
|
||||
if (gadget.getItemJsonName().equals("Default_MonsterWeapon")) {
|
||||
this.weaponId = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HpDrops {
|
||||
private int DropId;
|
||||
private int HpPercent;
|
||||
|
||||
public int getDropId(){
|
||||
return this.DropId;
|
||||
}
|
||||
public int getHpPercent(){
|
||||
return this.HpPercent;
|
||||
}
|
||||
}
|
||||
@Getter
|
||||
public class HpDrops {
|
||||
private int DropId;
|
||||
private int HpPercent;
|
||||
}
|
||||
}
|
||||
|
@ -3,33 +3,14 @@ package emu.grasscutter.data.excels;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.ResourceType.LoadPriority;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "MonsterDescribeExcelConfigData.json", loadPriority = LoadPriority.HIGH)
|
||||
@Getter
|
||||
public class MonsterDescribeData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private long nameTextMapHash;
|
||||
private int titleID;
|
||||
private int specialNameLabID;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getNameTextMapHash() {
|
||||
return nameTextMapHash;
|
||||
}
|
||||
|
||||
public int getTitleID() {
|
||||
return titleID;
|
||||
}
|
||||
|
||||
public int getSpecialNameLabID() {
|
||||
return specialNameLabID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,8 @@ import lombok.experimental.FieldDefaults;
|
||||
@Getter
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class MusicGameBasicData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
int id;
|
||||
int musicID;
|
||||
int musicLevel;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ package emu.grasscutter.data.excels;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "NpcExcelConfigData.json")
|
||||
@Getter
|
||||
public class NpcData extends GameResource {
|
||||
private int id;
|
||||
|
||||
private String jsonName;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
private String jsonName;
|
||||
private String alias;
|
||||
private String scriptDataPath;
|
||||
private String luaDataPath;
|
||||
@ -19,54 +22,4 @@ public class NpcData extends GameResource {
|
||||
|
||||
private long nameTextMapHash;
|
||||
private int campID;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getJsonName() {
|
||||
return jsonName;
|
||||
}
|
||||
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
public String getScriptDataPath() {
|
||||
return scriptDataPath;
|
||||
}
|
||||
|
||||
public String getLuaDataPath() {
|
||||
return luaDataPath;
|
||||
}
|
||||
|
||||
public boolean isIsInteractive() {
|
||||
return isInteractive;
|
||||
}
|
||||
|
||||
public boolean isHasMove() {
|
||||
return hasMove;
|
||||
}
|
||||
|
||||
public String getDyePart() {
|
||||
return dyePart;
|
||||
}
|
||||
|
||||
public String getBillboardIcon() {
|
||||
return billboardIcon;
|
||||
}
|
||||
|
||||
public long getNameTextMapHash() {
|
||||
return nameTextMapHash;
|
||||
}
|
||||
|
||||
public int getCampID() {
|
||||
return campID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,14 @@ package emu.grasscutter.data.excels;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ResourceType(name = "OpenStateConfigData.json", loadPriority = ResourceType.LoadPriority.HIGHEST)
|
||||
public class OpenStateData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
@Getter private boolean defaultState;
|
||||
@Getter private boolean allowClientOpen;
|
||||
@ -32,11 +31,6 @@ public class OpenStateData extends GameResource {
|
||||
OPEN_STATE_COND_PARENT_QUEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Add this open state to the global list.
|
||||
|
@ -11,18 +11,13 @@ import java.util.List;
|
||||
|
||||
@ResourceType(name = "PersonalLineExcelConfigData.json")
|
||||
@Getter
|
||||
@Setter
|
||||
@Setter // TODO: remove setters next API break
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class PersonalLineData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
int id;
|
||||
int avatarID;
|
||||
List<Integer> preQuestId;
|
||||
int startQuestId;
|
||||
int chapterId;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,46 +1,23 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "ReliquaryAffixExcelConfigData.json")
|
||||
@Getter
|
||||
public class ReliquaryAffixData extends GameResource {
|
||||
private int id;
|
||||
|
||||
private int depotId;
|
||||
private int groupId;
|
||||
private FightProperty propType;
|
||||
private float propValue;
|
||||
private int weight;
|
||||
private int upgradeWeight;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getDepotId() {
|
||||
return depotId;
|
||||
}
|
||||
|
||||
public int getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public float getPropValue() {
|
||||
return propValue;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public int getUpgradeWeight() {
|
||||
return upgradeWeight;
|
||||
}
|
||||
|
||||
public FightProperty getFightProp() {
|
||||
return propType;
|
||||
}
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
private int depotId;
|
||||
private int groupId;
|
||||
@SerializedName("propType")
|
||||
private FightProperty fightProp;
|
||||
private float propValue;
|
||||
private int weight;
|
||||
private int upgradeWeight;
|
||||
}
|
||||
|
@ -7,36 +7,19 @@ import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "ReliquaryLevelExcelConfigData.json")
|
||||
public class ReliquaryLevelData extends GameResource {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private Int2FloatMap propMap;
|
||||
|
||||
private int rank;
|
||||
private int level;
|
||||
private int exp;
|
||||
@Getter private int rank;
|
||||
@Getter private int level;
|
||||
@Getter private int exp;
|
||||
private List<RelicLevelProperty> addProps;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int getRank() {
|
||||
return rank;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public int getExp() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
public float getPropValue(FightProperty prop) {
|
||||
return getPropValue(prop.getId());
|
||||
}
|
||||
@ -54,16 +37,9 @@ public class ReliquaryLevelData extends GameResource {
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public class RelicLevelProperty {
|
||||
private String propType;
|
||||
private float value;
|
||||
|
||||
public String getPropType() {
|
||||
return propType;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,20 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "ReliquaryMainPropExcelConfigData.json")
|
||||
@Getter
|
||||
public class ReliquaryMainPropData extends GameResource {
|
||||
private int id;
|
||||
|
||||
private int propDepotId;
|
||||
private FightProperty propType;
|
||||
private int weight;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getPropDepotId() {
|
||||
return propDepotId;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
|
||||
public FightProperty getFightProp() {
|
||||
return propType;
|
||||
}
|
||||
private int propDepotId;
|
||||
@SerializedName("propType")
|
||||
private FightProperty fightProp;
|
||||
private int weight;
|
||||
}
|
||||
|
@ -1,43 +1,35 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
|
||||
import lombok.Getter;
|
||||
import emu.grasscutter.data.ResourceType.LoadPriority;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import emu.grasscutter.data.common.ItemParamStringData;
|
||||
|
||||
@ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH)
|
||||
public class RewardPreviewData extends GameResource {
|
||||
private int id;
|
||||
private ItemParamStringData[] previewItems;
|
||||
private ItemParamData[] previewItemsArray;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
private ItemParamStringData[] previewItems;
|
||||
private ItemParamData[] previewItemsArray;
|
||||
|
||||
public ItemParamData[] getPreviewItems() {
|
||||
return previewItemsArray;
|
||||
}
|
||||
public ItemParamData[] getPreviewItems() {
|
||||
return previewItemsArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.previewItems != null && this.previewItems.length > 0) {
|
||||
this.previewItemsArray = Arrays.stream(this.previewItems)
|
||||
.filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty())
|
||||
.map(ItemParamStringData::toItemParamData)
|
||||
.toArray(size -> new ItemParamData[size]);
|
||||
} else {
|
||||
this.previewItemsArray = new ItemParamData[0];
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.previewItems != null && this.previewItems.length > 0) {
|
||||
this.previewItemsArray = Arrays.stream(this.previewItems)
|
||||
.filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty())
|
||||
.map(ItemParamStringData::toItemParamData)
|
||||
.toArray(size -> new ItemParamData[size]);
|
||||
} else {
|
||||
this.previewItemsArray = new ItemParamData[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,19 @@
|
||||
package emu.grasscutter.data.excels;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "SceneExcelConfigData.json")
|
||||
@Getter
|
||||
public class SceneData extends GameResource {
|
||||
private int id;
|
||||
private SceneType type;
|
||||
private String scriptData;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public SceneType getSceneType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getScriptData() {
|
||||
return scriptData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int id;
|
||||
@SerializedName("type")
|
||||
private SceneType sceneType;
|
||||
private String scriptData;
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ package emu.grasscutter.data.excels;
|
||||
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@ResourceType(name = "TowerFloorExcelConfigData.json")
|
||||
@Getter
|
||||
public class TowerFloorData extends GameResource {
|
||||
|
||||
private int floorId;
|
||||
private int floorIndex;
|
||||
private int levelGroupId;
|
||||
@ -17,33 +18,4 @@ public class TowerFloorData extends GameResource {
|
||||
public int getId() {
|
||||
return this.floorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
}
|
||||
|
||||
public int getFloorId() {
|
||||
return floorId;
|
||||
}
|
||||
|
||||
public int getFloorIndex() {
|
||||
return floorIndex;
|
||||
}
|
||||
|
||||
public int getLevelGroupId() {
|
||||
return levelGroupId;
|
||||
}
|
||||
|
||||
public int getOverrideMonsterLevel() {
|
||||
return overrideMonsterLevel;
|
||||
}
|
||||
|
||||
public int getTeamNum() {
|
||||
return teamNum;
|
||||
}
|
||||
|
||||
public int getFloorLevelConfigId() {
|
||||
return floorLevelConfigId;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package emu.grasscutter.database;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
|
||||
@ -154,6 +155,11 @@ public final class DatabaseHelper {
|
||||
DatabaseManager.getAccountDatastore().find(Account.class).filter(Filters.eq("id", target.getId())).delete();
|
||||
}
|
||||
|
||||
public static <T> Stream<T> getByGameClass(Class<T> classType) {
|
||||
return DatabaseManager.getGameDatastore().find(classType).stream();
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public static List<Player> getAllPlayers() {
|
||||
return DatabaseManager.getGameDatastore().find(Player.class).stream().toList();
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo;
|
||||
import emu.grasscutter.net.proto.ShowEquipOuterClass.ShowEquip;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
@ -89,7 +90,7 @@ public class Avatar {
|
||||
private float currentEnergy;
|
||||
|
||||
@Transient @Getter private final Int2ObjectMap<GameItem> equips;
|
||||
@Transient private final Int2FloatOpenHashMap fightProp;
|
||||
@Transient @Getter private final Int2FloatOpenHashMap fightProperties;
|
||||
@Transient @Getter private final Int2FloatOpenHashMap fightPropOverrides;
|
||||
@Transient @Getter private Set<String> extraAbilityEmbryos;
|
||||
|
||||
@ -115,7 +116,7 @@ public class Avatar {
|
||||
@Deprecated // Do not use. Morhpia only!
|
||||
public Avatar() {
|
||||
this.equips = new Int2ObjectOpenHashMap<>();
|
||||
this.fightProp = new Int2FloatOpenHashMap();
|
||||
this.fightProperties = new Int2FloatOpenHashMap();
|
||||
this.fightPropOverrides = new Int2FloatOpenHashMap();
|
||||
this.extraAbilityEmbryos = new HashSet<>();
|
||||
this.fetters = new ArrayList<>(); // TODO Move to avatar
|
||||
@ -276,10 +277,6 @@ public class Avatar {
|
||||
}
|
||||
}
|
||||
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return fightProp;
|
||||
}
|
||||
|
||||
public void setFightProperty(FightProperty prop, float value) {
|
||||
this.getFightProperties().put(prop.getId(), value);
|
||||
}
|
||||
@ -399,9 +396,9 @@ public class Avatar {
|
||||
|
||||
public void recalcStats(boolean forceSendAbilityChange) {
|
||||
// Setup
|
||||
AvatarData data = this.getAvatarData();
|
||||
AvatarPromoteData promoteData = GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
|
||||
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
|
||||
var data = this.getAvatarData();
|
||||
var promoteData = GameData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
|
||||
var setMap = new Int2IntOpenHashMap();
|
||||
|
||||
// Extra ability embryos
|
||||
Set<String> prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos();
|
||||
@ -579,21 +576,11 @@ public class Avatar {
|
||||
// Add any skill strings from this constellation
|
||||
|
||||
// Set % stats
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_MAX_HP,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_HP) * (1f + getFightProperty(FightProperty.FIGHT_PROP_HP_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_HP)
|
||||
);
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_ATTACK,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK) * (1f + getFightProperty(FightProperty.FIGHT_PROP_ATTACK_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_ATTACK)
|
||||
);
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_DEFENSE,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE) * (1f + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE)
|
||||
);
|
||||
FightProperty.forEachCompoundProperty(c -> this.setFightProperty(c.getResult(),
|
||||
this.getFightProperty(c.getFlat()) + (this.getFightProperty(c.getBase()) * (1f + this.getFightProperty(c.getPercent())))));
|
||||
|
||||
// Reapply all overrides
|
||||
this.fightProp.putAll(this.fightPropOverrides);
|
||||
this.fightProperties.putAll(this.fightPropOverrides);
|
||||
|
||||
// Set current hp
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent);
|
||||
@ -809,12 +796,14 @@ public class Avatar {
|
||||
if (level < 0) { // Special case for resetConst to remove inactive depots too
|
||||
this.talentIdList.clear();
|
||||
this.recalcStats();
|
||||
this.save();
|
||||
return;
|
||||
}
|
||||
this.talentIdList.removeAll(this.getTalentIdList()); // Only remove constellations from active depot
|
||||
for (int i = 0; i < level; i++)
|
||||
this.unlockConstellation(true);
|
||||
this.recalcStats();
|
||||
this.save();
|
||||
}
|
||||
|
||||
public boolean sendSkillExtraChargeMap() {
|
||||
|
@ -1,124 +0,0 @@
|
||||
package emu.grasscutter.game.avatar;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
public enum AvatarStat {
|
||||
FIGHT_PROP_NONE(0),
|
||||
FIGHT_PROP_BASE_HP(1),
|
||||
FIGHT_PROP_HP(2),
|
||||
FIGHT_PROP_HP_PERCENT(3),
|
||||
FIGHT_PROP_BASE_ATTACK(4),
|
||||
FIGHT_PROP_ATTACK(5),
|
||||
FIGHT_PROP_ATTACK_PERCENT(6),
|
||||
FIGHT_PROP_BASE_DEFENSE(7),
|
||||
FIGHT_PROP_DEFENSE(8),
|
||||
FIGHT_PROP_DEFENSE_PERCENT(9),
|
||||
FIGHT_PROP_BASE_SPEED(10),
|
||||
FIGHT_PROP_SPEED_PERCENT(11),
|
||||
FIGHT_PROP_HP_MP_PERCENT(12),
|
||||
FIGHT_PROP_ATTACK_MP_PERCENT(13),
|
||||
FIGHT_PROP_CRITICAL(20),
|
||||
FIGHT_PROP_ANTI_CRITICAL(21),
|
||||
FIGHT_PROP_CRITICAL_HURT(22),
|
||||
FIGHT_PROP_CHARGE_EFFICIENCY(23),
|
||||
FIGHT_PROP_ADD_HURT(24),
|
||||
FIGHT_PROP_SUB_HURT(25),
|
||||
FIGHT_PROP_HEAL_ADD(26),
|
||||
FIGHT_PROP_HEALED_ADD(27),
|
||||
FIGHT_PROP_ELEMENT_MASTERY(28),
|
||||
FIGHT_PROP_PHYSICAL_SUB_HURT(29),
|
||||
FIGHT_PROP_PHYSICAL_ADD_HURT(30),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_RATIO(31),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_DELTA(32),
|
||||
FIGHT_PROP_FIRE_ADD_HURT(40),
|
||||
FIGHT_PROP_ELEC_ADD_HURT(41),
|
||||
FIGHT_PROP_WATER_ADD_HURT(42),
|
||||
FIGHT_PROP_GRASS_ADD_HURT(43),
|
||||
FIGHT_PROP_WIND_ADD_HURT(44),
|
||||
FIGHT_PROP_ROCK_ADD_HURT(45),
|
||||
FIGHT_PROP_ICE_ADD_HURT(46),
|
||||
FIGHT_PROP_HIT_HEAD_ADD_HURT(47),
|
||||
FIGHT_PROP_FIRE_SUB_HURT(50),
|
||||
FIGHT_PROP_ELEC_SUB_HURT(51),
|
||||
FIGHT_PROP_WATER_SUB_HURT(52),
|
||||
FIGHT_PROP_GRASS_SUB_HURT(53),
|
||||
FIGHT_PROP_WIND_SUB_HURT(54),
|
||||
FIGHT_PROP_ROCK_SUB_HURT(55),
|
||||
FIGHT_PROP_ICE_SUB_HURT(56),
|
||||
FIGHT_PROP_EFFECT_HIT(60),
|
||||
FIGHT_PROP_EFFECT_RESIST(61),
|
||||
FIGHT_PROP_FREEZE_RESIST(62),
|
||||
FIGHT_PROP_TORPOR_RESIST(63),
|
||||
FIGHT_PROP_DIZZY_RESIST(64),
|
||||
FIGHT_PROP_FREEZE_SHORTEN(65),
|
||||
FIGHT_PROP_TORPOR_SHORTEN(66),
|
||||
FIGHT_PROP_DIZZY_SHORTEN(67),
|
||||
FIGHT_PROP_MAX_FIRE_ENERGY(70),
|
||||
FIGHT_PROP_MAX_ELEC_ENERGY(71),
|
||||
FIGHT_PROP_MAX_WATER_ENERGY(72),
|
||||
FIGHT_PROP_MAX_GRASS_ENERGY(73),
|
||||
FIGHT_PROP_MAX_WIND_ENERGY(74),
|
||||
FIGHT_PROP_MAX_ICE_ENERGY(75),
|
||||
FIGHT_PROP_MAX_ROCK_ENERGY(76),
|
||||
FIGHT_PROP_SKILL_CD_MINUS_RATIO(80),
|
||||
FIGHT_PROP_SHIELD_COST_MINUS_RATIO(81),
|
||||
FIGHT_PROP_CUR_FIRE_ENERGY(1000),
|
||||
FIGHT_PROP_CUR_ELEC_ENERGY(1001),
|
||||
FIGHT_PROP_CUR_WATER_ENERGY(1002),
|
||||
FIGHT_PROP_CUR_GRASS_ENERGY(1003),
|
||||
FIGHT_PROP_CUR_WIND_ENERGY(1004),
|
||||
FIGHT_PROP_CUR_ICE_ENERGY(1005),
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY(1006),
|
||||
FIGHT_PROP_CUR_HP(1010),
|
||||
FIGHT_PROP_MAX_HP(2000),
|
||||
FIGHT_PROP_CUR_ATTACK(2001),
|
||||
FIGHT_PROP_CUR_DEFENSE(2002),
|
||||
FIGHT_PROP_CUR_SPEED(2003),
|
||||
FIGHT_PROP_NONEXTRA_ATTACK(3000),
|
||||
FIGHT_PROP_NONEXTRA_DEFENSE(3001),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL(3002),
|
||||
FIGHT_PROP_NONEXTRA_ANTI_CRITICAL(3003),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL_HURT(3004),
|
||||
FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY(3005),
|
||||
FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY(3006),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT(3007),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT(3008),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT(3009),
|
||||
FIGHT_PROP_NONEXTRA_WATER_ADD_HURT(3010),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT(3011),
|
||||
FIGHT_PROP_NONEXTRA_WIND_ADD_HURT(3012),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT(3013),
|
||||
FIGHT_PROP_NONEXTRA_ICE_ADD_HURT(3014),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT(3015),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT(3016),
|
||||
FIGHT_PROP_NONEXTRA_WATER_SUB_HURT(3017),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT(3018),
|
||||
FIGHT_PROP_NONEXTRA_WIND_SUB_HURT(3019),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT(3020),
|
||||
FIGHT_PROP_NONEXTRA_ICE_SUB_HURT(3021),
|
||||
FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO(3022),
|
||||
FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO(3023),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT(3024);
|
||||
|
||||
private final int id;
|
||||
private static final Int2ObjectMap<AvatarStat> map = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static {
|
||||
Stream.of(values()).forEach(e -> map.put(e.getId(), e));
|
||||
}
|
||||
|
||||
private AvatarStat(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static AvatarStat getStatById(int value) {
|
||||
return map.getOrDefault(value, FIGHT_PROP_NONE);
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
||||
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
||||
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
|
||||
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
|
||||
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
||||
@ -38,20 +37,25 @@ import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
|
||||
public class EntityAvatar extends GameEntity {
|
||||
private final Avatar avatar;
|
||||
@Getter private final Avatar avatar;
|
||||
|
||||
private PlayerDieType killedType;
|
||||
private int killedBy;
|
||||
@Getter private PlayerDieType killedType;
|
||||
@Getter private int killedBy;
|
||||
|
||||
public EntityAvatar(Avatar avatar) {
|
||||
this(null, avatar);
|
||||
}
|
||||
|
||||
public EntityAvatar(Scene scene, Avatar avatar) {
|
||||
super(scene);
|
||||
this.avatar = avatar;
|
||||
this.avatar.setCurrentEnergy();
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
|
||||
if (scene != null)
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
|
||||
|
||||
GameItem weapon = this.getAvatar().getWeapon();
|
||||
if (weapon != null) {
|
||||
@ -59,47 +63,20 @@ public class EntityAvatar extends GameEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public EntityAvatar(Avatar avatar) {
|
||||
super(null);
|
||||
this.avatar = avatar;
|
||||
this.avatar.setCurrentEnergy();
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return avatar.getPlayer();
|
||||
}
|
||||
public Player getPlayer() {return this.avatar.getPlayer();}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return getPlayer().getPosition();
|
||||
}
|
||||
public Position getPosition() {return getPlayer().getPosition();}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return getPlayer().getRotation();
|
||||
}
|
||||
|
||||
public Avatar getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public int getKilledBy() {
|
||||
return killedBy;
|
||||
}
|
||||
|
||||
public PlayerDieType getKilledType() {
|
||||
return killedType;
|
||||
}
|
||||
public Position getRotation() {return getPlayer().getRotation();}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return getAvatar().getFightProperties();
|
||||
}
|
||||
@Override public Int2FloatMap getFightProperties() {return getAvatar().getFightProperties();}
|
||||
|
||||
public int getWeaponEntityId() {
|
||||
if (getAvatar().getWeapon() != null) {
|
||||
@ -145,11 +122,8 @@ public class EntityAvatar extends GameEntity {
|
||||
|
||||
public void clearEnergy(ChangeEnergyReason reason) {
|
||||
// Fight props.
|
||||
FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
|
||||
FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp();
|
||||
|
||||
// Get max energy.
|
||||
float maxEnergy = this.avatar.getFightProperty(maxEnergyProp);
|
||||
val curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
|
||||
float curEnergy = this.getFightProperty(curEnergyProp);
|
||||
|
||||
// Set energy to zero.
|
||||
this.avatar.setCurrentEnergy(curEnergyProp, 0);
|
||||
@ -158,7 +132,7 @@ public class EntityAvatar extends GameEntity {
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp));
|
||||
|
||||
if (reason == ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START) {
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -maxEnergy, reason));
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -curEnergy, reason));
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,18 +141,16 @@ public class EntityAvatar extends GameEntity {
|
||||
}
|
||||
public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) {
|
||||
// Get current and maximum energy for this avatar.
|
||||
FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
|
||||
FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp();
|
||||
val elementType = this.getAvatar().getSkillDepot().getElementType();
|
||||
val curEnergyProp = elementType.getCurEnergyProp();
|
||||
val maxEnergyProp = elementType.getMaxEnergyProp();
|
||||
|
||||
float curEnergy = this.getFightProperty(curEnergyProp);
|
||||
float maxEnergy = this.getFightProperty(maxEnergyProp);
|
||||
|
||||
// Get energy recharge.
|
||||
float energyRecharge = this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY);
|
||||
|
||||
// Scale amount by energy recharge, if the amount is not flat.
|
||||
if (!isFlat) {
|
||||
amount *= energyRecharge;
|
||||
amount *= this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY);
|
||||
}
|
||||
|
||||
// Determine the new energy value.
|
||||
|
@ -3,11 +3,23 @@ package emu.grasscutter.game.entity;
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class EntityBaseGadget extends GameEntity {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
protected final Position position;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
protected final Position rotation;
|
||||
|
||||
public EntityBaseGadget(Scene scene) {
|
||||
this(scene, null, null);
|
||||
}
|
||||
|
||||
public EntityBaseGadget(Scene scene, Position position, Position rotation) {
|
||||
super(scene);
|
||||
this.position = position != null ? position.clone() : new Position();
|
||||
this.rotation = rotation != null ? rotation.clone() : new Position();
|
||||
}
|
||||
|
||||
public abstract int getGadgetId();
|
||||
|
@ -19,30 +19,28 @@ import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EntityClientGadget extends EntityBaseGadget {
|
||||
private final Player owner;
|
||||
@Getter private final Player owner;
|
||||
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private int gadgetId;
|
||||
|
||||
private int configId;
|
||||
private int campId;
|
||||
private int campType;
|
||||
private int ownerEntityId;
|
||||
private int targetEntityId;
|
||||
private boolean asyncLoad;
|
||||
@Getter private int campId;
|
||||
@Getter private int campType;
|
||||
@Getter private int ownerEntityId;
|
||||
@Getter private int targetEntityId;
|
||||
@Getter private boolean asyncLoad;
|
||||
|
||||
private int originalOwnerEntityId;
|
||||
@Getter private int originalOwnerEntityId;
|
||||
|
||||
public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) {
|
||||
super(scene);
|
||||
super(scene, new Position(notify.getInitPos()), new Position(notify.getInitEulerAngles()));
|
||||
this.owner = player;
|
||||
this.id = notify.getEntityId();
|
||||
this.pos = new Position(notify.getInitPos());
|
||||
this.rot = new Position(notify.getInitEulerAngles());
|
||||
this.configId = notify.getConfigId();
|
||||
this.gadgetId = notify.getConfigId();
|
||||
this.campId = notify.getCampId();
|
||||
this.campType = notify.getCampType();
|
||||
this.ownerEntityId = notify.getPropOwnerEntityId();
|
||||
@ -58,61 +56,12 @@ public class EntityClientGadget extends EntityBaseGadget {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGadgetId() {
|
||||
return configId;
|
||||
}
|
||||
|
||||
public Player getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public int getCampId() {
|
||||
return campId;
|
||||
}
|
||||
|
||||
public int getCampType() {
|
||||
return campType;
|
||||
}
|
||||
|
||||
public int getOwnerEntityId() {
|
||||
return ownerEntityId;
|
||||
}
|
||||
|
||||
public int getTargetEntityId() {
|
||||
return targetEntityId;
|
||||
}
|
||||
|
||||
public boolean isAsyncLoad() {
|
||||
return this.asyncLoad;
|
||||
}
|
||||
|
||||
public int getOriginalOwnerEntityId() {
|
||||
return this.originalOwnerEntityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(int killerId) {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
// TODO Auto-generated method stub
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
// TODO Auto-generated method stub
|
||||
return this.rot;
|
||||
}
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
|
@ -6,8 +6,6 @@ import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.entity.gadget.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
@ -29,77 +27,47 @@ import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ToString(callSuper = true)
|
||||
public class EntityGadget extends EntityBaseGadget {
|
||||
private final GadgetData data;
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
@Getter private final GadgetData gadgetData;
|
||||
@Getter(onMethod = @__(@Override)) @Setter
|
||||
private int gadgetId;
|
||||
|
||||
private int state;
|
||||
private int pointType;
|
||||
private GadgetContent content;
|
||||
private Int2FloatOpenHashMap fightProp;
|
||||
private SceneGadget metaGadget;
|
||||
@Getter @Setter private int state;
|
||||
@Getter @Setter private int pointType;
|
||||
@Getter private GadgetContent content;
|
||||
@Getter(onMethod = @__(@Override), lazy = true)
|
||||
private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap();
|
||||
@Getter @Setter private SceneGadget metaGadget;
|
||||
@Nullable @Getter
|
||||
private ConfigGadget configGadget;
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) {
|
||||
super(scene);
|
||||
this.data = GameData.getGadgetDataMap().get(gadgetId);
|
||||
if (data!=null && data.getJsonName()!=null) {
|
||||
this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName());
|
||||
}
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.gadgetId = gadgetId;
|
||||
this.pos = pos.clone();
|
||||
this.rot = rot != null ? rot.clone() : new Position();
|
||||
fillFightProps(configGadget);
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
||||
this(scene, gadgetId, pos, null, null);
|
||||
}
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
||||
this(scene, gadgetId, pos, new Position());
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) {
|
||||
this(scene, gadgetId, pos, rot, null);
|
||||
}
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) {
|
||||
this(scene, gadgetId, pos, rot);
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public GadgetData getGadgetData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return this.rot;
|
||||
}
|
||||
|
||||
public int getGadgetId() {
|
||||
return gadgetId;
|
||||
}
|
||||
|
||||
public void setGadgetId(int gadgetId) {
|
||||
super(scene, pos, rot);
|
||||
this.gadgetData = GameData.getGadgetDataMap().get(gadgetId);
|
||||
this.configGadget = Optional.ofNullable(this.gadgetData).map(GadgetData::getJsonName).map(GameData.getGadgetConfigData()::get).orElse(null);
|
||||
this.id = this.getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.gadgetId = gadgetId;
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(int state) {
|
||||
this.state = state;
|
||||
this.content = content;
|
||||
fillFightProps(configGadget);
|
||||
}
|
||||
|
||||
public void updateState(int state) {
|
||||
@ -108,39 +76,18 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_STATE_CHANGE, new ScriptArgs(state, this.getConfigId()));
|
||||
}
|
||||
|
||||
public int getPointType() {
|
||||
return pointType;
|
||||
}
|
||||
|
||||
public void setPointType(int pointType) {
|
||||
this.pointType = pointType;
|
||||
}
|
||||
|
||||
public GadgetContent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Deprecated // Dont use!
|
||||
@Deprecated(forRemoval = true) // Dont use!
|
||||
public void setContent(GadgetContent content) {
|
||||
this.content = this.content == null ? content : this.content;
|
||||
}
|
||||
|
||||
public SceneGadget getMetaGadget() {
|
||||
return metaGadget;
|
||||
}
|
||||
|
||||
public void setMetaGadget(SceneGadget metaGadget) {
|
||||
this.metaGadget = metaGadget;
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
public void buildContent() {
|
||||
if (getContent() != null || getGadgetData() == null || getGadgetData().getType() == null) {
|
||||
if (this.getContent() != null || this.getGadgetData() == null || this.getGadgetData().getType() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityType type = getGadgetData().getType();
|
||||
GadgetContent content = switch (type) {
|
||||
this.content = switch (this.getGadgetData().getType()) {
|
||||
case GatherPoint -> new GadgetGatherPoint(this);
|
||||
case GatherObject -> new GadgetGatherObject(this);
|
||||
case Worktop -> new GadgetWorktop(this);
|
||||
@ -149,14 +96,6 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
case Gadget -> new GadgetObject(this);
|
||||
default -> null;
|
||||
};
|
||||
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
|
||||
return this.fightProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -216,7 +155,7 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
entityInfo.addPropList(pair);
|
||||
|
||||
// We do not use the getter to null check because the getter will create a fight prop map if it is null
|
||||
if (this.fightProp != null) {
|
||||
if (this.fightProperties != null) {
|
||||
addAllFightPropsToEntityInfo(entityInfo);
|
||||
}
|
||||
|
||||
|
@ -25,57 +25,33 @@ import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EntityItem extends EntityBaseGadget {
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
|
||||
private final GameItem item;
|
||||
private final long guid;
|
||||
|
||||
private final boolean share;
|
||||
@Getter private final GameItem item;
|
||||
@Getter private final long guid;
|
||||
@Getter private final boolean share;
|
||||
|
||||
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count) {
|
||||
super(scene);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position();
|
||||
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.item = new GameItem(itemData, count);
|
||||
this.share = true;
|
||||
this(scene, player, itemData, pos, count, true);
|
||||
}
|
||||
|
||||
// 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);
|
||||
super(scene, pos, null);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position();
|
||||
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.item = new GameItem(itemData, count);
|
||||
this.share = share;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
private GameItem getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
public ItemData getItemData() {
|
||||
return this.getItem().getItemData();
|
||||
}
|
||||
|
||||
public long getGuid() {
|
||||
return guid;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.getItem().getCount();
|
||||
}
|
||||
@ -85,24 +61,7 @@ public class EntityItem extends EntityBaseGadget {
|
||||
return this.getItemData().getGadgetId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return this.rot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isShare() {
|
||||
return share;
|
||||
}
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
|
||||
@Override
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {
|
||||
|
@ -1,14 +1,12 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import java.util.Optional;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import emu.grasscutter.data.common.PropGrowCurve;
|
||||
import emu.grasscutter.data.excels.EnvAnimalGatherConfigData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.data.excels.MonsterCurveData;
|
||||
import emu.grasscutter.data.excels.MonsterData;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
@ -16,13 +14,11 @@ import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
||||
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
||||
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.MonsterBornTypeOuterClass.MonsterBornType;
|
||||
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
||||
@ -35,31 +31,32 @@ import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class EntityMonster extends GameEntity {
|
||||
private final MonsterData monsterData;
|
||||
private final Int2FloatOpenHashMap fightProp;
|
||||
@Getter private final MonsterData monsterData;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Int2FloatOpenHashMap fightProperties;
|
||||
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
private final Position bornPos;
|
||||
private final int level;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Position position;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Position rotation;
|
||||
@Getter private final Position bornPos;
|
||||
@Getter private final int level;
|
||||
private int weaponEntityId;
|
||||
private int poseId;
|
||||
@Getter @Setter
|
||||
private int aiId=-1;
|
||||
@Getter @Setter private int poseId;
|
||||
@Getter @Setter private int aiId = -1;
|
||||
|
||||
public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) {
|
||||
super(scene);
|
||||
this.id = getWorld().getNextEntityId(EntityIdType.MONSTER);
|
||||
this.monsterData = monsterData;
|
||||
this.fightProp = new Int2FloatOpenHashMap();
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position();
|
||||
this.fightProperties = new Int2FloatOpenHashMap();
|
||||
this.position = new Position(pos);
|
||||
this.rotation = new Position();
|
||||
this.bornPos = getPosition().clone();
|
||||
this.level = level;
|
||||
|
||||
@ -71,59 +68,19 @@ public class EntityMonster extends GameEntity {
|
||||
this.recalcStats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public MonsterData getMonsterData() {
|
||||
return monsterData;
|
||||
}
|
||||
|
||||
public int getMonsterWeaponId() {
|
||||
return getMonsterData().getWeaponId();
|
||||
return this.getMonsterData().getWeaponId();
|
||||
}
|
||||
|
||||
private int getMonsterId() {
|
||||
return this.getMonsterData().getId();
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return this.rot;
|
||||
}
|
||||
|
||||
public Position getBornPos() {
|
||||
return bornPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return fightProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
|
||||
}
|
||||
|
||||
public int getPoseId() {
|
||||
return poseId;
|
||||
}
|
||||
|
||||
public void setPoseId(int poseId) {
|
||||
this.poseId = poseId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {
|
||||
EnvAnimalGatherConfigData gatherData = GameData.getEnvAnimalGatherConfigDataMap().get(this.getMonsterData().getId());
|
||||
@ -163,27 +120,24 @@ public class EntityMonster extends GameEntity {
|
||||
@Override
|
||||
public void onDeath(int killerId) {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
var scene = this.getScene();
|
||||
var challenge = Optional.ofNullable(scene.getChallenge());
|
||||
var scriptManager = scene.getScriptManager();
|
||||
|
||||
Optional.ofNullable(this.getSpawnEntry()).ifPresent(scene.getDeadSpawnedEntities()::add);
|
||||
|
||||
if (this.getSpawnEntry() != null) {
|
||||
this.getScene().getDeadSpawnedEntities().add(getSpawnEntry());
|
||||
}
|
||||
// first set the challenge data
|
||||
if (getScene().getChallenge() != null) {
|
||||
getScene().getChallenge().onMonsterDeath(this);
|
||||
}
|
||||
if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) {
|
||||
if (getScene().getScriptManager().getScriptMonsterSpawnService() != null) {
|
||||
getScene().getScriptManager().getScriptMonsterSpawnService().onMonsterDead(this);
|
||||
}
|
||||
challenge.ifPresent(c -> c.onMonsterDeath(this));
|
||||
|
||||
if (scriptManager.isInit() && this.getGroupId() > 0) {
|
||||
Optional.ofNullable(scriptManager.getScriptMonsterSpawnService()).ifPresent(s -> s.onMonsterDead(this));
|
||||
|
||||
// prevent spawn monster after success
|
||||
if (getScene().getChallenge() != null && getScene().getChallenge().inProgress()) {
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
|
||||
}else if (getScene().getChallenge() == null) {
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
|
||||
}
|
||||
if (challenge.map(c -> c.inProgress()).orElse(true))
|
||||
scriptManager.callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
|
||||
}
|
||||
// Battle Pass trigger
|
||||
getScene().getPlayers().forEach(p -> p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_MONSTER_DIE, this.getMonsterId(), 1));
|
||||
scene.getPlayers().forEach(p -> p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_MONSTER_DIE, this.getMonsterId(), 1));
|
||||
}
|
||||
|
||||
public void recalcStats() {
|
||||
@ -197,18 +151,7 @@ public class EntityMonster extends GameEntity {
|
||||
this.getFightProperties().clear();
|
||||
|
||||
// Base stats
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, data.getBaseHp());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, data.getBaseAttack());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE, data.getBaseDefense());
|
||||
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, data.getPhysicalSubHurt());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_FIRE_SUB_HURT, .1f);
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_ELEC_SUB_HURT, data.getElecSubHurt());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_WATER_SUB_HURT, data.getWaterSubHurt());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_GRASS_SUB_HURT, data.getGrassSubHurt());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_WIND_SUB_HURT, data.getWindSubHurt());
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_ROCK_SUB_HURT, .1f);
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_ICE_SUB_HURT, data.getIceSubHurt());
|
||||
MonsterData.definedFightProperties.forEach(prop -> this.setFightProperty(prop, data.getFightProperty(prop)));
|
||||
|
||||
// Level curve
|
||||
MonsterCurveData curve = GameData.getMonsterCurveDataMap().get(this.getLevel());
|
||||
@ -220,18 +163,8 @@ public class EntityMonster extends GameEntity {
|
||||
}
|
||||
|
||||
// Set % stats
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_MAX_HP,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_HP) * (1f + getFightProperty(FightProperty.FIGHT_PROP_HP_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_HP)
|
||||
);
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_ATTACK,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK) * (1f + getFightProperty(FightProperty.FIGHT_PROP_ATTACK_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_ATTACK)
|
||||
);
|
||||
this.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_DEFENSE,
|
||||
(getFightProperty(FightProperty.FIGHT_PROP_BASE_DEFENSE) * (1f + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE_PERCENT))) + getFightProperty(FightProperty.FIGHT_PROP_DEFENSE)
|
||||
);
|
||||
FightProperty.forEachCompoundProperty(c -> this.setFightProperty(c.getResult(),
|
||||
this.getFightProperty(c.getFlat()) + (this.getFightProperty(c.getBase()) * (1f + this.getFightProperty(c.getPercent())))));
|
||||
|
||||
// Set current hp
|
||||
this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * hpPercent);
|
||||
@ -239,14 +172,14 @@ public class EntityMonster extends GameEntity {
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
var authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(this.getBornPos().toProto()))
|
||||
.setBornPos(this.getBornPos().toProto())
|
||||
.build();
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
var entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER)
|
||||
.setMotionInfo(this.getMotionInfo())
|
||||
@ -257,13 +190,12 @@ public class EntityMonster extends GameEntity {
|
||||
|
||||
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel()))
|
||||
.build();
|
||||
entityInfo.addPropList(pair);
|
||||
entityInfo.addPropList(PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel()))
|
||||
.build());
|
||||
|
||||
SceneMonsterInfo.Builder monsterInfo = SceneMonsterInfo.newBuilder()
|
||||
var monsterInfo = SceneMonsterInfo.newBuilder()
|
||||
.setMonsterId(getMonsterId())
|
||||
.setGroupId(this.getGroupId())
|
||||
.setConfigId(this.getConfigId())
|
||||
|
@ -5,14 +5,16 @@ import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.scripts.data.SceneNPC;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EntityNPC extends GameEntity{
|
||||
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Position position;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Position rotation;
|
||||
private final SceneNPC metaNpc;
|
||||
private final int suiteId;
|
||||
@Getter private final int suiteId;
|
||||
|
||||
public EntityNPC(Scene scene, SceneNPC metaNPC, int blockId, int suiteId) {
|
||||
super(scene);
|
||||
@ -27,24 +29,7 @@ public class EntityNPC extends GameEntity{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public int getSuiteId() {
|
||||
return suiteId;
|
||||
}
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
|
@ -5,7 +5,7 @@ import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Set;
|
||||
@ -57,20 +57,11 @@ public class EntityRegion extends GameEntity{
|
||||
}
|
||||
public boolean entityLeave() {return this.entityLeave;}
|
||||
public void resetEntityLeave() {this.entityLeave = false;}
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
@Override public Position getPosition() {return position;}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return null;
|
||||
}
|
||||
@Override public Position getRotation() {return null;}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
|
@ -12,7 +12,6 @@ import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncState
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
||||
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
||||
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
||||
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
|
||||
@ -36,10 +35,8 @@ import java.util.List;
|
||||
public class EntityVehicle extends EntityBaseGadget {
|
||||
|
||||
@Getter private final Player owner;
|
||||
private final Int2FloatMap fightProp;
|
||||
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Int2FloatMap fightProperties;
|
||||
|
||||
@Getter private final int pointId;
|
||||
@Getter private final int gadgetId;
|
||||
@ -49,12 +46,10 @@ public class EntityVehicle extends EntityBaseGadget {
|
||||
@Nullable @Getter private ConfigGadget configGadget;
|
||||
|
||||
public EntityVehicle(Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) {
|
||||
super(scene);
|
||||
super(scene, pos, rot);
|
||||
this.owner = player;
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.fightProp = new Int2FloatOpenHashMap();
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position(rot);
|
||||
this.fightProperties = new Int2FloatOpenHashMap();
|
||||
this.gadgetId = gadgetId;
|
||||
this.pointId = pointId;
|
||||
this.curStamina = 240; // might be in configGadget.GCALKECLLLP.JBAKBEFIMBN.ANBMPHPOALP
|
||||
@ -74,19 +69,6 @@ public class EntityVehicle extends EntityBaseGadget {
|
||||
this.addFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return fightProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() { return this.pos; }
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return this.rot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
|
||||
|
@ -33,7 +33,7 @@ public abstract class GameEntity {
|
||||
@Getter @Setter private int configId;
|
||||
@Getter @Setter private int groupId;
|
||||
|
||||
private MotionState moveState;
|
||||
@Getter @Setter private MotionState motionState;
|
||||
@Getter @Setter private int lastMoveSceneTimeMs;
|
||||
@Getter @Setter private int lastMoveReliableSeq;
|
||||
|
||||
@ -45,7 +45,7 @@ public abstract class GameEntity {
|
||||
|
||||
public GameEntity(Scene scene) {
|
||||
this.scene = scene;
|
||||
this.moveState = MotionState.MOTION_STATE_NONE;
|
||||
this.motionState = MotionState.MOTION_STATE_NONE;
|
||||
}
|
||||
|
||||
public int getEntityType() {
|
||||
@ -84,14 +84,6 @@ public abstract class GameEntity {
|
||||
|
||||
public abstract Position getRotation();
|
||||
|
||||
public MotionState getMotionState() {
|
||||
return moveState;
|
||||
}
|
||||
|
||||
public void setMotionState(MotionState moveState) {
|
||||
this.moveState = moveState;
|
||||
}
|
||||
|
||||
public void setFightProperty(FightProperty prop, float value) {
|
||||
this.getFightProperties().put(prop.getId(), value);
|
||||
}
|
||||
|
@ -20,12 +20,12 @@ import javax.annotation.Nullable;
|
||||
public class EntityPlatform extends EntityBaseGadget {
|
||||
@Getter
|
||||
private final Player owner;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final int gadgetId;
|
||||
@Getter
|
||||
private final EntityClientGadget gadget;
|
||||
private final Int2FloatMap fightProp;
|
||||
private final Position pos;
|
||||
private final Position rot;
|
||||
@Getter(onMethod = @__(@Override))
|
||||
private final Int2FloatMap fightProperties;
|
||||
@Nullable
|
||||
@Getter
|
||||
private ConfigGadget configGadget;
|
||||
@ -39,13 +39,11 @@ public class EntityPlatform extends EntityBaseGadget {
|
||||
private boolean isActive;
|
||||
|
||||
public EntityPlatform(EntityClientGadget gadget, Scene scene, Player player, int gadgetId, Position pos, Position rot, MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType) {
|
||||
super(scene);
|
||||
super(scene, pos, rot);
|
||||
this.gadget = gadget;
|
||||
this.owner = player;
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.fightProp = new Int2FloatOpenHashMap();
|
||||
this.pos = new Position(pos);
|
||||
this.rot = new Position(rot);
|
||||
this.fightProperties = new Int2FloatOpenHashMap();
|
||||
this.movingPlatformType = movingPlatformType;
|
||||
this.gadgetId = gadgetId;
|
||||
GadgetData data = GameData.getGadgetDataMap().get(gadgetId);
|
||||
@ -56,26 +54,6 @@ public class EntityPlatform extends EntityBaseGadget {
|
||||
fillFightProps(configGadget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGadgetId() {
|
||||
return gadgetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return fightProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return rot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
var platform = PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
|
@ -2,6 +2,7 @@ package emu.grasscutter.game.gacha;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.*;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.common.ItemParamData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.proto.GachaInfoOuterClass.GachaInfo;
|
||||
@ -39,14 +40,41 @@ public class GachaBanner {
|
||||
private int eventChance4 = 50; // Chance to win a featured event item
|
||||
private int eventChance5 = 50; // Chance to win a featured event item
|
||||
@Getter private BannerType bannerType = BannerType.STANDARD;
|
||||
|
||||
// Kinda wanna deprecate these but they're in people's configs
|
||||
private int[] rateUpItems1 = {};
|
||||
private int[] rateUpItems2 = {};
|
||||
private int eventChance = -1;
|
||||
private int costItem = 0;
|
||||
@Getter private int wishMaxProgress = 2;
|
||||
|
||||
// Deprecated fields that were tolerated in early May 2022 but have apparently still being circulating in new custom configs
|
||||
// For now, throw up big scary errors on load telling people that they will be banned outright in a future version
|
||||
@Deprecated private int[] rateUpItems1 = {};
|
||||
@Deprecated private int[] rateUpItems2 = {};
|
||||
@Deprecated private int eventChance = -1;
|
||||
@Deprecated private int costItem = 0;
|
||||
@Deprecated private int softPity = -1;
|
||||
@Deprecated private int hardPity = -1;
|
||||
@Deprecated private int minItemType = -1;
|
||||
@Deprecated private int maxItemType = -1;
|
||||
|
||||
private static void warnDeprecated(String name, String replacement) {
|
||||
Grasscutter.getLogger().error("Deprecated field found in Banners.json: "+name+" was replaced back in early May 2022, use "+replacement+" instead. If you do not remove this key from your config, it will refuse to load in a future Grasscutter version.");
|
||||
}
|
||||
public void onLoad() {
|
||||
if (eventChance != -1)
|
||||
warnDeprecated("eventChance", "eventChance4 & eventChance5");
|
||||
if (costItem != 0)
|
||||
warnDeprecated("costItem", "costItemId");
|
||||
if (softPity != -1)
|
||||
warnDeprecated("softPity", "weights5");
|
||||
if (hardPity != -1)
|
||||
warnDeprecated("hardPity", "weights5");
|
||||
if (minItemType != -1)
|
||||
warnDeprecated("minItemType", "fallbackItems[4,5]Pool[1,2]");
|
||||
if (maxItemType != -1)
|
||||
warnDeprecated("maxItemType", "fallbackItems[4,5]Pool[1,2]");
|
||||
if (rateUpItems1.length > 0)
|
||||
warnDeprecated("rateUpItems1", "rateUpItems5");
|
||||
if (rateUpItems2.length > 0)
|
||||
warnDeprecated("rateUpItems2", "rateUpItems4");
|
||||
}
|
||||
|
||||
public String getPreviewPrefabPath() {
|
||||
if (this.previewPrefabPath != null && !this.previewPrefabPath.isEmpty())
|
||||
return this.previewPrefabPath;
|
||||
|
@ -73,6 +73,7 @@ public class GachaSystem extends BaseGameSystem {
|
||||
List<GachaBanner> banners = DataLoader.loadList("Banners.json", GachaBanner.class);
|
||||
if (banners.size() > 0) {
|
||||
for (GachaBanner banner : banners) {
|
||||
banner.onLoad();
|
||||
getGachaBanners().put(banner.getScheduleId(), banner);
|
||||
}
|
||||
Grasscutter.getLogger().debug("Banners successfully loaded.");
|
||||
|
@ -11,6 +11,7 @@ import emu.grasscutter.data.excels.HomeWorldLevelData;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -20,6 +21,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity(value = "homes", useDiscriminator = false)
|
||||
@Data
|
||||
@ -57,6 +59,7 @@ public class GameHome {
|
||||
.ownerUid(uid)
|
||||
.level(1)
|
||||
.sceneMap(new ConcurrentHashMap<>())
|
||||
.unlockedHomeBgmList(new HashSet<>())
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -93,7 +96,7 @@ public class GameHome {
|
||||
}
|
||||
|
||||
public boolean addUnlockedHomeBgm(int homeBgmId) {
|
||||
if (getUnlockedHomeBgmList().add(homeBgmId)) return false;
|
||||
if (!getUnlockedHomeBgmList().add(homeBgmId)) return false;
|
||||
|
||||
var player = this.getPlayer();
|
||||
player.sendPacket(new PacketUnlockHomeBgmNotify(homeBgmId));
|
||||
@ -102,20 +105,22 @@ public class GameHome {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<Integer> getUnlockedHomeBgmListInfo() {
|
||||
public Set<Integer> getUnlockedHomeBgmList() {
|
||||
if (this.unlockedHomeBgmList == null) {
|
||||
this.unlockedHomeBgmList = new HashSet<>();
|
||||
addAllDefaultUnlockedBgmIds(this.unlockedHomeBgmList);
|
||||
}
|
||||
|
||||
if (this.unlockedHomeBgmList.addAll(getDefaultUnlockedHomeBgmIds())) {
|
||||
save();
|
||||
}
|
||||
|
||||
return this.unlockedHomeBgmList;
|
||||
}
|
||||
|
||||
private void addAllDefaultUnlockedBgmIds(Set<Integer> list) {
|
||||
GameData.getHomeWorldBgmDataMap().forEach((id, data) -> {
|
||||
if (data.isDefaultUnlock())
|
||||
list.add(id);
|
||||
});
|
||||
private Set<Integer> getDefaultUnlockedHomeBgmIds() {
|
||||
return GameData.getHomeWorldBgmDataMap().int2ObjectEntrySet().stream()
|
||||
.filter(e -> e.getValue().isDefaultUnlock())
|
||||
.map(Int2ObjectMap.Entry::getIntKey)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,14 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
|
||||
List<GameItem> changedItems = new ArrayList<>();
|
||||
for (var item : items) {
|
||||
if (item.getItemId() == 0) continue;
|
||||
GameItem result = putItem(item);
|
||||
GameItem result = null;
|
||||
try {
|
||||
// putItem might throws exception
|
||||
// ignore that exception and continue
|
||||
result = putItem(item);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (result != null) {
|
||||
getPlayer().getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_OBTAIN_MATERIAL_NUM, result.getItemId(), result.getCount());
|
||||
changedItems.add(result);
|
||||
@ -174,6 +181,7 @@ public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
|
||||
|
||||
if (data.isUseOnGain()) {
|
||||
var params = new UseItemParams(this.player, data.getUseTarget());
|
||||
params.usedItemId = data.getId();
|
||||
this.player.getServer().getInventorySystem().useItemDirect(data, params);
|
||||
return null;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ public class Player {
|
||||
|
||||
public Account getAccount() {
|
||||
if (this.account == null)
|
||||
this.account = DatabaseHelper.getAccountById(Integer.toString(this.id));
|
||||
this.account = DatabaseHelper.getAccountById(this.accountId);
|
||||
return this.account;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package emu.grasscutter.game.player;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -15,11 +15,8 @@ import emu.grasscutter.server.packet.send.PacketServerBuffChangeNotify;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public class PlayerBuffManager extends BasePlayerManager {
|
||||
private int nextBuffUid;
|
||||
|
||||
@ -29,7 +26,7 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
public PlayerBuffManager(Player player) {
|
||||
super(player);
|
||||
this.buffs = new Int2ObjectOpenHashMap<>();
|
||||
this.pendingBuffs = new LinkedList<>();
|
||||
this.pendingBuffs = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,7 +43,7 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
* @return True if a buff with this group id exists
|
||||
*/
|
||||
public synchronized boolean hasBuff(int groupId) {
|
||||
return this.getBuffs().containsKey(groupId);
|
||||
return this.buffs.containsKey(groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,11 +52,11 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
public synchronized void clearBuffs() {
|
||||
// Remove from player
|
||||
getPlayer().sendPacket(
|
||||
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, getBuffs().values())
|
||||
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.buffs.values())
|
||||
);
|
||||
|
||||
// Clear
|
||||
getBuffs().clear();
|
||||
this.buffs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,13 +130,11 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
}
|
||||
|
||||
// Clear previous buff if it exists
|
||||
if (this.hasBuff(buffData.getGroupId())) {
|
||||
this.removeBuff(buffData.getGroupId());
|
||||
}
|
||||
this.removeBuff(buffData.getGroupId());
|
||||
|
||||
// Create and store buff
|
||||
PlayerBuff buff = new PlayerBuff(getNextBuffUid(), buffData, duration);
|
||||
getBuffs().put(buff.getGroupId(), buff);
|
||||
this.buffs.put(buff.getGroupId(), buff);
|
||||
|
||||
// Packet
|
||||
getPlayer().sendPacket(new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_ADD_SERVER_BUFF, buff));
|
||||
@ -153,7 +148,7 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
* @return True if a buff was remove
|
||||
*/
|
||||
public synchronized boolean removeBuff(int buffGroupId) {
|
||||
PlayerBuff buff = this.getBuffs().get(buffGroupId);
|
||||
PlayerBuff buff = this.buffs.remove(buffGroupId);
|
||||
|
||||
if (buff != null) {
|
||||
getPlayer().sendPacket(
|
||||
@ -167,28 +162,24 @@ public class PlayerBuffManager extends BasePlayerManager {
|
||||
|
||||
public synchronized void onTick() {
|
||||
// Skip if no buffs
|
||||
if (getBuffs().size() == 0) return;
|
||||
if (this.buffs.isEmpty()) return;
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
// Add to pending buffs to remove if buff has expired
|
||||
for (PlayerBuff buff : getBuffs().values()) {
|
||||
if (currentTime > buff.getEndTime()) {
|
||||
this.getPendingBuffs().add(buff);
|
||||
}
|
||||
}
|
||||
this.buffs.values().removeIf(buff -> {
|
||||
if (currentTime <= buff.getEndTime())
|
||||
return false;
|
||||
this.pendingBuffs.add(buff);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (this.getPendingBuffs().size() > 0) {
|
||||
if (this.pendingBuffs.size() > 0) {
|
||||
// Send packet
|
||||
getPlayer().sendPacket(
|
||||
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.pendingBuffs)
|
||||
);
|
||||
|
||||
// Remove buff from player buff map
|
||||
for (PlayerBuff buff : this.getPendingBuffs()) {
|
||||
getBuffs().remove(buff.getGroupId());
|
||||
}
|
||||
this.getPendingBuffs().clear();
|
||||
this.pendingBuffs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.util.Map.entry;
|
||||
|
||||
@ -12,133 +13,134 @@ import java.util.stream.Stream;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum FightProperty {
|
||||
FIGHT_PROP_NONE(0),
|
||||
FIGHT_PROP_BASE_HP(1),
|
||||
FIGHT_PROP_HP(2),
|
||||
FIGHT_PROP_HP_PERCENT(3),
|
||||
FIGHT_PROP_BASE_ATTACK(4),
|
||||
FIGHT_PROP_ATTACK(5),
|
||||
FIGHT_PROP_ATTACK_PERCENT(6),
|
||||
FIGHT_PROP_BASE_DEFENSE(7),
|
||||
FIGHT_PROP_DEFENSE(8),
|
||||
FIGHT_PROP_DEFENSE_PERCENT(9),
|
||||
FIGHT_PROP_BASE_SPEED(10),
|
||||
FIGHT_PROP_SPEED_PERCENT(11),
|
||||
FIGHT_PROP_HP_MP_PERCENT(12),
|
||||
FIGHT_PROP_ATTACK_MP_PERCENT(13),
|
||||
FIGHT_PROP_CRITICAL(20),
|
||||
FIGHT_PROP_ANTI_CRITICAL(21),
|
||||
FIGHT_PROP_CRITICAL_HURT(22),
|
||||
FIGHT_PROP_CHARGE_EFFICIENCY(23),
|
||||
FIGHT_PROP_ADD_HURT(24),
|
||||
FIGHT_PROP_SUB_HURT(25),
|
||||
FIGHT_PROP_HEAL_ADD(26),
|
||||
FIGHT_PROP_HEALED_ADD(27),
|
||||
FIGHT_PROP_ELEMENT_MASTERY(28),
|
||||
FIGHT_PROP_PHYSICAL_SUB_HURT(29),
|
||||
FIGHT_PROP_PHYSICAL_ADD_HURT(30),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_RATIO(31),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_DELTA(32),
|
||||
FIGHT_PROP_FIRE_ADD_HURT(40),
|
||||
FIGHT_PROP_ELEC_ADD_HURT(41),
|
||||
FIGHT_PROP_WATER_ADD_HURT(42),
|
||||
FIGHT_PROP_GRASS_ADD_HURT(43),
|
||||
FIGHT_PROP_WIND_ADD_HURT(44),
|
||||
FIGHT_PROP_ROCK_ADD_HURT(45),
|
||||
FIGHT_PROP_ICE_ADD_HURT(46),
|
||||
FIGHT_PROP_HIT_HEAD_ADD_HURT(47),
|
||||
FIGHT_PROP_FIRE_SUB_HURT(50),
|
||||
FIGHT_PROP_ELEC_SUB_HURT(51),
|
||||
FIGHT_PROP_WATER_SUB_HURT(52),
|
||||
FIGHT_PROP_GRASS_SUB_HURT(53),
|
||||
FIGHT_PROP_WIND_SUB_HURT(54),
|
||||
FIGHT_PROP_ROCK_SUB_HURT(55),
|
||||
FIGHT_PROP_ICE_SUB_HURT(56),
|
||||
FIGHT_PROP_EFFECT_HIT(60),
|
||||
FIGHT_PROP_EFFECT_RESIST(61),
|
||||
FIGHT_PROP_FREEZE_RESIST(62),
|
||||
FIGHT_PROP_TORPOR_RESIST(63),
|
||||
FIGHT_PROP_DIZZY_RESIST(64),
|
||||
FIGHT_PROP_FREEZE_SHORTEN(65),
|
||||
FIGHT_PROP_TORPOR_SHORTEN(66),
|
||||
FIGHT_PROP_DIZZY_SHORTEN(67),
|
||||
FIGHT_PROP_MAX_FIRE_ENERGY(70),
|
||||
FIGHT_PROP_MAX_ELEC_ENERGY(71),
|
||||
FIGHT_PROP_MAX_WATER_ENERGY(72),
|
||||
FIGHT_PROP_MAX_GRASS_ENERGY(73),
|
||||
FIGHT_PROP_MAX_WIND_ENERGY(74),
|
||||
FIGHT_PROP_MAX_ICE_ENERGY(75),
|
||||
FIGHT_PROP_MAX_ROCK_ENERGY(76),
|
||||
FIGHT_PROP_SKILL_CD_MINUS_RATIO(80),
|
||||
FIGHT_PROP_SHIELD_COST_MINUS_RATIO(81),
|
||||
FIGHT_PROP_CUR_FIRE_ENERGY(1000),
|
||||
FIGHT_PROP_CUR_ELEC_ENERGY(1001),
|
||||
FIGHT_PROP_CUR_WATER_ENERGY(1002),
|
||||
FIGHT_PROP_CUR_GRASS_ENERGY(1003),
|
||||
FIGHT_PROP_CUR_WIND_ENERGY(1004),
|
||||
FIGHT_PROP_CUR_ICE_ENERGY(1005),
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY(1006),
|
||||
FIGHT_PROP_CUR_HP(1010),
|
||||
FIGHT_PROP_MAX_HP(2000),
|
||||
FIGHT_PROP_CUR_ATTACK(2001),
|
||||
FIGHT_PROP_CUR_DEFENSE(2002),
|
||||
FIGHT_PROP_CUR_SPEED(2003),
|
||||
FIGHT_PROP_NONEXTRA_ATTACK(3000),
|
||||
FIGHT_PROP_NONEXTRA_DEFENSE(3001),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL(3002),
|
||||
FIGHT_PROP_NONEXTRA_ANTI_CRITICAL(3003),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL_HURT(3004),
|
||||
FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY(3005),
|
||||
FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY(3006),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT(3007),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT(3008),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT(3009),
|
||||
FIGHT_PROP_NONEXTRA_WATER_ADD_HURT(3010),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT(3011),
|
||||
FIGHT_PROP_NONEXTRA_WIND_ADD_HURT(3012),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT(3013),
|
||||
FIGHT_PROP_NONEXTRA_ICE_ADD_HURT(3014),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT(3015),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT(3016),
|
||||
FIGHT_PROP_NONEXTRA_WATER_SUB_HURT(3017),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT(3018),
|
||||
FIGHT_PROP_NONEXTRA_WIND_SUB_HURT(3019),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT(3020),
|
||||
FIGHT_PROP_NONEXTRA_ICE_SUB_HURT(3021),
|
||||
FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO(3022),
|
||||
FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO(3023),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT(3024);
|
||||
|
||||
private final int id;
|
||||
private static final Int2ObjectMap<FightProperty> map = new Int2ObjectOpenHashMap<>();
|
||||
private static final Map<String, FightProperty> stringMap = new HashMap<>();
|
||||
|
||||
public static final int[] fightProps = new int[] {1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 55, 56, 2000, 2001, 2002, 2003, 1010};
|
||||
|
||||
static {
|
||||
Stream.of(values()).forEach(e -> {
|
||||
map.put(e.getId(), e);
|
||||
stringMap.put(e.name(), e);
|
||||
});
|
||||
}
|
||||
|
||||
private FightProperty(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
FIGHT_PROP_NONE(0),
|
||||
FIGHT_PROP_BASE_HP(1),
|
||||
FIGHT_PROP_HP(2),
|
||||
FIGHT_PROP_HP_PERCENT(3),
|
||||
FIGHT_PROP_BASE_ATTACK(4),
|
||||
FIGHT_PROP_ATTACK(5),
|
||||
FIGHT_PROP_ATTACK_PERCENT(6),
|
||||
FIGHT_PROP_BASE_DEFENSE(7),
|
||||
FIGHT_PROP_DEFENSE(8),
|
||||
FIGHT_PROP_DEFENSE_PERCENT(9),
|
||||
FIGHT_PROP_BASE_SPEED(10),
|
||||
FIGHT_PROP_SPEED_PERCENT(11),
|
||||
FIGHT_PROP_HP_MP_PERCENT(12),
|
||||
FIGHT_PROP_ATTACK_MP_PERCENT(13),
|
||||
FIGHT_PROP_CRITICAL(20),
|
||||
FIGHT_PROP_ANTI_CRITICAL(21),
|
||||
FIGHT_PROP_CRITICAL_HURT(22),
|
||||
FIGHT_PROP_CHARGE_EFFICIENCY(23),
|
||||
FIGHT_PROP_ADD_HURT(24),
|
||||
FIGHT_PROP_SUB_HURT(25),
|
||||
FIGHT_PROP_HEAL_ADD(26),
|
||||
FIGHT_PROP_HEALED_ADD(27),
|
||||
FIGHT_PROP_ELEMENT_MASTERY(28),
|
||||
FIGHT_PROP_PHYSICAL_SUB_HURT(29),
|
||||
FIGHT_PROP_PHYSICAL_ADD_HURT(30),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_RATIO(31),
|
||||
FIGHT_PROP_DEFENCE_IGNORE_DELTA(32),
|
||||
FIGHT_PROP_FIRE_ADD_HURT(40),
|
||||
FIGHT_PROP_ELEC_ADD_HURT(41),
|
||||
FIGHT_PROP_WATER_ADD_HURT(42),
|
||||
FIGHT_PROP_GRASS_ADD_HURT(43),
|
||||
FIGHT_PROP_WIND_ADD_HURT(44),
|
||||
FIGHT_PROP_ROCK_ADD_HURT(45),
|
||||
FIGHT_PROP_ICE_ADD_HURT(46),
|
||||
FIGHT_PROP_HIT_HEAD_ADD_HURT(47),
|
||||
FIGHT_PROP_FIRE_SUB_HURT(50),
|
||||
FIGHT_PROP_ELEC_SUB_HURT(51),
|
||||
FIGHT_PROP_WATER_SUB_HURT(52),
|
||||
FIGHT_PROP_GRASS_SUB_HURT(53),
|
||||
FIGHT_PROP_WIND_SUB_HURT(54),
|
||||
FIGHT_PROP_ROCK_SUB_HURT(55),
|
||||
FIGHT_PROP_ICE_SUB_HURT(56),
|
||||
FIGHT_PROP_EFFECT_HIT(60),
|
||||
FIGHT_PROP_EFFECT_RESIST(61),
|
||||
FIGHT_PROP_FREEZE_RESIST(62),
|
||||
FIGHT_PROP_TORPOR_RESIST(63),
|
||||
FIGHT_PROP_DIZZY_RESIST(64),
|
||||
FIGHT_PROP_FREEZE_SHORTEN(65),
|
||||
FIGHT_PROP_TORPOR_SHORTEN(66),
|
||||
FIGHT_PROP_DIZZY_SHORTEN(67),
|
||||
FIGHT_PROP_MAX_FIRE_ENERGY(70),
|
||||
FIGHT_PROP_MAX_ELEC_ENERGY(71),
|
||||
FIGHT_PROP_MAX_WATER_ENERGY(72),
|
||||
FIGHT_PROP_MAX_GRASS_ENERGY(73),
|
||||
FIGHT_PROP_MAX_WIND_ENERGY(74),
|
||||
FIGHT_PROP_MAX_ICE_ENERGY(75),
|
||||
FIGHT_PROP_MAX_ROCK_ENERGY(76),
|
||||
FIGHT_PROP_SKILL_CD_MINUS_RATIO(80),
|
||||
FIGHT_PROP_SHIELD_COST_MINUS_RATIO(81),
|
||||
FIGHT_PROP_CUR_FIRE_ENERGY(1000),
|
||||
FIGHT_PROP_CUR_ELEC_ENERGY(1001),
|
||||
FIGHT_PROP_CUR_WATER_ENERGY(1002),
|
||||
FIGHT_PROP_CUR_GRASS_ENERGY(1003),
|
||||
FIGHT_PROP_CUR_WIND_ENERGY(1004),
|
||||
FIGHT_PROP_CUR_ICE_ENERGY(1005),
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY(1006),
|
||||
FIGHT_PROP_CUR_HP(1010),
|
||||
FIGHT_PROP_MAX_HP(2000),
|
||||
FIGHT_PROP_CUR_ATTACK(2001),
|
||||
FIGHT_PROP_CUR_DEFENSE(2002),
|
||||
FIGHT_PROP_CUR_SPEED(2003),
|
||||
FIGHT_PROP_NONEXTRA_ATTACK(3000),
|
||||
FIGHT_PROP_NONEXTRA_DEFENSE(3001),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL(3002),
|
||||
FIGHT_PROP_NONEXTRA_ANTI_CRITICAL(3003),
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL_HURT(3004),
|
||||
FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY(3005),
|
||||
FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY(3006),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT(3007),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT(3008),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT(3009),
|
||||
FIGHT_PROP_NONEXTRA_WATER_ADD_HURT(3010),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT(3011),
|
||||
FIGHT_PROP_NONEXTRA_WIND_ADD_HURT(3012),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT(3013),
|
||||
FIGHT_PROP_NONEXTRA_ICE_ADD_HURT(3014),
|
||||
FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT(3015),
|
||||
FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT(3016),
|
||||
FIGHT_PROP_NONEXTRA_WATER_SUB_HURT(3017),
|
||||
FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT(3018),
|
||||
FIGHT_PROP_NONEXTRA_WIND_SUB_HURT(3019),
|
||||
FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT(3020),
|
||||
FIGHT_PROP_NONEXTRA_ICE_SUB_HURT(3021),
|
||||
FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO(3022),
|
||||
FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO(3023),
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT(3024);
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static FightProperty getPropById(int value) {
|
||||
return map.getOrDefault(value, FIGHT_PROP_NONE);
|
||||
}
|
||||
|
||||
public static FightProperty getPropByName(String name) {
|
||||
return stringMap.getOrDefault(name, FIGHT_PROP_NONE);
|
||||
}
|
||||
private final int id;
|
||||
private static final Int2ObjectMap<FightProperty> map = new Int2ObjectOpenHashMap<>();
|
||||
private static final Map<String, FightProperty> stringMap = new HashMap<>();
|
||||
|
||||
public static final int[] fightProps = new int[] {1, 4, 7, 20, 21, 22, 23, 26, 27, 28, 29, 30, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 55, 56, 2000, 2001, 2002, 2003, 1010};
|
||||
|
||||
static {
|
||||
Stream.of(values()).forEach(e -> {
|
||||
map.put(e.getId(), e);
|
||||
stringMap.put(e.name(), e);
|
||||
});
|
||||
}
|
||||
|
||||
private FightProperty(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static FightProperty getPropById(int value) {
|
||||
return map.getOrDefault(value, FIGHT_PROP_NONE);
|
||||
}
|
||||
|
||||
public static FightProperty getPropByName(String name) {
|
||||
return stringMap.getOrDefault(name, FIGHT_PROP_NONE);
|
||||
}
|
||||
|
||||
public static FightProperty getPropByShortName(String name) {
|
||||
return shortNameMap.getOrDefault(name, FIGHT_PROP_NONE);
|
||||
@ -151,28 +153,28 @@ public enum FightProperty {
|
||||
// This was originally for relic properties so some names might not be applicable for e.g. setstats
|
||||
private static final Map<String, FightProperty> shortNameMap = Map.ofEntries(
|
||||
// Normal relic stats
|
||||
entry("hp", FIGHT_PROP_HP),
|
||||
entry("atk", FIGHT_PROP_ATTACK),
|
||||
entry("def", FIGHT_PROP_DEFENSE),
|
||||
entry("hp%", FIGHT_PROP_HP_PERCENT),
|
||||
entry("atk%", FIGHT_PROP_ATTACK_PERCENT),
|
||||
entry("def%", FIGHT_PROP_DEFENSE_PERCENT),
|
||||
entry("em", FIGHT_PROP_ELEMENT_MASTERY),
|
||||
entry("er", FIGHT_PROP_CHARGE_EFFICIENCY),
|
||||
entry("hb", FIGHT_PROP_HEAL_ADD),
|
||||
entry("hp", FIGHT_PROP_HP),
|
||||
entry("atk", FIGHT_PROP_ATTACK),
|
||||
entry("def", FIGHT_PROP_DEFENSE),
|
||||
entry("hp%", FIGHT_PROP_HP_PERCENT),
|
||||
entry("atk%", FIGHT_PROP_ATTACK_PERCENT),
|
||||
entry("def%", FIGHT_PROP_DEFENSE_PERCENT),
|
||||
entry("em", FIGHT_PROP_ELEMENT_MASTERY),
|
||||
entry("er", FIGHT_PROP_CHARGE_EFFICIENCY),
|
||||
entry("hb", FIGHT_PROP_HEAL_ADD),
|
||||
entry("heal", FIGHT_PROP_HEAL_ADD),
|
||||
entry("cd", FIGHT_PROP_CRITICAL_HURT),
|
||||
entry("cdmg", FIGHT_PROP_CRITICAL_HURT),
|
||||
entry("cr", FIGHT_PROP_CRITICAL),
|
||||
entry("crate", FIGHT_PROP_CRITICAL),
|
||||
entry("phys%", FIGHT_PROP_PHYSICAL_ADD_HURT),
|
||||
entry("dendro%", FIGHT_PROP_GRASS_ADD_HURT),
|
||||
entry("geo%", FIGHT_PROP_ROCK_ADD_HURT),
|
||||
entry("anemo%", FIGHT_PROP_WIND_ADD_HURT),
|
||||
entry("hydro%", FIGHT_PROP_WATER_ADD_HURT),
|
||||
entry("cryo%", FIGHT_PROP_ICE_ADD_HURT),
|
||||
entry("electro%", FIGHT_PROP_ELEC_ADD_HURT),
|
||||
entry("pyro%", FIGHT_PROP_FIRE_ADD_HURT),
|
||||
entry("cd", FIGHT_PROP_CRITICAL_HURT),
|
||||
entry("cdmg", FIGHT_PROP_CRITICAL_HURT),
|
||||
entry("cr", FIGHT_PROP_CRITICAL),
|
||||
entry("crate", FIGHT_PROP_CRITICAL),
|
||||
entry("phys%", FIGHT_PROP_PHYSICAL_ADD_HURT),
|
||||
entry("dendro%", FIGHT_PROP_GRASS_ADD_HURT),
|
||||
entry("geo%", FIGHT_PROP_ROCK_ADD_HURT),
|
||||
entry("anemo%", FIGHT_PROP_WIND_ADD_HURT),
|
||||
entry("hydro%", FIGHT_PROP_WATER_ADD_HURT),
|
||||
entry("cryo%", FIGHT_PROP_ICE_ADD_HURT),
|
||||
entry("electro%", FIGHT_PROP_ELEC_ADD_HURT),
|
||||
entry("pyro%", FIGHT_PROP_FIRE_ADD_HURT),
|
||||
// Other stats
|
||||
entry("maxhp", FIGHT_PROP_MAX_HP),
|
||||
entry("dmg", FIGHT_PROP_ADD_HURT), // This seems to get reset after attacks
|
||||
@ -189,14 +191,43 @@ public enum FightProperty {
|
||||
entry("reshydro", FIGHT_PROP_WATER_SUB_HURT),
|
||||
entry("respyro", FIGHT_PROP_FIRE_SUB_HURT),
|
||||
entry("resphys", FIGHT_PROP_PHYSICAL_SUB_HURT)
|
||||
);
|
||||
);
|
||||
|
||||
private static final List<FightProperty> flatProps = Arrays.asList(
|
||||
FIGHT_PROP_BASE_HP, FIGHT_PROP_HP, FIGHT_PROP_BASE_ATTACK, FIGHT_PROP_ATTACK, FIGHT_PROP_BASE_DEFENSE,
|
||||
FIGHT_PROP_DEFENSE, FIGHT_PROP_HEALED_ADD, FIGHT_PROP_CUR_FIRE_ENERGY, FIGHT_PROP_CUR_ELEC_ENERGY,
|
||||
FIGHT_PROP_CUR_WATER_ENERGY, FIGHT_PROP_CUR_GRASS_ENERGY, FIGHT_PROP_CUR_WIND_ENERGY, FIGHT_PROP_CUR_ICE_ENERGY,
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY, FIGHT_PROP_CUR_HP, FIGHT_PROP_MAX_HP, FIGHT_PROP_CUR_ATTACK, FIGHT_PROP_CUR_DEFENSE);
|
||||
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY, FIGHT_PROP_CUR_HP, FIGHT_PROP_MAX_HP, FIGHT_PROP_CUR_ATTACK, FIGHT_PROP_CUR_DEFENSE);
|
||||
|
||||
@Getter
|
||||
public static class CompoundProperty {
|
||||
private FightProperty result;
|
||||
private FightProperty base;
|
||||
private FightProperty percent;
|
||||
private FightProperty flat;
|
||||
|
||||
public CompoundProperty(FightProperty result, FightProperty base, FightProperty percent, FightProperty flat) {
|
||||
this.result = result;
|
||||
this.base = base;
|
||||
this.percent = percent;
|
||||
this.flat = flat;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<FightProperty, CompoundProperty> compoundProperties = Map.ofEntries(
|
||||
entry(FIGHT_PROP_MAX_HP, new CompoundProperty(FIGHT_PROP_MAX_HP, FIGHT_PROP_BASE_HP, FIGHT_PROP_HP_PERCENT, FIGHT_PROP_HP)),
|
||||
entry(FIGHT_PROP_CUR_ATTACK, new CompoundProperty(FIGHT_PROP_CUR_ATTACK, FIGHT_PROP_BASE_ATTACK, FIGHT_PROP_ATTACK_PERCENT, FIGHT_PROP_ATTACK)),
|
||||
entry(FIGHT_PROP_CUR_DEFENSE, new CompoundProperty(FIGHT_PROP_CUR_DEFENSE, FIGHT_PROP_BASE_DEFENSE, FIGHT_PROP_DEFENSE_PERCENT, FIGHT_PROP_DEFENSE))
|
||||
);
|
||||
|
||||
public static CompoundProperty getCompoundProperty(FightProperty result) {
|
||||
return compoundProperties.get(result);
|
||||
}
|
||||
|
||||
public static void forEachCompoundProperty(Consumer<CompoundProperty> consumer) {
|
||||
compoundProperties.values().forEach(consumer);
|
||||
}
|
||||
|
||||
public static boolean isPercentage(FightProperty prop) {
|
||||
return !flatProps.contains(prop);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class ItemUseAction {
|
||||
case ITEM_USE_GAIN_AVATAR -> new ItemUseGainAvatar(useParam);
|
||||
case ITEM_USE_GAIN_COSTUME -> new ItemUseGainCostume(useParam); // TODO - real success/fail
|
||||
case ITEM_USE_GAIN_FLYCLOAK -> new ItemUseGainFlycloak(useParam); // TODO - real success/fail
|
||||
case ITEM_USE_GAIN_NAME_CARD -> new ItemUseGainNameCard(useParam); // TODO
|
||||
case ITEM_USE_GAIN_NAME_CARD -> new ItemUseGainNameCard(useParam);
|
||||
case ITEM_USE_CHEST_SELECT_ITEM -> new ItemUseChestSelectItem(useParam);
|
||||
case ITEM_USE_ADD_SELECT_ITEM -> new ItemUseAddSelectItem(useParam);
|
||||
case ITEM_USE_GRANT_SELECT_REWARD -> new ItemUseGrantSelectReward(useParam);
|
||||
|
@ -2,6 +2,8 @@ package emu.grasscutter.game.props.ItemUseAction;
|
||||
|
||||
import emu.grasscutter.game.props.ItemUseOp;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
|
||||
public class ItemUseGainCostume extends ItemUseInt {
|
||||
@Override
|
||||
public ItemUseOp getItemUseOp() {
|
||||
@ -14,7 +16,9 @@ public class ItemUseGainCostume extends ItemUseInt {
|
||||
|
||||
@Override
|
||||
public boolean useItem(UseItemParams params) {
|
||||
params.player.getInventory().addItem(this.i); // TODO: Currently this returns false for all virtual items - need to have a proper success/fail
|
||||
if (GameData.getAvatarCostumeDataMap().containsKey(this.i)) {
|
||||
params.player.addCostume(this.i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package emu.grasscutter.game.props.ItemUseAction;
|
||||
|
||||
import emu.grasscutter.game.props.ItemUseOp;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
|
||||
public class ItemUseGainFlycloak extends ItemUseInt {
|
||||
@Override
|
||||
public ItemUseOp getItemUseOp() {
|
||||
@ -14,7 +16,9 @@ public class ItemUseGainFlycloak extends ItemUseInt {
|
||||
|
||||
@Override
|
||||
public boolean useItem(UseItemParams params) {
|
||||
params.player.getInventory().addItem(this.i); // TODO: Currently this returns false for all virtual items - need to have a proper success/fail
|
||||
if (GameData.getAvatarFlycloakDataMap().containsKey(this.i)) {
|
||||
params.player.addFlycloak(this.i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ public class ItemUseGainNameCard extends ItemUseAction {
|
||||
|
||||
@Override
|
||||
public boolean useItem(UseItemParams params) {
|
||||
return false; // TODO: work out if this is actually used and how to get the namecard id
|
||||
params.player.addNameCard(params.usedItemId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,13 @@ public class ItemUseOpenRandomChest extends ItemUseInt {
|
||||
|
||||
@Override
|
||||
public boolean useItem(UseItemParams params) { // cash shop material bundles
|
||||
var rewardItems = params.player.getServer().getShopSystem().getShopChestData(this.i).stream().map(GameItem::new).toList();
|
||||
var data = params.player.getServer().getShopSystem().getShopChestData(this.i);
|
||||
if (data == null)
|
||||
return false;
|
||||
var rewardItems = data.stream().map(GameItem::new).toList();
|
||||
if (!rewardItems.isEmpty()) {
|
||||
params.player.getInventory().addItems(rewardItems, ActionReason.Shop);
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ public class UseItemParams {
|
||||
public int count = 1;
|
||||
public int optionId = 0;
|
||||
public boolean isEnterMpDungeonTeam = false;
|
||||
public int usedItemId = 0;
|
||||
|
||||
public UseItemParams(Player player, ItemUseTarget itemUseTarget, Avatar targetAvatar, int count, int optionId, boolean isEnterMpDungeonTeam) {
|
||||
this.player = player;
|
||||
|
@ -167,7 +167,7 @@ public class GameMainQuest {
|
||||
boolean didRewind = false;
|
||||
for (GameQuest quest : sortedByOrder) {
|
||||
int i = sortedByOrder.indexOf(quest);
|
||||
if ( i == sortedByOrder.size()) {
|
||||
if ( (i+1) >= sortedByOrder.size()) {
|
||||
didRewind = quest.rewind(null);
|
||||
} else {
|
||||
didRewind = quest.rewind(sortedByOrder.get(i+1));
|
||||
|
@ -54,7 +54,7 @@ public class QuestSystem extends BaseGameSystem {
|
||||
return;
|
||||
}
|
||||
|
||||
map.put(opcode.value().getValue(), handlerClass.newInstance());
|
||||
map.put(opcode.value().getValue(), handlerClass.getDeclaredConstructor().newInstance());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -743,6 +743,7 @@ public class InventorySystem extends BaseGameSystem {
|
||||
if (itemData == null) return null;
|
||||
|
||||
var params = new UseItemParams(player, itemData.getUseTarget(), target, count, optionId, isEnterMpDungeonTeam);
|
||||
params.usedItemId = item.getItemId();
|
||||
if (useItemDirect(itemData, params)) {
|
||||
player.getInventory().removeItem(item, count);
|
||||
var actions = itemData.getItemUseActions();
|
||||
@ -778,7 +779,7 @@ public class InventorySystem extends BaseGameSystem {
|
||||
}
|
||||
|
||||
int[] satiationParams = itemData.getSatiationParams();
|
||||
if (satiationParams != null && target.isPresent()) {
|
||||
if (satiationParams != null && satiationParams.length > 0 && target.isPresent()) {
|
||||
// Invoke and call player use food event.
|
||||
var event = new PlayerUseFoodEvent(params.player, itemData, params.targetAvatar.getAsEntity()); event.call();
|
||||
if (event.isCanceled()) return false;
|
||||
|
@ -274,15 +274,8 @@ public class Scene {
|
||||
}
|
||||
|
||||
public void showOtherEntities(Player player) {
|
||||
List<GameEntity> entities = new LinkedList<>();
|
||||
GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity();
|
||||
|
||||
for (GameEntity entity : this.getEntities().values()) {
|
||||
if (entity == currentEntity) {
|
||||
continue;
|
||||
}
|
||||
entities.add(entity);
|
||||
}
|
||||
List<GameEntity> entities = this.getEntities().values().stream().filter(entity -> entity != currentEntity).toList();
|
||||
|
||||
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_TYPE_MEET));
|
||||
}
|
||||
@ -422,8 +415,8 @@ public class Scene {
|
||||
}
|
||||
|
||||
// Todo
|
||||
List<GameEntity> toAdd = new LinkedList<>();
|
||||
List<GameEntity> toRemove = new LinkedList<>();
|
||||
List<GameEntity> toAdd = new ArrayList<>();
|
||||
List<GameEntity> toRemove = new ArrayList<>();
|
||||
var spawnedEntities = this.getSpawnedEntities();
|
||||
for (SpawnDataEntry entry : visible) {
|
||||
// If spawn entry is in our view and hasnt been spawned/killed yet, we should spawn it
|
||||
|
@ -27,7 +27,8 @@ public class PacketOpcodesUtils {
|
||||
PacketOpcodes.PingRsp,
|
||||
PacketOpcodes.WorldPlayerRTTNotify,
|
||||
PacketOpcodes.UnionCmdNotify,
|
||||
PacketOpcodes.QueryPathReq
|
||||
PacketOpcodes.QueryPathReq,
|
||||
PacketOpcodes.QueryPathRsp
|
||||
);
|
||||
|
||||
static {
|
||||
|
@ -181,7 +181,7 @@ public final class PluginManager {
|
||||
// Add the plugin to the list of loaded plugins.
|
||||
this.plugins.put(identifier.name, plugin);
|
||||
// Create a collection for the plugin's listeners.
|
||||
this.listeners.put(plugin, new LinkedList<>());
|
||||
this.listeners.put(plugin, new ArrayList<>());
|
||||
|
||||
// Call the plugin's onLoad method.
|
||||
try {
|
||||
@ -242,18 +242,14 @@ public final class PluginManager {
|
||||
* @param priority The priority to call for.
|
||||
*/
|
||||
private void checkAndFilter(Event event, HandlerPriority priority) {
|
||||
// Create a collection of listeners.
|
||||
List<EventHandler<? extends Event>> listeners = new LinkedList<>();
|
||||
|
||||
// Add all listeners from every plugin.
|
||||
this.listeners.values().forEach(listeners::addAll);
|
||||
|
||||
listeners.stream()
|
||||
this.listeners.values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
// Filter the listeners by priority.
|
||||
.filter(handler -> handler.handles().isInstance(event))
|
||||
.filter(handler -> handler.getPriority() == priority)
|
||||
// Invoke the event.
|
||||
.toList().forEach(handler -> this.invokeHandler(event, handler));
|
||||
.forEach(handler -> this.invokeHandler(event, handler));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,8 +11,9 @@ import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.server.http.HttpServer;
|
||||
import emu.grasscutter.server.http.Router;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Hooks into the {@link GameServer} class, adding convenient ways to do certain things.
|
||||
@ -60,8 +61,17 @@ public final class ServerHook {
|
||||
* Gets all online players.
|
||||
* @return Players connected to the server.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public List<Player> getOnlinePlayers() {
|
||||
return new LinkedList<>(this.gameServer.getPlayers().values());
|
||||
return new ArrayList<>(this.gameServer.getPlayers().values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all online players.
|
||||
* @return Players connected to the server.
|
||||
*/
|
||||
public Stream<Player> getOnlinePlayersStream() {
|
||||
return this.gameServer.getPlayers().values().stream();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,7 @@ public class SceneBlock {
|
||||
|
||||
// Set groups
|
||||
this.groups = ScriptLoader.getSerializer().toList(SceneGroup.class, bindings.get("groups")).stream()
|
||||
.collect(Collectors.toMap(x -> x.id, y -> y));
|
||||
.collect(Collectors.toMap(x -> x.id, y -> y, (a, b) -> a));
|
||||
|
||||
this.groups.values().forEach(g -> g.block_id = this.id);
|
||||
this.sceneGroupIndex = SceneIndexManager.buildIndex(3, this.groups.values(), g -> g.pos.toPoint());
|
||||
|
@ -96,20 +96,20 @@ public class SceneGroup {
|
||||
|
||||
// Set
|
||||
this.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, this.bindings.get("monsters")).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y));
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.monsters.values().forEach(m -> m.group = this);
|
||||
|
||||
this.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, this.bindings.get("gadgets")).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y));
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.gadgets.values().forEach(m -> m.group = this);
|
||||
|
||||
this.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, this.bindings.get("triggers")).stream()
|
||||
.collect(Collectors.toMap(x -> x.name, y -> y));
|
||||
.collect(Collectors.toMap(x -> x.name, y -> y, (a, b) -> a));
|
||||
this.triggers.values().forEach(t -> t.currentGroup = this);
|
||||
|
||||
this.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites"));
|
||||
this.regions = ScriptLoader.getSerializer().toList(SceneRegion.class, this.bindings.get("regions")).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y));
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.regions.values().forEach(m -> m.group = this);
|
||||
|
||||
this.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, this.bindings.get("init_config"));
|
||||
|
@ -60,7 +60,7 @@ public class SceneMeta {
|
||||
|
||||
}
|
||||
|
||||
this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b));
|
||||
this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b, (a, b) -> a));
|
||||
this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle);
|
||||
|
||||
} catch (ScriptException exception) {
|
||||
|
@ -99,7 +99,7 @@ public class GameServerPacketHandler {
|
||||
}
|
||||
|
||||
// Log unhandled packets
|
||||
if (GAME_INFO.logPackets == ServerDebugMode.MISSING) {
|
||||
if (GAME_INFO.logPackets == ServerDebugMode.MISSING || GAME_INFO.logPackets == ServerDebugMode.ALL) {
|
||||
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode));
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,8 @@ public class GameSession implements GameSessionManager.KcpChannel {
|
||||
|
||||
public void logPacket(String sendOrRecv, int opcode, byte[] payload) {
|
||||
Grasscutter.getLogger().info(sendOrRecv + ": " + PacketOpcodesUtils.getOpcodeName(opcode) + " (" + opcode + ")");
|
||||
System.out.println(Utils.bytesToHex(payload));
|
||||
if (GAME_INFO.isShowPacketPayload)
|
||||
System.out.println(Utils.bytesToHex(payload));
|
||||
}
|
||||
|
||||
public void send(BasePacket packet) {
|
||||
@ -122,7 +123,7 @@ public class GameSession implements GameSessionManager.KcpChannel {
|
||||
// Log
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode())) {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode()) || GAME_INFO.isShowLoopPackets) {
|
||||
logPacket("SEND", packet.getOpcode(), packet.getData());
|
||||
}
|
||||
}
|
||||
@ -154,7 +155,6 @@ public class GameSession implements GameSessionManager.KcpChannel {
|
||||
Grasscutter.getLogger().info(translate("messages.game.connect", this.getAddress().toString()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleReceive(byte[] bytes) {
|
||||
// Decrypt and turn back into a packet
|
||||
@ -200,7 +200,7 @@ public class GameSession implements GameSessionManager.KcpChannel {
|
||||
// Log packet
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode)) {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode) || GAME_INFO.isShowLoopPackets) {
|
||||
logPacket("RECV", opcode, payload);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import static emu.grasscutter.config.Configuration.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Handles requests related to the announcements page.
|
||||
@ -72,7 +73,17 @@ public final class AnnouncementsHandler implements Router {
|
||||
}
|
||||
|
||||
private static void getPageResources(Context ctx) {
|
||||
try (InputStream filestream = DataLoader.load(ctx.path())) {
|
||||
// Re-process the path - remove the first slash and prevent directory traversal
|
||||
// (the first slash will act as root path when resolving local path)
|
||||
String[] path = ctx.path().split("/");
|
||||
StringJoiner stringJoiner = new StringJoiner("/");
|
||||
for (String pathName : path) {
|
||||
// Filter the illegal payload to prevent directory traversal
|
||||
if (!pathName.isEmpty() && !pathName.equals("..") && !pathName.contains("\\")) {
|
||||
stringJoiner.add(pathName);
|
||||
}
|
||||
}
|
||||
try (InputStream filestream = DataLoader.load(stringJoiner.toString())) {
|
||||
String possibleFilename = ctx.path();
|
||||
|
||||
ContentType fromExtension = ContentType.getContentTypeByExtension(possibleFilename.substring(possibleFilename.lastIndexOf(".") + 1));
|
||||
|
@ -15,7 +15,6 @@ import io.javalin.http.Context;
|
||||
import io.javalin.http.staticfiles.Location;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@ -42,13 +41,6 @@ public final class GachaHandler implements Router {
|
||||
}
|
||||
|
||||
private static void gachaRecords(Context ctx) {
|
||||
File recordsTemplate = FileUtils.getDataPath("gacha/records.html").toFile();
|
||||
if (!recordsTemplate.exists()) {
|
||||
Grasscutter.getLogger().warn("File does not exist: " + recordsTemplate);
|
||||
ctx.status(500);
|
||||
return;
|
||||
}
|
||||
|
||||
String sessionKey = ctx.queryParam("s");
|
||||
Account account = DatabaseHelper.getAccountBySessionKey(sessionKey);
|
||||
if (account == null) {
|
||||
@ -70,7 +62,7 @@ public final class GachaHandler implements Router {
|
||||
String records = DatabaseHelper.getGachaRecords(player.getUid(), page, gachaType).toString();
|
||||
long maxPage = DatabaseHelper.getGachaRecordsMaxPage(player.getUid(), page, gachaType);
|
||||
|
||||
String template = new String(FileUtils.read(recordsTemplate), StandardCharsets.UTF_8)
|
||||
String template = new String(FileUtils.read(FileUtils.getDataPath("gacha/records.html")), StandardCharsets.UTF_8)
|
||||
.replace("{{REPLACE_RECORDS}}", records)
|
||||
.replace("{{REPLACE_MAXPAGE}}", String.valueOf(maxPage))
|
||||
.replace("{{TITLE}}", translate(player, "gacha.records.title"))
|
||||
|
@ -17,7 +17,6 @@ public class HandlerChangeHomeBgmReq extends PacketHandler {
|
||||
int homeBgmId = req.getUnk2700BJHAMKKECEI();
|
||||
var home = session.getPlayer().getHome();
|
||||
|
||||
home.addUnlockedHomeBgm(homeBgmId); // Not sure if this is sane
|
||||
home.getHomeSceneItem(session.getPlayer().getSceneId()).setHomeBgmId(homeBgmId);
|
||||
home.save();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user