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
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ on:

jobs:
publish:
uses: bentoboxworld/.github/.github/workflows/publish-platforms.yml@ca2dcd167e8db4e0f671a976080744dda43801a6 # master
uses: bentoboxworld/.github/.github/workflows/publish-platforms.yml@1f91a0edf72e8c86d671b3b8fdd3121ac6fb88e1 # master
with:
use_release_asset: "true" # publish the jar attached to the release; do not rebuild
hangar_slug: "ChunkBlock" # blank = skip Hangar
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ earn the levels back.
- The classic OneBlock loop: 18 phases, thousands of blocks, mobs, and treasure chests.
- Territory that grows the way *you* choose — punch the border to claim the next chunk.
- A particle curtain shows the frontier; claiming chunks is celebrated in style.
- `/cb chunks` shows a live map of your territory and what you can claim next.
- `/ch chunks` shows a live map of your territory and what you can claim next.

## Installation

Expand All @@ -34,15 +34,15 @@ commands, and permissions.

## Commands

The player command is `/cb` (alias `/chunkblock`), the admin command `/cbadmin`
The player command is `/ch` (alias `/chunkblock`), the admin command `/chadmin`
(aliases `/chunkblockadmin`, `/cba`). Beyond the standard BentoBox island commands:

| Command | Description |
|---|---|
| `/cb chunks` | Your chunk count, spendable credit, and a chat map of your territory |
| `/cb count` | Magic block count and phase |
| `/cbadmin chunks <player> [reset]` | Inspect a player's chunks and credit, or re-lock them back to the start |
| `/cbadmin bypass` | Toggle chunk-lock enforcement for yourself (needs `chunkblock.mod.bypasschunks`) |
| `/ch chunks` | Your chunk count, spendable credit, and a chat map of your territory |
| `/ch count` | Magic block count and phase |
| `/chadmin chunks <player> [reset]` | Inspect a player's chunks and credit, or re-lock them back to the start |
| `/chadmin bypass` | Toggle chunk-lock enforcement for yourself (needs `chunkblock.mod.bypasschunks`) |

## How claiming works

Expand Down Expand Up @@ -106,7 +106,7 @@ Lush Caves, Dripstone Caves, Mangrove Swamp, Meadow, Cherry Grove, and Jagged Pe
Q: Why can't I walk past the glowing red wall?

A: That chunk is still locked! If you're the island owner and have level credit, hit the
wall to claim the chunk. Check `/cb chunks` to see your credit and what's claimable.
wall to claim the chunk. Check `/ch chunks` to see your credit and what's claimable.

