From b6255e5f466d819bd238c0b5c27fbd414466de2a Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 26 Sep 2026 11:38:35 +0100 Subject: [PATCH 1/8] Build with JDK 25 in CI BentoBox 3.23 and later are compiled for Java 25 (class version 69), so JDK 21 cannot compile against them. Use JDK 25 in the build and Modrinth publish workflows so the addon can move to a current BentoBox. The bytecode target stays at Java 21. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 2 +- .github/workflows/modrinth-publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f16ddcd5..447adcc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'adopt' - java-version: '21' + java-version: '25' - name: Cache SonarCloud packages uses: actions/cache@v4 with: diff --git a/.github/workflows/modrinth-publish.yml b/.github/workflows/modrinth-publish.yml index eaca55cd..8f946303 100644 --- a/.github/workflows/modrinth-publish.yml +++ b/.github/workflows/modrinth-publish.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Java 21 uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '25' distribution: 'temurin' # 3. Cache Maven dependencies to speed up builds From 2abf785319aa00b9c1c1d773bf581d91f8e3936e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 26 Sep 2026 15:40:54 +0100 Subject: [PATCH 2/8] build: get ItemsAdder API from Maven Central ItemsAdder's old repo (maven.devs.beer) returns 522, which broke dependency resolution in CI. The API is now published to Maven Central as beer.devs:itemsadder-api, matching BentoBox. Drop the old repo. Co-Authored-By: Claude Opus 5.5 --- pom.xml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c565baf8..87b780f3 100644 --- a/pom.xml +++ b/pom.xml @@ -160,11 +160,6 @@ songoda-plugins https://repo.songoda.com/repository/minecraft-plugins/ - - - matteodev - https://maven.devs.beer/ - oraxen @@ -276,11 +271,11 @@ 1.0.0-SNAPSHOT provided - + - dev.lone - api-itemsadder - 4.0.10 + beer.devs + itemsadder-api + 4.0.17 provided From b14355f33d388f834af525793d395cc5f3924a3e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 26 Sep 2026 15:41:53 +0100 Subject: [PATCH 3/8] feat: apply BentoBox admin deaths commands to island deaths Since deaths became per-island (ff59b02), / deaths only changed BentoBox's per-world counter, which Level reads once at migration, so admins could not change an island's death handicap. Level now listens for BentoBox's PlayerDeathsChangedEvent and applies the change to every island the player is a member of in that world: - add: adds to the player's count (capped at deaths.max) - remove: takes from the player's count, then from anonymous deaths - set/reset: sets the player's count and clears anonymous deaths (migrated legacy deaths and deaths of former members) The listener is only registered if the running BentoBox has the event. Bumps the BentoBox dependency to 3.23.1-SNAPSHOT. Co-Authored-By: Claude Opus 5.5 --- pom.xml | 2 +- src/main/java/world/bentobox/level/Level.java | 8 ++ .../world/bentobox/level/LevelsManager.java | 70 ++++++++++++ .../bentobox/level/config/ConfigSettings.java | 2 + .../level/listeners/AdminDeathsListener.java | 57 ++++++++++ src/main/resources/config.yml | 2 + .../bentobox/level/LevelsManagerTest.java | 77 +++++++++++++ .../listeners/AdminDeathsListenerTest.java | 107 ++++++++++++++++++ 8 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 src/main/java/world/bentobox/level/listeners/AdminDeathsListener.java create mode 100644 src/test/java/world/bentobox/level/listeners/AdminDeathsListenerTest.java diff --git a/pom.xml b/pom.xml index c565baf8..ba97b527 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ 4.110.0 1.21.11-R0.1-SNAPSHOT - 3.15.1-SNAPSHOT + 3.23.1-SNAPSHOT 1.12.0 diff --git a/src/main/java/world/bentobox/level/Level.java b/src/main/java/world/bentobox/level/Level.java index b903185e..6c490d95 100644 --- a/src/main/java/world/bentobox/level/Level.java +++ b/src/main/java/world/bentobox/level/Level.java @@ -43,6 +43,7 @@ import world.bentobox.level.commands.IslandValueCommand; import world.bentobox.level.config.BlockConfig; import world.bentobox.level.config.ConfigSettings; +import world.bentobox.level.listeners.AdminDeathsListener; import world.bentobox.level.listeners.IslandActivitiesListeners; import world.bentobox.level.listeners.JoinLeaveListener; import world.bentobox.level.listeners.MigrationListener; @@ -154,6 +155,13 @@ private void registerAllListeners() { registerListener(new IslandActivitiesListeners(this)); registerListener(new JoinLeaveListener(this)); registerListener(new MigrationListener(this)); + // The admin deaths event only exists in newer BentoBox versions + try { + Class.forName("world.bentobox.bentobox.api.events.player.PlayerDeathsChangedEvent"); + registerListener(new AdminDeathsListener(this)); + } catch (ClassNotFoundException e) { + log("This BentoBox version does not support syncing admin deaths commands to island levels. Update BentoBox to enable it."); + } } private void registerGameModeCommands() { diff --git a/src/main/java/world/bentobox/level/LevelsManager.java b/src/main/java/world/bentobox/level/LevelsManager.java index c7521b32..f79c57e7 100644 --- a/src/main/java/world/bentobox/level/LevelsManager.java +++ b/src/main/java/world/bentobox/level/LevelsManager.java @@ -661,6 +661,76 @@ public void rollDeathsToAnonymous(@NonNull Island island, @NonNull UUID playerUU handler.saveObjectAsync(data); } + /** + * Admin set of a player's deaths on this island. The player's count becomes + * {@code deaths}, capped at the game mode's {@code deaths.max} setting. Anonymous + * deaths are cleared too: they are unattributed (migrated legacy deaths or deaths + * of former members), so an admin setting the deaths expects them to go. + * + * @param island the island + * @param playerUUID the player whose deaths are being set + * @param deaths the new death count, zero or more + */ + public void setDeaths(@NonNull Island island, @NonNull UUID playerUUID, int deaths) { + IslandLevels data = checkDeathsMigration(island); + data.setAnonymousDeaths(0); + int count = capDeaths(island, Math.max(0, deaths)); + if (count > 0) { + data.getMemberDeaths().put(playerUUID.toString(), count); + } else { + data.getMemberDeaths().remove(playerUUID.toString()); + } + handler.saveObjectAsync(data); + } + + /** + * Admin addition of deaths to a player on this island, capped at the game mode's + * {@code deaths.max} setting. + * + * @param island the island + * @param playerUUID the player + * @param amount the number of deaths to add + */ + public void addDeaths(@NonNull Island island, @NonNull UUID playerUUID, int amount) { + if (amount <= 0) { + return; + } + IslandLevels data = checkDeathsMigration(island); + int current = data.getMemberDeaths().getOrDefault(playerUUID.toString(), 0); + data.getMemberDeaths().put(playerUUID.toString(), capDeaths(island, (int) Math.min(Integer.MAX_VALUE, (long) current + amount))); + handler.saveObjectAsync(data); + } + + /** + * Admin removal of deaths from a player on this island. Deaths come off the + * player's own count first and any remainder comes off the island's anonymous + * deaths. Neither goes below zero. + * + * @param island the island + * @param playerUUID the player + * @param amount the number of deaths to remove + */ + public void removeDeaths(@NonNull Island island, @NonNull UUID playerUUID, int amount) { + if (amount <= 0) { + return; + } + IslandLevels data = checkDeathsMigration(island); + int current = data.getMemberDeaths().getOrDefault(playerUUID.toString(), 0); + int fromPlayer = Math.min(current, amount); + if (current - fromPlayer > 0) { + data.getMemberDeaths().put(playerUUID.toString(), current - fromPlayer); + } else { + data.getMemberDeaths().remove(playerUUID.toString()); + } + data.setAnonymousDeaths(Math.max(0, data.getAnonymousDeaths() - (amount - fromPlayer))); + handler.saveObjectAsync(data); + } + + private int capDeaths(Island island, int deaths) { + int max = addon.getPlugin().getIWM().getDeathsMax(island.getWorld()); + return max > 0 ? Math.min(max, deaths) : deaths; + } + /** * Get the death handicap for an island: anonymous deaths plus all current member * deaths in this island's space. diff --git a/src/main/java/world/bentobox/level/config/ConfigSettings.java b/src/main/java/world/bentobox/level/config/ConfigSettings.java index 2d7aa675..fe010022 100644 --- a/src/main/java/world/bentobox/level/config/ConfigSettings.java +++ b/src/main/java/world/bentobox/level/config/ConfigSettings.java @@ -129,6 +129,8 @@ public class ConfigSettings implements ConfigObject { @ConfigComment("and they stay with the island even if the player later leaves the team.") @ConfigComment("The per-player count is capped by the deaths max setting in the GameModeAddon's config.yml,") @ConfigComment("and deaths are only recorded if deaths counted is enabled there.") + @ConfigComment("The game mode's admin deaths commands (set/add/remove/reset) also change the island's deaths.") + @ConfigComment("Set and reset also clear deaths left by former members and deaths carried over from older versions.") @ConfigComment("Set to zero to not use this feature") @ConfigEntry(path = "deathpenalty") private int deathPenalty = 100; diff --git a/src/main/java/world/bentobox/level/listeners/AdminDeathsListener.java b/src/main/java/world/bentobox/level/listeners/AdminDeathsListener.java new file mode 100644 index 00000000..3465501c --- /dev/null +++ b/src/main/java/world/bentobox/level/listeners/AdminDeathsListener.java @@ -0,0 +1,57 @@ +package world.bentobox.level.listeners; + +import java.util.UUID; + +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import world.bentobox.bentobox.api.events.player.PlayerDeathsChangedEvent; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.level.Level; + +/** + * Applies the BentoBox admin deaths commands ({@code / deaths set|add|remove|reset}) + * to Level's per-island death counts, so admins do not need a separate Level command. + * The change is applied to every island the player is a member of in that game mode. + *

