Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cda9694
Initial plan
Copilot Apr 9, 2026
62c5c85
Add CraftEngine custom block support
Copilot Apr 9, 2026
0419455
Fix comment wording in CraftEngineListener
Copilot Apr 9, 2026
87c14e4
Initial plan
Copilot Apr 11, 2026
5a086d2
docs: strengthen README documentation for MythicMobs, ItemsAdder, and…
Copilot Apr 11, 2026
1dee3cb
Merge pull request #498 from BentoBoxWorld/copilot/fix-mythicmobs-bug…
tastybento Apr 11, 2026
1a48e8a
Add craft-engine-core dependency to fix compilation errors
Copilot Apr 11, 2026
98c1086
Merge pull request #496 from BentoBoxWorld/copilot/add-support-for-cr…
tastybento Apr 18, 2026
afc0c8d
Update build version to 1.24.0
tastybento Apr 18, 2026
50c159b
Initial plan
Copilot Apr 19, 2026
338bb81
fix: return defaults for empty placeholders when player has no island
Copilot Apr 19, 2026
461da40
Merge pull request #501 from BentoBoxWorld/copilot/fix-empty-placehol…
tastybento Apr 19, 2026
78bed9a
Add missing actionbar and placeholder translations to all locale files
tastybento Apr 19, 2026
30bd7c8
Update CLAUDE.md with dependency lookup, project layout, and key depe…
tastybento Apr 19, 2026
fbc0f06
refactor: reduce cognitive complexity in BlockListener and OneBlocksM…
tastybento Apr 19, 2026
e5ef79b
fix: address 36 SonarCloud MEDIUM code-quality issues
tastybento Apr 19, 2026
6771e64
fix: resolve SonarCloud LOW severity issues
tastybento Apr 19, 2026
d645a60
fix: pin modrinth-publish action to full commit SHA (S7637)
tastybento Apr 19, 2026
bcd51a5
fix: consolidate getLocation() call in BossBarListener (S2637)
tastybento Apr 19, 2026
9beac33
fix: enable JaCoCo coverage reporting to SonarCloud
tastybento Apr 19, 2026
c823f01
refactor: use BentoBox CraftEngineHook instead of direct API calls
tastybento Apr 21, 2026
4b2b755
fix: enable snapshots for bentoboxworld repository in pom.xml
tastybento Apr 23, 2026
cd5f0d1
Merge pull request #503 from BentoBoxWorld/feat/craftengine-hook
tastybento Apr 23, 2026
b811b4e
fix: resolve S2637 nullability warnings in listeners
tastybento Apr 26, 2026
5d1a7f4
Initial plan
Copilot Apr 26, 2026
fab1a1c
Disable OBSIDIAN_SCOOPING by default
Copilot Apr 26, 2026
f59dff3
Initial plan
Copilot Apr 26, 2026
8669105
Merge pull request #505 from BentoBoxWorld/copilot/disallow-obsidian-…
tastybento Apr 26, 2026
4bc726c
Initial plan
Copilot Apr 26, 2026
a25d2d7
Add CHEST_WITH_X fixed block notation and update Plains phase starter…
Copilot Apr 26, 2026
2675052
feat: add configurable chest particle types and colors per rarity
Copilot Apr 26, 2026
0244e37
fix: make resolveChestColor explicit for all rarity cases
Copilot Apr 26, 2026
ed0bb22
Merge pull request #506 from BentoBoxWorld/copilot/fix-sequences-of-b…
tastybento Apr 26, 2026
cc3bc02
Merge pull request #507 from BentoBoxWorld/copilot/add-chest-particle…
tastybento Apr 26, 2026
3457284
Initial plan
Copilot Apr 26, 2026
988eda8
Fix NPE in loadData() when called before oneBlockManager is initialized
Copilot Apr 26, 2026
3272242
Merge pull request #509 from BentoBoxWorld/copilot/fix-aoneblock-relo…
tastybento Apr 26, 2026
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/modrinth-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
# project page under the three-dot menu ("Copy ID")
#
- name: Publish to Modrinth
uses: cloudnode-pro/modrinth-publish@v2
uses: cloudnode-pro/modrinth-publish@0be4916ad5f081d936eb5615aa35ce3f0949979c # v2
with:
token: ${{ secrets.MODRINTH_TOKEN }}
project: ${{ secrets.MODRINTH_PROJECT_ID }}
Expand Down
89 changes: 89 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,92 @@ AOneBlock is a BentoBox GameModeAddon for Minecraft. Players start on a single m
All tests extend `CommonTestSetup`, which sets up a MockBukkit server, mocks BentoBox and its managers (islands, players, worlds), and tears everything down after each test. Use Mockito and the repository's `world.bentobox.aoneblock.WhiteBox` helper for injecting state into private fields.

