LiteLoaderBDS-1.16.40/LiteLoader/Main/LiteLoader.cpp

354 lines
11 KiB
C++

#include <windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
#include <string>
#include <iostream>
#include <LoggerAPI.h>
#include <Utils/StringHelper.h>
#include <Utils/FileHelper.h>
#include <seh_exception/seh_exception.hpp>
#include <ServerAPI.h>
#include <HookAPI.h>
#include "Config.h"
#include "Loader.h"
#include "CrashLogger.h"
#include "AddonsHelper.h"
#include <EventAPI.h>
#include "Version.h"
#include "MC/Minecraft.hpp"
#include <csignal>
using namespace std;
Logger logger("LiteLoader");
time_t startTime;
time_t endTime;
// Add plugins folder to path
void FixPluginsLibDir() {
auto buffer = new WCHAR[8192];
auto sz = GetEnvironmentVariableW(TEXT("PATH"), buffer, 8192);
std::wstring PATH{buffer, sz};
sz = GetCurrentDirectoryW(8192, buffer);
std::wstring CWD{buffer, sz};
SetEnvironmentVariableW(TEXT("PATH"), (CWD + L"\\plugins;" + PATH).c_str());
delete[] buffer;
}
void FixUpCWD() {
string buf;
buf.assign(8192, '\0');
GetModuleFileNameA(nullptr, buf.data(), 8192);
buf = buf.substr(0, buf.find_last_of('\\'));
SetCurrentDirectoryA(buf.c_str());
}
#include <FMT/format.h>
void UnzipNodeModules() {
if (std::filesystem::exists(std::filesystem::path(TEXT(".\\plugins\\lib\\node_modules.tar")))) {
std::error_code ec;
//if(std::filesystem::exists(".\\plugins\\lib\\node_modules\\"))
// filesystem::remove_all(".\\plugins\\lib\\node_modules\\", ec);
auto res = NewProcessSync(fmt::format("{} x \"{}\" -o\".\\plugins\\lib\\\" -aoa", ZIP_PROGRAM_PATH, ".\\plugins\\lib\\node_modules.tar"), 30000);
if (res.first != 0) {
logger.error(tr("ll.unzipNodeModules.fail"));
} else {
filesystem::remove(".\\plugins\\lib\\node_modules.tar", ec);
}
}
}
void DecompressResourcePacks() {
if (std::filesystem::exists(std::filesystem::path(TEXT(".\\plugins\\LiteLoader\\ResourcePacks\\LiteLoaderBDS-CUI.tar")))) {
std::error_code ec;
// if(std::filesystem::exists(".\\plugins\\lib\\node_modules\\"))
// filesystem::remove_all(".\\plugins\\lib\\node_modules\\", ec);
auto res = NewProcessSync(fmt::format("{} x \"{}\" -o\".\\plugins\\LiteLoader\\ResourcePacks\\\" -aoa", ZIP_PROGRAM_PATH, ".\\plugins\\LiteLoader\\ResourcePacks\\LiteLoaderBDS-CUI.tar"), 30000);
if (res.first != 0) {
logger.error(tr("ll.decompressResourcePacks.fail"));
} else {
filesystem::remove(".\\plugins\\LiteLoader\\ResourcePacks\\LiteLoaderBDS-CUI.tar", ec);
}
}
}
void CheckRunningBDS() {
if (!LL::globalConfig.enableCheckRunningBDS)
return;
std::vector<DWORD> pids;
PROCESSENTRY32 pe32{};
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return;
bool res = Process32First(hProcessSnap, &pe32); // Start traversing
while (res) {
std::wstring name = pe32.szExeFile;
auto pid = pe32.th32ProcessID;
if (_getpid() != pid && (name == L"bedrock_server.exe" || name == L"bedrock_server_mod.exe")) {
pids.push_back(pid);
}
res = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
// Get current process path
WCHAR buf[8196] = {0};
auto sz = GetModuleFileName(nullptr, buf, 8196);
std::wstring current{buf, sz}; // Copy
// Check the BDS process paths
for (auto& pid : pids) {
WCHAR buf[8196] = {0};
// Open process handle
auto handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, pid);
if (handle) {
DWORD sz = NULL;
WCHAR buf[8196] = {0};
// Get the full path of the process
if (sz = GetModuleFileNameEx(handle, nullptr, buf, 8196)) {
std::wstring path{buf, sz};
if (current == path) {
logger.error(tr("ll.main.checkRunningBDS.detected"));
logger.error(tr("ll.main.checkRunningBDS.tip"));
logger.error(tr("ll.main.checkRunningBDS.ask", pid));
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y') {
// auto cmd = "taskkill /F /PID " + std::to_string(pid);
// system(cmd.c_str());
TerminateProcess(handle, 1);
}
}
}
CloseHandle(handle);
}
}
}
void FixAllowList() {
// 这个应该不必改吧?以后也许会同步
// if (filesystem::exists("whitelist.json")) {
// if (filesystem::exists("allowlist.json")) {
// auto res = ReadAllFile("allowlist.json");
// if (res && (res->empty() || nlohmann::json::parse(*res, nullptr, true, true).empty())) {
// logger.warn(tr("ll.main.fixAllowList.removeEmptyAllowlist"));
// filesystem::remove("allowlist.json");
// } else {
// logger.warn(tr("ll.main.fixAllowList.checkManually"));
// return;
// }
// }
// std::error_code ec;
// // Rename whitelist.json to allowlist.json
// filesystem::copy_file("whitelist.json", "allowlist.json", filesystem::copy_options::overwrite_existing, ec);
// filesystem::remove("whitelist.json", ec);
// logger.warn(tr("ll.main.fixAllowList.renamed"));
// }
}
extern void RegisterCommands();
extern bool InitPlayerDatabase();
extern void RegisterSimpleServerLogger();
void Welcome() {
if (!LL::globalConfig.enableWelcomeText)
return;
cout << "\r"
<< R"( )" << endl
<< "\r"
<< R"( _ _ _ _ _ )" << endl
<< "\r"
<< R"( | | (_) |_ ___| | ___ __ _ __| | ___ _ __ )" << endl
<< "\r"
<< R"( | | | | __/ _ \ | / _ \ / _` |/ _` |/ _ \ '__| )" << endl
<< "\r"
<< R"( | |___| | || __/ |__| (_) | (_| | (_| | __/ | )" << endl
<< "\r"
<< R"( |_____|_|\__\___|_____\___/ \__,_|\__,_|\___|_| )" << endl
<< "\r"
<< R"( )" << endl
<< "\r"
<< R"( -------- Light-Weight BDS Plugin Loader ---------- )" << endl
<< "\r"
<< R"( )" << endl;
}
void CheckDevMode() {
if (LL::globalConfig.debugMode)
logger.warn(tr("ll.main.warning.inDevMode"));
}
void CheckBetaVersion() {
if (LITELOADER_VERSION_STATUS != LL::Version::Release) {
logger.warn(tr("ll.main.warning.betaVersion"));
logger.warn(tr("ll.main.warning.productionEnv"));
}
}
void CheckProtocolVersion() {
auto currentProtocol = LL::getServerProtocolVersion();
if (TARGET_BDS_PROTOCOL_VERSION != currentProtocol) {
logger.warn(tr("ll.main.warning.protocolVersionNotMatch.1"), TARGET_BDS_PROTOCOL_VERSION, currentProtocol);
logger.warn(tr("ll.main.warning.protocolVersionNotMatch.2"));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
//BOOL WINAPI ConsoleExitHandler(DWORD CEvent) {
// switch (CEvent) {
// case CTRL_C_EVENT:
// case CTRL_CLOSE_EVENT:
// case CTRL_SHUTDOWN_EVENT: {
// if (Global<Minecraft>) {
// Global<Minecraft>->requestServerShutdown();
// } else {
// std::terminate();
// }
// return TRUE;
// }
// }
// return FALSE;
//}
//void UnixSignalHandler(int signum) {
// switch (signum) {
// case SIGINT:
// case SIGTERM: {
// if (Global<Minecraft>) {
// Global<Minecraft>->requestServerShutdown();
// } else {
// std::terminate();
// }
// }
// }
//}
// extern
extern void EndScheduleSystem();
namespace bstats {
void registerBStats();
}
void LLMain() {
// Set global SEH-Exception handler
auto oldSeTranslator = _set_se_translator(seh_exception::TranslateSEHtoCE);
// Prohibit pop-up windows to facilitate automatic restart
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOALIGNMENTFAULTEXCEPT);
// Disable Output-Sync
std::ios::sync_with_stdio(false);
// Create Plugin Directory
std::error_code ec;
std::filesystem::create_directories("plugins", ec);
// I18n
auto i18n = Translation::load("plugins/LiteLoader/LangPack/");
// Load Config
LL::LoadLLConfig();
//Unzip packed Node Modules
UnzipNodeModules();
//Decompress resource packs
DecompressResourcePacks();
// If SEH Protection is not enabled (Debug mode), restore old SE translator
if (!LL::isDebugMode())
_set_se_translator(oldSeTranslator);
// Update default language
if (i18n && LL::globalConfig.language != "system") {
i18n->defaultLocaleName = LL::globalConfig.language;
}
// Check Protocol Version
CheckProtocolVersion();
// Fix problems
FixUpCWD();
FixPluginsLibDir();
// Check whether allowlist.json exists/is empty or not
//FixAllowList();
// Init LL Logger
Logger::setDefaultFile("logs/LiteLoader-latest.log", false);
// Check Running BDS(Requires Config)
CheckRunningBDS();
// Builtin CrashLogger
LL::InitCrashLogger(LL::globalConfig.enableCrashLogger);
// Initialize Player Database
InitPlayerDatabase();
// Rename Window
HWND hwnd = GetConsoleWindow();
std::wstring s = L"Bedrock Dedicated Server " + str2wstr(LL::getBdsVersion().substr(1));
SetWindowText(hwnd, s.c_str());
// Register Exit Event Handler.
// SetConsoleCtrlHandler(ConsoleExitHandler, TRUE);
// signal(SIGTERM, UnixSignalHandler);
// signal(SIGINT, UnixSignalHandler);
// Welcome
Welcome();
// DebugMode
CheckDevMode();
// Addon Helper
// if (LL::globalConfig.enableAddonsHelper) {
// InitAddonsHelper();
// }
// Load plugins
LL::LoadMain();
// Register built-in commands
RegisterCommands();
// Register simple server logger
RegisterSimpleServerLogger();
// Register BStats
bstats::registerBStats();
// Register Started
Event::ServerStartedEvent::subscribe([](Event::ServerStartedEvent) {
logger.info(tr("ll.notice.license", "LGPLv3"));
logger.info(tr("ll.notice.newForum", "https://forum.litebds.com"));
logger.info(tr("ll.notice.translateText", "https://crowdin.com/project/liteloaderbds"));
logger.info("Thanks to RhyMC(rhymc.com) for the support");
return true;
});
// Register Cleanup
Event::ServerStoppedEvent::subscribe([](Event::ServerStoppedEvent) {
EndScheduleSystem();
return true;
});
}
// Call LLMain
THook(int, "main", int a, void* b) {
startTime = clock();
char** str = static_cast<char**>(b);
for (int i = 0; i < a; ++i) {
if (strcmp(str[i], "--noColor") == 0) {
LL::commandLineOption.noColorOption = true;
break;
}
}
LLMain();
return original(a, b);
}