From 270927d926e8988625ea0e9c7343e844b2040387 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 9 Aug 2026 17:46:07 -0700 Subject: [PATCH] fix: prefix the magic block flag ID so it cannot collide with AOneBlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MAGIC_BLOCK is the ID AOneBlock uses too, and BentoBox's flags manager drops the second registration of an ID without a word — so with both gamemodes installed, whichever loaded second was quietly running on the other addon's flag definition. Nothing misbehaved yet only because the two definitions are identical and neither sets a game mode on the builder; both are coincidences. This is the same bug class as the CHUNKBLOCK_* renames in 1.0.1, missed then. Renamed to CHUNKBLOCK_MAGIC_BLOCK in the flag, the field, default-island-flags and all 18 locale files, so translations follow the key. registerFlagOrWarn() now logs when the flags manager refuses a flag, for all five flags rather than just this one — the failure was invisible, which is why it went unnoticed for two releases. Addon already has a registerFlag() that returns the boolean; it just was not being checked. ChunkBlockTest asserts by reflection that every Flag field carries the prefix, so a new flag cannot reintroduce this. Fixes #24 --- .../world/bentobox/chunkblock/ChunkBlock.java | 28 +++++++++++++++---- .../chunkblock/listeners/BlockListener.java | 6 ++-- src/main/resources/config.yml | 2 +- src/main/resources/locales/cs.yml | 2 +- src/main/resources/locales/de.yml | 2 +- src/main/resources/locales/en-US.yml | 2 +- src/main/resources/locales/es.yml | 2 +- src/main/resources/locales/fr.yml | 2 +- src/main/resources/locales/hr.yml | 2 +- src/main/resources/locales/hu.yml | 2 +- src/main/resources/locales/id.yml | 2 +- src/main/resources/locales/it.yml | 2 +- src/main/resources/locales/ja.yml | 2 +- src/main/resources/locales/pl.yml | 2 +- src/main/resources/locales/pt.yml | 2 +- src/main/resources/locales/ru.yml | 2 +- src/main/resources/locales/tr.yml | 2 +- src/main/resources/locales/uk.yml | 2 +- src/main/resources/locales/vi.yml | 2 +- src/main/resources/locales/zh-CN.yml | 2 +- src/main/resources/locales/zh-TW.yml | 2 +- .../bentobox/chunkblock/ChunkBlockTest.java | 22 +++++++++++++++ .../listeners/BlockListenerTest2.java | 2 +- 23 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/main/java/world/bentobox/chunkblock/ChunkBlock.java b/src/main/java/world/bentobox/chunkblock/ChunkBlock.java index 38e3eda..8df0ff6 100644 --- a/src/main/java/world/bentobox/chunkblock/ChunkBlock.java +++ b/src/main/java/world/bentobox/chunkblock/ChunkBlock.java @@ -125,7 +125,7 @@ public class ChunkBlock extends GameModeAddon { /** * Flag to set who can break the magic block. */ - public final Flag MAGIC_BLOCK = new Flag.Builder("MAGIC_BLOCK", Material.GRASS_BLOCK) + public final Flag CHUNKBLOCK_MAGIC_BLOCK = new Flag.Builder("CHUNKBLOCK_MAGIC_BLOCK", Material.GRASS_BLOCK) .mode(Mode.BASIC) .type(Type.PROTECTION) .defaultRank(RanksManager.COOP_RANK) @@ -175,19 +175,35 @@ public void onLoad() { adminCommand = new AdminCommand(this); // Register flag with BentoBox // Register protection flag with BentoBox - getPlugin().getFlagsManager().registerFlag(this, CHUNKBLOCK_START_SAFETY); + registerFlagOrWarn(CHUNKBLOCK_START_SAFETY); // Bossbar if (getSettings().isBossBar()) { - getPlugin().getFlagsManager().registerFlag(this, this.CHUNKBLOCK_BOSSBAR); + registerFlagOrWarn(this.CHUNKBLOCK_BOSSBAR); } // Actionbar if (getSettings().isActionBar()) { - getPlugin().getFlagsManager().registerFlag(this, this.CHUNKBLOCK_ACTIONBAR); + registerFlagOrWarn(this.CHUNKBLOCK_ACTIONBAR); } // Magic Block protection - getPlugin().getFlagsManager().registerFlag(this, this.MAGIC_BLOCK); + registerFlagOrWarn(this.CHUNKBLOCK_MAGIC_BLOCK); // Who may spend level credit on chunks - getPlugin().getFlagsManager().registerFlag(this, this.CHUNKBLOCK_CLAIM_CHUNKS); + registerFlagOrWarn(this.CHUNKBLOCK_CLAIM_CHUNKS); + } + } + + /** + * Registers a flag and complains if it is refused. A flag whose ID is already taken by + * another addon is dropped silently by the flags manager, and this addon then runs + * against whichever definition won — so the only symptom would be settings that + * quietly do nothing. Every ID here is prefixed to avoid that, and this says so out + * loud if one ever collides anyway. + * + * @param flag the flag to register + */ + private void registerFlagOrWarn(Flag flag) { + if (!registerFlag(flag)) { + logError("Flag " + flag.getID() + " is already registered by another addon, so ChunkBlock's own " + + "definition was dropped. Its island settings will behave as that addon defines them."); } } diff --git a/src/main/java/world/bentobox/chunkblock/listeners/BlockListener.java b/src/main/java/world/bentobox/chunkblock/listeners/BlockListener.java index 722fdea..d9c50ae 100644 --- a/src/main/java/world/bentobox/chunkblock/listeners/BlockListener.java +++ b/src/main/java/world/bentobox/chunkblock/listeners/BlockListener.java @@ -230,7 +230,7 @@ public void onBlockFromTo(final BlockFromToEvent e) { /** * Cancels a magic-block break as early as possible when the player lacks the - * {@link ChunkBlock#MAGIC_BLOCK} permission. + * {@link ChunkBlock#CHUNKBLOCK_MAGIC_BLOCK} permission. *

