HyCodeYourTale

Death Handling

Death Handling

Detailní dokumentace k systému smrti v Hytale.

---

Přehled Architektury

Death System

├── DeathComponent
│ ├── Death cause
│ ├── Death message
│ ├── Items lost
│ └── Death screen config

├── DeathSystems
│ ├── ClearHealth
│ ├── ClearEffects
│ ├── DropItems
│ ├── KillFeed
│ ├── DeathScreen
│ └── CorpseRemoval

└── RespawnSystems
├── ResetStats
├── ClearEffects
└── RespawnController

---

DeathComponent

Komponenta přidaná entitě při smrti:

public class DeathComponent implements Component {
public static final BuilderCodec CODEC;

// Příčina smrti
private String deathCause;

// Zpráva o smrti
private Message deathMessage;

// Zobrazit death menu
private boolean showDeathMenu = true;

// Ztracené itemy
private ItemStack[] itemsLostOnDeath;
private double itemsAmountLossPercentage;
private double itemsDurabilityLossPercentage;

// Zobrazit data na death screen
private boolean displayDataOnDeathScreen;

// Reference na damage který způsobil smrt
private Damage deathInfo;

// Mód ztráty itemů
private DeathConfig.ItemsLossMode itemsLossMode = DeathConfig.ItemsLossMode.ALL;

// Interaction chain pro death
private InteractionChain interactionChain;

// ComponentType
public static ComponentType getComponentType() {
return DamageModule.get().getDeathComponentType();
}
}

Vytvoření DeathComponent

// Automaticky přes damage systém
// Když health klesne na 0, DeathComponent se přidá automaticky

// Manuální přidání (pro speciální případy)
public static void tryAddComponent(Store store, Ref ref, Damage damage) {
if (!store.getArchetype(ref).contains(getComponentType())) {
store.addComponent(ref, getComponentType(), new DeathComponent(damage));
}
}

// V CommandBuffer
public static void tryAddComponent(CommandBuffer commandBuffer, Ref ref, Damage damage) {
if (!commandBuffer.getArchetype(ref).contains(getComponentType())) {
commandBuffer.run(store -> tryAddComponent(store, ref, damage));
}
}

---

DeathSystems

ClearHealth

Nastaví health na 0 při smrti:

public static class ClearHealth extends OnDeathSystem {
@Override
public Query getQuery() {
return EntityStatMap.getComponentType();
}

@Override
public Set> getDependencies() {
return RootDependency.firstSet(); // Běží jako první
}

public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
EntityStatMap statMap = store.getComponent(ref, EntityStatMap.getComponentType());
statMap.setStatValue(DefaultEntityStatTypes.getHealth(), 0.0f);
}
}

ClearEntityEffects

Odstraní všechny efekty při smrti:

public static class ClearEntityEffects extends OnDeathSystem {
@Override
public Query getQuery() {
return EffectControllerComponent.getComponentType();
}

public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
EffectControllerComponent effects = commandBuffer.getComponent(ref, EffectControllerComponent.getComponentType());
effects.clearEffects(ref, commandBuffer);
}
}

ClearInteractions

Zruší všechny aktivní interakce:

public static class ClearInteractions extends OnDeathSystem {
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
// Zruší interakce jako wielding, charging, atd.
}
}

PlayerKilledPlayer

Zpracování PvP kill:

public static class PlayerKilledPlayer extends OnDeathSystem {
@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}

public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
Damage deathInfo = component.getDeathInfo();
if (deathInfo != null && deathInfo.getSource() instanceof Damage.EntitySource entitySource) {
Ref killerRef = entitySource.getRef();
// Zpracuj PvP kill
}
}
}

DropPlayerDeathItems

Drop itemů při smrti:

public static class DropPlayerDeathItems extends OnDeathSystem {
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
// Získej inventář
// Dropni itemy podle nastavení
// Nastav itemsLostOnDeath
}
}

KillFeed

Zobrazení zprávy o smrti:

public static class KillFeed extends OnDeathSystem {
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
// Vytvoří KillFeedEvent
// Pošle zprávu všem hráčům
KillFeedMessage message = new KillFeedMessage(
victimName,
killerName,
deathIcon
);
}
}

PlayerDeathScreen

Zobrazení death obrazovky:

public static class PlayerDeathScreen extends OnDeathSystem {
@Override
public Query getQuery() {
return EntityModule.get().getPlayerComponentType();
}

public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {
if (component.isShowDeathMenu()) {
Player player = store.getComponent(ref, Player.getComponentType());
// Otevři RespawnPage
PageManager.openPage(player, RespawnPage.class);
}
}
}

DeathAnimation

Přehrání death animace:

public static class DeathAnimation extends OnDeathSystem {
@Override
public Query getQuery() {
return MovementStatesComponent.getComponentType();
}

// Přehraje death animaci podle:
// - Pohybového stavu (stojící, běžící, plavání)
// - Příčiny smrti (pád, utopení, boj)
}

CorpseRemoval

Odstranění mrtvoly po čase:

public static class CorpseRemoval extends EntityTickingSystem {
@Override
public Query getQuery() {
return Query.and(
DeathComponent.getComponentType(),
DeferredCorpseRemoval.getComponentType()
);
}

@Override
public void tick(int index, ArchetypeChunk chunk,
Store store, CommandBuffer commandBuffer) {
// Zkontroluj čas od smrti
// Odstraň entitu když uplyne čas
}
}

---

RespawnSystems

ResetStatsRespawnSystem

Reset statistik při respawnu:

public static class ResetStatsRespawnSystem {
// Resetuje health na maximum
// Resetuje další staty
}

ClearEntityEffectsRespawnSystem

Vyčistí efekty při respawnu:

public static class ClearEntityEffectsRespawnSystem {
// Odstraní všechny aktivní efekty
}

RespawnControllerRespawnSystem

Určení pozice respawnu:

public static class RespawnControllerRespawnSystem {
// Získá respawn pozici z:
// - RespawnBlock (postel)
// - World spawn
// - Custom respawn point
}

---

Custom Death System

Základní OnDeathSystem

public class MyDeathSystem extends DeathSystems.OnDeathSystem {

@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}

@Override
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {

PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
if (playerRef == null) return;

UUID victimUuid = playerRef.getUuid();

// Logování
getLogger().atInfo().log("Player %s died!", playerRef.getUsername());

// Získání killera
Damage deathInfo = component.getDeathInfo();
if (deathInfo != null) {
Damage.Source source = deathInfo.getSource();

if (source instanceof Damage.EntitySource entitySource) {
Ref killerRef = entitySource.getRef();
PlayerRef killerPlayerRef = store.getComponent(killerRef, PlayerRef.getComponentType());

if (killerPlayerRef != null) {
UUID killerUuid = killerPlayerRef.getUuid();
// PvP kill
onPlayerKill(killerUuid, victimUuid);
}
}
}

// Aktualizace statistik
incrementDeathCount(victimUuid);
}

private void onPlayerKill(UUID killer, UUID victim) {
// Inkrementuj kill count
}

private void incrementDeathCount(UUID uuid) {
// Inkrementuj death count
}
}

// Registrace
@Override
protected void setup() {
getEntityStoreRegistry().registerSystem(new MyDeathSystem());
}

---

ItemsLossMode

Módy ztráty itemů při smrti:

public enum ItemsLossMode {
NONE, // Žádné itemy se neztrácí
ALL, // Všechny itemy
PERCENTAGE, // Procento itemů
RANDOM, // Náhodně
HOTBAR_ONLY, // Pouze hotbar
EQUIPPED_ONLY // Pouze equipnuté
}

Konfigurace v DeathComponent

// Nastavení módu
deathComponent.setItemsLossMode(DeathConfig.ItemsLossMode.PERCENTAGE);

// Procento ztráty množství
deathComponent.setItemsAmountLossPercentage(0.5); // 50%

