Skip to content

New Release#164

Open
tastybento wants to merge 34 commits into
masterfrom
develop
Open

New Release#164
tastybento wants to merge 34 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybento and others added 30 commits July 3, 2026 18:23
Add StoneGeneratorPladdon loader, config/ and utils/ packages, and
GeneratorExhaustionData to the docs; clarify the 3 @table objects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
The existing GeneratorBuyEvent fires after a purchase completes, so it
cannot be used to veto a purchase. Add a new cancellable
GeneratorPreBuyEvent fired at the start of
StoneGeneratorManager.purchaseGenerator, before any money is withdrawn
and before GeneratorBuyEvent is fired. Cancelling it aborts the purchase.

This lets other plugins add their own requirements to the generator
purchasing process.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Unlocked generator tiers were a permanent grant that was never revoked
when an island's owner changed. If a player with a generator permission
created an island, unlocked a permission-gated tier, then left and handed
ownership to a player without that permission, the tier stayed unlocked
and usable.

checkGeneratorUnlockStatus now revokes permission-gated tiers from the
island's unlocked and active lists when the current (online) owner does
not hold the required permissions. This runs on the existing
TeamSetownerEvent -> validateIslandData -> checkGeneratorUnlockStatus
path, so it fires on ownership transfer. Purchase records are preserved,
so a generator becomes available again if the permission is regained.
Nothing is revoked while the owner is offline, since permissions cannot
be checked reliably then.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Generator lists were sorted by default-flag, priority, type and finally
by friendly name. The friendly-name tiebreaker meant renaming a generator
moved it in the player GUI, which was confusing.

Use the stable unique id as the final tiebreaker instead, in both
getAllGeneratorTiers (drives the player list) and the bundle edit panel.
The existing per-generator priority field already lets admins order
generators explicitly (e.g. 10/20/30/40); this makes ordering within an
equal priority stable and rename-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Players could accidentally buy a generator with a single click. Add a
buy-confirmation config option (default true) that asks the player to
confirm in chat before the purchase is made.

The three BUY click handlers in the player panels now delegate to a new
shared CommonPanel.purchaseGenerator helper, which:
- refreshes the panel and bails out if the generator cannot be purchased
  (the reason is already messaged by canPurchaseGenerator),
- purchases directly when confirmation is disabled,
- otherwise requests a chat confirmation and only purchases on confirm.

Adds the buy-confirmation setting, a confirm-generator-purchase locale
string, and tests for the helper and the setting default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
SonarCloud flagged the new GeneratorPreBuyEvent as duplicated code: it
repeated the targetPlayer/islandUUID/generator/generatorID fields and
accessors that GeneratorBuyEvent, GeneratorActivationEvent and
GeneratorUnlockEvent already duplicated among themselves.

Introduce an abstract GeneratorEvent base holding those common fields and
their getters/setters, and have all four events extend it. The change is
backwards compatible: the public accessors are simply inherited, so
external listeners are unaffected. Each concrete event keeps its own
HandlerList, as Bukkit requires for correct per-type routing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Generators produce blocks from a BlockFormEvent (lava/water flow) rather
than a player mining a block, so Bukkit's BlockDropItemEvent - which
requires a Player and a broken BlockState - does not fit. Instead add a
dedicated cancellable GeneratorTreasureDropEvent, fired in
MagicGenerator just before a treasure is dropped.