Q: I lost levels and my farm is behind the wall now. Is it gone?

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.0.0</build.version>
<build.version>1.0.1</build.version>
<!-- SonarCloud -->
<sonar.projectKey>BentoBoxWorld_ChunkBlock</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
Expand Down
27 changes: 20 additions & 7 deletions src/main/java/world/bentobox/chunkblock/ChunkBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import world.bentobox.chunkblock.requests.UnlockedChunksHandler;
import world.bentobox.chunkblock.requests.LocationStatsHandler;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.addons.Addon.State;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.flags.Flag;
Expand Down Expand Up @@ -95,7 +96,7 @@ public class ChunkBlock extends GameModeAddon {
/**
* Flag to enable or disable start safety for players.
*/
public final Flag START_SAFETY = new Flag.Builder("START_SAFETY", Material.BAMBOO_BLOCK)
public final Flag CHUNKBLOCK_START_SAFETY = new Flag.Builder("CHUNKBLOCK_START_SAFETY", Material.BAMBOO_BLOCK)
.mode(Mode.BASIC)
.type(Type.WORLD_SETTING)
.listener(new StartSafetyListener(this))
Expand All @@ -106,7 +107,7 @@ public class ChunkBlock extends GameModeAddon {
/**
* Flag to enable or disable the OneBlock boss bar.
*/
public final Flag ONEBLOCK_BOSSBAR = new Flag.Builder("ONEBLOCK_BOSSBAR", Material.DRAGON_HEAD)
public final Flag CHUNKBLOCK_BOSSBAR = new Flag.Builder("CHUNKBLOCK_BOSSBAR", Material.DRAGON_HEAD)
.mode(Mode.BASIC)
.type(Type.SETTING)
.listener(bossBar)
Expand All @@ -115,7 +116,7 @@ public class ChunkBlock extends GameModeAddon {
/**
* Flag to enable or disable the OneBlock action bar.
*/
public final Flag ONEBLOCK_ACTIONBAR = new Flag.Builder("ONEBLOCK_ACTIONBAR", Material.IRON_BARS)
public final Flag CHUNKBLOCK_ACTIONBAR = new Flag.Builder("CHUNKBLOCK_ACTIONBAR", Material.IRON_BARS)
.mode(Mode.BASIC)
.type(Type.SETTING)
.listener(bossBar)
Expand Down Expand Up @@ -165,14 +166,14 @@ public void onLoad() {
adminCommand = new AdminCommand(this);
// Register flag with BentoBox
// Register protection flag with BentoBox
getPlugin().getFlagsManager().registerFlag(this, START_SAFETY);
getPlugin().getFlagsManager().registerFlag(this, CHUNKBLOCK_START_SAFETY);
// Bossbar
if (getSettings().isBossBar()) {
getPlugin().getFlagsManager().registerFlag(this, this.ONEBLOCK_BOSSBAR);
getPlugin().getFlagsManager().registerFlag(this, this.CHUNKBLOCK_BOSSBAR);
}
// Actionbar
if (getSettings().isActionBar()) {
getPlugin().getFlagsManager().registerFlag(this, this.ONEBLOCK_ACTIONBAR);
getPlugin().getFlagsManager().registerFlag(this, this.CHUNKBLOCK_ACTIONBAR);
}
// Magic Block protection
getPlugin().getFlagsManager().registerFlag(this, this.MAGIC_BLOCK);
Expand Down Expand Up @@ -200,6 +201,18 @@ private boolean loadSettings() {

@Override
public void onEnable() {
// ChunkBlock cannot run without the Level addon: island levels are the currency
// spent to claim chunks. addon.yml declares the hard dependency, but check here
// too so a missing Level shuts the addon down cleanly instead of leaving it
// half-alive.
if (getAddonByName("Level").isEmpty()) {
logError("ChunkBlock requires the Level addon - island levels are the currency used to claim chunks.");
logError("Install Level from https://github.com/BentoBoxWorld/Level or remove ChunkBlock. Disabling.");
// Take down the flags registered in onLoad so their listeners do not linger
getPlugin().getFlagsManager().unregister(this);
setState(State.DISABLED);
return;
}
// Initialize the OneBlock manager
oneBlockManager = new OneBlocksManager(this);
// Initialize the chunk lock manager
Expand All @@ -226,7 +239,7 @@ public void onEnable() {
registerListener(new JoinLeaveListener(this));
registerListener(new InfoListener(this));
// Note: bossBar is registered as a listener by the FlagsManager when the
// ONEBLOCK_BOSSBAR or ONEBLOCK_ACTIONBAR flag is registered in onLoad, so it
// CHUNKBLOCK_BOSSBAR or CHUNKBLOCK_ACTIONBAR flag is registered in onLoad, so it
// must not be registered here too or events would be handled twice
// Register placeholders
phManager = new ChunkBlockPlaceholders(this, getPlugin().getPlaceholdersManager());
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/world/bentobox/chunkblock/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public class Settings implements WorldSettings {
@ConfigComment("Player command. What command users will run to access their island.")
@ConfigComment("To define alias, just separate commands with white space.")
@ConfigEntry(path = "chunkblock.command.island") //, since = "1.3.0")
private String playerCommandAliases = "cb chunkblock";
private String playerCommandAliases = "ch chunkblock";

@ConfigComment("The admin command.")
@ConfigComment("To define alias, just separate commands with white space.")
@ConfigEntry(path = "chunkblock.command.admin") // , since = "1.3.0")
private String adminCommandAliases = "cbadmin chunkblockadmin cba";
private String adminCommandAliases = "chadmin chunkblockadmin cha";

@ConfigComment("The default action for new player command call.")
@ConfigComment("Sub-command of main player command that will be run on first player command call.")
Expand Down Expand Up @@ -269,7 +269,7 @@ public class Settings implements WorldSettings {
private int islandDistance = 256;

@ConfigComment("Default protection range radius in blocks. Cannot be larger than distance.")
@ConfigComment("Admins can change protection sizes for players individually using /cbadmin range set <player> <new range>")
@ConfigComment("Admins can change protection sizes for players individually using /chadmin range set <player> <new range>")
@ConfigComment("or set this permission: chunkblock.island.range.<number>")
@ConfigComment("ChunkBlock: this must cover the largest unlockable ring of chunks (see chunkblock.max-chunks).")
@ConfigEntry(path = "world.protection-range")
Expand Down Expand Up @@ -475,7 +475,7 @@ public class Settings implements WorldSettings {
private int maxHomes = 5;

// Reset
@ConfigComment("How many resets a player is allowed (manage with /cbadmin reset add/remove/reset/set command)")
@ConfigComment("How many resets a player is allowed (manage with /chadmin reset add/remove/reset/set command)")
@ConfigComment("Value of -1 means unlimited, 0 means hardcore - no resets.")
@ConfigComment("Example, 2 resets means they get 2 resets or 3 islands lifetime")
@ConfigEntry(path = "island.reset.reset-limit")
Expand Down Expand Up @@ -612,7 +612,7 @@ public class Settings implements WorldSettings {
@ConfigComment("")
@ConfigComment("Here are some examples of valid commands to execute:")
@ConfigComment(" * \"[SUDO] bbox version\"")
@ConfigComment(" * \"cbadmin deaths set [player] 0\"")
@ConfigComment(" * \"chadmin deaths set [player] 0\"")
@ConfigEntry(path = "island.commands.on-join") // , since = "1.8.0")
private List<String> onJoinCommands = new ArrayList<>();

Expand All @@ -625,7 +625,7 @@ public class Settings implements WorldSettings {
@ConfigComment("")
@ConfigComment("Here are some examples of valid commands to execute:")
@ConfigComment(" * '[SUDO] bbox version'")
@ConfigComment(" * 'cbadmin deaths set [player] 0'")
@ConfigComment(" * 'chadmin deaths set [player] 0'")
@ConfigComment("")
@ConfigComment("Note that player-executed commands might not work, as these commands can be run with said player being offline.")
@ConfigEntry(path = "island.commands.on-leave") // , since = "1.8.0")
Expand All @@ -640,7 +640,7 @@ public class Settings implements WorldSettings {
@ConfigComment("")
@ConfigComment("Here are some examples of valid commands to execute:")
@ConfigComment(" * '[SUDO] bbox version'")
@ConfigComment(" * 'cbadmin deaths set [player] 0'")
@ConfigComment(" * 'chadmin deaths set [player] 0'")
@ConfigComment("")
@ConfigComment("Note that player-executed commands might not work, as these commands can be run with said player being offline.")
@ConfigEntry(path = "island.commands.on-respawn") // , since = "1.14.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import world.bentobox.chunkblock.ChunkBlock;

/**
* /cbadmin bypass — lets staff with the bypass permission toggle chunk lock enforcement
* /chadmin bypass — lets staff with the bypass permission toggle chunk lock enforcement
* for themselves, so they can test the game as players see it and inspect cleanly.
*
* @author tastybento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import world.bentobox.chunkblock.chunks.ChunkManager;

/**
* /cbadmin chunks &lt;player&gt; [reset] — support and debug tool: shows a player's
* /chadmin chunks &lt;player&gt; [reset] — support and debug tool: shows a player's
* unlocked chunks, spending and credit, or re-locks everything back to the center chunk.
*
* @author tastybento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public void setup() {
@Override
public boolean execute(User user, String label, List<String> args) {
getIslands().getIslandAt(user.getLocation()).ifPresent(i -> {
if (!i.isAllowed(addon.ONEBLOCK_ACTIONBAR)) {
if (!i.isAllowed(addon.CHUNKBLOCK_ACTIONBAR)) {
user.sendMessage("chunkblock.actionbar.not-active");
}
});
// Toggle state
boolean newState = !user.getMetaData(BossBarListener.AONEBLOCK_ACTIONBAR).map(MetaDataValue::asBoolean).orElse(true);
user.putMetaData(BossBarListener.AONEBLOCK_ACTIONBAR, new MetaDataValue(newState));
boolean newState = !user.getMetaData(BossBarListener.ACTIONBAR_METADATA).map(MetaDataValue::asBoolean).orElse(true);
user.putMetaData(BossBarListener.ACTIONBAR_METADATA, new MetaDataValue(newState));
if (newState) {
user.sendMessage("chunkblock.commands.island.actionbar.status_on");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void setup() {
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_BOSSBAR)) {
if (!i.isAllowed(addon.CHUNKBLOCK_BOSSBAR)) {
user.sendMessage("chunkblock.bossbar.not-active");
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import world.bentobox.chunkblock.chunks.ChunkManager.ClaimResult;

/**
* /cb chunks — shows how big your island is, how much level credit you can spend, and a
* /ch chunks — shows how big your island is, how much level credit you can spend, and a
* little chat map of your territory with the chunks you could claim next.
*
* @author tastybento
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

public class BossBarListener implements Listener {

private static final String AONEBLOCK_BOSSBAR = "chunkblock.bossbar";
public static final String AONEBLOCK_ACTIONBAR = "chunkblock.actionbar";
private static final String BOSSBAR_METADATA = "chunkblock.bossbar";
public static final String ACTIONBAR_METADATA = "chunkblock.actionbar";

private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.builder()
.character('&')
Expand All @@ -50,24 +50,40 @@ public BossBarListener(ChunkBlock addon) {
// Store a boss bar for each player (using their UUID)
private final Map<Island, BossBar> islandBossBars = new HashMap<>();

/**
* This listener is registered with the flags in onLoad, so it can outlive an addon
* that never enabled (e.g. missing dependency) and therefore has no worlds. Every
* event handler must bail out via this check before touching addon state.
* @return true if the addon is running with its world available
*/
private boolean ready() {
return addon.getOverWorld() != null;
}

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onBreakBlockEvent(MagicBlockEvent e) {
if (!ready()) {
return;
}
// 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())) {
if (ready() && addon.inWorld(event.getIsland().getWorld())) {
tryToShowBossBar(event.getPlayerUUID(), event.getIsland());
tryToShowActionBar(event.getPlayerUUID(), event.getIsland());
}
}

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onFlagChange(FlagSettingChangeEvent e) {
if (e.getEditedFlag() == addon.ONEBLOCK_BOSSBAR) {
if (!ready()) {
return;
}
if (e.getEditedFlag() == addon.CHUNKBLOCK_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 -> {
Expand Down Expand Up @@ -100,11 +116,11 @@ private void tryToShowActionBar(UUID uuid, Island island) {
Player player = Bukkit.getPlayer(uuid);

// Only show if enabled for island
if (!island.isAllowed(addon.ONEBLOCK_ACTIONBAR)) {
if (!island.isAllowed(addon.CHUNKBLOCK_ACTIONBAR)) {
return;
}
// Default to showing action bar unless it is explicitly turned off
if (!user.getMetaData(AONEBLOCK_ACTIONBAR).map(MetaDataValue::asBoolean).orElse(true)) {
if (!user.getMetaData(ACTIONBAR_METADATA).map(MetaDataValue::asBoolean).orElse(true)) {
// Do not show an action bar
return;
}
Expand Down Expand Up @@ -138,7 +154,7 @@ private void tryToShowBossBar(UUID uuid, Island island) {
User user = User.getInstance(uuid);

// Only show if enabled for island
if (!island.isAllowed(addon.ONEBLOCK_BOSSBAR)) {
if (!island.isAllowed(addon.CHUNKBLOCK_BOSSBAR)) {
BossBar removed = islandBossBars.remove(island);
if (removed != null) {
// Remove all players from the boss bar
Expand All @@ -147,7 +163,7 @@ private void tryToShowBossBar(UUID uuid, Island island) {
return;
}
// Default to showing boss bar unless it is explicitly turned off
if (!user.getMetaData(AONEBLOCK_BOSSBAR).map(MetaDataValue::asBoolean).orElse(true)) {
if (!user.getMetaData(BOSSBAR_METADATA).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
Expand Down Expand Up @@ -213,6 +229,9 @@ private void removeBar(User user, Island island) {

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onExitIsland(IslandExitEvent event) {
if (!ready()) {
return;
}
User user = User.getInstance(event.getPlayerUUID());
removeBar(user, event.getIsland());
}
Expand All @@ -221,7 +240,7 @@ public void onExitIsland(IslandExitEvent event) {
public void onJoin(PlayerJoinEvent e) {
// If the player is on an island then show the bar
Location playerLoc = e.getPlayer().getLocation();
if (playerLoc == null || !addon.inWorld(playerLoc)) {
if (!ready() || playerLoc == null || !addon.inWorld(playerLoc)) {
return;
}
addon.getIslands().getIslandAt(playerLoc)
Expand All @@ -240,8 +259,8 @@ public void onQuit(PlayerQuitEvent e) {
* @param user user to toggle
*/
public void toggleUser(User user) {
boolean newState = !user.getMetaData(AONEBLOCK_BOSSBAR).map(MetaDataValue::asBoolean).orElse(true);
user.putMetaData(AONEBLOCK_BOSSBAR, new MetaDataValue(newState));
boolean newState = !user.getMetaData(BOSSBAR_METADATA).map(MetaDataValue::asBoolean).orElse(true);
user.putMetaData(BOSSBAR_METADATA, new MetaDataValue(newState));
if (newState) {
// If the player is on an island then show the bar
addon.getIslands().getIslandAt(user.getLocation()).filter(is -> addon.inWorld(is.getWorld()))
Expand Down
Loading
Loading