reflect : format code

This commit is contained in:
2026-06-21 07:05:59 +08:00
Unverified
parent e475259310
commit edbec18b0b
9 changed files with 291 additions and 264 deletions
+3 -1
View File
@@ -8,7 +8,9 @@
"dependencies": [ "dependencies": [
{ {
"name": "GMLIB" "name": "GMLIB"
}, }
],
"optionalDependencies": [
{ {
"name": "ModAPI" "name": "ModAPI"
} }
+16 -238
View File
@@ -1,120 +1,34 @@
#include "Entry.h" #include "Entry.h"
#include "ll/api/event/player/PlayerConnectEvent.h"
#include "ll/api/event/player/PlayerDisconnectEvent.h"
#include "ll/api/memory/Hook.h" #include "ll/api/memory/Hook.h"
#include "ll/api/chrono/GameChrono.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/Mob.h"
#include "mc/world/actor/ActorDamageSource.h" #include "mc/world/actor/ActorDamageSource.h"
#include "mc/world/actor/ActorDamageByActorSource.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 "ll/api/service/Bedrock.h"
#include "mc/world/level/Level.h" #include "mc/world/level/Level.h"
#include "mc/world/actor/monster/EnderCrystal.h"
#include "mc/world/actor/ActorHurtResult.h"
#include "mc/world/actor/Actor.h" #include "mc/world/actor/Actor.h"
phmap::flat_hash_map<int64, float> mFallHeightMap; phmap::flat_hash_map<int64, float> mFallHeightMap;
phmap::flat_hash_map<int64, ActorUniqueID> mHurtByEntityMap; 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; std::vector<std::pair<std::string, int>> mCustomCauseMap;
phmap::flat_hash_map<int, std::string_view> mVanillaCauseMessage; 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; phmap::flat_hash_map<SharedTypes::Legacy::ActorDamageCause, phmap::flat_hash_map<std::string_view, std::string_view>> mHardCodedDeathMessage;
bool isCrystal = false; 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) { std::string getCause(SharedTypes::Legacy::ActorDamageCause cause) {
auto id = (int)cause; auto id = (int)cause;
if (isCustomCauseExist(id)) { for (auto& key : mCustomCauseMap) {
return getCustomCause(cause); if (key.second == id) {
for (auto& key1 : mCustomCauseMap) {
if ((SharedTypes::Legacy::ActorDamageCause)key1.second == cause) {
return key1.first;
}
}
return "none";
}
} }
if (mVanillaCauseMessage.count(id)) { if (mVanillaCauseMessage.count(id)) {
return std::string(mVanillaCauseMessage[id]); return std::string(mVanillaCauseMessage[id]);
@@ -151,7 +65,7 @@ DeathMessageResult makeDeathMessage(
bool isHardCodedMessage = false bool isHardCodedMessage = false
) { ) {
// 自定义类型构造 // 自定义类型构造
if (isCustomDefinition(cause) || isHardCodedMessage) { if (cause >= 35||mVanillaCauseMessage.count(cause) || isHardCodedMessage) {
std::string msg = "death.attack.damageCause.item"; std::string msg = "death.attack.damageCause.item";
ll::utils::string_utils::replaceAll(msg, "damageCause", getCause(SharedTypes::Legacy::ActorDamageCause(cause))); ll::utils::string_utils::replaceAll(msg, "damageCause", getCause(SharedTypes::Legacy::ActorDamageCause(cause)));
if (isHardCodedMessage) { if (isHardCodedMessage) {
@@ -186,6 +100,10 @@ DeathMessageResult makeDeathMessage(
// 如果没有击杀者和试图逃离,那么不可能使用 .player 结尾 // 如果没有击杀者和试图逃离,那么不可能使用 .player 结尾
ll::utils::string_utils::replaceAll(res.first, ".player", ""); ll::utils::string_utils::replaceAll(res.first, ".player", "");
} }
if (!DeathMessages::Entry::getInstance().isResourceI18nLoaded) {
res.first=tr(res.first, res.second);
res.second = {};
}
return res; return res;
} }
// 未定义返回vanilla值 // 未定义返回vanilla值
@@ -328,116 +246,6 @@ DeathMessageResult translateDeathMessage(DeathMessageResult origin, std::string
return makeDeathMessage((int)damageCause, origin, name, killer, weaponName, isEscaping); return makeDeathMessage((int)damageCause, origin, name, killer, weaponName, isEscaping);
} }
LL_AUTO_TYPE_INSTANCE_HOOK(
CryatslHurtHook,
HookPriority::Normal,
EnderCrystal,
&EnderCrystal::$_hurt,
::ActorHurtResult,
ActorDamageSource const& a1,
float a2,
bool a3,
bool a4
) {
auto res = origin(a1, a2, a3, a4);
isCrystal = true;
auto& executor = ll::thread::ThreadPoolExecutor::getDefault();
auto callback = executor.executeAfter(
[] {
isCrystal = false;
},
ll::chrono::game::ticks(1)
);
return res;
}
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) { bool setVanillaCauseMessage(SharedTypes::Legacy::ActorDamageCause cause, std::string_view msg) {
auto id = (int)cause; auto id = (int)cause;
if (!mVanillaCauseMessage.count(id)) { if (!mVanillaCauseMessage.count(id)) {
@@ -566,33 +374,3 @@ void RegisterDamageDefinition() {
"death.attack.player.item" "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().getRealName()}))
);
});
}
if (config.ConsoleLog.LeftMessage) {
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().getRealName()}))
);
}
);
}
if (config.ConsoleLog.DeathMessage) {
eventBus.emplaceListener<GMLIB::Event::EntityEvent::DeathMessageAfterEvent>(
[](GMLIB::Event::EntityEvent::DeathMessageAfterEvent& ev) {
auto msg = ev.getDeathMessage();
auto info = tr(msg.first, msg.second);
deathLogger->info(info);
ev.getDeathMessage() = {info, msg.second};
}
);
}
}*/
+35 -20
View File
@@ -11,6 +11,8 @@
#include "ll/api/data/IndirectValue.h" #include "ll/api/data/IndirectValue.h"
#include "gmlib/gm/i18n/LangI18n.h" #include "gmlib/gm/i18n/LangI18n.h"
#include "gmlib/gm/i18n/ResourceI18n.h" #include "gmlib/gm/i18n/ResourceI18n.h"
#include "ll/api/mod/ModManagerRegistry.h"
#include <ll/api/service/Bedrock.h>
ll::io::LoggerRegistry& loggerRegistry = ll::io::LoggerRegistry::getInstance(); ll::io::LoggerRegistry& loggerRegistry = ll::io::LoggerRegistry::getInstance();
std::shared_ptr<ll::io::Logger> logger = loggerRegistry.getOrCreate(MOD_NAME); std::shared_ptr<ll::io::Logger> logger = loggerRegistry.getOrCreate(MOD_NAME);
@@ -26,27 +28,32 @@ Entry& Entry::getInstance() {
} }
bool Entry::load() { bool Entry::load() {
isResourceI18nLoaded=false;
mConfig.emplace(); mConfig.emplace();
if (!ll::config::loadConfig(*mConfig, getSelf().getConfigDir() / u8"config.json")) { if (!ll::config::loadConfig(*mConfig, getSelf().getConfigDir() / u8"config.json")) {
ll::config::saveConfig(*mConfig, getSelf().getConfigDir() / u8"config.json"); ll::config::saveConfig(*mConfig, getSelf().getConfigDir() / u8"config.json");
} }
if (getConfig().ServerSideTranslation.Enabled) {
loadI18n();
} else {
loadResourcePack();
}
if (getConfig().FileLog.Enabled) { if (getConfig().FileLog.Enabled) {
auto& path = getConfig().FileLog.Path; auto& path = getConfig().FileLog.Path;
ll::Polymorphic<ll::io::PatternFormatter> polymorphicFormatter = ll::Polymorphic<ll::io::PatternFormatter> polymorphicFormatter =
ll::makePolymorphic<ll::io::PatternFormatter>("[{3:.3%F %T.} {2}][{1}] {0}", false); ll::makePolymorphic<ll::io::PatternFormatter>("[{3:.3%F %T.} {2}][{1}] {0}", false);
deathLogger->addSink(std::make_shared<ll::io::FileSink>(path, polymorphicFormatter)); deathLogger->addSink(std::make_shared<ll::io::FileSink>(path, polymorphicFormatter));
} }
loadI18n();
if ((!getConfig().ServerSideTranslation.Enabled)&&ll::mod::ModManagerRegistry::getInstance().hasMod("ModAPI")) {
loadResourcePack();
}
return true; return true;
} }
bool Entry::enable() { bool Entry::enable() {
RegisterDamageDefinition(); if (!ll::mod::ModManagerRegistry::getInstance().hasMod("ModAPI")) {
/* ListenEvents();*/ getSelf().getLogger().warn(tr("plugin.deathmessages.modapi.warn"));
}
RegisterDamageDefinition();
ListenEvents();
return true; return true;
} }
@@ -55,13 +62,16 @@ bool Entry::disable() { return true; }
bool Entry::unload() { bool Entry::unload() {
mConfig.reset(); mConfig.reset();
mI18n.reset(); mI18n.reset();
uninstallHooks();
// getInstance().reset(); // getInstance().reset();
return true; return true;
} }
Config& Entry::getConfig() { return mConfig.value(); } Config& Entry::getConfig() { return mConfig.value(); }
std::unique_ptr<gmlib::i18n::LangI18n> Entry::getI18n() { return std::move(mI18n); } gmlib::i18n::LangI18n& Entry::getI18n() {
return *mI18n;
}
void Entry::loadI18n() { void Entry::loadI18n() {
mI18n= std::make_unique<gmlib::i18n::LangI18n>(getSelf().getLangDir(), getConfig().ServerSideTranslation.Language); mI18n= std::make_unique<gmlib::i18n::LangI18n>(getSelf().getLangDir(), getConfig().ServerSideTranslation.Language);
@@ -71,24 +81,29 @@ void Entry::loadI18n() {
mI18n->setDefaultLanguage("zh_CN"); mI18n->setDefaultLanguage("zh_CN");
} }
void Entry::loadResourcePack() { void Entry::loadResourcePack() {
auto resource = gmlib::i18n::ResourceI18n{getSelf().getModDir() / u8"lang", MOD_NAME, 0, 8, 0}; auto mResource = std::make_unique<gmlib::i18n::ResourceI18n>(getSelf().getModDir() / u8"lang", MOD_NAME, 0, 16, 0);
resource.addLanguage("en_US", en_US); mResource->addLanguage("en_US", en_US);
resource.addLanguage("zh_CN", zh_CN); mResource->addLanguage("zh_CN", zh_CN);
resource.loadAllLanguages(); mResource->loadAllLanguages();
isResourceI18nLoaded=true;
} }
} // namespace DeathMessages } // namespace DeathMessages
LL_REGISTER_MOD(DeathMessages::Entry, DeathMessages::Entry::getInstance()); 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()) { auto& i18n = DeathMessages::Entry::getInstance().getI18n();
return i18n->get(key, params); return i18n.get(key, params);
}
auto i18n = DeathMessages::Entry::getI18n();
return i18n->get(key, params);
}*/ return key;
}
+3 -1
View File
@@ -32,12 +32,14 @@ public:
Config& getConfig(); Config& getConfig();
std::unique_ptr<gmlib::i18n::LangI18n> getI18n(); gmlib::i18n::LangI18n& getI18n();
void loadI18n(); void loadI18n();
void loadResourcePack(); void loadResourcePack();
bool isResourceI18nLoaded;
private: private:
ll::mod::NativeMod& mSelf; ll::mod::NativeMod& mSelf;
std::optional<Config> mConfig; std::optional<Config> mConfig;
+15 -4
View File
@@ -1,15 +1,26 @@
#pragma once #pragma once
#include <ll/api/io/Logger.h> #include <ll/api/io/Logger.h>
#include <mc/legacy/ActorUniqueID.h>
#include <mc/world/actor/ActorDamageSource.h>
#include <parallel_hashmap/phmap.h>
#include "ll/api/i18n/I18n.h"
#define MOD_NAME "DeathMessages" #define MOD_NAME "DeathMessages"
extern std::shared_ptr<ll::io::Logger> logger; extern std::shared_ptr<ll::io::Logger> logger;
extern std::shared_ptr<ll::io::Logger> deathLogger; extern std::shared_ptr<ll::io::Logger> deathLogger;
extern std::shared_ptr<ll::io::Logger> infoLogger; extern std::shared_ptr<ll::io::Logger> infoLogger;
extern phmap::flat_hash_map<int64, float> mFallHeightMap;
extern phmap::flat_hash_map<int64, ActorUniqueID> mHurtByEntityMap;
extern bool isCrystal;
using DeathMessageResult = std::pair<std::string, std::vector<std::string>>;
using namespace ll::i18n_literals;
extern DeathMessageResult translateDeathMessage(DeathMessageResult origin, std::string name, Actor* dead, ActorDamageSource* ads);
extern void uninstallHooks();
extern void RegisterDamageDefinition(); extern void RegisterDamageDefinition();
/*
*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& params = {});
*extern void ListenEvents();*/ extern void ListenEvents();
+161
View File
@@ -0,0 +1,161 @@
#include "Entry.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 "mc/world/actor/monster/EnderCrystal.h"
#include "mc/world/actor/ActorHurtResult.h"
#include "Global.h"
#include "mc/world/actor/Actor.h"
#include "Hooks.h"
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)
);
}
LL_AUTO_TYPE_INSTANCE_HOOK(
CryatslHurtHook,
HookPriority::Normal,
EnderCrystal,
&EnderCrystal::$_hurt,
::ActorHurtResult,
ActorDamageSource const& a1,
float a2,
bool a3,
bool a4
) {
auto res = origin(a1, a2, a3, a4);
isCrystal = true;
auto& executor = ll::thread::ThreadPoolExecutor::getDefault();
auto callback = executor.executeAfter(
[] {
isCrystal = false;
},
ll::chrono::game::ticks(1)
);
return res;
}
LL_AUTO_TYPE_INSTANCE_HOOK(
ActorDamageHook,
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(
ActorDamageByActorHook,
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(
ActorDamageByBlockHook,
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(
ActorDamageByChildHook,
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;
}
void uninstallHooks() {
MobDieHook::unhook();
CryatslHurtHook::unhook();
ActorDamageHook::unhook();
ActorDamageByActorHook::unhook();
ActorDamageByBlockHook::unhook();
ActorDamageByChildHook::unhook();
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
namespace DeathMessages {
/**
* @brief Removes all installed memory hooks.
*
* This function uninstalls all previously installed hooks to restore
* original behavior.
*/
void uninstallHooks();
} // namespace DeathMessages
+2
View File
@@ -250,6 +250,7 @@ entity.breeze.name=Breeze
entity.creaking.name=Creaking entity.creaking.name=Creaking
multiplayer.player.joined=%s joined the game multiplayer.player.joined=%s joined the game
multiplayer.player.left=%s left the game multiplayer.player.left=%s left the game
plugin.deathmessages.modapi.warn=The plugin ModAPI is not loaded, so client-side translation is unavailable. Only server-side translation can be used.
)"; )";
std::string zh_CN = R"( std::string zh_CN = R"(
@@ -503,4 +504,5 @@ entity.breeze.name=旋风人
entity.creaking.name= entity.creaking.name=
multiplayer.player.joined=%s multiplayer.player.joined=%s
multiplayer.player.left=%s 退 multiplayer.player.left=%s 退
plugin.deathmessages.modapi.warn=ModAPI没有被加载使
)"; )";
+39
View File
@@ -0,0 +1,39 @@
#include "Entry.h"
#include "Global.h"
#include "ll/api/event/player/PlayerConnectEvent.h"
#include "ll/api/event/EventBus.h"
#include "ll/api/event/player/PlayerDieEvent.h"
#include "ll/api/event/player/PlayerDisconnectEvent.h"
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), fmt::runtime(tr("multiplayer.player.joined", {ev.self().getRealName()})))
);
});
}
if (config.ConsoleLog.LeftMessage) {
eventBus.emplaceListener<ll::event::player::PlayerDisconnectEvent>(
[](ll::event::player::PlayerDisconnectEvent& ev) {
infoLogger->info(
fmt::format(fg(fmt::color::yellow), fmt::runtime(tr("multiplayer.player.left", {ev.self().getRealName()})))
);
}
);
}
if (config.ConsoleLog.DeathMessage) {
eventBus.emplaceListener<ll::event::player::PlayerDieEvent>(
[](ll::event::player::PlayerDieEvent& ev) {
auto [key, params] = ev.source().getDeathMessage(ev.self().getRealName(), &ev.self());
auto info = tr(key, params);
deathLogger->info(info);
}
);
}
}