mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-08-04 20:51:49 +00:00
Compare commits
4 Commits
developmen
...
72f0c15108
Author | SHA1 | Date | |
---|---|---|---|
72f0c15108 | |||
d5b5e93522 | |||
60e713f4ff | |||
e1e0bb6928 |
51
.github/workflows/build_container.yml
vendored
51
.github/workflows/build_container.yml
vendored
@ -1,51 +0,0 @@
|
|||||||
name: Build Docker Container
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch: ~
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Project
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Generate Docker Meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
id: meta
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository }}
|
|
||||||
tags: |
|
|
||||||
type=ref,event=branch
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=semver,pattern={{major}}
|
|
||||||
type=sha
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Setup Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3.1.0
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3.0.0
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and Push Docker image
|
|
||||||
uses: docker/build-push-action@v5.2.0
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -64,7 +64,6 @@ tmp/
|
|||||||
|
|
||||||
/*.jar
|
/*.jar
|
||||||
/*.sh
|
/*.sh
|
||||||
!entrypoint.sh
|
|
||||||
|
|
||||||
GM Handbook*.txt
|
GM Handbook*.txt
|
||||||
handbook.html
|
handbook.html
|
||||||
|
14
Dockerfile
14
Dockerfile
@ -1,14 +1,11 @@
|
|||||||
# Builder
|
FROM gradle:8.5.0-jdk17-alpine as builder
|
||||||
FROM gradle:jdk17-alpine as builder
|
|
||||||
|
|
||||||
RUN apk add --update nodejs npm
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY ./ /app/
|
COPY ./ /app/
|
||||||
|
|
||||||
RUN gradle jar --no-daemon
|
RUN gradle jar --no-daemon
|
||||||
|
|
||||||
# Fetch Data
|
|
||||||
FROM bitnami/git:2.43.0-debian-11-r1 as data
|
FROM bitnami/git:2.43.0-debian-11-r1 as data
|
||||||
|
|
||||||
ARG DATA_REPOSITORY=https://gitlab.com/YuukiPS/GC-Resources.git
|
ARG DATA_REPOSITORY=https://gitlab.com/YuukiPS/GC-Resources.git
|
||||||
@ -18,13 +15,14 @@ WORKDIR /app
|
|||||||
|
|
||||||
RUN git clone --branch ${DATA_BRANCH} --depth 1 ${DATA_REPOSITORY}
|
RUN git clone --branch ${DATA_BRANCH} --depth 1 ${DATA_REPOSITORY}
|
||||||
|
|
||||||
# Result Container
|
FROM bitnami/java:21.0.1-12
|
||||||
FROM amazoncorretto:17-alpine
|
|
||||||
|
RUN apt-get update && apt-get install unzip
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy built assets
|
# Copy built assets
|
||||||
COPY --from=builder /app/grasscutter-*.jar /app/grasscutter.jar
|
COPY --from=builder /app/grasscutter-1.7.4.jar /app/grasscutter.jar
|
||||||
COPY --from=builder /app/keystore.p12 /app/keystore.p12
|
COPY --from=builder /app/keystore.p12 /app/keystore.p12
|
||||||
|
|
||||||
# Copy the resources
|
# Copy the resources
|
||||||
|
15
README.md
15
README.md
@ -18,24 +18,15 @@
|
|||||||
* 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).
|
||||||
|
|
||||||
### Quick Start (automatic)
|
### Quick Start (automatic)
|
||||||
|
|
||||||
- Get [Java 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
|
- Get Java 17: https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
|
||||||
- Get [MongoDB Community Server](https://www.mongodb.com/try/download/community)
|
- Get [MongoDB Community Server](https://www.mongodb.com/try/download/community)
|
||||||
- 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 (4.0.x client can be found here if you don't have it): https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/4.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)
|
|
||||||
- ***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.
|
||||||
@ -47,7 +38,7 @@ Grasscutter has not been actively maintained and currently (as of January 12th,
|
|||||||
|
|
||||||
- Click the small button next to launch.
|
- Click the small button next to launch.
|
||||||
- Click the launch button.
|
- Click the launch button.
|
||||||
- Log in with whatever username you want. Password can be anything.
|
- Log in with whatever username you want. Password doesn't matter.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
|
30
docker-compose.yml
Normal file
30
docker-compose.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
grasscutter:
|
||||||
|
image: grasscutter:latest
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080"
|
||||||
|
- "8888:8888"
|
||||||
|
- "22102:22102"
|
||||||
|
environment:
|
||||||
|
DATABASE_INFO_SERVER_CONNECTION_URI: "mongodb://lawnmower:grasscutter@database:27017"
|
||||||
|
DATABASE_INFO_SERVER_COLLECTION: grasscutter
|
||||||
|
DATABASE_INFO_GAME_CONNECTION_URI: "mongodb://lawnmower:grasscutter@database:27017"
|
||||||
|
DATABASE_INFO_GAME_COLLECTION: grasscutter
|
||||||
|
|
||||||
|
stdin_open: true
|
||||||
|
|
||||||
|
database:
|
||||||
|
image: mongo:7.0.4
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: lawnmower
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: grasscutter
|
||||||
|
MONGO_INITDB_DATABASE: grasscutter
|
||||||
|
volumes:
|
||||||
|
- mongodata:/data/db
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mongodata:
|
@ -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/stable/CONTRIBUTING.md) zorgvuldig door voordat u uw bijdrage toevoegt.
|
**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.
|
||||||
|
|
||||||
## Huidige functies
|
## Huidige functies
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
|
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
|
||||||
|
|
||||||
[EN](../README.md) | [简中](README_zh-CN.md) | [繁中](README_zh-TW.md) | [FR](README_fr-FR.md) | [ES](README_es-ES.md) | [HE](README_HE.md) | [RU](README_ru-RU.md) | [PL](README_pl-PL.md) | [ID](README_id-ID.md) | [KR](README_ko-KR.md) | [FIL/PH](README_fil-PH.md) | [NL](README_NL.md) | [JP](README_ja-JP.md) | [IT](README_it-IT.md) | [VI](README_vi-VN.md) | [हिंदी](README_hn-IN.md)
|
[EN](README.md) | [简中](docs/README_zh-CN.md) | [繁中](docs/README_zh-TW.md) | [FR](docs/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)
|
||||||
|
|
||||||
**ध्यान:** हम हमेशा परियोजना में योगदानकर्ताओं का स्वागत करते हैं।. अपना योगदान जोड़ने से पहले कृपया हमारा ध्यानपूर्वक पढ़ें [आचार संहिता](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md).
|
**ध्यान:** हम हमेशा परियोजना में योगदानकर्ताओं का स्वागत करते हैं।. अपना योगदान जोड़ने से पहले कृपया हमारा ध्यानपूर्वक पढ़ें [आचार संहिता](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
|
<div align="center"><a href="https://discord.gg/T5vZU6UyeG"><img alt="Discord - Grasscutter" src="https://img.shields.io/discord/965284035985305680?label=Discord&logo=discord&style=for-the-badge"></a></div>
|
||||||
|
|
||||||
[EN](../README.md) | [简中](README_zh-CN.md) | [繁中](README_zh-TW.md) | [FR](README_fr-FR.md) | [ES](README_es-ES.md) | [HE](README_HE.md) | [RU](README_ru-RU.md) | [PL](README_pl-PL.md) | [ID](README_id-ID.md) | [KR](README_ko-KR.md) | [FIL/PH](README_fil-PH.md) | [NL](README_NL.md) | [JP](README_ja-JP.md) | [IT](README_it-IT.md) | [VI](README_vi-VN.md) | [HI](README_hn-IN.md)
|
[EN](README.md) | [简中](docs/README_zh-CN.md) | [繁中](docs/README_zh-TW.md) | [FR](docs/README_fr-FR.md) | [ES](docs/README_es-ES.md) | [HE](docs/README_HE.md) | [RU](docs/README_ru-RU.md) | [PL](docs/README_pl-PL.md) | [ID](docs/README_id-ID.md) | [KR](docs/README_ko-KR.md) | [FIL/PH](docs/README_fil-PH.md) | [NL](docs/README_NL.md) | [JP](docs/README_ja-JP.md) | [IT](docs/README_it-IT.md) | [VI](docs/README_vi-VN.md)
|
||||||
|
|
||||||
|
|
||||||
**Attention:** 私たちはプロジェクトへのコントリビュータをいつでも歓迎します。コントリビュートする前に、私たちの [行動規範](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)をよくお読みください。
|
**Attention:** 私たちはプロジェクトへのコントリビュータをいつでも歓迎します。コントリビュートする前に、私たちの [行動規範](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md)をよくお読みください。
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
- [Java (バージョン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) を用意する
|
- [MongoDB Community Server](https://www.mongodb.com/try/download/community) を用意する
|
||||||
- ゲームバージョンがREL4.0.Xのクライアントを用意する (4.0.Xのクライアントを持っていない場合は右のリンクからダウンロード): [Github](https://github.com/JRSKelvin/GenshinRepository/blob/main/Version%204.0.0.md), [クラウド(123云盘)](https://www.123pan.com/s/HoqUVv-U7SBA.html)
|
- ゲームバージョンがREL4.0.Xのものを用意する (4.0.Xのクライアントを持っていない場合は右のリンクからダウンロード): https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/4.0.0.md
|
||||||
- [最新の Cultivation](https://github.com/Grasscutters/Cultivation/releases/latest)をダウンロードする。`.msi`インストーラを使ってください。
|
- [最新の Cultivation](https://github.com/Grasscutters/Cultivation/releases/latest)をダウンロードする。`.msi`インストーラを使ってください。
|
||||||
- 管理者権限を付与して Cultivation を実行した後、右上端にあるダウンロードアイコンのボタンを押す。
|
- 管理者権限を付与して Cultivation を実行した後、右上端にあるダウンロードアイコンのボタンを押す。
|
||||||
- `Download All-in-One` をクリックする
|
- `Download All-in-One` をクリックする
|
||||||
@ -35,9 +35,10 @@
|
|||||||
- `Game Install Path` にゲームファイルのパスを指定する。
|
- `Game Install Path` にゲームファイルのパスを指定する。
|
||||||
- `Custom Java Path` に、自分が用意したJavaのパスを指定する。 (例: `C:\Program Files\Java\jdk-17\bin\java.exe`)
|
- `Custom Java Path` に、自分が用意したJavaのパスを指定する。 (例: `C:\Program Files\Java\jdk-17\bin\java.exe`)
|
||||||
- その他の設定には手を付けず次の段階に進む。
|
- その他の設定には手を付けず次の段階に進む。
|
||||||
|
|
||||||
- Launch の隣にある小さいボタンを押す。
|
- Launch の隣にある小さいボタンを押す。
|
||||||
- Launchボタンを押す
|
- Launchボタンを押す
|
||||||
- 好きなユーザ名でログインする。ログインに関する設定がデフォルトの場合、パスワードは何を入れてもいい。
|
- 好きなユーザ名でログインする。パスワードは特段気にすることはない。
|
||||||
|
|
||||||
|
|
||||||
### ビルド
|
### ビルド
|
||||||
@ -78,22 +79,7 @@ chmod +x gradlew
|
|||||||
./gradlew jar # コンパイル
|
./gradlew jar # コンパイル
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 手動によるハンドブックの生成
|
生成されたjarファイルはプロジェクトフォルダのルートにあります。
|
||||||
|
|
||||||
Gradleを使用する場合:
|
|
||||||
```shell
|
|
||||||
./gradlew generateHandbook
|
|
||||||
```
|
|
||||||
|
|
||||||
NPMを使用する場合:
|
|
||||||
```shell
|
|
||||||
cd src/handbook
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
生成されたjarファイルはプロジェクトのルートフォルダにあります。
|
|
||||||
|
|
||||||
### トラブルシューティング
|
### トラブルシューティング
|
||||||
|
|
||||||
|
@ -22,25 +22,52 @@
|
|||||||
|
|
||||||
**각주 :** 도움이 필요할 경우 [Discord](https://discord.gg/T5vZU6UyeG)에 가입하세요.
|
**각주 :** 도움이 필요할 경우 [Discord](https://discord.gg/T5vZU6UyeG)에 가입하세요.
|
||||||
|
|
||||||
### 빠른 설치 (자동)
|
### 설치에 필요한 것들
|
||||||
|
|
||||||
- [Java 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))
|
||||||
- [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)
|
|
||||||
|
|
||||||
- [최신 Cultivation](https://github.com/Grasscutters/Cultivation/releases/latest) 다운로드하세요. `.msi` 설치파일을 사용하면 됩니다.
|
**각주 :** **실행**만을 원한다면, **jre**만 있어도 괜찮습니다.
|
||||||
- (관리자 권한으로) 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 환경 변수를 등록해야 합니다.**
|
||||||
|
|
||||||
### 빌드하기
|
### 빌드하기
|
||||||
|
|
||||||
@ -50,50 +77,39 @@ 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 --recurse-submodules https://github.com/Grasscutters/Grasscutter.git
|
git clone https://github.com/Grasscutters/Grasscutter.git
|
||||||
cd Grasscutter
|
cd Grasscutter
|
||||||
|
.\gradlew.bat # 개발 환경 설정
|
||||||
|
.\gradlew jar # 컴파일
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 컴파일
|
##### 윈도우 (로컬)
|
||||||
|
|
||||||
**각주**: 핸드북 생성은 일부 시스템에서 실패할 수도 있습니다. 핸드북 생성을 비활성화하려면, `gradlew jar`명령에 `-PskipHandbook=1`명령줄 스위치를 추가하세요.
|
|
||||||
|
|
||||||
|
|
||||||
윈도우:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
.\gradlew.bat # 환경 준비
|
cd <로컬 주소>/Grasscutter
|
||||||
.\gradlew jar
|
.\gradlew.bat # 개발 환경 설정
|
||||||
|
.\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 등) > 게임
|
||||||
|
@ -26,9 +26,7 @@
|
|||||||
|
|
||||||
- 获取Java 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社区版](https://www.mongodb.com/try/download/community)
|
- 获取[MongoDB社区版](https://www.mongodb.com/try/download/community)
|
||||||
- 获取游戏4.0正式版 (如果你没有4.0的客户端,可以在这里找到):
|
- 获取游戏4.0正式版 (如果你没有4.0的客户端,可以在这里找到):https://github.com/MAnggiarMustofa/GI-Download-Library/blob/main/GenshinImpact/Client/4.0.0.md)
|
||||||
[123pan share](https://www.123pan.com/s/HoqUVv-U7SBA.html)
|
|
||||||
[github](https://github.com/JRSKelvin/GenshinRepository/blob/main/Version%204.0.0.md)
|
|
||||||
|
|
||||||
- 下载[最新的Cultivation版本](https://github.com/Grasscutters/Cultivation/releases/latest)(使用以“.msi”为后缀的安装包)。
|
- 下载[最新的Cultivation版本](https://github.com/Grasscutters/Cultivation/releases/latest)(使用以“.msi”为后缀的安装包)。
|
||||||
- 以管理员身份打开Cultivation,按右上角的下载按钮。
|
- 以管理员身份打开Cultivation,按右上角的下载按钮。
|
||||||
|
0
entrypoint.sh
Normal file → Executable file
0
entrypoint.sh
Normal file → Executable file
@ -77,8 +77,6 @@ public final class Grasscutter {
|
|||||||
|
|
||||||
// Load server configuration.
|
// Load server configuration.
|
||||||
Grasscutter.loadConfig();
|
Grasscutter.loadConfig();
|
||||||
// Attempt to update configuration.
|
|
||||||
ConfigContainer.updateConfig();
|
|
||||||
|
|
||||||
Grasscutter.getLogger().info("Loading Grasscutter...");
|
Grasscutter.getLogger().info("Loading Grasscutter...");
|
||||||
|
|
||||||
@ -238,22 +236,7 @@ public final class Grasscutter {
|
|||||||
/** Attempts to load the configuration from a file. */
|
/** Attempts to load the configuration from a file. */
|
||||||
public static void loadConfig() {
|
public static void loadConfig() {
|
||||||
// Check if config.json exists. If not, we generate a new config.
|
// Check if config.json exists. If not, we generate a new config.
|
||||||
if (!configFile.exists()) {
|
|
||||||
getLogger().info("config.json could not be found. Generating a default configuration ...");
|
|
||||||
config = new ConfigContainer();
|
config = new ConfigContainer();
|
||||||
Grasscutter.saveConfig(config);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the file already exists, we attempt to load it.
|
|
||||||
try {
|
|
||||||
config = JsonUtils.loadToClass(configFile.toPath(), ConfigContainer.class);
|
|
||||||
} catch (Exception exception) {
|
|
||||||
getLogger()
|
|
||||||
.error(
|
|
||||||
"There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,11 +17,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -1,81 +1,257 @@
|
|||||||
package emu.grasscutter.config;
|
package emu.grasscutter.config;
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.utils.Crypto;
|
||||||
import emu.grasscutter.utils.*;
|
import emu.grasscutter.utils.Utils;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static emu.grasscutter.Grasscutter.*;
|
import static emu.grasscutter.Grasscutter.ServerDebugMode;
|
||||||
|
import static emu.grasscutter.Grasscutter.ServerRunMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* *when your JVM fails*
|
* *when your JVM fails*
|
||||||
*/
|
*/
|
||||||
public class ConfigContainer {
|
public class ConfigContainer {
|
||||||
/*
|
/**
|
||||||
* Configuration changes:
|
* Retrieves the given key from the environment variables.
|
||||||
* Version 5 - 'questing' has been changed from a boolean
|
* <p>
|
||||||
* to a container of options ('questOptions').
|
* When the key is not set it will return the given default value.
|
||||||
* This field will be removed in future versions.
|
*
|
||||||
* Version 6 - 'questing' has been fully replaced with 'questOptions'.
|
* @param key The name of the environment variable
|
||||||
* The field for 'legacyResources' has been removed.
|
* @param defaultValue The default value when the key is not set
|
||||||
* Version 7 - 'regionKey' is being added for authentication
|
* @return The value from the environment variable or the default value
|
||||||
* with the new dispatch server.
|
|
||||||
* Version 8 - 'server' is being added for enforcing handbook server
|
|
||||||
* addresses.
|
|
||||||
* Version 9 - 'limits' was added for handbook requests.
|
|
||||||
* Version 10 - 'trialCostumes' was added for enabling costumes
|
|
||||||
* on trial avatars.
|
|
||||||
* Version 11 - 'server.fastRequire' was added for disabling the new
|
|
||||||
* Lua script require system if performance is a concern.
|
|
||||||
* Version 12 - 'http.startImmediately' was added to control whether the
|
|
||||||
* HTTP server should start immediately.
|
|
||||||
* Version 13 - 'game.useUniquePacketKey' was added to control whether the
|
|
||||||
* encryption key used for packets is a constant or randomly generated.
|
|
||||||
*/
|
*/
|
||||||
private static int version() {
|
static String getStringFromEnv(String key, String defaultValue) {
|
||||||
return 13;
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to update the server's existing configuration.
|
* Retrieves the given key from the environment variables and tries to parse it as integer.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param defaultValue The default value when the environment variable does not exists or is not a valid integer
|
||||||
|
* @return The parsed integer or the default value
|
||||||
*/
|
*/
|
||||||
public static void updateConfig() {
|
static int getIntFromEnv(String key, int defaultValue) {
|
||||||
try { // Check if the server is using a legacy config.
|
var currentValue = System.getenv(key);
|
||||||
var configObject = JsonUtils.loadToClass(Grasscutter.configFile.toPath(), JsonObject.class);
|
|
||||||
if (!configObject.has("version")) {
|
if (currentValue == null) {
|
||||||
Grasscutter.getLogger().info("Updating legacy config...");
|
return defaultValue;
|
||||||
Grasscutter.saveConfig(null);
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) { }
|
|
||||||
|
|
||||||
var existing = config.version;
|
|
||||||
var latest = version();
|
|
||||||
|
|
||||||
if (existing == latest)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Create a new configuration instance.
|
|
||||||
var updated = new ConfigContainer();
|
|
||||||
// Update all configuration fields.
|
|
||||||
var fields = ConfigContainer.class.getDeclaredFields();
|
|
||||||
Arrays.stream(fields).forEach(field -> {
|
|
||||||
try {
|
try {
|
||||||
field.set(updated, field.get(config));
|
return Integer.parseInt(currentValue, 10);
|
||||||
} catch (Exception exception) {
|
} catch (Exception e) {
|
||||||
Grasscutter.getLogger().error("Failed to update a configuration field.", exception);
|
return defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}); updated.version = version();
|
|
||||||
|
|
||||||
try { // Save configuration and reload.
|
/**
|
||||||
Grasscutter.saveConfig(updated);
|
* Retrieves the given key from the environment variables and tries to parse it as float.
|
||||||
Grasscutter.loadConfig();
|
* <p>
|
||||||
} catch (Exception exception) {
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
Grasscutter.getLogger().warn("Failed to save the updated configuration.", exception);
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param defaultValue The default value when the environment variable does not exist or is not a valid float
|
||||||
|
* @return The parsed float or the default value
|
||||||
|
*/
|
||||||
|
static float getFloatFromEnv(String key, float defaultValue) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Float.parseFloat(currentValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given key from the environment variables and tries to parse it as float.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param defaultValue The default value when the environment variable does not exists or is not a valid bool
|
||||||
|
* @return The parsed boolean or the default value
|
||||||
|
*/
|
||||||
|
static boolean getBoolFromEnv(String key, boolean defaultValue) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (currentValue.trim()) {
|
||||||
|
case "true", "on", "1" -> true;
|
||||||
|
case "false", "off", "0" -> false;
|
||||||
|
default -> defaultValue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given from the environment variables and tries to parse it as a Set<String>.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param defaultValue The default value when the environment variable does not exist or is not a valid set
|
||||||
|
* @param separator The separator which will be used for splitting up the string
|
||||||
|
* @return The parsed set or the default value
|
||||||
|
*/
|
||||||
|
static Set<String> getStringSetFromEnv(String key, Set<String> defaultValue, String separator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts = currentValue.split(separator);
|
||||||
|
|
||||||
|
return Set.of(parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given key from the environment variables and tries to parse it as a string array.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable
|
||||||
|
* @param defaultValue The default value when the environment variable does not exist
|
||||||
|
* @param separator The separator which will be used for splitting up the environment variable
|
||||||
|
* @return The parsed integer set or the default value
|
||||||
|
*/
|
||||||
|
static Set<Integer> getIntSetFromEnv(String key, Set<Integer> defaultValue, String separator) {
|
||||||
|
var defaultValues = defaultValue.stream().map(Object::toString).collect(Collectors.toSet());
|
||||||
|
var currentValue = getStringSetFromEnv(key, defaultValues, separator);
|
||||||
|
|
||||||
|
return currentValue.stream().map(entry -> Integer.parseInt(entry, 10)).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given key from the environment variables and tries to parse it as an enum member.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param enumClass The enum class which contains all members
|
||||||
|
* @param defaultValue The default value when the environment variable does not exists or is not a valid enum member
|
||||||
|
* @param <T> The type of the enum member
|
||||||
|
* @return The parsed enum member or the default value
|
||||||
|
*/
|
||||||
|
static <T extends Enum<T>> T getEnumFromEnv(String key, Class<T> enumClass, T defaultValue) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Enum.valueOf(enumClass, currentValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the given key from the environment variables and tries to parse it as string array.
|
||||||
|
* <p>
|
||||||
|
* If the environment variable is not present or the parsing fails then the default value will be returned.
|
||||||
|
*
|
||||||
|
* @param key The name of the environment variable to parse
|
||||||
|
* @param defaultValue The default value when the environment variable does not exist
|
||||||
|
* @param separator The separator which will be used for splitting up the string
|
||||||
|
* @return The parsed string array or the default value
|
||||||
|
*/
|
||||||
|
static String[] getStringArrayFromEnv(String key, String[] defaultValue, String separator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentValue.split(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int[] getIntArrayFromEnv(String key, int[] defaultValue, String separator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arrays.stream(currentValue.split(separator)).mapToInt(Integer::parseInt).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static emu.grasscutter.game.mail.Mail.MailItem[] getMailItemsFromEnv(String key, emu.grasscutter.game.mail.Mail.MailItem[] defaultValue, String partsSeparator, String valuesSeparator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts = Arrays.stream(currentValue.split(partsSeparator)).map(part -> part.split(valuesSeparator));
|
||||||
|
|
||||||
|
return (emu.grasscutter.game.mail.Mail.MailItem[]) parts.filter(part -> part.length != 3).map(part -> {
|
||||||
|
var itemId = Integer.parseInt(part[0], 10);
|
||||||
|
var itemCount = Integer.parseInt(part[1], 10);
|
||||||
|
var itemLevel = Integer.parseInt(part[2], 10);
|
||||||
|
|
||||||
|
return new emu.grasscutter.game.mail.Mail.MailItem(itemId, itemCount, itemLevel);
|
||||||
|
}).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static VisionOptions[] getVisionOptionsFromEnv(String key, VisionOptions[] defaultValue, String partsSeparator, String valuesSeparator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts = currentValue.split(partsSeparator);
|
||||||
|
return (VisionOptions[]) Arrays.stream(parts).map(part -> part.split(valuesSeparator)).filter(values -> values.length == 3).map(values -> {
|
||||||
|
var name = values[0];
|
||||||
|
var visionRange = Integer.parseInt(values[1]);
|
||||||
|
var gridWidth = Integer.parseInt(values[2]);
|
||||||
|
|
||||||
|
return new VisionOptions(name, visionRange, gridWidth);
|
||||||
|
}).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Region> getRegionsFromEnv(String key, List<Region> defaultValue, String partsSeparator, String valuesSeparator) {
|
||||||
|
var currentValue = System.getenv(key);
|
||||||
|
|
||||||
|
if (currentValue == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts = currentValue.split(partsSeparator);
|
||||||
|
return Arrays.stream(parts).map(part -> part.split(valuesSeparator)).filter(values -> values.length == 4).map(values -> {
|
||||||
|
var name = values[0];
|
||||||
|
var title = values[1];
|
||||||
|
var address = values[2];
|
||||||
|
var port = Integer.parseInt(values[3]);
|
||||||
|
|
||||||
|
return new Region(name, title, address, port);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Structure folderStructure = new Structure();
|
public Structure folderStructure = new Structure();
|
||||||
@ -84,9 +260,6 @@ public class ConfigContainer {
|
|||||||
public Account account = new Account();
|
public Account account = new Account();
|
||||||
public Server server = new Server();
|
public Server server = new Server();
|
||||||
|
|
||||||
// DO NOT. TOUCH. THE VERSION NUMBER.
|
|
||||||
public int version = version();
|
|
||||||
|
|
||||||
/* Option containers. */
|
/* Option containers. */
|
||||||
|
|
||||||
public static class Database {
|
public static class Database {
|
||||||
@ -100,28 +273,29 @@ public class ConfigContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Structure {
|
public static class Structure {
|
||||||
public String resources = "./resources/";
|
public String resources = getStringFromEnv("FOLDER_STRUCTURE_RESOURCES", "./resources/");
|
||||||
public String data = "./data/";
|
public String data = getStringFromEnv("FOLDER_STRUCTURE_DATA", "./data/");
|
||||||
public String packets = "./packets/";
|
public String packets = getStringFromEnv("FOLDER_STRUCTURE_PACKETS", "./packets/");
|
||||||
public String scripts = "resources:Scripts/";
|
public String scripts = getStringFromEnv("FOLDER_STRUCTURE_SCRIPTS", "resources:Scripts/");
|
||||||
public String plugins = "./plugins/";
|
public String plugins = getStringFromEnv("FOLDER_STRUCTURE_PLUGINS", "./plugins/");
|
||||||
public String cache = "./cache/";
|
public String cache = getStringFromEnv("FOLDER_STRUCTURE_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 Set<Integer> debugWhitelist = Set.of();
|
public Set<Integer> debugWhitelist = getIntSetFromEnv("SERVER_DEBUG_WHITELIST", Set.of(), ",");
|
||||||
public Set<Integer> debugBlacklist = Set.of();
|
public Set<Integer> debugBlacklist = getIntSetFromEnv("SERVER_DEBUG_BLACKLIST", Set.of(), ",");
|
||||||
public ServerRunMode runMode = ServerRunMode.HYBRID;
|
public ServerRunMode runMode = getEnumFromEnv("SERVER_RUN_MODE", ServerRunMode.class, ServerRunMode.HYBRID);
|
||||||
public boolean logCommands = false;
|
|
||||||
|
public boolean logCommands = getBoolFromEnv("SERVER_LOG_COMMANDS", 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 boolean fastRequire = true;
|
public boolean fastRequire = getBoolFromEnv("SERVER_FAST_REQUIRE", true);
|
||||||
|
|
||||||
public HTTP http = new HTTP();
|
public HTTP http = new HTTP();
|
||||||
public Game game = new Game();
|
public Game game = new Game();
|
||||||
@ -133,30 +307,29 @@ public class ConfigContainer {
|
|||||||
public static class Language {
|
public static class Language {
|
||||||
public Locale language = Locale.getDefault();
|
public Locale language = Locale.getDefault();
|
||||||
public Locale fallback = Locale.US;
|
public Locale fallback = Locale.US;
|
||||||
public String document = "EN";
|
public String document = getStringFromEnv("LANGUAGE_DOCUMENT", "EN");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Account {
|
public static class Account {
|
||||||
public boolean autoCreate = false;
|
public boolean autoCreate = getBoolFromEnv("ACCOUNT_AUTO_CREATE", false);
|
||||||
public boolean EXPERIMENTAL_RealPassword = false;
|
public boolean EXPERIMENTAL_RealPassword = getBoolFromEnv("ACCOUNT_EXPERIMENTAL_REAL_PASSWORD", false);
|
||||||
public String[] defaultPermissions = {};
|
public String[] defaultPermissions = getStringArrayFromEnv("ACCOUNT_DEFAULT_PERMISSIONS", new String[]{}, ",");
|
||||||
public String playerEmail = "grasscutter.io";
|
public int maxPlayer = getIntFromEnv("ACCOUNT_MAX_PLAYER", -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 boolean startImmediately = false;
|
public boolean startImmediately = getBoolFromEnv("SERVER_HTTP_START_IMMEDIATELY", false);
|
||||||
|
|
||||||
public String bindAddress = "0.0.0.0";
|
public String bindAddress = getStringFromEnv("SERVER_HTTP_BIND_ADDRESS", "0.0.0.0");
|
||||||
public int bindPort = 443;
|
public int bindPort = getIntFromEnv("SERVER_HTTP_BIND_PORT", 443);
|
||||||
|
|
||||||
/* This is the address used in URLs. */
|
/* This is the address used in URLs. */
|
||||||
public String accessAddress = "127.0.0.1";
|
public String accessAddress = getStringFromEnv("SERVER_HTTP_ACCESS_ADDRESS", "127.0.0.1");
|
||||||
/* This is the port used in URLs. */
|
/* This is the port used in URLs. */
|
||||||
public int accessPort = 0;
|
public int accessPort = getIntFromEnv("SERVER_HTTP_ACCESS_PORT", 0);
|
||||||
|
|
||||||
public Encryption encryption = new Encryption();
|
public Encryption encryption = new Encryption();
|
||||||
public Policies policies = new Policies();
|
public Policies policies = new Policies();
|
||||||
@ -164,66 +337,65 @@ public class ConfigContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Game {
|
public static class Game {
|
||||||
public String bindAddress = "0.0.0.0";
|
public String bindAddress = getStringFromEnv("SERVER_GAME_BIND_ADDRESS", "0.0.0.0");
|
||||||
public int bindPort = 22102;
|
public int bindPort = getIntFromEnv("SERVER_GAME_BIND_PORT", 22102);
|
||||||
|
|
||||||
/* This is the address used in the default region. */
|
/* This is the address used in the default region. */
|
||||||
public String accessAddress = "127.0.0.1";
|
public String accessAddress = getStringFromEnv("SERVER_GAME_ACCESS_ADDRESS", "127.0.0.1");
|
||||||
/* This is the port used in the default region. */
|
/* This is the port used in the default region. */
|
||||||
public int accessPort = 0;
|
public int accessPort = getIntFromEnv("SERVER_GAME_ACCESS_PORT", 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 boolean useUniquePacketKey = true;
|
public boolean useUniquePacketKey = getBoolFromEnv("SERVER_GAME_USE_UNIQUE_PACKET_KEY", true);
|
||||||
|
|
||||||
/* Entities within a certain range will be loaded for the player */
|
/* Entities within a certain range will be loaded for the player */
|
||||||
public int loadEntitiesForPlayerRange = 300;
|
public int loadEntitiesForPlayerRange = getIntFromEnv("SERVER_GAME_LOAD_ENTITIES_FOR_PLAYER_RANGE", 300);
|
||||||
/* Start in 'unstable-quests', Lua scripts will be enabled by default. */
|
/* Start in 'unstable-quests', Lua scripts will be enabled by default. */
|
||||||
public boolean enableScriptInBigWorld = true;
|
public boolean enableScriptInBigWorld = getBoolFromEnv("SERVER_GAME_ENABLE_SCRIPT_IN_BIG_WORLD", true);
|
||||||
public boolean enableConsole = true;
|
public boolean enableConsole = getBoolFromEnv("SERVER_GAME_ENABLE_CONSOLE", true);
|
||||||
|
|
||||||
/* Kcp internal work interval (milliseconds) */
|
/* Kcp internal work interval (milliseconds) */
|
||||||
public int kcpInterval = 20;
|
public int kcpInterval = getIntFromEnv("SERVER_GAME_KCP_INTERVAL", 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 = getEnumFromEnv("SERVER_GAME_LOG_PACKETS", ServerDebugMode.class, 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) */
|
||||||
public boolean isShowPacketPayload = false;
|
public boolean isShowPacketPayload = getBoolFromEnv("SERVER_GAME_IS_SHOW_PACKET_PAYLOAD", false);
|
||||||
/* Show annoying loop packets or no */
|
/* Show annoying loop packets or no */
|
||||||
public boolean isShowLoopPackets = false;
|
public boolean isShowLoopPackets = getBoolFromEnv("SERVER_GAME_IS_SHOW_LOOP_PACKETS", false);
|
||||||
|
|
||||||
public boolean cacheSceneEntitiesEveryRun = false;
|
public boolean cacheSceneEntitiesEveryRun = getBoolFromEnv("SERVER_GAME_CACHE_SCENE_ENTITIES_EVERY_RUN", false);
|
||||||
|
|
||||||
public GameOptions gameOptions = new GameOptions();
|
public GameOptions gameOptions = new GameOptions();
|
||||||
public JoinOptions joinOptions = new JoinOptions();
|
public JoinOptions joinOptions = new JoinOptions();
|
||||||
public ConsoleAccount serverAccount = new ConsoleAccount();
|
public ConsoleAccount serverAccount = new ConsoleAccount();
|
||||||
|
|
||||||
public VisionOptions[] visionOptions = new VisionOptions[] {
|
public VisionOptions[] visionOptions = getVisionOptionsFromEnv("SERVER_GAME_VISION_OPTIONS", 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),
|
||||||
new VisionOptions("VISION_LEVEL_SUPER" , 4000 , 1000),
|
new VisionOptions("VISION_LEVEL_SUPER", 4000, 1000),
|
||||||
new VisionOptions("VISION_LEVEL_NEARBY" , 40 , 20),
|
new VisionOptions("VISION_LEVEL_NEARBY", 40, 20),
|
||||||
new VisionOptions("VISION_LEVEL_SUPER_NEARBY" , 20 , 20)
|
new VisionOptions("VISION_LEVEL_SUPER_NEARBY", 20, 20)
|
||||||
};
|
}, "|", ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data containers. */
|
/* Data containers. */
|
||||||
|
|
||||||
public static class Dispatch {
|
public static class Dispatch {
|
||||||
/* An array of servers. */
|
/* An array of servers. */
|
||||||
public List<Region> regions = List.of();
|
public List<Region> regions = getRegionsFromEnv("SERVER_DISPATCH_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 String dispatchUrl = "ws://127.0.0.1:1111";
|
public String dispatchUrl = getStringFromEnv("SERVER_DISPATCH_DISPATCH_URL", "ws://127.0.0.1:1111");
|
||||||
/* A unique key used for encryption. */
|
/* A unique key used for encryption. */
|
||||||
public byte[] encryptionKey = Crypto.createSessionKey(32);
|
public byte[] encryptionKey = Utils.base64Decode(getStringFromEnv("SERVER_DISPATCH_ENCRYPTION_KEY", Utils.base64Encode(Crypto.createSessionKey(32))));
|
||||||
/* A unique key used for authentication. */
|
/* A unique key used for authentication. */
|
||||||
public String dispatchKey = Utils.base64Encode(
|
public String dispatchKey = getStringFromEnv("SERVER_DISPATCH_DISPATCH_KEY", Utils.base64Encode(Crypto.createSessionKey(32)));
|
||||||
Crypto.createSessionKey(32));
|
|
||||||
|
|
||||||
public String defaultName = "Grasscutter";
|
public String defaultName = getStringFromEnv("SERVER_DISPATCH_DEFAULT_NAME", "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 = getEnumFromEnv("SERVER_DISPATCH_SERVER_DEBUG_MODE", ServerDebugMode.class, ServerDebugMode.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug options container, used when jar launch argument is -debug | -debugall and override default values
|
/* Debug options container, used when jar launch argument is -debug | -debugall and override default values
|
||||||
@ -237,46 +409,46 @@ public class ConfigContainer {
|
|||||||
public 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 ServerDebugMode logPackets = ServerDebugMode.ALL;
|
public ServerDebugMode logPackets = getEnumFromEnv("SERVER_DEBUG_MODE_LOG_PACKETS", ServerDebugMode.class, 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 boolean isShowPacketPayload = false;
|
public boolean isShowPacketPayload = getBoolFromEnv("SERVER_DEBUG_MODE_IS_SHOW_PACKET_PAYLOAD", false);
|
||||||
|
|
||||||
/* Show annoying loop packets or no */
|
/* Show annoying loop packets or no */
|
||||||
public boolean isShowLoopPackets = false;
|
public boolean isShowLoopPackets = getBoolFromEnv("SERVER_DEBUG_MODE_IS_SHOW_LOOP_PACKETS", false);
|
||||||
|
|
||||||
/* 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.ALL;
|
public ServerDebugMode logRequests = getEnumFromEnv("SERVER_DEBUG_MODE_LOG_REQUESTS", ServerDebugMode.class, ServerDebugMode.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Encryption {
|
public static class Encryption {
|
||||||
public boolean useEncryption = true;
|
public boolean useEncryption = getBoolFromEnv("SERVER_HTTP_ENCRYPTION_USE_ENCRYPTION", true);
|
||||||
/* Should 'https' be appended to URLs? */
|
/* Should 'https' be appended to URLs? */
|
||||||
public boolean useInRouting = true;
|
public boolean useInRouting = getBoolFromEnv("SERVER_HTTP_ENCRYPTION_USE_IN_ROUTING", true);
|
||||||
public String keystore = "./keystore.p12";
|
public String keystore = getStringFromEnv("SERVER_HTTP_ENCRYPTION_KEYSTORE", "./keystore.p12");
|
||||||
public String keystorePassword = "123456";
|
public String keystorePassword = getStringFromEnv("SERVER_HTTP_ENCRYPTION_KEYSTORE_PASSWORD", "123456");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Policies {
|
public static class Policies {
|
||||||
public Policies.CORS cors = new Policies.CORS();
|
public Policies.CORS cors = new Policies.CORS();
|
||||||
|
|
||||||
public static class CORS {
|
public static class CORS {
|
||||||
public boolean enabled = true;
|
public boolean enabled = getBoolFromEnv("SERVER_HTTP_POLICIES_CORS_ENABLED", true);
|
||||||
public String[] allowedOrigins = new String[]{"*"};
|
public String[] allowedOrigins = getStringArrayFromEnv("SERVER_HTTP_POLICIES_ALLOWED_ORIGINS", new String[]{"*"}, ",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GameOptions {
|
public static class GameOptions {
|
||||||
public InventoryLimits inventoryLimits = new InventoryLimits();
|
public InventoryLimits inventoryLimits = new InventoryLimits();
|
||||||
public AvatarLimits avatarLimits = new AvatarLimits();
|
public AvatarLimits avatarLimits = new AvatarLimits();
|
||||||
public int sceneEntityLimit = 1000; // Unenforced. TODO: Implement.
|
public int sceneEntityLimit = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_SCENE_ENTITY_LIMIT", 1000); // Unenforced. TODO: Implement.
|
||||||
|
|
||||||
public boolean watchGachaConfig = false;
|
public boolean watchGachaConfig = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_WATCH_GACHA_CONFIG", false);
|
||||||
public boolean enableShopItems = true;
|
public boolean enableShopItems = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_ENABLE_SHOP_ITEMS", true);
|
||||||
public boolean staminaUsage = true;
|
public boolean staminaUsage = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_STAMINA_USAGE", true);
|
||||||
public boolean energyUsage = true;
|
public boolean energyUsage = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_ENERGY_USAGE", true);
|
||||||
public boolean fishhookTeleport = true;
|
public boolean fishhookTeleport = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_FISHHOOK_TELEPORT", true);
|
||||||
public boolean trialCostumes = false;
|
public boolean trialCostumes = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_TRIAL_COSTUMES", false);
|
||||||
|
|
||||||
@SerializedName(value = "questing", alternate = "questOptions")
|
@SerializedName(value = "questing", alternate = "questOptions")
|
||||||
public Questing questing = new Questing();
|
public Questing questing = new Questing();
|
||||||
@ -286,63 +458,63 @@ public class ConfigContainer {
|
|||||||
public HandbookOptions handbook = new HandbookOptions();
|
public HandbookOptions handbook = new HandbookOptions();
|
||||||
|
|
||||||
public static class InventoryLimits {
|
public static class InventoryLimits {
|
||||||
public int weapons = 2000;
|
public int weapons = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_INVENTORY_LIMITS_WEAPONS", 2000);
|
||||||
public int relics = 2000;
|
public int relics = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_INVENTORY_LIMITS_RELICS", 2000);
|
||||||
public int materials = 2000;
|
public int materials = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_INVENTORY_LIMITS_MATERIALS", 2000);
|
||||||
public int furniture = 2000;
|
public int furniture = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_INVENTORY_LIMITS_FURNITURE", 2000);
|
||||||
public int all = 30000;
|
public int all = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_INVENTORY_LIMITS_ALL", 30000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AvatarLimits {
|
public static class AvatarLimits {
|
||||||
public int singlePlayerTeam = 4;
|
public int singlePlayerTeam = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_AVATAR_LIMITS_SINGLE_PLAYER_TEAM", 4);
|
||||||
public int multiplayerTeam = 4;
|
public int multiplayerTeam = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_AVATAR_LIMITS_MULTIPLAYER_TEAM", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Rates {
|
public static class Rates {
|
||||||
public float adventureExp = 1.0f;
|
public float adventureExp = getFloatFromEnv("SERVER_GAME_GAME_OPTIONS_RATES_ADVENTURE_EXP", 1.0f);
|
||||||
public float mora = 1.0f;
|
public float mora = getFloatFromEnv("SERVER_GAME_GAME_OPTIONS_RATES_MORA", 1.0f);
|
||||||
public float leyLines = 1.0f;
|
public float leyLines = getFloatFromEnv("SERVER_GAME_GAME_OPTIONS_RATES_LEY_LINES", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResinOptions {
|
public static class ResinOptions {
|
||||||
public boolean resinUsage = false;
|
public boolean resinUsage = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_RESIN_OPTIONS_RESIN_USAGE", false);
|
||||||
public int cap = 160;
|
public int cap = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_RESIN_OPTIONS_CAP", 160);
|
||||||
public int rechargeTime = 480;
|
public int rechargeTime = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_RESIN_OPTIONS_RECHARGE_TIME", 480);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Questing {
|
public static class Questing {
|
||||||
/* Should questing behavior be used? */
|
/* Should questing behavior be used? */
|
||||||
public boolean enabled = true;
|
public boolean enabled = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_QUESTING_ENABLED", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HandbookOptions {
|
public static class HandbookOptions {
|
||||||
public boolean enable = false;
|
public boolean enable = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_ENABLE", false);
|
||||||
public boolean allowCommands = true;
|
public boolean allowCommands = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_ALLOW_COMMANDS", true);
|
||||||
|
|
||||||
public Limits limits = new Limits();
|
public Limits limits = new Limits();
|
||||||
public 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 boolean enabled = false;
|
public boolean enabled = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_LIMITS_ENABLED", false);
|
||||||
/* The time for limits to expire. */
|
/* The time for limits to expire. */
|
||||||
public int interval = 3;
|
public int interval = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_LIMITS_INTERVAL", 3);
|
||||||
|
|
||||||
/* The maximum amount of normal requests. */
|
/* The maximum amount of normal requests. */
|
||||||
public int maxRequests = 10;
|
public int maxRequests = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_LIMITS_MAX_REQUESTS", 10);
|
||||||
/* The maximum amount of entities to be spawned in one request. */
|
/* The maximum amount of entities to be spawned in one request. */
|
||||||
public int maxEntities = 25;
|
public int maxEntities = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_OPTIONS_LIMITS_MAX_ENTITIES", 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 boolean enforced = false;
|
public boolean enforced = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_CONFIG_SERVER_ENFORCED", false);
|
||||||
/* The default server address for the handbook's authentication. */
|
/* The default server address for the handbook's authentication. */
|
||||||
public String address = "127.0.0.1";
|
public String address = getStringFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_CONFIG_SERVER_ADDRESS", "127.0.0.1");
|
||||||
/* The default server port for the handbook's authentication. */
|
/* The default server port for the handbook's authentication. */
|
||||||
public int port = 443;
|
public int port = getIntFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_CONFIG_SERVER_PORT", 443);
|
||||||
/* Should the defaults be enforced? */
|
/* Should the defaults be enforced? */
|
||||||
public boolean canChange = true;
|
public boolean canChange = getBoolFromEnv("SERVER_GAME_GAME_OPTIONS_HANDBOOK_CONFIG_SERVER_CAN_CHANGE", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,40 +532,37 @@ public class ConfigContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class JoinOptions {
|
public static class JoinOptions {
|
||||||
public int[] welcomeEmotes = {2007, 1002, 4010};
|
public int[] welcomeEmotes = getIntArrayFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_EMOTES", new int[]{2007, 1002, 4010}, ",");
|
||||||
public String welcomeMessage = "Welcome to a Grasscutter server.";
|
public String welcomeMessage = getStringFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_MESSAGE", "Welcome to a Grasscutter server.");
|
||||||
public JoinOptions.Mail welcomeMail = new JoinOptions.Mail();
|
public JoinOptions.Mail welcomeMail = new JoinOptions.Mail();
|
||||||
|
|
||||||
public static class Mail {
|
public static class Mail {
|
||||||
public String title = "Welcome to Grasscutter!";
|
public String title = getStringFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_MAIL_TITLE", "Welcome to Grasscutter!");
|
||||||
public String content = """
|
public String content = getStringFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_MAIL_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 String sender = "Lawnmower";
|
public String sender = getStringFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_MAIL_SENDER", "Lawnmower");
|
||||||
public emu.grasscutter.game.mail.Mail.MailItem[] items = {
|
public emu.grasscutter.game.mail.Mail.MailItem[] items = getMailItemsFromEnv("SERVER_GAME_JOIN_OPTIONS_WELCOME_MAIL_ITEMS", new emu.grasscutter.game.mail.Mail.MailItem[]{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(13509, 1, 1),
|
|
||||||
new emu.grasscutter.game.mail.Mail.MailItem(201, 99999, 1)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ConsoleAccount {
|
public static class ConsoleAccount {
|
||||||
public int avatarId = 10000007;
|
public int avatarId = getIntFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_AVATAR_ID", 10000007);
|
||||||
public int nameCardId = 210001;
|
public int nameCardId = getIntFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_NAME_CARD_ID", 210001);
|
||||||
public int adventureRank = 1;
|
public int adventureRank = getIntFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_ADVENTURE_RANK", 1);
|
||||||
public int worldLevel = 0;
|
public int worldLevel = getIntFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_WORLD_LEVEL", 0);
|
||||||
|
|
||||||
public String nickName = "Server";
|
public String nickName = getStringFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_NICK_NAME", "Server");
|
||||||
public String signature = "Welcome to Grasscutter!";
|
public String signature = getStringFromEnv("SERVER_GAME_CONSOLE_ACCOUNT_SIGNATURE", "Welcome to Grasscutter!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Files {
|
public static class Files {
|
||||||
public String indexFile = "./index.html";
|
public String indexFile = getStringFromEnv("SERVER_HTTP_FILES_INDEX_FILE", "./index.html");
|
||||||
public String errorFile = "./404.html";
|
public String errorFile = getStringFromEnv("SERVER_HTTP_FILES_ERROR_FILE", "./404.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Objects. */
|
/* Objects. */
|
||||||
@ -405,10 +574,7 @@ public class ConfigContainer {
|
|||||||
public String Ip = "127.0.0.1";
|
public String Ip = "127.0.0.1";
|
||||||
public int Port = 22102;
|
public int Port = 22102;
|
||||||
|
|
||||||
public Region(
|
public Region(String name, String title, String address, int port) {
|
||||||
String name, String title,
|
|
||||||
String address, int port
|
|
||||||
) {
|
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.Title = title;
|
this.Title = title;
|
||||||
this.Ip = address;
|
this.Ip = address;
|
||||||
|
@ -109,7 +109,7 @@ public class Account {
|
|||||||
return email;
|
return email;
|
||||||
} else {
|
} else {
|
||||||
// As of game version 3.5+, only the email is displayed to a user.
|
// As of game version 3.5+, only the email is displayed to a user.
|
||||||
return this.getUsername() + "@" + ACCOUNT.playerEmail;
|
return this.getUsername() + "@grasscutter.io";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +235,7 @@ public class Account {
|
|||||||
this.addPermission("*");
|
this.addPermission("*");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set account default language to server default language
|
// Set account default language as server default language
|
||||||
if (!document.containsKey("locale")) {
|
if (!document.containsKey("locale")) {
|
||||||
this.locale = LANGUAGE;
|
this.locale = LANGUAGE;
|
||||||
}
|
}
|
||||||
|
@ -218,8 +218,6 @@ public final class HttpServer {
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<img src="https://http.cat/404" />
|
<img src="https://http.cat/404" />
|
||||||
<h1>Grasscutter cannot find the route you're trying to access.</h1>
|
|
||||||
<p>Your proxy is active, so if you're trying to download something close the game/stop the proxy.</p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
""");
|
""");
|
||||||
|
Reference in New Issue
Block a user