reflect : format code
This commit is contained in:
+3
-1
@@ -8,7 +8,9 @@
|
|||||||
"dependencies": [
|
"dependencies": [
|
||||||
{
|
{
|
||||||
"name": "GMLIB"
|
"name": "GMLIB"
|
||||||
},
|
}
|
||||||
|
],
|
||||||
|
"optionalDependencies": [
|
||||||
{
|
{
|
||||||
"name": "ModAPI"
|
"name": "ModAPI"
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-238
@@ -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};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
+34
-19
@@ -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() {
|
||||||
|
if (!ll::mod::ModManagerRegistry::getInstance().hasMod("ModAPI")) {
|
||||||
|
getSelf().getLogger().warn(tr("plugin.deathmessages.modapi.warn"));
|
||||||
|
}
|
||||||
RegisterDamageDefinition();
|
RegisterDamageDefinition();
|
||||||
/* ListenEvents();*/
|
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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user