Skip to content

Commit 045a634

Browse files
authored
Merge pull request #401 from BentoBoxWorld/develop
Release 2.22.1
2 parents 3faaff7 + 6b986b8 commit 045a634

19 files changed

+1525
-760
lines changed

CLAUDE.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
**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.
8+
9+
## Build & Test Commands
10+
11+
```bash
12+
# Build
13+
mvn clean package
14+
15+
# Run all tests
16+
mvn test
17+
18+
# Run a single test class
19+
mvn test -Dtest=LevelTest
20+
21+
# Run a specific test method
22+
mvn test -Dtest=LevelTest#testMethodName
23+
24+
# Full build with coverage
25+
mvn verify
26+
```
27+
28+
Java 21 is required. The build produces a shaded JAR (includes PanelUtils).
29+
30+
## Architecture
31+
32+
### Entry Points
33+
- `LevelPladdon` — Bukkit plugin entry point; instantiates `Level` via the `Pladdon` interface
34+
- `Level` — main addon class; loads config, registers commands/listeners/placeholders, and hooks into optional third-party plugins
35+
36+
### Lifecycle
37+
`onLoad()``onEnable()``allLoaded()`
38+
39+
`allLoaded()` is where integrations with other BentoBox add-ons (Warps, Visit) are established, since those may not be loaded yet during `onEnable()`.
40+
41+
### Key Classes
42+
43+
| Class | Role |
44+
|---|---|
45+
| `LevelsManager` | Central manager: island level cache, top-ten lists, database reads/writes |
46+
| `Pipeliner` | Async queue; limits concurrent island calculations (configurable) |
47+
| `IslandLevelCalculator` | Core chunk-scanning algorithm; supports multiple block stacker plugins |
48+
| `Results` | Data object returned by a completed calculation |
49+
| `ConfigSettings` | Main config bound to `config.yml` via BentoBox's `@ConfigEntry` annotations |
50+
| `BlockConfig` | Block point-value mappings from `blockconfig.yml` |
51+
| `PlaceholderManager` | Registers PlaceholderAPI placeholders |
52+
53+
### Package Layout
54+
```
55+
world/bentobox/level/
56+
├── calculators/ # IslandLevelCalculator, Pipeliner, Results, EquationEvaluator
57+
├── commands/ # Player and admin sub-commands
58+
├── config/ # ConfigSettings, BlockConfig
59+
├── events/ # IslandPreLevelEvent, IslandLevelCalculatedEvent
60+
├── listeners/ # Island activity, join/leave, migration listeners
61+
├── objects/ # IslandLevels, TopTenData (database-persisted objects)
62+
├── panels/ # GUI panels (top-ten, details, block values)
63+
├── requests/ # API request handlers for inter-addon queries
64+
└── util/ # Utils, ConversationUtils, CachedData
65+
```
66+
67+
### Island Level Calculation Flow
68+
1. A calculation request enters `Pipeliner` (async queue, default concurrency = 1)
69+
2. `IslandLevelCalculator` scans island chunks using chunk snapshots (non-blocking)
70+
3. Block counts are looked up against `BlockConfig` point values
71+
4. An equation (configurable formula) converts total points → island level
72+
5. Results are stored via `LevelsManager` and fired as `IslandLevelCalculatedEvent`
73+
74+
### Optional Plugin Integrations
75+
Level hooks into these plugins when present: WildStacker, RoseStacker, UltimateStacker (block counts), AdvancedChests, ItemsAdder, Oraxen (custom blocks), and the BentoBox Warps/Visit add-ons.
76+
77+
## Testing
78+
79+
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.
80+
81+
JaCoCo coverage reports are generated during `mvn verify`.
82+
83+
## Configuration Resources
84+
85+
| File | Location in JAR | Purpose |
86+
|---|---|---|
87+
| `config.yml` | `src/main/resources/` | Main settings (level cost formula, world inclusion, etc.) |
88+
| `blockconfig.yml` | `src/main/resources/` | Points per block type |
89+
| `locales/` | `src/main/resources/locales/` | Translation strings |
90+
| `panels/` | `src/main/resources/panels/` | GUI layout definitions |
91+
92+
## Code Conventions
93+
94+
- Null safety via Eclipse JDT annotations (`@NonNull`, `@Nullable`) — honour these on public APIs
95+
- BentoBox framework patterns: `CompositeCommand` for commands, `@ConfigEntry`/`@ConfigComment` for config, `@StoreAt` for database objects
96+
- Pre- and post-events (`IslandPreLevelEvent`, `IslandLevelCalculatedEvent`) follow BentoBox's cancellable event pattern — fire both when adding new calculation triggers

