9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-25 09:39:18 +00:00

Compare commits

...

38 Commits
3.7 ... 3.7.2

Author SHA1 Message Date
William
e04c19acf5 build: general dependency bump 2024-12-07 21:28:26 +00:00
William
1820a810f4 feat: add method for getting OnlineUser in common module 2024-12-07 20:58:40 +00:00
William
cedd12a048 feat: target Minecraft 1.21.4, replacing 1.21.3 2024-12-07 20:58:38 +00:00
dependabot[bot]
7967d00208 deps: bump commons-io:commons-io from 2.17.0 to 2.18.0 (#426)
Bumps commons-io:commons-io from 2.17.0 to 2.18.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 22:01:50 +00:00
dependabot[bot]
00a68be2ad deps: bump com.zaxxer:HikariCP from 6.2.0 to 6.2.1 (#427)
Bumps [com.zaxxer:HikariCP](https://github.com/brettwooldridge/HikariCP) from 6.2.0 to 6.2.1.
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-6.2.0...HikariCP-6.2.1)

---
updated-dependencies:
- dependency-name: com.zaxxer:HikariCP
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 22:01:41 +00:00
William278
da5d991d2a build: bump to 3.7.2 2024-11-21 16:16:48 +00:00
dependabot[bot]
c2f6d240ad deps: bump com.zaxxer:HikariCP from 6.1.0 to 6.2.0 (#422)
Bumps [com.zaxxer:HikariCP](https://github.com/brettwooldridge/HikariCP) from 6.1.0 to 6.2.0.
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-6.1.0...HikariCP-6.2.0)

---
updated-dependencies:
- dependency-name: com.zaxxer:HikariCP
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 16:09:56 +00:00
dependabot[bot]
4cde24c536 deps: bump org.projectlombok:lombok from 1.18.34 to 1.18.36 (#420)
Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.34 to 1.18.36.
- [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown)
- [Commits](https://github.com/projectlombok/lombok/compare/v1.18.34...v1.18.36)

---
updated-dependencies:
- dependency-name: org.projectlombok:lombok
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 16:09:45 +00:00
dependabot[bot]
029617bc45 deps: bump com.gradleup.shadow from 8.3.4 to 8.3.5 (#423)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 8.3.4 to 8.3.5.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/8.3.4...8.3.5)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 16:09:31 +00:00
William
0627fb20e4 refactor: adjust equals impl in Identifier 2024-11-15 12:11:02 +00:00
William278
bc1f983684 build: actually checkout 1.21.1 on 1.21.1 2024-11-14 17:11:27 +00:00
William278
31eb747c55 build: fix release script 2024-11-14 17:00:17 +00:00
William278
e8facf52ce fix: correct env in release file 2024-11-14 15:42:35 +00:00
William278
5ee4bdd644 fix: fix broken sendPacket mixin on Fabric 2024-11-14 15:33:26 +00:00
William278
92c371e201 fix: disable "other" gui actions.
Fixes an issue where you could double-click stack to collect unstacked items without edit perms.

Unfortunately this breaks pick block on creative without edit permission, but this is  considered a necessary compromise.
2024-11-14 15:06:46 +00:00
William278
d27278454a feat: warn if server name matches default, close #314 2024-11-14 14:58:43 +00:00
William278
16780c149c build: bump deps 2024-11-14 14:54:50 +00:00
William278
0445ba63bc fix: use correct map render logic, close #406 2024-11-14 14:38:11 +00:00
dependabot[bot]
b6aefd6f57 ci: bump mikepenz/action-junit-report from 4 to 5 (#412)
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4 to 5.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/v4...v5)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 23:47:27 +00:00
William
f803af0225 feat: support newer Map data format, close #406 2024-11-04 21:49:24 +00:00
William
2675f4a377 fix: Paper event listener not registering events 2024-11-04 19:44:53 +00:00
William
03341c981f build: bump nbt-api to 2.14.0 2024-11-04 19:29:52 +00:00
William
38cc654167 fix: fixup some compiler warns 2024-11-01 22:44:29 +00:00
William
b347a8d060 fix: API not publishing, close #399 2024-11-01 22:32:03 +00:00
William
8733b86b45 [ci skip]: build 1.21.1 ver 2024-11-01 14:31:56 +00:00
William
eda8e72633 build: target Minecraft 1.21.3 2024-10-31 23:52:09 +00:00
William
c942a015d1 feat: start 1.21.3 2024-10-31 20:57:27 +00:00
William
c00265f1f9 fix: add getPlayerCustomDataStore impl on Fabric 2024-10-27 00:14:20 +01:00
dependabot[bot]
e303984dcf deps: bump org.jetbrains:annotations from 26.0.0 to 26.0.1 (#407)
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 26.0.0 to 26.0.1.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/26.0.0...26.0.1)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 11:40:45 +01:00
Preva1l
b449b5dee6 fix: cache save causes, fix Fabric data save on shutdown (#405)
Co-authored-by: seeruk <wright.elliot@gmail.com>
2024-10-17 16:21:42 +01:00
dependabot[bot]
48f8c0c967 deps: bump org.jetbrains:annotations from 25.0.0 to 26.0.0 (#400)
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 25.0.0 to 26.0.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/25.0.0...26.0.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-15 16:20:30 +01:00
dependabot[bot]
f88c4c3e2c deps: bump org.ajoberstar.grgit from 5.2.2 to 5.3.0 (#401)
Bumps [org.ajoberstar.grgit](https://github.com/ajoberstar/grgit) from 5.2.2 to 5.3.0.
- [Release notes](https://github.com/ajoberstar/grgit/releases)
- [Commits](https://github.com/ajoberstar/grgit/compare/5.2.2...5.3.0)

---
updated-dependencies:
- dependency-name: org.ajoberstar.grgit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-15 16:20:23 +01:00
dependabot[bot]
e6273fa9a0 deps: bump org.junit.jupiter:junit-jupiter-params from 5.11.1 to 5.11.2 (#402)
Bumps [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit5) from 5.11.1 to 5.11.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-15 16:20:09 +01:00
dependabot[bot]
1ba5585d0d deps: bump org.junit.jupiter:junit-jupiter-api from 5.11.1 to 5.11.2 (#395)
Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.11.1 to 5.11.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 12:31:29 +01:00
dependabot[bot]
73547371ae deps: bump org.junit.jupiter:junit-jupiter-engine from 5.11.1 to 5.11.2 (#394)
Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.11.1 to 5.11.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 12:31:21 +01:00
dependabot[bot]
fca6825394 deps: bump org.jetbrains:annotations from 24.1.0 to 25.0.0 (#396)
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 24.1.0 to 25.0.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/24.1.0...25.0.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 12:31:15 +01:00
dependabot[bot]
53af114f44 deps: bump com.gradleup.shadow from 8.3.2 to 8.3.3 (#397)
Bumps [com.gradleup.shadow](https://github.com/GradleUp/shadow) from 8.3.2 to 8.3.3.
- [Release notes](https://github.com/GradleUp/shadow/releases)
- [Commits](https://github.com/GradleUp/shadow/compare/8.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: com.gradleup.shadow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 12:31:07 +01:00
William
311cc85c92 docs: document incompatibility with /restart 2024-10-05 17:09:14 +01:00
42 changed files with 410 additions and 178 deletions

View File

@@ -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'

View File

@@ -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
View 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

View File

@@ -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'

View File

@@ -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

View File

@@ -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:

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -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

View File

@@ -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(

View File

@@ -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());
} }
} }

View File

@@ -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'
} }

View File

@@ -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
* *

View File

@@ -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
* *

View File

@@ -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
* *

View File

@@ -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
};
} }
} }

View File

@@ -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

View File

@@ -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>

View File

@@ -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) &ndash; Supported for up to 12-18 months * Long Term Support (LTS) &ndash; Supported for up to 12-18 months
* Non-Long Term Support (Non-LTS) &ndash; Supported for 3-6 months * Non-Long Term Support (Non-LTS) &ndash; 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 |

View File

@@ -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 &mdash; Getting an online user</summary> <summary>Code Example &mdash; Getting an online user</summary>

View File

@@ -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]]

View File

@@ -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.

View File

@@ -1,5 +1,6 @@
## Guides ## Guides
* 📚 [[Setup]] * 📚 [[Setup]]
* ⚠️ [[Compatibility]]
* 📄 [[Config File]] * 📄 [[Config File]]
* 🔗 [[Troubleshooting]] * 🔗 [[Troubleshooting]]
* ↪️ [[Data Rotation]] * ↪️ [[Data Rotation]]

View File

@@ -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")
} }

View File

@@ -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() {

View File

@@ -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);
} }
} }

View File

@@ -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> {

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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));
} }
} }

View File

@@ -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;

View File

@@ -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];

View File

@@ -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",

View File

@@ -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

Binary file not shown.

View File

@@ -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
View File

@@ -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/.

View File

@@ -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')
} }
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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']