Overview
SharedStatsHandler implements the core “Soul Link” mechanic where all players share the same health, hunger, saturation, and absorption values. This creates the signature challenge: damage to one player affects everyone.
Location: src/main/java/net/zenzty/soullink/server/health/SharedStatsHandler.java
Core Architecture
Master Stat Values
The handler maintains master values that are synchronized to all players:SharedStatsHandler.java:23-30
All fields are static and volatile for thread-safe access across server threads.
Accumulators for Fractional Values
To prevent rounding errors when dividing by player count, accumulators track fractional amounts:SharedStatsHandler.java:33-43
Without accumulators, effects like regeneration would heal at wildly different rates depending on player count.
Manhunt Mode Integration
In Manhunt mode, only Speedrunners share stats (Hunters use vanilla mechanics):SharedStatsHandler.java:60-72
This method is called before every stat synchronization to determine eligibility.
Initialization and Reset
Reset Method
Called when starting a new run:SharedStatsHandler.java:77-97
The maxHealth respects “Half Heart Mode” (1 HP vs 20 HP):
SharedStatsHandler.java:48-50
Syncing Late Joiners
SharedStatsHandler.java:103-120
Health Synchronization
Damage Handling
When a player takes damage:SharedStatsHandler.java:138-243
Why Separate Periodic Damage?
Poison and Wither damage ticks every player simultaneously. Without normalization:- 1 poisoned player: -1 HP every 25 ticks
- 4 poisoned players: -4 HP every 25 ticks (4x faster death!)
SharedStatsHandler.java:250-306
Now 4 poisoned players = 4 × (1 HP / 4 players) = 1 HP per tick (same as 1 player).
Syncing Damage to Others
When non-periodic damage occurs, sync to all other players:SharedStatsHandler.java:180-239
Important: player.damage() is called to trigger client-side visual/audio feedback, then health is set to the correct shared value.
Healing
Healing (from potions, golden apples, etc.) works similarly:SharedStatsHandler.java:314-369
Regeneration Normalization
Natural Regeneration
Similar to periodic damage, natural regen must be normalized:SharedStatsHandler.java:523-600
Regeneration Effect
The Regeneration potion effect is handled separately:SharedStatsHandler.java:378-458
Hunger Synchronization
Food Level and Saturation
SharedStatsHandler.java:605-662
Natural Hunger Drain
When health regenerates naturally, it consumes hunger. This must also be normalized:SharedStatsHandler.java:670-753
Absorption Hearts
Golden apples and similar items grant absorption (yellow hearts):SharedStatsHandler.java:464-515
Periodic Sync Check
Every second, ensure all players stay synchronized:SharedStatsHandler.java:758-803
This catches any desync issues from network lag or mixin timing.
Preventing Infinite Loops
TheisSyncing flag is critical:
- Player A takes damage
onPlayerHealthChanged()syncs to Player B- Player B’s health changes, triggering
onPlayerHealthChanged()again - Infinite loop crashes server
Helper Methods
Sync Disabled Wrapper
SharedStatsHandler.java:823-832
Used by other handlers (like SharedPotionHandler) to temporarily disable sync detection.
Getters and Setters
SharedStatsHandler.java:836-846
Provide read-only access to current shared stat values for UI display or debugging.