Skip to content

Commit 0c8860f

Browse files
authored
Merge pull request #394 from BentoBoxWorld/develop
Release 1.6.0
2 parents d51ef11 + c274e0e commit 0c8860f

93 files changed

Lines changed: 16660 additions & 11388 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: Publish to Modrinth
2+
3+
# Triggers when you publish a GitHub Release
4+
on:
5+
release:
6+
types: [published]
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: 'Release tag to publish (e.g. 1.6.0)'
11+
required: true
12+
type: string
13+
14+
jobs:
15+
publish:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
20+
steps:
21+
# 1. Check out the repository at the release tag
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
# 2. Set up Java 21
26+
- name: Set up Java 21
27+
uses: actions/setup-java@v4
28+
with:
29+
java-version: '21'
30+
distribution: 'temurin'
31+
32+
# 3. Cache Maven dependencies to speed up builds
33+
- name: Cache Maven packages
34+
uses: actions/cache@v4
35+
with:
36+
path: ~/.m2
37+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
38+
restore-keys: ${{ runner.os }}-m2
39+
40+
# 4. Build the JAR
41+
# GIT_BRANCH=origin/master activates the Maven 'master' profile which
42+
# produces a clean version number (e.g. 1.6.0) without -SNAPSHOT/-LOCAL.
43+
- name: Build with Maven
44+
run: mvn -B clean package -DskipTests
45+
env:
46+
GIT_BRANCH: origin/master
47+
48+
# 5. Upload the JAR to Modrinth
49+
#
50+
# Prerequisites — add these secrets in your GitHub repo settings
51+
# (Settings → Secrets and variables → Actions):
52+
#
53+
# MODRINTH_TOKEN — personal access token from https://modrinth.com/settings/pats
54+
# (scope: "Create versions")
55+
# MODRINTH_PROJECT_ID — your Modrinth project ID for Challenges, visible on the
56+
# project page under the three-dot menu ("Copy ID")
57+
#
58+
- name: Publish to Modrinth
59+
uses: cloudnode-pro/modrinth-publish@0be4916ad5f081d936eb5615aa35ce3f0949979c # v2
60+
with:
61+
token: ${{ secrets.MODRINTH_TOKEN }}
62+
project: ${{ secrets.MODRINTH_PROJECT_ID }}
63+
64+
# Use the release tag, or the manually supplied tag when triggered via workflow_dispatch
65+
version: ${{ github.event.release.tag_name || inputs.tag }}
66+
67+
# Use the GitHub release body as the changelog (empty when run manually)
68+
changelog: ${{ github.event.release.body }}
69+
70+
# Challenges is a BentoBox addon running on Paper-based servers
71+
loaders: |-
72+
paper
73+
purpur
74+
75+
# Minecraft versions supported (BentoBox API 3.12.0 targets Paper 1.21.11+)
76+
game-versions: |-
77+
1.21.5
78+
1.21.6
79+
1.21.7
80+
1.21.8
81+
1.21.9
82+
1.21.10
83+
1.21.11
84+
26.1
85+
26.1.1
86+
87+
# Path to the built JAR
88+
files: target/Challenges-${{ github.event.release.tag_name || inputs.tag }}.jar

