mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-25 09:39:18 +00:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e04c19acf5 | ||
|
|
1820a810f4 | ||
|
|
cedd12a048 | ||
|
|
7967d00208 | ||
|
|
00a68be2ad | ||
|
|
da5d991d2a | ||
|
|
c2f6d240ad | ||
|
|
4cde24c536 | ||
|
|
029617bc45 | ||
|
|
0627fb20e4 | ||
|
|
bc1f983684 | ||
|
|
31eb747c55 | ||
|
|
e8facf52ce | ||
|
|
5ee4bdd644 | ||
|
|
92c371e201 | ||
|
|
d27278454a | ||
|
|
16780c149c | ||
|
|
0445ba63bc | ||
|
|
b6aefd6f57 | ||
|
|
f803af0225 | ||
|
|
2675f4a377 | ||
|
|
03341c981f | ||
|
|
38cc654167 | ||
|
|
b347a8d060 | ||
|
|
8733b86b45 | ||
|
|
eda8e72633 | ||
|
|
c942a015d1 | ||
|
|
c00265f1f9 | ||
|
|
e303984dcf | ||
|
|
b449b5dee6 | ||
|
|
48f8c0c967 | ||
|
|
f88c4c3e2c | ||
|
|
e6273fa9a0 | ||
|
|
1ba5585d0d | ||
|
|
73547371ae | ||
|
|
fca6825394 | ||
|
|
53af114f44 | ||
|
|
311cc85c92 |
8
.github/workflows/ci_1.20.1.yml
vendored
8
.github/workflows/ci_1.20.1.yml
vendored
@@ -30,14 +30,14 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: 'minecraft/1.20.1'
|
ref: 'minecraft/1.20.1'
|
||||||
env:
|
|
||||||
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
|
||||||
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
|
||||||
- name: '[Current - 1.20.1] Build 🛎️'
|
- name: '[Current - 1.20.1] Build 🛎️'
|
||||||
run: |
|
run: |
|
||||||
./gradlew clean build publish
|
./gradlew clean build publish
|
||||||
|
env:
|
||||||
|
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: 'Publish Test Report 📊'
|
- name: 'Publish Test Report 📊'
|
||||||
uses: mikepenz/action-junit-report@v4
|
uses: mikepenz/action-junit-report@v5
|
||||||
if: success() || failure() # Continue on failure
|
if: success() || failure() # Continue on failure
|
||||||
with:
|
with:
|
||||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
|
|||||||
12
.github/workflows/ci_1.21.1.yml
vendored
12
.github/workflows/ci_1.21.1.yml
vendored
@@ -2,7 +2,7 @@ name: CI Tests
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ 'master' ]
|
branches: [ 'minecraft/1.21.1' ]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'workflows/**'
|
- 'workflows/**'
|
||||||
@@ -28,14 +28,16 @@ jobs:
|
|||||||
gradle-version: '8.8'
|
gradle-version: '8.8'
|
||||||
- name: 'Checkout for CI 🛎️'
|
- name: 'Checkout for CI 🛎️'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
env:
|
with:
|
||||||
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
ref: 'minecraft/1.21.1'
|
||||||
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
|
||||||
- name: '[Current - 1.21.1] Build 🛎️'
|
- name: '[Current - 1.21.1] Build 🛎️'
|
||||||
run: |
|
run: |
|
||||||
./gradlew clean build publish
|
./gradlew clean build publish
|
||||||
|
env:
|
||||||
|
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: 'Publish Test Report 📊'
|
- name: 'Publish Test Report 📊'
|
||||||
uses: mikepenz/action-junit-report@v4
|
uses: mikepenz/action-junit-report@v5
|
||||||
if: success() || failure() # Continue on failure
|
if: success() || failure() # Continue on failure
|
||||||
with:
|
with:
|
||||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
|
|||||||
68
.github/workflows/ci_master.yml
vendored
Normal file
68
.github/workflows/ci_master.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
name: CI Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ 'master' ]
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'workflows/**'
|
||||||
|
- 'README.md'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
checks: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: 'Build - 1.21.4'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 'Setup JDK 21 📦'
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '21'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: 'Setup Gradle 8.8 🏗️'
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
with:
|
||||||
|
gradle-version: '8.8'
|
||||||
|
- name: 'Checkout for CI 🛎️'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: '[Current - 1.21.4] Build 🛎️'
|
||||||
|
run: |
|
||||||
|
./gradlew clean build publish
|
||||||
|
env:
|
||||||
|
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
|
- name: 'Publish Test Report 📊'
|
||||||
|
uses: mikepenz/action-junit-report@v5
|
||||||
|
if: success() || failure() # Continue on failure
|
||||||
|
with:
|
||||||
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
|
- name: 'Fetch Version String 📝'
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=VERSION_NAME::$(./gradlew properties --no-daemon --console=plain -q | grep "^version:" | awk '{printf $2}')"
|
||||||
|
id: fetch-version
|
||||||
|
- name: 'Set Version Variable 📝'
|
||||||
|
run: |
|
||||||
|
echo "version_name=${{steps.fetch-version.outputs.VERSION_NAME}}" >> $GITHUB_ENV
|
||||||
|
- name: 'Publish to William278.net 🚀'
|
||||||
|
uses: WiIIiam278/bones-publish-action@v1
|
||||||
|
with:
|
||||||
|
api-key: ${{ secrets.BONES_API_KEY }}
|
||||||
|
project: 'husksync'
|
||||||
|
channel: 'alpha'
|
||||||
|
version: ${{ env.version_name }}
|
||||||
|
changelog: ${{ github.event.head_commit.message }}
|
||||||
|
distro-names: |
|
||||||
|
paper-1.21.4
|
||||||
|
fabric-1.21.4
|
||||||
|
distro-groups: |
|
||||||
|
paper
|
||||||
|
fabric
|
||||||
|
distro-descriptions: |
|
||||||
|
Paper 1.21.4
|
||||||
|
Fabric 1.21.4
|
||||||
|
files: |
|
||||||
|
target/HuskSync-Paper-${{ env.version_name }}+mc.1.21.4.jar
|
||||||
|
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.4.jar
|
||||||
2
.github/workflows/pr_tests.yml
vendored
2
.github/workflows/pr_tests.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
arguments: test
|
arguments: test
|
||||||
- name: 'Publish Test Report 📊'
|
- name: 'Publish Test Report 📊'
|
||||||
uses: mikepenz/action-junit-report@v4
|
uses: mikepenz/action-junit-report@v5
|
||||||
if: success() || failure() # Continue on failure
|
if: success() || failure() # Continue on failure
|
||||||
with:
|
with:
|
||||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
33
.github/workflows/release.yml
vendored
33
.github/workflows/release.yml
vendored
@@ -23,33 +23,50 @@ jobs:
|
|||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
with:
|
with:
|
||||||
gradle-version: '8.8'
|
gradle-version: '8.8'
|
||||||
- name: '[Current - 1.21.1] Checkout for CI 🛎️'
|
- name: '[Current - 1.21.4] Checkout for CI 🛎️'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
path: '1_21_4'
|
||||||
|
- name: '[Non-LTS - 1.21.1] Checkout for CI 🛎️'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: 'minecraft/1.21.1'
|
||||||
path: '1_21_1'
|
path: '1_21_1'
|
||||||
- name: '[LTS - 1.20.1] Checkout for CI 🛎️'
|
- name: '[LTS - 1.20.1] Checkout for CI 🛎️'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: 'minecraft/1.20.1'
|
ref: 'minecraft/1.20.1'
|
||||||
path: '1_20_1'
|
path: '1_20_1'
|
||||||
|
- name: '[Current - 1.21.4] Build 🛎️'
|
||||||
|
run: |
|
||||||
|
mkdir target
|
||||||
|
cd 1_21_4
|
||||||
|
./gradlew clean build publish -Dforce-hide-version-meta=1
|
||||||
|
cp -rf target/* ../target/
|
||||||
|
cd ..
|
||||||
env:
|
env:
|
||||||
RELEASES_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
RELEASES_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
RELEASES_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
RELEASES_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: '[Current - 1.21.1] Build 🛎️'
|
- name: '[Non-LTS - 1.21.1] Build 🛎️'
|
||||||
run: |
|
run: |
|
||||||
mkdir target
|
|
||||||
cd 1_21_1
|
cd 1_21_1
|
||||||
./gradlew clean build publish -Dforce-hide-version-meta=1
|
./gradlew clean build publish -Dforce-hide-version-meta=1
|
||||||
cp -rf target/* ../target/
|
cp -rf target/* ../target/
|
||||||
cd ..
|
cd ..
|
||||||
|
env:
|
||||||
|
RELEASES_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
RELEASES_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: '[LTS - 1.20.1] Build 🛎️'
|
- name: '[LTS - 1.20.1] Build 🛎️'
|
||||||
run: |
|
run: |
|
||||||
cd 1_20_1
|
cd 1_20_1
|
||||||
./gradlew clean build publish -Dforce-hide-version-meta=1
|
./gradlew clean build publish -Dforce-hide-version-meta=1
|
||||||
cp -rf target/* ../target/
|
cp -rf target/* ../target/
|
||||||
cd ..
|
cd ..
|
||||||
|
env:
|
||||||
|
RELEASES_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
RELEASES_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: 'Publish Test Report 📊'
|
- name: 'Publish Test Report 📊'
|
||||||
uses: mikepenz/action-junit-report@v4
|
uses: mikepenz/action-junit-report@v5
|
||||||
if: success() || failure() # Continue on failure
|
if: success() || failure() # Continue on failure
|
||||||
with:
|
with:
|
||||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
@@ -62,6 +79,8 @@ jobs:
|
|||||||
version: ${{ github.event.release.tag_name }}
|
version: ${{ github.event.release.tag_name }}
|
||||||
changelog: ${{ github.event.release.body }}
|
changelog: ${{ github.event.release.body }}
|
||||||
distro-names: |
|
distro-names: |
|
||||||
|
paper-1.21.4
|
||||||
|
fabric-1.21.4
|
||||||
paper-1.21.1
|
paper-1.21.1
|
||||||
fabric-1.21.1
|
fabric-1.21.1
|
||||||
paper-1.20.1
|
paper-1.20.1
|
||||||
@@ -71,12 +90,18 @@ jobs:
|
|||||||
fabric
|
fabric
|
||||||
paper
|
paper
|
||||||
fabric
|
fabric
|
||||||
|
paper
|
||||||
|
fabric
|
||||||
distro-descriptions: |
|
distro-descriptions: |
|
||||||
|
Paper 1.21.4
|
||||||
|
Fabric 1.21.4
|
||||||
Paper 1.21.1
|
Paper 1.21.1
|
||||||
Fabric 1.21.1
|
Fabric 1.21.1
|
||||||
Paper 1.20.1
|
Paper 1.20.1
|
||||||
Fabric 1.20.1
|
Fabric 1.20.1
|
||||||
files: |
|
files: |
|
||||||
|
target/HuskSync-Paper-${{ github.event.release.tag_name }}+mc.1.21.4.jar
|
||||||
|
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.4.jar
|
||||||
target/HuskSync-Paper-${{ github.event.release.tag_name }}+mc.1.21.1.jar
|
target/HuskSync-Paper-${{ github.event.release.tag_name }}+mc.1.21.1.jar
|
||||||
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.1.jar
|
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.1.jar
|
||||||
target/HuskSync-Paper-${{ github.event.release.tag_name }}+mc.1.20.1.jar
|
target/HuskSync-Paper-${{ github.event.release.tag_name }}+mc.1.20.1.jar
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -1,8 +1,8 @@
|
|||||||
<!--suppress ALL -->
|
<!--suppress ALL -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="images/banner.png" alt="HuskSync" />
|
<img src="images/banner.png" alt="HuskSync" />
|
||||||
<a href="https://github.com/WiIIiam278/HuskSync/actions/workflows/ci_1.21.1.yml">
|
<a href="https://github.com/WiIIiam278/HuskSync/actions/workflows/ci_master.yml">
|
||||||
<img src="https://img.shields.io/github/actions/workflow/status/WiIIiam278/HuskSync/ci_1.21.1.yml?branch=master&logo=github"/>
|
<img src="https://img.shields.io/github/actions/workflow/status/WiIIiam278/HuskSync/ci_master.yml?branch=master&logo=github"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://repo.william278.net/#/releases/net/william278/husksync/">
|
<a href="https://repo.william278.net/#/releases/net/william278/husksync/">
|
||||||
<img src="https://repo.william278.net/api/badge/latest/releases/net/william278/husksync/husksync-common?color=00fb9a&name=Maven&prefix=v" />
|
<img src="https://repo.william278.net/api/badge/latest/releases/net/william278/husksync/husksync-common?color=00fb9a&name=Maven&prefix=v" />
|
||||||
@@ -46,14 +46,16 @@
|
|||||||
## Compatibility
|
## Compatibility
|
||||||
HuskSync supports the following [compatible versions](https://william278.net/docs/husksync/compatibility) of Minecraft. Since v3.7, you must download the correct version of HuskSync for your server:
|
HuskSync supports the following [compatible versions](https://william278.net/docs/husksync/compatibility) of Minecraft. Since v3.7, you must download the correct version of HuskSync for your server:
|
||||||
|
|
||||||
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Ends |
|
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Status |
|
||||||
|:---------------:|:---------------:|:------------:|:--------------|:--------------------------|
|
|:---------------:|:---------------:|:------------:|:--------------|:-----------------------------|
|
||||||
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **Active Release** |
|
| 1.21.4 | _latest_ | 21 | Paper, Fabric | ✅ **Active Release** |
|
||||||
| 1.20.6 | 3.6.8 | 17 | Paper | ❌ _October 2024_ |
|
| 1.21.3 | 3.7.1 | 21 | Paper, Fabric | 🗃️ Archived (December 2024) |
|
||||||
| 1.20.4 | 3.6.8 | 17 | Paper | ❌ _July 2024_ |
|
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **November 2024** (LTS) |
|
||||||
| 1.20.1 | _latest_ | 17 | Paper, Fabric | ✅ **November 2025** (LTS) |
|
| 1.20.6 | 3.6.8 | 17 | Paper | 🗃️ Archived (October 2024) |
|
||||||
| 1.17.1 - 1.19.4 | 3.6.8 | 17 | Paper | ❌ _Support ended_ |
|
| 1.20.4 | 3.6.8 | 17 | Paper | 🗃️ Archived (July 2024) |
|
||||||
| 1.16.5 | 3.2.1 | 16 | Paper | ❌ _Support ended_ |
|
| 1.20.1 | _latest_ | 17 | Paper, Fabric | ✅ **November 2025** (LTS) |
|
||||||
|
| 1.17.1 - 1.19.4 | 3.6.8 | 17 | Paper | 🗃️ Archived |
|
||||||
|
| 1.16.5 | 3.2.1 | 16 | Paper | 🗃️ Archived |
|
||||||
|
|
||||||
HuskSync is primarily developed against the latest release. Old Minecraft versions are allocated a support channel based on popularity, mod support, etc:
|
HuskSync is primarily developed against the latest release. Old Minecraft versions are allocated a support channel based on popularity, mod support, etc:
|
||||||
|
|
||||||
|
|||||||
13
build.gradle
13
build.gradle
@@ -1,10 +1,10 @@
|
|||||||
import org.apache.tools.ant.filters.ReplaceTokens
|
import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.gradleup.shadow' version '8.3.2'
|
id 'com.gradleup.shadow' version '8.3.5'
|
||||||
id 'org.cadixdev.licenser' version '0.6.1' apply false
|
id 'org.cadixdev.licenser' version '0.6.1' apply false
|
||||||
id 'fabric-loom' version '1.7-SNAPSHOT' apply false
|
id 'fabric-loom' version "$fabric_loom_version" apply false
|
||||||
id 'org.ajoberstar.grgit' version '5.2.2'
|
id 'org.ajoberstar.grgit' version '5.3.0'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'java'
|
id 'java'
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,7 @@ allprojects {
|
|||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
|
||||||
compileJava.options.encoding = 'UTF-8'
|
compileJava.options.encoding = 'UTF-8'
|
||||||
|
compileJava.options.compilerArgs += ['-Xlint:unchecked', '-Xlint:deprecation']
|
||||||
compileJava.options.release.set Integer.parseInt(rootProject.ext.javaVersion)
|
compileJava.options.release.set Integer.parseInt(rootProject.ext.javaVersion)
|
||||||
javadoc.options.encoding = 'UTF-8'
|
javadoc.options.encoding = 'UTF-8'
|
||||||
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
|
javadoc.options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
@@ -85,9 +86,9 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3'
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3'
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.11.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.11.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':common')
|
implementation project(path: ':common')
|
||||||
|
|
||||||
implementation 'net.william278.uniform:uniform-bukkit:1.2.1'
|
implementation 'net.william278.uniform:uniform-bukkit:1.2.3'
|
||||||
implementation 'net.william278:mpdbdataconverter:1.0.1'
|
implementation 'net.william278:mpdbdataconverter:1.0.1'
|
||||||
implementation 'net.william278:hsldataconverter:1.0'
|
implementation 'net.william278:hsldataconverter:1.0'
|
||||||
implementation 'net.william278:mapdataapi:1.0.3'
|
implementation 'net.william278:mapdataapi:2.0'
|
||||||
implementation 'org.bstats:bstats-bukkit:3.1.0'
|
implementation 'org.bstats:bstats-bukkit:3.1.0'
|
||||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
|
||||||
implementation 'dev.triumphteam:triumph-gui:3.1.10'
|
implementation 'dev.triumphteam:triumph-gui:3.1.10'
|
||||||
implementation 'space.arim.morepaperlib:morepaperlib:0.4.4'
|
implementation 'space.arim.morepaperlib:morepaperlib:0.4.4'
|
||||||
implementation 'de.tr7zw:item-nbt-api:2.13.2'
|
implementation 'de.tr7zw:item-nbt-api:2.14.1-SNAPSHOT'
|
||||||
|
|
||||||
compileOnly "org.spigotmc:spigot-api:${bukkit_spigot_api}"
|
compileOnly "org.spigotmc:spigot-api:${bukkit_spigot_api}"
|
||||||
compileOnly 'com.github.retrooper.packetevents:spigot:2.3.0'
|
compileOnly 'com.github.retrooper.packetevents:spigot:2.3.0'
|
||||||
compileOnly 'com.comphenix.protocol:ProtocolLib:5.1.0'
|
compileOnly 'com.comphenix.protocol:ProtocolLib:5.3.0'
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.34'
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
compileOnly 'commons-io:commons-io:2.17.0'
|
compileOnly 'commons-io:commons-io:2.18.0'
|
||||||
compileOnly 'org.json:json:20240303'
|
compileOnly 'org.json:json:20240303'
|
||||||
compileOnly 'net.william278:minedown:1.8.2'
|
compileOnly 'net.william278:minedown:1.8.2'
|
||||||
compileOnly 'de.exlll:configlib-yaml:4.5.0'
|
compileOnly 'de.exlll:configlib-yaml:4.5.0'
|
||||||
compileOnly 'com.zaxxer:HikariCP:6.0.0'
|
compileOnly 'com.zaxxer:HikariCP:6.2.1'
|
||||||
compileOnly 'net.william278:DesertWell:2.0.4'
|
compileOnly 'net.william278:DesertWell:2.0.4'
|
||||||
compileOnly 'net.william278:AdvancementAPI:97a9583413'
|
compileOnly 'net.william278:AdvancementAPI:97a9583413'
|
||||||
compileOnly "redis.clients:jedis:$jedis_version"
|
compileOnly "redis.clients:jedis:$jedis_version"
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import de.tr7zw.changeme.nbtapi.utils.DataFixerUtil;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -78,6 +79,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.Supplier,
|
public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.Supplier,
|
||||||
BukkitEventDispatcher, BukkitMapPersister {
|
BukkitEventDispatcher, BukkitMapPersister {
|
||||||
|
|
||||||
@@ -127,6 +129,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
|
|||||||
loadSettings();
|
loadSettings();
|
||||||
loadLocales();
|
loadLocales();
|
||||||
loadServer();
|
loadServer();
|
||||||
|
validateConfigFiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.eventListener = createEventListener();
|
this.eventListener = createEventListener();
|
||||||
@@ -330,6 +333,22 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
|
|||||||
return Version.fromString(getServer().getBukkitVersion());
|
return Version.fromString(getServer().getBukkitVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDataVersion(@NotNull Version mcVersion) {
|
||||||
|
return switch (mcVersion.toStringWithoutMetadata()) {
|
||||||
|
case "1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5" -> DataFixerUtil.VERSION1_16_5;
|
||||||
|
case "1.17", "1.17.1" -> DataFixerUtil.VERSION1_17_1;
|
||||||
|
case "1.18", "1.18.1", "1.18.2" -> DataFixerUtil.VERSION1_18_2;
|
||||||
|
case "1.19", "1.19.1", "1.19.2" -> DataFixerUtil.VERSION1_19_2;
|
||||||
|
case "1.20", "1.20.1", "1.20.2" -> DataFixerUtil.VERSION1_20_2;
|
||||||
|
case "1.20.3", "1.20.4" -> DataFixerUtil.VERSION1_20_4;
|
||||||
|
case "1.20.5", "1.20.6" -> DataFixerUtil.VERSION1_20_5;
|
||||||
|
case "1.21", "1.21.1" -> DataFixerUtil.VERSION1_21;
|
||||||
|
case "1.21.2", "1.21.3" -> DataFixerUtil.VERSION1_21_2;
|
||||||
|
case "1.21.4" -> 4189/*DataFixerUtil.VERSION1_21_4*/;
|
||||||
|
default -> DataFixerUtil.getCurrentVersion();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getPlatformType() {
|
public String getPlatformType() {
|
||||||
|
|||||||
@@ -153,21 +153,11 @@ public class BukkitSerializer {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private ReadWriteNBT upgradeItemData(@NotNull ReadWriteNBT tag, @NotNull Version mcVersion)
|
private ReadWriteNBT upgradeItemData(@NotNull ReadWriteNBT tag, @NotNull Version mcVersion)
|
||||||
throws NoSuchFieldException, IllegalAccessException {
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
return DataFixerUtil.fixUpItemData(tag, getDataVersion(mcVersion), DataFixerUtil.getCurrentVersion());
|
return DataFixerUtil.fixUpItemData(
|
||||||
}
|
tag,
|
||||||
|
getPlugin().getDataVersion(mcVersion),
|
||||||
private int getDataVersion(@NotNull Version mcVersion) {
|
DataFixerUtil.getCurrentVersion()
|
||||||
return switch (mcVersion.toStringWithoutMetadata()) {
|
);
|
||||||
case "1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5" -> DataFixerUtil.VERSION1_16_5;
|
|
||||||
case "1.17", "1.17.1" -> DataFixerUtil.VERSION1_17_1;
|
|
||||||
case "1.18", "1.18.1", "1.18.2" -> DataFixerUtil.VERSION1_18_2;
|
|
||||||
case "1.19", "1.19.1", "1.19.2" -> DataFixerUtil.VERSION1_19_2;
|
|
||||||
case "1.20", "1.20.1", "1.20.2" -> DataFixerUtil.VERSION1_20_2;
|
|
||||||
case "1.20.3", "1.20.4" -> DataFixerUtil.VERSION1_20_4;
|
|
||||||
case "1.20.5", "1.20.6" -> DataFixerUtil.VERSION1_20_5;
|
|
||||||
case "1.21" -> DataFixerUtil.VERSION1_21;
|
|
||||||
default -> DataFixerUtil.getCurrentVersion();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -229,7 +219,7 @@ public class BukkitSerializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BukkitData.PersistentData deserialize(@NotNull String serialized) throws DeserializationException {
|
public BukkitData.PersistentData deserialize(@NotNull String serialized) throws DeserializationException {
|
||||||
return BukkitData.PersistentData.from(new NBTContainer(serialized));
|
return BukkitData.PersistentData.from((NBTContainer) NBT.parseNBT(serialized));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class BukkitUser extends OnlineUser implements BukkitUserDataHolder {
|
|||||||
if (!editable) {
|
if (!editable) {
|
||||||
builder.disableAllInteractions();
|
builder.disableAllInteractions();
|
||||||
}
|
}
|
||||||
final StorageGui gui = builder.enableOtherActions()
|
final StorageGui gui = builder
|
||||||
.apply(a -> a.getInventory().setContents(contents))
|
.apply(a -> a.getInventory().setContents(contents))
|
||||||
.title(title.toComponent()).create();
|
.title(title.toComponent()).create();
|
||||||
gui.setCloseGuiAction((close) -> onClose.accept(BukkitData.Items.ItemArray.adapt(
|
gui.setCloseGuiAction((close) -> onClose.accept(BukkitData.Items.ItemArray.adapt(
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ public interface BukkitMapPersister {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render the map
|
// Render the map
|
||||||
final PersistentMapCanvas canvas = new PersistentMapCanvas(view);
|
final int dataVersion = getPlugin().getDataVersion(getPlugin().getMinecraftVersion());
|
||||||
|
final PersistentMapCanvas canvas = new PersistentMapCanvas(view, dataVersion);
|
||||||
for (MapRenderer renderer : view.getRenderers()) {
|
for (MapRenderer renderer : view.getRenderers()) {
|
||||||
renderer.render(view, canvas, delegateRenderer);
|
renderer.render(view, canvas, delegateRenderer);
|
||||||
getPlugin().debug(String.format("Rendered locked map canvas to view (#%s)", view.getId()));
|
getPlugin().debug(String.format("Rendered locked map canvas to view (#%s)", view.getId()));
|
||||||
@@ -140,6 +141,7 @@ public interface BukkitMapPersister {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ItemStack applyMapView(@NotNull ItemStack map) {
|
private ItemStack applyMapView(@NotNull ItemStack map) {
|
||||||
|
final int dataVersion = getPlugin().getDataVersion(getPlugin().getMinecraftVersion());
|
||||||
final MapMeta meta = Objects.requireNonNull((MapMeta) map.getItemMeta());
|
final MapMeta meta = Objects.requireNonNull((MapMeta) map.getItemMeta());
|
||||||
NBT.get(map, nbt -> {
|
NBT.get(map, nbt -> {
|
||||||
if (!nbt.hasTag(MAP_DATA_KEY)) {
|
if (!nbt.hasTag(MAP_DATA_KEY)) {
|
||||||
@@ -178,8 +180,9 @@ public interface BukkitMapPersister {
|
|||||||
final MapData canvasData;
|
final MapData canvasData;
|
||||||
try {
|
try {
|
||||||
getPlugin().debug("Deserializing map data from NBT and generating view...");
|
getPlugin().debug("Deserializing map data from NBT and generating view...");
|
||||||
canvasData = MapData.fromByteArray(Objects.requireNonNull(mapData.getByteArray(MAP_PIXEL_DATA_KEY),
|
canvasData = MapData.fromByteArray(
|
||||||
"Map pixel data is null"));
|
dataVersion,
|
||||||
|
Objects.requireNonNull(mapData.getByteArray(MAP_PIXEL_DATA_KEY), "Pixel data null!"));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
getPlugin().log(Level.WARNING, "Failed to deserialize map data from NBT", e);
|
getPlugin().log(Level.WARNING, "Failed to deserialize map data from NBT", e);
|
||||||
return;
|
return;
|
||||||
@@ -294,6 +297,7 @@ public interface BukkitMapPersister {
|
|||||||
/**
|
/**
|
||||||
* A {@link MapRenderer} that can be used to render persistently serialized {@link MapData} to a {@link MapView}
|
* A {@link MapRenderer} that can be used to render persistently serialized {@link MapData} to a {@link MapView}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
class PersistentMapRenderer extends MapRenderer {
|
class PersistentMapRenderer extends MapRenderer {
|
||||||
|
|
||||||
private final MapData canvasData;
|
private final MapData canvasData;
|
||||||
@@ -308,7 +312,7 @@ public interface BukkitMapPersister {
|
|||||||
// We set the pixels in this order to avoid the map being rendered upside down
|
// We set the pixels in this order to avoid the map being rendered upside down
|
||||||
for (int i = 0; i < 128; i++) {
|
for (int i = 0; i < 128; i++) {
|
||||||
for (int j = 0; j < 128; j++) {
|
for (int j = 0; j < 128; j++) {
|
||||||
canvas.setPixelColor(j, i, canvasData.getMapColorAt(i, j));
|
canvas.setPixel(j, i, (byte) canvasData.getColorAt(i, j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,13 +359,16 @@ public interface BukkitMapPersister {
|
|||||||
/**
|
/**
|
||||||
* A {@link MapCanvas} implementation used for pre-rendering maps to be converted into {@link MapData}
|
* A {@link MapCanvas} implementation used for pre-rendering maps to be converted into {@link MapData}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
class PersistentMapCanvas implements MapCanvas {
|
class PersistentMapCanvas implements MapCanvas {
|
||||||
|
|
||||||
|
private final int mapDataVersion;
|
||||||
private final MapView mapView;
|
private final MapView mapView;
|
||||||
private final int[][] pixels = new int[128][128];
|
private final int[][] pixels = new int[128][128];
|
||||||
private MapCursorCollection cursors;
|
private MapCursorCollection cursors;
|
||||||
|
|
||||||
private PersistentMapCanvas(@NotNull MapView mapView) {
|
private PersistentMapCanvas(@NotNull MapView mapView, int mapDataVersion) {
|
||||||
|
this.mapDataVersion = mapDataVersion;
|
||||||
this.mapView = mapView;
|
this.mapView = mapView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,24 +404,24 @@ public interface BukkitMapPersister {
|
|||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public byte getBasePixel(int x, int y) {
|
public byte getBasePixel(int x, int y) {
|
||||||
return getPixel(x, y);
|
return (byte) pixels[x][y];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPixelColor(int i, int i1, @Nullable Color color) {
|
public void setPixelColor(int x, int y, @Nullable Color color) {
|
||||||
pixels[i][i1] = color == null ? 0 : color.getRGB();
|
pixels[x][y] = color == null ? -1 : MapPalette.matchColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Color getPixelColor(int x, int y) {
|
public Color getPixelColor(int x, int y) {
|
||||||
return getBasePixelColor(x, y);
|
return MapPalette.getColor((byte) pixels[x][y]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Color getBasePixelColor(int x, int y) {
|
public Color getBasePixelColor(int x, int y) {
|
||||||
return new Color(pixels[x][y]);
|
return MapPalette.getColor((byte) pixels[x][y]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -459,7 +466,7 @@ public interface BukkitMapPersister {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return MapData.fromPixels(pixels, getDimension(), (byte) 2, banners, List.of());
|
return MapData.fromPixels(mapDataVersion, pixels, getDimension(), (byte) 2, banners, List.of());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'commons-io:commons-io:2.17.0'
|
api 'commons-io:commons-io:2.18.0'
|
||||||
api 'org.apache.commons:commons-text:1.12.0'
|
api 'org.apache.commons:commons-text:1.12.0'
|
||||||
api 'net.william278:minedown:1.8.2'
|
api 'net.william278:minedown:1.8.2'
|
||||||
api 'org.json:json:20240303'
|
api 'org.json:json:20240303'
|
||||||
@@ -12,14 +12,14 @@ dependencies {
|
|||||||
api 'de.exlll:configlib-yaml:4.5.0'
|
api 'de.exlll:configlib-yaml:4.5.0'
|
||||||
api 'net.william278:paginedown:1.1.2'
|
api 'net.william278:paginedown:1.1.2'
|
||||||
api 'net.william278:DesertWell:2.0.4'
|
api 'net.william278:DesertWell:2.0.4'
|
||||||
api('com.zaxxer:HikariCP:6.0.0') {
|
api('com.zaxxer:HikariCP:6.2.1') {
|
||||||
exclude module: 'slf4j-api'
|
exclude module: 'slf4j-api'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOnly 'net.william278.uniform:uniform-common:1.2.1'
|
compileOnly 'net.william278.uniform:uniform-common:1.2.3'
|
||||||
compileOnly 'com.mojang:brigadier:1.1.8'
|
compileOnly 'com.mojang:brigadier:1.1.8'
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.34'
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
compileOnly 'org.jetbrains:annotations:24.1.0'
|
compileOnly 'org.jetbrains:annotations:26.0.1'
|
||||||
compileOnly 'net.kyori:adventure-api:4.17.0'
|
compileOnly 'net.kyori:adventure-api:4.17.0'
|
||||||
compileOnly 'net.kyori:adventure-platform-api:4.3.4'
|
compileOnly 'net.kyori:adventure-platform-api:4.3.4'
|
||||||
compileOnly 'com.google.guava:guava:33.3.1-jre'
|
compileOnly 'com.google.guava:guava:33.3.1-jre'
|
||||||
@@ -36,7 +36,7 @@ dependencies {
|
|||||||
testImplementation 'com.google.guava:guava:33.3.1-jre'
|
testImplementation 'com.google.guava:guava:33.3.1-jre'
|
||||||
testImplementation 'com.github.plan-player-analytics:Plan:5.5.2272'
|
testImplementation 'com.github.plan-player-analytics:Plan:5.5.2272'
|
||||||
testCompileOnly 'de.exlll:configlib-yaml:4.5.0'
|
testCompileOnly 'de.exlll:configlib-yaml:4.5.0'
|
||||||
testCompileOnly 'org.jetbrains:annotations:24.1.0'
|
testCompileOnly 'org.jetbrains:annotations:26.0.1'
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
}
|
}
|
||||||
@@ -249,6 +249,14 @@ public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider
|
|||||||
@NotNull
|
@NotNull
|
||||||
Version getMinecraftVersion();
|
Version getMinecraftVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data version for a Minecraft version
|
||||||
|
*
|
||||||
|
* @param minecraftVersion the Minecraft version
|
||||||
|
* @return the data version int
|
||||||
|
*/
|
||||||
|
int getDataVersion(@NotNull Version minecraftVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the platform type
|
* Returns the platform type
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -99,6 +99,18 @@ public class HuskSyncAPI {
|
|||||||
return plugin.supplyAsync(() -> plugin.getDatabase().getUser(uuid));
|
return plugin.supplyAsync(() -> plugin.getDatabase().getUser(uuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an {@link OnlineUser} by their UUID
|
||||||
|
*
|
||||||
|
* @param uuid the UUID of the user to get
|
||||||
|
* @return The {@link OnlineUser} wrapped in an optional, if they are online on <i>this</i> server.
|
||||||
|
* @since 3.7.2
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Optional<OnlineUser> getOnlineUser(@NotNull UUID uuid) {
|
||||||
|
return plugin.getOnlineUser(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a {@link User} by their username
|
* Get a {@link User} by their username
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -131,6 +131,15 @@ public interface ConfigProvider {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void validateConfigFiles() {
|
||||||
|
// Validate server name is default
|
||||||
|
if (getServerName().equals("server")) {
|
||||||
|
getPlugin().log(Level.WARNING, "The server name set in ~/plugins/HuskSync/server.yml appears to" +
|
||||||
|
"be unchanged from the default (currently set to: \"server\"). Please check that this value has" +
|
||||||
|
"been updated to match the case-sensitive ID of this server in your proxy config file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a plugin resource
|
* Get a plugin resource
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -913,6 +913,8 @@ public class DataSnapshot {
|
|||||||
|
|
||||||
private final boolean fireDataSaveEvent;
|
private final boolean fireDataSaveEvent;
|
||||||
|
|
||||||
|
private static Map<String, SaveCause> registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or create a {@link SaveCause} from a name
|
* Get or create a {@link SaveCause} from a name
|
||||||
*
|
*
|
||||||
@@ -921,7 +923,7 @@ public class DataSnapshot {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static SaveCause of(@NotNull String name) {
|
public static SaveCause of(@NotNull String name) {
|
||||||
return new SaveCause(name.length() > 32 ? name.substring(0, 31) : name, true);
|
return of(name,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -933,7 +935,14 @@ public class DataSnapshot {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static SaveCause of(@NotNull String name, boolean firesSaveEvent) {
|
public static SaveCause of(@NotNull String name, boolean firesSaveEvent) {
|
||||||
return new SaveCause(name.length() > 32 ? name.substring(0, 31) : name, firesSaveEvent);
|
name = name.length() > 32 ? name.substring(0, 31) : name;
|
||||||
|
|
||||||
|
if (registry == null) registry = new HashMap<>();
|
||||||
|
if (registry.containsKey(name)) return registry.get(name);
|
||||||
|
|
||||||
|
SaveCause cause = new SaveCause(name, firesSaveEvent);
|
||||||
|
registry.put(cause.name(), cause);
|
||||||
|
return cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -944,11 +953,10 @@ public class DataSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ApiStatus.Obsolete
|
||||||
public static SaveCause[] values() {
|
public static SaveCause[] values() {
|
||||||
return new SaveCause[]{
|
if (registry == null) registry = new HashMap<>();
|
||||||
DISCONNECT, WORLD_SAVE, DEATH, SERVER_SHUTDOWN, INVENTORY_COMMAND, ENDERCHEST_COMMAND,
|
return registry.values().toArray(new SaveCause[0]);
|
||||||
BACKUP_RESTORE, API, MPDB_MIGRATION, LEGACY_MIGRATION, CONVERTED_FROM_V2
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import net.kyori.adventure.key.Key;
|
|||||||
import org.intellij.lang.annotations.Subst;
|
import org.intellij.lang.annotations.Subst;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -229,11 +230,8 @@ public class Identifier {
|
|||||||
* @return {@code true} if the given object is an identifier with the same key as this identifier
|
* @return {@code true} if the given object is an identifier with the same key as this identifier
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
if (obj instanceof Identifier other) {
|
return obj instanceof Identifier other ? toString().equals(other.toString()) : super.equals(obj);
|
||||||
return key.equals(other.key);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the config entry for the identifier
|
// Get the config entry for the identifier
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ The HuskSync API is available for the following platforms:
|
|||||||
* `fabric` - Fabric API for Minecraft. Provides Fabric API event listeners and adapters to `net.minecraft` objects.
|
* `fabric` - Fabric API for Minecraft. Provides Fabric API event listeners and adapters to `net.minecraft` objects.
|
||||||
* `common` - Common API for all platforms.
|
* `common` - Common API for all platforms.
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Targeting older versions</summary>
|
<summary>Targeting older versions</summary>
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
HuskSync supports the following versions of Minecraft. Since v3.7, you must download the correct version of HuskSync for your server:
|
HuskSync supports the following versions of Minecraft. Since v3.7, you must download the correct version of HuskSync for your server:
|
||||||
|
|
||||||
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Ends |
|
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Status |
|
||||||
|:---------------:|:---------------:|:------------:|:--------------|:--------------------------|
|
|:---------------:|:---------------:|:------------:|:--------------|:-----------------------------|
|
||||||
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **Active Release** |
|
| 1.21.4 | _latest_ | 21 | Paper, Fabric | ✅ **Active Release** |
|
||||||
| 1.20.6 | 3.6.8 | 17 | Paper | ❌ _October 2024_ |
|
| 1.21.3 | 3.7.1 | 21 | Paper, Fabric | 🗃️ Archived (December 2024) |
|
||||||
| 1.20.4 | 3.6.8 | 17 | Paper | ❌ _July 2024_ |
|
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **November 2024** (LTS) |
|
||||||
| 1.20.1 | _latest_ | 17 | Paper, Fabric | ✅ **November 2025** (LTS) |
|
| 1.20.6 | 3.6.8 | 17 | Paper | 🗃️ Archived (October 2024) |
|
||||||
| 1.17.1 - 1.19.4 | 3.6.8 | 17 | Paper | ❌ _Support ended_ |
|
| 1.20.4 | 3.6.8 | 17 | Paper | 🗃️ Archived (July 2024) |
|
||||||
| 1.16.5 | 3.2.1 | 16 | Paper | ❌ _Support ended_ |
|
| 1.20.1 | _latest_ | 17 | Paper, Fabric | ✅ **November 2025** (LTS) |
|
||||||
|
| 1.17.1 - 1.19.4 | 3.6.8 | 17 | Paper | 🗃️ Archived |
|
||||||
|
| 1.16.5 | 3.2.1 | 16 | Paper | 🗃️ Archived |
|
||||||
|
|
||||||
HuskSync is primarily developed against the latest release. Old Minecraft versions are allocated a support channel based on popularity, mod support, etc:
|
HuskSync is primarily developed against the latest release. Old Minecraft versions are allocated a support channel based on popularity, mod support, etc:
|
||||||
|
|
||||||
* Long Term Support (LTS) – Supported for up to 12-18 months
|
* Long Term Support (LTS) – Supported for up to 12-18 months
|
||||||
* Non-Long Term Support (Non-LTS) – Supported for 3-6 months
|
* Non-Long Term Support (Non-LTS) – Supported for 3-6 months
|
||||||
|
|
||||||
## Incompatible
|
## Incompatible versions
|
||||||
This plugin does not support the following software-Minecraft version combinations. The plugin will fail to load if you attempt to run it with these versions. Apologies for the inconvenience.
|
This plugin does not support the following software-Minecraft version combinations. The plugin will fail to load if you attempt to run it with these versions. Apologies for the inconvenience.
|
||||||
|
|
||||||
| Minecraft | Server Software | Notes |
|
| Minecraft | Server Software | Notes |
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ huskSyncAPI.getUser(uuid).thenAccept(optionalUser -> {
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
* If you have an online `org.bukkit.Player` object, you can use `BukkitPlayer#adapt(player)` to get an `OnlineUser` (extends `User`), representing a logged-in user.
|
* If you have an online `org.bukkit.Player` object, you can use `BukkitPlayer#adapt(player)` to get an `OnlineUser` (extends `User`), representing a logged-in user.
|
||||||
|
* You can also use `#getOnlineUser(UUID)` to get an OnlineUser by their UUID - note this only works for players online on the server the logic is called from, however.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Code Example — Getting an online user</summary>
|
<summary>Code Example — Getting an online user</summary>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Welcome! This is the plugin documentation for HuskSync v3.x+. Please click throu
|
|||||||
|
|
||||||
## Guides
|
## Guides
|
||||||
* 📚 [[Setup]]
|
* 📚 [[Setup]]
|
||||||
|
* ⚠️ [[Compatibility]]
|
||||||
* 📄 [[Config File]]
|
* 📄 [[Config File]]
|
||||||
* 🔗 [[Troubleshooting]]
|
* 🔗 [[Troubleshooting]]
|
||||||
* ↪️ [[Data Rotation]]
|
* ↪️ [[Data Rotation]]
|
||||||
|
|||||||
@@ -25,3 +25,17 @@ If you are hosting your Redis server on the same node as your servers, you need
|
|||||||
|
|
||||||
### MySQL connection problems on Pterodactyl
|
### MySQL connection problems on Pterodactyl
|
||||||
If you have more than one MySQL server connected to your panel, you may need to set `useSSL=true` in the parameters.
|
If you have more than one MySQL server connected to your panel, you may need to set `useSSL=true` in the parameters.
|
||||||
|
|
||||||
|
### Issues with player data going out of sync during a server restart
|
||||||
|
This can happen due to the way in which your server restarts. If your server uses either:
|
||||||
|
|
||||||
|
* `/restart` (this is a weird Spigot command that uses legacy bash scripting)
|
||||||
|
* ANY restart plugin, e.g. UltimateAutoRestart (these basically execute an API-called restart using the same legacy bash logic as per above)
|
||||||
|
|
||||||
|
These are **not compatible** with HuskSync in most cases due to the way in which this causes restart servers causing shutdown logic to process in strange and unpredictable orders, usually before HuskSync has had a chance to scan and perform its shutdown logic. To safely restart your server, please use:
|
||||||
|
|
||||||
|
* A Pterodactyl task to perform a Restart. This executes the Power Action program stopcode (and then execute the startup command when the container has terminated)
|
||||||
|
* A cronjob to send a stop command / Power Action program stopcode, listen for the service to fully terminate, and then execute your startup command
|
||||||
|
* For manual restarts, executing `/stop` and starting your server up with the startup command is totally fine.
|
||||||
|
|
||||||
|
It's not a great idea to use a plugin to handle restarts. Plugins are only able to operate when your server is turned on and must rely on scripts which don't safely shutdown servers when restarting.
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
## Guides
|
## Guides
|
||||||
* 📚 [[Setup]]
|
* 📚 [[Setup]]
|
||||||
|
* ⚠️ [[Compatibility]]
|
||||||
* 📄 [[Config File]]
|
* 📄 [[Config File]]
|
||||||
* 🔗 [[Troubleshooting]]
|
* 🔗 [[Troubleshooting]]
|
||||||
* ↪️ [[Data Rotation]]
|
* ↪️ [[Data Rotation]]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '1.7-SNAPSHOT'
|
id 'fabric-loom' version "$fabric_loom_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'fabric-loom'
|
apply plugin: 'fabric-loom'
|
||||||
@@ -18,7 +18,7 @@ dependencies {
|
|||||||
modImplementation include("net.kyori:adventure-platform-fabric:${fabric_adventure_platform_version}")
|
modImplementation include("net.kyori:adventure-platform-fabric:${fabric_adventure_platform_version}")
|
||||||
modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}")
|
modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}")
|
||||||
modImplementation include("eu.pb4:sgui:${fabric_sgui_version}")
|
modImplementation include("eu.pb4:sgui:${fabric_sgui_version}")
|
||||||
modImplementation include('net.william278.uniform:uniform-fabric:1.2.1+1.20.1')
|
modImplementation include("net.william278.uniform:uniform-fabric:1.2.3+${minecraft_version}")
|
||||||
modCompileOnly "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
|
modCompileOnly "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
|
||||||
|
|
||||||
implementation include('org.apache.commons:commons-pool2:2.12.0')
|
implementation include('org.apache.commons:commons-pool2:2.12.0')
|
||||||
@@ -28,11 +28,11 @@ dependencies {
|
|||||||
implementation include("org.postgresql:postgresql:$postgres_driver_version")
|
implementation include("org.postgresql:postgresql:$postgres_driver_version")
|
||||||
implementation include("org.xerial.snappy:snappy-java:$snappy_version")
|
implementation include("org.xerial.snappy:snappy-java:$snappy_version")
|
||||||
|
|
||||||
compileOnly 'org.jetbrains:annotations:24.1.0'
|
compileOnly 'org.jetbrains:annotations:26.0.1'
|
||||||
compileOnly 'net.william278:DesertWell:2.0.4'
|
compileOnly 'net.william278:DesertWell:2.0.4'
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.34'
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
|
|
||||||
shadow project(path: ":common")
|
shadow project(path: ":common")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
|||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.fabricmc.loader.api.ModContainer;
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
import net.kyori.adventure.platform.AudienceProvider;
|
import net.kyori.adventure.platform.AudienceProvider;
|
||||||
import net.kyori.adventure.platform.fabric.FabricServerAudiences;
|
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.william278.desertwell.util.Version;
|
import net.william278.desertwell.util.Version;
|
||||||
import net.william278.husksync.adapter.DataAdapter;
|
import net.william278.husksync.adapter.DataAdapter;
|
||||||
@@ -78,11 +78,25 @@ import java.util.logging.Level;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync, FabricTask.Supplier,
|
public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync, FabricTask.Supplier,
|
||||||
FabricEventDispatcher {
|
FabricEventDispatcher {
|
||||||
|
|
||||||
private static final String PLATFORM_TYPE_ID = "fabric";
|
private static final String PLATFORM_TYPE_ID = "fabric";
|
||||||
|
|
||||||
|
private static final int VERSION1_16_5 = 2586;
|
||||||
|
private static final int VERSION1_17_1 = 2730;
|
||||||
|
private static final int VERSION1_18_2 = 2975;
|
||||||
|
private static final int VERSION1_19_2 = 3120;
|
||||||
|
private static final int VERSION1_19_4 = 3337;
|
||||||
|
private static final int VERSION1_20_1 = 3465;
|
||||||
|
private static final int VERSION1_20_2 = 3578;
|
||||||
|
private static final int VERSION1_20_4 = 3700;
|
||||||
|
private static final int VERSION1_20_5 = 3837;
|
||||||
|
private static final int VERSION1_21_1 = 3955;
|
||||||
|
private static final int VERSION1_21_3 = 4082;
|
||||||
|
private static final int VERSION1_21_4 = 4189; // Current
|
||||||
|
|
||||||
private final TreeMap<Identifier, Serializer<? extends Data>> serializers = Maps.newTreeMap(
|
private final TreeMap<Identifier, Serializer<? extends Data>> serializers = Maps.newTreeMap(
|
||||||
SerializerRegistry.DEPENDENCY_ORDER_COMPARATOR
|
SerializerRegistry.DEPENDENCY_ORDER_COMPARATOR
|
||||||
);
|
);
|
||||||
@@ -125,6 +139,7 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
|
|||||||
loadSettings();
|
loadSettings();
|
||||||
loadLocales();
|
loadLocales();
|
||||||
loadServer();
|
loadServer();
|
||||||
|
validateConfigFiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register commands
|
// Register commands
|
||||||
@@ -142,7 +157,7 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
|
|||||||
|
|
||||||
private void onEnable() {
|
private void onEnable() {
|
||||||
// Initial plugin setup
|
// Initial plugin setup
|
||||||
this.audiences = FabricServerAudiences.of(minecraftServer);
|
this.audiences = MinecraftServerAudiences.of(minecraftServer);
|
||||||
|
|
||||||
// Check compatibility
|
// Check compatibility
|
||||||
checkCompatibility();
|
checkCompatibility();
|
||||||
@@ -274,6 +289,15 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
|
|||||||
return FabricUniform.getInstance(mod.getMetadata().getId());
|
return FabricUniform.getInstance(mod.getMetadata().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Map<Identifier, Data> getPlayerCustomDataStore(@NotNull OnlineUser user) {
|
||||||
|
return playerCustomDataStore.compute(
|
||||||
|
user.getUuid(),
|
||||||
|
(uuid, data) -> data == null ? Maps.newHashMap() : data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public InputStream getResource(@NotNull String name) {
|
public InputStream getResource(@NotNull String name) {
|
||||||
@@ -336,6 +360,25 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
|
|||||||
return Version.fromString(minecraftServer.getVersion());
|
return Version.fromString(minecraftServer.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public int getDataVersion(@NotNull Version mcVersion) {
|
||||||
|
return switch (mcVersion.toStringWithoutMetadata()) {
|
||||||
|
case "1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5" -> VERSION1_16_5;
|
||||||
|
case "1.17", "1.17.1" -> VERSION1_17_1;
|
||||||
|
case "1.18", "1.18.1", "1.18.2" -> VERSION1_18_2;
|
||||||
|
case "1.19", "1.19.1", "1.19.2" -> VERSION1_19_2;
|
||||||
|
case "1.19.4" -> VERSION1_19_4;
|
||||||
|
case "1.20", "1.20.1" -> VERSION1_20_1;
|
||||||
|
case "1.20.2" -> VERSION1_20_2;
|
||||||
|
case "1.20.4" -> VERSION1_20_4;
|
||||||
|
case "1.20.5", "1.20.6" -> VERSION1_20_5;
|
||||||
|
case "1.21", "1.21.1" -> VERSION1_21_1;
|
||||||
|
case "1.21.2", "1.21.3" -> VERSION1_21_3;
|
||||||
|
case "1.21.4" -> VERSION1_21_4;
|
||||||
|
default -> VERSION1_21_4; // Current supported ver
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getPlatformType() {
|
public String getPlatformType() {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import net.william278.husksync.FabricHuskSync;
|
|||||||
import net.william278.husksync.HuskSync;
|
import net.william278.husksync.HuskSync;
|
||||||
import net.william278.husksync.adapter.Adaptable;
|
import net.william278.husksync.adapter.Adaptable;
|
||||||
import net.william278.husksync.config.Settings.SynchronizationSettings.AttributeSettings;
|
import net.william278.husksync.config.Settings.SynchronizationSettings.AttributeSettings;
|
||||||
|
import net.william278.husksync.mixins.HungerManagerMixin;
|
||||||
import net.william278.husksync.user.FabricUser;
|
import net.william278.husksync.user.FabricUser;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -157,7 +158,7 @@ public abstract class FabricData implements Data {
|
|||||||
@Override
|
@Override
|
||||||
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
|
public void apply(@NotNull FabricUser user, @NotNull FabricHuskSync plugin) throws IllegalStateException {
|
||||||
final ServerPlayerEntity player = user.getPlayer();
|
final ServerPlayerEntity player = user.getPlayer();
|
||||||
player.playerScreenHandler.clearCraftingSlots();
|
player.playerScreenHandler.getCraftingInput().clear();
|
||||||
player.currentScreenHandler.setCursorStack(ItemStack.EMPTY);
|
player.currentScreenHandler.setCursorStack(ItemStack.EMPTY);
|
||||||
final ItemStack[] items = getContents();
|
final ItemStack[] items = getContents();
|
||||||
for (int slot = 0; slot < player.getInventory().size(); slot++) {
|
for (int slot = 0; slot < player.getInventory().size(); slot++) {
|
||||||
@@ -693,7 +694,7 @@ public abstract class FabricData implements Data {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static FabricData.Hunger adapt(@NotNull ServerPlayerEntity player) {
|
public static FabricData.Hunger adapt(@NotNull ServerPlayerEntity player) {
|
||||||
final HungerManager hunger = player.getHungerManager();
|
final HungerManager hunger = player.getHungerManager();
|
||||||
return from(hunger.getFoodLevel(), hunger.getSaturationLevel(), hunger.getExhaustion());
|
return from(hunger.getFoodLevel(), hunger.getSaturationLevel(), ((HungerManagerMixin) hunger).getExhaustion());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -707,7 +708,7 @@ public abstract class FabricData implements Data {
|
|||||||
final HungerManager hunger = player.getHungerManager();
|
final HungerManager hunger = player.getHungerManager();
|
||||||
hunger.setFoodLevel(foodLevel);
|
hunger.setFoodLevel(foodLevel);
|
||||||
hunger.setSaturationLevel(saturation);
|
hunger.setSaturationLevel(saturation);
|
||||||
hunger.setExhaustion(exhaustion);
|
((HungerManagerMixin) hunger).setExhaustion(exhaustion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,17 +142,6 @@ public abstract class FabricSerializer {
|
|||||||
|
|
||||||
private interface ItemDeserializer {
|
private interface ItemDeserializer {
|
||||||
|
|
||||||
int VERSION1_16_5 = 2586;
|
|
||||||
int VERSION1_17_1 = 2730;
|
|
||||||
int VERSION1_18_2 = 2975;
|
|
||||||
int VERSION1_19_2 = 3120;
|
|
||||||
int VERSION1_19_4 = 3337;
|
|
||||||
int VERSION1_20_1 = 3465;
|
|
||||||
int VERSION1_20_2 = 3578; // Future
|
|
||||||
int VERSION1_20_4 = 3700; // Future
|
|
||||||
int VERSION1_20_5 = 3837; // Future
|
|
||||||
int VERSION1_21 = 3953; // Future
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
default ItemStack[] getItems(@NotNull NbtCompound tag, @NotNull Version mcVersion, @NotNull FabricHuskSync plugin) {
|
default ItemStack[] getItems(@NotNull NbtCompound tag, @NotNull Version mcVersion, @NotNull FabricHuskSync plugin) {
|
||||||
try {
|
try {
|
||||||
@@ -186,7 +175,7 @@ public abstract class FabricSerializer {
|
|||||||
if (item == null || item.isEmpty()) {
|
if (item == null || item.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NbtCompound entry = (NbtCompound) item.encode(registryManager);
|
NbtCompound entry = (NbtCompound) item.toNbt(registryManager);
|
||||||
entry.putInt("Slot", i);
|
entry.putInt("Slot", i);
|
||||||
itemList.add(entry);
|
itemList.add(entry);
|
||||||
}
|
}
|
||||||
@@ -213,33 +202,16 @@ public abstract class FabricSerializer {
|
|||||||
return itemStacks;
|
return itemStacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"}) // For NBTOps lookup
|
@SuppressWarnings({"rawtypes", "unchecked"}) // For NBTOps lookup
|
||||||
private NbtCompound upgradeItemData(@NotNull NbtCompound tag, @NotNull Version mcVersion,
|
private NbtCompound upgradeItemData(@NotNull NbtCompound tag, @NotNull Version mcVersion,
|
||||||
@NotNull FabricHuskSync plugin) {
|
@NotNull FabricHuskSync plugin) {
|
||||||
return (NbtCompound) plugin.getMinecraftServer().getDataFixer().update(
|
return (NbtCompound) plugin.getMinecraftServer().getDataFixer().update(
|
||||||
TypeReferences.ITEM_STACK, new Dynamic<Object>((DynamicOps) NbtOps.INSTANCE, tag),
|
TypeReferences.ITEM_STACK, new Dynamic<Object>((DynamicOps) NbtOps.INSTANCE, tag),
|
||||||
getDataVersion(mcVersion), getDataVersion(plugin.getMinecraftVersion())
|
plugin.getDataVersion(mcVersion), plugin.getDataVersion(plugin.getMinecraftVersion())
|
||||||
).getValue();
|
).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getDataVersion(@NotNull Version mcVersion) {
|
|
||||||
return switch (mcVersion.toStringWithoutMetadata()) {
|
|
||||||
case "1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5" -> VERSION1_16_5;
|
|
||||||
case "1.17", "1.17.1" -> VERSION1_17_1;
|
|
||||||
case "1.18", "1.18.1", "1.18.2" -> VERSION1_18_2;
|
|
||||||
case "1.19", "1.19.1", "1.19.2" -> VERSION1_19_2;
|
|
||||||
case "1.19.4" -> VERSION1_19_4;
|
|
||||||
case "1.20", "1.20.1" -> VERSION1_20_1;
|
|
||||||
case "1.20.2" -> VERSION1_20_2; // Future
|
|
||||||
case "1.20.4" -> VERSION1_20_4; // Future
|
|
||||||
case "1.20.5", "1.20.6" -> VERSION1_20_5; // Future
|
|
||||||
case "1.21" -> VERSION1_21; // Future
|
|
||||||
default -> VERSION1_20_1; // Current supported ver
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PotionEffects extends FabricSerializer implements Serializer<FabricData.PotionEffects> {
|
public static class PotionEffects extends FabricSerializer implements Serializer<FabricData.PotionEffects> {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import net.minecraft.server.network.ServerPlayerEntity;
|
|||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.TypedActionResult;
|
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -124,9 +123,8 @@ public class FabricEventListener extends EventListener implements LockedHandler
|
|||||||
return (cancelPlayerEvent(player.getUuid())) ? ActionResult.FAIL : ActionResult.PASS;
|
return (cancelPlayerEvent(player.getUuid())) ? ActionResult.FAIL : ActionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedActionResult<ItemStack> handleItemInteract(PlayerEntity player, World world, Hand hand) {
|
private ActionResult handleItemInteract(PlayerEntity player, World world, Hand hand) {
|
||||||
ItemStack stackInHand = player.getStackInHand(hand);
|
return (cancelPlayerEvent(player.getUuid())) ? ActionResult.FAIL : ActionResult.PASS;
|
||||||
return (cancelPlayerEvent(player.getUuid())) ? TypedActionResult.fail(stackInHand) : TypedActionResult.pass(stackInHand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleBlockBreak(World world, PlayerEntity player, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
|
private boolean handleBlockBreak(World world, PlayerEntity player, BlockPos blockPos, BlockState blockState, BlockEntity blockEntity) {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of HuskSync, licensed under the Apache License 2.0.
|
||||||
|
*
|
||||||
|
* Copyright (c) William278 <will27528@gmail.com>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.william278.husksync.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.HungerManager;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(HungerManager.class)
|
||||||
|
public interface HungerManagerMixin {
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
float getExhaustion();
|
||||||
|
|
||||||
|
@Accessor("exhaustion")
|
||||||
|
void setExhaustion(float exhaustion);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ import net.william278.husksync.event.ItemDropCallback;
|
|||||||
import net.william278.husksync.event.PlayerCommandCallback;
|
import net.william278.husksync.event.PlayerCommandCallback;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@@ -44,18 +45,21 @@ public abstract class ServerPlayNetworkHandlerMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
public ServerPlayerEntity player;
|
public ServerPlayerEntity player;
|
||||||
|
|
||||||
public abstract void sendPacket(Packet<?> packet);
|
@Unique
|
||||||
|
private void sendToPlayer(Packet<?> packet) {
|
||||||
|
this.player.networkHandler.sendPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "onPlayerAction", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "onPlayerAction", at = @At("HEAD"), cancellable = true)
|
||||||
public void onPlayerAction(PlayerActionC2SPacket packet, CallbackInfo ci) {
|
public void onPlayerAction(PlayerActionC2SPacket packet, CallbackInfo ci) {
|
||||||
if (packet.getAction() == PlayerActionC2SPacket.Action.DROP_ITEM
|
if (packet.getAction() == PlayerActionC2SPacket.Action.DROP_ITEM
|
||||||
|| packet.getAction() == PlayerActionC2SPacket.Action.DROP_ALL_ITEMS) {
|
|| packet.getAction() == PlayerActionC2SPacket.Action.DROP_ALL_ITEMS) {
|
||||||
ItemStack stack = player.getStackInHand(Hand.MAIN_HAND);
|
ItemStack stack = player.getStackInHand(Hand.MAIN_HAND);
|
||||||
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
||||||
|
|
||||||
if (result == ActionResult.FAIL) {
|
if (result == ActionResult.FAIL) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(
|
sendToPlayer(new ScreenHandlerSlotUpdateS2CPacket(
|
||||||
-2,
|
-2,
|
||||||
1,
|
1,
|
||||||
player.getInventory().getSlotWithStack(stack),
|
player.getInventory().getSlotWithStack(stack),
|
||||||
@@ -68,30 +72,34 @@ public abstract class ServerPlayNetworkHandlerMixin {
|
|||||||
@Inject(method = "onClickSlot", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "onClickSlot", at = @At("HEAD"), cancellable = true)
|
||||||
public void onClickSlot(ClickSlotC2SPacket packet, CallbackInfo ci) {
|
public void onClickSlot(ClickSlotC2SPacket packet, CallbackInfo ci) {
|
||||||
int slot = packet.getSlot();
|
int slot = packet.getSlot();
|
||||||
if (slot < 0) return;
|
if (slot < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ItemStack stack = this.player.getInventory().getStack(slot);
|
ItemStack stack = this.player.getInventory().getStack(slot);
|
||||||
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
||||||
|
|
||||||
if (result == ActionResult.FAIL) {
|
if (result == ActionResult.FAIL) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(-2, 1, slot, stack));
|
sendToPlayer(new ScreenHandlerSlotUpdateS2CPacket(-2, 1, slot, stack));
|
||||||
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(-1, 1, -1, ItemStack.EMPTY));
|
sendToPlayer(new ScreenHandlerSlotUpdateS2CPacket(-1, 1, -1, ItemStack.EMPTY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "onCreativeInventoryAction", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "onCreativeInventoryAction", at = @At("HEAD"), cancellable = true)
|
||||||
public void onCreativeInventoryAction(CreativeInventoryActionC2SPacket packet, CallbackInfo ci) {
|
public void onCreativeInventoryAction(CreativeInventoryActionC2SPacket packet, CallbackInfo ci) {
|
||||||
int slot = packet.slot();
|
int slot = packet.slot();
|
||||||
if (slot < 0) return;
|
if (slot < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ItemStack stack = this.player.getInventory().getStack(slot);
|
ItemStack stack = this.player.getInventory().getStack(slot);
|
||||||
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
ActionResult result = ItemDropCallback.EVENT.invoker().interact(player, stack);
|
||||||
|
|
||||||
if (result == ActionResult.FAIL) {
|
if (result == ActionResult.FAIL) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(-2, 1, slot, stack));
|
sendToPlayer(new ScreenHandlerSlotUpdateS2CPacket(-2, 1, slot, stack));
|
||||||
this.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(-1, 1, -1, ItemStack.EMPTY));
|
sendToPlayer(new ScreenHandlerSlotUpdateS2CPacket(-1, 1, -1, ItemStack.EMPTY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class ServerWorldMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
private MinecraftServer server;
|
private MinecraftServer server;
|
||||||
|
|
||||||
@Inject(method = "saveLevel", at = @At("HEAD"))
|
@Inject(method = "savePersistentState", at = @At("HEAD"))
|
||||||
public void saveLevel(CallbackInfo ci) {
|
public void saveLevel(CallbackInfo ci) {
|
||||||
if (server.isStopping() || server.isStopped()) {
|
if (server.isStopping() || server.isStopped()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import eu.pb4.sgui.api.elements.GuiElementInterface;
|
|||||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||||
import net.kyori.adventure.audience.Audience;
|
import net.kyori.adventure.audience.Audience;
|
||||||
import net.kyori.adventure.platform.fabric.FabricServerAudiences;
|
import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.screen.GenericContainerScreenHandler;
|
import net.minecraft.screen.GenericContainerScreenHandler;
|
||||||
import net.minecraft.screen.ScreenHandlerType;
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
@@ -102,7 +102,7 @@ public class FabricUser extends OnlineUser implements FabricUserDataHolder {
|
|||||||
this.editable = editable;
|
this.editable = editable;
|
||||||
|
|
||||||
// Set title, items
|
// Set title, items
|
||||||
this.setTitle(((FabricServerAudiences) plugin.getAudiences()).toNative(title.toComponent()));
|
this.setTitle(((MinecraftServerAudiences) plugin.getAudiences()).asNative(title.toComponent()));
|
||||||
this.setLockPlayerInventory(!editable);
|
this.setLockPlayerInventory(!editable);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
final ItemStack item = items.getContents()[i];
|
final ItemStack item = items.getContents()[i];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"package": "net.william278.husksync.mixins",
|
"package": "net.william278.husksync.mixins",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"server": [
|
"server": [
|
||||||
|
"HungerManagerMixin",
|
||||||
"ItemEntityMixin",
|
"ItemEntityMixin",
|
||||||
"PlayerEntityMixin",
|
"PlayerEntityMixin",
|
||||||
"ServerPlayerEntityMixin",
|
"ServerPlayerEntityMixin",
|
||||||
|
|||||||
@@ -4,27 +4,28 @@ org.gradle.daemon=true
|
|||||||
javaVersion=21
|
javaVersion=21
|
||||||
|
|
||||||
# Plugin settings
|
# Plugin settings
|
||||||
plugin_version=3.7
|
plugin_version=3.7.2
|
||||||
minecraft_version=1.21.1
|
minecraft_version=1.21.4
|
||||||
plugin_archive=husksync
|
plugin_archive=husksync
|
||||||
plugin_description=A modern, cross-server player data synchronization system
|
plugin_description=A modern, cross-server player data synchronization system
|
||||||
|
|
||||||
# Drivers
|
# Drivers
|
||||||
jedis_version=5.1.4
|
jedis_version=5.2.0
|
||||||
mysql_driver_version=9.0.0
|
mysql_driver_version=9.1.0
|
||||||
mariadb_driver_version=3.4.1
|
mariadb_driver_version=3.5.1
|
||||||
postgres_driver_version=42.7.3
|
postgres_driver_version=42.7.4
|
||||||
mongodb_driver_version=5.1.2
|
mongodb_driver_version=5.2.1
|
||||||
snappy_version=1.1.10.6
|
snappy_version=1.1.10.7
|
||||||
|
|
||||||
# Spigot/Paper build settings
|
# Spigot/Paper build settings
|
||||||
bukkit_spigot_api=1.21.1-R0.1-SNAPSHOT
|
bukkit_spigot_api=1.21.4-R0.1-SNAPSHOT
|
||||||
bukkit_paper_api=1.21.1-R0.1-SNAPSHOT
|
bukkit_paper_api=1.21.4-R0.1-SNAPSHOT
|
||||||
|
|
||||||
# Fabric build settings
|
# Fabric build settings
|
||||||
fabric_loader_version=0.16.2
|
fabric_loom_version=1.8-SNAPSHOT
|
||||||
fabric_yarn_mappings=1.21.1+build.3
|
fabric_loader_version=0.16.9
|
||||||
fabric_api_version=0.102.1+1.21.1
|
fabric_yarn_mappings=1.21.4+build.1
|
||||||
fabric_adventure_platform_version=5.14.1
|
fabric_api_version=0.111.0+1.21.4
|
||||||
fabric_permissions_api_version=0.3.1
|
fabric_adventure_platform_version=6.1.0
|
||||||
fabric_sgui_version=1.6.0+1.21
|
fabric_permissions_api_version=0.3.3
|
||||||
|
fabric_sgui_version=1.8.1+1.21.4
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
2
gradlew
vendored
2
gradlew
vendored
@@ -55,7 +55,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ dependencies {
|
|||||||
implementation project(':bukkit')
|
implementation project(':bukkit')
|
||||||
compileOnly project(':common')
|
compileOnly project(':common')
|
||||||
|
|
||||||
implementation 'net.william278.uniform:uniform-paper:1.2.1'
|
implementation 'net.william278.uniform:uniform-paper:1.2.2'
|
||||||
|
|
||||||
compileOnly "io.papermc.paper:paper-api:${bukkit_paper_api}"
|
compileOnly "io.papermc.paper:paper-api:${bukkit_paper_api}"
|
||||||
compileOnly 'org.jetbrains:annotations:24.1.0'
|
compileOnly 'org.jetbrains:annotations:26.0.1'
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.34'
|
compileOnly 'org.projectlombok:lombok:1.18.36'
|
||||||
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.34'
|
annotationProcessor 'org.projectlombok:lombok:1.18.36'
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
@@ -49,6 +49,6 @@ shadowJar {
|
|||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
runServer {
|
runServer {
|
||||||
minecraftVersion('1.21.1')
|
minecraftVersion('1.21.4')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unchecked", "unused"})
|
||||||
public class PaperHuskSync extends BukkitHuskSync {
|
public class PaperHuskSync extends BukkitHuskSync {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ public class PaperEventListener extends BukkitEventListener {
|
|||||||
super(plugin);
|
super(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin());
|
||||||
|
lockedHandler.onEnable();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePlayerDeath(@NotNull PlayerDeathEvent event) {
|
public void handlePlayerDeath(@NotNull PlayerDeathEvent event) {
|
||||||
// If the player is locked or the plugin disabling, clear their drops
|
// If the player is locked or the plugin disabling, clear their drops
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from tqdm import tqdm
|
|||||||
class Parameters:
|
class Parameters:
|
||||||
root_dir = './servers/'
|
root_dir = './servers/'
|
||||||
proxy_version = "1.21"
|
proxy_version = "1.21"
|
||||||
minecraft_version = '1.21.1'
|
minecraft_version = '1.21.4'
|
||||||
eula_agreement = 'true'
|
eula_agreement = 'true'
|
||||||
|
|
||||||
backend_names = ['alpha', 'beta']
|
backend_names = ['alpha', 'beta']
|
||||||
|
|||||||
Reference in New Issue
Block a user