pom.xml

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@
5252
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
5353
<java.version>21</java.version>
5454
<!-- Non-minecraft related dependencies -->
55-
<powermock.version>2.0.9</powermock.version>
55+
<junit.version>5.10.2</junit.version>
56+
<mockito.version>5.11.0</mockito.version>
57+
<mock-bukkit.version>v1.21-SNAPSHOT</mock-bukkit.version>
5658
<!-- More visible way how to change dependency versions -->
57-
<spigot.version>1.21.5-R0.1-SNAPSHOT</spigot.version>
58-
<bentobox.version>3.7.4</bentobox.version>
59+
<paper.version>1.21.11-R0.1-SNAPSHOT</paper.version>
60+
<bentobox.version>3.10.2</bentobox.version>
5961
<!-- Warps addon version -->
6062
<warps.version>1.12.0</warps.version>
6163
<!-- Visit addon version -->
@@ -67,7 +69,7 @@
6769
<!-- Do not change unless you want different name for local builds. -->
6870
<build.number>-LOCAL</build.number>
6971
<!-- This allows to change between versions. -->
70-
<build.version>2.22.0</build.version>
72+
<build.version>2.23.0</build.version>
7173
<sonar.projectKey>BentoBoxWorld_Level</sonar.projectKey>
7274
<sonar.organization>bentobox-world</sonar.organization>
7375
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
@@ -124,24 +126,24 @@
124126

125127
<repositories>
126128
<repository>
127-
<id>spigot-repo</id>
128-
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
129+
<id>jitpack.io</id>
130+
<url>https://jitpack.io</url>
129131
</repository>
130132
<repository>
131-
<id>codemc</id>
132-
<url>https://repo.codemc.org/repository/maven-snapshots/</url>
133+
<id>codemc-repo</id>
134+
<url>https://repo.codemc.org/repository/maven-public</url>
133135
</repository>
134136
<repository>
135-
<id>codemc-repo</id>
136-
<url>https://repo.codemc.org/repository/maven-public/</url>
137+
<id>papermc</id>
138+
<url>https://repo.papermc.io/repository/maven-public/</url>
137139
</repository>
138140
<repository>
139-
<id>bentoboxworld</id>
140-
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
141+
<id>codemc</id>
142+
<url>https://repo.codemc.org/repository/maven-snapshots/</url>
141143
</repository>
142144
<repository>
143-
<id>jitpack.io</id>
144-
<url>https://jitpack.io</url>
145+
<id>bentoboxworld</id>
146+
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
145147
</repository>
146148
<!--Wild Stacker repo -->
147149
<repository>
@@ -169,39 +171,58 @@
169171
<name>Oraxen Repository</name>
170172
<url>https://repo.oraxen.com/releases</url>
171173
</repository>
174+
<!-- Nexo repo -->
175+
<repository>
176+
<id>nexo</id>
177+
<name>Nexo Repository</name>
178+
<url>https://repo.nexomc.com/releases</url>
179+
</repository>
172180
</repositories>
173181

