| Change | Description |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Removed noisy normal-case logging** | Stopped treating “no player row found” as an `INFO` event, because this is normal for first join / first lookup. |
| **Debug-only missing-record logs** | Kept optional visibility by moving the message behind `debug: true` instead of always spamming console. |
| **Cleaner DB reads** | `MySQL#getHearts()` and `SQLite#getHearts()` now return `starting-hearts` quietly when no record exists. |
| **Reduced console clutter** | Makes real errors easier to notice because harmless first-time lookups no longer flood logs. |
| **Safer connection checks** | Added `isConnectionOpen()` style checks before queries so bad connection states are logged clearly and separately. |
| Change | Description |
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Custom-beacon-only detection** | The revive listener no longer treats any plain beacon as a revive beacon; it checks the custom beacon metadata. |
| **Right-click + place support** | The beacon now works seamlessly whether the player right-clicks it or tries to place it. Placement is cancelled and revive mode starts instead. |
| **Config-synced beacon metadata** | `/lifestealadmin revivebeacon` now builds the beacon from `revive-beacon-crafting.display-name` and `revive-beacon-crafting.lore`, matching listener checks exactly. |
| **Session timeout handling** | Revive sessions now expire cleanly after the timeout instead of lingering awkwardly. |
| **Duplicate-session prevention** | A player cannot start multiple revive sessions at once. |
| **Safer target lookup** | Revive chat logic now resolves the target more carefully and handles invalid names more safely. |
| **Guaranteed beacon consumption on success** | After a successful revive, the beacon is consumed correctly from the reviver’s main hand. |
| **Listener cleanup** | Chat listener unregisters itself and cancels timeout tasks after completion, preventing stale revive sessions. |
| Change | Description |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **Pre-check before consume** | The listener now checks current hearts before consuming the heart item. |
| **No wasted item at max hearts** | If the player is already at the max-heart cap, the item is not consumed. |
| **No partial-overflow loss** | If a tiered heart item would exceed max hearts, usage is blocked instead of silently consuming the item for no effective gain. |
| **Clear user feedback** | Players now get a proper message when they cannot use a heart item due to the cap. |
| **Cap respects bypass permission** | `lifesteal.bypasslimit` still allows exceeding the configured max as intended. |
| Change | Description |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Revive beacon creation centralized** | Added a dedicated `buildReviveBeacon()` path so admin-given beacons always match plugin expectations. |
| **Inventory-full protection** | `giveheart` and `revivebeacon` now check leftovers from `Inventory#addItem()` instead of silently failing. |
| **Safer player targeting** | Uses exact player lookup in the improved version for more reliable targeting. |
| **More consistent prefixed messages** | Standardized more admin feedback through `MessageUtils.sendWithPrefix()`. |
| **Config-driven beacon metadata** | Removed hardcoded revive-beacon metadata drift by syncing item creation with config values. |
| Change | Description |
| ------------------------------- | --------------------------------------------------------------------------------------------------------- |
| **Main-hand beacon validation** | Before reviving, the plugin verifies the player still has the proper revive beacon in hand. |
| **Safe session cleanup** | Cancels timeout tasks and unregisters the listener after the chat flow ends. |
| **Safer chat handling** | Ignores unrelated chat, trims input, and handles blank target names safely. |
| **Controlled revive flow** | The revive only proceeds when the target exists, is banned, and the reviver still holds the valid beacon. |
| **Consumption after success** | Beacon removal occurs as part of the success path, so valid revives actually spend the item. |
| Change | Description |
| -------------------------------- | ------------------------------------------------------------------------------------- |
| **Unified revive session start** | Moved the common revive-start behavior into one reusable method. |
| **Placement interception** | `BlockPlaceEvent` support lets the beacon work even when the player tries placing it. |
| **Metadata normalization** | Name/lore checks normalize formatting and stripped colors for more reliable matching. |
| **Lore-aware validation** | The listener can validate both display name and lore, reducing accidental matches. |
| **Permission-first handling** | Fails early with a clear message if the player lacks `lifesteal.revive`. |
| Change | Description |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Max-cap sanitation** | Keeps hearts from going negative and clamps to config max unless bypass permission exists. |
| **Reliable health sync** | Applies max health immediately after heart changes so gameplay matches stored values. |
| **At-least-one-heart safeguard** | Converts heart counts to health with a minimum of `2.0` health. |
| **Cleaner heart adjustment path** | Centralizes add/remove behavior through `adjustHearts()`. |
| **Recommended sync-save path** | I recommended replacing async per-change saves with synchronous saves for heart updates to avoid race conditions under rapid events. |
| **Modern max-health recommendation** | I recommended switching from `player.setMaxHealth(...)` to the attribute API for newer server compatibility. |
| Change | Description |
| ------------------------------------ | ----------------------------------------------------------------------------------------------- |
| **Verified kill transfer logic** | Confirmed PvP deaths give the killer `+1` heart and remove `-1` from the victim. |
| **Non-PvP penalty preserved** | Confirmed non-player deaths only remove a heart if `death-penalty-enabled` is true. |
| **Ban check after heart loss** | Victims are checked for zero hearts immediately after removal. |
| **Cleaner structure recommendation** | I suggested splitting PvP and non-PvP death handling into dedicated helper methods for clarity. |
| **Optional feedback messages** | Added a cleaner version that informs killer and victim about the heart transfer. |
| Change | Description |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **Safer ban checks** | Verifies player validity and avoids duplicate bans. |
| **Consistent kick-on-ban behavior** | Permanent ban flow bans and kicks with a constructed config-based message. |
| **Cleaner unban path** | Prevents null/invalid unban attempts and logs successful unbans clearly. |
| **Better naming/flow clarity** | Recommended a cleaner `banSync()` path and more direct `checkBan()` flow. |
| **Compatibility with heart-loss flow** | Works correctly with the victim heart removal path so players reaching `0` hearts are punished immediately. |
Optional dependencies
PlaceholderAPI
Any compatible version
Developer information
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle.
maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" }