diff --git a/src/main/java/world/bentobox/aoneblock/AOneBlock.java b/src/main/java/world/bentobox/aoneblock/AOneBlock.java index 601038a..ea187e4 100644 --- a/src/main/java/world/bentobox/aoneblock/AOneBlock.java +++ b/src/main/java/world/bentobox/aoneblock/AOneBlock.java @@ -199,9 +199,9 @@ public void onEnable() { registerListener(new BlockProtect(this)); registerListener(new JoinLeaveListener(this)); registerListener(new InfoListener(this)); - if (getSettings().isBossBar() && getSettings().isActionBar()) { - registerListener(bossBar); - } + // Note: bossBar is registered as a listener by the FlagsManager when the + // ONEBLOCK_BOSSBAR or ONEBLOCK_ACTIONBAR flag is registered in onLoad, so it + // must not be registered here too or events would be handled twice // Register placeholders phManager = new AOneBlockPlaceholders(this, getPlugin().getPlaceholdersManager()); diff --git a/src/main/java/world/bentobox/aoneblock/listeners/BossBarListener.java b/src/main/java/world/bentobox/aoneblock/listeners/BossBarListener.java index 966d8d8..ece5aa2 100644 --- a/src/main/java/world/bentobox/aoneblock/listeners/BossBarListener.java +++ b/src/main/java/world/bentobox/aoneblock/listeners/BossBarListener.java @@ -91,6 +91,11 @@ public static Component bukkitToAdventure(String legacyString) { } private void tryToShowActionBar(UUID uuid, Island island) { + // The listener is registered whenever either the boss bar or action bar flag is + // registered, so the global setting must be checked here as well as the flag + if (!addon.getSettings().isActionBar()) { + return; + } User user = User.getInstance(uuid); Player player = Bukkit.getPlayer(uuid); @@ -125,6 +130,11 @@ private void tryToShowActionBar(UUID uuid, Island island) { * @param island island they are on */ private void tryToShowBossBar(UUID uuid, Island island) { + // The listener is registered whenever either the boss bar or action bar flag is + // registered, so the global setting must be checked here as well as the flag + if (!addon.getSettings().isBossBar()) { + return; + } User user = User.getInstance(uuid); // Only show if enabled for island diff --git a/src/test/java/world/bentobox/aoneblock/listeners/BossBarListenerTest.java b/src/test/java/world/bentobox/aoneblock/listeners/BossBarListenerTest.java new file mode 100644 index 0000000..8bc4bec --- /dev/null +++ b/src/test/java/world/bentobox/aoneblock/listeners/BossBarListenerTest.java @@ -0,0 +1,144 @@ +package world.bentobox.aoneblock.listeners; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.boss.BossBar; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +import net.kyori.adventure.text.Component; +import world.bentobox.aoneblock.AOneBlock; +import world.bentobox.aoneblock.CommonTestSetup; +import world.bentobox.aoneblock.Settings; +import world.bentobox.aoneblock.dataobjects.OneBlockIslands; +import world.bentobox.aoneblock.events.MagicBlockEvent; +import world.bentobox.aoneblock.oneblocks.OneBlocksManager; + +/** + * Tests the display of the boss bar and action bar, and in particular that the + * config.yml settings turn them off (https://github.com/BentoBoxWorld/AOneBlock/issues/537). + * @author tastybento + */ +public class BossBarListenerTest extends CommonTestSetup { + + private AOneBlock addon; + private Settings settings; + private BossBarListener bbl; + @Mock + private OneBlocksManager obm; + @Mock + private OneBlockIslands obi; + @Mock + private BossBar bossBar; + @Mock + private Block block; + + /** + */ + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + addon = spy(new AOneBlock()); + settings = new Settings(); + addon.setSettings(settings); + doNothing().when(addon).logError(anyString()); + doReturn(obm).when(addon).getOneBlockManager(); + doReturn(obi).when(addon).getOneBlocksIsland(any()); + + // Phase progress + when(obi.getPhaseName()).thenReturn("Plains"); + when(obm.getNextPhaseBlocks(obi)).thenReturn(100); + when(obm.getPhaseBlocks(obi)).thenReturn(500); + when(obm.getPercentageDone(obi)).thenReturn(80D); + + // Bukkit + mockedBukkit.when(() -> Bukkit.getPlayer(uuid)).thenReturn(mockPlayer); + mockedBukkit.when(() -> Bukkit.createBossBar(anyString(), any(), any())).thenReturn(bossBar); + when(bossBar.getPlayers()).thenReturn(Collections.emptyList()); + + bbl = new BossBarListener(addon); + } + + /** + */ + @Override + @AfterEach + public void tearDown() throws Exception { + super.tearDown(); + } + + private void fireMagicBlockEvent() { + bbl.onBreakBlockEvent(new MagicBlockEvent(island, uuid, null, block, Material.STONE)); + } + + /** + * Test that the action bar is shown when enabled in the config and allowed on the island. + */ + @Test + void testActionBarShownWhenEnabled() { + when(island.isAllowed(addon.ONEBLOCK_ACTIONBAR)).thenReturn(true); + fireMagicBlockEvent(); + verify(mockPlayer).sendActionBar(any(Component.class)); + } + + /** + * Test for https://github.com/BentoBoxWorld/AOneBlock/issues/537 - the action bar + * must not be shown when disabled in config.yml, even though the boss bar flag has + * registered the listener. + */ + @Test + void testActionBarNotShownWhenDisabledInConfig() { + settings.setActionBar(false); + when(island.isAllowed(addon.ONEBLOCK_ACTIONBAR)).thenReturn(true); + fireMagicBlockEvent(); + verify(mockPlayer, never()).sendActionBar(any(Component.class)); + } + + /** + * Test that the action bar is not shown when the island flag denies it. + */ + @Test + void testActionBarNotShownWhenFlagDenied() { + // island.isAllowed is false by default in CommonTestSetup + fireMagicBlockEvent(); + verify(mockPlayer, never()).sendActionBar(any(Component.class)); + } + + /** + * Test that the boss bar is shown when enabled in the config and allowed on the island. + */ + @Test + void testBossBarShownWhenEnabled() { + when(island.isAllowed(addon.ONEBLOCK_BOSSBAR)).thenReturn(true); + fireMagicBlockEvent(); + verify(bossBar).addPlayer(mockPlayer); + } + + /** + * Test that the boss bar is not shown when disabled in config.yml. + */ + @Test + void testBossBarNotShownWhenDisabledInConfig() { + settings.setBossBar(false); + when(island.isAllowed(addon.ONEBLOCK_BOSSBAR)).thenReturn(true); + fireMagicBlockEvent(); + mockedBukkit.verify(() -> Bukkit.createBossBar(anyString(), any(), any()), never()); + verify(bossBar, never()).addPlayer(any()); + } +}