Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cd55357
Version 2.22.1
tastybento Oct 11, 2025
c13774c
Remove 'chain' from config
tastybento Oct 11, 2025
5059619
WIP - not working yet
tastybento Nov 28, 2025
6a2abbe
Improvements
tastybento Nov 28, 2025
a5ccb7b
Fixed test
tastybento Nov 28, 2025
3b4163c
Remove debug.
tastybento Nov 28, 2025
b58e621
Remove commented out code
tastybento Nov 28, 2025
5a4e264
Merge pull request #393 from BentoBoxWorld/mockito5
tastybento Nov 28, 2025
cc9fda1
Add block limit count placeholder #391
tastybento Nov 28, 2025
9f71ece
Merge pull request #394 from BentoBoxWorld/391_block_count_limit_plac…
tastybento Nov 28, 2025
2613fb3
Add CLAUDE.md with build commands and architecture overview
tastybento Feb 20, 2026
a6e5d3d
Add Oraxen furniture mechanic support for island level calculation #390
tastybento Feb 20, 2026
ee1dd24
Update Paper API to 1.21.11 to match MockBukkit
tastybento Feb 20, 2026
6a319f3
Update Paper API to 1.21.11 to match MockBukkit
tastybento Feb 20, 2026
b83349a
Merge pull request #399 from BentoBoxWorld/update_paper_1.21.11
tastybento Feb 20, 2026
ff0e8ee
Merge pull request #397 from BentoBoxWorld/390_oraxen_furniture
tastybento Feb 20, 2026
6b224dc
Add Nexo custom block and furniture support for island level calculat…
tastybento Feb 20, 2026
3179732
Merge pull request #398 from BentoBoxWorld/389_nexo_support
tastybento Feb 20, 2026
3537573
Fix custom block placeholders for Oraxen, Nexo, and ItemsAdder #391
tastybento Feb 20, 2026
6b986b8
Merge pull request #400 from BentoBoxWorld/391_custom_block_placeholders
tastybento Feb 20, 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
96 changes: 96 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**Level** is a BentoBox add-on for Minecraft that calculates island levels based on block types and counts, maintains top-ten leaderboards, and provides competitive metrics for players on game modes like BSkyBlock and AcidIsland.

## Build & Test Commands

```bash
# Build
mvn clean package

# Run all tests
mvn test

# Run a single test class
mvn test -Dtest=LevelTest

# Run a specific test method
mvn test -Dtest=LevelTest#testMethodName

# Full build with coverage
mvn verify
```

Java 21 is required. The build produces a shaded JAR (includes PanelUtils).

## Architecture

### Entry Points
- `LevelPladdon` — Bukkit plugin entry point; instantiates `Level` via the `Pladdon` interface
- `Level` — main addon class; loads config, registers commands/listeners/placeholders, and hooks into optional third-party plugins

### Lifecycle
`onLoad()` → `onEnable()` → `allLoaded()`

`allLoaded()` is where integrations with other BentoBox add-ons (Warps, Visit) are established, since those may not be loaded yet during `onEnable()`.

### Key Classes

| Class | Role |
|---|---|
| `LevelsManager` | Central manager: island level cache, top-ten lists, database reads/writes |
| `Pipeliner` | Async queue; limits concurrent island calculations (configurable) |
| `IslandLevelCalculator` | Core chunk-scanning algorithm; supports multiple block stacker plugins |
| `Results` | Data object returned by a completed calculation |
| `ConfigSettings` | Main config bound to `config.yml` via BentoBox's `@ConfigEntry` annotations |
| `BlockConfig` | Block point-value mappings from `blockconfig.yml` |
| `PlaceholderManager` | Registers PlaceholderAPI placeholders |

### Package Layout
```
world/bentobox/level/
├── calculators/ # IslandLevelCalculator, Pipeliner, Results, EquationEvaluator
├── commands/ # Player and admin sub-commands
├── config/ # ConfigSettings, BlockConfig
├── events/ # IslandPreLevelEvent, IslandLevelCalculatedEvent
├── listeners/ # Island activity, join/leave, migration listeners
├── objects/ # IslandLevels, TopTenData (database-persisted objects)
├── panels/ # GUI panels (top-ten, details, block values)
├── requests/ # API request handlers for inter-addon queries
└── util/ # Utils, ConversationUtils, CachedData
```

### Island Level Calculation Flow
1. A calculation request enters `Pipeliner` (async queue, default concurrency = 1)
2. `IslandLevelCalculator` scans island chunks using chunk snapshots (non-blocking)
3. Block counts are looked up against `BlockConfig` point values
4. An equation (configurable formula) converts total points → island level
5. Results are stored via `LevelsManager` and fired as `IslandLevelCalculatedEvent`

### Optional Plugin Integrations
Level hooks into these plugins when present: WildStacker, RoseStacker, UltimateStacker (block counts), AdvancedChests, ItemsAdder, Oraxen (custom blocks), and the BentoBox Warps/Visit add-ons.

## Testing

Tests live in `src/test/java/world/bentobox/level/`. The framework is JUnit 5 + Mockito 5 + MockBukkit. `CommonTestSetup` is a shared base class that sets up the MockBukkit server and BentoBox mocks — extend it for new test classes.

JaCoCo coverage reports are generated during `mvn verify`.

