Skip to content

feat: Fishing System v2#6

Merged
MrInspection merged 4 commits into
masterfrom
feat/fishing-system
Nov 11, 2025
Merged

feat: Fishing System v2#6
MrInspection merged 4 commits into
masterfrom
feat/fishing-system

Conversation

@MrInspection

@MrInspection MrInspection commented Nov 11, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

Release Notes

  • New Features

    • Redesigned fishing system with environment-specific loot tables for enhanced variety
    • Added new custom entity to the game
  • Bug Fixes

    • Admin commands now properly enforce permission checks to prevent unauthorized access
    • Fixed entity health synchronization for attachments
    • Improved spawn condition logic for sky-exposed detection
    • Enhanced error messaging for entity spawning failures
  • Changes

    • Currency system renamed from Favors to Gems throughout gameplay
    • Teleport commands restructured with improved argument validation and error handling

@coderabbitai

coderabbitai Bot commented Nov 11, 2025

Copy link
Copy Markdown

Walkthrough

The PR introduces permission enforcement guards in admin commands, systematically renames the currency system from "favors" to "gems" across multiple components, completely refactors the fishing loot system from an interface-based design to a concrete builder pattern, adds the Dummy entity, and makes various refinements to entity handling, data persistence, and utility classes.

Changes

Cohort / File(s) Summary
Admin Command Permission Enforcement
BroadcastCommand.java, FlyCommand.java, ForceCommand.java, GemsCommand.java, GiveItemCommand.java, GodCommand.java, KaboomCommand.java, LoopCommand.java, SpawnCustomMobCommand.java
Added early-return guards to enforce admin permissions; commands now abort if enforceAdminPermission(player) returns false, preventing execution for unauthorized players.
TeleportCommands Refactoring
TeleportCommands.java
Rewrote command dispatch from nested if-statements to a switch-case pattern; added per-case admin permission enforcement, argument validation, self-teleport prevention, and improved error handling for tp, tphere, tpall, and tppos subcommands.
Currency Rename (Favors → Gems)
GemsCommand.java, GemsItem.java, GemsLoot.java, BlightedPlayer.java, PlayerData.java, PlayerDataHandler.java
Renamed currency system from "favors" to "gems"; updated method names, parameter names, user-facing messages, persistent data keys, and loot transfer logic throughout.
Fishing System Refactoring (Core)
FishingListener.java
Replaced vanilla loot logic with environment-aware custom loot flow; introduced random loot selection, world-environment-based loot table selection, and integration with new builder-based FishingLootTable.
Fishing System Refactoring (Old Structure - Removed)
FishingSystem.java, LootTable/FishingLootTable.java, LootTable/LootCondition.java, LootTable/LootContext.java, LootTable/LootEntry.java, LootTable/LootPool.java, LootTable/pools/EndFishingPool.java, LootTable/pools/OverworldFishingPool.java
Removed interface-based and concrete implementations of fishing loot system (old package structure).
Fishing System Refactoring (New Structure - Added)
FishingLootTable.java, loot/LootCondition.java, loot/LootContext.java, loot/LootEntry.java, loot/LootPool.java, environment/EndFishing.java, environment/OverworldFishing.java, package-info.java
Introduced new concrete FishingLootTable class with builder pattern, moved loot utilities to new package structure, added environment-specific fishing configurations (End and Overworld), and documented the fishing package.
Entity System Refinements
BlightedEntitiesListener.java, EntitiesRegistry.java, Dummy.java, SpawnConditions.java
Enhanced entity listener with ThreadLocal cleanup and health synchronization fixes; registered new Dummy entity; adjusted spawn condition for sky exposure; introduced new Dummy entity with Drowned-type configuration and Turtle mounting.
Entity Profile Enhancements
SpawnableEntityProfile.java
Added input validation (@Positive weight, min/max group size validation), new public getters (getWeight, getMinGroup, getMaxGroup, getSpawnChance), and corrected exception message.
Item & Registry System
ItemTemplate.java, ItemDirectory.java, ItemDirectoryMenu.java
Removed example usage of .addToRegistry() from Javadoc; added registry pre-clearing in initialization; introduced null-safe search predicate for display name matching.
Ability System
BonemerangAbility.java, RocketBootsAbility.java
Changed cooldown storage from WeakHashMap to ConcurrentHashMap for thread safety; refactored boot durability damage application to internalize damage calculation and incorporate Unbreaking enchantment logic.
Utilities & Configuration
CommandInfo.java, Formatter.java, SoundSequence.java, .idea/artifacts/blightedmc_jar.xml
Added precondition checks in command usage validation; improved formatting logic (null-safe enum formatting, integer-valued double handling, spacing consistency); replaced explicit imports with wildcards; changed list storage from unmodifiable to immutable copy; updated IDE artifact configuration (name and output path).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–75 minutes