Phase YAML files under `src/main/resources/phases/` are loaded at startup; tests that exercise `OneBlocksManager` need those resources on the classpath (they are by default via Maven's test resource path).

## Dependency Source Lookup

When you need to inspect source code for a dependency (e.g., BentoBox, addons):

1. **Check local Maven repo first**: `~/.m2/repository/` — sources jars are named `*-sources.jar`
2. **Check the workspace**: Look for sibling directories or Git submodules that may contain the dependency as a local project (e.g., `../bentoBox`, `../addon-*`)
3. **Check Maven local cache for already-extracted sources** before downloading anything
4. Only download a jar or fetch from the internet if the above steps yield nothing useful

Prefer reading `.java` source files directly from a local Git clone over decompiling or extracting a jar.

In general, the latest version of BentoBox should be targeted.

## Project Layout

Related projects are checked out as siblings under `~/git/`:

**Core:**
- `bentobox/` — core BentoBox framework

**Game modes:**
- `addon-acidisland/` — AcidIsland game mode
- `addon-bskyblock/` — BSkyBlock game mode
- `Boxed/` — Boxed game mode (expandable box area)
- `CaveBlock/` — CaveBlock game mode
- `OneBlock/` — AOneBlock game mode
- `SkyGrid/` — SkyGrid game mode
- `RaftMode/` — Raft survival game mode
- `StrangerRealms/` — StrangerRealms game mode
- `Brix/` — plot game mode
- `parkour/` — Parkour game mode
- `poseidon/` — Poseidon game mode
- `gg/` — gg game mode

**Addons:**
- `addon-level/` — island level calculation
- `addon-challenges/` — challenges system
- `addon-welcomewarpsigns/` — warp signs
- `addon-limits/` — block/entity limits
- `addon-invSwitcher/` / `invSwitcher/` — inventory switcher
- `addon-biomes/` / `Biomes/` — biomes management
- `Bank/` — island bank
- `Border/` — world border for islands
- `Chat/` — island chat
- `CheckMeOut/` — island submission/voting
- `ControlPanel/` — game mode control panel
- `Converter/` — ASkyBlock to BSkyBlock converter
- `DimensionalTrees/` — dimension-specific trees
- `discordwebhook/` — Discord integration
- `Downloads/` — BentoBox downloads site
- `DragonFights/` — per-island ender dragon fights
- `ExtraMobs/` — additional mob spawning rules
- `FarmersDance/` — twerking crop growth
- `GravityFlux/` — gravity addon
- `Greenhouses-addon/` — greenhouse biomes
- `IslandFly/` — island flight permission
- `IslandRankup/` — island rankup system
- `Likes/` — island likes/dislikes
- `Limits/` — block/entity limits
- `lost-sheep/` — lost sheep adventure
- `MagicCobblestoneGenerator/` — custom cobblestone generator
- `PortalStart/` — portal-based island start
- `pp/` — pp addon
- `Regionerator/` — region management
- `Residence/` — residence addon
- `TopBlock/` — top ten for OneBlock
- `TwerkingForTrees/` — twerking tree growth
- `Upgrades/` — island upgrades (Vault)
- `Visit/` — island visiting
- `weblink/` — web link addon
- `CrowdBound/` — CrowdBound addon

**Data packs:**
- `BoxedDataPack/` — advancement datapack for Boxed

**Documentation & tools:**
- `docs/` — main documentation site
- `docs-chinese/` — Chinese documentation
- `docs-french/` — French documentation
- `BentoBoxWorld.github.io/` — GitHub Pages site
- `website/` — website
- `translation-tool/` — translation tool

Check these for source before any network fetch.

## Key Dependencies (source locations)

- `world.bentobox:bentobox` → `~/git/bentobox/src/`
88 changes: 83 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,12 @@ blocks:
# #303: spawn a MythicMob via BentoBox's MythicMobs hook. Requires the MythicMobs
# plugin to be installed; otherwise the entry is logged and skipped at runtime.
- type: mythic-mob
mob: SkeletalKnight
level: 3
power: 1.0
display-name: "Boss"
underlying-block: STONE
mob: SkeletalKnight # MythicMob internal type ID (required)
level: 3 # mob level (optional, default: 1)
power: 1.0 # mob power multiplier (optional, default: 0)
display-name: "Boss" # override display name (optional)
stance: "" # MythicMobs stance string (optional)
underlying-block: STONE # block placed under the mob (optional, default: STONE)
probability: 5
```

Expand Down Expand Up @@ -251,6 +252,83 @@ setblock mode flag so the intent is obvious at a glance.
> if it works there it will work here. Bad NBT is logged and the spawn is
> skipped.

#### MythicMobs configuration

To use `type: mythic-mob` you need:
1. [MythicMobs](https://www.spigotmc.org/resources/mythicmobs.5702/) (free or premium) installed on the server.
2. BentoBox's built-in MythicMobs hook active (it registers automatically when MythicMobs is detected).

**Fields:**

| Field | Required | Default | Description |
|---|---|---|---|
| `mob` | ✅ | — | The internal MythicMobs mob type ID as defined in your MythicMobs config (case-sensitive). |
| `level` | ❌ | `1` | The level at which to spawn the mob. |
| `power` | ❌ | `0` | The power multiplier for the mob. |
| `display-name` | ❌ | mob ID | Override the mob's display name. |
| `stance` | ❌ | `""` | An optional MythicMobs stance string. |
| `underlying-block` | ❌ | `STONE` | The vanilla block placed at the magic-block position before the mob spawns. |
| `probability` | ❌ | — | The relative spawn weight in the phase pool. |

**Alternative approach using commands:**

If you experience any issues with MythicMobs skills or abilities when spawning
via `type: mythic-mob`, you can use the MythicMobs `/mm mobs spawn` command
inside the phase's `start-commands` or `end-commands` instead. This spawns the
mob through MythicMobs directly, which ensures all skills and behaviours work
exactly as configured:

```yaml
start-commands:
# Spawn mob at the island's magic-block position using MythicMobs command.
# Replace <world>, <x>, <y>, <z> with the actual coordinates, or use a
# console command that targets the player's location.
- 'mm mobs spawn MY_MYTHIC_MOB 1 [world],[x],[y],[z]'
```

> **Tip:** When spawning MythicMobs via commands you have full control over
> the exact spawn location and can still use all MythicMobs features without
> any compatibility limitations.

#### ItemsAdder custom blocks

Requires the [ItemsAdder](https://www.spigotmc.org/resources/itemsadder.73355/)
plugin to be installed. ItemsAdder blocks can be referenced in two ways:

**Map form** (inside a `blocks:` or `custom-blocks:` list):
```yaml
blocks:
- type: itemsadder
id: namespace:block_id # ItemsAdder block ID (required)
probability: 20
```

**Short form** — place the ItemsAdder block ID directly as a map key (same as
vanilla materials):
```yaml
blocks:
namespace:block_id: 20
```

#### Nexo custom blocks

Requires the [Nexo](https://www.spigotmc.org/resources/nexo.112709/) plugin to
be installed. Nexo blocks can be referenced in two ways:

**Map form** (inside a `blocks:` or `custom-blocks:` list):
```yaml
blocks:
- type: nexo
id: nexo_block_id # Nexo block ID (required)
probability: 20
```

**Short form** — place the Nexo block ID directly as a map key:
```yaml
blocks:
nexo_block_id: 20
```

If you'd rather leave your existing `blocks:` map-form section untouched, you
can put custom entries in a sibling `custom-blocks:` list. Both sections are
read and their entries merged into the same weighted pool, so probabilities in
Expand Down
29 changes: 25 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,23 @@
<mockito.version>5.11.0</mockito.version>
<mock-bukkit.version>v1.21-SNAPSHOT</mock-bukkit.version>
<!-- More visible way how to change dependency versions -->
<bentobox.version>3.13.0</bentobox.version>
<bentobox.version>3.15.0-SNAPSHOT</bentobox.version>
<items-adder.version>4.0.10</items-adder.version>
<nexo.version>1.8.0</nexo.version>
<craftengine.version>0.0.67</craftengine.version>
<level.version>2.6.2</level.version>
<bank.version>1.3.0</bank.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- 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.23.0</build.version>
<build.version>1.24.0</build.version>
<!-- SonarCloud -->
<sonar.projectKey>BentoBoxWorld_AOneBlock</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.coverage.jacoco.xmlReportPaths>${project.build.directory}/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>

<!-- Profiles will allow to automatically change build version. -->
Expand Down Expand Up @@ -136,7 +138,7 @@
<id>bentoboxworld</id>
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<!-- Paper API snapshots -->
<repository>
Expand All @@ -159,6 +161,13 @@
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<!-- CraftEngine API -->
<repository>
<id>momirealms-releases</id>
<url>https://repo.momirealms.net/releases/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<!-- General Maven public mirror -->
<repository>
<id>codemc-repo</id>
Expand Down Expand Up @@ -271,6 +280,18 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.momirealms</groupId>
<artifactId>craft-engine-bukkit</artifactId>
<version>${craftengine.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -343,7 +364,7 @@
<include>**/*Test?.java</include>
<include>**/*Test??.java</include>
</includes>
<argLine>
<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
22 changes: 22 additions & 0 deletions src/main/java/world/bentobox/aoneblock/AOneBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
import world.bentobox.aoneblock.listeners.BossBarListener;
import world.bentobox.aoneblock.listeners.HoloListener;
import world.bentobox.aoneblock.listeners.InfoListener;
import world.bentobox.aoneblock.listeners.CraftEngineListener;
import world.bentobox.aoneblock.listeners.ItemsAdderListener;
import world.bentobox.aoneblock.listeners.JoinLeaveListener;
import world.bentobox.aoneblock.listeners.NexoListener;
import world.bentobox.aoneblock.listeners.NoBlockHandler;
import world.bentobox.aoneblock.listeners.StartSafetyListener;
import world.bentobox.aoneblock.oneblocks.OneBlockCustomBlockCreator;
import world.bentobox.aoneblock.oneblocks.OneBlocksManager;
import world.bentobox.aoneblock.oneblocks.customblock.CraftEngineCustomBlock;
import world.bentobox.aoneblock.oneblocks.customblock.ItemsAdderCustomBlock;
import world.bentobox.aoneblock.oneblocks.customblock.NexoCustomBlock;
import world.bentobox.aoneblock.requests.IslandStatsHandler;
Expand Down Expand Up @@ -57,6 +59,8 @@ public class AOneBlock extends GameModeAddon {
private boolean hasItemsAdder = false;
/** Whether Nexo is present on the server */
private boolean hasNexo = false;
/** Whether CraftEngine is present on the server */
private boolean hasCraftEngine = false;

/** The addon settings */
private Settings settings;
Expand Down Expand Up @@ -127,6 +131,13 @@ public void onLoad() {
OneBlockCustomBlockCreator.register("nexo", NexoCustomBlock::fromMap);
hasNexo = true;
}
// Check if CraftEngine exists, if yes register listener
if (Bukkit.getPluginManager().getPlugin("CraftEngine") != null) {
registerListener(new CraftEngineListener(this));
OneBlockCustomBlockCreator.register(CraftEngineCustomBlock::fromId);
OneBlockCustomBlockCreator.register("craftengine", CraftEngineCustomBlock::fromMap);
hasCraftEngine = true;
}
// Save the default config from config.yml
saveDefaultConfig();
// Load settings from config.yml. This will check if there are any issues with
Expand Down Expand Up @@ -208,6 +219,10 @@ public void onEnable() {
* @return true if there was an error, false otherwise.
*/
public boolean loadData() {
if (oneBlockManager == null) {
// oneBlockManager is not yet initialized (addon not fully enabled)
return false;
}
try {
oneBlockManager.loadPhases();
} catch (IOException e) {
Expand Down Expand Up @@ -416,6 +431,13 @@ public boolean hasNexo() {
return hasNexo;
}

/**
* @return true if CraftEngine is on the server
*/
public boolean hasCraftEngine() {
return hasCraftEngine;
}

/**
* Set the addon's world. Used only for testing.
* @param world world
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class AOneBlockPlaceholders {

private static final TreeMap<Double, String> SCALE;
private static final String INFINITE = "aoneblock.placeholders.infinite";
private static final String UNKNOWN_PHASE = "aoneblock.placeholders.my-island-phase-default";
static {
SCALE = new TreeMap<>();
SCALE.put(0D, "&c╍╍╍╍╍╍╍╍");
Expand Down Expand Up @@ -163,7 +164,8 @@ public String getCountByLocation(User user) {
public String getPhase(User user) {
if (user == null || user.getUniqueId() == null)
return "";
return getUsersIsland(user).map(i -> addon.getOneBlocksIsland(i).getPhaseName()).orElse("");
return getUsersIsland(user).map(i -> addon.getOneBlocksIsland(i).getPhaseName())
.orElse(user.getTranslation(UNKNOWN_PHASE));
}

/**
Expand All @@ -175,7 +177,7 @@ public String getPhase(User user) {
public String getCount(User user) {
if (user == null || user.getUniqueId() == null)
return "";
return getUsersIsland(user).map(i -> String.valueOf(addon.getOneBlocksIsland(i).getBlockNumber())).orElse("");
return getUsersIsland(user).map(i -> String.valueOf(addon.getOneBlocksIsland(i).getBlockNumber())).orElse("0");
}

/**
Expand Down Expand Up @@ -274,7 +276,7 @@ public String getPercentDone(User user) {
return getUsersIsland(user).map(i -> {
double num = addon.getOneBlockManager().getPercentageDone(addon.getOneBlocksIsland(i));
return Math.round(num) + "%";
}).orElse("");
}).orElse("0%");
}

/**
Expand Down
Loading
Loading