Listeners can cancel the event to veto the drop, or replace the
ItemStack / drop location to modify it. A backwards-compatible
processBlockReplacement overload threads the island through for event
context; the existing two-argument method delegates with a null island.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Now that the shared GeneratorEvent base exists on develop (#137), make
GeneratorTreasureDropEvent extend it to drop the duplicated
generator/generatorID/islandUUID fields and accessors. Treasure drops
have no associated player, so null is passed for the user. The
location and itemStack remain event-specific.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add cancellable GeneratorTreasureDropEvent for treasure drops (#140)
Revoke permission-gated generators when island owner loses permission (#133)
Add optional purchase confirmation before buying a generator (#109)
Generators can now require other generator tiers to be unlocked before
they become available, enabling progression chains (e.g. Gen1 before
Gen2).

- GeneratorTierObject gains a requiredGeneratorTiers set (unique ids),
  persisted via @expose and copied in clone().
- checkGeneratorUnlockStatus only unlocks a generator once all of its
  required tiers are already unlocked. Tiers are streamed in priority
  order, so a lower-priority prerequisite is unlocked earlier in the same
  pass.
- The requirements description shows a "Required Generators" section for
  locked generators, with new en-US locale strings.

Configurable via generator export/import for now; an admin GUI selector
can follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add a MultiGeneratorSelector (mirroring MultiBiomeSelector) and a
REQUIRED_GENERATORS button in the generator edit panel so admins can pick
prerequisite generators from a GUI. Shift-click resets the list. New
en-US locale strings for the button, the selector title and its accept
button.

Also add GeneratorTierObjectTest covering the new requiredGeneratorTiers
field default, accessors and clone copy, addressing the SonarCloud
new-code coverage note on the data model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
- Requirements lore and the edit-panel button now fall back to showing
  the raw generator id when a prerequisite id cannot be resolved
  (deleted/renamed), instead of silently dropping it, so a locked
  generator always shows what is blocking it.
- MultiGeneratorSelector now filters to deployed generators only, since
  non-deployed tiers can never be unlocked and would permanently lock
  their dependents; this matches its documented behaviour.
- Fix the misleading @param consumer Javadoc (null is passed as the
  value on cancel; the consumer itself is never null).
- Drop the now-unused Objects import in GeneratorEditPanel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
SonarCloud:
- GeneratorEditPanel: extract duplicated "shift-click-to-reset" tip and
  ".list" suffix literals into constants (S1192).
- MultiGeneratorSelector: use Stream.toList() instead of
  collect(Collectors.toList()) (S6204) and replace the two-branch switch
  with an if/else (S1301); drop the now-unused Collectors import.

Review:
- GeneratorTierObject.requiredGeneratorTiers is now null-safe: the setter
  normalizes null to an empty set, the getter lazily initialises a null
  field (guards deserialized JSON), and clone() goes through the getter,
  so clone()/containsAll()/isEmpty() can no longer NPE.
- MultiGeneratorSelector now also shows generators that are already
  selected even if they would otherwise be filtered out (undeployed or
  default), so existing selections remain visible and deselectable
  instead of being hidden yet persisted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Generators can now be flagged to activate automatically as soon as they
are unlocked, making it easy to manage progressive generator tiers via
bundles without relying on default generators.

- GeneratorTierObject gains an activateOnUnlock boolean (@expose, cloned).
- unlockGenerator auto-activates the generator when the flag is set,
  via a new userless autoActivateGenerator helper that respects the
  active-generator limit and the overwrite-on-active setting, fires the
  GeneratorActivationEvent, and skips the (now irrelevant)
  click-to-activate notification.
- Generator edit panel gains an ACTIVATE_ON_UNLOCK toggle button, with
  new en-US locale strings.

Auto-activation bypasses activation/purchase cost, as it is a
configuration-driven automatic action.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
autoActivateGenerator now:
- Returns whether it actually activated. unlockGenerator only skips the
  click-to-activate notification when activation succeeded, so a tier
  that stays unlocked-but-inactive (active limit reached without
  overwrite, or activation event cancelled) still notifies the player.
- Fires the cancellable activation event *before* mutating the active
  list, so a cancelled activation no longer loses an already active
  generator when overwrite-on-active is enabled.
- Frees a slot via deactivateGenerator (firing the deactivation event)
  when a user is present, instead of silently removing the old
  generator; aborts if the deactivation is cancelled.
- Sends the "generator disabled" hint when the addon is not allowed on
  the island, matching manual activation.

Adds a regression test that a cancelled activation event preserves the
existing active generator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add activate-on-unlock option for generators (#106)
Adds "/{admin} generator reset <player>", a confirmable admin subcommand
that resets a single island's generator data (unlocked, purchased and
active generators) without touching the rest of the database.

- StoneGeneratorManager.resetIslandData wipes the island's stored data
  and recreates a fresh default data object so the island keeps working.
- New ResetCommand subcommand (permission admin.stone-generator.reset)
  with player tab-completion and a confirmation prompt.
- New en-US locale strings for the command and the success message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
SonarCloud flagged the new ResetCommand as duplicating GeneratorWhyCommand
(identical player tab-completion and target-resolution). Extract two shared
static helpers in GeneratorAdminCommand - playerTabComplete and
resolveTargetUUID - and use them from both subcommands, removing the
duplicated block.

Review feedback:
- resetIslandData now recreates the data object via addIslandData, which
  works even for ownerless islands (e.g. spawn), where validateIslandData
  returns early; validateIslandData is still called for owned islands. This
  ensures reset never deletes data without recreating it.
- The reset command falls back to the typed argument for the player name
  when the server cannot resolve a name for the UUID, so confirmation and
  success messages are never blank.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
The static helpers only removed part of the duplication SonarCloud
flagged between ResetCommand and GeneratorWhyCommand; the identical
execute preamble (arg check + UUID resolution) and tab-completion
remained.

Introduce an abstract PlayerTargetCommand base (extends
ConfirmableCommand) that handles argument validation, target-UUID
resolution and player tab-completion, and delegates to an abstract
executeForTarget(user, name, uuid). GeneratorWhyCommand and ResetCommand
now extend it and only implement setup() and their own executeForTarget,
removing the duplicated block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
The remaining SonarCloud duplication was the structurally identical
constructor + setup() shared by GeneratorWhyCommand and ResetCommand
(Sonar normalizes the differing string literals).

Implement setup() once in the PlayerTargetCommand base, deriving the
permission and locale keys from the subcommand label, and remove the
per-command setup() overrides. The subcommands now only provide a
constructor and their own executeForTarget.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add admin command to reset a player's generator data (#149)
Adds a lose-tiers-on-level-loss config option (default false). When
enabled, generators that were unlocked purely by reaching an island
level are locked again if the island level later drops below their
required level.

- Settings.loseTiersOnLevelLoss (lose-tiers-on-level-loss, default false).
- checkGeneratorUnlockStatus now calls revokeLevelLockedGenerators, which
  removes level-gated tiers from the unlocked and active lists when the
  island level is below their requirement. Runs on the existing
  IslandLevelCalculatedEvent -> checkGeneratorUnlockStatus path.
- Purchased tiers are always kept, so players never lose generators they
  actually paid for.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add option to lose level-gated tiers when island level drops (#118)
Generators can now require an AOneBlock phase to be reached before they
unlock, enabling OneBlock progression-gated generators.

- Adds aoneblock as a provided-scope dependency (mirrors level/bank).
- GeneratorTierObject.requiredPhase (String, @expose, cloned, empty by
  default; null-normalised).
- checkGeneratorUnlockStatus only unlocks a phase-gated generator once
  the island's block count has reached the required phase's starting
  block, via AOneBlock's getOneBlockManager().getPhase(name) and
  getOneBlocksIsland(island).getBlockNumber(). Non-AOneBlock worlds never
  satisfy a phase requirement.
- Requirements lore shows a "Required Phase" line ([phase]) with new
  en-US locale strings.

Configurable via generator export/import for now; an admin GUI editor can
follow (the edit panel is currently full).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
tastybento and others added 4 commits July 4, 2026 19:01
…ment

Add AOneBlock phase requirement for generators (#121)
Completes the OneBlock progression unlocking from #117 (the phase part is
handled by #121): a generator can now require a number of OneBlock blocks
to have been broken on the island before it unlocks - a level-free way to
gate generators behind digging progress.

- GeneratorTierObject.requiredBlockCount (int, @expose, cloned, 0 = none).
- checkGeneratorUnlockStatus only unlocks such a generator once the
  island's OneBlock block count (getOneBlocksIsland(island).getBlockNumber,
  same value as /ob count) has reached the requirement. Non-AOneBlock
  worlds never satisfy it. Shares a getAOneBlock helper with the phase
  check.
- Requirements lore shows a "Required Blocks Broken" line ([block-count])
  with new en-US locale strings.

Configurable via generator export/import for now; admin GUI editor to
follow (edit panel is full).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7NWPeGXmsUJnnX42X24Rd
Add OneBlock block-count requirement for generators (#117)
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps the addon version and introduces several new generator-related capabilities: richer event hooks (treasure drops + pre-buy), new unlock/visibility requirements (prerequisite generators, AOneBlock phase/block-count gating), optional auto-activation on unlock, a purchase confirmation flow in panels, and an admin “reset player generator data” command.

Changes:

  • Add cancellable events: GeneratorTreasureDropEvent (treasure interception) and GeneratorPreBuyEvent (pre-purchase veto), and refactor existing generator events to share a common base.
  • Extend generator tier requirements (required generators, AOneBlock phase, block count) + optional auto-activate-on-unlock, with corresponding panel UI and unlock logic.
  • Add buy-confirmation chat flow for panel purchases and introduce an admin reset subcommand, plus extensive new tests and locale strings.

Reviewed changes

Copilot reviewed 28 out of 29 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/main/java/world/bentobox/magiccobblestonegenerator/tasks/MagicGenerator.java Fires treasure-drop event and uses it to allow cancellation/modification of treasure drops.
src/main/java/world/bentobox/magiccobblestonegenerator/listeners/GeneratorListener.java Passes island context into block replacement for better event context.
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorTreasureDropEvent.java New cancellable event for treasure drops with mutable drop item/location.
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorPreBuyEvent.java New cancellable pre-purchase event to allow external requirements/veto.
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorEvent.java New shared base for generator events (common fields + accessors).
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorActivationEvent.java Refactored to extend GeneratorEvent.
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorBuyEvent.java Refactored to extend GeneratorEvent.
src/main/java/world/bentobox/magiccobblestonegenerator/events/GeneratorUnlockEvent.java Refactored to extend GeneratorEvent and clarify semantics.
src/main/java/world/bentobox/magiccobblestonegenerator/managers/StoneGeneratorManager.java Adds prerequisite/phase/block-count gating, revocation logic, auto-activation, pre-buy event, and island data reset.
src/main/java/world/bentobox/magiccobblestonegenerator/database/objects/GeneratorTierObject.java Adds new tier requirement fields + activate-on-unlock flag and clones them correctly.
src/main/java/world/bentobox/magiccobblestonegenerator/config/Settings.java Adds buy-confirmation and lose-tiers-on-level-loss configuration options.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/CommonPanel.java Centralizes purchase flow and adds optional chat confirmation.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/player/GeneratorViewPanel.java Routes BUY action through the shared confirmed purchase helper.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/player/GeneratorUserPanel.java Routes BUY action through the shared confirmed purchase helper.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/admin/GeneratorEditPanel.java Adds UI for prerequisite generators + activate-on-unlock toggle.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/admin/BundleEditPanel.java Makes generator ordering stable by unique id to avoid rename reorder.
src/main/java/world/bentobox/magiccobblestonegenerator/panels/utils/MultiGeneratorSelector.java New multi-select UI for prerequisite generator selection.
src/main/java/world/bentobox/magiccobblestonegenerator/commands/admin/GeneratorAdminCommand.java Adds player-target base command + new reset subcommand with confirmation.
src/main/resources/locales/en-US.yml Adds/updates messages for new UI, requirements, confirmations, and reset flow.
pom.xml Bumps build version and adds provided aoneblock dependency.
CLAUDE.md Updates contributor documentation and package map.
src/test/java/world/bentobox/magiccobblestonegenerator/tasks/MagicGeneratorTest.java New tests for treasure-drop event behavior (cancel/replace/drop).
src/test/java/world/bentobox/magiccobblestonegenerator/panels/CommonPanelPurchaseTest.java New tests for buy-confirmation purchase flow.
src/test/java/world/bentobox/magiccobblestonegenerator/managers/StoneGeneratorManagerTest.java Adds tests for ordering, gating, revocation, auto-activation, pre-buy event, reset.
src/test/java/world/bentobox/magiccobblestonegenerator/events/GeneratorTreasureDropEventTest.java New unit tests for the new treasure drop event.
src/test/java/world/bentobox/magiccobblestonegenerator/events/GeneratorPreBuyEventTest.java New unit tests for the new pre-buy event.
src/test/java/world/bentobox/magiccobblestonegenerator/database/objects/GeneratorTierObjectTest.java New unit tests for new tier fields (required gens/phase/blockcount/activate).
src/test/java/world/bentobox/magiccobblestonegenerator/commands/admin/GeneratorAdminCommandTest.java Updates tests to cover new reset admin command/help output.
.idea/modules.xml Adds IntelliJ module metadata (likely unintended to commit).
Files not reviewed (1)
  • .idea/modules.xml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +150 to +163
if (!treasureEvent.isCancelled() && treasureEvent.getItemStack() != null)
{
ItemStack finalDrop = treasureEvent.getItemStack();
Location dropLocation = treasureEvent.getLocation();

Why.report(location, "Dropping treasure " + finalDrop + " by " + generatorTier.getUniqueId());

// drop item naturally in the location of the block
dropLocation.getWorld().dropItemNaturally(dropLocation, finalDrop);
}
else
{
Why.report(location, "Treasure drop cancelled by " + generatorTier.getUniqueId());
}
Comment on lines +31 to +42
* @param generator the generator
* @param user the user, or null if there is no associated user
* @param islandUUID the island unique id
*/
protected GeneratorEvent(GeneratorTierObject generator, @Nullable User user, String islandUUID)
{
this.generator = generator.getFriendlyName();
this.generatorID = generator.getUniqueId();

this.targetPlayer = user == null ? null : user.getUniqueId();
this.islandUUID = islandUUID;
}
Comment on lines +45 to +53
/**
* Gets target player.
*
* @return the target player
*/
public UUID getTargetPlayer()
{
return targetPlayer;
}
Comment on lines +67 to +75
/**
* Gets island uuid.
*
* @return the island uuid
*/
public String getIslandUUID()
{
return islandUUID;
}
Comment on lines +98 to +101
this.filterElements = this.elements.stream().
filter(element -> element.getFriendlyName().toLowerCase().contains(this.searchString.toLowerCase())).
distinct().
toList();
Comment thread .idea/modules.xml
Comment on lines +1 to +8
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/magiccobblestonegenerator.iml" filepath="$PROJECT_DIR$/magiccobblestonegenerator.iml" />
</modules>
</component>
</project> No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants