SoulKeeper
ModKeep your items after death inside a soul
Type
Mod
Modrinth Downloads
1,169
Modrinth ID
tnr41XhG
Last Updated
Jun 21, 2026
Description
👻 SoulKeeper
Your items survive death. So does your progress.
SoulKeeper captures your full inventory and experience into a glowing soul the instant you die — persisting through lava, fire, and even the void — and waits quietly at the death spot until you return to claim it.

✨ Inspiration
SoulKeeper is the spiritual successor of DeadSoulsKT — rebuilt from scratch with a clean multiplatform architecture, async-first design, and a strong focus on reliability. Where DeadSoulsKT laid the foundation, SoulKeeper brings production-grade persistence, rich visual feedback, and cross-platform support to the same beloved mechanic.
💀 How Souls Work
Creating a soul
The moment you die, SoulKeeper silently intercepts the death event before anything hits the ground. Your entire inventory and a configurable portion of your dropped XP are captured and stored in the database as a soul — nothing is scattered across the floor.
A burst of red particles and a resonant bell signal that your soul has been born. The soul appears as a shimmering particle cloud with a floating nameplate — "Soul of <Your Name>" — right where you fell.
Souls spawned in The End are clamped to a minimum Y so they can never sink into the void.
Picking up a soul
Just walk close — no right-click, no shift, no interaction. As soon as you enter the soul's range, it detects you and begins transferring:
Signal Meaning 🔵 Cyan dust particles Soul holds XP ⚪ White dust particles Soul holds items 🔔 Beacon ambient sound Soul is nearby — follow the sound 🟣 Purple smoke + anvil sound Inventory full — items still remain ✨ Bright flash + extinguish sound Soul fully collected and goneItems flow back inventory-slot by inventory-slot. If your inventory is full, partial pickup works: XP is absorbed, whatever fits goes in, and the soul persists with only what remains — no items are ever dropped or lost because of a full bag.
Soul lifecycle
Death → [PRIVATE] ──── soul_free_after ────▶ [PUBLIC] ──── soul_fade_after ────▶ [DELETED] │ │ Only owner Any player can collect can collect State Who can collect Default timing 🔒 Private Owner only Immediately after death 🔓 Public Any player After soul_free_after (default: 2 days) 💨 Gone — After soul_fade_after (default: 14 days)Background workers (FreeSoulWorker, DeleteSoulWorker) run on a configurable tick cadence and advance souls through this lifecycle automatically — no cron jobs, no restarts, no admin action needed.
🗃️ Krates — Backup Storage
Every death also writes a Krate: a standalone YAML snapshot of the soul, saved to disk independently of the database.
plugins/SoulKeeper/ deaths/ <player-uuid>/ <epoch-second>_0.yml ← first krate <epoch-second>_1.yml ← second krate (if retry occurred) ...Krates are a last-resort safety net. Even if the SQLite database is lost, corrupted, or rolled back, an admin can restore any dead player's exact inventory from the krate file — zero database interaction required.
/soulkrate <uuid> <epoch-second> <index>This reads the matching <epoch>_<index>.yml krate file and deposits its items directly into the requesting player's inventory. Use it when:
- A database failure occurred during a busy session
- A player was rolled back by an external tool
- Items need to be restored from a specific past death
🚀 Features
🔄 Fully non-blocking
Every heavy operation — soul creation, pickup detection, database reads/writes, background worker loops — runs on Kotlin coroutines dispatched to background threads via KotlinDispatchers. The main game thread is never touched for I/O.
🛡️ Safe, explicit failure paths
Database operations return kotlin.Result<T>. Failures are logged at the call site and skipped gracefully — they never crash the server, silently eat items, or leave souls in a broken state. Concurrent DB writes in SoulsDaoImpl, the pickup loop in PickUpWorker, and death event handling in ForgeSoulEvents/BukkitSoulEvents are each guarded by their own Mutex.
📦 Krate safety net
A file-based snapshot is written on every death independently of the database. Items cannot be lost in a catastrophic DB failure.
🎨 Fully customizable effects
Every particle (type, color, size, count) and every sound (ID, volume, pitch) is independently configurable per event type. Six sound cues, five particle effects — all tweakable without touching code.
⏳ Configurable soul lifecycle
soul_free_after and soul_fade_after are plain duration values. Set them to seconds, minutes, hours, or days. Background services poll reactively from a config Flow — changes reload live without a restart.
📈 Partial pickup
If your inventory is full when you reach a soul, XP is collected first, then as many items as fit go in. The soul survives with the remainder. Walk back once you have space — nothing is ever force-dropped.
🏷️ Virtual floating name tags
Floating armor-stand nameplates ("Soul of <Player>") are sent as virtual entities via PacketEvents on Bukkit — no real entities are spawned into the world, so performance is unaffected regardless of soul count.
🔔 Proximity soul calling
A SoulCallWorker tracks every online player's position. When a player enters soul_call_radius blocks of a soul they can collect, ambient sounds and particles begin pulsing — guiding them back even in complete darkness or deep underground.
🌍 End dimension safety
Souls spawned in The End are clamped to endLocationLimitY so they never fall below the island floor and become unreachable.
📑 Paginated soul browser
/souls lists all visible souls with owner name, coordinates, age (formatted as "X days ago"), and item/XP indicators. Admins see clickable [FREE] and [TP] buttons inline. 5 souls per page; prev/next navigation included.
🗄️ Versioned database migrations
DatabaseMigrator carries all schema migration steps. Upgrading the plugin never requires manual SQL — migrations run automatically on startup.
⚙️ Configuration
All settings live in config.yml inside the plugin data folder and are hot-reloadable via /skreload.
# Database file path (SQLite) database: ... # Soul becomes publicly collectible after this duration soul_free_after: 2d # Soul disappears permanently after this duration soul_fade_after: 14d # Radius (blocks) within which a soul emits sounds/particles to guide its owner soul_call_radius: 100 # Fraction of dropped XP stored in the soul (0.0 – 1.0) retained_xp: 1.0 # Minimum Y for souls in The End (prevents void loss) end_location_limit_y: 0.0 # Show floating "Soul of <player>" name tags above souls display_soul_titles: true # How PvP deaths are handled # NONE – PvP deaths create no soul # EXP_ONLY – soul holds XP only # ITEMS_ONLY – soul holds items only # EXP_AND_ITEMS – soul holds everything (same as normal death) pvp_behaviour: NONE🎵 Sounds
Every audio cue is independently configurable with id, volume, and pitch:
Key Default sound Trigger collect_xp entity.experience_orb.pickup XP absorbed from soul collect_item item.trident.return Items absorbed from soul soul_disappear entity.generic.extinguish_fire Soul fully collected soul_dropped block.bell.resonate Soul created on death soul_calling block.beacon.ambient Soul pulsing near owner soul_content_left block.anvil.place Inventory full, items remain🌟 Particles
Every particle effect is independently configurable with key, count, and optional dust_options (RGBA color + size):
Key Default color Trigger soul_items White #FFFFFF Soul contains items (continuous) soul_xp Cyan #00FFFF Soul contains XP (continuous) soul_created Red #eb3437 Burst on soul creation soul_gone Yellow #FFFF00 Burst on full collection soul_content_left Purple #a103fc Inventory full warning🛠️ Commands
Command Description Permission /skreload Hot-reload config and translations soulkeeper.reload /souls [page] List your souls (5 per page) (none) /souls [page] List all server souls soulkeeper.all /souls → [FREE] Force-free any soul immediately soulkeeper.free.all /souls → [TP] Teleport to a soul's location soulkeeper.teleport /soulkrate <uuid> <epoch> <index> Restore items from a krate file soulkeeper.load🌐 Multiplatform
SoulKeeper ships a separate fat-jar for each supported platform. All core logic — soul lifecycle, pickup detection, database, background workers, commands — lives in shared platform-agnostic modules. Only event wiring and item serialization are platform-specific.
Platform Jar Minimum version Paper / Spigot soulkeeper-bukkit.jar Paper 1.21.1 Forge soulkeeper-forge.jar Forge 1.21.1 NeoForge soulkeeper-neoforge.jar NeoForge 1.21.1Pick the jar for your platform and drop it in — the same soul data, the same commands, the same behaviour everywhere.
🎬 Preview
On death — soul created
https://github.com/user-attachments/assets/ec5f1437-0dab-404f-a4a8-725ee1cd9129
Returning — soul collected
https://github.com/user-attachments/assets/75f58f92-7d13-4c23-a7fb-b2d89476748b
⚠️ Known Incompatibilities
- Plugins that cancel or heavily modify PlayerDeathEvent (Bukkit) or the equivalent drop events (Forge/NeoForge) may prevent soul creation. Items may not be captured correctly when those plugins are present.
🐛 Support
- Reproduce the issue in a clean environment (no unrelated plugins/mods).
- Collect the full server log from startup through the issue.
- Join our Discord and open a ticket in #support.
💡 Feature Requests
Open a ticket in #suggestions on our Discord and we'll discuss it before creating a GitHub issue.
More plugins from AstraInteractive
Compatibility
Mod Loaders
Game Versions
Screenshots
Similar Mods
Create: Stats & Additions
Create: Stats & Additions is a Create add-on focused on telemetry, dashboards, topology maps, efficiency grading, produc...
Pony Magic
Adds four pony "types" and various magic spells based on My little pony TV show
Beardielover's More Ender Pearls Mod
More Enderpearls adds ender pearls that can explode, swap your position with another entity, bring you with them, and mo...
Dev GUI [FABRIC]
Client side mod to make developing my mods and modpacks more easily
More of Yearn: Enchants & Crafts
To provide you with more Echantments and Recipes
Lucky's Palette
A simple mod that adds new building blocks into the game!