#include "Entry.h" #include "ll/api/chrono/GameChrono.h" #include "ll/api/memory/Hook.h" #include "ll/api/service/Bedrock.h" #include "mc/world/actor/ActorDamageSource.h" #include "mc/world/actor/ActorDamageByActorSource.h" #include "mc/world/actor/Actor.h" #include "mc/world/actor/Mob.h" #include "mc/world/level/Level.h" //===============GMLIB 0.13.5 ActorDamageCause.cc=============== phmap::flat_hash_map mFallHeightMap; phmap::flat_hash_map mHurtByEntityMap; phmap::flat_hash_map mVanillaCauseMessage; phmap::flat_hash_map> mHardCodedDeathMessage; bool isCrystal = false; std::string getCause(SharedTypes::Legacy::ActorDamageCause cause) { auto id = (int)cause; if (mVanillaCauseMessage.count(id)){return std::string(mVanillaCauseMessage[id]);} return ""; } Actor* getDamagingEntity(ActorDamageSource* ads) { auto id = ads->getDamagingEntityUniqueID(); return ll::service::getLevel()->fetchEntity(id,true); } // %entity.warden.name std::string getResourcePackKey(std::string const& name, Actor* ac) { if (ac->hasCategory(ActorCategory::Player)){return name;} auto type = ac->getTypeName(); ll::utils::string_utils::replaceAll(type, "minecraft:", ""); std::string res = "%entity." + type + ".name"; return res; } // 构造死亡信息输出 DeathMessageResult makeDeathMessage( int cause, DeathMessageResult& deathMessage, std::string& name, Actor* killer, std::string& weaponName, bool isEscaping, bool isHardCodedMessage = false ) { // 自定义类型构造 if (cause >= 35||mVanillaCauseMessage.count(cause) || isHardCodedMessage) { std::string msg = "death.attack.damageCause.item"; ll::utils::string_utils::replaceAll(msg, "damageCause", getCause(SharedTypes::Legacy::ActorDamageCause(cause))); if (isHardCodedMessage) { msg = deathMessage.first;} // 没有武器名不使用.item结尾 if (weaponName.empty()) { // 试图逃离 xx 使用.player if (killer) { if (isEscaping){ll::utils::string_utils::replaceAll(msg, ".item", ".player");} } else { ll::utils::string_utils::replaceAll(msg, ".item", ""); } } DeathMessageResult res = {msg, {name}}; if (killer) { if (killer->isPlayer()) { res.second.push_back(((Player*)killer)->getRealName()); } else { res.second.push_back(getResourcePackKey(name, killer)); } auto weaponname = killer->getCarriedItem().getCustomName(); if (!weaponname.empty()) { weaponname = "[§b§o" + weaponname + "§r]"; res.second.push_back(weaponname); } else { ll::utils::string_utils::replaceAll(res.first, ".item", ""); } } else { // 如果没有击杀者和试图逃离,那么不可能使用 .player 结尾 ll::utils::string_utils::replaceAll(res.first, ".player", ""); } if (!DeathMessages::Entry::getInstance().isResourceI18nLoaded) { res.first=tr(res.first, res.second); logger->info("原消息name为 {}", res.first); res.second = {}; } return res; } // 未定义返回vanilla值 return deathMessage; } DeathMessageResult tryTranslateHardCodedFallingDeathMessage( DeathMessageResult& deathMessage, std::string& name, Actor* killer, std::string& directKiller, std::string& weaponName, bool isEscaping, int64 deadUniqueId ) { if (!directKiller.empty()) { deathMessage.first = "death.fell.finish.item"; } // 低处 else if (deathMessage.first == "death.attack.fall") { deathMessage.first = "death.attack.fall.item"; } // 高处 else if (deathMessage.first == "death.fell.accident.generic") { // 试图逃离而亡 if (killer) { std::string weapon = killer->getCarriedItem().getCustomName(); if (!weapon.empty()) { deathMessage.first = "death.fell.assist.item"; } else { deathMessage.first = "death.fell.assist"; } } // 超高 else if (mFallHeightMap[deadUniqueId] >= 100) { deathMessage.first = "death.fell.killer"; } else { deathMessage.first = "death.fell.accident.generic"; } } else { deathMessage.first = "death.attack.generic"; } return makeDeathMessage((int)SharedTypes::Legacy::ActorDamageCause::Fall, deathMessage, name, killer, weaponName, false, true); } std::optional tryTranslateHardCodedDeathMessage( SharedTypes::Legacy::ActorDamageCause cause, DeathMessageResult& deathMessage, std::string& name, Actor* killer, std::string& directKiller, std::string& weaponName, bool isEscaping, int64 deadUniqueId ) { switch (cause) { // 硬编码摔死信息 case SharedTypes::Legacy::ActorDamageCause::Fall: { return tryTranslateHardCodedFallingDeathMessage( deathMessage, name, killer, directKiller, weaponName, isEscaping, deadUniqueId ); } // 硬编码爆炸信息 case SharedTypes::Legacy::ActorDamageCause::BlockExplosion: { if (!isCrystal) { deathMessage.first = "death.attack.badRespawnPoint.message"; } else { deathMessage.first = "death.attack.explosion.item"; } return makeDeathMessage((int)cause, deathMessage, name, killer, weaponName, isEscaping, true); } case SharedTypes::Legacy::ActorDamageCause::Contact: { switch (ll::hash_utils::doHash(deathMessage.first)) { case ll::hash_utils::doHash("death.attack.cactus"): deathMessage.first = "death.attack.cactus.item"; break; case ll::hash_utils::doHash("death.attack.sweetBerry"): deathMessage.first = "death.attack.sweetBerry.item"; break; default: deathMessage.first = "death.attack.generic.item"; break; } return makeDeathMessage((int)cause, deathMessage, name, killer, weaponName, isEscaping, true); } } if (mHardCodedDeathMessage.contains(cause)) { if (directKiller.empty()) { directKiller = "empty"; } if (mHardCodedDeathMessage[cause].contains(directKiller)) { deathMessage.first = std::string(mHardCodedDeathMessage[cause][directKiller]); return makeDeathMessage((int)cause, deathMessage, name, killer, weaponName, isEscaping, true); } else if (mHardCodedDeathMessage[cause].contains("all")) { deathMessage.first = std::string(mHardCodedDeathMessage[cause]["all"]); return makeDeathMessage((int)cause, deathMessage, name, killer, weaponName, isEscaping, true); } } return {}; } DeathMessageResult translateDeathMessage(DeathMessageResult origin, std::string name, Actor* dead, ActorDamageSource* ads) { name = getResourcePackKey(name, dead); if (origin.first.length() > 65565) { return {"death.attack.even_more_magic", {name}}; } auto damageCause = ads->mCause; // 伤害类型 Actor* killer = nullptr; // 击杀者 std::string directKiller; // 直接击杀实体 std::string weaponName; // 是否持有武器 bool isEscaping = false; int64 uid = dead->getOrCreateUniqueID().rawID; if (ads->isEntitySource()) { directKiller = getDamagingEntity(ads)->getTypeName(); if (ads->isChildEntitySource()) { killer = getDamagingEntity(ads)->getOwner(); } else { killer = getDamagingEntity(ads); } } if (mHurtByEntityMap.count(uid)) { if (killer == nullptr) { killer = ll::service::getLevel()->fetchEntity(mHurtByEntityMap[uid],true); } isEscaping = true; } if (killer != nullptr) { weaponName = killer->getCarriedItem().getCustomName(); } // Vanilla的硬编码死亡信息类型 auto result = tryTranslateHardCodedDeathMessage(damageCause, origin, name, killer, directKiller, weaponName, isEscaping, uid); if (result.has_value()) { return result.value(); } return makeDeathMessage((int)damageCause, origin, name, killer, weaponName, isEscaping); } bool setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause cause, std::string_view msg) { auto id = (int)cause; if (!mVanillaCauseMessage.count(id)) { mVanillaCauseMessage[id] = msg; return true; } return false; } bool registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause cause, std::string_view message, std::string_view killerType ) { if (mHardCodedDeathMessage.contains(cause)) { if (mHardCodedDeathMessage[cause].contains(killerType)) { return false; } } mHardCodedDeathMessage[cause][killerType] = message; return true; } //===============Copy finish=============== void RegisterDamageDefinition() { setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Anvil, "anvil"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::EntityAttack, "mob"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::RamAttack, "mob"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Drowning, "drown"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::FallingBlock, "fallingBlock"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Fire, "inFire"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::FireTick, "onFire"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Fireworks, "fireworks"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::FlyIntoWall, "flyIntoWall"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Freezing, "freeze"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Lava, "lava"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Lightning, "lightningBolt"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Wither, "wither"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Magic, "indirectMagic"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Magma, "hotFloor"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Stalactite, "stalactite"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Stalagmite, "stalagmite"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Starve, "starve"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Suffocation, "inWall"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::SonicBoom, "sonicBoom"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Void, "outOfWorld"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::SelfDestruct, "genericKill"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Projectile, "thrown"); setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause::Thorns, "thorns"); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.fireball.item", "minecraft:small_fireball" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.trident.item", "minecraft:thrown_trident" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.spit", "minecraft:llama_spit" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.bullet", "minecraft:shulker_bullet" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.arrow.item", "minecraft:arrow" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.explosion.player", "minecraft:fireball" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Projectile, "death.attack.mob", "minecraft:breeze_wind_charge_projectile" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Magic, "death.attack.magic", "empty" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::SonicBoom, "death.attack.sonicBoom", "minecraft:warden" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::Thorns, "death.attack.generic", "empty" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::EntityExplosion, "death.attack.explosion.player", "all" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::EntityExplosion, "minecraft:wither_skull", "death.attack.witherSkull.item" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::EntityExplosion, "minecraft:wither_skull_dangerous", "death.attack.witherSkull.item" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::EntityAttack, "minecraft:player", "death.attack.player.item" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::EntityAttack, "minecraft:bee", "death.attack.sting.item" ); registerCustomDeathMessage( SharedTypes::Legacy::ActorDamageCause::RamAttack, "minecraft:player", "death.attack.player.item" ); }