CLAUDE.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
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
6+
7+
Challenges is a BentoBox addon (Bukkit/Spigot plugin module) that adds player challenges to any BentoBox GameMode addon (BSkyBlock, AcidIsland, SkyGrid, CaveBlock). It is not a standalone plugin — it is loaded by BentoBox at runtime.
8+
9+
- Java 21, Maven, Spigot `1.21.3-R0.1-SNAPSHOT`
10+
- Depends on BentoBox `3.4.0`, optionally Level `2.6.3` and Vault `1.7`
11+
- Version is set via `<build.version>` in `pom.xml` (uses `${revision}` / CI `-bNNN` suffix)
12+
13+
## Commands
14+
15+
```bash
16+
# Full build + tests + shaded jar (output in target/)
17+
mvn clean verify
18+
19+
# Compile only
20+
mvn compile
21+
22+
# Run all tests
23+
mvn test
24+
25+
# Run a single test class
26+
mvn test -Dtest=ChallengesManagerTest
27+
28+
# Run a single test method
29+
mvn test -Dtest=ChallengesManagerTest#methodName
30+
31+
# Release build (strips -SNAPSHOT) — set via profile, normally CI only
32+
mvn clean verify -Dbuild.number=-bLOCAL
33+
```
34+
35+
Built jar lands in `target/` and must be dropped into `BentoBox/addons/` on a running BentoBox server to test manually.
36+
37+
## Architecture
38+
39+
Entry point: `ChallengesAddon` (extends BentoBox `Addon`). `ChallengesPladdon` is the Paper-plugin wrapper used when BentoBox is loaded as a Paper plugin. `onLoad` reads `config.yml` into `Settings`, `onEnable` registers commands against each hooked `GameModeAddon`, instantiates managers, registers flags, and wires listeners.
40+
41+
Key subsystems:
42+
43+
- **`managers/ChallengesManager`** — central service. Owns in-memory caches of `Challenge`, `ChallengeLevel`, and per-player `ChallengesPlayerData`, plus the BentoBox `Database` handles that persist them. All mutation of challenges/levels/player progress should go through this manager so caches and DB stay consistent. Challenges and levels are keyed by a unique ID that is prefixed by the gamemode (e.g. `bskyblock_mychallenge`) — see `getUniqueID` / `addChallengeToLevel` for the prefixing contract.
44+
- **`managers/ChallengesImportManager`** — imports/exports challenges from `default.json`, template YAML, and library downloads via `web/WebManager` (the "Web Library" in the GUI).
45+
- **`database/object/`** — Gson-serialized data objects (`Challenge`, `ChallengeLevel`, `ChallengesPlayerData`). `requirements/` holds the polymorphic `Requirement` hierarchy (Island, Inventory, Other, Statistic) used to gate completion; `adapters/` contains Gson type adapters that make the polymorphism work — new requirement types must be registered there.
46+
- **`panel/`** — all GUI code, built on `bentobox-panelutils`. `CommonPanel`/`CommonPagedPanel` are the base classes; `admin/` contains the admin editor GUIs, `user/` the player-facing GUIs. Conversations (text input prompts) go through `ConversationUtils`.
47+
- **`commands/`** — player commands (`ChallengesPlayerCommand`, `ChallengesGlobalPlayerCommand`, `CompleteChallengeCommand`) and `commands/admin/` admin commands. Each is registered per gamemode in `ChallengesAddon.onEnable`.
48+
- **`handlers/`** — BentoBox API request handlers (`ChallengeDataRequestHandler`, `LevelListRequestHandler`, etc.) exposed over the BentoBox inter-addon request API so other addons can query challenge data.
49+
- **`listeners/`**`ResetListener` wipes player data on island reset; `SaveListener` flushes caches on save/quit.
50+
- **`tasks/`**`TryToComplete` is the core completion pipeline: validates requirements, consumes costs, applies rewards, fires events. New reward/requirement logic typically plugs in here.
51+
- **`events/`** — custom Bukkit events (`ChallengeCompletedEvent`, `LevelCompletedEvent`, etc.) fired by `TryToComplete`/managers. Extend the existing event hierarchy rather than adding ad-hoc callbacks.
52+
- **`web/WebManager`** — downloads the public challenges library via BentoBox's `WebManager`/GitHub content.
53+
54+
Resources in `src/main/resources/`: `addon.yml` (addon metadata read by BentoBox), `config.yml` (user settings → `config/Settings`), `default.json` (bundled default challenges), `template.yml`, `panels/*.yml` (GUI layouts loaded by panelutils), `locales/*.yml` (translations — managed via GitLocalize, do not hand-edit beyond `en-US.yml`).
55+
56+
## Conventions
57+
58+
- Target branch for PRs is `master`; active development happens on `develop`.
59+
- When adding a new `Requirement` subclass, also register its Gson adapter in `database/object/adapters/` or loading will fail silently with missing fields.
60+
- Challenge/level IDs are always gamemode-prefixed on disk; when comparing or looking up, use `ChallengesManager` helpers rather than raw string compares.
61+
- User-visible strings belong in `locales/en-US.yml` under the appropriate namespace — never hardcode them in Java.
62+
63+
## Dependency Source Lookup
64+
65+
When you need to inspect source code for a dependency (e.g., BentoBox, addons):
66+
67+
1. **Check local Maven repo first**: `~/.m2/repository/` — sources jars are named `*-sources.jar`
68+
2. **Check the workspace**: Look for sibling directories or Git submodules that may contain the dependency as a local project (e.g., `../bentoBox`, `../addon-*`)
69+
3. **Check Maven local cache for already-extracted sources** before downloading anything
70+
4. Only download a jar or fetch from the internet if the above steps yield nothing useful
71+
72+
Prefer reading `.java` source files directly from a local Git clone over decompiling or extracting a jar.
73+
74+
In general, the latest version of BentoBox should be targeted.
75+
76+
## Project Layout
77+
78+
Related projects are checked out as siblings under `~/git/`:
79+
80+
**Core:**
81+
- `bentobox/` — core BentoBox framework
82+
83+
**Game modes:**
84+
- `addon-acidisland/` — AcidIsland game mode
85+
- `addon-bskyblock/` — BSkyBlock game mode
86+
- `Boxed/` — Boxed game mode (expandable box area)
87+
- `CaveBlock/` — CaveBlock game mode
88+
- `OneBlock/` — AOneBlock game mode
89+
- `SkyGrid/` — SkyGrid game mode
90+
- `RaftMode/` — Raft survival game mode
91+
- `StrangerRealms/` — StrangerRealms game mode
92+
- `Brix/` — plot game mode
93+
- `parkour/` — Parkour game mode
94+
- `poseidon/` — Poseidon game mode
95+
- `gg/` — gg game mode
96+
97+
**Addons:**
98+
- `addon-level/` — island level calculation
99+
- `addon-challenges/` — challenges system
100+
- `addon-welcomewarpsigns/` — warp signs
101+
- `addon-limits/` — block/entity limits
102+
- `addon-invSwitcher/` / `invSwitcher/` — inventory switcher
103+
- `addon-biomes/` / `Biomes/` — biomes management
104+
- `Bank/` — island bank
105+
- `Border/` — world border for islands
106+
- `Chat/` — island chat
107+
- `CheckMeOut/` — island submission/voting
108+
- `ControlPanel/` — game mode control panel
109+
- `Converter/` — ASkyBlock to BSkyBlock converter
110+
- `DimensionalTrees/` — dimension-specific trees
111+
- `discordwebhook/` — Discord integration
112+
- `Downloads/` — BentoBox downloads site
113+
- `DragonFights/` — per-island ender dragon fights
114+
- `ExtraMobs/` — additional mob spawning rules
115+
- `FarmersDance/` — twerking crop growth
116+
- `GravityFlux/` — gravity addon
117+
- `Greenhouses-addon/` — greenhouse biomes
118+
- `IslandFly/` — island flight permission
119+
- `IslandRankup/` — island rankup system
120+
- `Likes/` — island likes/dislikes
121+
- `Limits/` — block/entity limits
122+
- `lost-sheep/` — lost sheep adventure
123+
- `MagicCobblestoneGenerator/` — custom cobblestone generator
124+
- `PortalStart/` — portal-based island start
125+
- `pp/` — pp addon
126+
- `Regionerator/` — region management
127+
- `Residence/` — residence addon
128+
- `TopBlock/` — top ten for OneBlock
129+
- `TwerkingForTrees/` — twerking tree growth
130+
- `Upgrades/` — island upgrades (Vault)
131+
- `Visit/` — island visiting
132+
- `weblink/` — web link addon
133+
- `CrowdBound/` — CrowdBound addon
134+
135+
**Data packs:**
136+
- `BoxedDataPack/` — advancement datapack for Boxed
137+
138+
**Documentation & tools:**
139+
- `docs/` — main documentation site
140+
- `docs-chinese/` — Chinese documentation
141+
- `docs-french/` — French documentation
142+
- `BentoBoxWorld.github.io/` — GitHub Pages site
143+
- `website/` — website
144+
- `translation-tool/` — translation tool
145+
146+
Check these for source before any network fetch.
147+
148+
## Testing
149+
150+
The project uses a mixed test stack:
151+
152+
- **JUnit 4 + PowerMock** — existing tests in `commands/`, `tasks/`, `utils/`, `database/`, and top-level addon/manager tests. These use `@RunWith(PowerMockRunner.class)` and `@PrepareForTest`.
153+
- **JUnit 5 + Mockito** — newer tests in `panel/` package. These use `@ExtendWith(MockitoExtension.class)` with `@MockitoSettings(strictness = Strictness.LENIENT)`.
154+
- Both frameworks coexist via `junit-vintage-engine` which runs JUnit 4 tests on the JUnit 5 platform.
155+
156+
### Writing new JUnit 5 tests alongside PowerMock
157+
158+
PowerMock's MockMaker conflicts with mockito-inline, so **`mockStatic()` and `mockConstruction()` are not available** in JUnit 5 tests. Use these workarounds:
159+
160+
- **Static singletons** (`Bukkit.getServer()`, `BentoBox.getInstance()`): Set via reflection on the private static field. See `PanelTestHelper.setServer()` and `setBentoBoxInstance()` for examples. Always save/restore the previous value in `@BeforeEach`/`@AfterEach`.
161+
- **Final methods** (`JavaPlugin.getServer()` is final): Set the `server` field on the plugin object via reflection walking the class hierarchy. See `PanelTestHelper.setPluginServer()`.
162+
- **Java records** (`ItemTemplateRecord`, `TemplatedPanel.ItemSlot`): Cannot be mocked. Create real instances using their public constructors. For `TemplatedPanel` (which has no public constructor), use `sun.misc.Unsafe.allocateInstance()` then set fields via reflection. See `PanelTestHelper.createItemSlot()`.
163+
- **Varargs methods** (`User.getTranslation(String, String...)`): Use `Mockito.doAnswer().when()` with `Mockito.<String>any()` instead of `when().thenAnswer()`. The `doAnswer` pattern handles varargs correctly. See `PanelTestHelper.setupUserTranslations()`.
164+
165+
### PanelTestHelper
166+
167+
`src/test/java/world/bentobox/challenges/panel/PanelTestHelper.java` is a shared utility for all panel tests. It provides:
168+
- Reflection helpers for Bukkit/BentoBox static fields
169+
- `ItemTemplateRecord` factory methods (`createTemplate`, `createSimpleTemplate`, `createEmptyTemplate`)
170+
- `createItemSlot()` for `TemplatedPanel.ItemSlot` records
171+
- `createBasicChallenge()` for fully-mocked `Challenge` objects
172+
- `setupUserTranslations()` for varargs-safe translation mocking
173+
174+
## Key Dependencies (source locations)
175+
176+
- `world.bentobox:bentobox``~/git/bentobox/src/`

0 commit comments

Comments
 (0)