feat: adapt to Levilamina 26.10.5

Code references logic from ActorDamageCause.cc(GMLIB 0.13.5)
This commit is contained in:
2026-06-20 16:49:21 +08:00
Unverified
parent a525d066c6
commit ce09c29431
6 changed files with 539 additions and 115 deletions
+2 -1
View File
@@ -15,4 +15,5 @@ build/
/.xmake
/CMakeLists.txt
/bin
/.cache
/.cache
/.idea
+493 -63
View File
@@ -1,123 +1,553 @@
#include "Entry.h"
#include "GMLIB/Mod/Addons/CustomDamageCause.h"
#include "Global.h"
#include "ll/api/event/player/PlayerConnectEvent.h"
#include "ll/api/event/player/PlayerDisconnectEvent.h"
#include "ll/api/memory/Hook.h"
#include "ll/api/chrono/GameChrono.h"
#include "ll/api/thread/ThreadPoolExecutor.h"
#include <chrono>
#include "mc/world/actor/Mob.h"
#include "mc/world/actor/ActorDamageSource.h"
#include "mc/world/actor/ActorDamageByActorSource.h"
#include "mc/world/actor/ActorDamageByBlockSource.h"
#include "mc/world/actor/ActorDamageByChildActorSource.h"
#include "ll/api/service/Bedrock.h"
#include "mc/world/level/Level.h"
#include "mc/world/actor/Actor.h"
phmap::flat_hash_map<int64, float> mFallHeightMap;
phmap::flat_hash_map<int64, ActorUniqueID> mHurtByEntityMap;
LL_AUTO_TYPE_INSTANCE_HOOK(
MobDieHook,
HookPriority::Normal,
Mob,
&Mob::$die,
void,
ActorDamageSource const& ads
) {
auto uid = getOrCreateUniqueID();
if (ads.mCause == SharedTypes::Legacy::ActorDamageCause::Fall) {
mFallHeightMap[uid.rawID] = getFallDistance();
logger->info("跌落高度为 {}", getFallDistance());
}
if (hasCategory(ActorCategory::Player) || isTame()) {
if (mLastHurtByMobTime != 0) {
auto hm = getLastHurtByMob();
mHurtByEntityMap[uid.rawID] = hm->getOrCreateUniqueID();
if (!getLastHurtByMob()->getNameTag().empty()) logger->info("伤害来源为 {}", getLastHurtByMob()->getNameTag());
logger->info("伤害来源为 {}", getLastHurtByMob()->getTypeName());
if (!getLastHurtByMob()->getCarriedItem().getCustomName().empty()) logger->info("伤害来源为 {}", getLastHurtByMob()->getCarriedItem().getCustomName());
}
}
origin(ads);
auto& executor = ll::thread::ThreadPoolExecutor::getDefault();
auto callback = executor.executeAfter(
[] {
mHurtByEntityMap.clear();
mFallHeightMap.clear();
},
ll::chrono::game::ticks(1)
);
}
using DeathMessageResult = std::pair<std::string, std::vector<std::string>>;
int mMaxCauseId = 34;
std::vector<std::pair<std::string, int>> mCustomCauseMap;
phmap::flat_hash_map<int, std::string_view> mVanillaCauseMessage;
phmap::flat_hash_map<SharedTypes::Legacy::ActorDamageCause, phmap::flat_hash_map<std::string_view, std::string_view>> mHardCodedDeathMessage;
bool isCrystal = false;
bool isCustomDefinition(int cause) {
if (cause >= 35) {
return true;
}
if (mVanillaCauseMessage.count(cause)) {
return true;
}
return false;
}
bool isCustomCauseExist(std::string const& causeName) {
for (auto& key : mCustomCauseMap) {
if (key.first == causeName) {
return true;
}
}
return false;
}
bool isCustomCauseExist(int cause) {
for (auto& key : mCustomCauseMap) {
if (key.second == cause) {
return true;
}
}
return false;
}
SharedTypes::Legacy::ActorDamageCause getCustomCause(std::string const& causeName) {
for (auto& key : mCustomCauseMap) {
if (key.first == causeName) {
return (SharedTypes::Legacy::ActorDamageCause)key.second;
}
}
return SharedTypes::Legacy::ActorDamageCause::None;
}
std::string getCustomCause(SharedTypes::Legacy::ActorDamageCause cause) {
for (auto& key : mCustomCauseMap) {
if ((SharedTypes::Legacy::ActorDamageCause)key.second == cause) {
return key.first;
}
}
return "none";
}
std::string getCause(SharedTypes::Legacy::ActorDamageCause cause) {
auto id = (int)cause;
if (isCustomCauseExist(id)) {
return getCustomCause(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 (isCustomDefinition(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 = "[" + 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", "");
}
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, isEscaping, true);
}
std::optional<DeathMessageResult> 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 (killer == nullptr && mHurtByEntityMap.count(uid)) {
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);
}
LL_AUTO_TYPE_INSTANCE_HOOK(
DeathMessageHook1,
HookPriority::Lowest,
ActorDamageSource,
&ActorDamageSource::$getDeathMessage,
DeathMessageResult,
std::string a1,
Actor* a2
) {
auto originl = origin(a1, a2);
logger->info("原消息name为 {}", a1);
logger->info("原消息为 {}", originl.first);
auto res = translateDeathMessage(originl, a1, a2, this);
return res;
}
LL_AUTO_TYPE_INSTANCE_HOOK(
DeathMessageHook2,
HookPriority::Lowest,
ActorDamageByActorSource,
&ActorDamageByActorSource::$getDeathMessage,
DeathMessageResult,
std::string a1,
Actor* a2
) {
auto originl = origin(a1, a2);
logger->info("原消息name为 {}", a1);
logger->info("原消息为 {}", originl.first);
auto res = translateDeathMessage(originl, a1, a2, this);
return res;
}
LL_AUTO_TYPE_INSTANCE_HOOK(
DeathMessageHook3,
HookPriority::Lowest,
ActorDamageByBlockSource,
&ActorDamageByBlockSource::$getDeathMessage,
DeathMessageResult,
std::string a1,
Actor* a2
) {
auto originl = origin(a1, a2);
logger->info("原消息name为 {}", a1);
logger->info("原消息为 {}", originl.first);
auto res = translateDeathMessage(originl, a1, a2, this);
return res;
}
LL_AUTO_TYPE_INSTANCE_HOOK(
DeathMessageHook4,
HookPriority::Lowest,
ActorDamageByChildActorSource,
&ActorDamageByChildActorSource::$getDeathMessage,
DeathMessageResult,
std::string a1,
Actor* a2
) {
auto originl = origin(a1, a2);
logger->info("原消息name为 {}", a1);
logger->info("原消息为 {}", originl.first);
auto res = translateDeathMessage(originl, a1, a2, this);
return res;
}
int getNextCauseId() {
mMaxCauseId++;
return mMaxCauseId;
}
bool registerDamageCause(std::string const& causeName) {
if (!isCustomCauseExist(causeName)) {
auto id = getNextCauseId();
mCustomCauseMap.push_back({causeName, id});
return true;
}
return false;
}
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;
}
void RegisterDamageDefinition() {
GMLIB::Mod::DamageCause::DamageCause::setCustomDamageCauseEnabled();
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Anvil, "anvil");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::EntityAttack, "mob");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::RamAttack, "mob");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Drowning, "drown");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::FallingBlock, "fallingBlock");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Fire, "inFire");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::FireTick, "onFire");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Fireworks, "fireworks");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::FlyIntoWall, "flyIntoWall");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Freezing, "freeze");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Lava, "lava");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Lightning, "lightningBolt");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Wither, "wither");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Magic, "indirectMagic");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Magma, "hotFloor");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Stalactite, "stalactite");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Stalagmite, "stalagmite");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Starve, "starve");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Suffocation, "inWall");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::SonicBoom, "sonicBoom");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Void, "outOfWorld");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::SelfDestruct, "genericKill");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Projectile, "thrown");
GMLIB::Mod::DamageCause::DamageCause::setVanillaCauseMessage(ActorDamageCause::Thorns, "thorns");
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
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"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.trident.item",
"minecraft:thrown_trident"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.spit",
"minecraft:llama_spit"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.bullet",
"minecraft:shulker_bullet"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.arrow.item",
"minecraft:arrow"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.explosion.player",
"minecraft:fireball"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Projectile,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Projectile,
"death.attack.mob",
"minecraft:breeze_wind_charge_projectile"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Magic,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Magic,
"death.attack.magic",
"empty"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::SonicBoom,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::SonicBoom,
"death.attack.sonicBoom",
"minecraft:warden"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::Thorns,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::Thorns,
"death.attack.generic",
"empty"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::EntityExplosion,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::EntityExplosion,
"death.attack.explosion.player",
"all"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::EntityExplosion,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::EntityExplosion,
"minecraft:wither_skull",
"death.attack.witherSkull.item"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::EntityExplosion,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::EntityExplosion,
"minecraft:wither_skull_dangerous",
"death.attack.witherSkull.item"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::EntityAttack,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::EntityAttack,
"minecraft:player",
"death.attack.player.item"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::EntityAttack,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::EntityAttack,
"minecraft:bee",
"death.attack.sting.item"
);
GMLIB::Mod::DamageCause::DamageCause::registerCustomDeathMessage(
ActorDamageCause::RamAttack,
registerCustomDeathMessage(
SharedTypes::Legacy::ActorDamageCause::RamAttack,
"minecraft:player",
"death.attack.player.item"
);
}
/*
void ListenEvents() {
auto& config = DeathMessages::Entry::getInstance().getConfig();
auto& eventBus = ll::event::EventBus::getInstance();
if (config.ConsoleLog.JoinMessage) {
eventBus.emplaceListener<ll::event::player::PlayerConnectEvent>([](ll::event::player::PlayerConnectEvent& ev) {
infoLogger->info(fmt::format(fg(fmt::color::yellow), tr("multiplayer.player.joined", {ev.self().getName()}))
infoLogger->info(fmt::format(fg(fmt::color::yellow), tr("multiplayer.player.joined", {ev.self().getRealName()}))
);
});
}
@@ -125,7 +555,7 @@ void ListenEvents() {
eventBus.emplaceListener<ll::event::player::PlayerDisconnectEvent>(
[](ll::event::player::PlayerDisconnectEvent& ev) {
infoLogger->info(
fmt::format(fg(fmt::color::yellow), tr("multiplayer.player.left", {ev.self().getName()}))
fmt::format(fg(fmt::color::yellow), tr("multiplayer.player.left", {ev.self().getRealName()}))
);
}
);
@@ -140,4 +570,4 @@ void ListenEvents() {
}
);
}
}
}*/
+22 -9
View File
@@ -1,6 +1,16 @@
#include "Entry.h"
#include "Global.h"
#include "Language.h"
#include "ll/api/mod/Mod.h"
#include "ll/api/Config.h"
#include "ll/api/io/PatternFormatter.h"
#include "ll/api/io/Logger.h"
#include "ll/api/io/LoggerRegistry.h"
#include "ll/api/io/FileSink.h"
#include "ll/api/mod/RegisterHelper.h"
#include "ll/api/data/IndirectValue.h"
#include "gmlib/gm/i18n/LangI18n.h"
#include "gmlib/gm/i18n/ResourceI18n.h"
ll::io::LoggerRegistry& loggerRegistry = ll::io::LoggerRegistry::getInstance();
std::shared_ptr<ll::io::Logger> logger = loggerRegistry.getOrCreate(MOD_NAME);
@@ -35,8 +45,8 @@ bool Entry::load() {
}
bool Entry::enable() {
RegisterDamageDefinition();
ListenEvents();
/* RegisterDamageDefinition();
ListenEvents();*/
return true;
}
@@ -51,10 +61,10 @@ bool Entry::unload() {
Config& Entry::getConfig() { return mConfig.value(); }
std::optional<GMLIB::Files::I18n::LangI18n> Entry::getI18n() { return mI18n; }
std::unique_ptr<gmlib::i18n::LangI18n> Entry::getI18n() { return std::move(mI18n); }
void Entry::loadI18n() {
mI18n.emplace(getSelf().getLangDir(), getConfig().ServerSideTranslation.Language);
mI18n= std::make_unique<gmlib::i18n::LangI18n>(getSelf().getLangDir(), getConfig().ServerSideTranslation.Language);
mI18n->updateOrCreateLanguage("en_US", en_US);
mI18n->updateOrCreateLanguage("zh_CN", zh_CN);
mI18n->loadAllLanguages();
@@ -62,8 +72,7 @@ void Entry::loadI18n() {
}
void Entry::loadResourcePack() {
GMLIB::Mod::VanillaFix::setFixI18nEnabled();
auto resource = GMLIB::Files::ResourceLanguage(getSelf().getModDir() / u8"resource", MOD_NAME, 0, 8, 0);
auto resource = gmlib::i18n::ResourceI18n(getSelf().getModDir() / u8"resource", MOD_NAME, 0, 8, 0);
resource.addLanguage("en_US", en_US);
resource.addLanguage("zh_CN", zh_CN);
}
@@ -72,9 +81,13 @@ void Entry::loadResourcePack() {
LL_REGISTER_MOD(DeathMessages::Entry, DeathMessages::Entry::getInstance());
std::string tr(std::string const& key, std::vector<std::string> const& params) {
/*std::string tr(std::string const& key, std::vector<std::string> const& params) {
if (auto i18n = DeathMessages::Entry::getInstance().getI18n()) {
return i18n->get(key, params);
}
return ::I18nAPI::get(key, params);
}
auto i18n = DeathMessages::Entry::getI18n();
return i18n->get(key, params);
}*/
+7 -2
View File
@@ -1,6 +1,11 @@
#pragma once
#include "Config.h"
#include "Global.h"
#include "ll/api/mod/Mod.h"
#include <ll/api/mod/NativeMod.h>
#include <gmlib/gm/i18n/LangI18n.h>
namespace DeathMessages {
@@ -27,7 +32,7 @@ public:
Config& getConfig();
std::optional<GMLIB::Files::I18n::LangI18n> getI18n();
std::unique_ptr<gmlib::i18n::LangI18n> getI18n();
void loadI18n();
@@ -36,7 +41,7 @@ public:
private:
ll::mod::NativeMod& mSelf;
std::optional<Config> mConfig;
std::optional<GMLIB::Files::I18n::LangI18n> mI18n;
std::unique_ptr<gmlib::i18n::LangI18n> mI18n;
};
} // namespace DeathMessages
+3 -3
View File
@@ -1,5 +1,5 @@
#pragma once
#include <include_all.h>
#include <ll/api/io/Logger.h>
#define MOD_NAME "DeathMessages"
@@ -7,7 +7,7 @@ extern std::shared_ptr<ll::io::Logger> logger;
extern std::shared_ptr<ll::io::Logger> deathLogger;
extern std::shared_ptr<ll::io::Logger> infoLogger;
extern std::string tr(std::string const& key, std::vector<std::string> const& data = {});
/*extern std::string tr(std::string const& key, std::vector<std::string> const& data = {});
extern void RegisterDamageDefinition();
extern void ListenEvents();
extern void ListenEvents();*/
+12 -37
View File
@@ -7,45 +7,20 @@ if not has_config("vs_runtime") then
set_runtimes("MD")
end
add_requires("levilamina 1.0.0")
add_requires("levibuildscript 0.3.0")
add_requires("gmlib 0.13.10")
add_requires("levilamina 26.10.5",{configs = {target_type = "server"}})
add_requires("levibuildscript")
add_requires("gmlib 26.10.0")
target("DeathMessages") -- Change this to your mod name.
add_cxflags(
"/EHa",
"/utf-8"
)
add_files(
"src/**.cpp"
)
add_includedirs(
"src"
)
add_packages(
"levilamina",
"gmlib"
)
add_defines(
"NOMINMAX",
"UNICODE",
"_HAS_CXX17",
"_HAS_CXX20",
"_HAS_CXX23"
)
add_rules("@levibuildscript/linkrule")
set_exceptions("none")
add_rules("@levibuildscript/modpacker")
add_cxflags( "/EHa", "/utf-8", "/W4", "/w44265", "/w44289", "/w44296", "/w45263", "/w44738", "/w45204")
add_defines("NOMINMAX", "UNICODE")
add_packages("levilamina","gmlib")
set_exceptions("none") -- To avoid conflicts with /EHa.
set_kind("shared")
set_languages("cxx20")
set_languages("c++23")
set_symbols("debug")
after_build(function (target)
local mod_packer = import("scripts.after_build")
local mod_define = {
modName = target:name(),
modFile = path.filename(target:targetfile()),
}
mod_packer.pack_mod(target,mod_define)
end)
add_headerfiles("src/**.h")
add_files("src/**.cpp")
add_includedirs("src")