Compare commits
2 Commits
8aaef54548
...
main
@@ -19,17 +19,26 @@ That allows players to freely switch languages on their own.
|
||||
|
||||
## Death Messages Translation
|
||||
|
||||
By default, this plugin uses resource packs for translation to ensure perfect compatibility with various addons. <br> `This requires ModAPI to be enabled.`
|
||||
### Resource Pack Translation
|
||||
By default, this plugin uses resource packs for translation to ensure perfect compatibility with various addons. <br>
|
||||
<br>(The plugin automatically builds the resource pack and sends it to players upon joining. Using resource pack-based translation is recommended.)
|
||||
>[!IMPORTANT]
|
||||
>If you wnt to use Resource Pack Translation<br>
|
||||
>This requires ModAPI to be enabled.<br>
|
||||
>You can configure language for console in `server.properties` like `language=en_US`
|
||||
### Server-Side Translation
|
||||
|
||||
If you prefer not to use resource packs, you can enable server-side translation in the configuration file.<br> This way, all translations are handled entirely on the server without requiring any client-side resource packs.
|
||||
|
||||
>[!IMPORTANT]
|
||||
>You can configure language for Server-Side Translation in `./plugins/DeathMessages/config/config.json` like `Language=en_US`
|
||||
#### For issues, please report them via GitHub Issues!!!
|
||||
#### Pull Requests are also welcome!
|
||||
|
||||
You can also customize death messages by editing the language files.<br>
|
||||
(The resource pack will be generated in the ./plugins/DeathMessages/log directory; feel free to modify it as needed.)
|
||||
<br> `This requires ModAPI to be enabled.`
|
||||
(The language files will be generated in the ./plugins/DeathMessages/lang directory; feel free to modify it as needed.)
|
||||
>[!WARNING]
|
||||
> DO NOT modify files in directory `./plugins/DeathMessages/resource`, unless you know what you are doing
|
||||
|
||||
High performance: Implemented using native functions with no additional data storage, resulting in minimal performance overhead.
|
||||
Uses native death message broadcasting, preserving the vanilla showdeathmessages game rule behavior.
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "${modName}",
|
||||
"entry": "${modFile}",
|
||||
"type": "native",
|
||||
"version": "0.14.0",
|
||||
"version": "0.14.1",
|
||||
"author": "GroupMountain",
|
||||
"description": "Better Death Messages",
|
||||
"dependencies": [
|
||||
|
||||
+14
-1
@@ -10,6 +10,8 @@
|
||||
#include "mc/world/actor/Mob.h"
|
||||
#include "mc/world/level/Level.h"
|
||||
|
||||
#include <gmlib/mc/locale/I18nAPI.h>
|
||||
|
||||
//===============GMLIB 0.13.5 ActorDamageCause.cc===============
|
||||
|
||||
phmap::flat_hash_map<int64, float> mFallHeightMap;
|
||||
@@ -83,10 +85,21 @@ DeathMessageResult makeDeathMessage(
|
||||
// 如果没有击杀者和试图逃离,那么不可能使用 .player 结尾
|
||||
ll::utils::string_utils::replaceAll(res.first, ".player", "");
|
||||
}
|
||||
|
||||
if (!DeathMessages::Entry::getInstance().isResourceI18nLoaded) {
|
||||
res.first=tr(res.first, res.second);
|
||||
auto translatedMessage=tr(res.first, res.second);
|
||||
res.first = translatedMessage;
|
||||
res.second = {};
|
||||
|
||||
|
||||
}
|
||||
auto& config = DeathMessages::Entry::getInstance().getConfig();
|
||||
|
||||
if (config.ConsoleLog.DeathMessage) {
|
||||
auto translatedMessage=tr(res.first, res.second);
|
||||
deathLogger->info(translatedMessage);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
// 未定义返回vanilla值
|
||||
|
||||
+50
-13
@@ -12,9 +12,12 @@
|
||||
#include "ll/api/mod/ModManagerRegistry.h"
|
||||
#include "ll/api/mod/RegisterHelper.h"
|
||||
#include "ll/api/service/Bedrock.h"
|
||||
#include "ll/api/io/FileUtils.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include "gmlib/gm/i18n/LangI18n.h"
|
||||
#include "gmlib/gm/i18n/ResourceI18n.h"
|
||||
#include "gmlib/mc/locale/I18nAPI.h"
|
||||
|
||||
ll::io::LoggerRegistry& loggerRegistry = ll::io::LoggerRegistry::getInstance();
|
||||
std::shared_ptr<ll::io::Logger> logger = loggerRegistry.getOrCreate(MOD_NAME);
|
||||
@@ -33,8 +36,13 @@ Entry& Entry::getInstance() {
|
||||
}
|
||||
|
||||
bool Entry::load() {
|
||||
isResourceI18nLoaded=false;
|
||||
|
||||
isResourceI18nLoaded=false;
|
||||
if (!ll::file_utils::readFile(getSelf().getLangDir() / u8"en_US.lang").has_value()) {
|
||||
ll::file_utils::writeFile(getSelf().getLangDir() / u8"en_US.lang", en_US);
|
||||
}
|
||||
if (!ll::file_utils::readFile(getSelf().getLangDir() / u8"zh_CN.lang").has_value()) {
|
||||
ll::file_utils::writeFile(getSelf().getLangDir() / u8"zh_CN.lang", zh_CN);
|
||||
}
|
||||
mConfig.emplace();
|
||||
if (!ll::config::loadConfig(*mConfig, getSelf().getConfigDir() / u8"config.json")) {
|
||||
ll::config::saveConfig(*mConfig, getSelf().getConfigDir() / u8"config.json");
|
||||
@@ -46,9 +54,11 @@ bool Entry::load() {
|
||||
ll::makePolymorphic<ll::io::PatternFormatter>("[{3:.3%F %T.} {2}][{1}] {0}", false);
|
||||
deathLogger->addSink(std::make_shared<ll::io::FileSink>(path, polymorphicFormatter));
|
||||
}
|
||||
loadI18n();
|
||||
if ((!getConfig().ServerSideTranslation.Enabled)&&ll::mod::ModManagerRegistry::getInstance().hasMod("ModAPI")) {
|
||||
loadResourcePack();
|
||||
}else {
|
||||
loadI18n();
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -82,19 +92,38 @@ gmlib::i18n::LangI18n& Entry::getI18n() {
|
||||
}
|
||||
|
||||
void Entry::loadI18n() {
|
||||
const std::string custom_zh_CN = ll::file_utils::readFile(
|
||||
getSelf().getLangDir() / u8"zh_CN.lang",
|
||||
false
|
||||
)
|
||||
.value_or(zh_CN);
|
||||
const std::string custom_en_US = ll::file_utils::readFile(
|
||||
getSelf().getLangDir() / u8"en_US.lang",
|
||||
false
|
||||
)
|
||||
.value_or(en_US);
|
||||
|
||||
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->updateOrCreateLanguage("en_US", custom_en_US);
|
||||
mI18n->updateOrCreateLanguage("zh_CN", custom_zh_CN);
|
||||
mI18n->loadAllLanguages();
|
||||
mI18n->setDefaultLanguage("zh_CN");
|
||||
mI18n->setDefaultLanguage(getConfig().ServerSideTranslation.Language);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Entry::loadResourcePack() {
|
||||
auto mResource = std::make_unique<gmlib::i18n::ResourceI18n>(getSelf().getModDir() / u8"lang", MOD_NAME, 0, 16, 1);
|
||||
mResource->addLanguage("en_US", en_US);
|
||||
mResource->addLanguage("zh_CN", zh_CN);
|
||||
if (
|
||||
ll::file_utils::readFile(getSelf().getLangDir() / u8"en_US.lang")!=
|
||||
ll::file_utils::readFile(getSelf().getModDir() / u8"resource/language_pack/texts/en_US.lang")
|
||||
||ll::file_utils::readFile(getSelf().getLangDir() / u8"zh_CN.lang")!=
|
||||
ll::file_utils::readFile(getSelf().getModDir() / u8"resource/language_pack/texts/zh_CN.lang")
|
||||
)
|
||||
std::filesystem::remove_all(getSelf().getModDir() / u8"resource");
|
||||
|
||||
auto mResource = std::make_unique<gmlib::i18n::ResourceI18n>(getSelf().getModDir() / u8"resource", MOD_NAME, 0, 16, 1);
|
||||
mResource->addLanguageFromPath("zh_CN",getSelf().getLangDir() / u8"zh_CN.lang");
|
||||
mResource->addLanguageFromPath("en_US",getSelf().getLangDir() / u8"en_US.lang");
|
||||
mResource->loadAllLanguages();
|
||||
isResourceI18nLoaded=true;
|
||||
}
|
||||
@@ -107,11 +136,19 @@ 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> params) {
|
||||
if (DeathMessages::Entry::getInstance().isResourceI18nLoaded) {
|
||||
return gmlib::I18nAPI::get(key, params);
|
||||
}
|
||||
auto& i18n = DeathMessages::Entry::getInstance().getI18n();
|
||||
return i18n.get(key, params);
|
||||
|
||||
|
||||
logger->info(DeathMessages::Entry::getInstance().isResourceI18nLoaded ? "ResourceI18nLoaded" : "LangI18nLoaded");
|
||||
if (params.size() > 1)
|
||||
params.at(1) = gmlib::I18nAPI::get(
|
||||
params.at(1),
|
||||
{},
|
||||
DeathMessages::Entry::getInstance().getConfig().ServerSideTranslation.Language
|
||||
);
|
||||
return i18n.get(key, params);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -17,4 +17,4 @@ extern bool isCrystal;
|
||||
using DeathMessageResult = std::pair<std::string, std::vector<std::string>>;
|
||||
|
||||
extern DeathMessageResult translateDeathMessage(DeathMessageResult origin, std::string name, Actor* dead, ActorDamageSource* ads);
|
||||
extern std::string tr(std::string const& key, std::vector<std::string> const& params = {});
|
||||
extern std::string tr(std::string const& key, std::vector<std::string> params = {});
|
||||
|
||||
+5
-5
@@ -87,8 +87,8 @@ LL_AUTO_TYPE_INSTANCE_HOOK(
|
||||
auto res = translateDeathMessage(originl, a1, a2, this);
|
||||
return res;
|
||||
}
|
||||
|
||||
LL_AUTO_TYPE_INSTANCE_HOOK(
|
||||
//
|
||||
/*LL_AUTO_TYPE_INSTANCE_HOOK(
|
||||
ActorDamageByActorHook,
|
||||
HookPriority::Lowest,
|
||||
ActorDamageByActorSource,
|
||||
@@ -128,13 +128,13 @@ LL_AUTO_TYPE_INSTANCE_HOOK(
|
||||
auto originl = origin(a1, a2);
|
||||
auto res = translateDeathMessage(originl, a1, a2, this);
|
||||
return res;
|
||||
}
|
||||
}*/
|
||||
|
||||
void uninstallHooks() {
|
||||
MobDieHook::unhook();
|
||||
CryatslHurtHook::unhook();
|
||||
ActorDamageHook::unhook();
|
||||
ActorDamageByActorHook::unhook();
|
||||
/*ActorDamageByActorHook::unhook();
|
||||
ActorDamageByBlockHook::unhook();
|
||||
ActorDamageByChildHook::unhook();
|
||||
ActorDamageByChildHook::unhook();*/
|
||||
}
|
||||
|
||||
+3
-11
@@ -8,7 +8,6 @@
|
||||
#include "ll/api/event/EventBus.h"
|
||||
|
||||
ll::event::ListenerPtr playerConnectEventListener;
|
||||
ll::event::ListenerPtr playerDieEventListener;
|
||||
ll::event::ListenerPtr playerDisconnectEventListener;
|
||||
void ListenEvents() {
|
||||
auto& config = DeathMessages::Entry::getInstance().getConfig();
|
||||
@@ -30,20 +29,13 @@ void ListenEvents() {
|
||||
}
|
||||
);
|
||||
}
|
||||
if (config.ConsoleLog.DeathMessage) {
|
||||
playerDieEventListener=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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//Die Message move to DeathMessage.cpp 93L
|
||||
|
||||
}
|
||||
|
||||
void uninstallEventListeners() {
|
||||
auto& eventBus = ll::event::EventBus::getInstance();
|
||||
eventBus.removeListener(playerDieEventListener);
|
||||
eventBus.removeListener(playerConnectEventListener);
|
||||
eventBus.removeListener(playerDisconnectEventListener);
|
||||
}
|
||||
@@ -4,3 +4,4 @@
|
||||
#define LL_MEMORY_OPERATORS
|
||||
|
||||
#include "ll/api/memory/MemoryOperators.h" // IWYU pragma: keep
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"format_version": 3,
|
||||
"format_uuid": "289f771f-2c9a-4d73-9f3f-8492495a924d",
|
||||
"tooth": "github.com/GroupMountain/DeathMessages",
|
||||
"version": "0.14.0",
|
||||
"version": "0.14.1",
|
||||
"info": {
|
||||
"name": "DeathMessages",
|
||||
"description": "Better Death Messages on MCBE",
|
||||
|
||||
Reference in New Issue
Block a user