mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-05 03:43:40 +00:00
354 lines
11 KiB
C++
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);
|
|
}
|