## Configuration Resources

| File | Location in JAR | Purpose |
|---|---|---|
| `config.yml` | `src/main/resources/` | Main settings (level cost formula, world inclusion, etc.) |
| `blockconfig.yml` | `src/main/resources/` | Points per block type |
| `locales/` | `src/main/resources/locales/` | Translation strings |
| `panels/` | `src/main/resources/panels/` | GUI layout definitions |

## Code Conventions

- Null safety via Eclipse JDT annotations (`@NonNull`, `@Nullable`) — honour these on public APIs
- BentoBox framework patterns: `CompositeCommand` for commands, `@ConfigEntry`/`@ConfigComment` for config, `@StoreAt` for database objects
- Pre- and post-events (`IslandPreLevelEvent`, `IslandLevelCalculatedEvent`) follow BentoBox's cancellable event pattern — fire both when adding new calculation triggers
107 changes: 71 additions & 36 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>21</java.version>
<!-- Non-minecraft related dependencies -->
<powermock.version>2.0.9</powermock.version>
<junit.version>5.10.2</junit.version>
<mockito.version>5.11.0</mockito.version>
<mock-bukkit.version>v1.21-SNAPSHOT</mock-bukkit.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.21.5-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>3.7.4</bentobox.version>
<paper.version>1.21.11-R0.1-SNAPSHOT</paper.version>
<bentobox.version>3.10.2</bentobox.version>
<!-- Warps addon version -->
<warps.version>1.12.0</warps.version>
<!-- Visit addon version -->
Expand All @@ -67,7 +69,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>2.22.0</build.version>
<build.version>2.23.0</build.version>
<sonar.projectKey>BentoBoxWorld_Level</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
Expand Down Expand Up @@ -124,24 +126,24 @@

<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>codemc</id>
<url>https://repo.codemc.org/repository/maven-snapshots/</url>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>bentoboxworld</id>
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
<id>codemc</id>
<url>https://repo.codemc.org/repository/maven-snapshots/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<id>bentoboxworld</id>
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
</repository>
<!--Wild Stacker repo -->
<repository>
Expand Down Expand Up @@ -169,39 +171,58 @@
<name>Oraxen Repository</name>
<url>https://repo.oraxen.com/releases</url>
</repository>
<!-- Nexo repo -->
<repository>
<id>nexo</id>
<name>Nexo Repository</name>
<url>https://repo.nexomc.com/releases</url>
</repository>
</repositories>

<dependencies>
<!-- Spigot API -->
<!-- Mock Bukkit - used to mock the server in tests -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<!-- Mockito (Unit testing) -->
<groupId>com.github.MockBukkit</groupId>
<artifactId>MockBukkit</artifactId>
<version>${mock-bukkit.version}</version>
<scope>test</scope>
</dependency>
<!-- Mockito (Unit testing) This goes at the top to ensure the dependencies are accurate. -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.11.1</version>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<!-- Paper API -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>${paper.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>world.bentobox</groupId>
<artifactId>bentobox</artifactId>
<version>3.7.4-SNAPSHOT</version>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>world.bentobox</groupId>
Expand Down Expand Up @@ -262,6 +283,19 @@
<version>4.0.10</version>
<scope>provided</scope>
</dependency>
<!-- Nexo -->
<dependency>
<groupId>com.nexomc</groupId>
<artifactId>nexo</artifactId>
<version>1.19.1</version>
<exclusions>
<exclusion>
<groupId>dev.triumphteam</groupId>
<artifactId>triumph-gui</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<!-- Oraxen -->
<dependency>
<groupId>io.th0rgal</groupId>
Expand Down Expand Up @@ -354,18 +388,19 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<version>3.14.1</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
<version>3.5.4</version>
<configuration>
<argLine>
${argLine}
-XX:+EnableDynamicAgentLoading
--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 Expand Up @@ -478,7 +513,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<version>0.8.13</version>
<configuration>
<append>true</append>
<excludes>
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/world/bentobox/level/Level.java
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,12 @@ public boolean isItemsAdder() {
return !getSettings().isDisableItemsAdder() && getPlugin().getHooks().getHook("ItemsAdder").isPresent();
}

/**
* @return true if the Nexo plugin is enabled and not disabled in config
*/
public boolean isNexo() {
return !getSettings().getDisabledPluginHooks().contains("Nexo")
&& Bukkit.getPluginManager().isPluginEnabled("Nexo");
}

}
3 changes: 1 addition & 2 deletions src/main/java/world/bentobox/level/LevelsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public LevelsManager(Level addon) {
// Set up the database handler to store and retrieve data
// Note that these are saved by the BentoBox database
handler = new Database<>(addon, IslandLevels.class);

// Initialize the cache
levelsCache = new HashMap<>();
// Initialize top ten lists
Expand Down Expand Up @@ -237,7 +238,6 @@ private long getNumBlocks(final long initialLevel) throws ParseException, IOExce
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @param ownerOnly - return level only if the target player is the owner
* @return Level of the player's island or zero if player is unknown or UUID is
* null
*/
Expand Down Expand Up @@ -492,7 +492,6 @@ public void setInitialIslandCount(@NonNull Island island, long lv) {
* member
*
* @param world - world
* @param island - island
* @param lv - level
*/
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
Expand Down
Loading