Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,12 @@

<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>minecraft-repo</id>
Expand Down Expand Up @@ -153,18 +157,17 @@
</repositories>

<dependencies>
<!-- Spigot API -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<groupId>com.github.MockBukkit</groupId>
<artifactId>MockBukkit</artifactId>
<version>v1.21-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>plugin-annotations</artifactId>
<version>1.2.3-SNAPSHOT</version>
<scope>compile</scope>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Apache Commons Text -->
<dependency>
Expand Down Expand Up @@ -223,7 +226,6 @@
<version>${items-adder.version}</version>
<scope>provided</scope>
</dependency>

</dependencies>

<build>
Expand Down Expand Up @@ -292,7 +294,6 @@
<version>3.0.0-M5</version>
<configuration>
<argLine>
${argLine}
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.math=ALL-UNNAMED
--add-opens java.base/java.io=ALL-UNNAMED
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/world/bentobox/aoneblock/AOneBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,15 @@ public class AOneBlock extends GameModeAddon {
.listener(bossBar)
.defaultSetting(true)
.build();

/**
* Flag to enable or disable the OneBlock action bar.
*/
public final Flag ONEBLOCK_ACTIONBAR = new Flag.Builder("ONEBLOCK_ACTIONBAR", Material.IRON_BARS)
.mode(Mode.BASIC)
.type(Type.SETTING)
.listener(bossBar)
.defaultSetting(true)
.build();
/**
* Flag to set who can break the magic block.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package world.bentobox.aoneblock.commands.island;

import java.util.List;

import world.bentobox.aoneblock.AOneBlock;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;

public class IslandActionBarCommand extends CompositeCommand {

private AOneBlock addon;

public IslandActionBarCommand(CompositeCommand islandCommand, String label, String[] aliases)
{
super(islandCommand, label, aliases);
}

@Override
public void setup() {
setDescription("aoneblock.commands.island.actionbar.description");
setOnlyPlayer(true);
// Permission
setPermission("island.actionbar");
addon = getAddon();
}

@Override
public boolean execute(User user, String label, List<String> args) {
addon.getBossBar().toggleUser(user);
getIslands().getIslandAt(user.getLocation()).ifPresent(i -> {
if (!i.isAllowed(addon.ONEBLOCK_ACTIONBAR)) {
user.sendMessage("aoneblock.actionbar.not-active");
}
});
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import org.bukkit.event.player.PlayerQuitEvent;
import org.eclipse.jdt.annotation.NonNull;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import world.bentobox.aoneblock.AOneBlock;
import world.bentobox.aoneblock.dataobjects.OneBlockIslands;
import world.bentobox.aoneblock.events.MagicBlockEvent;
Expand All @@ -30,6 +33,12 @@
public class BossBarListener implements Listener {

private static final String AONEBLOCK_BOSSBAR = "aoneblock.bossbar";
private static final String AONEBLOCK_ACTIONBAR = "aoneblock.actionbar";

private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.builder()
.character('&')
.hexColors() // Enables support for modern hex codes (e.g., &#FF0000) alongside legacy codes.
.build();

public BossBarListener(AOneBlock addon) {
super();
Expand All @@ -45,12 +54,14 @@ public BossBarListener(AOneBlock addon) {
public void onBreakBlockEvent(MagicBlockEvent e) {
// Update boss bar
tryToShowBossBar(e.getPlayerUUID(), e.getIsland());
tryToShowActionBar(e.getPlayerUUID(), e.getIsland());
}

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onEnterIsland(IslandEnterEvent event) {
if (addon.inWorld(event.getIsland().getWorld())) {
tryToShowBossBar(event.getPlayerUUID(), event.getIsland());
tryToShowActionBar(event.getPlayerUUID(), event.getIsland());
}
}

Expand All @@ -59,10 +70,56 @@ public void onFlagChange(FlagSettingChangeEvent e) {
if (e.getEditedFlag() == addon.ONEBLOCK_BOSSBAR) {
// Show to players on island. If it isn't allowed then this will clean up the boss bar too
e.getIsland().getPlayersOnIsland().stream().map(Player::getUniqueId)
.forEach(uuid -> this.tryToShowBossBar(uuid, e.getIsland()));
.forEach(uuid -> {
tryToShowBossBar(uuid, e.getIsland());
tryToShowActionBar(uuid, e.getIsland());
});
}
}

/**
* Converts a string containing Bukkit color codes ('&') into an Adventure Component.
*
* @param legacyString The string with Bukkit color and format codes.
* @return The resulting Adventure Component.
*/
public static Component bukkitToAdventure(String legacyString) {
if (legacyString == null) {
return Component.empty();
}
return LEGACY_SERIALIZER.deserialize(legacyString);
}

private void tryToShowActionBar(UUID uuid, Island island) {
User user = User.getInstance(uuid);
Player player = Bukkit.getPlayer(uuid);

// Only show if enabled for island
if (!island.isAllowed(addon.ONEBLOCK_ACTIONBAR)) {
return;
}
// Default to showing boss bar unless it is explicitly turned off
if (!user.getMetaData(AONEBLOCK_ACTIONBAR).map(MetaDataValue::asBoolean).orElse(true)) {
// Remove any boss bar from user if they are in the world
removeBar(user, island);
// Do not show a boss bar
return;
}
// Get the progress
@NonNull
OneBlockIslands obi = addon.getOneBlocksIsland(island);

// --- Create the Action Bar Component ---
int numBlocksToGo = addon.getOneBlockManager().getNextPhaseBlocks(obi);
int phaseBlocks = addon.getOneBlockManager().getPhaseBlocks(obi);
int done = phaseBlocks - numBlocksToGo;
String translation = user.getTranslationOrNothing("aoneblock.actionbar.status", "[togo]",
String.valueOf(numBlocksToGo), "[total]", String.valueOf(phaseBlocks), "[done]", String.valueOf(done),
"[phase-name]", obi.getPhaseName(), "[percent-done]",
Math.round(addon.getOneBlockManager().getPercentageDone(obi)) + "%");
// Send
player.sendActionBar(bukkitToAdventure(translation));
}
/**
* Try to show the bossbar to the player
* @param uuid player's UUID
Expand Down Expand Up @@ -128,7 +185,6 @@ private void tryToShowBossBar(UUID uuid, Island island) {
}
// Save the boss bar for later reference (e.g., when updating or removing)
islandBossBars.put(island, bar);

}

private void removeBar(User user, Island island) {
Expand Down Expand Up @@ -159,7 +215,7 @@ public void onJoin(PlayerJoinEvent e) {
return;
}
addon.getIslands().getIslandAt(e.getPlayer().getLocation())
.ifPresent(is -> this.tryToShowBossBar(e.getPlayer().getUniqueId(), is));
.ifPresent(is -> this.tryToShowBossBar(e.getPlayer().getUniqueId(), is));
}

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
Expand All @@ -179,7 +235,7 @@ public void toggleUser(User user) {
if (newState) {
// If the player is on an island then show the bar
addon.getIslands().getIslandAt(user.getLocation()).filter(is -> addon.inWorld(is.getWorld()))
.ifPresent(is -> this.tryToShowBossBar(user.getUniqueId(), is));
.ifPresent(is -> this.tryToShowBossBar(user.getUniqueId(), is));
user.sendMessage("aoneblock.commands.island.bossbar.status_on");
} else {
// Remove player from any boss bars. Adding happens automatically
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
Expand Down Expand Up @@ -260,7 +260,7 @@ private Map<Integer, OneBlockObject> parseFirstBlocksConfig(ConfigurationSection
Map<Integer, OneBlockObject> result = new HashMap<>();

for (String key : firstBlocksConfig.getKeys(false)) {
if (!NumberUtils.isNumber(key)) {
if (!NumberUtils.isCreatable(key)) {
addon.logError("Fixed block key must be an integer. " + key);
continue;
}
Expand Down Expand Up @@ -335,7 +335,7 @@ private void addHologramLines(OneBlockPhase obPhase, ConfigurationSection fb) {
return;
Map<Integer, String> result = new HashMap<>();
for (String key : fb.getKeys(false)) {
if (!NumberUtils.isNumber(key)) {
if (!NumberUtils.isCreatable(key)) {
addon.logError("Fixed block key must be an integer. " + key);
continue;
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/resources/locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ protection:
description: |
&b Shows a status bar
&b for each phase.

ONEBLOCK_ACTIONBAR:
name: Action Bar
description: |
&b Shows a status
&b for each phase
&b in the Action Bar.

aoneblock:
bossbar:
title: "Blocks remaining"
Expand All @@ -35,6 +43,9 @@ aoneblock:
# SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20
style: SOLID
not-active: "&c Boss Bar is not active for this island"
actionbar:
status: "&a Phase: &b [phase-name] &d | &a Blocks: &b [done] &d / &b [total] &d | &a Progression: &b [percent-done]"
not-active: "&c Action Bar is not active for this island"
commands:
admin:
setcount:
Expand Down Expand Up @@ -71,6 +82,10 @@ aoneblock:
description: "toggles phase boss bar"
status_on: "&b Bossbar turned &a on"
status_off: "&b Bossbar turned &c off"
actionbar:
description: "toggles phase action bar"
status_on: "&b Action Bar turned &a on"
status_off: "&b Action Bar turned &c off"
setcount:
parameters: "<count>"
description: "set block count to previously completed value"
Expand Down
10 changes: 7 additions & 3 deletions src/test/java/world/bentobox/aoneblock/AOneBlockTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.RETURNS_MOCKS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockitoSession;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -40,6 +42,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockbukkit.mockbukkit.MockBukkit;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
Expand Down Expand Up @@ -110,7 +113,7 @@ public static void beforeClass() throws IllegalAccessException, InvocationTarget

@After
public void tearDown() throws IOException {
ServerMocks.unsetBukkitServer();
MockBukkit.unmock();
User.clearUsers();
Mockito.framework().clearInlineMocks();
deleteAll(new File("database"));
Expand All @@ -132,7 +135,8 @@ private void deleteAll(File file) throws IOException {
*/
@Before
public void setUp() throws Exception {
Server server = ServerMocks.newServer();
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
Server server = MockBukkit.mock();
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
when(plugin.getLogger()).thenReturn(Logger.getAnonymousLogger());
Expand Down Expand Up @@ -174,7 +178,7 @@ public void setUp() throws Exception {
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));

// Server
PowerMockito.mockStatic(Bukkit.class);
PowerMockito.mockStatic(Bukkit.class, RETURNS_MOCKS);
when(Bukkit.getServer()).thenReturn(server);
when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger());
when(Bukkit.getPluginManager()).thenReturn(mock(PluginManager.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
Expand All @@ -39,11 +40,13 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockbukkit.mockbukkit.MockBukkit;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;

import world.bentobox.aoneblock.AOneBlock;
import world.bentobox.aoneblock.Settings;
import world.bentobox.aoneblock.mocks.ServerMocks;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.IslandsManager;

Expand Down Expand Up @@ -75,6 +78,8 @@ public class BlockProtectTest {
*/
@Before
public void setUp() throws Exception {

Server server = MockBukkit.mock();

when(p.getWorld()).thenReturn(world);
// In World
Expand Down Expand Up @@ -105,6 +110,7 @@ public void setUp() throws Exception {
*/
@After
public void tearDown() throws Exception {
MockBukkit.unmock();
}

/**
Expand Down
Loading
Loading