9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-26 01:59:20 +00:00

Compare commits

...

17 Commits
3.8.4 ... 3.8.5

Author SHA1 Message Date
William278
2ada0497ec docs: update compatibility 2025-06-25 18:55:44 +01:00
William278
e9f2856040 feat: add support for Minecraft 1.21.6 2025-06-23 00:15:11 +01:00
William278
6050c584c0 refactor(paper): improve handling of locked maps in item frames 2025-06-22 14:23:52 +01:00
William278
7ebf91bfae refactor(paper): further refactors to locked maps 2025-06-22 00:24:36 +01:00
William278
2d7799628a refactor(paper): avoid use of default maven central URL 2025-06-21 15:32:02 +01:00
William278
1627de732b refactor: enable check-in petitions by default 2025-06-21 15:09:17 +01:00
William278
fea882c642 fix(paper): locked maps losing data on restart, close #498 2025-06-21 15:08:16 +01:00
dependabot[bot]
8b749357f7 build(deps): bump urllib3 from 2.2.2 to 2.5.0 in /test (#528)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.2 to 2.5.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.2.2...2.5.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.5.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-19 23:34:42 +01:00
dependabot[bot]
e4ff7e6d6c deps: bump org.ajoberstar.grgit from 5.3.0 to 5.3.2 (#526)
Bumps [org.ajoberstar.grgit](https://github.com/ajoberstar/grgit) from 5.3.0 to 5.3.2.
- [Release notes](https://github.com/ajoberstar/grgit/releases)
- [Commits](https://github.com/ajoberstar/grgit/compare/5.3.0...5.3.2)

---
updated-dependencies:
- dependency-name: org.ajoberstar.grgit
  dependency-version: 5.3.2
  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>
2025-06-19 23:34:33 +01:00
William278
396630821f fix: return false if user is checked out if CIPs are off 2025-06-18 22:19:54 +01:00
William278
70f65d126b build: bump adventure platform to 6.4.0 2025-06-15 16:28:00 +01:00
dependabot[bot]
e8925a0d79 build(deps): bump requests from 2.32.0 to 2.32.4 in /test (#523)
Bumps [requests](https://github.com/psf/requests) from 2.32.0 to 2.32.4.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.0...v2.32.4)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.32.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-14 13:28:07 +01:00
dependabot[bot]
2a3cf9be7d deps: bump org.junit:junit-bom from 5.12.2 to 5.13.1 (#519)
Bumps [org.junit:junit-bom](https://github.com/junit-team/junit5) from 5.12.2 to 5.13.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.2...r5.13.1)

---
updated-dependencies:
- dependency-name: org.junit:junit-bom
  dependency-version: 5.13.1
  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>
2025-06-14 13:27:59 +01:00
dependabot[bot]
971d3f5167 deps: bump net.kyori:adventure-api from 4.20.0 to 4.21.0 (#520)
Bumps [net.kyori:adventure-api](https://github.com/KyoriPowered/adventure) from 4.20.0 to 4.21.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.20.0...v4.21.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-api
  dependency-version: 4.21.0
  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>
2025-06-14 13:27:51 +01:00
dependabot[bot]
99da65a4d8 deps: bump org.snakeyaml:snakeyaml-engine from 2.7 to 2.9 (#522)
Bumps [org.snakeyaml:snakeyaml-engine](https://bitbucket.org/snakeyaml/snakeyaml-engine) from 2.7 to 2.9.
- [Commits](https://bitbucket.org/snakeyaml/snakeyaml-engine/branches/compare/snakeyaml-engine-2.9..snakeyaml-engine-2.7)

---
updated-dependencies:
- dependency-name: org.snakeyaml:snakeyaml-engine
  dependency-version: '2.9'
  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>
2025-06-14 13:27:39 +01:00
William278
25744b4ef7 Merge remote-tracking branch 'origin/master' 2025-06-13 19:25:31 +01:00
William278
8f2d1c7298 refactor: place checkin petitions behind experimental setting 2025-06-13 17:51:09 +01:00
24 changed files with 193 additions and 111 deletions

View File

@@ -55,15 +55,19 @@ jobs:
paper-1.21.1
paper-1.21.4
paper-1.21.5
paper-1.21.6
fabric-1.20.1
fabric-1.21.1
fabric-1.21.4
fabric-1.21.5
fabric-1.21.6
distro-groups: |
paper
paper
paper
paper
paper
fabric
fabric
fabric
fabric
@@ -73,16 +77,20 @@ jobs:
Paper 1.21.1
Paper 1.21.4
Paper 1.21.5
Paper 1.21.6
Fabric 1.20.1
Fabric 1.21.1
Fabric 1.21.4
Fabric 1.21.5
Fabric 1.21.6
files: |
target/HuskSync-Bukkit-${{ env.version_name }}+mc.1.20.1.jar
target/HuskSync-Bukkit-${{ env.version_name }}+mc.1.21.1.jar
target/HuskSync-Bukkit-${{ env.version_name }}+mc.1.21.4.jar
target/HuskSync-Bukkit-${{ env.version_name }}+mc.1.21.5.jar
target/HuskSync-Bukkit-${{ env.version_name }}+mc.1.21.6.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.20.1.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.1.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.4.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.5.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.5.jar
target/HuskSync-Fabric-${{ env.version_name }}+mc.1.21.6.jar

View File

@@ -44,15 +44,19 @@ jobs:
paper-1.21.1
paper-1.21.4
paper-1.21.5
paper-1.21.6
fabric-1.20.1
fabric-1.21.1
fabric-1.21.4
fabric-1.21.5
fabric-1.21.6
distro-groups: |
paper
paper
paper
paper
paper
fabric
fabric
fabric
fabric
@@ -62,16 +66,20 @@ jobs:
Paper 1.21.1
Paper 1.21.4
Paper 1.21.5
Paper 1.21.6
Fabric 1.20.1
Fabric 1.21.1
Fabric 1.21.4
Fabric 1.21.5
Fabric 1.21.6
files: |
target/HuskSync-Bukkit-${{ github.event.release.tag_name }}+mc.1.20.1.jar
target/HuskSync-Bukkit-${{ github.event.release.tag_name }}+mc.1.21.1.jar
target/HuskSync-Bukkit-${{ github.event.release.tag_name }}+mc.1.21.4.jar
target/HuskSync-Bukkit-${{ github.event.release.tag_name }}+mc.1.21.5.jar
target/HuskSync-Bukkit-${{ github.event.release.tag_name }}+mc.1.21.6.jar
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.20.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.4.jar
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.5.jar
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.5.jar
target/HuskSync-Fabric-${{ github.event.release.tag_name }}+mc.1.21.6.jar

View File

@@ -48,7 +48,8 @@ HuskSync supports the following [compatible versions](https://william278.net/doc
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Status |
|:---------------:|:---------------:|:------------:|:--------------|:------------------------------|
| 1.21.5 | _latest_ | 21 | Paper | ✅ **Active Release** |
| 1.21.6 | _latest_ | 21 | Paper | ✅ **Active Release** |
| 1.21.5 | _latest_ | 21 | Paper | ✅ **January 2026** (Non-LTS) |
| 1.21.4 | _latest_ | 21 | Paper, Fabric | ✅ **November 2025** (Non-LTS) |
| 1.21.3 | 3.7.1 | 21 | Paper, Fabric | 🗃️ Archived (December 2024) |
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **November 2025** (LTS) |

View File

@@ -5,7 +5,7 @@ plugins {
id 'org.cadixdev.licenser' version '0.6.1' apply false
id 'dev.architectury.loom' version '1.9-SNAPSHOT' apply false
id 'gg.essential.multi-version.root' apply false
id 'org.ajoberstar.grgit' version '5.3.0'
id 'org.ajoberstar.grgit' version '5.3.2'
id 'maven-publish'
id 'java'
}
@@ -89,7 +89,7 @@ allprojects {
}
dependencies {
testImplementation(platform("org.junit:junit-bom:5.12.2"))
testImplementation(platform("org.junit:junit-bom:5.13.1"))
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testCompileOnly 'org.jetbrains:annotations:26.0.2'

View File

@@ -0,0 +1,3 @@
minecraft_version_numeric=12106
minecraft_api_version=1.21
paper_api_version=1.21.6-R0.1-SNAPSHOT

View File

@@ -8,9 +8,9 @@ plugins {
dependencies {
implementation project(path: ':common')
implementation 'net.william278.uniform:uniform-bukkit:1.3.4'
implementation 'net.william278.uniform:uniform-paper:1.3.4'
implementation 'net.william278.toilet:toilet-bukkit:1.0.13'
implementation 'net.william278.uniform:uniform-bukkit:1.3.5'
implementation 'net.william278.uniform:uniform-paper:1.3.5'
implementation 'net.william278.toilet:toilet-bukkit:1.0.14'
implementation 'net.william278:mpdbdataconverter:1.0.1'
implementation 'net.william278:hsldataconverter:1.0'
implementation 'net.william278:mapdataapi:2.0'

View File

@@ -354,9 +354,11 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
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;
case "1.21.2" -> DataFixerUtil.VERSION1_21_2;
case "1.21.3" -> DataFixerUtil.VERSION1_21_3;
case "1.21.4" -> DataFixerUtil.VERSION1_21_4;
case "1.21.5" -> DataFixerUtil.VERSION1_21_5;
case "1.21.6" -> 4435;
default -> DataFixerUtil.getCurrentVersion();
};
}

View File

@@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@NoArgsConstructor
@SuppressWarnings("UnstableApiUsage")
@@ -46,13 +47,20 @@ public class PaperHuskSyncLoader implements PluginLoader {
resolveLibraries(classpathBuilder).stream()
.map(DefaultArtifact::new)
.forEach(artifact -> resolver.addDependency(new Dependency(artifact, null)));
resolver.addRepository(new RemoteRepository.Builder(
"maven", "default", "https://repo.maven.apache.org/maven2/"
).build());
resolver.addRepository(new RemoteRepository.Builder("maven", "default", getMavenUrl()).build());
classpathBuilder.addLibrary(resolver);
}
@NotNull
private static String getMavenUrl() {
return Stream.of(
System.getenv("PAPER_DEFAULT_CENTRAL_REPOSITORY"),
System.getProperty("org.bukkit.plugin.java.LibraryLoader.centralURL"),
"https://maven-central.storage-download.googleapis.com/maven2"
).filter(Objects::nonNull).findFirst().orElseThrow(IllegalStateException::new);
}
@NotNull
private static List<String> resolveLibraries(@NotNull PluginClasspathBuilder classpathBuilder) {
try (InputStream input = getLibraryListFile()) {

View File

@@ -135,7 +135,7 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven
@EventHandler(ignoreCancelled = true)
public void onMapInitialize(@NotNull MapInitializeEvent event) {
if (plugin.getSettings().getSynchronization().isPersistLockedMaps() && event.getMap().isLocked()) {
getPlugin().runAsync(() -> ((BukkitHuskSync) plugin).renderPersistedMap(event.getMap()));
getPlugin().runAsync(() -> ((BukkitHuskSync) plugin).renderInitializingLockedMap(event.getMap()));
}
}

View File

@@ -254,111 +254,139 @@ public interface BukkitMapHandler {
if (!nbt.hasTag(MAP_DATA_KEY)) {
return;
}
final ReadableNBT mapData = nbt.getCompound(MAP_DATA_KEY);
if (mapData == null) {
return;
}
// Determine map ID
final String originServerName = mapData.getString(MAP_ORIGIN_KEY);
final String currentServerName = getPlugin().getServerName();
final int originalMapId = mapData.getInteger(MAP_ID_KEY);
int newId = currentServerName.equals(originServerName)
? originalMapId : getBoundMapId(originServerName, originalMapId, currentServerName);
// Server the map was originally created on, and the current server. If they match, isOrigin is true.
final String originServer = mapData.getString(MAP_ORIGIN_KEY);
final String currentServer = getPlugin().getServerName();
final boolean isOrigin = currentServer.equals(originServer);
// Determine the map's ID on its origin server, and the new ID it should be bound to here.
// Then, update the map item / data accordingly (re-rendering and caching the map if needed)
final int originalId = mapData.getInteger(MAP_ID_KEY);
int newId = isOrigin ? originalId : getBoundMapId(originServer, originalId, currentServer);
if (newId != -1) {
final MapView view = Bukkit.getMap(newId);
if (view != null) {
meta.setMapView(view);
meta.setMapId(newId);
map.setItemMeta(meta);
getPlugin().debug(String.format("Map ID set to #%s", newId));
return;
}
getPlugin().debug(String.format("Map ID #%s not saved on this server, creating...", newId));
handleBoundMap(meta, nbt, originServer, originalId, newId, isOrigin);
} else {
handleUnboundMap(meta, nbt, originServer, originalId, currentServer);
}
// Read the pixel data from the ItemStack and generate a map view otherwise
getPlugin().debug("Deserializing map data from NBT and generating view...");
@Nullable Map.Entry<MapData, Boolean> readMapData = readMapData(originServerName, originalMapId);
if (readMapData == null && nbt.hasTag(MAP_LEGACY_PIXEL_DATA_KEY)) {
readMapData = readLegacyMapItemData(nbt);
}
// If map data was found, add a renderer to the MapView
if (readMapData == null) {
getPlugin().debug("Read pixel data was not found in database, skipping...");
return;
}
final MapData canvasData = Objects.requireNonNull(readMapData, "Pixel data null!").getKey();
final MapView view = generateRenderedMap(canvasData);
meta.setMapView(view);
map.setItemMeta(meta);
// Bind in the database & Redis
final int id = view.getId();
getRedisManager().bindMapIds(originServerName, originalMapId, currentServerName, id);
getPlugin().getDatabase().setMapBinding(originServerName, originalMapId, currentServerName, id);
meta.setMapId(id);
getPlugin().debug(String.format("Bound map to view (#%s) on server %s", id, currentServerName));
});
return map;
}
default void renderPersistedMap(@NotNull MapView view) {
if (getMapView(view.getId()).isPresent()) {
private void handleBoundMap(@NotNull MapMeta meta, @NotNull ReadableItemNBT nbt, @NotNull String originServer,
int originalId, int newId, boolean isOrigin) {
MapView view = Bukkit.getMap(newId);
if (isOrigin && view != null) {
meta.setMapView(view);
getPlugin().debug("Map ID set to original ID #%s".formatted(newId));
return;
}
// Read map data, or
@Nullable Map.Entry<MapData, Boolean> data = readMapData(getPlugin().getServerName(), view.getId());
Optional<MapView> optionalView = getMapView(newId);
if (optionalView.isPresent()) {
meta.setMapView(optionalView.get());
getPlugin().debug("Map ID set to #%s".formatted(newId));
return;
}
getPlugin().debug("Deserializing map data from NBT and generating view...");
Map.Entry<MapData, Boolean> mapData = readMapData(originServer, originalId);
if (mapData == null && nbt.hasTag(MAP_LEGACY_PIXEL_DATA_KEY)) {
mapData = readLegacyMapItemData(nbt);
}
if (mapData == null) {
getPlugin().debug("Read pixel data was not found in database, skipping...");
return;
}
MapView newView = view != null ? view : Bukkit.createMap(getDefaultMapWorld());
generateRenderedMap(Objects.requireNonNull(mapData).getKey(), newView);
meta.setMapView(newView);
}
private void handleUnboundMap(@NotNull MapMeta meta, @NotNull ReadableItemNBT nbt, @NotNull String originServer,
int originalId, @NotNull String currentServer) {
getPlugin().debug("Deserializing map data from NBT and generating view...");
Map.Entry<MapData, Boolean> mapData = readMapData(originServer, originalId);
if (mapData == null && nbt.hasTag(MAP_LEGACY_PIXEL_DATA_KEY)) {
mapData = readLegacyMapItemData(nbt);
}
if (mapData == null) {
getPlugin().debug("Read pixel data was not found in database, skipping...");
return;
}
final MapView view = generateRenderedMap(Objects.requireNonNull(mapData, "Pixel data null!").getKey());
meta.setMapView(view);
final int id = view.getId();
getRedisManager().bindMapIds(originServer, originalId, currentServer, id);
getPlugin().getDatabase().setMapBinding(originServer, originalId, currentServer, id);
getPlugin().debug("Bound map to view (#%s) on server %s".formatted(id, currentServer));
}
// Render a persisted locked map that is initializing (i.e. in an item frame)
default void renderInitializingLockedMap(@NotNull MapView view) {
if (view.isVirtual()) {
return;
}
final Optional<MapView> optionalView = getMapView(view.getId());
if (optionalView.isPresent()) {
view.getRenderers().clear();
view.getRenderers().addAll(optionalView.get().getRenderers());
view.setLocked(true);
view.setScale(MapView.Scale.NORMAL);
view.setTrackingPosition(false);
view.setUnlimitedTracking(false);
return;
}
Map.Entry<MapData, Boolean> data = readMapData(getPlugin().getServerName(), view.getId());
if (data == null) {
data = readLegacyMapFileData(view.getId());
}
// Don't render maps with no data
if (data == null) {
final World world = view.getWorld() == null ? getDefaultMapWorld() : view.getWorld();
World world = view.getWorld() == null ? getDefaultMapWorld() : view.getWorld();
getPlugin().debug("Not rendering map: no data in DB for world %s, map #%s."
.formatted(world.getName(), view.getId()));
return;
}
// Don't render persisted maps on this server
if (data.getValue()) {
return;
}
final MapData canvasData = data.getKey();
// Create a new map view renderer with the map data color at each pixel
// use view.removeRenderer() to remove all this maps renderers
view.getRenderers().forEach(view::removeRenderer);
view.addRenderer(new PersistentMapRenderer(canvasData));
view.setLocked(true);
view.setScale(MapView.Scale.NORMAL);
view.setTrackingPosition(false);
view.setUnlimitedTracking(false);
// Set the view to the map
setMapView(view);
renderMapView(view, data.getKey());
}
// Sets the renderer of a map, and returns the generated MapView
@NotNull
private MapView generateRenderedMap(@NotNull MapData canvasData) {
final MapView view = Bukkit.createMap(getDefaultMapWorld());
view.getRenderers().clear();
return generateRenderedMap(canvasData, Bukkit.createMap(getDefaultMapWorld()));
}
// Create a new map view renderer with the map data color at each pixel
@NotNull
private MapView generateRenderedMap(@NotNull MapData canvasData, @NotNull MapView view) {
renderMapView(view, canvasData);
return view;
}
private void renderMapView(@NotNull MapView view, @NotNull MapData canvasData) {
view.getRenderers().clear();
view.addRenderer(new PersistentMapRenderer(canvasData));
view.setLocked(true);
view.setScale(MapView.Scale.NORMAL);
view.setTrackingPosition(false);
view.setUnlimitedTracking(false);
// Set the view to the map and return it
setMapView(view);
return view;
}
@NotNull

View File

@@ -17,15 +17,15 @@ dependencies {
exclude module: 'slf4j-api'
}
compileOnlyApi 'net.william278.toilet:toilet-common:1.0.13'
compileOnlyApi 'net.william278.toilet:toilet-common:1.0.14'
compileOnly 'net.william278.uniform:uniform-common:1.3.4'
compileOnly 'net.william278.uniform:uniform-common:1.3.5'
compileOnly 'com.mojang:brigadier:1.1.8'
compileOnly 'org.projectlombok:lombok:1.18.38'
compileOnly 'org.jetbrains:annotations:26.0.2'
compileOnly 'net.kyori:adventure-api:4.20.0'
compileOnly 'net.kyori:adventure-api:4.23.0'
compileOnly 'net.kyori:adventure-platform-api:4.4.0'
compileOnly "net.kyori:adventure-text-serializer-plain:4.21.0"
compileOnly "net.kyori:adventure-text-serializer-plain:4.23.0"
compileOnly 'com.google.guava:guava:33.4.8-jre'
compileOnly 'com.github.plan-player-analytics:Plan:5.6.2965'
compileOnly "redis.clients:jedis:$jedis_version"

View File

@@ -150,7 +150,7 @@ public class Settings {
}
}
// 𝓡𝓮𝓭𝓲𝓼 settings
// Redis settings
@Comment("Redis settings")
private RedisSettings redis = new RedisSettings();
@@ -326,6 +326,9 @@ public class Settings {
@Getter(AccessLevel.NONE)
private Map<String, String> eventPriorities = EventListener.ListenerType.getDefaults();
@Comment("Enable check-in petitions for data syncing (don't change this unless you know what you're doing)")
private boolean checkinPetitions = true;
public boolean doAutoPin(@NotNull DataSnapshot.SaveCause cause) {
return autoPinnedSaveCauses.contains(cause.name());
}

View File

@@ -190,7 +190,8 @@ public class RedisManager extends JedisPubSub {
).dispatch(plugin, RedisMessage.Type.RETURN_USER_DATA)
);
case CHECK_IN_PETITION -> {
if (!redisMessage.isTargetServer(plugin)) {
if (!redisMessage.isTargetServer(plugin)
|| !plugin.getSettings().getSynchronization().isCheckinPetitions()) {
return;
}
final String payload = new String(redisMessage.getPayload(), StandardCharsets.UTF_8);

View File

@@ -54,7 +54,9 @@ public class LockstepDataSyncer extends DataSyncer {
// If they are checked out, ask the server to check them back in and return false
final Optional<String> server = getRedis().getUserCheckedOut(user);
if (server.isPresent() && !server.get().equals(plugin.getServerName())) {
getRedis().petitionServerCheckin(server.get(), user);
if (plugin.getSettings().getSynchronization().isCheckinPetitions()) {
getRedis().petitionServerCheckin(server.get(), user);
}
return false;
}

View File

@@ -2,7 +2,8 @@ HuskSync supports the following versions of Minecraft. Since v3.7, you must down
| Minecraft | Latest HuskSync | Java Version | Platforms | Support Status |
|:---------------:|:---------------:|:------------:|:--------------|:------------------------------|
| 1.21.5 | _latest_ | 21 | Paper | ✅ **Active Release** |
| 1.21.6 | _latest_ | 21 | Paper | ✅ **Active Release** |
| 1.21.5 | _latest_ | 21 | Paper | ✅ **January 2026** (Non-LTS) |
| 1.21.4 | _latest_ | 21 | Paper, Fabric | ✅ **November 2025** (Non-LTS) |
| 1.21.3 | 3.7.1 | 21 | Paper, Fabric | 🗃️ Archived (December 2024) |
| 1.21.1 | _latest_ | 21 | Paper, Fabric | ✅ **November 2025** (LTS) |

View File

@@ -3,5 +3,5 @@ essential.defaults.loom.mappings=net.fabricmc:yarn:1.21.5+build.1:v2
fabric_loader_version=0.16.14
fabric_api_version=0.122.0+1.21.5
fabric_permissions_api_version=0.3.3
fabric_adventure_platform_version=6.4.0-SNAPSHOT
fabric_adventure_platform_version=6.4.0
fabric_sgui_version=1.9.0+1.21.5

View File

@@ -0,0 +1,7 @@
essential.defaults.loom.mappings=net.fabricmc:yarn:1.21.6+build.1:v2
fabric_loader_version=0.16.14
fabric_api_version=0.127.1+1.21.6
fabric_permissions_api_version=0.4.0
fabric_adventure_platform_version=6.5.0-SNAPSHOT
fabric_sgui_version=1.10.0+1.21.6

View File

@@ -14,13 +14,13 @@ dependencies {
modImplementation include("net.kyori:adventure-platform-fabric:${fabric_adventure_platform_version}")
modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}")
modImplementation include("eu.pb4:sgui:${fabric_sgui_version}")
modImplementation include("net.william278.uniform:uniform-fabric:1.3.4+${project.name}")
modImplementation include("net.william278.toilet:toilet-fabric:1.0.13+${project.name}")
modImplementation include("net.william278.uniform:uniform-fabric:1.3.5+${project.name}")
modImplementation include("net.william278.toilet:toilet-fabric:1.0.14+${project.name}")
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
// Manually include config deps due to the way including api deps works
implementation include("de.exlll:configlib-core:4.6.1")
implementation include("org.snakeyaml:snakeyaml-engine:2.7")
implementation include("org.snakeyaml:snakeyaml-engine:2.9")
implementation include('org.apache.commons:commons-pool2:2.12.1')
// Include driver deps due to no runtime dep loading support

View File

@@ -1 +1 @@
1.21.5
1.21.6

View File

@@ -3,13 +3,15 @@ plugins {
}
preprocess {
def fabric12106 = createNode("1.21.6", 12106, "yarn")
def fabric12105 = createNode("1.21.5", 12105, "yarn")
def fabric12104 = createNode("1.21.4", 12104, "yarn")
def fabric12101 = createNode("1.21.1", 12101, "yarn")
def fabric12001 = createNode("1.20.1", 12001, "yarn")
strictExtraMappings.set(true)
fabric12104.link(fabric12105, null)
fabric12101.link(fabric12105, null)
fabric12001.link(fabric12105, null)
fabric12105.link(fabric12106, null)
fabric12104.link(fabric12106, null)
fabric12101.link(fabric12106, null)
fabric12001.link(fabric12106, null)
}

View File

@@ -99,8 +99,9 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
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 static final int VERSION1_21_4 = 4189;
private static final int VERSION1_21_5 = 4323;
private static final int VERSION1_21_6 = 4435;
private final HashMap<Identifier, Serializer<? extends Data>> serializers = Maps.newHashMap();
private final Map<UUID, Map<Identifier, Data>> playerCustomDataStore = Maps.newConcurrentMap();
@@ -387,10 +388,13 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
case "1.21.2", "1.21.3" -> VERSION1_21_3;
case "1.21.4" -> VERSION1_21_4;
case "1.21.5" -> VERSION1_21_5;
//#if MC==12105
case "1.21.6" -> VERSION1_21_6;
//#if MC==12106
default -> VERSION1_21_6;
//#elseif MC==12105
//$$ default -> VERSION1_21_5;
//#elseif MC==12104
default -> VERSION1_21_4;
//$$ default -> VERSION1_21_4;
//#elseif MC==12101
//$$ default -> VERSION1_21_1;
//#elseif MC==12001

View File

@@ -272,12 +272,14 @@ public abstract class FabricSerializer {
}
@Nullable
private NbtCompound encodeNbt(@NotNull ItemStack item, @NotNull DynamicRegistryManager registryManager) {
private NbtCompound encodeNbt(@NotNull ItemStack item, @NotNull DynamicRegistryManager reg) {
try {
//#if MC>=12104
return (NbtCompound) item.toNbt(registryManager);
//#if MC>=12106
return (NbtCompound) ItemStack.CODEC.encodeStart(reg.getOps(NbtOps.INSTANCE), item).getOrThrow();
//#elseif MC>=12104
//$$ return (NbtCompound) item.toNbt(reg);
//#elseif MC==12101
//$$ return (NbtCompound) item.encode(registryManager);
//$$ return (NbtCompound) item.encode(reg);
//#elseif MC==12001
//$$ final NbtCompound compound = new NbtCompound();
//$$ item.writeNbt(compound);
@@ -289,14 +291,16 @@ public abstract class FabricSerializer {
}
@NotNull
private ItemStack decodeNbt(@NotNull NbtElement item, @NotNull DynamicRegistryManager registryManager) {
//#if MC==12001
private ItemStack decodeNbt(@NotNull NbtElement item, @NotNull DynamicRegistryManager reg) {
//#if MC>=12106
final @Nullable ItemStack stack = ItemStack.CODEC.decode(reg.getOps(NbtOps.INSTANCE), item).getOrThrow().getFirst();
//#elseif MC>12001
//$$ final @Nullable ItemStack stack = ItemStack.fromNbt(reg, item).orElse(null);
//#elseif MC==12001
//$$ final @Nullable ItemStack stack = ItemStack.fromNbt((NbtCompound) item);
//#else
final @Nullable ItemStack stack = ItemStack.fromNbt(registryManager, item).orElse(null);
//#endif
if (stack == null) {
throw new IllegalStateException("Failed to decode item NBT (got null 'fromNbt'): (%s)".formatted(item));
throw new IllegalStateException("Failed to decode item NBT (decode got null): (%s)".formatted(item));
}
return stack;
}

View File

@@ -4,7 +4,7 @@ org.gradle.daemon=true
javaVersion=21
# Plugin metadata
plugin_version=3.8.4
plugin_version=3.8.5
plugin_archive=husksync
plugin_description=A modern, cross-server player data synchronization system

View File

@@ -2,6 +2,6 @@ certifi==2024.7.4
charset-normalizer==3.2.0
colorama==0.4.6
idna==3.7
requests==2.32.0
requests==2.32.4
tqdm==4.66.3
urllib3==2.2.2
urllib3==2.5.0