// Procento ztráty durability
deathComponent.setItemsDurabilityLossPercentage(0.2); // 20%

// Získání ztracených itemů
DeathItemLoss loss = deathComponent.getDeathItemLoss();

---

KillFeedEvent

Event pro kill feed:

// Příklad použití
getEventRegistry().registerGlobal(KillFeedEvent.class, event -> {
Message message = event.getMessage();
// Custom zpracování
});

---

Příklady

Kill Tracker

public class KillTracker {
private final Map kills = new ConcurrentHashMap<>();
private final Map deaths = new ConcurrentHashMap<>();

public void onPlayerDeath(UUID victimUuid, @Nullable UUID killerUuid) {
deaths.merge(victimUuid, 1, Integer::sum);

if (killerUuid != null) {
kills.merge(killerUuid, 1, Integer::sum);
}
}

public int getKills(UUID uuid) {
return kills.getOrDefault(uuid, 0);
}

public int getDeaths(UUID uuid) {
return deaths.getOrDefault(uuid, 0);
}

public double getKDRatio(UUID uuid) {
int k = getKills(uuid);
int d = getDeaths(uuid);
return d == 0 ? k : (double) k / d;
}
}

Custom Death Message

public class CustomDeathMessageSystem extends DeathSystems.OnDeathSystem {

@Override
public Query getQuery() {
return PlayerRef.getComponentType();
}

@Override
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {

PlayerRef victim = store.getComponent(ref, PlayerRef.getComponentType());
if (victim == null) return;

Damage deathInfo = component.getDeathInfo();
DamageCause cause = component.getDeathCause();

// Custom death message
Message customMessage;
if (cause != null && "Fall".equals(cause.getId())) {
customMessage = Message.raw(victim.getUsername() + " zapomněl, že nemůže létat");
} else {
customMessage = component.getDeathMessage();
}

component.setDeathMessage(customMessage);
}
}

Respawn se Ztrátou XP

public class XPLossOnDeathSystem extends DeathSystems.OnDeathSystem {

private final double xpLossPercent = 0.1; // 10%

@Override
public Query getQuery() {
return Query.and(
PlayerRef.getComponentType(),
EntityStatMap.getComponentType()
);
}

@Override
public void onComponentAdded(Ref ref, DeathComponent component,
Store store, CommandBuffer commandBuffer) {

EntityStatMap stats = store.getComponent(ref, EntityStatMap.getComponentType());
if (stats == null) return;

// Získej aktuální XP
int xpStatType = ...; // Custom stat type pro XP
float currentXP = stats.getStatValue(xpStatType);

// Odečti procento
float xpLoss = currentXP * (float) xpLossPercent;
stats.subtractStatValue(xpStatType, xpLoss);

// Informuj hráče
Player player = store.getComponent(ref, Player.getComponentType());
if (player != null) {
player.sendMessage(Message.raw(String.format("Ztratil jsi %.0f XP!", xpLoss)));
}
}
}

---

Shrnutí

| Třída | Účel |
|-------|------|
| DeathComponent | Komponenta přidaná při smrti |
| DeathSystems | Vestavěné death systémy |
| RespawnSystems | Systémy pro respawn |
| DeathConfig | Konfigurace death chování |
| KillFeedEvent | Event pro kill feed |

| DeathSystem | Popis |
|-------------|-------|
| ClearHealth | Nastaví health na 0 |
| ClearEntityEffects | Odstraní efekty |
| DropPlayerDeathItems | Drop itemů |
| KillFeed | Zobrazí zprávu o smrti |
| PlayerDeathScreen | Zobrazí death screen |
| DeathAnimation | Přehraje animaci |
| CorpseRemoval | Odstraní mrtvolu |

| ItemsLossMode | Popis |
|---------------|-------|
| NONE | Žádná ztráta |
| ALL | Vše |
| PERCENTAGE | Procento |
| RANDOM | Náhodně |
| HOTBAR_ONLY | Pouze hotbar |
| EQUIPPED_ONLY | Pouze equipnuté |

Last updated: 20. ledna 2026