174182
<dependencies>
175-
<!-- Spigot API -->
183+
<!-- Mock Bukkit - used to mock the server in tests -->
176184
<dependency>
177-
<groupId>org.spigotmc</groupId>
178-
<artifactId>spigot-api</artifactId>
179-
<version>${spigot.version}</version>
180-
<scope>provided</scope>
181-
</dependency>
182-
<!-- Mockito (Unit testing) -->
185+
<groupId>com.github.MockBukkit</groupId>
186+
<artifactId>MockBukkit</artifactId>
187+
<version>${mock-bukkit.version}</version>
188+
<scope>test</scope>
189+
</dependency>
190+
<!-- Mockito (Unit testing) This goes at the top to ensure the dependencies are accurate. -->
191+
<dependency>
192+
<groupId>org.junit.jupiter</groupId>
193+
<artifactId>junit-jupiter-api</artifactId>
194+
<version>${junit.version}</version>
195+
<scope>test</scope>
196+
</dependency>
197+
<dependency>
198+
<groupId>org.junit.jupiter</groupId>
199+
<artifactId>junit-jupiter-engine</artifactId>
200+
<version>${junit.version}</version>
201+
<scope>test</scope>
202+
</dependency>
203+
<dependency>
204+
<groupId>org.mockito</groupId>
205+
<artifactId>mockito-junit-jupiter</artifactId>
206+
<version>5.11.0</version>
207+
<scope>test</scope>
208+
</dependency>
183209
<dependency>
184210
<groupId>org.mockito</groupId>
185211
<artifactId>mockito-core</artifactId>
186-
<version>3.11.1</version>
212+
<version>${mockito.version}</version>
187213
<scope>test</scope>
188214
</dependency>
215+
<!-- Paper API -->
189216
<dependency>
190-
<groupId>org.powermock</groupId>
191-
<artifactId>powermock-module-junit4</artifactId>
192-
<version>${powermock.version}</version>
193-
<scope>test</scope>
194-
</dependency>
195-
<dependency>
196-
<groupId>org.powermock</groupId>
197-
<artifactId>powermock-api-mockito2</artifactId>
198-
<version>${powermock.version}</version>
199-
<scope>test</scope>
217+
<groupId>io.papermc.paper</groupId>
218+
<artifactId>paper-api</artifactId>
219+
<version>${paper.version}</version>
220+
<scope>provided</scope>
200221
</dependency>
201222
<dependency>
202223
<groupId>world.bentobox</groupId>
203224
<artifactId>bentobox</artifactId>
204-
<version>3.7.4-SNAPSHOT</version>
225+
<version>3.10.0</version>
205226
</dependency>
206227
<dependency>
207228
<groupId>world.bentobox</groupId>
@@ -262,6 +283,19 @@
262283
<version>4.0.10</version>
263284
<scope>provided</scope>
264285
</dependency>
286+
<!-- Nexo -->
287+
<dependency>
288+
<groupId>com.nexomc</groupId>
289+
<artifactId>nexo</artifactId>
290+
<version>1.19.1</version>
291+
<exclusions>
292+
<exclusion>
293+
<groupId>dev.triumphteam</groupId>
294+
<artifactId>triumph-gui</artifactId>
295+
</exclusion>
296+
</exclusions>
297+
<scope>provided</scope>
298+
</dependency>
265299
<!-- Oraxen -->
266300
<dependency>
267301
<groupId>io.th0rgal</groupId>
@@ -354,18 +388,19 @@
354388
<plugin>
355389
<groupId>org.apache.maven.plugins</groupId>
356390
<artifactId>maven-compiler-plugin</artifactId>
357-
<version>3.13.0</version>
391+
<version>3.14.1</version>
358392
<configuration>
359393
<release>${java.version}</release>
360394
</configuration>
361395
</plugin>
362396
<plugin>
363397
<groupId>org.apache.maven.plugins</groupId>
364398
<artifactId>maven-surefire-plugin</artifactId>
365-
<version>3.5.2</version>
399+
<version>3.5.4</version>
366400
<configuration>
367401
<argLine>
368402
${argLine}
403+
-XX:+EnableDynamicAgentLoading
369404
--add-opens java.base/java.lang=ALL-UNNAMED
370405
--add-opens java.base/java.math=ALL-UNNAMED
371406
--add-opens java.base/java.io=ALL-UNNAMED
@@ -478,7 +513,7 @@
478513
<plugin>
479514
<groupId>org.jacoco</groupId>
480515
<artifactId>jacoco-maven-plugin</artifactId>
481-
<version>0.8.10</version>
516+
<version>0.8.13</version>
482517
<configuration>
483518
<append>true</append>
484519
<excludes>

src/main/java/world/bentobox/level/Level.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,4 +488,12 @@ public boolean isItemsAdder() {
488488
return !getSettings().isDisableItemsAdder() && getPlugin().getHooks().getHook("ItemsAdder").isPresent();
489489
}
490490

491+
/**
492+
* @return true if the Nexo plugin is enabled and not disabled in config
493+
*/
494+
public boolean isNexo() {
495+
return !getSettings().getDisabledPluginHooks().contains("Nexo")
496+
&& Bukkit.getPluginManager().isPluginEnabled("Nexo");
497+
}
498+
491499
}

src/main/java/world/bentobox/level/LevelsManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public LevelsManager(Level addon) {
5757
// Set up the database handler to store and retrieve data
5858
// Note that these are saved by the BentoBox database
5959
handler = new Database<>(addon, IslandLevels.class);
60+
6061
// Initialize the cache
6162
levelsCache = new HashMap<>();
6263
// Initialize top ten lists
@@ -237,7 +238,6 @@ private long getNumBlocks(final long initialLevel) throws ParseException, IOExce
237238
*
238239
* @param world - world where the island is
239240
* @param targetPlayer - target player UUID
240-
* @param ownerOnly - return level only if the target player is the owner
241241
* @return Level of the player's island or zero if player is unknown or UUID is
242242
* null
243243
*/
@@ -492,7 +492,6 @@ public void setInitialIslandCount(@NonNull Island island, long lv) {
492492
* member
493493
*
494494
* @param world - world
495-
* @param island - island
496495
* @param lv - level
497496
*/
498497
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) {

0 commit comments

Comments
 (0)