* The full magic-block processing runs at {@link EventPriority#HIGHEST} so that * other protection plugins get a chance to cancel first. However, reward-granting @@ -256,7 +256,7 @@ public void onBlockBreakDeny(final BlockBreakEvent e) { // checkIsland cancels the event and sends the protection message if the player // is not allowed to break the magic block. addon.getIslands().getIslandAt(l).filter(i -> l.equals(i.getCenter())) - .ifPresent(i -> checkIsland(e, e.getPlayer(), i.getCenter(), addon.MAGIC_BLOCK)); + .ifPresent(i -> checkIsland(e, e.getPlayer(), i.getCenter(), addon.CHUNKBLOCK_MAGIC_BLOCK)); } /** @@ -394,7 +394,7 @@ private void process(@NonNull Cancellable e, @NonNull Island island, @Nullable P // player (e.g. the block is broken by a JetsMinions minion) the protection flag // check is skipped: it requires a User and would otherwise throw an NPE inside // BentoBox's FlagListener. See https://github.com/BentoBoxWorld/ChunkBlock/issues/525 - if (player != null && !checkIsland((@NonNull Event) e, player, island.getCenter(), addon.MAGIC_BLOCK)) { + if (player != null && !checkIsland((@NonNull Event) e, player, island.getCenter(), addon.CHUNKBLOCK_MAGIC_BLOCK)) { // Not allowed return; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 03577ef..5c5aec4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -425,7 +425,7 @@ world: BREAK_BLOCKS: 500 CHORUS_FRUIT: 500 CONTAINER: 500 - MAGIC_BLOCK: 200 + CHUNKBLOCK_MAGIC_BLOCK: 200 CHUNKBLOCK_CLAIM_CHUNKS: 1000 JUKEBOX: 500 POTION_THROWING: 500 diff --git a/src/main/resources/locales/cs.yml b/src/main/resources/locales/cs.yml index dbf0f44..5f61bf5 100644 --- a/src/main/resources/locales/cs.yml +++ b/src/main/resources/locales/cs.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Ochrana Kouzelného Bloku description: |- &b Hodnost, která může rozbít diff --git a/src/main/resources/locales/de.yml b/src/main/resources/locales/de.yml index 5cd4cb5..073f740 100644 --- a/src/main/resources/locales/de.yml +++ b/src/main/resources/locales/de.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Schutz des Magischen Blocks description: |- &b Rang, der den magischen diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index dfc6990..21e4da2 100755 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -5,7 +5,7 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Magic Block Protection description: |- &b Rank that can break the magic diff --git a/src/main/resources/locales/es.yml b/src/main/resources/locales/es.yml index 3558929..eda91e8 100644 --- a/src/main/resources/locales/es.yml +++ b/src/main/resources/locales/es.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Protección de Bloque Mágico description: |- &b Rango que puede romper el diff --git a/src/main/resources/locales/fr.yml b/src/main/resources/locales/fr.yml index 531f1a4..8e33ba3 100644 --- a/src/main/resources/locales/fr.yml +++ b/src/main/resources/locales/fr.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Protection du Bloc Magique description: |- &b Rang qui peut casser le bloc diff --git a/src/main/resources/locales/hr.yml b/src/main/resources/locales/hr.yml index 6cb4138..c31c5a1 100644 --- a/src/main/resources/locales/hr.yml +++ b/src/main/resources/locales/hr.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Zaštita Magičnog Bloka description: |- &b Rang koji može razbiti diff --git a/src/main/resources/locales/hu.yml b/src/main/resources/locales/hu.yml index aaba727..590c841 100644 --- a/src/main/resources/locales/hu.yml +++ b/src/main/resources/locales/hu.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Mágikus Blokk Védelem description: |- &b Rang, amely képes diff --git a/src/main/resources/locales/id.yml b/src/main/resources/locales/id.yml index dce0c28..a08e651 100644 --- a/src/main/resources/locales/id.yml +++ b/src/main/resources/locales/id.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Perlindungan Blok Ajaib description: |- &b Pangkat yang dapat diff --git a/src/main/resources/locales/it.yml b/src/main/resources/locales/it.yml index f9bcbf4..300d221 100644 --- a/src/main/resources/locales/it.yml +++ b/src/main/resources/locales/it.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Protezione Blocco Magico description: |- &b Rango che può rompere il diff --git a/src/main/resources/locales/ja.yml b/src/main/resources/locales/ja.yml index fc08cba..8239163 100644 --- a/src/main/resources/locales/ja.yml +++ b/src/main/resources/locales/ja.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: 魔法ブロック保護 description: |- &b ブロックを破壊できる場合、 diff --git a/src/main/resources/locales/pl.yml b/src/main/resources/locales/pl.yml index 24e7225..2fdb553 100644 --- a/src/main/resources/locales/pl.yml +++ b/src/main/resources/locales/pl.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Ochrona Magicznego Bloku description: |- &b Ranga, która może zniszczyć diff --git a/src/main/resources/locales/pt.yml b/src/main/resources/locales/pt.yml index ef33ccb..5e417a0 100644 --- a/src/main/resources/locales/pt.yml +++ b/src/main/resources/locales/pt.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Proteção de Bloco Mágico description: |- &b Rank que pode quebrar o diff --git a/src/main/resources/locales/ru.yml b/src/main/resources/locales/ru.yml index 1f3ece3..6b8fc56 100644 --- a/src/main/resources/locales/ru.yml +++ b/src/main/resources/locales/ru.yml @@ -5,7 +5,7 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Магический блок description: |- Предотвращает ломание diff --git a/src/main/resources/locales/tr.yml b/src/main/resources/locales/tr.yml index 351ac03..6854346 100644 --- a/src/main/resources/locales/tr.yml +++ b/src/main/resources/locales/tr.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Büyülü Blok Koruması description: |- &b Blokları kırabilirlerse diff --git a/src/main/resources/locales/uk.yml b/src/main/resources/locales/uk.yml index 76b12bb..b1af17c 100644 --- a/src/main/resources/locales/uk.yml +++ b/src/main/resources/locales/uk.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Захист Магічного Блоку description: |- &b Ранг, який може зламати diff --git a/src/main/resources/locales/vi.yml b/src/main/resources/locales/vi.yml index 53510a5..1473291 100644 --- a/src/main/resources/locales/vi.yml +++ b/src/main/resources/locales/vi.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: Bảo Vệ Khối Ma Thuật description: |- &b Xếp hạng có thể phá diff --git a/src/main/resources/locales/zh-CN.yml b/src/main/resources/locales/zh-CN.yml index dc17eb0..934a27a 100644 --- a/src/main/resources/locales/zh-CN.yml +++ b/src/main/resources/locales/zh-CN.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: 魔法方块保护 description: |- &b 如果玩家可以破坏方块, diff --git a/src/main/resources/locales/zh-TW.yml b/src/main/resources/locales/zh-TW.yml index b3dd13f..48dd328 100644 --- a/src/main/resources/locales/zh-TW.yml +++ b/src/main/resources/locales/zh-TW.yml @@ -1,6 +1,6 @@ protection: flags: - MAGIC_BLOCK: + CHUNKBLOCK_MAGIC_BLOCK: name: 魔法方塊保護 description: |- &b 如果玩家可以破壞方塊, diff --git a/src/test/java/world/bentobox/chunkblock/ChunkBlockTest.java b/src/test/java/world/bentobox/chunkblock/ChunkBlockTest.java index 8c6d1e5..73c8bf4 100644 --- a/src/test/java/world/bentobox/chunkblock/ChunkBlockTest.java +++ b/src/test/java/world/bentobox/chunkblock/ChunkBlockTest.java @@ -15,6 +15,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -38,6 +39,7 @@ import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon.State; import world.bentobox.bentobox.api.addons.AddonDescription; +import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.DatabaseSetup; @@ -209,6 +211,26 @@ void testOnLoad() { } + /** + * Every flag ID must be prefixed. AOneBlock, which this addon was forked from, declares + * flags of its own, and BentoBox's flags manager silently drops the second registration + * of an ID — so an unprefixed ID means that whichever gamemode loads second quietly runs + * on the other one's definition. See issue #24. + */ + @Test + void testEveryFlagIdIsPrefixed() throws IllegalAccessException { + int checked = 0; + for (Field field : ChunkBlock.class.getDeclaredFields()) { + if (Flag.class.isAssignableFrom(field.getType())) { + String id = ((Flag) field.get(addon)).getID(); + assertTrue(id.startsWith("CHUNKBLOCK_"), + "Flag " + id + " needs a CHUNKBLOCK_ prefix or it collides with another addon"); + checked++; + } + } + assertTrue(checked > 0, "no flags found to check — has the field type changed?"); + } + /** * Test method for {@link world.bentobox.chunkblock.ChunkBlock#onReload()}. */ diff --git a/src/test/java/world/bentobox/chunkblock/listeners/BlockListenerTest2.java b/src/test/java/world/bentobox/chunkblock/listeners/BlockListenerTest2.java index b59c377..541a569 100644 --- a/src/test/java/world/bentobox/chunkblock/listeners/BlockListenerTest2.java +++ b/src/test/java/world/bentobox/chunkblock/listeners/BlockListenerTest2.java @@ -1079,7 +1079,7 @@ void testOnBlockBreakDenyRegisteredAtLowestPriority() throws NoSuchMethodExcepti /** * Test method for * {@link world.bentobox.chunkblock.listeners.BlockListener#onBlockBreakDeny(BlockBreakEvent)} - * When the player lacks the MAGIC_BLOCK permission the break is cancelled at this + * When the player lacks the CHUNKBLOCK_MAGIC_BLOCK permission the break is cancelled at this * early stage (via checkIsland), so later reward plugins are skipped. Regression * test for https://github.com/BentoBoxWorld/ChunkBlock/issues/534 */