Recovery Implementation
Recovery folds runtime results into long-lived readable data. We have to keep three things separate here: long-term player knowledge, relic snapshots, and client tooltip reads.
Verified Key Boundaries
| Topic | Verified API or event | Conclusion |
|---|---|---|
| player respawn migration | PlayerEvent.Clone.getOriginal(), PlayerEvent.Clone.isWasDeath() | if knowledge lives on player entity data, it must be copied on death respawn |
| tooltip read | ItemTooltipEvent.getItemStack(), getToolTip(), getFlags() | tooltip should only read saved results |
| null-player tooltip path | ItemTooltipEvent.getEntity() may be null | rendering cannot depend on live player |
| item NBT read | ItemStack.getTag(), getOrCreateTag() | snapshots can live directly on item NBT |
| item NBT writeback | ItemStack.setTag(@Nullable CompoundTag) | full-tag replacement is possible when needed |
| player initialization | PlayerEvent.PlayerLoggedInEvent | missing keys may be initialized on login |
Data Layering
| Data | Recommended home |
|---|---|
lc_identification_level | long-term player data |
siteRef, siteTypeId, ResonanceState, patternKey | relic snapshot |
| codex or statistics results | separate record layer |
Item Snapshot Write Boundary
The recovery snapshot should live under one root tag on ItemStack, not as scattered top-level fields.
public static final String RELIC_RESULT_KEY = "lost_civilization.recovered_relic";Recommended write flow:
- read
stack.getOrCreateTag(), - write
RecoveredRelicSnapshotfields under a single root key, - do not overwrite unrelated item tags.
That avoids collisions with enchantments, display names, and mod-added item fields.
Recommended RecoveredRelicSnapshot Shape
public record RecoveredRelicSnapshot(
String siteRef,
String siteTypeId,
ResonanceState state,
String patternKey
) {}Suggested Snapshot Codec Shape
public final class RecoveredRelicSnapshotCodec {
private RecoveredRelicSnapshotCodec() {
}
public static void write(ItemStack stack, RecoveredRelicSnapshot snapshot) {
CompoundTag root = stack.getOrCreateTag();
CompoundTag resultTag = new CompoundTag();
resultTag.putString("site_ref", snapshot.siteRef());
resultTag.putString("site_type_id", snapshot.siteTypeId());
resultTag.putString("state", snapshot.state().name());
resultTag.putString("pattern_key", snapshot.patternKey());
root.put(RELIC_RESULT_KEY, resultTag);
}
}The important constraint is not the field names. It is that encoding should have one entry point only. Otherwise tooltip, recovery, and debug commands will drift into separate formats.
Long-Term Player Knowledge Migration
If lc_identification_level lives on player entity data, keep at least the following subscription:
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
if (!event.isWasDeath()) {
return;
}
// copy long-term knowledge from event.getOriginal() to the new player
}Copy long-term knowledge only. Do not copy pending short markers or live runtime state.
Tooltip Read Rules
ItemTooltipEvent does not derive results. It only presents them.
@SubscribeEvent
public static void onTooltip(ItemTooltipEvent event) {
// 1. read RecoveredRelicSnapshot from event.getItemStack()
// 2. read long-term player knowledge; event.getEntity() may be null
// 3. call RelicTooltipView.build(...)
// 4. append lines to event.getToolTip()
}Recommended read rules:
- try
event.getItemStack().getTag()first, - if the tag does not exist, degrade quietly to the minimum display,
- if
event.getEntity()is null, skip player-knowledge enhancement.
RelicTooltipView Responsibilities
| Should do | Must not do |
|---|---|
| format text from the snapshot and knowledge values | recalculate resonance |
| degrade gracefully when no player is present | access the runtime registry |
| return stable text lines | query the world ledger to decide results |
Minimum Test Requirements
| Scenario | Expected result |
|---|---|
tooltip with player == null | still shows the minimum information |
| item without result tag | degrades quietly without errors |
| low knowledge level | shows only coarse result information |
| high knowledge level | shows deeper state or pattern information |
| after death and respawn | long-term knowledge remains, short markers do not |
Implementation Red Lines
- do not serialize live runtime objects as relic results,
- do not put all recovery data back onto the player entity,
- do not make tooltip the only source of truth,
- do not define multiple incompatible item-snapshot formats.