+ * Only registered when the running BentoBox has {@link PlayerDeathsChangedEvent}. + * + * @author tastybento + */ +public class AdminDeathsListener implements Listener { + + private final Level addon; + + /** + * @param addon - addon + */ + public AdminDeathsListener(Level addon) { + this.addon = addon; + } + + /** + * Apply an admin deaths change to the player's islands in that world. + * @param e event + */ + @EventHandler(priority = EventPriority.MONITOR) + public void onDeathsChanged(PlayerDeathsChangedEvent e) { + World world = e.getWorld(); + if (world == null || !addon.isRegisteredGameModeWorld(world)) { + return; + } + UUID uuid = e.getPlayerUUID(); + for (Island island : addon.getIslands().getIslands(world, uuid)) { + if (!island.getMemberSet().contains(uuid)) { + continue; + } + switch (e.getAction()) { + case SET -> addon.getManager().setDeaths(island, uuid, e.getAmount()); + case RESET -> addon.getManager().setDeaths(island, uuid, 0); + case ADD -> addon.getManager().addDeaths(island, uuid, e.getAmount()); + case REMOVE -> addon.getManager().removeDeaths(island, uuid, e.getAmount()); + } + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 57e5dd2b..a9207ce4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -80,6 +80,8 @@ levelwait: 60 # and they stay with the island even if the player later leaves the team. # The per-player count is capped by the deaths max setting in the GameModeAddon's config.yml, # and deaths are only recorded if deaths counted is enabled there. +# The game mode's admin deaths commands (set/add/remove/reset) also change the island's deaths. +# Set and reset also clear deaths left by former members and deaths carried over from older versions. # Set to zero to not use this feature deathpenalty: 100 # Deprecated - no longer used for level calculation, which now always counts all deaths diff --git a/src/test/java/world/bentobox/level/LevelsManagerTest.java b/src/test/java/world/bentobox/level/LevelsManagerTest.java index e8718e50..543a5ba7 100644 --- a/src/test/java/world/bentobox/level/LevelsManagerTest.java +++ b/src/test/java/world/bentobox/level/LevelsManagerTest.java @@ -554,4 +554,81 @@ void testGetDeathHandicapSumsAnonymousAndMembers() throws Exception { assertEquals(6, lm.getDeathHandicap(island)); } + /** + * Test method for + * {@link world.bentobox.level.LevelsManager#setDeaths(Island, UUID, int)}. + * Reproduces the Discord report: migrated deaths sit in the anonymous count and + * an admin reset must clear them. + */ + @Test + void testSetDeathsZeroClearsAnonymousAndPlayer() throws Exception { + IslandLevels data = deathData(true); + data.setAnonymousDeaths(3); + data.getMemberDeaths().put(uuid.toString(), 2); + UUID mate = UUID.randomUUID(); + data.getMemberDeaths().put(mate.toString(), 1); + + lm.setDeaths(island, uuid, 0); + + assertEquals(0L, data.getAnonymousDeaths()); + assertFalse(data.getMemberDeaths().containsKey(uuid.toString())); + // Other members keep their deaths + assertEquals(1, lm.getDeathHandicap(island)); + } + + /** + * Test method for + * {@link world.bentobox.level.LevelsManager#setDeaths(Island, UUID, int)} + */ + @Test + void testSetDeathsCapsAtDeathsMax() throws Exception { + IslandLevels data = deathData(true); + when(iwm.getDeathsMax(world)).thenReturn(10); + + lm.setDeaths(island, uuid, 5); + assertEquals(5, data.getMemberDeaths().get(uuid.toString()).intValue()); + lm.setDeaths(island, uuid, 50); + assertEquals(10, data.getMemberDeaths().get(uuid.toString()).intValue()); + } + + /** + * Test method for + * {@link world.bentobox.level.LevelsManager#addDeaths(Island, UUID, int)} + */ + @Test + void testAddDeaths() throws Exception { + IslandLevels data = deathData(true); + when(iwm.getDeathsMax(world)).thenReturn(10); + data.setAnonymousDeaths(1); + + lm.addDeaths(island, uuid, 4); + lm.addDeaths(island, uuid, 4); + assertEquals(8, data.getMemberDeaths().get(uuid.toString()).intValue()); + lm.addDeaths(island, uuid, 4); + assertEquals(10, data.getMemberDeaths().get(uuid.toString()).intValue()); + assertEquals(11, lm.getDeathHandicap(island)); + } + + /** + * Test method for + * {@link world.bentobox.level.LevelsManager#removeDeaths(Island, UUID, int)} + */ + @Test + void testRemoveDeathsSpillsIntoAnonymous() throws Exception { + IslandLevels data = deathData(true); + data.setAnonymousDeaths(3); + data.getMemberDeaths().put(uuid.toString(), 2); + + lm.removeDeaths(island, uuid, 1); + assertEquals(1, data.getMemberDeaths().get(uuid.toString()).intValue()); + assertEquals(3L, data.getAnonymousDeaths()); + + lm.removeDeaths(island, uuid, 3); + assertFalse(data.getMemberDeaths().containsKey(uuid.toString())); + assertEquals(1L, data.getAnonymousDeaths()); + + lm.removeDeaths(island, uuid, 100); + assertEquals(0, lm.getDeathHandicap(island)); + } + } diff --git a/src/test/java/world/bentobox/level/listeners/AdminDeathsListenerTest.java b/src/test/java/world/bentobox/level/listeners/AdminDeathsListenerTest.java new file mode 100644 index 00000000..e6bbe315 --- /dev/null +++ b/src/test/java/world/bentobox/level/listeners/AdminDeathsListenerTest.java @@ -0,0 +1,107 @@ +package world.bentobox.level.listeners; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.UUID; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +import com.google.common.collect.ImmutableSet; + +import world.bentobox.bentobox.api.events.player.PlayerDeathsChangedEvent; +import world.bentobox.bentobox.api.events.player.PlayerDeathsChangedEvent.Action; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.level.CommonTestSetup; +import world.bentobox.level.LevelsManager; + +/** + * Tests for {@link AdminDeathsListener} + */ +class AdminDeathsListenerTest extends CommonTestSetup { + + @Mock + private LevelsManager manager; + @Mock + private Island otherIsland; + + private AdminDeathsListener listener; + + @Override + @BeforeEach + protected void setUp() throws Exception { + super.setUp(); + when(addon.getManager()).thenReturn(manager); + when(addon.isRegisteredGameModeWorld(world)).thenReturn(true); + when(island.getMemberSet()).thenReturn(ImmutableSet.of(uuid)); + when(im.getIslands(world, uuid)).thenReturn(List.of(island)); + listener = new AdminDeathsListener(addon); + } + + @Override + @AfterEach + protected void tearDown() throws Exception { + super.tearDown(); + } + + private PlayerDeathsChangedEvent event(Action action, int amount) { + return new PlayerDeathsChangedEvent(world, uuid, action, amount, 3, 0); + } + + @Test + void testSet() { + listener.onDeathsChanged(event(Action.SET, 4)); + verify(manager).setDeaths(island, uuid, 4); + } + + @Test + void testReset() { + listener.onDeathsChanged(event(Action.RESET, 0)); + verify(manager).setDeaths(island, uuid, 0); + } + + @Test + void testAdd() { + listener.onDeathsChanged(event(Action.ADD, 2)); + verify(manager).addDeaths(island, uuid, 2); + } + + @Test + void testRemove() { + listener.onDeathsChanged(event(Action.REMOVE, 3)); + verify(manager).removeDeaths(island, uuid, 3); + } + + @Test + void testAppliesToEveryIslandPlayerIsMemberOf() { + when(otherIsland.getMemberSet()).thenReturn(ImmutableSet.of(uuid, UUID.randomUUID())); + when(im.getIslands(world, uuid)).thenReturn(List.of(island, otherIsland)); + listener.onDeathsChanged(event(Action.REMOVE, 3)); + verify(manager).removeDeaths(island, uuid, 3); + verify(manager).removeDeaths(otherIsland, uuid, 3); + } + + @Test + void testSkipsIslandsWherePlayerIsNotMember() { + // e.g. trusted/coop islands returned by the lookup + when(otherIsland.getMemberSet()).thenReturn(ImmutableSet.of(UUID.randomUUID())); + when(im.getIslands(world, uuid)).thenReturn(List.of(otherIsland)); + listener.onDeathsChanged(event(Action.RESET, 0)); + verify(manager, never()).setDeaths(any(), any(), anyInt()); + } + + @Test + void testIgnoresUnregisteredWorld() { + when(addon.isRegisteredGameModeWorld(world)).thenReturn(false); + listener.onDeathsChanged(event(Action.RESET, 0)); + verifyNoInteractions(manager); + } +} From a30db89a9f92a1e96105bd01e151b572f97be524 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 26 Sep 2026 16:47:47 +0100 Subject: [PATCH 4/8] Update pom.xml - version up --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 87b780f3..4a491c0b 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ -LOCAL - 2.29.0 + 2.30.0 BentoBoxWorld_Level bentobox-world https://sonarcloud.io From 52eba5f4d986223510f397dc40c6878a69518caa Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 30 Oct 2026 18:33:24 -0700 Subject: [PATCH 5/8] build: depend on BentoBox 3.23.3 for PlayerDeathsChangedEvent AdminDeathsListener (#461) uses PlayerDeathsChangedEvent, first released in BentoBox 3.23.3. The pom still pointed at 3.23.1-SNAPSHOT, so CI builds #763-#765 failed to compile. Raise api-version to match, since the listener cannot load on older BentoBox. Co-Authored-By: Claude Opus 5.5 --- pom.xml | 2 +- src/main/resources/addon.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 47afa544..cf526e92 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ 4.110.0 1.21.11-R0.1-SNAPSHOT - 3.23.1-SNAPSHOT + 3.23.3 1.12.0 diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index 61e4c896..d8d68239 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -2,7 +2,7 @@ name: Level main: world.bentobox.level.Level version: ${version}${build.number} icon: DIAMOND -api-version: 3.16.0 +api-version: 3.23.3 authors: tastybento From 3940ea07be44dbdef45a6fdb2af83806c8b75f3d Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 30 Oct 2026 18:34:05 -0700 Subject: [PATCH 6/8] build: compile and test against Paper 26.3 with MockBukkit v26.3 MockBukkit 4.119.0 ships a mockbukkit-v26.3 artifact, so move both the Paper API (26.3.build.231-stable) and the MockBukkit coordinate to the 26.3 line together, matching BentoBox. Co-Authored-By: Claude Opus 5.5 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index cf526e92..156e691c 100644 --- a/pom.xml +++ b/pom.xml @@ -54,9 +54,9 @@ 5.10.2 5.11.0 - 4.110.0 + 4.119.0 - 1.21.11-R0.1-SNAPSHOT + 26.3.build.231-stable 3.23.3 1.12.0 @@ -178,7 +178,7 @@ org.mockbukkit.mockbukkit - mockbukkit-v1.21 + mockbukkit-v26.3 ${mock-bukkit.version} test From a2c4574c4b55b0bfa2120e6b28a7cb734eae9272 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 30 Oct 2026 18:36:01 -0700 Subject: [PATCH 7/8] ci: list Minecraft 26.2 and 26.3 as supported game versions Co-Authored-By: Claude Opus 5.5 --- .github/workflows/modrinth-publish.yml | 2 ++ .github/workflows/publish.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/modrinth-publish.yml b/.github/workflows/modrinth-publish.yml index 8f946303..dca196f3 100644 --- a/.github/workflows/modrinth-publish.yml +++ b/.github/workflows/modrinth-publish.yml @@ -95,6 +95,8 @@ jobs: 26.1 26.1.1 26.1.2 + 26.2 + 26.3 # Path to the built JAR — Maven produces Level-{version}.jar in target/ files: target/Level-${{ github.event.release.tag_name || inputs.tag }}.jar diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 290ec3b6..f48e5036 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: hangar_slug: "Level" curseforge_id: "1514824" # Keep in sync with the game-versions list in modrinth-publish.yml - game_versions: "26.1.2,26.1.1,26.1,1.21.11,1.21.10,1.21.9,1.21.8,1.21.7,1.21.6,1.21.5" + game_versions: "26.3,26.2,26.1.2,26.1.1,26.1,1.21.11,1.21.10,1.21.9,1.21.8,1.21.7,1.21.6,1.21.5" version: ${{ inputs.version }} # empty on release events -> falls back to the release tag secrets: HANGAR_API_KEY: ${{ secrets.HANGAR_API_KEY }} From 81c1537f9681b1a363244c1f21f4b395f2761192 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 30 Oct 2026 18:42:38 -0700 Subject: [PATCH 8/8] build: restore api-version 3.16.0 Level registers AdminDeathsListener only when BentoBox has PlayerDeathsChangedEvent, so older BentoBox is still supported. Raising api-version to 3.23.3 in 52eba5f would have stopped Level loading there. Co-Authored-By: Claude Opus 5.5 --- src/main/resources/addon.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index d8d68239..61e4c896 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -2,7 +2,7 @@ name: Level main: world.bentobox.level.Level version: ${version}${build.number} icon: DIAMOND -api-version: 3.23.3 +api-version: 3.16.0 authors: tastybento