PLAYER_DIED Event Migration Guide
Deprecation Date: March 26, 2026Removal Date: TBD (next major version)
Related PR: #1094
Overview
ThePLAYER_DIED event has been deprecated in favor of PLAYER_SET_DEAD. This migration guide explains why the change was made, how to update your code, and what to watch out for.
Why the Change?
Problem with PLAYER_DIED
The oldPLAYER_DIED event was emitted multiple times during the death flow:
- First emission:
PlayerSystem.handleDeath()when health reaches 0 - Second emission:
PlayerDeathSystem.postDeathCleanup()after death processing
- Subscribers received duplicate events
- Timing was unpredictable (before or after death processing?)
- Race conditions when multiple systems reacted to the same death
- Difficult to reason about event ordering
Solution: PLAYER_SET_DEAD
The newPLAYER_SET_DEAD event is emitted exactly once, after all death processing completes:
- Emitted in
PlayerDeathSystem.postDeathCleanup() - Fires after inventory/equipment cleared
- Fires after gravestone created
- Fires after death lock created
- Fires after player state set to DYING
PLAYER_SET_DEAD fires, the player is fully dead and all death processing is complete.
Migration Steps
Step 1: Find All Usages
Search your codebase forPLAYER_DIED:
Step 2: Update Event Listeners
ReplacePLAYER_DIED with PLAYER_SET_DEAD:
Before:
Step 3: Update Event Emissions (if any)
You should NOT be emitting PLAYER_DIED directly. This event is internal to the death system. If you find code emittingPLAYER_DIED:
- Remove the emission
- Let
PlayerSystem.handleDeath()handle it - Subscribe to
PLAYER_SET_DEADinstead
Step 4: Test Your Changes
After migration, verify:-
Death events fire correctly:
- Kill a player
- Check that
PLAYER_SET_DEADfires exactly once - Check that your subscriber receives the event
-
No duplicate handling:
- Ensure your code doesn’t run twice for the same death
- Check logs for duplicate messages
-
Timing is correct:
- Verify death processing completes before your subscriber runs
- Check that gravestone exists when your code runs
- Check that player is in DYING state when your code runs
Event Timing Comparison
Old Flow (PLAYER_DIED)
New Flow (PLAYER_SET_DEAD)
Common Migration Patterns
Pattern 1: Death Logging
Before:Pattern 2: Death Statistics
Before:Pattern 3: Death Notifications
Before:Pattern 4: Achievement Tracking
Before:killedBy is now sanitized (XSS protection), but still usable for logic.
Pattern 5: Conditional Logic Based on Death State
Before (fragile):Breaking Changes
Event Payload
No breaking changes - payload structure is identical:Event Timing
Breaking change - event fires at different time:- PLAYER_DIED: Fired before death processing (unreliable)
- PLAYER_SET_DEAD: Fired after death processing (reliable)
Event Frequency
Breaking change - event fires once instead of twice:- PLAYER_DIED: Fired 2 times per death
- PLAYER_SET_DEAD: Fired 1 time per death
Deprecation Timeline
Phase 1: Deprecation (March 26, 2026)
PLAYER_DIEDmarked@deprecatedin JSDocPLAYER_SET_DEADis the recommended event- Both events work (backward compatibility)
PLAYER_SET_DEAD at your convenience.
Phase 2: Removal (TBD - next major version)
PLAYER_DIEDevent removed entirely- Code using
PLAYER_DIEDwill break - No backward compatibility
Testing Your Migration
Unit Tests
Update test assertions: Before:Integration Tests
Verify death flow end-to-end:Troubleshooting
Issue: Event not firing
Symptoms:PLAYER_SET_DEAD never fires when player dies.
Diagnosis:
- Check that player health actually reaches 0
- Check server logs for death processing errors
- Verify
PlayerDeathSystemis registered in world
PlayerDeathSystem is in your world’s system list.
Issue: Event fires multiple times
Symptoms:PLAYER_SET_DEAD fires more than once for a single death.
Diagnosis:
- Check for duplicate
PlayerDeathSysteminstances - Check for manual
PLAYER_SET_DEADemissions (anti-pattern)
PLAYER_SET_DEAD manually.
Issue: Gravestone doesn’t exist when event fires
Symptoms:PLAYER_SET_DEAD fires but gravestone entity is undefined.
Diagnosis:
- Check server logs for gravestone creation errors
- Verify position is valid (not NaN/Infinity)
- Check entity manager for gravestone entity
FAQ
Q: Can I use both PLAYER_DIED and PLAYER_SET_DEAD during migration?
A: Yes, both events work during the deprecation phase. However, you should migrate toPLAYER_SET_DEAD as soon as possible to avoid breaking changes in the next major version.
Q: What’s the difference between ENTITY_DEATH and PLAYER_SET_DEAD?
A:ENTITY_DEATHis a generic event for any entity death (players, mobs, NPCs)PLAYER_SET_DEADis player-specific and fires after death processing completes- Use
PLAYER_SET_DEADfor player-specific logic (respawn, gravestones, etc.) - Use
ENTITY_DEATHfor generic death logic (kill tracking, loot drops, etc.)
Q: Does PLAYER_SET_DEAD fire for mob deaths?
A: No,PLAYER_SET_DEAD is player-only. For mob deaths, use ENTITY_DEATH or mob-specific events.
Q: What if I need to run code BEFORE death processing?
A: Subscribe toENTITY_DEATH instead. This fires immediately when health reaches 0, before death processing starts.
Example:
Q: Can I still access player inventory when PLAYER_SET_DEAD fires?
A: No, inventory and equipment are cleared beforePLAYER_SET_DEAD fires. If you need pre-death inventory, subscribe to ENTITY_DEATH instead.
Example:
Q: What about ElizaOS agents?
A: Theplugin-hyperscape package has been updated to use PLAYER_SET_DEAD. If you’re using a custom ElizaOS plugin, update your event listeners.
File: packages/plugin-hyperscape/src/types.ts
Before:
Automated Migration
Search and Replace
Use your editor’s search-and-replace to migrate: Find:PLAYER_DIEDReplace:
PLAYER_SET_DEAD
Regex (for event listener patterns):
Codemod Script
For large codebases, use a codemod:Rollback Plan
If you need to rollback during migration:Option 1: Listen to Both Events
Option 2: Feature Flag
Support
If you encounter issues during migration:- Check the logs: Look for death processing errors
- Review the PR: See PR #1094 for implementation details
- Read the docs: See death-system-architecture.md for complete system documentation
- Ask for help: Open an issue on GitHub with your migration question
References
- PR #1094: Player death system overhaul
- DeathUtils.ts: Pure utility functions
- PlayerDeathSystem.ts: Main death orchestration
- death-system-architecture.md: Complete system documentation
- CLAUDE.md: Recent changes section