diff --git a/src/ll/api/Logger.cpp b/src/ll/api/Logger.cpp index 3b335ae6f7..99f9d335a1 100644 --- a/src/ll/api/Logger.cpp +++ b/src/ll/api/Logger.cpp @@ -36,7 +36,7 @@ void Logger::OutputStream::print(std::string_view s) const noexcept { if (!ll::globalConfig.logger.colorLog) { str = removeEscapeCode(str); } - fmt::print("{}\r\n", str); + fmt::print("{}\n", str); } if (logger->getFile().is_open() && checkLogLevel(logger->fileLevel, level)) { logger->getFile() << removeEscapeCode(fmt::format( @@ -65,12 +65,12 @@ void Logger::OutputStream::print(std::string_view s) const noexcept { } catch (...) { try { fmt::print( - "\x1b[31mERROR IN LOGGER API:\r\n{}\x1b[0m\r\n", + "\x1b[31mERROR IN LOGGER API:\n{}\x1b[0m\n", error_info::makeExceptionString(std::current_exception()) ); } catch (...) { try { - fmt::print("\x1b[31mUNKNOWN ERROR IN LOGGER API\x1b[0m\r\n"); + fmt::print("\x1b[31mUNKNOWN ERROR IN LOGGER API\x1b[0m\n"); } catch (...) {} } } diff --git a/src/ll/api/base/ErrorInfo.cpp b/src/ll/api/base/ErrorInfo.cpp index 811809461a..ec1d4ac574 100644 --- a/src/ll/api/base/ErrorInfo.cpp +++ b/src/ll/api/base/ErrorInfo.cpp @@ -33,9 +33,9 @@ struct u8system_category : public std::_System_error_category { std::string res{string_utils::str2str({msg._Str, msg._Length})}; if (res.ends_with('\n')) { res.pop_back(); - } - if (res.ends_with('\r')) { - res.pop_back(); + if (res.ends_with('\r')) { + res.pop_back(); + } } return string_utils::replaceAll(res, "\r\n", ", "); } @@ -51,20 +51,25 @@ std::error_category const& u8system_category() noexcept { struct ntstatus_category : public std::error_category { constexpr ntstatus_category() noexcept : error_category() {} [[nodiscard]] std::string message(int errCode) const override { - wchar_t* msg = nullptr; - DWORD langId; - if (GetLocaleInfoEx( - LOCALE_NAME_SYSTEM_DEFAULT, - LOCALE_SNAME | LOCALE_RETURN_NUMBER, - reinterpret_cast(&langId), - sizeof(langId) / sizeof(wchar_t) - ) - == 0) { - langId = 0; - } - auto size = FormatMessageW( + static DWORD langId = [] { + DWORD res; + if (GetLocaleInfoEx( + LOCALE_NAME_SYSTEM_DEFAULT, + LOCALE_SNAME | LOCALE_RETURN_NUMBER, + reinterpret_cast(&res), + sizeof(res) / sizeof(wchar_t) + ) + == 0) { + res = 0; + } + return res; + }(); + static auto nt = GetModuleHandleW(L"ntdll"); + + wchar_t* msg = nullptr; + auto size = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, - GetModuleHandleW(L"ntdll"), + nt, errCode, langId, (wchar_t*)&msg, @@ -76,9 +81,9 @@ struct ntstatus_category : public std::error_category { LocalFree(msg); if (res.ends_with('\n')) { res.pop_back(); - } - if (res.ends_with('\r')) { - res.pop_back(); + if (res.ends_with('\r')) { + res.pop_back(); + } } return string_utils::replaceAll(res, "\r\n", ", "); } diff --git a/src/ll/api/memory/Hook.cpp b/src/ll/api/memory/Hook.cpp index 1117c42f02..6b91f6bedb 100644 --- a/src/ll/api/memory/Hook.cpp +++ b/src/ll/api/memory/Hook.cpp @@ -4,13 +4,19 @@ #include "ll/api/memory/Memory.h" +#include "ll/api/thread/GlobalThreadPauser.h" + namespace ll::memory { int hook(FuncPtr target, FuncPtr detour, FuncPtr* originalFunc, HookPriority priority) { + auto pause = ll::thread::GlobalThreadPauser{}; return pl::hook::pl_hook(target, detour, originalFunc, static_cast(priority)); } -bool unhook(FuncPtr target, FuncPtr detour) { return pl::hook::pl_unhook(target, detour); } +bool unhook(FuncPtr target, FuncPtr detour) { + auto pause = ll::thread::GlobalThreadPauser{}; + return pl::hook::pl_unhook(target, detour); +} FuncPtr resolveIdentifier(char const* identifier) { auto p = resolveSymbol(identifier); diff --git a/src/ll/api/memory/Hook.h b/src/ll/api/memory/Hook.h index c3b8623da9..0ba6afa0f7 100644 --- a/src/ll/api/memory/Hook.h +++ b/src/ll/api/memory/Hook.h @@ -15,22 +15,22 @@ try { \ static FuncPtr t = ll::memory::resolveIdentifier(IDENTIFIER); \ if (t == nullptr) { \ - fmt::print("\x1b[91mCan't resolve: [" #IDENTIFIER "]\x1b[0m\r\n"); \ + fmt::print("\x1b[91mCan't resolve: [" #IDENTIFIER "]\x1b[0m\n"); \ } else { \ auto symbols = ll::memory::lookupSymbol(t); \ if (symbols.size() > 1) { \ fmt::print( \ - "\x1b[93m[" #IDENTIFIER "] has {} matches, probability cause bugs.\x1b[0m\r\n", \ + "\x1b[93m[" #IDENTIFIER "] has {} matches, probability cause bugs.\x1b[0m\n", \ symbols.size() \ ); \ } \ - fmt::print("\x1b[96m v resolve [" #IDENTIFIER "] to:\x1b[0m\r\n"); \ + fmt::print("\x1b[96m v resolve [" #IDENTIFIER "] to:\x1b[0m\n"); \ for (auto& str : symbols) { \ - fmt::print(" {} {}\r\n", (&str == &symbols.back()) ? '-' : '|', str); \ + fmt::print(" {} {}\n", (&str == &symbols.back()) ? '-' : '|', str); \ } \ } \ } catch (...) { \ - fmt::print("\x1b[91m!!! Exception in resolve: [" #IDENTIFIER "]\x1b[0m\r\n"); \ + fmt::print("\x1b[91m!!! Exception in resolve: [" #IDENTIFIER "]\x1b[0m\n"); \ } \ return 0; \ }; \ diff --git a/src/ll/api/schedule/Scheduler.h b/src/ll/api/schedule/Scheduler.h index 1191589db3..ee097c8827 100644 --- a/src/ll/api/schedule/Scheduler.h +++ b/src/ll/api/schedule/Scheduler.h @@ -26,7 +26,7 @@ struct SleeperType { using Type = ll::chrono::TickSyncSleep; }; -template ::Type> +template ::Type, class Pool = ll::thread::ThreadPool> class Scheduler; using GameTickScheduler = Scheduler; @@ -34,7 +34,7 @@ using GameTimeScheduler = Scheduler; using SystemTimeScheduler = Scheduler; -template +template class Scheduler { private: using TimePoint = typename Clock::time_point; @@ -42,11 +42,11 @@ class Scheduler { using TaskPtr = std::shared_ptr>; using TaskType = std::multimap; - TaskType tasks; - std::atomic done; - std::mutex mutex; - Sleeper sleeper; - ll::thread::ThreadPool threads; + TaskType tasks; + std::atomic done; + std::mutex mutex; + Sleeper sleeper; + Pool threads; std::weak_ptr> addTask(TaskPtr t) { std::weak_ptr> res = t; diff --git a/src/ll/api/thread/GlobalThreadPauser.cpp b/src/ll/api/thread/GlobalThreadPauser.cpp new file mode 100644 index 0000000000..675775a1e8 --- /dev/null +++ b/src/ll/api/thread/GlobalThreadPauser.cpp @@ -0,0 +1,48 @@ +#include "ll/api/thread/GlobalThreadPauser.h" + +#include "ll/api/base/ErrorInfo.h" + +#include "windows.h" + +#include "tlhelp32.h" + +namespace ll::thread { +GlobalThreadPauser::GlobalThreadPauser() { + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (h == INVALID_HANDLE_VALUE) { + throw error_info::getWinLastError(); + } + static auto processId = GetCurrentProcessId(); + auto threadId = GetCurrentThreadId(); + + THREADENTRY32 te; + te.dwSize = sizeof(te); + if (Thread32First(h, &te)) { + do { + if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) { + // Suspend all threads EXCEPT the one we want to keep running + if (te.th32OwnerProcessID == processId && te.th32ThreadID != threadId) { + HANDLE thread = OpenThread(THREAD_ALL_ACCESS, false, te.th32ThreadID); + if (thread != nullptr) { + SuspendThread(thread); + CloseHandle(thread); + pausedIds.emplace_back(te.th32ThreadID); + } + } + } + te.dwSize = sizeof(te); + } while (Thread32Next(h, &te)); + } + CloseHandle(h); +} +GlobalThreadPauser::~GlobalThreadPauser() { + for (auto id : pausedIds) { + HANDLE thread = OpenThread(THREAD_ALL_ACCESS, false, id); + if (thread != nullptr) { + ResumeThread(thread); + CloseHandle(thread); + } + } +} + +} // namespace ll::thread diff --git a/src/ll/api/thread/GlobalThreadPauser.h b/src/ll/api/thread/GlobalThreadPauser.h new file mode 100644 index 0000000000..f470577c4a --- /dev/null +++ b/src/ll/api/thread/GlobalThreadPauser.h @@ -0,0 +1,15 @@ +#pragma once + +#include "ll/api/base/Macro.h" +#include "ll/api/base/StdInt.h" +#include + +namespace ll::thread { +class GlobalThreadPauser { + std::vector pausedIds; + +public: + LLNDAPI GlobalThreadPauser(); + LLNDAPI ~GlobalThreadPauser(); +}; +} // namespace ll::thread diff --git a/src/ll/core/form/FormHandler.cpp b/src/ll/core/form/FormHandler.cpp index 66626ab06c..56fda2aad8 100644 --- a/src/ll/core/form/FormHandler.cpp +++ b/src/ll/core/form/FormHandler.cpp @@ -113,6 +113,9 @@ LL_AUTO_TYPED_INSTANCE_HOOK( data = modalPacket.mJSONResponse.value().toStyledString(); if (data.ends_with('\n')) { data.pop_back(); + if (data.ends_with('\r')) { + data.pop_back(); + } } } diff --git a/src/ll/core/tweak/ModifyInfomation.cpp b/src/ll/core/tweak/ModifyInfomation.cpp index 963d442eea..79f04af1ce 100644 --- a/src/ll/core/tweak/ModifyInfomation.cpp +++ b/src/ll/core/tweak/ModifyInfomation.cpp @@ -111,6 +111,9 @@ LL_AUTO_STATIC_HOOK( while (std::getline(iss, line)) { if (line.ends_with('\n')) { line.pop_back(); + if (line.ends_with('\r')) { + line.pop_back(); + } } if (!serverStarted) tryModifyServerStartInfo(line); diff --git a/src/ll/test/ScheduleTest.cpp b/src/ll/test/ScheduleTest.cpp index 61f05e4d62..079cc6c217 100644 --- a/src/ll/test/ScheduleTest.cpp +++ b/src/ll/test/ScheduleTest.cpp @@ -6,6 +6,8 @@ #include "mc/server/ServerLevel.h" #include "mc/world/events/ServerInstanceEventCoordinator.h" +// #include "ll/api/thread/GlobalThreadPauser.h" + using namespace ll::schedule; using namespace ll::chrono_literals; @@ -65,6 +67,19 @@ LL_AUTO_TYPED_INSTANCE_HOOK( throw std::runtime_error("I'm a error from schedule Task!"); }); + // s2.add(0.3min, [&] { + // auto pause = ll::thread::GlobalThreadPauser{}; + + // schedulelogger.info("hello I paused all threads 1s"); + + // std::this_thread::sleep_for(1s); + // schedulelogger.info("hello I paused all threads 2s"); + + // std::this_thread::sleep_for(1s); + + // schedulelogger.info("hello I resumed all threads"); + // }); + return origin(ins); }