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é |