Areas requiring extra attention:

  • FishingListener.java and new loot system: Significant architectural refactoring from interface-based design to builder pattern; verify correct loot table selection logic, entity spawning, and item creation paths across environments.
  • TeleportCommands.java: Major control flow rewrite; ensure all subcommands (tp, tphere, tpall, tppos) are correctly handled, arguments validated, and error messages properly displayed.
  • RocketBootsAbility.java: Durability damage logic now includes Unbreaking enchantment handling; verify probabilistic reduction is correct and boot breakage is properly triggered.
  • SpawnableEntityProfile.java: New validations and getters added; confirm @Positive constraint and min/max group size validation work as intended.
  • Currency rename propagation: Verify all "favors" → "gems" renames are consistent, including persistent data keys, method names, and user-facing messages.

Possibly related PRs

  • feat/game-content-part-1 #1: Overlapping changes to entity handling, BlightedEntitiesListener, EntitiesRegistry, and fishing loot systems.
  • feat: core-enhancements #3: Directly related large refactoring of fishing/loot subsystem and registries; shares many class additions/removals (FishingLootTable, LootPool, LootEntry, LootCondition, LootContext).

Suggested labels

enhancement, area: core

Poem

🐰 Hopping through the code with careful paws,
From favors turned to gems—a currency clause,
Fishing loot rebuilt with builders so bright,
Permissions now guarded, commands held tight,
A Dummy awaits where waters run deep!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.74% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: Fishing System v2' directly and clearly summarizes the main objective: a new version of the fishing system. The changeset extensively refactors the fishing system with new loot tables, environment-specific fishing pools, and related updates across multiple files, aligning perfectly with this title.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/fishing-system

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MrInspection MrInspection added area: engine The core system of BlightedMC plugin area: commands Command logic of the Blugin labels Nov 11, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnableEntityProfile.java (1)

36-43: Add missing validation for positive group size values.

The method validates max >= min but doesn't ensure both values are actually positive. According to the AI summary, the max parameter should also be annotated with @Positive. More importantly, negative group sizes like groupSize(-5, -1) would currently be accepted.

Apply this diff to add proper validation:

-  public SpawnableEntityProfile groupSize(@Positive int min, int max) {
+  public SpawnableEntityProfile groupSize(@Positive int min, @Positive int max) {
+    if (min <= 0 || max <= 0) {
+      throw new IllegalArgumentException("Group sizes must be positive: min=" + min + ", max=" + max);
+    }
     if (max < min) {
       throw new IllegalArgumentException("Invalid group size: min=" + min + ", max=" + max);
     }
src/main/java/fr/moussax/blightedMC/core/entities/loot/gems/GemsItem.java (1)

20-88: Persistent data key mismatch breaks redemption

Newly created gemstones still store their amount under "favorsValue", but the constructor now only reads "gemsValue". Every fresh item therefore redeems as 1 gem, regardless of the intended amount. Existing legacy items also lose their value once picked up because we never read the old key.

Please read both keys (new first, old as a fallback) and write the new key when generating items—optionally mirroring the legacy key to stay backward compatible:

-    Integer value = meta.getPersistentDataContainer()
-      .get(new NamespacedKey(BlightedMC.getInstance(), "gemsValue"), PersistentDataType.INTEGER);
-    this(value != null ? value : 1);
+    NamespacedKey gemsKey = new NamespacedKey(BlightedMC.getInstance(), "gemsValue");
+    NamespacedKey legacyKey = new NamespacedKey(BlightedMC.getInstance(), "favorsValue");
+    Integer value = meta.getPersistentDataContainer().get(gemsKey, PersistentDataType.INTEGER);
+    if (value == null) {
+      value = meta.getPersistentDataContainer().get(legacyKey, PersistentDataType.INTEGER);
+    }
+    this(value != null ? value : 1);
...
-    meta.getPersistentDataContainer().set(new NamespacedKey(BlightedMC.getInstance(), "favorsValue"), PersistentDataType.INTEGER, amount);
+    NamespacedKey gemsKey = new NamespacedKey(BlightedMC.getInstance(), "gemsValue");
+    NamespacedKey legacyKey = new NamespacedKey(BlightedMC.getInstance(), "favorsValue");
+    meta.getPersistentDataContainer().set(gemsKey, PersistentDataType.INTEGER, amount);
+    meta.getPersistentDataContainer().set(legacyKey, PersistentDataType.INTEGER, amount);
src/main/java/fr/moussax/blightedMC/commands/admin/GemsCommand.java (1)

127-156: Tweak gems messaging for consistency

The player-facing strings still say “You gems has been set” and “players favor”, which is confusing after the currency rename.

-    target.sendMessage("§8 ■ §7You gems has been set to §d" + amount + "§7.");
+    target.sendMessage("§8 ■ §7Your gems have been set to §d" + amount + "§7.");
...
-    sender.sendMessage("§8 ■ §7All online players favor have been reset to §d0§7.");
+    sender.sendMessage("§8 ■ §7All online players' gems have been reset to §d0§7.");
🧹 Nitpick comments (4)
.idea/artifacts/blightedmc_jar.xml (1)

1-8: Consider excluding IDE configuration files from version control.

This is an IntelliJ IDEA artifact configuration file containing local development environment paths ($USER_HOME$ paths). IDE configuration files (.idea/ directory) are typically environment-specific and are often excluded from version control to prevent merge conflicts and environment-specific pollution.

The changes themselves (artifact name capitalization and output path) are non-functional and environment-specific. However, if not already present, consider adding the .idea/ directory to .gitignore to follow best practices.

If you'd like, verify the current state of your .gitignore:

#!/bin/bash
# Check if .idea is in .gitignore
grep -E '^\s*\.idea' .gitignore || echo ".idea is not explicitly listed in .gitignore"
src/main/java/fr/moussax/blightedMC/utils/sound/SoundSequence.java (1)

6-6: Consider using explicit imports instead of wildcard.

Wildcard imports can reduce code clarity by obscuring which specific classes are in use and may introduce naming conflicts.

Apply this diff to restore explicit imports:

-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
src/main/java/fr/moussax/blightedMC/gameplay/abilities/BonemerangAbility.java (1)

210-216: Consider simplifying the entity type check.

The current pattern checks instanceof Damageable, casts to damageable, then requires instanceof LivingEntity. Since LivingEntity implements Damageable, you can simplify:

 private void damageNearbyEntities(ArmorStand projectile, Player player) {
   for (Entity entity : projectile.getNearbyEntities(COLLISION_RADIUS, 1, COLLISION_RADIUS)) {
-    if (entity instanceof Damageable damageable && entity != player && entity instanceof LivingEntity) {
-      damageable.damage(DAMAGE_AMOUNT, player);
+    if (entity instanceof LivingEntity livingEntity && entity != player) {
+      livingEntity.damage(DAMAGE_AMOUNT, player);
     }
   }
 }
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootPool.java (1)

83-105: Remove Java version concern; fallback logic is optional refactoring.

The Java version check is resolved—the project targets Java 25, well above the Java 21 requirement for getLast().

The fallback at line 104 remains a valid observation: the weighted selection loop should always return when validEntries is non-empty, making the fallback theoretically unreachable. Consider whether this is defensive coding or can be simplified for clarity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ce8ef0 and 4627808.

📒 Files selected for processing (46)
  • .idea/artifacts/blightedmc_jar.xml (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/BroadcastCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/FlyCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/ForceCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/GemsCommand.java (7 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/GiveItemCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/GodCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/KaboomCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/LoopCommand.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/SpawnCustomMobCommand.java (2 hunks)
  • src/main/java/fr/moussax/blightedMC/commands/admin/TeleportCommands.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/listeners/BlightedEntitiesListener.java (3 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/loot/gems/GemsItem.java (3 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/loot/gems/GemsLoot.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/registry/EntitiesRegistry.java (3 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnConditions.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnableEntityProfile.java (4 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/FishingListener.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/FishingLootTable.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/FishingSystem.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/FishingLootTable.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootCondition.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootContext.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootEntry.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootPool.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/pools/EndFishingPool.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/pools/OverworldFishingPool.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/environment/EndFishing.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/environment/OverworldFishing.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootCondition.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootContext.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootPool.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/fishing/package-info.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/items/ItemTemplate.java (0 hunks)
  • src/main/java/fr/moussax/blightedMC/core/items/registry/ItemDirectory.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/items/registry/ItemDirectoryMenu.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (2 hunks)
  • src/main/java/fr/moussax/blightedMC/core/players/data/PlayerData.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/core/players/data/PlayerDataHandler.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/gameplay/abilities/BonemerangAbility.java (1 hunks)
  • src/main/java/fr/moussax/blightedMC/gameplay/abilities/RocketBootsAbility.java (2 hunks)
  • src/main/java/fr/moussax/blightedMC/gameplay/entities/Dummy.java (3 hunks)
  • src/main/java/fr/moussax/blightedMC/utils/formatting/CommandInfo.java (2 hunks)
  • src/main/java/fr/moussax/blightedMC/utils/formatting/Formatter.java (11 hunks)
  • src/main/java/fr/moussax/blightedMC/utils/sound/SoundSequence.java (1 hunks)
💤 Files with no reviewable changes (9)
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/pools/OverworldFishingPool.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootPool.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/pools/EndFishingPool.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootCondition.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/FishingSystem.java
  • src/main/java/fr/moussax/blightedMC/core/items/ItemTemplate.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/FishingLootTable.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootEntry.java
  • src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootContext.java
🧰 Additional context used
🧬 Code graph analysis (13)
src/main/java/fr/moussax/blightedMC/core/entities/registry/EntitiesRegistry.java (2)
src/main/java/fr/moussax/blightedMC/gameplay/entities/Dummy.java (1)
  • Dummy (15-66)
src/main/java/fr/moussax/blightedMC/core/entities/registry/SpawnableEntitiesRegistry.java (1)
  • SpawnableEntitiesRegistry (9-33)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootPool.java (2)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (1)
  • LootEntry (20-199)
src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootPool.java (1)
  • LootPool (8-43)
src/main/java/fr/moussax/blightedMC/commands/admin/FlyCommand.java (1)
src/main/java/fr/moussax/blightedMC/utils/formatting/Formatter.java (1)
  • Formatter (33-312)
src/main/java/fr/moussax/blightedMC/core/fishing/environment/EndFishing.java (2)
src/main/java/fr/moussax/blightedMC/core/fishing/FishingLootTable.java (1)
  • FishingLootTable (21-165)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (1)
  • LootEntry (20-199)
src/main/java/fr/moussax/blightedMC/core/fishing/FishingListener.java (3)
src/main/java/fr/moussax/blightedMC/core/fishing/environment/EndFishing.java (1)
  • EndFishing (9-28)
src/main/java/fr/moussax/blightedMC/core/fishing/environment/OverworldFishing.java (1)
  • OverworldFishing (12-35)
src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (1)
  • BlightedPlayer (20-216)
src/main/java/fr/moussax/blightedMC/commands/admin/ForceCommand.java (1)
src/main/java/fr/moussax/blightedMC/utils/formatting/CommandInfo.java (1)
  • CommandInfo (25-206)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootContext.java (2)
src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (1)
  • BlightedPlayer (20-216)
src/main/java/fr/moussax/blightedMC/core/fishing/LootTable/LootContext.java (1)
  • LootContext (7-8)
src/main/java/fr/moussax/blightedMC/core/fishing/FishingLootTable.java (3)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (1)
  • LootEntry (20-199)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootPool.java (1)
  • LootPool (15-124)
src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (1)
  • BlightedPlayer (20-216)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (2)
src/main/java/fr/moussax/blightedMC/core/entities/BlightedEntity.java (1)
  • BlightedEntity (32-436)
src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (1)
  • BlightedPlayer (20-216)
src/main/java/fr/moussax/blightedMC/commands/admin/GemsCommand.java (1)
src/main/java/fr/moussax/blightedMC/utils/formatting/CommandInfo.java (1)
  • CommandInfo (25-206)
src/main/java/fr/moussax/blightedMC/commands/admin/TeleportCommands.java (1)
src/main/java/fr/moussax/blightedMC/utils/formatting/CommandInfo.java (1)
  • CommandInfo (25-206)
src/main/java/fr/moussax/blightedMC/core/fishing/environment/OverworldFishing.java (3)
src/main/java/fr/moussax/blightedMC/core/fishing/FishingLootTable.java (1)
  • FishingLootTable (21-165)
src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootEntry.java (1)
  • LootEntry (20-199)
src/main/java/fr/moussax/blightedMC/gameplay/entities/Dummy.java (1)
  • Dummy (15-66)
src/main/java/fr/moussax/blightedMC/core/entities/loot/gems/GemsItem.java (2)
src/main/java/fr/moussax/blightedMC/BlightedMC.java (1)
  • BlightedMC (9-46)
src/main/java/fr/moussax/blightedMC/utils/formatting/Formatter.java (1)
  • Formatter (33-312)
🔇 Additional comments (31)
src/main/java/fr/moussax/blightedMC/core/fishing/package-info.java (1)

1-7: LGTM!

The package documentation is clear, well-formatted, and accurately describes the fishing system's responsibilities. The Javadoc follows standard conventions and aligns with the refactored fishing loot system introduced in this PR.

src/main/java/fr/moussax/blightedMC/utils/sound/SoundSequence.java (1)

9-11: Excellent use of List.copyOf for stronger immutability.

The switch from Collections.unmodifiableList to List.copyOf prevents aliasing—modifications to the original list after construction won't affect this instance. This aligns well with the immutable record pattern.

src/main/java/fr/moussax/blightedMC/gameplay/abilities/BonemerangAbility.java (1)

60-63: Verify the zero-second cooldown is intentional.

The method returns 0, which means the cooldown system at Line 50 sets expiry to the current timestamp. This makes the cooldown check at Line 86 always return false immediately, effectively disabling cooldowns.

If this is a placeholder, consider setting a non-zero default (e.g., 5 seconds). If instant reuse is intended, the entire cooldown tracking system could be simplified or removed.

src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnableEntityProfile.java (2)

54-68: LGTM!

The new getter methods are well-implemented and follow standard Java bean conventions. They provide appropriate read access to the profile's configuration properties.


78-78: LGTM!

The error message now correctly references the class name SpawnableEntityProfile, improving error clarity.

src/main/java/fr/moussax/blightedMC/core/items/registry/ItemDirectory.java (1)

36-36: No thread safety concerns detected. The change is safe for Bukkit plugin architecture.

The codebase uses Bukkit's plugin lifecycle pattern where initialization only occurs in onEnable() (single call at line 17 of BlightedMC.java) and cleanup only in onDisable() (line 40). For /reload scenarios, Bukkit invokes the normal disable/enable cycle. There are no concurrent calls to initializeAllRegistries(), and Bukkit event handlers run on a single server thread, eliminating race conditions. The addition of clearItems() before registration makes initializeItems() idempotent without introducing safety issues—it simply makes individual registries self-contained rather than relying on CoreRegistry-level clearing.

src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnConditions.java (1)

23-25: Behavior change confirmed: surface-level spawns are now excluded.

The actual change from the git history confirms the review comment: the condition was changed from == to <, which means the skyExposed() method now returns true only when a location is floating above the highest non-air block, not when it's exactly at the surface level.

  • Old behavior (==): Spawn only at the surface block level
  • New behavior (<): Spawn only in air above the surface

This is a breaking semantic change for entity spawning. The method is currently used in BlightedZombie spawning (line 178), meaning zombies will no longer spawn on the ground surface itself.

The question is whether this is intentional or a regression:

  • If spawning should include the surface level (typical for "sky exposed" checks), the condition should be <=
  • If spawning should only occur floating in air (strict interpretation), the current < is correct

Verify that all entities using skyExposed() have been tested and behave as expected with this stricter condition, or confirm whether <= was the intended boundary.

src/main/java/fr/moussax/blightedMC/gameplay/abilities/RocketBootsAbility.java (1)

98-121: Durability loss now respects Unbreaking.

The per-point roll mirrors vanilla’s 1/(level+1) loss chance and the break cleanup is tidy. Nicely done.

src/main/java/fr/moussax/blightedMC/core/players/data/PlayerData.java (1)

9-12: LGTM!

The constructor parameter and field assignment have been cleanly renamed from favors to gems, aligning with the broader currency system rename across the PR.

src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootPool.java (3)

26-51: LGTM!

The three overloaded add methods provide a flexible API for adding entries. The builder pattern with return this enables clean method chaining.


71-74: LGTM!

The clamping logic ensures rollChance stays within the valid probability range [0.0, 1.0], preventing invalid configurations.


112-123: LGTM!

The helper methods isEmpty() and size() provide a clean API for checking the pool state.

src/main/java/fr/moussax/blightedMC/core/fishing/loot/LootCondition.java (2)

23-38: LGTM!

The null-safe canonical constructor and test method are well-implemented. The semantics are clear: empty sets mean "no restriction," and both biome and environment conditions must be satisfied.


41-63: LGTM!

The factory methods provide clear, convenient ways to create common conditions. Using Collections.singleton ensures immutability.

src/main/java/fr/moussax/blightedMC/core/entities/registry/EntitiesRegistry.java (2)

18-21: LGTM!

Adding the call to SpawnableEntitiesRegistry.clearEntities() ensures that spawnable entities are properly cleared alongside regular entities, maintaining consistency across both registries.


52-52: LGTM!

The Dummy entity registration follows the established pattern and integrates cleanly with the existing entity system.

src/main/java/fr/moussax/blightedMC/commands/admin/KaboomCommand.java (1)

23-23: LGTM!

The permission guard now properly prevents command execution when the admin permission check fails. This security improvement aligns with the broader pattern applied across admin commands in this PR.

src/main/java/fr/moussax/blightedMC/commands/admin/LoopCommand.java (1)

27-27: LGTM!

The permission guard is especially important for this command, as it enables bulk command execution. Proper authorization prevents potential abuse.

src/main/java/fr/moussax/blightedMC/core/players/BlightedPlayer.java (1)

173-183: LGTM!

The method renames from addFavors/removeFavors to addGems/removeGems, along with the persistence update to setGems, are consistent with the broader currency system rename across the PR.

Also applies to: 200-200

src/main/java/fr/moussax/blightedMC/core/entities/loot/gems/GemsLoot.java (1)

13-13: LGTM!

The update from addFavors to addGems correctly reflects the renamed API in BlightedPlayer, maintaining consistency with the currency system changes.

src/main/java/fr/moussax/blightedMC/commands/admin/GodCommand.java (1)

17-17: Permission guard correctly implemented.

The early return pattern properly enforces admin permissions before executing the command logic.

src/main/java/fr/moussax/blightedMC/commands/admin/BroadcastCommand.java (1)

18-18: Permission guard correctly implemented.

The early return pattern properly enforces admin permissions before executing the command logic.

src/main/java/fr/moussax/blightedMC/commands/admin/ForceCommand.java (2)

21-21: Permission guard correctly implemented.

The early return pattern properly enforces admin permissions before executing the command logic.


24-25: Improved readability with multi-line format.

Splitting the usage message across multiple lines enhances code readability.

src/main/java/fr/moussax/blightedMC/commands/admin/SpawnCustomMobCommand.java (2)

20-20: Permission guard correctly implemented.

The early return pattern properly enforces admin permissions before executing the command logic.


39-39: Improved error message specificity.

Including the entity name in the error message provides clearer feedback to the user about which entity failed to spawn.

src/main/java/fr/moussax/blightedMC/commands/admin/GiveItemCommand.java (1)

23-23: Permission guard correctly implemented.

The early return pattern properly enforces admin permissions before executing the command logic.

src/main/java/fr/moussax/blightedMC/commands/admin/FlyCommand.java (2)

10-10: Static import appropriately added.

The static import for enforceAdminPermission improves code readability.


17-18: Permission guard correctly implemented with good spacing.

The early return pattern properly enforces admin permissions, and the blank line improves code readability by separating the guard from the main logic.

src/main/java/fr/moussax/blightedMC/utils/formatting/CommandInfo.java (2)

103-105: Input validation appropriately added.

The validation prevents potential issues downstream when accessing array indices. The error message mentions "null or empty" but only checks for empty arrays; however, the @Nonnull annotation on the parameter already prevents null values, making this acceptable.


170-172: Input validation appropriately added.

The validation prevents potential issues downstream when accessing array indices. The error message mentions "null or empty" but only checks for empty arrays; however, the @Nonnull annotation on the parameter already prevents null values, making this acceptable.

Comment on lines +5 to +7
import org.checkerframework.checker.index.qual.Positive;

import javax.annotation.Nonnull;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Verify the @Positive annotation source and remove unused imports.

Two concerns with the imports:

  1. The @Positive annotation from Checkerframework (org.checkerframework.checker.index.qual.Positive) is for static analysis only and provides no runtime validation. If runtime validation is intended, consider using javax.validation.constraints.Positive from Bean Validation (JSR 380) instead, or rely solely on the explicit runtime checks you've added.
  2. The @Nonnull import on line 7 appears unused in this file.

</invoke_comment_end -->

Comment on lines +28 to 34
public SpawnableEntityProfile weight(@Positive double weight) {
if (weight < 0.00) {
throw new IllegalArgumentException("Weight cannot be negative: " + weight);
}
this.weight = weight;
return this;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align validation logic with the @Positive annotation semantics.

The @Positive annotation typically means values strictly greater than zero, but your validation check weight < 0.00 permits weight = 0.0. This creates a semantic mismatch.

If zero is a valid weight, consider using @PositiveOrZero instead, or if weights must be strictly positive, update the validation to weight <= 0.

Apply this diff if weights must be strictly positive:

-    if (weight < 0.00) {
+    if (weight <= 0) {
       throw new IllegalArgumentException("Weight cannot be negative: " + weight);
     }

Note: Also update the error message to say "non-positive" rather than "negative" if you make this change.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public SpawnableEntityProfile weight(@Positive double weight) {
if (weight < 0.00) {
throw new IllegalArgumentException("Weight cannot be negative: " + weight);
}
this.weight = weight;
return this;
}
public SpawnableEntityProfile weight(@Positive double weight) {
if (weight <= 0) {
throw new IllegalArgumentException("Weight cannot be negative: " + weight);
}
this.weight = weight;
return this;
}
🤖 Prompt for AI Agents
In
src/main/java/fr/moussax/blightedMC/core/entities/spawnable/SpawnableEntityProfile.java
around lines 28 to 34, the runtime check (weight < 0.00) conflicts with the
@Positive annotation because it allows zero; either change the annotation to
@PositiveOrZero if zero is valid, or enforce strict positivity by changing the
check to weight <= 0 and update the thrown message to "Weight must be positive"
or "Weight cannot be non-positive: " + weight to reflect the tighter validation.

public class BonemerangAbility implements AbilityManager<PlayerInteractEvent> {
private static final NamespacedKey UUID_KEY = new NamespacedKey("blightedmc", "bonemerang_uuid");
private static final Map<UUID, Map<String, Long>> cooldowns = new WeakHashMap<>();
private static final Map<UUID, Map<String, Long>> cooldowns = new ConcurrentHashMap<>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Memory leak: cooldown entries accumulate indefinitely.

Switching from WeakHashMap to ConcurrentHashMap removes automatic cleanup of player entries. On long-running servers, this map will accumulate player UUIDs and their associated item cooldown maps indefinitely, even after cooldowns expire and players disconnect.

Consider one of these solutions:

Option 1: Implement periodic cleanup

private static void cleanupExpiredCooldowns() {
  long now = System.currentTimeMillis();
  cooldowns.forEach((playerId, itemCooldowns) -> {
    itemCooldowns.entrySet().removeIf(entry -> entry.getValue() <= now);
    if (itemCooldowns.isEmpty()) {
      cooldowns.remove(playerId);
    }
  });
}

Schedule this cleanup task to run periodically (e.g., every 5 minutes).

Option 2: Use Caffeine or Guava Cache

private static final Cache<UUID, Map<String, Long>> cooldowns = 
  Caffeine.newBuilder()
    .expireAfterAccess(Duration.ofHours(1))
    .build();

Option 3: Clean up on access

private boolean isItemOnCooldown(Player player, String uuid) {
  Map<String, Long> playerCooldowns = cooldowns.computeIfAbsent(
    player.getUniqueId(), k -> new ConcurrentHashMap<>());
  long currentTime = System.currentTimeMillis();
  
  // Remove expired entry
  Long expiry = playerCooldowns.get(uuid);
  if (expiry != null && expiry <= currentTime) {
    playerCooldowns.remove(uuid);
    return false;
  }
  return expiry != null;
}
🤖 Prompt for AI Agents
In src/main/java/fr/moussax/blightedMC/gameplay/abilities/BonemerangAbility.java
around line 21, the static ConcurrentHashMap storing per-player cooldown maps
never removes player entries, causing unbounded memory growth; fix by removing
expired cooldowns and player maps when empty: implement cleanup-on-access inside
the methods that check/set cooldowns (remove individual item entries when
expired and if the per-player map becomes empty remove the player UUID from the
outer map) and additionally schedule a periodic cleanup task (e.g., run every
few minutes) that iterates the outer map to prune expired item entries and
remove empty per-player maps; alternatively consider replacing the map with a
time-aware cache (Caffeine/Guava) if preferred.

Comment thread src/main/java/fr/moussax/blightedMC/utils/formatting/Formatter.java
@MrInspection
MrInspection merged commit a604886 into master Nov 11, 2025
3 checks passed
@MrInspection
MrInspection deleted the feat/fishing-system branch November 11, 2025 13:34
@coderabbitai coderabbitai Bot mentioned this pull request Dec 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: commands Command logic of the Blugin area: engine The core system of BlightedMC plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant