4 Commits

Author SHA1 Message Date
f373827a83 Update README.md for clarity (#2543)
* Update README.md for clarity

Readme is now theoretically the ONE THING you send to somebody in need of help. 

Updated sections for more clarity on support with GC.

* Update README.md

grammar

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

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
2025-04-26 22:05:59 -04:00
74b8de36d3 Updated korean readme to match with latest changes on main english readme. (#2548) 2025-04-26 21:49:12 -04:00
9c36daa3fa Update code of conduct reference (#2535)
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
2024-11-23 12:26:50 -05:00
d340758614 Fix cannot stop in dispatch-only mode (#2534) 2024-11-18 23:05:24 -05:00
368 changed files with 3067 additions and 1831 deletions

View File

@ -1,11 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

View File

@ -20,9 +20,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: '17' java-version: '17'
@ -44,7 +44,7 @@ jobs:
- name: Run Gradle - name: Run Gradle
run: ./gradlew -PskipHandbook=1 && ./gradlew jar -PskipHandbook=1 run: ./gradlew -PskipHandbook=1 && ./gradlew jar -PskipHandbook=1
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Grasscutter name: Grasscutter
path: grasscutter-*.jar path: grasscutter-*.jar

View File

@ -18,6 +18,12 @@
* Spawning monsters via console * Spawning monsters via console
* Inventory features (receiving items/characters, upgrading items/characters, etc) * Inventory features (receiving items/characters, upgrading items/characters, etc)
## Foreward
### **Grasscutter beyond the latest release will have no handholding in terms of instructions.**
Grasscutter has not been actively maintained and currently (as of January 12th, 2025) only works up to version REL4.0.1 (introduction to Fontaine). If you have a beta version/unofficial version of Grasscutter, this guide should theoretically still work, however, we will not provide official support these versions. You can still try your luck in the Discord if you are stuck, but please don't act entitled.
## Quick setup guide ## Quick setup guide
**Note**: For support please join our [Discord](https://discord.gg/T5vZU6UyeG). **Note**: For support please join our [Discord](https://discord.gg/T5vZU6UyeG).
@ -29,6 +35,7 @@
- Get game version REL4.0.x (If you don't have a 4.0.x client, you can find it here and open any of the links to download it): - Get game version REL4.0.x (If you don't have a 4.0.x client, you can find it here and open any of the links to download it):
[4.0.x Client-github](https://github.com/JRSKelvin/GenshinRepository/blob/main/Version%204.0.0.md) [4.0.x Client-github](https://github.com/JRSKelvin/GenshinRepository/blob/main/Version%204.0.0.md)
[4.0.x Client-cloud drive](https://www.123pan.com/s/HoqUVv-U7SBA.html) [4.0.x Client-cloud drive](https://www.123pan.com/s/HoqUVv-U7SBA.html)
- ***UPDATE JAN 12, 2025: YOU CANNOT MIX AND MATCH GAME VERSIONS AND SERVER VERSIONS, PLEASE DOWNLOAD THE CORRECT VERSION OF GRASSCUTTER FOR YOUR VERSION OF THE GAME.***
- Download the [latest Cultivation version](https://github.com/Grasscutters/Cultivation/releases/latest). Use the `.msi` installer. - Download the [latest Cultivation version](https://github.com/Grasscutters/Cultivation/releases/latest). Use the `.msi` installer.
- After opening Cultivation (as admin), press the download button in the upper right corner. - After opening Cultivation (as admin), press the download button in the upper right corner.

View File

@ -82,7 +82,7 @@ dependencies {
// Line reading libraries. // Line reading libraries.
implementation group: 'org.jline', name: 'jline', version: '3.21.0' implementation group: 'org.jline', name: 'jline', version: '3.21.0'
implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.26.1' implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.21.0'
implementation group: 'net.java.dev.jna', name: 'jna', version: '5.10.0' implementation group: 'net.java.dev.jna', name: 'jna', version: '5.10.0'
// Java Netty for networking. // Java Netty for networking.
@ -96,7 +96,7 @@ dependencies {
implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.19.6' implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.19.6'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2'
implementation platform('com.fasterxml.jackson:jackson-bom:2.17.1') implementation platform('com.fasterxml.jackson:jackson-bom:2.14.0')
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2'
// Reflections libraries. // Reflections libraries.
@ -130,7 +130,7 @@ dependencies {
// Testing libraries. // Testing libraries.
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.8.2' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.8.2'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.8.2' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.8.2'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.2' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.2'
// HTTP client library for testing. // HTTP client library for testing.
testImplementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.10.0' testImplementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.10.0'
@ -261,7 +261,7 @@ clean {
protobuf { protobuf {
protoc { protoc {
// The artifact spec for the Protobuf Compiler // The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:4.27.1' artifact = 'com.google.protobuf:protoc:3.18.1'
} }
generatedFilesBaseDir = "$projectDir/src/generated/" generatedFilesBaseDir = "$projectDir/src/generated/"

View File

@ -5,7 +5,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) | [IT](README_it-IT.md) | [VI](README_vi-VN.md) | [हिंदी](README_hn-IN.md) [EN](../README.md) | [简中](README_zh-CN.md) | [繁中](README_zh-TW.md) | [FR](README_fr-FR.md) | [ES](README_es-ES.md) | [HE](README_HE.md) | [RU](README_ru-RU.md) | [PL](README_pl-PL.md) | [ID](README_id-ID.md) | [KR](README_ko-KR.md) | [FIL/PH](README_fil-PH.md) | [NL](README_NL.md) | [JP](README_ja-JP.md) | [IT](README_it-IT.md) | [VI](README_vi-VN.md) | [हिंदी](README_hn-IN.md)
**Aantekening:** We verwelkomen altijd bijdragers aan het project. Lees onze [Gedragscode](https://github.com/Grasscutters/Grasscutter/blob/development/README_NL.md#bijdragen-aan-het-project) zorgvuldig door voordat u uw bijdrage toevoegt. **Aantekening:** We verwelkomen altijd bijdragers aan het project. Lees onze [Gedragscode](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md) zorgvuldig door voordat u uw bijdrage toevoegt.
## Huidige functies ## Huidige functies

View File

@ -22,52 +22,25 @@
**각주 :** 도움이 필요할 경우 [Discord](https://discord.gg/T5vZU6UyeG)에 가입하세요. **각주 :** 도움이 필요할 경우 [Discord](https://discord.gg/T5vZU6UyeG)에 가입하세요.
### 설치에 필요한 것들 ### 빠른 설치 (자동)
* Java SE - 17 ([링크](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)) - [Java 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) 설치
- [MongoDB Community Server](https://www.mongodb.com/try/download/community) 설치
- 게임 버전 REL4.0.x 다운로드 (만약 4.0.x 클라이언트를 가지고 있지 않다면, 여기서 찾을 수 있습니다.):
[4.0.x 클라이언트 - GitHub](https://github.com/JRSKelvin/GenshinRepository/blob/main/Version%204.0.0.md)
[4.0.x 클라이언트 - 구글 드라이브브](https://www.123pan.com/s/HoqUVv-U7SBA.html)
**각주 :** **실행**만을 원한다면, **jre**만 있어도 괜찮습니다. - [최신 Cultivation](https://github.com/Grasscutters/Cultivation/releases/latest) 다운로드하세요. `.msi` 설치파일을 사용하면 됩니다.
- (관리자 권한으로) Cultivation을 실행한 후, 우측 상단에 위치한 다운로드 버튼을 클릭하세요.
- `올인원 다운로드`를 클릭하세요.
- 우측 상단에 위치한 톱니바퀴 버튼을 누르세요.
- 게임 설치 경로를 게임이 위치한 경로로 설정하세요.
- 사용자 지정 Java 경로 설정을 `C:\Program Files\Java\jdk-17\bin\java.exe`로 설정하세요.
- 다른 모든 설정은 기본값으로 두세요.
* [MongoDB](https://www.mongodb.com/try/download/community) (4.0 이상의 버전 추천) - 게임 시작 버튼 옆에 위치한 작은 버튼을 누르세요.
- 게임 시작 버튼을 누르세요.
* 프록시 데몬 : mitmproxy (mitmdump 추천), Fiddler Classic 등. - 원하는 사용자 이름으로 로그인하세요. 비밀번호는 무엇이든 가능합니다.
### 실행
**각주 :** 구버전에서 업데이트 했을 경우, `config.json` 파일을 재생성하기 위해 파일을 삭제하세요.
1. `grasscutter.jar` 얻기
- [Actions](https://github.com/Grasscutters/Grasscutter/suites/6895963598/artifacts/267483297) 탭에서 다운로드
- [직접 빌드하기](#빌드하기)
2. grasscutter.jar 파일이 위치한 폴더에 `resources` 폴더를 생성하고, `BinOutput``ExcelBinOutput` 폴더를 생성한 폴더 내로 옮기세요. *(이 파일들을 얻는 더 자세한 방법에 대해서는 [위키](https://github.com/Grasscutters/Grasscutter/wiki)를 참조하세요.)*
3. Grasscutter를 `java -jar grasscutter.jar` 명령어로 실행합니다. **MongoDB 서비스가 정상적으로 실행되고 있는지 확인하세요.**
### 클라이언트와의 연결
½. [서버 콘솔 명령어](https://github.com/Grasscutters/Grasscutter/wiki/Commands#targeting)를 이용해서 계정을 생성합니다.
1. 리다이렉트 트래픽 : (1가지 선택)
- mitmdump: `mitmdump -s proxy.py -k`
신뢰하는 인증 기관 인증서 (CA Cert) :
**각주 :** CA 인증서는 보통 `%USERPROFILE%\ .mitmproxy` 경로에 저장되며, `http://mitm.it`에서 다운로드 받을 수도 있습니다.
더블 클릭하여 [설치](https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate#installing-a-trusted-root-certificate) 또는 ...
- 명령어를 통해서
```shell
certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
```
- Fiddler Classic : Fiddler Classic을 실행한 후, Setting에서 `Decrypt https traffic` 옵션을 켜고, Tools -> Options -> Connections에 있는 기본 포트를 `8888`을 제외한 다른 포트로 지정합니다. 그리고 [이 스크립트](https://github.lunatic.moe/fiddlerscript)를 불러옵니다.
- [호스트 파일](https://github.com/Grasscutters/Grasscutter/wiki/Running#traffic-route-map)
2. 네트워크 프록시를 `127.0.0.1:8080` 로 설정하거나 지정한 프록시 포트로 설정합니다.
**또한 `start.cmd`를 실행함으로써, 서버와 프록시 데몬을 자동으로 실행되게 할 수 있습니다. 이를 이용하기 위해서는 JAVA_HOME 환경 변수를 등록해야 합니다.**
### 빌드하기 ### 빌드하기
@ -77,39 +50,50 @@ Grasscutter는 종속성 및 컴파일 처리를 위해 Gradle을 이용합니
- [Java SE 개발 키트 - 17](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)
- [Git](https://git-scm.com/downloads) - [Git](https://git-scm.com/downloads)
- [NodeJS](https://nodejs.org/en/download) (선택, 핸드북을 빌드하기 위해 필요함.)
##### 윈도우 (온라인) ##### 클론
```shell ```shell
git clone https://github.com/Grasscutters/Grasscutter.git git clone --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter cd Grasscutter
.\gradlew.bat # 개발 환경 설정
.\gradlew jar # 컴파일
``` ```
##### 윈도우 (로컬) ##### 컴파일
**각주**: 핸드북 생성은 일부 시스템에서 실패할 수도 있습니다. 핸드북 생성을 비활성화하려면, `gradlew jar`명령에 `-PskipHandbook=1`명령줄 스위치를 추가하세요.
윈도우:
```shell ```shell
cd <로컬 주소>/Grasscutter .\gradlew.bat # 환경 준비
.\gradlew.bat # 개발 환경 설정 .\gradlew jar
.\gradlew jar # 컴파일
``` ```
##### 리눅스 리눅스 (GNU):
```bash ```bash
git clone https://github.com/Grasscutters/Grasscutter.git
cd Grasscutter
chmod +x gradlew chmod +x gradlew
./gradlew jar # 컴파일 ./gradlew jar
```
##### 핸드북 컴파일 (수동동)
Gradle 사용:
```shell
./gradlew generateHandbook
```
NPM 사용:
```shell
cd src/handbook
npm install
npm run build
``` ```
프로젝트 폴더의 최상단에서 jar 파일을 찾을 수 있습니다. 프로젝트 폴더의 최상단에서 jar 파일을 찾을 수 있습니다.
### 명령어들은 [위키](https://github.com/Grasscutters/Grasscutter/wiki/Commands)에서 확인할 수 있습니다. ### 문제 해결
흔한 문제들의 해결방법과 도움을 요청하려면, [우리의 디스코드 서버](https://discord.gg/T5vZU6UyeG)에 참가하고 support 채널에 가보세요.
# 빠른 문제 해결
* 만약 컴파일링이 정상적으로 완료되지 않을 경우, JDK 설치를 확인하세요. (JDK 버전 17 및 JDK의 bin 경로 변수 등록을 확인)
* 클라이언트가 연결되지 않거나, 로그인이 안 되거나, 4206 오류가 뜨는 등의 경우 - 대부분 프록시 데몬의 설치에 문제가 있을 것입니다. Fiddler를 사용하고 있다면, 8888을 제외한 다른 포트에서 구동되고 있는지 확인하세요.
* 구동 순서 : MongoDB > Grasscutter > 프록시 데몬 (mitmdump, fiddler 등) > 게임

View File

@ -1,12 +1,12 @@
package emu.grasscutter; package emu.grasscutter;
public final class DebugConstants { public final class DebugConstants {
public static final boolean LOG_ABILITIES = false; public static boolean LOG_ABILITIES = false;
public static final boolean LOG_LUA_SCRIPTS = false; public static boolean LOG_LUA_SCRIPTS = false;
public static final boolean LOG_QUEST_START = false; public static boolean LOG_QUEST_START = false;
public static final boolean LOG_MISSING_ABILITIES = false; public static boolean LOG_MISSING_ABILITIES = false;
public static final boolean LOG_MISSING_LUA_SCRIPTS = false; public static boolean LOG_MISSING_LUA_SCRIPTS = false;
public static final boolean LOG_MISSING_ABILITY_HANDLERS = false; public static boolean LOG_MISSING_ABILITY_HANDLERS = false;
/** /**
* WARNING: THIS IS A DANGEROUS SETTING. DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING. This * WARNING: THIS IS A DANGEROUS SETTING. DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING. This

View File

@ -7,8 +7,8 @@ import emu.grasscutter.utils.objects.SparseSet;
import java.util.Arrays; import java.util.Arrays;
public final class GameConstants { public final class GameConstants {
public static final String VERSION = "4.0.0"; public static String VERSION = "4.0.0";
public static final int[] VERSION_PARTS = {4, 0, 0}; public static int[] VERSION_PARTS = {4, 0, 0};
public static boolean DEBUG = false; public static boolean DEBUG = false;
public static final int DEFAULT_TEAMS = 4; public static final int DEFAULT_TEAMS = 4;

View File

@ -312,7 +312,7 @@ public final class Grasscutter {
public static void updateDayOfWeek() { public static void updateDayOfWeek() {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
Grasscutter.currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); Grasscutter.currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
logger.debug("Set day of week to {}", currentDayOfWeek); logger.debug("Set day of week to " + currentDayOfWeek);
} }
public static void startConsole() { public static void startConsole() {

View File

@ -103,7 +103,7 @@ public final class DefaultAuthenticators {
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(keySpec); RSAPrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, private_key); cipher.init(Cipher.DECRYPT_MODE, private_key);

View File

@ -53,7 +53,7 @@ public final class CommandMap {
* @return Instance chaining. * @return Instance chaining.
*/ */
public CommandMap registerCommand(String label, CommandHandler command) { public CommandMap registerCommand(String label, CommandHandler command) {
Grasscutter.getLogger().trace("Registered command: {}", label); Grasscutter.getLogger().trace("Registered command: " + label);
label = label.toLowerCase(); label = label.toLowerCase();
// Get command data. // Get command data.
@ -76,7 +76,7 @@ public final class CommandMap {
* @return Instance chaining. * @return Instance chaining.
*/ */
public CommandMap unregisterCommand(String label) { public CommandMap unregisterCommand(String label) {
Grasscutter.getLogger().trace("Un-registered command: {}", label); Grasscutter.getLogger().trace("Un-registered command: " + label);
CommandHandler handler = this.commands.get(label); CommandHandler handler = this.commands.get(label);
if (handler == null) return this; if (handler == null) return this;
@ -231,12 +231,14 @@ public final class CommandMap {
if (player != null) { if (player != null) {
Grasscutter.getLogger() Grasscutter.getLogger()
.info( .info(
"Command used by [{} (Player UID: {})]: {}", "Command used by ["
player.getAccount().getUsername(), + player.getAccount().getUsername()
player.getUid(), + " (Player UID: "
rawMessage); + player.getUid()
+ ")]: "
+ rawMessage);
} else { } else {
Grasscutter.getLogger().info("Command used by server console: {}", rawMessage); Grasscutter.getLogger().info("Command used by server console: " + rawMessage);
} }
} }
@ -348,12 +350,11 @@ public final class CommandMap {
this.registerCommand(cmdData.label(), (CommandHandler) object); this.registerCommand(cmdData.label(), (CommandHandler) object);
else else
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Class {} is not a CommandHandler!", annotated.getName()); .error("Class " + annotated.getName() + " is not a CommandHandler!");
} catch (Exception exception) { } catch (Exception exception) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error( .error(
"Failed to register command handler for {}", "Failed to register command handler for " + annotated.getSimpleName(),
annotated.getSimpleName(),
exception); exception);
} }
}); });

View File

@ -69,7 +69,7 @@ public final class AchievementCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
this.sendUsageMessage(sender); this.sendUsageMessage(sender);
return; return;
} }
@ -88,7 +88,7 @@ public final class AchievementCommand implements CommandHandler {
private void grant( private void grant(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) { Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
this.sendUsageMessage(sender); this.sendUsageMessage(sender);
} }
@ -109,7 +109,7 @@ public final class AchievementCommand implements CommandHandler {
private void revoke( private void revoke(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) { Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
this.sendUsageMessage(sender); this.sendUsageMessage(sender);
} }
@ -136,7 +136,7 @@ public final class AchievementCommand implements CommandHandler {
parseInt(args.remove(0)) parseInt(args.remove(0))
.ifPresentOrElse( .ifPresentOrElse(
integer -> integer -> {
parseInt(args.remove(0)) parseInt(args.remove(0))
.ifPresentOrElse( .ifPresentOrElse(
progress -> { progress -> {
@ -148,7 +148,8 @@ public final class AchievementCommand implements CommandHandler {
sender, ret.getRet().getKey()); sender, ret.getRet().getKey());
} }
}, },
() -> this.sendUsageMessage(sender)), () -> this.sendUsageMessage(sender));
},
() -> this.sendUsageMessage(sender)); () -> this.sendUsageMessage(sender));
} }
} }

View File

@ -19,7 +19,7 @@ public final class AnnounceCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
var manager = Grasscutter.getGameServer().getAnnouncementSystem(); var manager = Grasscutter.getGameServer().getAnnouncementSystem();
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }

View File

@ -51,7 +51,7 @@ public final class ClearCommand implements CommandHandler {
// Extract any tagged int arguments (e.g. "lv90", "x100", "r5") // Extract any tagged int arguments (e.g. "lv90", "x100", "r5")
parseIntParameters(args, param, intCommandHandlers); parseIntParameters(args, param, intCommandHandlers);
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }
@ -93,10 +93,9 @@ public final class ClearCommand implements CommandHandler {
} }
} }
@Setter
private static class ClearItemParameters { private static class ClearItemParameters {
public int lvl = 1; @Setter public int lvl = 1;
public int refinement = 1; @Setter public int refinement = 1;
public int rank = 4; @Setter public int rank = 4;
} }
} }

View File

@ -16,7 +16,7 @@ public final class EnterDungeonCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }

View File

@ -3,23 +3,16 @@ package emu.grasscutter.command.commands;
import static emu.grasscutter.GameConstants.*; import static emu.grasscutter.GameConstants.*;
import static emu.grasscutter.command.CommandHelpers.*; import static emu.grasscutter.command.CommandHelpers.*;
import emu.grasscutter.command.Command; import emu.grasscutter.command.*;
import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.*;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.data.excels.avatar.AvatarData; import emu.grasscutter.data.excels.avatar.AvatarData;
import emu.grasscutter.data.excels.reliquary.ReliquaryAffixData; import emu.grasscutter.data.excels.reliquary.*;
import emu.grasscutter.data.excels.reliquary.ReliquaryMainPropData;
import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.*;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.*;
import emu.grasscutter.game.props.FightProperty; import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import lombok.Setter; import lombok.Setter;
@ -286,7 +279,7 @@ public final class GiveCommand implements CommandHandler {
parseIntParameters(args, param, intCommandHandlers); parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be itemId/avatarId // At this point, first remaining argument MUST be itemId/avatarId
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@ -369,7 +362,7 @@ public final class GiveCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { // *No args* if (args.size() < 1) { // *No args*
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }

View File

@ -63,7 +63,9 @@ public final class GroupCommand implements CommandHandler {
CommandHandler.sendMessage(sender, translate(sender, "commands.group.refreshed", groupId)); CommandHandler.sendMessage(sender, translate(sender, "commands.group.refreshed", groupId));
} }
default -> sendUsageMessage(sender); default -> {
sendUsageMessage(sender);
}
} }
} }
} }

View File

@ -19,14 +19,14 @@ public final class ListCommand implements CommandHandler {
Map<Integer, Player> playersMap = Grasscutter.getGameServer().getPlayers(); Map<Integer, Player> playersMap = Grasscutter.getGameServer().getPlayers();
boolean needUID = false; boolean needUID = false;
if (!args.isEmpty()) { if (args.size() > 0) {
needUID = args.get(0).equals("uid"); needUID = args.get(0).equals("uid");
} }
CommandHandler.sendMessage( CommandHandler.sendMessage(
sender, translate(sender, "commands.list.success", playersMap.size())); sender, translate(sender, "commands.list.success", playersMap.size()));
if (!playersMap.isEmpty()) { if (playersMap.size() != 0) {
StringBuilder playerSet = new StringBuilder(); StringBuilder playerSet = new StringBuilder();
boolean finalNeedUID = needUID; boolean finalNeedUID = needUID;

View File

@ -18,7 +18,7 @@ public final class ResetConstCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (!args.isEmpty() && args.get(0).equalsIgnoreCase("all")) { if (args.size() > 0 && args.get(0).equalsIgnoreCase("all")) {
targetPlayer.getAvatars().forEach(this::resetConstellation); targetPlayer.getAvatars().forEach(this::resetConstellation);
CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.reset_all")); CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.reset_all"));
} else { } else {

View File

@ -24,7 +24,8 @@ public final class SendMailCommand implements CommandHandler {
// the command system (again). For now this will do // the command system (again). For now this will do
// Key = User that is constructing the mail. // Key = User that is constructing the mail.
private static final HashMap<Integer, MailBuilder> mailBeingConstructed = new HashMap<>(); private static final HashMap<Integer, MailBuilder> mailBeingConstructed =
new HashMap<Integer, MailBuilder>();
// Yes this is awful and I hate it. // Yes this is awful and I hate it.
@Override @Override
@ -68,7 +69,7 @@ public final class SendMailCommand implements CommandHandler {
} else { } else {
MailBuilder mailBuilder = mailBeingConstructed.get(senderId); MailBuilder mailBuilder = mailBeingConstructed.get(senderId);
if (!args.isEmpty()) { if (args.size() >= 1) {
switch (args.get(0).toLowerCase()) { switch (args.get(0).toLowerCase()) {
case "stop" -> { case "stop" -> {
mailBeingConstructed.remove(senderId); mailBeingConstructed.remove(senderId);
@ -105,12 +106,14 @@ public final class SendMailCommand implements CommandHandler {
getConstructionArgs(mailBuilder.constructionStage, sender))); getConstructionArgs(mailBuilder.constructionStage, sender)));
} }
} }
case "help" -> CommandHandler.sendMessage( case "help" -> {
CommandHandler.sendMessage(
sender, sender,
translate( translate(
sender, sender,
"commands.sendMail.please_use", "commands.sendMail.please_use",
getConstructionArgs(mailBuilder.constructionStage, sender))); getConstructionArgs(mailBuilder.constructionStage, sender)));
}
default -> { default -> {
switch (mailBuilder.constructionStage) { switch (mailBuilder.constructionStage) {
case 0 -> { case 0 -> {

View File

@ -17,7 +17,7 @@ public final class SendMessageCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { if (args.size() == 0) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }

View File

@ -17,7 +17,7 @@ import java.util.List;
public final class SetConstCommand implements CommandHandler { public final class SetConstCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }

View File

@ -291,9 +291,9 @@ public final class SetPropCommand implements CommandHandler {
} }
static class Prop { static class Prop {
final String name; String name;
final PlayerProperty prop; PlayerProperty prop;
final PseudoProp pseudoProp; PseudoProp pseudoProp;
public Prop(PlayerProperty prop) { public Prop(PlayerProperty prop) {
this(prop.toString(), prop, PseudoProp.NONE); this(prop.toString(), prop, PseudoProp.NONE);

View File

@ -95,8 +95,9 @@ public final class SetSceneTagCommand implements CommandHandler {
// Only remove for big world as some other scenes only have defaults // Only remove for big world as some other scenes only have defaults
.filter(sceneTag -> sceneTag.getSceneId() == 3) .filter(sceneTag -> sceneTag.getSceneId() == 3)
.forEach( .forEach(
sceneTag -> sceneTag -> {
targetPlayer.getSceneTags().get(sceneTag.getSceneId()).remove(sceneTag.getId())); targetPlayer.getSceneTags().get(sceneTag.getSceneId()).remove(sceneTag.getId());
});
this.setSceneTags(targetPlayer); this.setSceneTags(targetPlayer);
} }

View File

@ -171,8 +171,8 @@ public final class SetStatsCommand implements CommandHandler {
} }
private static class Stat { private static class Stat {
final String name; String name;
final FightProperty prop; FightProperty prop;
public Stat(FightProperty prop) { public Stat(FightProperty prop) {
this.name = prop.toString(); this.name = prop.toString();

View File

@ -49,7 +49,7 @@ public final class SpawnCommand implements CommandHandler {
parseIntParameters(args, param, intCommandHandlers); parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be the id and the rest the pos // At this point, first remaining argument MUST be the id and the rest the pos
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }

View File

@ -17,9 +17,11 @@ public final class StopCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
CommandHandler.sendMessage(null, translate("commands.stop.success")); CommandHandler.sendMessage(null, translate("commands.stop.success"));
if (Grasscutter.getGameServer() != null) {
for (Player p : Grasscutter.getGameServer().getPlayers().values()) { for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
CommandHandler.sendMessage(p, translate(p, "commands.stop.success")); CommandHandler.sendMessage(p, translate(p, "commands.stop.success"));
} }
}
System.exit(1000); System.exit(1000);
} }

View File

@ -27,7 +27,7 @@ public final class TalentCommand implements CommandHandler {
@Override @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) { if (args.size() < 1) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }
@ -45,7 +45,9 @@ public final class TalentCommand implements CommandHandler {
String cmdSwitch = args.get(0).toLowerCase(); String cmdSwitch = args.get(0).toLowerCase();
switch (cmdSwitch) { switch (cmdSwitch) {
default -> sendUsageMessage(sender); default -> {
sendUsageMessage(sender);
}
case "set" -> { case "set" -> {
if (args.size() < 3) { if (args.size() < 3) {
sendUsageMessage(sender); sendUsageMessage(sender);

View File

@ -131,7 +131,7 @@ public final class TrialAvatarActivityCommand implements CommandHandler {
translate( translate(
sender, "commands.trialAvatarActivity.success_reward", Integer.parseInt(param))); sender, "commands.trialAvatarActivity.success_reward", Integer.parseInt(param)));
} else { } else {
if (!param.equalsIgnoreCase("all")) { if (!param.toLowerCase().equals("all")) {
CommandHandler.sendMessage( CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param")); sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return; return;

View File

@ -78,11 +78,11 @@ public class ConfigContainer {
} }
} }
public final Structure folderStructure = new Structure(); public Structure folderStructure = new Structure();
public final Database databaseInfo = new Database(); public Database databaseInfo = new Database();
public final Language language = new Language(); public Language language = new Language();
public final Account account = new Account(); public Account account = new Account();
public final Server server = new Server(); public Server server = new Server();
// DO NOT. TOUCH. THE VERSION NUMBER. // DO NOT. TOUCH. THE VERSION NUMBER.
public int version = version(); public int version = version();
@ -90,99 +90,99 @@ public class ConfigContainer {
/* Option containers. */ /* Option containers. */
public static class Database { public static class Database {
public final DataStore server = new DataStore(); public DataStore server = new DataStore();
public final DataStore game = new DataStore(); public DataStore game = new DataStore();
public static class DataStore { public static class DataStore {
public final String connectionUri = "mongodb://localhost:27017"; public String connectionUri = "mongodb://localhost:27017";
public final String collection = "grasscutter"; public String collection = "grasscutter";
} }
} }
public static class Structure { public static class Structure {
public final String resources = "./resources/"; public String resources = "./resources/";
public final String data = "./data/"; public String data = "./data/";
public final String packets = "./packets/"; public String packets = "./packets/";
public final String scripts = "resources:Scripts/"; public String scripts = "resources:Scripts/";
public final String plugins = "./plugins/"; public String plugins = "./plugins/";
public final String cache = "./cache/"; public String cache = "./cache/";
// UNUSED (potentially added later?) // UNUSED (potentially added later?)
// public String dumps = "./dumps/"; // public String dumps = "./dumps/";
} }
public static class Server { public static class Server {
public final Set<Integer> debugWhitelist = Set.of(); public Set<Integer> debugWhitelist = Set.of();
public final Set<Integer> debugBlacklist = Set.of(); public Set<Integer> debugBlacklist = Set.of();
public final ServerRunMode runMode = ServerRunMode.HYBRID; public ServerRunMode runMode = ServerRunMode.HYBRID;
public final boolean logCommands = false; public boolean logCommands = false;
/** /**
* If enabled, the 'require' Lua function will load the script's compiled varient into the context. (faster; doesn't work as well) * If enabled, the 'require' Lua function will load the script's compiled varient into the context. (faster; doesn't work as well)
* If disabled, all 'require' calls will be replaced with the referenced script's source. (slower; works better) * If disabled, all 'require' calls will be replaced with the referenced script's source. (slower; works better)
*/ */
public final boolean fastRequire = true; public boolean fastRequire = true;
public final HTTP http = new HTTP(); public HTTP http = new HTTP();
public final Game game = new Game(); public Game game = new Game();
public final Dispatch dispatch = new Dispatch(); public Dispatch dispatch = new Dispatch();
public final DebugMode debugMode = new DebugMode(); public DebugMode debugMode = new DebugMode();
} }
public static class Language { public static class Language {
public Locale language = Locale.getDefault(); public Locale language = Locale.getDefault();
public final Locale fallback = Locale.US; public Locale fallback = Locale.US;
public final String document = "EN"; public String document = "EN";
} }
public static class Account { public static class Account {
public final boolean autoCreate = false; public boolean autoCreate = false;
public final boolean EXPERIMENTAL_RealPassword = false; public boolean EXPERIMENTAL_RealPassword = false;
public final String[] defaultPermissions = {}; public String[] defaultPermissions = {};
public final String playerEmail = "grasscutter.io"; public String playerEmail = "grasscutter.io";
public final int maxPlayer = -1; public int maxPlayer = -1;
} }
/* Server options. */ /* Server options. */
public static class HTTP { public static class HTTP {
/* This starts the HTTP server before the game server. */ /* This starts the HTTP server before the game server. */
public final boolean startImmediately = false; public boolean startImmediately = false;
public final String bindAddress = "0.0.0.0"; public String bindAddress = "0.0.0.0";
public final int bindPort = 443; public int bindPort = 443;
/* This is the address used in URLs. */ /* This is the address used in URLs. */
public final String accessAddress = "127.0.0.1"; public String accessAddress = "127.0.0.1";
/* This is the port used in URLs. */ /* This is the port used in URLs. */
public final int accessPort = 0; public int accessPort = 0;
public final Encryption encryption = new Encryption(); public Encryption encryption = new Encryption();
public final Policies policies = new Policies(); public Policies policies = new Policies();
public final Files files = new Files(); public Files files = new Files();
} }
public static class Game { public static class Game {
public final String bindAddress = "0.0.0.0"; public String bindAddress = "0.0.0.0";
public final int bindPort = 22102; public int bindPort = 22102;
/* This is the address used in the default region. */ /* This is the address used in the default region. */
public final String accessAddress = "127.0.0.1"; public String accessAddress = "127.0.0.1";
/* This is the port used in the default region. */ /* This is the port used in the default region. */
public final int accessPort = 0; public int accessPort = 0;
/* Enabling this will generate a unique packet encryption key for each player. */ /* Enabling this will generate a unique packet encryption key for each player. */
public final boolean useUniquePacketKey = true; public boolean useUniquePacketKey = true;
/* Entities within a certain range will be loaded for the player */ /* Entities within a certain range will be loaded for the player */
public final int loadEntitiesForPlayerRange = 300; public int loadEntitiesForPlayerRange = 300;
/* Start in 'unstable-quests', Lua scripts will be enabled by default. */ /* Start in 'unstable-quests', Lua scripts will be enabled by default. */
public final boolean enableScriptInBigWorld = true; public boolean enableScriptInBigWorld = true;
public boolean enableConsole = true; public boolean enableConsole = true;
/* Kcp internal work interval (milliseconds) */ /* Kcp internal work interval (milliseconds) */
public final int kcpInterval = 20; public int kcpInterval = 20;
/* Controls whether packets should be logged in console or not */ /* Controls whether packets should be logged in console or not */
public ServerDebugMode logPackets = ServerDebugMode.NONE; public ServerDebugMode logPackets = ServerDebugMode.NONE;
/* Show packet payload in console or no (in any case the payload is shown in encrypted view) */ /* Show packet payload in console or no (in any case the payload is shown in encrypted view) */
@ -190,13 +190,13 @@ public class ConfigContainer {
/* Show annoying loop packets or no */ /* Show annoying loop packets or no */
public boolean isShowLoopPackets = false; public boolean isShowLoopPackets = false;
public final boolean cacheSceneEntitiesEveryRun = false; public boolean cacheSceneEntitiesEveryRun = false;
public final GameOptions gameOptions = new GameOptions(); public GameOptions gameOptions = new GameOptions();
public final JoinOptions joinOptions = new JoinOptions(); public JoinOptions joinOptions = new JoinOptions();
public final ConsoleAccount serverAccount = new ConsoleAccount(); public ConsoleAccount serverAccount = new ConsoleAccount();
public final VisionOptions[] visionOptions = new VisionOptions[] { public VisionOptions[] visionOptions = new VisionOptions[] {
new VisionOptions("VISION_LEVEL_NORMAL" , 80 , 20), new VisionOptions("VISION_LEVEL_NORMAL" , 80 , 20),
new VisionOptions("VISION_LEVEL_LITTLE_REMOTE" , 16 , 40), new VisionOptions("VISION_LEVEL_LITTLE_REMOTE" , 16 , 40),
new VisionOptions("VISION_LEVEL_REMOTE" , 1000 , 250), new VisionOptions("VISION_LEVEL_REMOTE" , 1000 , 250),
@ -210,17 +210,17 @@ public class ConfigContainer {
public static class Dispatch { public static class Dispatch {
/* An array of servers. */ /* An array of servers. */
public final List<Region> regions = List.of(); public List<Region> regions = List.of();
/* The URL used to make HTTP requests to the dispatch server. */ /* The URL used to make HTTP requests to the dispatch server. */
public final String dispatchUrl = "ws://127.0.0.1:1111"; public String dispatchUrl = "ws://127.0.0.1:1111";
/* A unique key used for encryption. */ /* A unique key used for encryption. */
public final byte[] encryptionKey = Crypto.createSessionKey(32); public byte[] encryptionKey = Crypto.createSessionKey(32);
/* A unique key used for authentication. */ /* A unique key used for authentication. */
public final String dispatchKey = Utils.base64Encode( public String dispatchKey = Utils.base64Encode(
Crypto.createSessionKey(32)); Crypto.createSessionKey(32));
public final String defaultName = "Grasscutter"; public String defaultName = "Grasscutter";
/* Controls whether http requests should be logged in console or not */ /* Controls whether http requests should be logged in console or not */
public ServerDebugMode logRequests = ServerDebugMode.NONE; public ServerDebugMode logRequests = ServerDebugMode.NONE;
@ -230,127 +230,127 @@ public class ConfigContainer {
* (see StartupArguments.enableDebug) */ * (see StartupArguments.enableDebug) */
public static class DebugMode { public static class DebugMode {
/* Log level of the main server code (works only with -debug arg) */ /* Log level of the main server code (works only with -debug arg) */
public final Level serverLoggerLevel = Level.DEBUG; public Level serverLoggerLevel = Level.DEBUG;
/* Log level of the third-party services (works only with -debug arg): /* Log level of the third-party services (works only with -debug arg):
javalin, quartz, reflections, jetty, mongodb.driver */ javalin, quartz, reflections, jetty, mongodb.driver */
public final Level servicesLoggersLevel = Level.INFO; public Level servicesLoggersLevel = Level.INFO;
/* Controls whether packets should be logged in console or not */ /* Controls whether packets should be logged in console or not */
public final ServerDebugMode logPackets = ServerDebugMode.ALL; public ServerDebugMode logPackets = ServerDebugMode.ALL;
/* Show packet payload in console or no (in any case the payload is shown in encrypted view) */ /* Show packet payload in console or no (in any case the payload is shown in encrypted view) */
public final boolean isShowPacketPayload = false; public boolean isShowPacketPayload = false;
/* Show annoying loop packets or no */ /* Show annoying loop packets or no */
public final boolean isShowLoopPackets = false; public boolean isShowLoopPackets = false;
/* Controls whether http requests should be logged in console or not */ /* Controls whether http requests should be logged in console or not */
public final ServerDebugMode logRequests = ServerDebugMode.ALL; public ServerDebugMode logRequests = ServerDebugMode.ALL;
} }
public static class Encryption { public static class Encryption {
public boolean useEncryption = true; public boolean useEncryption = true;
/* Should 'https' be appended to URLs? */ /* Should 'https' be appended to URLs? */
public boolean useInRouting = true; public boolean useInRouting = true;
public final String keystore = "./keystore.p12"; public String keystore = "./keystore.p12";
public final String keystorePassword = "123456"; public String keystorePassword = "123456";
} }
public static class Policies { public static class Policies {
public final Policies.CORS cors = new Policies.CORS(); public Policies.CORS cors = new Policies.CORS();
public static class CORS { public static class CORS {
public final boolean enabled = true; public boolean enabled = true;
public final String[] allowedOrigins = new String[]{"*"}; public String[] allowedOrigins = new String[]{"*"};
} }
} }
public static class GameOptions { public static class GameOptions {
public final InventoryLimits inventoryLimits = new InventoryLimits(); public InventoryLimits inventoryLimits = new InventoryLimits();
public final AvatarLimits avatarLimits = new AvatarLimits(); public AvatarLimits avatarLimits = new AvatarLimits();
public final int sceneEntityLimit = 1000; // Unenforced. TODO: Implement. public int sceneEntityLimit = 1000; // Unenforced. TODO: Implement.
public final boolean watchGachaConfig = false; public boolean watchGachaConfig = false;
public final boolean enableShopItems = true; public boolean enableShopItems = true;
public final boolean staminaUsage = true; public boolean staminaUsage = true;
public final boolean energyUsage = true; public boolean energyUsage = true;
public final boolean fishhookTeleport = true; public boolean fishhookTeleport = true;
public final boolean trialCostumes = false; public boolean trialCostumes = false;
@SerializedName(value = "questing", alternate = "questOptions") @SerializedName(value = "questing", alternate = "questOptions")
public final Questing questing = new Questing(); public Questing questing = new Questing();
public final ResinOptions resinOptions = new ResinOptions(); public ResinOptions resinOptions = new ResinOptions();
public final Rates rates = new Rates(); public Rates rates = new Rates();
public final HandbookOptions handbook = new HandbookOptions(); public HandbookOptions handbook = new HandbookOptions();
public static class InventoryLimits { public static class InventoryLimits {
public final int weapons = 2000; public int weapons = 2000;
public final int relics = 2000; public int relics = 2000;
public final int materials = 2000; public int materials = 2000;
public final int furniture = 2000; public int furniture = 2000;
public final int all = 30000; public int all = 30000;
} }
public static class AvatarLimits { public static class AvatarLimits {
public final int singlePlayerTeam = 4; public int singlePlayerTeam = 4;
public final int multiplayerTeam = 4; public int multiplayerTeam = 4;
} }
public static class Rates { public static class Rates {
public final float adventureExp = 1.0f; public float adventureExp = 1.0f;
public float mora = 1.0f; public float mora = 1.0f;
public float leyLines = 1.0f; public float leyLines = 1.0f;
} }
public static class ResinOptions { public static class ResinOptions {
public final boolean resinUsage = false; public boolean resinUsage = false;
public final int cap = 160; public int cap = 160;
public final int rechargeTime = 480; public int rechargeTime = 480;
} }
public static class Questing { public static class Questing {
/* Should questing behavior be used? */ /* Should questing behavior be used? */
public final boolean enabled = true; public boolean enabled = true;
} }
public static class HandbookOptions { public static class HandbookOptions {
public final boolean enable = false; public boolean enable = false;
public final boolean allowCommands = true; public boolean allowCommands = true;
public final Limits limits = new Limits(); public Limits limits = new Limits();
public final Server server = new Server(); public Server server = new Server();
public static class Limits { public static class Limits {
/* Are rate limits checked? */ /* Are rate limits checked? */
public final boolean enabled = false; public boolean enabled = false;
/* The time for limits to expire. */ /* The time for limits to expire. */
public final int interval = 3; public int interval = 3;
/* The maximum amount of normal requests. */ /* The maximum amount of normal requests. */
public final int maxRequests = 10; public int maxRequests = 10;
/* The maximum amount of entities to be spawned in one request. */ /* The maximum amount of entities to be spawned in one request. */
public final int maxEntities = 25; public int maxEntities = 25;
} }
public static class Server { public static class Server {
/* Are the server settings sent to the handbook? */ /* Are the server settings sent to the handbook? */
public final boolean enforced = false; public boolean enforced = false;
/* The default server address for the handbook's authentication. */ /* The default server address for the handbook's authentication. */
public final String address = "127.0.0.1"; public String address = "127.0.0.1";
/* The default server port for the handbook's authentication. */ /* The default server port for the handbook's authentication. */
public final int port = 443; public int port = 443;
/* Should the defaults be enforced? */ /* Should the defaults be enforced? */
public final boolean canChange = true; public boolean canChange = true;
} }
} }
} }
public static class VisionOptions { public static class VisionOptions {
public final String name; public String name;
public final int visionRange; public int visionRange;
public final int gridWidth; public int gridWidth;
public VisionOptions(String name, int visionRange, int gridWidth) { public VisionOptions(String name, int visionRange, int gridWidth) {
this.name = name; this.name = name;
@ -360,21 +360,21 @@ public class ConfigContainer {
} }
public static class JoinOptions { public static class JoinOptions {
public final int[] welcomeEmotes = {2007, 1002, 4010}; public int[] welcomeEmotes = {2007, 1002, 4010};
public final String welcomeMessage = "Welcome to a Grasscutter server."; public String welcomeMessage = "Welcome to a Grasscutter server.";
public final JoinOptions.Mail welcomeMail = new JoinOptions.Mail(); public JoinOptions.Mail welcomeMail = new JoinOptions.Mail();
public static class Mail { public static class Mail {
public final String title = "Welcome to Grasscutter!"; public String title = "Welcome to Grasscutter!";
public final String content = """ public String content = """
Hi there!\r Hi there!\r
First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r
\r \r
Check out our:\r Check out our:\r
<type="browser" text="Discord" href="https://discord.gg/T5vZU6UyeG"/> <type="browser" text="Discord" href="https://discord.gg/T5vZU6UyeG"/>
"""; """;
public final String sender = "Lawnmower"; public String sender = "Lawnmower";
public final emu.grasscutter.game.mail.Mail.MailItem[] items = { public emu.grasscutter.game.mail.Mail.MailItem[] items = {
new emu.grasscutter.game.mail.Mail.MailItem(13509, 1, 1), new emu.grasscutter.game.mail.Mail.MailItem(13509, 1, 1),
new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1) new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1)
}; };
@ -382,18 +382,18 @@ public class ConfigContainer {
} }
public static class ConsoleAccount { public static class ConsoleAccount {
public final int avatarId = 10000007; public int avatarId = 10000007;
public final int nameCardId = 210001; public int nameCardId = 210001;
public final int adventureRank = 1; public int adventureRank = 1;
public final int worldLevel = 0; public int worldLevel = 0;
public final String nickName = "Server"; public String nickName = "Server";
public final String signature = "Welcome to Grasscutter!"; public String signature = "Welcome to Grasscutter!";
} }
public static class Files { public static class Files {
public final String indexFile = "./index.html"; public String indexFile = "./index.html";
public final String errorFile = "./404.html"; public String errorFile = "./404.html";
} }
/* Objects. */ /* Objects. */

View File

@ -1,17 +1,10 @@
package emu.grasscutter.data; package emu.grasscutter.data;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.*;
import emu.grasscutter.utils.JsonUtils; import java.io.*;
import emu.grasscutter.utils.TsvUtils; import java.nio.file.*;
import java.io.FileNotFoundException; import java.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import lombok.val; import lombok.val;
public class DataLoader { public class DataLoader {
@ -22,7 +15,7 @@ public class DataLoader {
* *
* @param resourcePath The path to the data file to be loaded. * @param resourcePath The path to the data file to be loaded.
* @return InputStream of the data file. * @return InputStream of the data file.
* @throws FileNotFoundException If the file is not found. * @throws FileNotFoundException
* @see #load(String, boolean) * @see #load(String, boolean)
*/ */
public static InputStream load(String resourcePath) throws FileNotFoundException { public static InputStream load(String resourcePath) throws FileNotFoundException {
@ -35,14 +28,18 @@ public class DataLoader {
* *
* @param resourcePath The path to the data file to be loaded. * @param resourcePath The path to the data file to be loaded.
* @return InputStreamReader of the data file. * @return InputStreamReader of the data file.
* @throws IOException If the file is not found. * @throws IOException
* @throws FileNotFoundException If the file is not found. * @throws FileNotFoundException
* @see #load(String, boolean) * @see #load(String, boolean)
*/ */
public static InputStreamReader loadReader(String resourcePath) throws IOException { public static InputStreamReader loadReader(String resourcePath)
throws IOException, FileNotFoundException {
try {
InputStream is = load(resourcePath, true); InputStream is = load(resourcePath, true);
if (is == null) throw new FileNotFoundException("File not found: " + resourcePath);
return new InputStreamReader(is); return new InputStreamReader(is);
} catch (FileNotFoundException exception) {
throw exception;
}
} }
/** /**
@ -52,7 +49,7 @@ public class DataLoader {
* @param useFallback If the file does not exist in the /data directory, should it use the default * @param useFallback If the file does not exist in the /data directory, should it use the default
* file in the jar? * file in the jar?
* @return InputStream of the data file. * @return InputStream of the data file.
* @throws FileNotFoundException If the file is not found. * @throws FileNotFoundException
*/ */
public static InputStream load(String resourcePath, boolean useFallback) public static InputStream load(String resourcePath, boolean useFallback)
throws FileNotFoundException { throws FileNotFoundException {
@ -92,7 +89,7 @@ public class DataLoader {
public static <T> List<T> loadTableToList(String resourcePath, Class<T> classType) public static <T> List<T> loadTableToList(String resourcePath, Class<T> classType)
throws IOException { throws IOException {
val path = FileUtils.getDataPathTsjJsonTsv(resourcePath); val path = FileUtils.getDataPathTsjJsonTsv(resourcePath);
Grasscutter.getLogger().trace("Loading data table from: {}", path); Grasscutter.getLogger().trace("Loading data table from: " + path);
return switch (FileUtils.getFileExtension(path)) { return switch (FileUtils.getFileExtension(path)) {
case "json" -> JsonUtils.loadToList(path, classType); case "json" -> JsonUtils.loadToList(path, classType);
case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType); case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType);
@ -123,9 +120,10 @@ public class DataLoader {
if (!Files.exists(filePath)) { if (!Files.exists(filePath)) {
var root = filePath.getParent(); var root = filePath.getParent();
if (root.toFile().mkdirs()) Grasscutter.getLogger().info("Created data folder '{}'", root); if (root.toFile().mkdirs())
Grasscutter.getLogger().info("Created data folder '" + root + "'");
Grasscutter.getLogger().debug("Creating default '{}' data", name); Grasscutter.getLogger().debug("Creating default '" + name + "' data");
FileUtils.copyResource("/defaults/data/" + name, filePath.toString()); FileUtils.copyResource("/defaults/data/" + name, filePath.toString());
} }
} }

View File

@ -569,8 +569,8 @@ public final class GameData {
private static final Int2IntMap trialAvatarIndexIdTrialActivityDataDataMap = private static final Int2IntMap trialAvatarIndexIdTrialActivityDataDataMap =
new Int2IntOpenHashMap(); new Int2IntOpenHashMap();
private static final Map<Integer, List<Integer>> fetters = new HashMap<>(); private static Map<Integer, List<Integer>> fetters = new HashMap<>();
private static final Map<Integer, List<ShopGoodsData>> shopGoods = new HashMap<>(); private static Map<Integer, List<ShopGoodsData>> shopGoods = new HashMap<>();
// Getters with different names that stay for now // Getters with different names that stay for now
public static Int2ObjectMap<MainQuestData> getMainQuestDataMap() { public static Int2ObjectMap<MainQuestData> getMainQuestDataMap() {
@ -630,21 +630,15 @@ public final class GameData {
// Non-nullable value getters // Non-nullable value getters
public static int getAvatarLevelExpRequired(int level) { public static int getAvatarLevelExpRequired(int level) {
return Optional.ofNullable(avatarLevelDataMap.get(level)) return Optional.ofNullable(avatarLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0);
.map(AvatarLevelData::getExp)
.orElse(0);
} }
public static int getAvatarFetterLevelExpRequired(int level) { public static int getAvatarFetterLevelExpRequired(int level) {
return Optional.ofNullable(avatarFetterLevelDataMap.get(level)) return Optional.ofNullable(avatarFetterLevelDataMap.get(level)).map(d -> d.getExp()).orElse(0);
.map(AvatarFetterLevelData::getExp)
.orElse(0);
} }
public static int getRelicExpRequired(int rankLevel, int level) { public static int getRelicExpRequired(int rankLevel, int level) {
return Optional.ofNullable(getRelicLevelData(rankLevel, level)) return Optional.ofNullable(getRelicLevelData(rankLevel, level)).map(d -> d.getExp()).orElse(0);
.map(ReliquaryLevelData::getExp)
.orElse(0);
} }
// Generic getter // Generic getter
@ -661,7 +655,7 @@ public final class GameData {
field.setAccessible(false); field.setAccessible(false);
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Error fetching resource map for {}", resourceDefinition.getSimpleName(), e); .error("Error fetching resource map for " + resourceDefinition.getSimpleName(), e);
} }
return map; return map;
@ -719,8 +713,8 @@ public final class GameData {
/** /**
* Fetches the trial data * Fetches the trial data
* *
* @param trialAvatarIndexId The ID of the trial avatar * @param trialAvatarIndexId
* @return The trial data for the trial avatar * @return
*/ */
@Nullable public static TrialAvatarActivityDataData getTrialAvatarActivityDataByAvatarIndex( @Nullable public static TrialAvatarActivityDataData getTrialAvatarActivityDataByAvatarIndex(
int trialAvatarIndexId) { int trialAvatarIndexId) {

View File

@ -13,17 +13,17 @@ import lombok.*;
public class GameDepot { public class GameDepot {
public static final int[] BLOCK_SIZE = new int[] {50, 500}; // Scales public static final int[] BLOCK_SIZE = new int[] {50, 500}; // Scales
private static final Int2ObjectMap<WeightedList<ReliquaryMainPropData>> relicRandomMainPropDepot = private static Int2ObjectMap<WeightedList<ReliquaryMainPropData>> relicRandomMainPropDepot =
new Int2ObjectOpenHashMap<>(); new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<List<ReliquaryMainPropData>> relicMainPropDepot = private static Int2ObjectMap<List<ReliquaryMainPropData>> relicMainPropDepot =
new Int2ObjectOpenHashMap<>(); new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<List<ReliquaryAffixData>> relicAffixDepot = private static Int2ObjectMap<List<ReliquaryAffixData>> relicAffixDepot =
new Int2ObjectOpenHashMap<>(); new Int2ObjectOpenHashMap<>();
@Getter @Setter private static Map<String, AvatarConfig> playerAbilities = new HashMap<>(); @Getter @Setter private static Map<String, AvatarConfig> playerAbilities = new HashMap<>();
@Getter @Getter
private static final HashMap<SpawnDataEntry.GridBlockId, ArrayList<SpawnDataEntry>> spawnLists = private static HashMap<SpawnDataEntry.GridBlockId, ArrayList<SpawnDataEntry>> spawnLists =
new HashMap<>(); new HashMap<>();
@Getter @Setter private static BlossomConfig blossomConfig; @Getter @Setter private static BlossomConfig blossomConfig;
@ -50,7 +50,7 @@ public class GameDepot {
list.add(data); list.add(data);
} }
// Let the server owner know if theyre missing weights // Let the server owner know if theyre missing weights
if (relicMainPropDepot.isEmpty() || relicAffixDepot.isEmpty()) { if (relicMainPropDepot.size() == 0 || relicAffixDepot.size() == 0) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error( .error(
"Relic properties are missing weights! Please check your ReliquaryMainPropExcelConfigData or ReliquaryAffixExcelConfigData files in your ExcelBinOutput folder."); "Relic properties are missing weights! Please check your ReliquaryMainPropExcelConfigData or ReliquaryAffixExcelConfigData files in your ExcelBinOutput folder.");

View File

@ -63,7 +63,7 @@ public final class ResourceLoader {
private static List<Set<Class<?>>> getResourceDefClassesPrioritySets() { private static List<Set<Class<?>>> getResourceDefClassesPrioritySets() {
val classes = Grasscutter.reflector.getSubTypesOf(GameResource.class); val classes = Grasscutter.reflector.getSubTypesOf(GameResource.class);
val priorities = ResourceType.LoadPriority.getInOrder(); val priorities = ResourceType.LoadPriority.getInOrder();
Grasscutter.getLogger().debug("Priorities are {}", priorities); Grasscutter.getLogger().debug("Priorities are " + priorities);
val map = new LinkedHashMap<ResourceType.LoadPriority, Set<Class<?>>>(priorities.size()); val map = new LinkedHashMap<ResourceType.LoadPriority, Set<Class<?>>>(priorities.size());
priorities.forEach(p -> map.put(p, new HashSet<>())); priorities.forEach(p -> map.put(p, new HashSet<>()));
@ -140,7 +140,7 @@ public final class ResourceLoader {
getResourceDefClassesPrioritySets() getResourceDefClassesPrioritySets()
.forEach( .forEach(
classes -> classes -> {
classes.stream() classes.stream()
.parallel() .parallel()
.unordered() .unordered()
@ -157,18 +157,19 @@ public final class ResourceLoader {
} catch (Exception e) { } catch (Exception e) {
errors.add(Pair.of(Arrays.toString(type.name()), e)); errors.add(Pair.of(Arrays.toString(type.name()), e));
} }
})); });
});
errors.forEach( errors.forEach(
pair -> pair ->
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Error loading resource file: {}", pair.left(), pair.right())); .error("Error loading resource file: " + pair.left(), pair.right()));
long endTime = System.nanoTime(); long endTime = System.nanoTime();
long ns = (endTime - startTime); // divide by 1000000 to get milliseconds. long ns = (endTime - startTime); // divide by 1000000 to get milliseconds.
Grasscutter.getLogger().debug("Loading resources took {}ns == {}ms", ns, ns / 1000000); Grasscutter.getLogger().debug("Loading resources took " + ns + "ns == " + ns / 1000000 + "ms");
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private static void loadFromResource( protected static void loadFromResource(
Class<?> c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception { Class<?> c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception {
val simpleName = c.getSimpleName(); val simpleName = c.getSimpleName();
if (doReload || !loadedResources.contains(simpleName)) { if (doReload || !loadedResources.contains(simpleName)) {
@ -180,7 +181,7 @@ public final class ResourceLoader {
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
private static <T> void loadFromResource(Class<T> c, Path filename, Int2ObjectMap map) protected static <T> void loadFromResource(Class<T> c, Path filename, Int2ObjectMap map)
throws Exception { throws Exception {
val results = val results =
switch (FileUtils.getFileExtension(filename)) { switch (FileUtils.getFileExtension(filename)) {
@ -199,7 +200,7 @@ public final class ResourceLoader {
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
private static <T> void loadFromResource(Class<T> c, String fileName, Int2ObjectMap map) protected static <T> void loadFromResource(Class<T> c, String fileName, Int2ObjectMap map)
throws Exception { throws Exception {
JsonUtils.loadToList(getResourcePath("ExcelBinOutput/" + fileName), c) JsonUtils.loadToList(getResourcePath("ExcelBinOutput/" + fileName), c)
.forEach( .forEach(
@ -282,7 +283,7 @@ public final class ResourceLoader {
} }
}); });
Grasscutter.getLogger() Grasscutter.getLogger()
.debug("Loaded {} SceneRouteDatas.", GameData.getSceneNpcBornData().size()); .debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneRouteDatas.");
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().error("Failed to load SceneRouteData folder."); Grasscutter.getLogger().error("Failed to load SceneRouteData folder.");
} }
@ -403,7 +404,7 @@ public final class ResourceLoader {
.forEach(data -> loadAbilityData(data.Default)); .forEach(data -> loadAbilityData(data.Default));
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Error loading ability modifiers from path {}: ", path.toString(), e); .error("Error loading ability modifiers from path " + path.toString() + ": ", e);
} }
} }
@ -412,7 +413,7 @@ public final class ResourceLoader {
GameData.getAbilityHashes().put(Utils.abilityHash(data.abilityName), data.abilityName); GameData.getAbilityHashes().put(Utils.abilityHash(data.abilityName), data.abilityName);
var modifiers = data.modifiers; var modifiers = data.modifiers;
if (modifiers == null || modifiers.isEmpty()) return; if (modifiers == null || modifiers.size() == 0) return;
var name = data.abilityName; var name = data.abilityName;
var modifierEntry = new AbilityModifierEntry(name); var modifierEntry = new AbilityModifierEntry(name);
@ -465,7 +466,7 @@ public final class ResourceLoader {
path, String.class, new TypeToken<List<TalentData>>() {}.getType())); path, String.class, new TypeToken<List<TalentData>>() {}.getType()));
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Error loading ability modifiers from path {}: ", path.toString(), e); .error("Error loading ability modifiers from path " + path.toString() + ": ", e);
} }
} }
@ -532,7 +533,7 @@ public final class ResourceLoader {
}); });
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger() Grasscutter.getLogger()
.error("Error loading open config: no files found in {}", folderName); .error("Error loading open config: no files found in " + folderName);
return; return;
} }
} }
@ -588,7 +589,7 @@ public final class ResourceLoader {
} }
Grasscutter.getLogger() Grasscutter.getLogger()
.debug("Loaded {} MainQuestDatas.", GameData.getMainQuestDataMap().size()); .debug("Loaded " + GameData.getMainQuestDataMap().size() + " MainQuestDatas.");
} }
public static void loadScriptSceneData() { public static void loadScriptSceneData() {
@ -606,7 +607,7 @@ public final class ResourceLoader {
} }
}); });
Grasscutter.getLogger() Grasscutter.getLogger()
.debug("Loaded {} ScriptSceneDatas.", GameData.getScriptSceneDataMap().size()); .debug("Loaded " + GameData.getScriptSceneDataMap().size() + " ScriptSceneDatas.");
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().debug("ScriptSceneData folder missing or empty."); Grasscutter.getLogger().debug("ScriptSceneData folder missing or empty.");
} }
@ -631,8 +632,9 @@ public final class ResourceLoader {
}); });
Grasscutter.getLogger() Grasscutter.getLogger()
.debug( .debug(
"Loaded {} HomeworldDefaultSaveDatas.", "Loaded "
GameData.getHomeworldDefaultSaveData().size()); + GameData.getHomeworldDefaultSaveData().size()
+ " HomeworldDefaultSaveDatas.");
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().error("Failed to load HomeworldDefaultSave folder."); Grasscutter.getLogger().error("Failed to load HomeworldDefaultSave folder.");
} }
@ -645,7 +647,7 @@ public final class ResourceLoader {
path -> { path -> {
try { try {
val data = JsonUtils.loadToClass(path, SceneNpcBornData.class); val data = JsonUtils.loadToClass(path, SceneNpcBornData.class);
if (data.getBornPosList() == null || data.getBornPosList().isEmpty()) { if (data.getBornPosList() == null || data.getBornPosList().size() == 0) {
return; return;
} }
@ -657,7 +659,7 @@ public final class ResourceLoader {
} }
}); });
Grasscutter.getLogger() Grasscutter.getLogger()
.debug("Loaded {} SceneNpcBornDatas.", GameData.getSceneNpcBornData().size()); .debug("Loaded " + GameData.getSceneNpcBornData().size() + " SceneNpcBornDatas.");
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().error("Failed to load SceneNpcBorn folder."); Grasscutter.getLogger().error("Failed to load SceneNpcBorn folder.");
} }
@ -835,6 +837,7 @@ public final class ResourceLoader {
try { try {
JsonUtils.loadToList(getResourcePath("Server/SubfieldMapping.json"), SubfieldMapping.class) JsonUtils.loadToList(getResourcePath("Server/SubfieldMapping.json"), SubfieldMapping.class)
.forEach(entry -> subfieldMap.put(entry.getEntityId(), entry)); .forEach(entry -> subfieldMap.put(entry.getEntityId(), entry));
;
} catch (IOException | NullPointerException ignored) { } catch (IOException | NullPointerException ignored) {
} }
Grasscutter.getLogger().debug("Loaded {} subfield mappings.", subfieldMap.size()); Grasscutter.getLogger().debug("Loaded {} subfield mappings.", subfieldMap.size());
@ -848,6 +851,7 @@ public final class ResourceLoader {
JsonUtils.loadToList( JsonUtils.loadToList(
getResourcePath("Server/DropSubfieldMapping.json"), DropSubfieldMapping.class) getResourcePath("Server/DropSubfieldMapping.json"), DropSubfieldMapping.class)
.forEach(entry -> dropSubfieldMap.put(entry.getDropId(), entry)); .forEach(entry -> dropSubfieldMap.put(entry.getDropId(), entry));
;
} catch (IOException | NullPointerException ignored) { } catch (IOException | NullPointerException ignored) {
} }
Grasscutter.getLogger().debug("Loaded {} drop subfield mappings.", dropSubfieldMap.size()); Grasscutter.getLogger().debug("Loaded {} drop subfield mappings.", dropSubfieldMap.size());
@ -862,6 +866,7 @@ public final class ResourceLoader {
getResourcePath("Server/DropTableExcelConfigData.json"), getResourcePath("Server/DropTableExcelConfigData.json"),
DropTableExcelConfigData.class) DropTableExcelConfigData.class)
.forEach(entry -> dropTableExcelConfigDataMap.put(entry.getId(), entry)); .forEach(entry -> dropTableExcelConfigDataMap.put(entry.getId(), entry));
;
} catch (IOException | NullPointerException ignored) { } catch (IOException | NullPointerException ignored) {
} }
Grasscutter.getLogger() Grasscutter.getLogger()

View File

@ -1,8 +1,5 @@
package emu.grasscutter.data.binout; package emu.grasscutter.data.binout;
import lombok.Getter;
@Getter
public class AbilityEmbryoEntry { public class AbilityEmbryoEntry {
private String name; private String name;
private String[] abilities; private String[] abilities;
@ -13,4 +10,12 @@ public class AbilityEmbryoEntry {
this.name = avatarName; this.name = avatarName;
this.abilities = array; this.abilities = array;
} }
public String getName() {
return name;
}
public String[] getAbilities() {
return abilities;
}
} }

View File

@ -3,18 +3,17 @@ package emu.grasscutter.data.binout;
import com.google.gson.*; import com.google.gson.*;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.*; import java.util.*;
public class AbilityMixinData implements Serializable { public class AbilityMixinData implements Serializable {
@Serial private static final long serialVersionUID = -2001232313615923575L; private static final long serialVersionUID = -2001232313615923575L;
public enum Type { public enum Type {
AttachToGadgetStateMixin, AttachToGadgetStateMixin,
AttachToStateIDMixin, AttachToStateIDMixin,
ShieldBarMixin, ShieldBarMixin,
TileAttackManagerMixin TileAttackManagerMixin;
} }
@SerializedName("$type") @SerializedName("$type")
@ -28,7 +27,7 @@ public class AbilityMixinData implements Serializable {
List<String> list = (new Gson()).fromJson(modifierName, listType); List<String> list = (new Gson()).fromJson(modifierName, listType);
return list; return list;
} else { } else {
return Collections.singletonList(modifierName.getAsString()); return Arrays.asList(modifierName.getAsString());
} }
} }
} }

View File

@ -3,12 +3,11 @@ package emu.grasscutter.data.binout;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.common.DynamicFloat; import emu.grasscutter.data.common.DynamicFloat;
import emu.grasscutter.game.props.ElementType; import emu.grasscutter.game.props.ElementType;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import lombok.ToString; import lombok.ToString;
public class AbilityModifier implements Serializable { public class AbilityModifier implements Serializable {
@Serial private static final long serialVersionUID = -2001232313615923575L; private static final long serialVersionUID = -2001232313615923575L;
public State state; public State state;
@ -265,7 +264,7 @@ public class AbilityModifier implements Serializable {
TurnDirectionToPos, TurnDirectionToPos,
UpdateReactionDamage, UpdateReactionDamage,
UseSkillEliteSet, UseSkillEliteSet,
WidgetSkillStart WidgetSkillStart;
} }
@SerializedName("$type") @SerializedName("$type")

View File

@ -2,13 +2,12 @@ package emu.grasscutter.data.binout;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction; import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import java.util.*; import java.util.*;
import lombok.Getter;
public class AbilityModifierEntry { public class AbilityModifierEntry {
public final List<AbilityModifierAction> onModifierAdded; public List<AbilityModifierAction> onModifierAdded;
@Getter public final List<AbilityModifierAction> onThinkInterval; public List<AbilityModifierAction> onThinkInterval;
@Getter public final List<AbilityModifierAction> onRemoved; public List<AbilityModifierAction> onRemoved;
@Getter private final String name; // Custom value private final String name; // Custom value
public AbilityModifierEntry(String name) { public AbilityModifierEntry(String name) {
this.name = name; this.name = name;
@ -17,7 +16,19 @@ public class AbilityModifierEntry {
this.onRemoved = new ArrayList<>(); this.onRemoved = new ArrayList<>();
} }
public String getName() {
return name;
}
public List<AbilityModifierAction> getOnAdded() { public List<AbilityModifierAction> getOnAdded() {
return onModifierAdded; return onModifierAdded;
} }
public List<AbilityModifierAction> getOnThinkInterval() {
return onThinkInterval;
}
public List<AbilityModifierAction> getOnRemoved() {
return onRemoved;
}
} }

View File

@ -5,22 +5,53 @@ import emu.grasscutter.data.GameData;
import emu.grasscutter.game.quest.enums.QuestType; import emu.grasscutter.game.quest.enums.QuestType;
import java.util.*; import java.util.*;
import lombok.Data; import lombok.Data;
import lombok.Getter;
public class MainQuestData { public class MainQuestData {
@Getter private int id; private int id;
private int ICLLDPJFIMA; private int ICLLDPJFIMA;
@Getter private int series; private int series;
@Getter private QuestType type; private QuestType type;
@Getter private long titleTextMapHash; private long titleTextMapHash;
@Getter private int[] suggestTrackMainQuestList; private int[] suggestTrackMainQuestList;
@Getter private int[] rewardIdList; private int[] rewardIdList;
@Getter private SubQuestData[] subQuests; private SubQuestData[] subQuests;
@Getter private List<TalkData> talks; private List<TalkData> talks;
private long[] preloadLuaList; private long[] preloadLuaList;
public int getId() {
return id;
}
public int getSeries() {
return series;
}
public QuestType getType() {
return type;
}
public long getTitleTextMapHash() {
return titleTextMapHash;
}
public int[] getSuggestTrackMainQuestList() {
return suggestTrackMainQuestList;
}
public int[] getRewardIdList() {
return rewardIdList;
}
public SubQuestData[] getSubQuests() {
return subQuests;
}
public List<TalkData> getTalks() {
return talks;
}
public void onLoad() { public void onLoad() {
if (this.talks == null) this.talks = new ArrayList<>(); if (this.talks == null) this.talks = new ArrayList<>();
if (this.subQuests == null) this.subQuests = new SubQuestData[0]; if (this.subQuests == null) this.subQuests = new SubQuestData[0];

View File

@ -2,9 +2,7 @@ package emu.grasscutter.data.binout;
import emu.grasscutter.data.ResourceLoader.OpenConfigData; import emu.grasscutter.data.ResourceLoader.OpenConfigData;
import java.util.*; import java.util.*;
import lombok.Getter;
@Getter
public class OpenConfigEntry { public class OpenConfigEntry {
private final String name; private final String name;
private String[] addAbilities; private String[] addAbilities;
@ -27,23 +25,46 @@ public class OpenConfigEntry {
} }
} }
if (!abilityList.isEmpty()) { if (abilityList.size() > 0) {
this.addAbilities = abilityList.toArray(new String[0]); this.addAbilities = abilityList.toArray(new String[0]);
} }
if (!modList.isEmpty()) { if (modList.size() > 0) {
this.skillPointModifiers = modList.toArray(new SkillPointModifier[0]); this.skillPointModifiers = modList.toArray(new SkillPointModifier[0]);
} }
} }
@Getter public String getName() {
return name;
}
public String[] getAddAbilities() {
return addAbilities;
}
public int getExtraTalentIndex() {
return extraTalentIndex;
}
public SkillPointModifier[] getSkillPointModifiers() {
return skillPointModifiers;
}
public static class SkillPointModifier { public static class SkillPointModifier {
private final int skillId; private int skillId;
private final int delta; private int delta;
public SkillPointModifier(int skillId, int delta) { public SkillPointModifier(int skillId, int delta) {
this.skillId = skillId; this.skillId = skillId;
this.delta = delta; this.delta = delta;
} }
public int getSkillId() {
return skillId;
}
public int getDelta() {
return delta;
}
} }
} }

View File

@ -3,10 +3,9 @@ package emu.grasscutter.data.binout;
import emu.grasscutter.data.common.PointData; import emu.grasscutter.data.common.PointData;
import lombok.Getter; import lombok.Getter;
@Getter
public class ScenePointEntry { public class ScenePointEntry {
private final int sceneId; @Getter private final int sceneId;
private final PointData pointData; @Getter private final PointData pointData;
@Deprecated(forRemoval = true) @Deprecated(forRemoval = true)
public ScenePointEntry(String name, PointData pointData) { public ScenePointEntry(String name, PointData pointData) {

View File

@ -10,7 +10,7 @@ public class TalentData implements Serializable {
ModifySkillCD, ModifySkillCD,
UnlockTalentParam, UnlockTalentParam,
AddTalentExtraLevel, AddTalentExtraLevel,
ModifyAbility ModifyAbility;
} }
@SerializedName("$type") @SerializedName("$type")

View File

@ -4,14 +4,13 @@ import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
@Getter
public class ConfigLevelEntity { public class ConfigLevelEntity {
private List<ConfigAbilityData> abilities; @Getter private List<ConfigAbilityData> abilities;
private List<ConfigAbilityData> monsterAbilities; @Getter private List<ConfigAbilityData> monsterAbilities;
private List<ConfigAbilityData> avatarAbilities; @Getter private List<ConfigAbilityData> avatarAbilities;
private List<ConfigAbilityData> teamAbilities; @Getter private List<ConfigAbilityData> teamAbilities;
private List<Integer> preloadMonsterEntityIDs; @Getter private List<Integer> preloadMonsterEntityIDs;
private String dropElemControlType; @Getter private String dropElemControlType;
} }

View File

@ -3,14 +3,13 @@ package emu.grasscutter.data.binout.routes;
// import emu.grasscutter.scripts.constants.IntValueEnum; // import emu.grasscutter.scripts.constants.IntValueEnum;
import lombok.Getter; import lombok.Getter;
@Getter
public enum RotAngleType /*implements IntValueEnum */ { public enum RotAngleType /*implements IntValueEnum */ {
ROT_NONE(-1), ROT_NONE(-1),
ROT_ANGLE_X(0), ROT_ANGLE_X(0),
ROT_ANGLE_Y(1), ROT_ANGLE_Y(1),
ROT_ANGLE_Z(2); ROT_ANGLE_Z(2);
private final int id; @Getter private final int id;
RotAngleType(int id) { RotAngleType(int id) {
this.id = id; this.id = id;

View File

@ -3,14 +3,13 @@ package emu.grasscutter.data.binout.routes;
// import emu.grasscutter.scripts.constants.IntValueEnum; // import emu.grasscutter.scripts.constants.IntValueEnum;
import lombok.Getter; import lombok.Getter;
@Getter
public enum RouteType /*implements IntValueEnum*/ { public enum RouteType /*implements IntValueEnum*/ {
Unknown(-1), Unknown(-1),
OneWay(0), OneWay(0),
Reciprocate(1), Reciprocate(1),
Loop(2); Loop(2);
private final int id; @Getter private final int id;
RouteType(int id) { RouteType(int id) {
this.id = id; this.id = id;

View File

@ -1,10 +1,19 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import lombok.Getter;
@Getter
public class CurveInfo { public class CurveInfo {
private String type; private String type;
private String arith; private String arith;
private float value; private float value;
public String getType() {
return type;
}
public String getArith() {
return arith;
}
public float getValue() {
return value;
}
} }

View File

@ -92,7 +92,7 @@ public class DynamicFloat {
} }
public static class StackOp { public static class StackOp {
public final Op op; public Op op;
public float fValue; public float fValue;
public String sValue; public String sValue;

View File

@ -1,14 +1,24 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import lombok.Getter;
@Getter
public class FightPropData { public class FightPropData {
private String propType; private String propType;
private FightProperty prop; private FightProperty prop;
private float value; private float value;
public String getPropType() {
return propType;
}
public float getValue() {
return value;
}
public FightProperty getProp() {
return prop;
}
public void onLoad() { public void onLoad() {
this.prop = FightProperty.getPropByName(propType); this.prop = FightProperty.getPropByName(propType);
} }

View File

@ -1,10 +1,8 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import lombok.Getter;
// Used in excels // Used in excels
@Getter
public class ItemParamData { public class ItemParamData {
@SerializedName( @SerializedName(
value = "id", value = "id",
@ -23,10 +21,18 @@ public class ItemParamData {
this.count = count; this.count = count;
} }
public int getId() {
return id;
}
public int getItemId() { public int getItemId() {
return id; return id;
} }
public int getCount() {
return count;
}
public int getItemCount() { public int getItemCount() {
return count; return count;
} }

View File

@ -1,14 +1,19 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import lombok.Getter;
@Getter
public class ItemParamStringData { public class ItemParamStringData {
private int id; private int id;
private String count; private String count;
public ItemParamStringData() {} public ItemParamStringData() {}
public int getId() {
return id;
}
public String getCount() {
return count;
}
public ItemParamData toItemParamData() { public ItemParamData toItemParamData() {
if (count.contains(";")) { if (count.contains(";")) {
String[] split = count.split(";"); String[] split = count.split(";");

View File

@ -1,11 +1,10 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import emu.grasscutter.game.props.ItemUseOp; import emu.grasscutter.game.props.ItemUseOp;
import lombok.Getter;
public class ItemUseData { public class ItemUseData {
private ItemUseOp useOp; private ItemUseOp useOp;
@Getter private String[] useParam; private String[] useParam;
public ItemUseOp getUseOp() { public ItemUseOp getUseOp() {
if (useOp == null) { if (useOp == null) {
@ -13,4 +12,8 @@ public class ItemUseData {
} }
return useOp; return useOp;
} }
public String[] getUseParam() {
return useParam;
}
} }

View File

@ -1,18 +1,24 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import java.util.List; import java.util.List;
import lombok.Getter;
@Getter
public class OpenCondData { public class OpenCondData {
private String condType; private String condType;
private List<Integer> paramList; private List<Integer> paramList;
public void setCondType(String cType) { public String getCondType() {
condType = cType; return condType;
} }
public void setParamList(List<Integer> pList) { public void setCondType(String condType) {
paramList = pList; condType = condType;
}
public List<Integer> getParamList() {
return paramList;
}
public void setParamList(List<Integer> paramList) {
paramList = paramList;
} }
} }

View File

@ -1,9 +1,14 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import lombok.Getter;
@Getter
public class PropGrowCurve { public class PropGrowCurve {
private String type; private String type;
private String growCurve; private String growCurve;
public String getType() {
return this.type;
}
public String getGrowCurve() {
return this.growCurve;
}
} }

View File

@ -4,22 +4,21 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.Getter;
@ResourceType(name = "CombineExcelConfigData.json") @ResourceType(name = "CombineExcelConfigData.json")
public class CombineData extends GameResource { public class CombineData extends GameResource {
@Getter private int combineId; private int combineId;
@Getter private int playerLevel; private int playerLevel;
private boolean isDefaultShow; private boolean isDefaultShow;
@Getter private int combineType; private int combineType;
@Getter private int subCombineType; private int subCombineType;
@Getter private int resultItemId; private int resultItemId;
@Getter private int resultItemCount; private int resultItemCount;
@Getter private int scoinCost; private int scoinCost;
@Getter private List<ItemParamData> randomItems; private List<ItemParamData> randomItems;
@Getter private List<ItemParamData> materialItems; private List<ItemParamData> materialItems;
@Getter private String recipeType; private String recipeType;
@Override @Override
public int getId() { public int getId() {
@ -36,7 +35,47 @@ public class CombineData extends GameResource {
materialItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList()); materialItems.stream().filter(item -> item.getId() > 0).collect(Collectors.toList());
} }
public int getCombineId() {
return combineId;
}
public int getPlayerLevel() {
return playerLevel;
}
public boolean isDefaultShow() { public boolean isDefaultShow() {
return isDefaultShow; return isDefaultShow;
} }
public int getCombineType() {
return combineType;
}
public int getSubCombineType() {
return subCombineType;
}
public int getResultItemId() {
return resultItemId;
}
public int getResultItemCount() {
return resultItemCount;
}
public int getScoinCost() {
return scoinCost;
}
public List<ItemParamData> getRandomItems() {
return randomItems;
}
public List<ItemParamData> getMaterialItems() {
return materialItems;
}
public String getRecipeType() {
return recipeType;
}
} }

View File

@ -2,9 +2,7 @@ package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import lombok.Getter;
@Getter
@ResourceType( @ResourceType(
name = {"CookBonusExcelConfigData.json"}, name = {"CookBonusExcelConfigData.json"},
loadPriority = LoadPriority.LOW) loadPriority = LoadPriority.LOW)
@ -19,6 +17,22 @@ public class CookBonusData extends GameResource {
return this.avatarId; return this.avatarId;
} }
public int getAvatarId() {
return avatarId;
}
public int getRecipeId() {
return recipeId;
}
public int[] getParamVec() {
return paramVec;
}
public int[] getComplexParamVec() {
return complexParamVec;
}
public int getReplacementItemId() { public int getReplacementItemId() {
return this.paramVec[0]; return this.paramVec[0];
} }

View File

@ -3,14 +3,13 @@ package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import java.util.List; import java.util.List;
import lombok.Getter;
@ResourceType( @ResourceType(
name = "EnvAnimalGatherExcelConfigData.json", name = "EnvAnimalGatherExcelConfigData.json",
loadPriority = ResourceType.LoadPriority.LOW) loadPriority = ResourceType.LoadPriority.LOW)
public class EnvAnimalGatherConfigData extends GameResource { public class EnvAnimalGatherConfigData extends GameResource {
@Getter private int animalId; private int animalId;
@Getter private String entityType; private String entityType;
private List<ItemParamData> gatherItemId; private List<ItemParamData> gatherItemId;
private String excludeWeathers; private String excludeWeathers;
private int aliveTime; private int aliveTime;
@ -22,7 +21,15 @@ public class EnvAnimalGatherConfigData extends GameResource {
return animalId; return animalId;
} }
public int getAnimalId() {
return animalId;
}
public String getEntityType() {
return entityType;
}
public ItemParamData getGatherItem() { public ItemParamData getGatherItem() {
return !gatherItemId.isEmpty() ? gatherItemId.get(0) : null; return gatherItemId.size() > 0 ? gatherItemId.get(0) : null;
} }
} }

View File

@ -3,18 +3,17 @@ package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.common.FightPropData; import emu.grasscutter.data.common.FightPropData;
import java.util.ArrayList; import java.util.ArrayList;
import lombok.Getter;
@ResourceType(name = "EquipAffixExcelConfigData.json") @ResourceType(name = "EquipAffixExcelConfigData.json")
public class EquipAffixData extends GameResource { public class EquipAffixData extends GameResource {
private int affixId; private int affixId;
private int id; private int id;
@Getter private int level; private int level;
@Getter private long nameTextMapHash; private long nameTextMapHash;
@Getter private String openConfig; private String openConfig;
@Getter private FightPropData[] addProps; private FightPropData[] addProps;
@Getter private float[] paramList; private float[] paramList;
@Override @Override
public int getId() { public int getId() {
@ -25,9 +24,29 @@ public class EquipAffixData extends GameResource {
return id; return id;
} }
public int getLevel() {
return level;
}
public long getNameTextMapHash() {
return nameTextMapHash;
}
public String getOpenConfig() {
return openConfig;
}
public FightPropData[] getAddProps() {
return addProps;
}
public float[] getParamList() {
return paramList;
}
@Override @Override
public void onLoad() { public void onLoad() {
ArrayList<FightPropData> parsed = new ArrayList<>(getAddProps().length); ArrayList<FightPropData> parsed = new ArrayList<FightPropData>(getAddProps().length);
for (FightPropData prop : getAddProps()) { for (FightPropData prop : getAddProps()) {
if (prop.getPropType() != null && prop.getValue() != 0f) { if (prop.getPropType() != null && prop.getValue() != 0f) {
prop.onLoad(); prop.onLoad();

View File

@ -2,18 +2,21 @@ package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import lombok.Getter;
@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) @ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST)
public class FetterCharacterCardData extends GameResource { public class FetterCharacterCardData extends GameResource {
private int avatarId; private int avatarId;
@Getter private int rewardId; private int rewardId;
@Override @Override
public int getId() { public int getId() {
return avatarId; return avatarId;
} }
public int getRewardId() {
return rewardId;
}
@Override @Override
public void onLoad() {} public void onLoad() {}
} }

View File

@ -4,7 +4,6 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.OpenCondData; import emu.grasscutter.data.common.OpenCondData;
import java.util.List; import java.util.List;
import lombok.Getter;
@ResourceType( @ResourceType(
name = { name = {
@ -16,7 +15,7 @@ import lombok.Getter;
}, },
loadPriority = LoadPriority.HIGHEST) loadPriority = LoadPriority.HIGHEST)
public class FetterData extends GameResource { public class FetterData extends GameResource {
@Getter private int avatarId; private int avatarId;
private int fetterId; private int fetterId;
private List<OpenCondData> openCond; private List<OpenCondData> openCond;
@ -25,6 +24,10 @@ public class FetterData extends GameResource {
return fetterId; return fetterId;
} }
public int getAvatarId() {
return avatarId;
}
public List<OpenCondData> getOpenConds() { public List<OpenCondData> getOpenConds() {
return openCond; return openCond;
} }

View File

@ -1,15 +1,14 @@
package emu.grasscutter.data.excels; package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = "GatherExcelConfigData.json") @ResourceType(name = "GatherExcelConfigData.json")
public class GatherData extends GameResource { public class GatherData extends GameResource {
private int pointType; private int pointType;
private int id; private int id;
@Getter private int gadgetId; private int gadgetId;
@Getter private int itemId; private int itemId;
@Getter private int cd; // Probably hours private int cd; // Probably hours
private boolean isForbidGuest; private boolean isForbidGuest;
private boolean initDisableInteract; private boolean initDisableInteract;
@ -22,6 +21,18 @@ public class GatherData extends GameResource {
return id; return id;
} }
public int getGadgetId() {
return gadgetId;
}
public int getItemId() {
return itemId;
}
public int getCd() {
return cd;
}
public boolean isForbidGuest() { public boolean isForbidGuest() {
return isForbidGuest; return isForbidGuest;
} }

View File

@ -24,7 +24,7 @@ public class ItemData extends GameResource {
@Getter(onMethod_ = @Override) @Getter(onMethod_ = @Override)
private int id; private int id;
private final int stackLimit = 1; private int stackLimit = 1;
private int maxUseCount; private int maxUseCount;
private int rankLevel; private int rankLevel;
private String effectName; private String effectName;
@ -37,7 +37,7 @@ public class ItemData extends GameResource {
private int[] destroyReturnMaterialCount; private int[] destroyReturnMaterialCount;
// Enums // Enums
private final ItemType itemType = ItemType.ITEM_NONE; private ItemType itemType = ItemType.ITEM_NONE;
private MaterialType materialType = MaterialType.MATERIAL_NONE; private MaterialType materialType = MaterialType.MATERIAL_NONE;
private EquipType equipType = EquipType.EQUIP_NONE; private EquipType equipType = EquipType.EQUIP_NONE;
private String effectType; private String effectType;
@ -48,10 +48,10 @@ public class ItemData extends GameResource {
private int[] satiationParams; private int[] satiationParams;
// Usable item // Usable item
private final ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE; private ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE;
private List<ItemUseData> itemUse; private List<ItemUseData> itemUse;
private List<ItemUseAction> itemUseActions; private List<ItemUseAction> itemUseActions;
private final boolean useOnGain = false; private boolean useOnGain = false;
// Relic // Relic
private int mainPropDepotId; private int mainPropDepotId;
@ -79,7 +79,7 @@ public class ItemData extends GameResource {
private int comfort; private int comfort;
private List<Integer> furnType; private List<Integer> furnType;
private List<Integer> furnitureGadgetID; private List<Integer> furnitureGadgetID;
private final SpecialFurnitureType specialFurnitureType = SpecialFurnitureType.NOT_SPECIAL; private SpecialFurnitureType specialFurnitureType = SpecialFurnitureType.NOT_SPECIAL;
@SerializedName( @SerializedName(
value = "roomSceneId", value = "roomSceneId",

View File

@ -39,10 +39,12 @@ public class OpenStateData extends GameResource {
OPEN_STATE_COND_PARENT_QUEST OPEN_STATE_COND_PARENT_QUEST
} }
@Getter
public static class OpenStateCond { public static class OpenStateCond {
@Getter
private OpenStateCondType condType; private OpenStateCondType condType;
@Getter
private int param; private int param;
@Getter
private int param2; private int param2;
} }
} }

View File

@ -9,7 +9,7 @@ public class PlayerLevelData extends GameResource {
private int level; private int level;
private int exp; private int exp;
private int rewardId; private int rewardId;
private final int expeditionLimitAdd = 0; private int expeditionLimitAdd = 0;
private int unlockWorldLevel; private int unlockWorldLevel;
private long unlockDescTextMapHash; private long unlockDescTextMapHash;

View File

@ -25,8 +25,7 @@ public class ProudSkillData extends GameResource {
@Getter private long nameTextMapHash; @Getter private long nameTextMapHash;
@Transient private Iterable<ItemParamData> totalCostItems; @Transient private Iterable<ItemParamData> totalCostItems;
@Transient @Getter @Transient @Getter private Object2FloatMap<String> paramListMap = new Object2FloatOpenHashMap<>();
private final Object2FloatMap<String> paramListMap = new Object2FloatOpenHashMap<>();
@Override @Override
public int getId() { public int getId() {

View File

@ -6,12 +6,11 @@ import emu.grasscutter.game.world.World;
import java.util.*; import java.util.*;
import lombok.Getter; import lombok.Getter;
@Getter
@ResourceType(name = "RefreshPolicyExcelConfigData.json") @ResourceType(name = "RefreshPolicyExcelConfigData.json")
public class RefreshPolicyExcelConfigData extends GameResource { public class RefreshPolicyExcelConfigData extends GameResource {
private int id; @Getter private int id;
private RefreshType type; @Getter private RefreshType type;
private String time; @Getter private String time;
private static int upperBound(List<Integer> list, int low, int high, int value) { private static int upperBound(List<Integer> list, int low, int high, int value) {
while (low < high) { while (low < high) {
@ -49,9 +48,9 @@ public class RefreshPolicyExcelConfigData extends GameResource {
upperBound( upperBound(
params, (int) params.get(0), (int) params.get(params.size() - 1), (int) temp); params, (int) params.get(0), (int) params.get(params.size() - 1), (int) temp);
var upper_bound = params.get(upper_bound_idx); var upper_bound = params.get(upper_bound_idx);
if (params.get(params.size() - 1).equals(upper_bound)) { if (params.get(params.size() - 1) == upper_bound) {
return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7; return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7;
} else if (params.get(0).equals(upper_bound)) { } else if (params.get(0) == upper_bound) {
return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7; return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7;
} }
return (params.get(upper_bound_idx - 1) - params.get(0)); return (params.get(upper_bound_idx - 1) - params.get(0));
@ -65,15 +64,15 @@ public class RefreshPolicyExcelConfigData extends GameResource {
upperBound( upperBound(
params, (int) params.get(0), (int) params.get(params.size() - 1), (int) temp); params, (int) params.get(0), (int) params.get(params.size() - 1), (int) temp);
var upper_bound = params.get(upper_bound_idx); var upper_bound = params.get(upper_bound_idx);
if (params.get(params.size() - 1).equals(upper_bound)) { if (params.get(params.size() - 1) == upper_bound) {
return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7; return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7;
} else if (params.get(0).equals(upper_bound)) { } else if (params.get(0) == upper_bound) {
return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7; return (params.get(params.size() - 1) - params.get(0)) + 60 * 60 * 24 * 7;
} }
return (params.get(upper_bound_idx - 1) - params.get(0)); return (params.get(upper_bound_idx - 1) - params.get(0));
} }
case REFRESH_DAYBEGIN_INTERVAL: case REFRESH_DAYBEGIN_INTERVAL:
if (params.isEmpty()) return -1; if (params.size() == 0) return -1;
return params.get(0) * 60 * 60 * 24; return params.get(0) * 60 * 60 * 24;
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -3,18 +3,21 @@ package emu.grasscutter.data.excels;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import java.util.List; import java.util.List;
import lombok.Getter;
@ResourceType(name = "RewardExcelConfigData.json") @ResourceType(name = "RewardExcelConfigData.json")
public class RewardData extends GameResource { public class RewardData extends GameResource {
public int rewardId; public int rewardId;
@Getter public List<ItemParamData> rewardItemList; public List<ItemParamData> rewardItemList;
@Override @Override
public int getId() { public int getId() {
return rewardId; return rewardId;
} }
public List<ItemParamData> getRewardItemList() {
return rewardItemList;
}
@Override @Override
public void onLoad() { public void onLoad() {
rewardItemList = rewardItemList.stream().filter(i -> i.getId() > 0).toList(); rewardItemList = rewardItemList.stream().filter(i -> i.getId() > 0).toList();

View File

@ -8,7 +8,7 @@ import lombok.Getter;
@ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH) @ResourceType(name = "RewardPreviewExcelConfigData.json", loadPriority = LoadPriority.HIGH)
public class RewardPreviewData extends GameResource { public class RewardPreviewData extends GameResource {
@Getter(onMethod = @__(@Override)) @Getter(onMethod_ = @Override)
private int id; private int id;
private ItemParamStringData[] previewItems; private ItemParamStringData[] previewItems;
@ -25,7 +25,7 @@ public class RewardPreviewData extends GameResource {
Arrays.stream(this.previewItems) Arrays.stream(this.previewItems)
.filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty()) .filter(d -> d.getId() > 0 && d.getCount() != null && !d.getCount().isEmpty())
.map(ItemParamStringData::toItemParamData) .map(ItemParamStringData::toItemParamData)
.toArray(ItemParamData[]::new); .toArray(size -> new ItemParamData[size]);
} else { } else {
this.previewItemsArray = new ItemParamData[0]; this.previewItemsArray = new ItemParamData[0];
} }

View File

@ -5,27 +5,25 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.game.shop.ShopInfo; import emu.grasscutter.game.shop.ShopInfo;
import java.util.List; import java.util.List;
import lombok.Getter;
@ResourceType(name = "ShopGoodsExcelConfigData.json") @ResourceType(name = "ShopGoodsExcelConfigData.json")
public class ShopGoodsData extends GameResource { public class ShopGoodsData extends GameResource {
@Getter private int goodsId; private int goodsId;
@Getter private int shopType; private int shopType;
@Getter private int itemId; private int itemId;
@Getter private int itemCount; private int itemCount;
@Getter private int costScoin; private int costScoin;
@Getter private int costHcoin; private int costHcoin;
@Getter private int costMcoin; private int costMcoin;
@Getter private List<ItemParamData> costItems; private List<ItemParamData> costItems;
@Getter private int minPlayerLevel; private int minPlayerLevel;
@Getter private int maxPlayerLevel; private int maxPlayerLevel;
@Getter private int buyLimit; private int buyLimit;
@Getter
@SerializedName( @SerializedName(
value = "subTabId", value = "subTabId",
alternate = {"secondarySheetId"}) alternate = {"secondarySheetId"})
@ -34,7 +32,7 @@ public class ShopGoodsData extends GameResource {
private String refreshType; private String refreshType;
private transient ShopInfo.ShopRefreshType refreshTypeEnum; private transient ShopInfo.ShopRefreshType refreshTypeEnum;
@Getter private int refreshParam; private int refreshParam;
@Override @Override
public void onLoad() { public void onLoad() {
@ -55,7 +53,59 @@ public class ShopGoodsData extends GameResource {
return getGoodsId(); return getGoodsId();
} }
public int getGoodsId() {
return goodsId;
}
public int getShopType() {
return shopType;
}
public int getItemId() {
return itemId;
}
public int getItemCount() {
return itemCount;
}
public int getCostScoin() {
return costScoin;
}
public int getCostHcoin() {
return costHcoin;
}
public int getCostMcoin() {
return costMcoin;
}
public List<ItemParamData> getCostItems() {
return costItems;
}
public int getMinPlayerLevel() {
return minPlayerLevel;
}
public int getMaxPlayerLevel() {
return maxPlayerLevel;
}
public int getBuyLimit() {
return buyLimit;
}
public int getSubTabId() {
return subTabId;
}
public ShopInfo.ShopRefreshType getRefreshType() { public ShopInfo.ShopRefreshType getRefreshType() {
return refreshTypeEnum; return refreshTypeEnum;
} }
public int getRefreshParam() {
return refreshParam;
}
} }

View File

@ -4,15 +4,13 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import lombok.*; import lombok.*;
@Setter
@Getter
@ResourceType(name = "StatuePromoteExcelConfigData.json") @ResourceType(name = "StatuePromoteExcelConfigData.json")
public class StatuePromoteData extends GameResource { public class StatuePromoteData extends GameResource {
private int level; @Getter @Setter private int level;
private int cityId; @Getter @Setter private int cityId;
private ItemParamData[] costItems; @Getter @Setter private ItemParamData[] costItems;
private int[] rewardIdList; @Getter @Setter private int[] rewardIdList;
private int stamina; @Getter @Setter private int stamina;
@Override @Override
public int getId() { public int getId() {

View File

@ -14,7 +14,7 @@ public class AchievementData extends GameResource {
private static final AtomicBoolean isDivided = new AtomicBoolean(); private static final AtomicBoolean isDivided = new AtomicBoolean();
private int goalId; private int goalId;
private int preStageAchievementId; private int preStageAchievementId;
private final Set<Integer> groupAchievementIdList = new HashSet<>(); private Set<Integer> groupAchievementIdList = new HashSet<>();
private boolean isParent; private boolean isParent;
private long titleTextMapHash; private long titleTextMapHash;
private long descTextMapHash; private long descTextMapHash;

View File

@ -15,10 +15,9 @@ public class ActivityCondExcelConfigData extends GameResource {
LogicType condComb; LogicType condComb;
List<ActivityConfigCondition> cond; List<ActivityConfigCondition> cond;
@Getter
public static class ActivityConfigCondition { public static class ActivityConfigCondition {
private ActivityConditions type; @Getter private ActivityConditions type;
private List<Integer> param; @Getter private List<Integer> param;
public int[] paramArray() { public int[] paramArray() {
return param.stream().mapToInt(Integer::intValue).toArray(); return param.stream().mapToInt(Integer::intValue).toArray();

View File

@ -5,12 +5,11 @@ import emu.grasscutter.game.shop.ShopType;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
@Getter
@ResourceType(name = "ActivityShopOverallExcelConfigData.json") @ResourceType(name = "ActivityShopOverallExcelConfigData.json")
public class ActivityShopData extends GameResource { public class ActivityShopData extends GameResource {
private int scheduleId; @Getter private int scheduleId;
private ShopType shopType; @Getter private ShopType shopType;
private List<Integer> sheetList; @Getter private List<Integer> sheetList;
@Override @Override
public int getId() { public int getId() {

View File

@ -2,22 +2,33 @@ package emu.grasscutter.data.excels.avatar;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = "AvatarCostumeExcelConfigData.json") @ResourceType(name = "AvatarCostumeExcelConfigData.json")
public class AvatarCostumeData extends GameResource { public class AvatarCostumeData extends GameResource {
@SerializedName(value = "skinId", alternate = "costumeId") @SerializedName(value = "skinId", alternate = "costumeId")
private int skinId; private int skinId;
@Getter private int itemId; private int itemId;
@Getter private int characterId; private int characterId;
@Getter private int quality; private int quality;
@Override @Override
public int getId() { public int getId() {
return this.skinId; return this.skinId;
} }
public int getItemId() {
return this.itemId;
}
public int getCharacterId() {
return characterId;
}
public int getQuality() {
return quality;
}
@Override @Override
public void onLoad() { public void onLoad() {
GameData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this); GameData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this);

View File

@ -4,11 +4,10 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.common.CurveInfo; import emu.grasscutter.data.common.CurveInfo;
import java.util.*; import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
import lombok.Getter;
@ResourceType(name = "AvatarCurveExcelConfigData.json") @ResourceType(name = "AvatarCurveExcelConfigData.json")
public class AvatarCurveData extends GameResource { public class AvatarCurveData extends GameResource {
@Getter private int level; private int level;
private CurveInfo[] curveInfos; private CurveInfo[] curveInfos;
private Map<String, Float> curveInfoMap; private Map<String, Float> curveInfoMap;
@ -18,6 +17,10 @@ public class AvatarCurveData extends GameResource {
return this.level; return this.level;
} }
public int getLevel() {
return level;
}
public Map<String, Float> getCurveInfos() { public Map<String, Float> getCurveInfos() {
return curveInfoMap; return curveInfoMap;
} }

View File

@ -55,7 +55,7 @@ public class AvatarData extends GameResource {
@Getter @Getter
private IntList abilities; private IntList abilities;
@Getter @Getter
private final List<String> abilitieNames = new ArrayList<>(); private List<String> abilitieNames = new ArrayList<>();
@Getter @Getter
private List<Integer> fetters; private List<Integer> fetters;

View File

@ -1,18 +1,21 @@
package emu.grasscutter.data.excels.avatar; package emu.grasscutter.data.excels.avatar;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = "AvatarFlycloakExcelConfigData.json") @ResourceType(name = "AvatarFlycloakExcelConfigData.json")
public class AvatarFlycloakData extends GameResource { public class AvatarFlycloakData extends GameResource {
private int flycloakId; private int flycloakId;
@Getter private long nameTextMapHash; private long nameTextMapHash;
@Override @Override
public int getId() { public int getId() {
return this.flycloakId; return this.flycloakId;
} }
public long getNameTextMapHash() {
return nameTextMapHash;
}
@Override @Override
public void onLoad() {} public void onLoad() {}
} }

View File

@ -1,9 +1,7 @@
package emu.grasscutter.data.excels.avatar; package emu.grasscutter.data.excels.avatar;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@Getter
@ResourceType(name = "AvatarLevelExcelConfigData.json") @ResourceType(name = "AvatarLevelExcelConfigData.json")
public class AvatarLevelData extends GameResource { public class AvatarLevelData extends GameResource {
private int level; private int level;
@ -13,4 +11,12 @@ public class AvatarLevelData extends GameResource {
public int getId() { public int getId() {
return this.level; return this.level;
} }
public int getLevel() {
return level;
}
public int getExp() {
return exp;
}
} }

View File

@ -3,28 +3,51 @@ package emu.grasscutter.data.excels.avatar;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.common.*; import emu.grasscutter.data.common.*;
import java.util.ArrayList; import java.util.ArrayList;
import lombok.Getter;
@ResourceType(name = "AvatarPromoteExcelConfigData.json") @ResourceType(name = "AvatarPromoteExcelConfigData.json")
public class AvatarPromoteData extends GameResource { public class AvatarPromoteData extends GameResource {
@Getter private int avatarPromoteId; private int avatarPromoteId;
@Getter private int promoteLevel; private int promoteLevel;
private int scoinCost; private int scoinCost;
@Getter private ItemParamData[] costItems; private ItemParamData[] costItems;
@Getter private int unlockMaxLevel; private int unlockMaxLevel;
@Getter private FightPropData[] addProps; private FightPropData[] addProps;
@Getter private int requiredPlayerLevel; private int requiredPlayerLevel;
@Override @Override
public int getId() { public int getId() {
return (avatarPromoteId << 8) + promoteLevel; return (avatarPromoteId << 8) + promoteLevel;
} }
public int getAvatarPromoteId() {
return avatarPromoteId;
}
public int getPromoteLevel() {
return promoteLevel;
}
public ItemParamData[] getCostItems() {
return costItems;
}
public int getCoinCost() { public int getCoinCost() {
return scoinCost; return scoinCost;
} }
public FightPropData[] getAddProps() {
return addProps;
}
public int getUnlockMaxLevel() {
return unlockMaxLevel;
}
public int getRequiredPlayerLevel() {
return requiredPlayerLevel;
}
@Override @Override
public void onLoad() { public void onLoad() {
// Trim item params // Trim item params

View File

@ -52,7 +52,7 @@ public class AvatarSkillDepotData extends GameResource {
this.elementType = ElementType.None; this.elementType = ElementType.None;
} }
// Set embryo abilities (if player skill depot) // Set embryo abilities (if player skill depot)
if (getSkillDepotAbilityGroup() != null && !getSkillDepotAbilityGroup().isEmpty()) { if (getSkillDepotAbilityGroup() != null && getSkillDepotAbilityGroup().length() > 0) {
AvatarConfig config = GameDepot.getPlayerAbilities().get(getSkillDepotAbilityGroup()); AvatarConfig config = GameDepot.getPlayerAbilities().get(getSkillDepotAbilityGroup());
if (config != null) { if (config != null) {
@ -67,7 +67,7 @@ public class AvatarSkillDepotData extends GameResource {
Optional.ofNullable(this.talents) Optional.ofNullable(this.talents)
.map(talents -> talents.get(0)) .map(talents -> talents.get(0))
.map(i -> GameData.getAvatarTalentDataMap().get((int) i)) .map(i -> GameData.getAvatarTalentDataMap().get((int) i))
.map(AvatarTalentData::getMainCostItemId) .map(talentData -> talentData.getMainCostItemId())
.ifPresent(itemId -> this.talentCostItemId = itemId); .ifPresent(itemId -> this.talentCostItemId = itemId);
} }

View File

@ -4,19 +4,18 @@ import emu.grasscutter.data.*;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.FightPropData; import emu.grasscutter.data.common.FightPropData;
import java.util.ArrayList; import java.util.ArrayList;
import lombok.Getter;
@ResourceType(name = "AvatarTalentExcelConfigData.json", loadPriority = LoadPriority.HIGHEST) @ResourceType(name = "AvatarTalentExcelConfigData.json", loadPriority = LoadPriority.HIGHEST)
public class AvatarTalentData extends GameResource { public class AvatarTalentData extends GameResource {
private int talentId; private int talentId;
private int prevTalent; private int prevTalent;
@Getter private long nameTextMapHash; private long nameTextMapHash;
@Getter private String icon; private String icon;
@Getter private int mainCostItemId; private int mainCostItemId;
@Getter private int mainCostItemCount; private int mainCostItemCount;
@Getter private String openConfig; private String openConfig;
@Getter private FightPropData[] addProps; private FightPropData[] addProps;
@Getter private float[] paramList; private float[] paramList;
@Override @Override
public int getId() { public int getId() {
@ -27,9 +26,37 @@ public class AvatarTalentData extends GameResource {
return prevTalent; return prevTalent;
} }
public long getNameTextMapHash() {
return nameTextMapHash;
}
public String getIcon() {
return icon;
}
public int getMainCostItemId() {
return mainCostItemId;
}
public int getMainCostItemCount() {
return mainCostItemCount;
}
public String getOpenConfig() {
return openConfig;
}
public FightPropData[] getAddProps() {
return addProps;
}
public float[] getParamList() {
return paramList;
}
@Override @Override
public void onLoad() { public void onLoad() {
ArrayList<FightPropData> parsed = new ArrayList<>(getAddProps().length); ArrayList<FightPropData> parsed = new ArrayList<FightPropData>(getAddProps().length);
for (FightPropData prop : getAddProps()) { for (FightPropData prop : getAddProps()) {
if (prop.getPropType() != null || prop.getValue() == 0f) { if (prop.getPropType() != null || prop.getValue() == 0f) {
prop.onLoad(); prop.onLoad();

View File

@ -1,15 +1,25 @@
package emu.grasscutter.data.excels.codex; package emu.grasscutter.data.excels.codex;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@Getter
@ResourceType(name = {"MaterialCodexExcelConfigData.json"}) @ResourceType(name = {"MaterialCodexExcelConfigData.json"})
public class CodexMaterialData extends GameResource { public class CodexMaterialData extends GameResource {
private int Id; private int Id;
private int materialId; private int materialId;
private int sortOrder; private int sortOrder;
public int getSortOrder() {
return sortOrder;
}
public int getMaterialId() {
return materialId;
}
public int getId() {
return Id;
}
@Override @Override
public void onLoad() { public void onLoad() {
GameData.getCodexMaterialDataIdMap().put(this.getMaterialId(), this); GameData.getCodexMaterialDataIdMap().put(this.getMaterialId(), this);

View File

@ -1,16 +1,31 @@
package emu.grasscutter.data.excels.codex; package emu.grasscutter.data.excels.codex;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = {"QuestCodexExcelConfigData.json"}) @ResourceType(name = {"QuestCodexExcelConfigData.json"})
public class CodexQuestData extends GameResource { public class CodexQuestData extends GameResource {
@Getter private int Id; private int Id;
@Getter private int parentQuestId; private int parentQuestId;
@Getter private int chapterId; private int chapterId;
@Getter private int sortOrder; private int sortOrder;
private boolean isDisuse; private boolean isDisuse;
public int getParentQuestId() {
return parentQuestId;
}
public int getId() {
return Id;
}
public int getChapterId() {
return chapterId;
}
public int getSortOrder() {
return sortOrder;
}
public boolean getIsDisuse() { public boolean getIsDisuse() {
return isDisuse; return isDisuse;
} }

View File

@ -1,19 +1,30 @@
package emu.grasscutter.data.excels.codex; package emu.grasscutter.data.excels.codex;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = {"WeaponCodexExcelConfigData.json"}) @ResourceType(name = {"WeaponCodexExcelConfigData.json"})
public class CodexWeaponData extends GameResource { public class CodexWeaponData extends GameResource {
@Getter private int Id; private int Id;
@Getter private int weaponId; private int weaponId;
private int gadgetId; private int gadgetId;
@Getter private int sortOrder; private int sortOrder;
public int getSortOrder() {
return sortOrder;
}
public int getWeaponId() {
return weaponId;
}
public int getGadgetId() { public int getGadgetId() {
return weaponId; return weaponId;
} }
public int getId() {
return Id;
}
@Override @Override
public void onLoad() { public void onLoad() {
GameData.getCodexWeaponDataIdMap().put(this.getWeaponId(), this); GameData.getCodexWeaponDataIdMap().put(this.getWeaponId(), this);

View File

@ -9,7 +9,7 @@ import lombok.Getter;
@Getter @Getter
@ResourceType(name = "DungeonChallengeConfigData.json") @ResourceType(name = "DungeonChallengeConfigData.json")
public class DungeonChallengeConfigData extends GameResource { public class DungeonChallengeConfigData extends GameResource {
@Getter private int id; private int id;
private ChallengeType challengeType; private ChallengeType challengeType;
private boolean noSuccessHint; private boolean noSuccessHint;
private boolean noFailHint; private boolean noFailHint;
@ -42,6 +42,10 @@ public class DungeonChallengeConfigData extends GameResource {
alternate = {"NJBJIKAIENN"}) alternate = {"NJBJIKAIENN"})
private AllowAnimationType animationOnSubFail; private AllowAnimationType animationOnSubFail;
public int getId() {
return id;
}
public enum InterruptButtonType { public enum InterruptButtonType {
INTERRUPT_BUTTON_TYPE_NONE, INTERRUPT_BUTTON_TYPE_NONE,
INTERRUPT_BUTTON_TYPE_HOST, INTERRUPT_BUTTON_TYPE_HOST,

View File

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

View File

@ -11,32 +11,32 @@ import javax.annotation.*;
import lombok.*; import lombok.*;
import lombok.experimental.FieldDefaults; import lombok.experimental.FieldDefaults;
@Getter
@ResourceType(name = "QuestExcelConfigData.json") @ResourceType(name = "QuestExcelConfigData.json")
@Getter
@ToString @ToString
public class QuestData extends GameResource { public class QuestData extends GameResource {
private int subId; @Getter private int subId;
private int mainId; @Getter private int mainId;
private int order; @Getter private int order;
private long descTextMapHash; @Getter private long descTextMapHash;
private boolean finishParent; @Getter private boolean finishParent;
private boolean isRewind; @Getter private boolean isRewind;
private LogicType acceptCondComb; @Getter private LogicType acceptCondComb;
private LogicType finishCondComb; @Getter private LogicType finishCondComb;
private LogicType failCondComb; @Getter private LogicType failCondComb;
private List<QuestAcceptCondition> acceptCond; @Getter private List<QuestAcceptCondition> acceptCond;
private List<QuestContentCondition> finishCond; @Getter private List<QuestContentCondition> finishCond;
private List<QuestContentCondition> failCond; @Getter private List<QuestContentCondition> failCond;
private List<QuestExecParam> beginExec; @Getter private List<QuestExecParam> beginExec;
private List<QuestExecParam> finishExec; @Getter private List<QuestExecParam> finishExec;
private List<QuestExecParam> failExec; @Getter private List<QuestExecParam> failExec;
private Guide guide; @Getter private Guide guide;
private List<Integer> trialAvatarList; @Getter private List<Integer> trialAvatarList;
private List<ItemParamData> gainItems; @Getter private List<ItemParamData> gainItems;
public static String questConditionKey( public static String questConditionKey(
@Nonnull Enum<?> type, int firstParam, @Nullable String paramsStr) { @Nonnull Enum<?> type, int firstParam, @Nullable String paramsStr) {

View File

@ -8,7 +8,7 @@ import lombok.Getter;
@ResourceType(name = "ReliquaryMainPropExcelConfigData.json") @ResourceType(name = "ReliquaryMainPropExcelConfigData.json")
@Getter @Getter
public class ReliquaryMainPropData extends GameResource { public class ReliquaryMainPropData extends GameResource {
@Getter(onMethod = @__(@Override)) @Getter(onMethod_ = @Override)
private int id; private int id;
private int propDepotId; private int propDepotId;

View File

@ -2,14 +2,12 @@ package emu.grasscutter.data.excels.reliquary;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = "ReliquarySetExcelConfigData.json") @ResourceType(name = "ReliquarySetExcelConfigData.json")
public class ReliquarySetData extends GameResource { public class ReliquarySetData extends GameResource {
private int setId; private int setId;
@Getter private int[] setNeedNum; private int[] setNeedNum;
@Getter
@SerializedName( @SerializedName(
value = "equipAffixId", value = "equipAffixId",
alternate = {"EquipAffixId"}) alternate = {"EquipAffixId"})
@ -20,6 +18,14 @@ public class ReliquarySetData extends GameResource {
return setId; return setId;
} }
public int[] getSetNeedNum() {
return setNeedNum;
}
public int getEquipAffixId() {
return equipAffixId;
}
@Override @Override
public void onLoad() {} public void onLoad() {}
} }

View File

@ -9,7 +9,7 @@ import lombok.Getter;
@ResourceType(name = "SceneExcelConfigData.json") @ResourceType(name = "SceneExcelConfigData.json")
@Getter @Getter
public final class SceneData extends GameResource { public final class SceneData extends GameResource {
@Getter(onMethod = @__(@Override)) @Getter(onMethod_ = @Override)
private int id; private int id;
@SerializedName("type") @SerializedName("type")

View File

@ -8,7 +8,7 @@ import lombok.Getter;
@ResourceType(name = "SceneTagConfigData.json") @ResourceType(name = "SceneTagConfigData.json")
@Getter @Getter
public final class SceneTagData extends GameResource { public final class SceneTagData extends GameResource {
@Getter(onMethod = @__(@Override)) @Getter(onMethod_ = @Override)
private int id; private int id;
@SerializedName("DJCOAOBDIHP") @SerializedName("DJCOAOBDIHP")

View File

@ -30,8 +30,8 @@ public class TowerLevelData extends GameResource {
// Just packaging condition parameters for convenience. // Just packaging condition parameters for convenience.
@Getter @Getter
public class TowerCondTimeParams { public class TowerCondTimeParams {
private final int param1; private int param1;
private final int minimumTimeInSeconds; private int minimumTimeInSeconds;
public TowerCondTimeParams(int param1, int minimumTimeInSeconds) { public TowerCondTimeParams(int param1, int minimumTimeInSeconds) {
this.param1 = param1; this.param1 = param1;
@ -41,9 +41,9 @@ public class TowerLevelData extends GameResource {
@Getter @Getter
public class TowerCondHpParams { public class TowerCondHpParams {
private final int sceneId; private int sceneId;
private final int configId; private int configId;
private final int minimumHpPercentage; private int minimumHpPercentage;
public TowerCondHpParams(int sceneId, int configId, int minimumHpPercentage) { public TowerCondHpParams(int sceneId, int configId, int minimumHpPercentage) {
this.sceneId = sceneId; this.sceneId = sceneId;

View File

@ -2,9 +2,7 @@ package emu.grasscutter.data.excels.tower;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import java.util.List; import java.util.List;
import lombok.Getter;
@Getter
@ResourceType(name = "TowerScheduleExcelConfigData.json") @ResourceType(name = "TowerScheduleExcelConfigData.json")
public class TowerScheduleData extends GameResource { public class TowerScheduleData extends GameResource {
private int scheduleId; private int scheduleId;
@ -21,11 +19,30 @@ public class TowerScheduleData extends GameResource {
public void onLoad() { public void onLoad() {
super.onLoad(); super.onLoad();
this.schedules = this.schedules =
this.schedules.stream().filter(item -> !item.getFloorList().isEmpty()).toList(); this.schedules.stream().filter(item -> item.getFloorList().size() > 0).toList();
}
public int getScheduleId() {
return scheduleId;
}
public List<Integer> getEntranceFloorId() {
return entranceFloorId;
}
public List<ScheduleDetail> getSchedules() {
return schedules;
}
public int getMonthlyLevelConfigId() {
return monthlyLevelConfigId;
} }
@Getter
public static class ScheduleDetail { public static class ScheduleDetail {
private List<Integer> floorList; private List<Integer> floorList;
public List<Integer> getFloorList() {
return floorList;
}
} }
} }

View File

@ -10,7 +10,7 @@ import lombok.experimental.FieldDefaults;
@Data @Data
@FieldDefaults(level = AccessLevel.PRIVATE) @FieldDefaults(level = AccessLevel.PRIVATE)
public class TrialAvatarActivityDataData extends GameResource { public class TrialAvatarActivityDataData extends GameResource {
@Getter(onMethod = @__({@Override})) @Getter(onMethod_ = @Override)
private int id; private int id;
private int trialAvatarIndexId; private int trialAvatarIndexId;

View File

@ -1,9 +1,7 @@
package emu.grasscutter.data.excels.weapon; package emu.grasscutter.data.excels.weapon;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@Getter
@ResourceType(name = "WeaponLevelExcelConfigData.json") @ResourceType(name = "WeaponLevelExcelConfigData.json")
public class WeaponLevelData extends GameResource { public class WeaponLevelData extends GameResource {
private int level; private int level;
@ -13,4 +11,12 @@ public class WeaponLevelData extends GameResource {
public int getId() { public int getId() {
return this.level; return this.level;
} }
public int getLevel() {
return level;
}
public int[] getRequiredExps() {
return requiredExps;
}
} }

View File

@ -3,9 +3,7 @@ package emu.grasscutter.data.excels.weapon;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import emu.grasscutter.data.common.*; import emu.grasscutter.data.common.*;
import java.util.ArrayList; import java.util.ArrayList;
import lombok.Getter;
@Getter
@ResourceType(name = "WeaponPromoteExcelConfigData.json") @ResourceType(name = "WeaponPromoteExcelConfigData.json")
public class WeaponPromoteData extends GameResource { public class WeaponPromoteData extends GameResource {
@ -22,6 +20,34 @@ public class WeaponPromoteData extends GameResource {
return (weaponPromoteId << 8) + promoteLevel; return (weaponPromoteId << 8) + promoteLevel;
} }
public int getWeaponPromoteId() {
return weaponPromoteId;
}
public int getPromoteLevel() {
return promoteLevel;
}
public ItemParamData[] getCostItems() {
return costItems;
}
public int getCoinCost() {
return coinCost;
}
public FightPropData[] getAddProps() {
return addProps;
}
public int getUnlockMaxLevel() {
return unlockMaxLevel;
}
public int getRequiredPlayerLevel() {
return requiredPlayerLevel;
}
@Override @Override
public void onLoad() { public void onLoad() {
// Trim item params // Trim item params

View File

@ -4,20 +4,19 @@ import emu.grasscutter.data.*;
import emu.grasscutter.game.props.ClimateType; import emu.grasscutter.game.props.ClimateType;
import lombok.Getter; import lombok.Getter;
@Getter
@ResourceType(name = "WeatherExcelConfigData.json") @ResourceType(name = "WeatherExcelConfigData.json")
public class WeatherData extends GameResource { public class WeatherData extends GameResource {
private int areaID; @Getter private int areaID;
private int weatherAreaId; @Getter private int weatherAreaId;
private String maxHeightStr; @Getter private String maxHeightStr;
private int gadgetID; @Getter private int gadgetID;
private boolean isDefaultValid; @Getter private boolean isDefaultValid;
private String templateName; @Getter private String templateName;
private int priority; @Getter private int priority;
private String profileName; @Getter private String profileName;
private ClimateType defaultClimate; @Getter private ClimateType defaultClimate;
private boolean isUseDefault; @Getter private boolean isUseDefault;
private int sceneID; @Getter private int sceneID;
@Override @Override
public int getId() { public int getId() {

View File

@ -1,18 +1,21 @@
package emu.grasscutter.data.excels.world; package emu.grasscutter.data.excels.world;
import emu.grasscutter.data.*; import emu.grasscutter.data.*;
import lombok.Getter;
@ResourceType(name = "WorldLevelExcelConfigData.json") @ResourceType(name = "WorldLevelExcelConfigData.json")
public class WorldLevelData extends GameResource { public class WorldLevelData extends GameResource {
private int level; private int level;
@Getter private int monsterLevel; private int monsterLevel;
@Override @Override
public int getId() { public int getId() {
return this.level; return this.level;
} }
public int getMonsterLevel() {
return monsterLevel;
}
@Override @Override
public void onLoad() {} public void onLoad() {}
} }

View File

@ -6,18 +6,12 @@ import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.world.*; import emu.grasscutter.game.world.*;
import emu.grasscutter.scripts.SceneIndexManager; import emu.grasscutter.scripts.SceneIndexManager;
import java.util.*; import java.util.*;
import lombok.Getter;
public class Grid { public class Grid {
public transient RTree<Map.Entry<GridPosition, Set<Integer>>, Geometry> gridOptimized = null; public transient RTree<Map.Entry<GridPosition, Set<Integer>>, Geometry> gridOptimized = null;
private final transient Set<Integer> nearbyGroups = new HashSet<>(100); private transient Set<Integer> nearbyGroups = new HashSet<>(100);
/** public Map<GridPosition, Set<Integer>> grid = new LinkedHashMap<>();
* -- GETTER --
*
* @return The correctly loaded grid map.
*/
@Getter public Map<GridPosition, Set<Integer>> grid = new LinkedHashMap<>();
/** Creates an optimized cache of the grid. */ /** Creates an optimized cache of the grid. */
private void optimize() { private void optimize() {
@ -29,6 +23,13 @@ public class Grid {
} }
} }
/**
* @return The correctly loaded grid map.
*/
public Map<GridPosition, Set<Integer>> getGrid() {
return this.grid;
}
public Set<Integer> getNearbyGroups(int vision_level, Position position) { public Set<Integer> getNearbyGroups(int vision_level, Position position) {
this.optimize(); // Check to see if the grid is optimized. this.optimize(); // Check to see if the grid is optimized.

View File

@ -550,7 +550,7 @@ public final class DatabaseHelper {
.first(); .first();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Grasscutter.getLogger() Grasscutter.getLogger()
.debug("Error occurred while getting uid {}'s achievement data", uid, e); .debug("Error occurred while getting uid " + uid + "'s achievement data", e);
DatabaseManager.getGameDatabase().getCollection("achievements").deleteMany(eq("uid", uid)); DatabaseManager.getGameDatabase().getCollection("achievements").deleteMany(eq("uid", uid));
return null; return null;
} }

View File

@ -11,12 +11,15 @@ import dev.morphia.query.experimental.filters.Filters;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerRunMode; import emu.grasscutter.Grasscutter.ServerRunMode;
import emu.grasscutter.game.Account; import emu.grasscutter.game.Account;
import lombok.Getter;
public final class DatabaseManager { public final class DatabaseManager {
@Getter private static Datastore gameDatastore; private static Datastore gameDatastore;
private static Datastore dispatchDatastore; private static Datastore dispatchDatastore;
public static Datastore getGameDatastore() {
return gameDatastore;
}
public static Datastore getAccountDatastore() { public static Datastore getAccountDatastore() {
if (Grasscutter.getRunMode() == ServerRunMode.HYBRID) return gameDatastore; if (Grasscutter.getRunMode() == ServerRunMode.HYBRID) return gameDatastore;
else return dispatchDatastore; else return dispatchDatastore;

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