diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 722d901702..560e4937ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,12 @@ jobs: # with: # xmake-version: branch@master + - uses: matbour/setup-sentry-cli@v1 + with: + token: ${{ SECRETS.SENTRY_TOKEN }} + organization: ${{ SECRETS.SENTRY_ORG }} + project: ${{ SECRETS.SENTRY_PROJECT }} + - uses: actions/cache@v4 with: path: | @@ -58,7 +64,10 @@ jobs: xmake f -a x64 -m ${{ matrix.mode }} -p windows -v -y --target_type=${{ matrix.target_type }} --tests=${{ matrix.tests }} - run: | - xmake -v -w -y + xmake -v -y + + - run: | + sentry-cli debug-files upload --include-sources bin/LeviLamina - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7fc6db0613..a65cba2d58 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,12 @@ jobs: # with: # xmake-version: branch@master + - uses: matbour/setup-sentry-cli@v1 + with: + token: ${{ SECRETS.SENTRY_TOKEN }} + organization: ${{ SECRETS.SENTRY_ORG }} + project: ${{ SECRETS.SENTRY_PROJECT }} + - uses: actions/cache@v4 with: path: | @@ -35,10 +41,13 @@ jobs: xmake repo -u - run: | - xmake f -a x64 -m ${{ matrix.mode }} -p windows -v -y + xmake f -a x64 -m ${{ matrix.mode }} -p windows -v -y --publish=y + + - run: | + xmake -v -y - run: | - xmake -v -w -y + sentry-cli debug-files upload --include-sources bin/LeviLamina # - run: | # xmake package -v -y diff --git a/manifest.json b/manifest.json index 7ea95c5517..dfdc61e845 100644 --- a/manifest.json +++ b/manifest.json @@ -2,5 +2,7 @@ "name": "${modName}", "entry": "${modFile}", "version": "${modVersion}", - "type": "preload-native" + "type": "preload-native", + "sentry-dsn": "https://43a888504c33385bfd2e570c9ac939aa@o4508652421906432.ingest.us.sentry.io/4508652563398656", + "sentry-force-upload": true } \ No newline at end of file diff --git a/src-client/ll/core/gui/ImGuiAnsiColor.cpp b/src-client/ll/core/gui/ImGuiAnsiColor.cpp index 1eff6bfef8..422308795e 100644 --- a/src-client/ll/core/gui/ImGuiAnsiColor.cpp +++ b/src-client/ll/core/gui/ImGuiAnsiColor.cpp @@ -43,7 +43,7 @@ static constexpr uint colors256[] = { 0xffd0d0d0, 0xffdadada, 0xffe4e4e4, 0xffeeeeee }; -bool parseColor(const char* s, ImU32* col, int* skipChars) { +bool parseColor(char const* s, ImU32* col, int* skipChars) { if (s[0] != '\033' || s[1] != '[') { return false; } @@ -60,7 +60,7 @@ bool parseColor(const char* s, ImU32* col, int* skipChars) { return true; } - const char* seqEnd = &s[2]; + char const* seqEnd = &s[2]; while (*seqEnd != 'm') { seqEnd++; } @@ -69,7 +69,7 @@ bool parseColor(const char* s, ImU32* col, int* skipChars) { std::string colorStr; char colorArgsType = 0; std::vector colorArgs; - for (const auto& el : string_utils::splitByPattern(seq, ";")) { + for (auto const& el : string_utils::splitByPattern(seq, ";")) { if (colorStr.empty()) { if (el.size() == 2 && el[0] == '3') { // 30-39 colorStr = el; @@ -133,14 +133,14 @@ bool parseColor(const char* s, ImU32* col, int* skipChars) { } void ImFont_RenderAnsiText( - const ImFont* font, + ImFont const* font, ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, - const ImVec4& clip_rect, - const char* text_begin, - const char* text_end, + ImVec4 const& clip_rect, + char const* text_begin, + char const* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false ) { @@ -159,13 +159,13 @@ void ImFont_RenderAnsiText( const float scale = size / font->FontSize; const float line_height = font->FontSize * scale; const bool word_wrap_enabled = (wrap_width > 0.0f); - const char* word_wrap_eol = nullptr; + char const* word_wrap_eol = nullptr; // Fast-forward to first visible line - const char* s = text_begin; + char const* s = text_begin; if (y + line_height < clip_rect.y && !word_wrap_enabled) while (y + line_height < clip_rect.y && s < text_end) { - s = (const char*)memchr(s, '\n', text_end - s); + s = (char const*)memchr(s, '\n', text_end - s); s = s ? s + 1 : text_end; y += line_height; } @@ -174,10 +174,10 @@ void ImFont_RenderAnsiText( // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer // without a newline will likely crash atm) if (text_end - s > 10000 && !word_wrap_enabled) { - const char* s_end = s; + char const* s_end = s; float y_end = y; while (y_end < clip_rect.w && s_end < text_end) { - s_end = (const char*)memchr(s_end, '\n', text_end - s_end); + s_end = (char const*)memchr(s_end, '\n', text_end - s_end); s = s ? s + 1 : text_end; y_end += line_height; } @@ -200,7 +200,7 @@ void ImFont_RenderAnsiText( { int index = 0; int skipChars = 0; - const char* sLocal = s; + char const* sLocal = s; ImU32 temp_col = col; while (sLocal < text_end) { if (sLocal <= text_end - 4 && parseColor(sLocal, &temp_col, &skipChars)) { @@ -219,7 +219,7 @@ void ImFont_RenderAnsiText( } - const char* s1 = s; + char const* s1 = s; while (s < text_end) { if (char_skip[s - s1]) { s++; @@ -278,7 +278,7 @@ void ImFont_RenderAnsiText( } float char_width = 0.0f; - if (const ImFontGlyph* glyph = font->FindGlyph((ImWchar)c)) { + if (ImFontGlyph const* glyph = font->FindGlyph((ImWchar)c)) { char_width = glyph->AdvanceX * scale; // Arbitrarily assume that both space and tabs are empty glyphs as an optimization @@ -373,14 +373,14 @@ void ImFont_RenderAnsiText( void ImDrawList_AddAnsiText( ImDrawList* drawList, - const ImFont* font, + ImFont const* font, float font_size, - const ImVec2& pos, + ImVec2 const& pos, ImU32 col, - const char* text_begin, - const char* text_end = nullptr, + char const* text_begin, + char const* text_end = nullptr, float wrap_width = 0.0f, - const ImVec4* cpu_fine_clip_rect = nullptr + ImVec4 const* cpu_fine_clip_rect = nullptr ) { if ((col & IM_COL32_A_MASK) == 0) return; @@ -417,12 +417,12 @@ void ImDrawList_AddAnsiText( ); } -void RenderAnsiText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) { +void RenderAnsiText(ImVec2 pos, char const* text, char const* text_end, bool hide_text_after_hash) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Hide anything after a '##' string - const char* text_display_end; + char const* text_display_end; if (hide_text_after_hash) { text_display_end = FindRenderedTextEnd(text, text_end); } else { @@ -443,7 +443,7 @@ void RenderAnsiText(ImVec2 pos, const char* text, const char* text_end, bool hid } } -void RenderAnsiTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) { +void RenderAnsiTextWrapped(ImVec2 pos, char const* text, char const* text_end, float wrap_width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -470,7 +470,7 @@ void textAnsiUnformatted(std::string_view view) { ImGuiContext& g = *GImGui; IM_ASSERT(text != nullptr); - const char* text_begin = text; + char const* text_begin = text; const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); const float wrap_pos_x = window->DC.TextWrapPos; @@ -484,7 +484,7 @@ void textAnsiUnformatted(std::string_view view) { // because we are likely the biggest and only item on the line. // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster // than a casually written loop. - const char* line = text; + char const* line = text; const float line_height = GetTextLineHeight(); const ImRect clip_rect = window->ClipRect; ImVec2 text_size(0, 0); @@ -498,7 +498,7 @@ void textAnsiUnformatted(std::string_view view) { if (lines_skippable > 0) { int lines_skipped = 0; while (line < text_end && lines_skipped < lines_skippable) { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + char const* line_end = (char const*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; line = line_end + 1; lines_skipped++; @@ -513,7 +513,7 @@ void textAnsiUnformatted(std::string_view view) { while (line < text_end) { if (IsClippedEx(line_rect, 0)) break; - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + char const* line_end = (char const*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; const ImVec2 line_size = CalcTextSize(line, line_end, false); text_size.x = ImMax(text_size.x, line_size.x); @@ -527,7 +527,7 @@ void textAnsiUnformatted(std::string_view view) { // Count remaining lines int lines_skipped = 0; while (line < text_end) { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + char const* line_end = (char const*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; line = line_end + 1; lines_skipped++; diff --git a/src-client/ll/core/gui/ImGuiHooks.h b/src-client/ll/core/gui/ImGuiHooks.h index ce18aa8bf8..c04b702047 100644 --- a/src-client/ll/core/gui/ImGuiHooks.h +++ b/src-client/ll/core/gui/ImGuiHooks.h @@ -4,6 +4,6 @@ namespace ll::gui { void init(); -const std::string& getGPUName(); -const std::string& getRendererType(); +std::string const& getGPUName(); +std::string const& getRendererType(); } // namespace ll::gui diff --git a/src-client/ll/core/gui/win/GUI.cpp b/src-client/ll/core/gui/win/GUI.cpp index 33f0ee47dc..abd4e11c4e 100644 --- a/src-client/ll/core/gui/win/GUI.cpp +++ b/src-client/ll/core/gui/win/GUI.cpp @@ -31,7 +31,7 @@ class LogWindow { bool autoScroll = true; public: - LogWindow(const std::string& title) : title(title) { clear(); } + LogWindow(std::string const& title) : title(title) { clear(); } void clear() { buf.clear(); @@ -39,7 +39,7 @@ class LogWindow { lineOffsets.push_back(0); } - void addLog(const std::string& log) { + void addLog(std::string const& log) { if (log.empty()) { return; } @@ -80,14 +80,14 @@ class LogWindow { ImGui::LogToClipboard(); } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - const char* bufBegin = this->buf.begin(); - const char* bufEnd = this->buf.end(); + char const* bufBegin = this->buf.begin(); + char const* bufEnd = this->buf.end(); if (filter.IsActive()) { // Don't use the clipper when Filter is enabled because we don't have random access // to the result of the filter for (int lineNum = 0; lineNum < lineOffsets.size(); lineNum++) { - const char* lineStart = bufBegin + lineOffsets[lineNum]; - const char* lineEnd = + char const* lineStart = bufBegin + lineOffsets[lineNum]; + char const* lineEnd = (lineNum + 1 < lineOffsets.size()) ? (bufBegin + lineOffsets[lineNum + 1] - 1) : bufEnd; if (filter.PassFilter(lineStart, lineEnd)) { textAnsiUnformatted({lineStart, lineEnd}); @@ -99,8 +99,8 @@ class LogWindow { clipper.Begin((int)lineOffsets.size()); while (clipper.Step()) { for (int lineNum = clipper.DisplayStart; lineNum < clipper.DisplayEnd; lineNum++) { - const char* lineStart = bufBegin + lineOffsets[lineNum]; - const char* lineEnd = + char const* lineStart = bufBegin + lineOffsets[lineNum]; + char const* lineEnd = (lineNum + 1 < lineOffsets.size()) ? (bufBegin + lineOffsets[lineNum + 1] - 1) : bufEnd; textAnsiUnformatted({lineStart, lineEnd}); } diff --git a/src-client/ll/core/gui/win/ImGuiHooks.cpp b/src-client/ll/core/gui/win/ImGuiHooks.cpp index b5e68c688c..4f970c842e 100644 --- a/src-client/ll/core/gui/win/ImGuiHooks.cpp +++ b/src-client/ll/core/gui/win/ImGuiHooks.cpp @@ -39,7 +39,7 @@ typedef HRESULT(STDMETHODCALLTYPE* PFN_IDXGIFactory2_CreateSwapChainForCoreWindo /* [annotation][in] */ _In_ IUnknown* pWindow, /* [annotation][in] */ - _In_ const DXGI_SWAP_CHAIN_DESC1* pDesc, + _In_ DXGI_SWAP_CHAIN_DESC1 const* pDesc, /* [annotation][in] */ _In_opt_ IDXGIOutput* pRestrictToOutput, /* [annotation][out] */ @@ -70,9 +70,9 @@ static uint64_t gpuVideoMemory; static uint32_t gpuVendorID; static uint32_t gpuDeviceID; -const std::string& getGPUName() { return gpuName; } +std::string const& getGPUName() { return gpuName; } -const std::string& getRendererType() { return rendererType; } +std::string const& getRendererType() { return rendererType; } static void replaceVtable(void* vptr, size_t index, void** outOldFunc, void* newFunc) { void** ptr = (void**)vptr; @@ -394,7 +394,7 @@ HRESULT STDMETHODCALLTYPE IDXGIFactory2_CreateSwapChainForC IDXGIFactory2* This, IUnknown* pDevice, IUnknown* pWindow, - const DXGI_SWAP_CHAIN_DESC1* pDesc, + DXGI_SWAP_CHAIN_DESC1 const* pDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain ) { diff --git a/src-server/ll/api/form/CustomForm.cpp b/src-server/ll/api/form/CustomForm.cpp index c09b63f999..b97b116dfa 100644 --- a/src-server/ll/api/form/CustomForm.cpp +++ b/src-server/ll/api/form/CustomForm.cpp @@ -252,7 +252,7 @@ class CustomForm::CustomFormImpl : public FormImpl { void setTitle(std::string const& title) { mTitle = title; } - void append(const std::shared_ptr& element) { mElements.push_back(element); } + void append(std::shared_ptr const& element) { mElements.push_back(element); } void sendTo(Player& player, Callback callback) { uint id = handler::addFormHandler(std::make_unique(std::move(callback), mElements)); diff --git a/src-server/ll/core/Statistics.cpp b/src-server/ll/core/Statistics.cpp index 58c997ade0..7eb1537f26 100644 --- a/src-server/ll/core/Statistics.cpp +++ b/src-server/ll/core/Statistics.cpp @@ -129,31 +129,11 @@ struct Statistics::Impl { } Impl() { - namespace fs = std::filesystem; - - auto& dataDir = getSelfModIns()->getDataDir(); - - if (!fs::exists(dataDir)) { - fs::create_directory(dataDir); - } - auto uuidPath = dataDir / u8"statisticsUuid"; - if (!fs::exists(uuidPath)) { - std::string uuid = mce::UUID::random().asString(); - json["serverUUID"] = uuid; - file_utils::writeFile(uuidPath, uuid); - } else { - auto uuidFile = file_utils::readFile(uuidPath); - if (uuidFile.has_value()) { - json["serverUUID"] = uuidFile.value(); - } else { - std::string uuid = mce::UUID::random().asString(); - file_utils::writeFile(uuidPath, uuid); - } - } - json["osName"] = sys_utils::isWine() ? "Linux(wine)" : "Windows"; - json["osArch"] = "amd64"; - json["osVersion"] = ""; - json["coreCount"] = std::thread::hardware_concurrency(); + json["serverUUID"] = getServiceUuid(); + json["osName"] = sys_utils::isWine() ? "Linux(wine)" : "Windows"; + json["osArch"] = "amd64"; + json["osVersion"] = ""; + json["coreCount"] = std::thread::hardware_concurrency(); coro::keepThis([&]() -> coro::CoroTask<> { co_await (1.0min * random_utils::rand(3.0, 6.0)); diff --git a/src-server/ll/core/form/FormHandler.cpp b/src-server/ll/core/form/FormHandler.cpp index 04d33fece2..697e9753d1 100644 --- a/src-server/ll/core/form/FormHandler.cpp +++ b/src-server/ll/core/form/FormHandler.cpp @@ -22,16 +22,16 @@ namespace ll::form::handler { -nlohmann::ordered_json jsonCppValueToNlohmannOrderedJson(const Json::Value& value) { +nlohmann::ordered_json jsonCppValueToNlohmannOrderedJson(Json::Value const& value) { if (value.isObject()) { nlohmann::ordered_json result = nlohmann::ordered_json::object(); - for (const auto& key : value.getMemberNames()) { + for (auto const& key : value.getMemberNames()) { result[key] = jsonCppValueToNlohmannOrderedJson(value[key]); } return result; } else if (value.isArray()) { nlohmann::ordered_json result = nlohmann::ordered_json::array(); - for (const auto& item : value) { + for (auto const& item : value) { result.push_back(jsonCppValueToNlohmannOrderedJson(item)); } return result; diff --git a/src-test/server/FormTest.cpp b/src-test/server/FormTest.cpp index 237740e4b3..4fbb006642 100644 --- a/src-test/server/FormTest.cpp +++ b/src-test/server/FormTest.cpp @@ -50,7 +50,7 @@ void registerFormTestCommand() { return; } for (auto [name, result] : *data) { - static auto logDebugResult = [&](const ll::form::CustomFormElementResult& var) { + static auto logDebugResult = [&](ll::form::CustomFormElementResult const& var) { if (std::holds_alternative(var)) { logptr->info("CustomForm callback {} = {}", name, std::get(var)); } else if (std::holds_alternative(var)) { diff --git a/src-test/server/TestMolang.cpp b/src-test/server/TestMolang.cpp index 92ebe0a292..36258b2d11 100644 --- a/src-test/server/TestMolang.cpp +++ b/src-test/server/TestMolang.cpp @@ -29,7 +29,7 @@ LL_AUTO_TYPE_INSTANCE_HOOK( ExpressionNode::registerQueryFunction( "query.is_levilamina", - [&](RenderParams&, const std::vector&) -> MolangScriptArg const& { + [&](RenderParams&, std::vector const&) -> MolangScriptArg const& { static auto v = MolangScriptArg(true); return v; }, @@ -42,7 +42,7 @@ LL_AUTO_TYPE_INSTANCE_HOOK( ); ExpressionNode::registerQueryFunction( "query.homo_number", - [&](RenderParams&, const std::vector&) -> MolangScriptArg const& { + [&](RenderParams&, std::vector const&) -> MolangScriptArg const& { static auto v = MolangScriptArg(114514); return v; }, diff --git a/src-test/server/customWorldGenerator/FlatWorldGeneratorOptions.json b/src-test/server/customWorldGenerator/FlatWorldGeneratorOptions.json deleted file mode 100644 index 5b61d7cc59..0000000000 --- a/src-test/server/customWorldGenerator/FlatWorldGeneratorOptions.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "biome_id": 192, - "world_version": "version.post_1_18", - "block_layers": [ - { - "block_name": "minecraft:air", - "count": 64 - }, - { - "block_name": "minecraft:bedrock", - "count": 1 - }, - { - "block_name": "minecraft:cherry_log", - "count": 2 - }, - { - "block_name": "minecraft:cherry_leaves", - "count": 1 - } - ], - "encoding_version": 6, - "structure_options": null -} \ No newline at end of file diff --git a/src-test/server/customWorldGenerator/McClassMembersTests/FeatureMembersTest.cpp b/src-test/server/customWorldGenerator/McClassMembersTests/FeatureMembersTest.cpp deleted file mode 100644 index 418f321e63..0000000000 --- a/src-test/server/customWorldGenerator/McClassMembersTests/FeatureMembersTest.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "ll/api/io/Logger.h" -#include "ll/api/memory/Hook.h" -#include "ll/core/LeviLamina.h" -#include "magic_enum/magic_enum.hpp" -#include "mc/util/Random.h" -#include "mc/util/WorldChangeTransaction.h" -#include "mc/world/level/BlockPos.h" -#include "mc/world/level/BlockSource.h" -#include "mc/world/level/block/Block.h" -#include "mc/world/level/levelgen/structure/StructureStart.h" - -/* -LL_AUTO_TYPE_INSTANCE_HOOK( - StructureStartHook, - ll::memory::HookPriority::Normal, - StructureStart, - &StructureStart::calculateBoundingBox, - void -) { - origin(); - - ll::getLogger().debug("calculateBoundingBox"); - ll::getLogger().debug("StructureStart:"); - ll::getLogger().debug("mChunkX={}", this->mChunkX); - ll::getLogger().debug("mChunkZ={}", this->mChunkZ); - unhook(); -} - -LL_AUTO_TYPE_INSTANCE_HOOK( - WorldChangeTransactionHook, - ll::memory::HookPriority::Normal, - WorldChangeTransaction, - &WorldChangeTransaction::apply, - bool -) { - bool rtv = origin(); - - ll::getLogger().debug("{}<-calculateBoundingBox", rtv); - ll::getLogger().debug("WorldChangeTransaction:"); - for (auto& v : this->mData->mChanges) { - ll::getLogger().debug( - "mData->mChanges[{},{{{},{},{}}}]", - v.first.toString(), - v.second.mUpdateFlags, - v.second.mOldBlock->getName().getString(), - v.second.mNewBlock->getName().getString() - ); - } - - return rtv; -} -*/ diff --git a/src-test/server/customWorldGenerator/McClassMembersTests/FlatWorldGeneratorOptionsMembersTest.cpp b/src-test/server/customWorldGenerator/McClassMembersTests/FlatWorldGeneratorOptionsMembersTest.cpp deleted file mode 100644 index 8f702ef09c..0000000000 --- a/src-test/server/customWorldGenerator/McClassMembersTests/FlatWorldGeneratorOptionsMembersTest.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ll/api/io/Logger.h" -#include "ll/api/memory/Hook.h" -#include "ll/core/LeviLamina.h" -#include "mc/world/level/levelgen/flat/FlatWorldGenerator.h" -#include "mc/world/level/levelgen/flat/FlatWorldGeneratorOptions.h" - -// LL_AUTO_TYPE_INSTANCE_HOOK( -// FlatWorldGeneratorGeneratePrototypeBlockValuesHook, -// ll::memory::HookPriority::Normal, -// FlatWorldGenerator, -// &FlatWorldGenerator::_generatePrototypeBlockValues, -// void, -// FlatWorldGeneratorOptions const& flatWorldGeneratorOptions, -// short s -//) { -// -// origin(flatWorldGeneratorOptions, s); -// -// ll::getLogger().warn("FlatWorldGeneratorGeneratePrototypeBlockValuesHook"); -// ll::getLogger().warn("flatWorldGeneratorOptions.mEncodingVersion={}", -// flatWorldGeneratorOptions.mEncodingVersion); ll::getLogger().warn("flatWorldGeneratorOptions.mWorldVersion={}", -// (int)flatWorldGeneratorOptions.mWorldVersion); ll::getLogger().warn( -// "flatWorldGeneratorOptions.mStructureOptions={}", -// flatWorldGeneratorOptions.mStructureOptions.toStyledString() -// ); -// } diff --git a/src-test/server/customWorldGenerator/MyWorldGenerator.cpp b/src-test/server/customWorldGenerator/MyWorldGenerator.cpp deleted file mode 100644 index 3c317278f8..0000000000 --- a/src-test/server/customWorldGenerator/MyWorldGenerator.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -// #pragma once -// -// #include "ll/api/utils/RandomUtils.h" -// -// #include "ll/api/io/Logger.h" -// #include "ll/api/memory/Hook.h" -// #include "ll/api/memory/Memory.h" -// #include "ll/api/service/Bedrock.h" -// #include "ll/core/LeviLamina.h" -// #include "mc/deps/game_refs/WeakRef.h" -// #include "mc/deps/core/utility/optional_ref.h" -// #include "mc/deps/core/common/bedrock/Intrusive.h" -// #include "mc/deps/core/data/DividedPos2d.h" -// #include "mc/deps/core/debug/log/ContentLog.h" -// #include "mc/deps/core/mce/Math.h" -// #include "mc/deps/core/string/HashedString.h" -// #include "mc/deps/core/utility/buffer_span.h" -// #include "mc/deps/json/Reader.h" -// #include "mc/deps/json/Value.h" -// #include "mc/deps/json/Writer.h" -// #include "mc/entity/systems/common/BiomeSurfaceSystem.h" -// #include "mc/server/commands/CommandOutput.h" -// #include "mc/util/Random.h" -// #include "mc/util/random/XoroshiroPositionalRandomFactory.h" -// #include "mc/world/actor/player/Player.h" -// #include "mc/world/level/BlockPalette.h" -// #include "mc/world/level/BlockSource.h" -// #include "mc/world/level/BlockTickingQueue.h" -// #include "mc/world/level/BlockVolumeTarget.h" -// #include "mc/world/level/ChunkBlockPos.h" -// #include "mc/world/level/ChunkPos.h" -// #include "mc/world/level/DimensionConversionData.h" -// #include "mc/world/level/Level.h" -// #include "mc/world/level/MolangVariableMap.h" -// #include "mc/world/level/WorldBlockTarget.h" -// #include "mc/world/level/WorldGenContext.h" -// #include "mc/world/level/biome/Biome.h" -// #include "mc/world/level/biome/VanillaBiomeNames.h" -// #include "mc/world/level/biome/registry/BiomeRegistry.h" -// #include "mc/world/level/biome/source/BiomeArea.h" -// #include "mc/world/level/biome/source/FixedBiomeSource.h" -// #include "mc/world/level/biome/surface/ISurfaceBuilder.h" -// #include "mc/world/level/levelgen/synth/PerlinNoise.h" -// #include "mc/world/level/levelgen/synth/PerlinSimplexNoise.h" -// #include "mc/world/level/block/Block.h" -// #include "mc/world/level/block/BlockVolume.h" -// #include "mc/world/level/block/actor/EndGatewayBlockActor.h" -// #include "mc/world/level/block/registry/BlockTypeRegistry.h" -// #include "mc/world/level/block/utils/BedrockBlockNames.h" -// #include "mc/world/level/block/utils/VanillaBlockTypeIds.h" -// #include "mc/world/level/chunk/ChunkGeneratorStructureState.h" -// #include "mc/world/level/chunk/ChunkViewSource.h" -// #include "mc/world/level/chunk/LevelChunk.h" -// #include "mc/world/level/chunk/LevelChunkBlockActorAccessToken.h" -// #include "mc/world/level/chunk/PostprocessingManager.h" -// #include "mc/world/level/chunk/VanillaLevelChunkUpgrade.h" -// #include "mc/world/level/dimension/Dimension.h" -// #include "mc/world/level/dimension/DimensionBrightnessRamp.h" -// #include "mc/world/level/dimension/OverworldBrightnessRamp.h" -// #include "mc/world/level/dimension/OverworldDimension.h" -// #include "mc/world/level/dimension/VanillaDimensions.h" -// #include "mc/world/level/levelgen/WorldGenerator.h" -// #include "mc/world/level/levelgen/feature/BambooFeature.h" -// #include "mc/world/level/levelgen/feature/DesertWellFeature.h" -// #include "mc/world/level/levelgen/feature/FlowerFeature.h" -// #include "mc/world/level/levelgen/feature/LakeFeature.h" -// #include "mc/world/level/levelgen/feature/SpikeFeature.h" -// #include "mc/world/level/levelgen/feature/VanillaTreeFeature.h" -// #include "mc/world/level/levelgen/feature/gamerefs_feature/FeatureRefTraits.h" -// #include "mc/world/level/levelgen/feature/helpers/RenderParams.h" -// #include "mc/world/level/levelgen/feature/registry/FeatureRegistry.h" -// #include "mc/world/level/levelgen/flat/FlatWorldGenerator.h" -// #include "mc/world/level/levelgen/flat/FlatWorldGeneratorOptions.h" -// #include "mc/world/level/levelgen/structure/EndCityFeature.h" -// #include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h" -// #include "mc/world/level/levelgen/structure/StructureFeatureType.h" -// #include "mc/world/level/levelgen/structure/StructureSetRegistry.h" -// #include "mc/world/level/levelgen/structure/VillageFeature.h" -// #include "mc/world/level/levelgen/v1/Aquifer.h" -// #include "mc/world/level/levelgen/v1/ChunkLocalNoiseCache.h" -// #include "mc/world/level/levelgen/v1/HardcodedSpawnAreaRegistry.h" -// #include "mc/world/level/levelgen/v1/NetherGenerator.h" -// #include "mc/world/level/levelgen/v1/OverworldGenerator2d.h" -// #include "mc/world/level/levelgen/v1/OverworldGeneratorMultinoise.h" -// #include "mc/world/level/levelgen/v1/TheEndGenerator.h" -// #include "mc/world/level/levelgen/v1/WorldGenCache.h" -// #include "mc/world/level/storage/LevelData.h" -// -// #include "mc/entity/systems/common/BiomeDecorationSystem.h" -// #include "mc/resources/VanillaGameVersions.h" -// #include "mc/world/components/FeatureHelper.h" -// #include "mc/world/level/levelgen/feature/EndIslandFeature.h" -// #include "mc/world/level/levelgen/feature/helpers/TheEndSpikeHelper.h" -// #include -// -//// namespace Bedrock { -//// namespace Threading { -//// template -//// class InstancedThreadLocalBase { -//// protected: -//// void _debugAddThread(); -//// void _debugRemoveThread(); -//// }; -//// -//// template > -//// class InstancedThreadLocal : public InstancedThreadLocalBase { -//// Bedrock::Threading::InstancedThreadLocal<_Ty, _Alloc>::Constructor mConstructor; -//// -//// typedef std::function Constructor; -//// -//// Bedrock::Threading::InstancedThreadLocal<_Ty, _Alloc>::ItemList mItems; -//// -//// typedef Bedrock::Intrusive::list< -//// Bedrock::Threading::InstancedThreadLocal<_Ty, _Alloc>::Item, -//// Bedrock::Intrusive::list_base_hook, -//// Bedrock::Intrusive::list_base_hook> -//// ItemList; -//// -//// struct Item : list_base_hook { -//// std::aligned_storage<262144UL, 8UL>::type mData; -//// _Ty* data(); -//// }; -//// -//// MutexType mMutex; -//// Bedrock::Threading::CustomTLS::Key mKey; -//// bool mInitialized; -//// -//// public: -//// InstancedThreadLocal(); -//// ~InstancedThreadLocal(); -//// _Ty& get(); -//// _Ty& operator*(); -//// _Ty* operator->(); -//// Bedrock::Threading::InstancedThreadLocal<_Ty, _Alloc>::IteratorType begin(); -//// -//// private: -//// public: -//// Bedrock::Threading::InstancedThreadLocal<_Ty, _Alloc>::IteratorType end(); -//// -//// private: -//// void _init(); -//// void _destroy(); -//// _Ty* _load(); -//// typedef std::allocator_traits<_Alloc>::rebind_alloc::Item> / AllocatorType; / }; -//// -//// } // namespace Threading -//// } // namespace Bedrock -// -// -// class MyWorldGenerator : public WorldGenerator { -// public: -// struct ThreadData { -// std::array mBlockBuffer; -// }; -// -// public: -// std::unique_ptr mLPerlinNoise1; -// std::unique_ptr mLPerlinNoise2; -// std::unique_ptr mPerlinNoise1; -// std::unique_ptr mIslandNoise; -// std::unique_ptr mMaterialAdjNoise; -// // Bedrock::Threading::InstancedThreadLocal -// char mGeneratorHelpersPool[168]; -// std::unique_ptr mBiomeSource; -// Random mRandom; -// uint mSeed; -// -// public: -// MyWorldGenerator(Dimension& dimension, uint seed) : WorldGenerator(dimension), mSeed(seed) { -// mRandom.mRandom.mObject._setSeed(seed); -// mLPerlinNoise1 = std::make_unique(mRandom, 16, 0); -// mLPerlinNoise2 = std::make_unique(mRandom, 16, 0); -// mPerlinNoise1 = std::make_unique(mRandom, 8, 0); -// mIslandNoise = std::make_unique(mRandom, 0); -// mMaterialAdjNoise = std::make_unique(mRandom, 3, 0); -// mBiomeSource = std::make_unique( -// *dimension.getLevel().getBiomeRegistry().lookupByHash(VanillaBiomeNames::TheEnd) -// ); -// -// for (auto& v : getStructureFeatureRegistry().mStructureFeatures) { -// v->initMobSpawnTypes(*mHardcodedSpawnTypes); -// } -// } -// -// virtual bool isNaturalDimension() const { return 0; } -// -// -// public: -// bool postProcess(ChunkViewSource& neighborhood) { -// ChunkPos chunkPos; -// chunkPos.x = neighborhood.getArea().mBounds.min.x; -// chunkPos.z = neighborhood.getArea().mBounds.min.z; -// auto levelChunk = neighborhood.getExistingChunk(chunkPos); -// -// auto lockChunk = -// levelChunk->getDimension().mPostProcessingManager->tryLock(levelChunk->getPosition(), neighborhood); -// -// if (!lockChunk) { -// return false; -// } -// BlockSource blockSource(getLevel(), neighborhood.getDimension(), neighborhood, false, true, true); -// auto chunkPosL = levelChunk->getPosition(); -// mRandom.mRandom.mObject._setSeed(mSeed); -// auto one = 2 * (mRandom.nextInt() / 2) + 1; -// auto two = 2 * (mRandom.nextInt() / 2) + 1; -// mRandom.mRandom.mObject._setSeed(mSeed ^ (chunkPosL.x * one + chunkPosL.z * two)); -// WorldGenerator::postProcessStructureFeatures(blockSource, mRandom, chunkPosL.x, chunkPosL.z); -// WorldGenerator::postProcessStructures(blockSource, mRandom, chunkPosL.x, chunkPosL.z); -// return true; -// // int v5; // edx -// // bool Has_value; // al -// // unsigned __int8 v9; // r14 -// // __int64 v10; // rsi -// // std::string* Ptr; // rbx -// // unsigned int v16; // edi -// // unsigned int v17; // edi -// // std::string* v18; // rbx -// // SpikeFeature::EndSpike* Myfirst; // rdi -// // SpikeFeature::EndSpike* Mylast; // r14 -// // int CenterZ; // ebx -// // unsigned __int64 v22; // rdx -// // SpikeFeature::EndSpike* v23; // rax -// // unsigned __int64 v24; // r8 -// // unsigned __int64 v25; // r8 -// // unsigned int v26; // eax -// // std::string* v27; // rbx -// // unsigned int v28; // edi -// // unsigned int v29; // ebx -// // char v30; // al -// // unsigned __int64 v31; // r8 -// // std::string* v32; // rbx -// // signed int v33; // r13d -// // signed int v34; // r12d -// // unsigned int v35; // edi -// // unsigned int v36; // esi -// // __int16 Heightmap; // ax -// // int v38; // r14d -// // BlockLegacy* v39; // rcx -// // unsigned __int64 Hash; // rbx -// // unsigned int v41; // eax -// // unsigned int v42; // ebx -// // unsigned int v43; // edi -// // __int16 v44; // ax -// // int v45; // r14d -// // unsigned int v46; // eax -// // BlockActor* BlockEntity; // rax -// // EndGatewayBlockActor* v48; // rbx -// // const BlockPos* v49; // rax -// // std::string* v50; // rbx -// // BlockTickingQueue* TickQueue; // rax -// // BlockTickingQueue* v52; // rax -// // LevelChunkBlockActorAccessToken* mChunk; // rbx -// // LevelChunkBlockActorAccessToken* v54; // rdi -// // unsigned __int64 v55; // rdx -// // LevelChunkBlockActorAccessToken* v56; // rax -// // unsigned __int64 v57; // r8 -// // unsigned __int64 v58; // r8 -// // PostprocessingManager::LockedChunk* v59; // rcx -// // PostprocessingManager::LockedChunk* v60; // rsi -// // Bedrock::Threading::UniqueLock* p_mChunkLock; // rdi -// // volatile signed __int32* v62; // rbx -// // unsigned __int64 v63; // rdx -// // PostprocessingManager::LockedChunk* v64; // rax -// // std::_Ref_count_base* Rep; // rbx -// // BlockPos pos; // [rsp+40h] [rbp-C0h] -// // BYREF BlockPos v83; // [rsp+4Ch] -// // [rbp-B4h] BYREF BlockPos v84; // -// // [rsp+58h] [rbp-A8h] BYREF BlockPos v85; // -// [rsp+64h] -// // [rbp-9Ch] BYREF BlockPos target; // -// // [rsp+70h] [rbp-90h] BYREF BlockPos v87; // -// [rsp+7Ch] -// // [rbp-84h] BYREF TheEndGenerator* v88; // -// // [rsp+88h] [rbp-78h] BYREF Feature* v89; // -// // [rsp+98h] [rbp-68h] BYREF std::string name; // -// // [rsp+B0h] [rbp-50h] BYREF std::string v91; // -// [rsp+D0h] -// // [rbp-30h] BYREF std::string v92; // -// // [rsp+F0h] [rbp-10h] BYREF std::string v93; // -// // [rsp+110h] [rbp+10h] BYREF std::string v94; // -// // [rsp+130h] [rbp+30h] BYREF BlockPos gatewayPos; // -// // [rsp+160h] [rbp+60h] BYREF ChunkPos centerPos; // -// // [rsp+180h] [rbp+80h] BYREF BlockPos featurePlacement; // [rsp+188h] [rbp+88h] BYREF -// // std::vector spikes; // [rsp+1B0h] [rbp+B0h] -// // BYREF EndIslandFeature endIslands; // [rsp+1C8h] -// // [rbp+C8h] BYREF BlockTickingQueue randomTickQueue; // -// // [rsp+200h] [rbp+100h] BYREF BlockTickingQueue instaTickQueue; -// // // [rsp+250h] [rbp+150h] BYREF SpikeFeature spikeFeature; // [rsp+2F0h] [rbp+1F0h] -// // BYREF Random v113; // [rsp+4D0h] -// // [rbp+3D0h] BYREF -// -// // centerPos.x = neighborhood.getArea().mBounds.min.x + 1; -// // centerPos.z = neighborhood.getArea().mBounds.min.z + 1; -// // auto levelChunk = neighborhood.getExistingChunk(centerPos); -// // ChunkPos Position = levelChunk->getPosition(); -// // if (neighborhood.getArea().mBounds.mVolume != 9) { -// // } -// // Dimension& dimension = levelChunk->getDimension(); -// -// // std::optional> ownsNeighborhood = -// // dimension.mPostProcessingManager->tryLock(Position, neighborhood); -// -// // if (ownsNeighborhood.has_value()) { -// // std::vector blockEntityLock = -// neighborhood.enableBlockEntityAccess(); -// // Dimension& ndimension = neighborhood.getDimension(); -// // Level& level = neighborhood.getLevel(); -// // BlockSource source(level, ndimension, neighborhood, 0, 1, 1); -// // source.setTickingQueue(instaTickQueue); -// // source.setRandomTickingQueue(&source, &randomTickQueue); -// // BlockPos min = levelChunk->getMin(); -// // Biome biome = source.getBiome(min); -// // BlockPos origin(Position, 0); -// // LODWORD(v12) = -1724254968 * Position->x - 245998635 * Position->z; -// // v113.IRandom::__vftable = -// // (Random_vtbl*)IRandom::`vftable'; Bedrock::EnableNonOwnerReferences::EnableNonOwnerReferences( -// // &v113.Bedrock::EnableNonOwnerReferences -// // ); -// // v113.IRandom::__vftable = (Random_vtbl*)Random::`vftable '{for `IRandom' -// // }; -// // v113.Bedrock::EnableNonOwnerReferences::__vftable = -// // (Bedrock::EnableNonOwnerReferences_vtbl*)Random::`vftable '{for `Bedrock::EnableNonOwnerReferences' -// // -// // v113.mRandom.mObject.__vftable = -// // (Core::Random_vtbl*)Core::Random::`vftable'; v113.mRandom.mObject.mFakeUniformRandomInt = 0; -// // v113.mRandom.mObject.mTest_OnlyUsedDeterministically = 0; -// // Core::Random::_setSeed(&v113.mRandom.mObject, (unsigned int)v12); -// // v113.mRandom.mThreadIdInitialized = 0; -// //*(_QWORD*)&v113.mRandom.mThreadId._Id = 0ll; -// // LODWORD(v12) = this->mLevel->getSeed(this->mLevel); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // Core::Random::_setSeed(&v113.mRandom.mObject, (unsigned int)v12); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v16 = ((Core::Random::_genRandInt32(&v113.mRandom.mObject) >> 1) & 0xFFFFFFFE) + 1; -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // LODWORD(v12) = ((Core::Random::_genRandInt32(&v113.mRandom.mObject) >> 1) & 0xFFFFFFFE) + 1; -// // v17 = ((__int64(__fastcall*)(Level*))this->mLevel->getSeed)(this->mLevel) -// // ^ (Position->z * (_DWORD)v12 + Position->x * v16); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // Core::Random::_setSeed(&v113.mRandom.mObject, v17); -// // WorldGenerator::postProcessStructureFeatures(this, &source, &v113, Position->x, Position->z); -// // v18 = &label_305; -// // if (_TSS2 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS2); -// // if (_TSS2 == -1) { -// // Core::Profile::constructLabel(&label_305, "TheEndGenerator::postProcess"); -// // j_atexit(TheEndGenerator::postProcess_::_31_::_dynamic_atexit_destructor_for__label_305__); -// // j__Init_thread_footer(&_TSS2); -// // } -// //} -// // if (_TSS3 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS3); -// // if (_TSS3 == -1) { -// // if (label_305._Mypair._Myval2._Myres >= 0x10) v18 = -// (std::string*)label_305._Mypair._Myval2._Bx._Ptr; -// // v91._Mypair._Myval2._Bx._Ptr = 0ll; -// // v91._Mypair._Myval2._Mysize = 0ll; -// // v91._Mypair._Myval2._Myres = 15ll; -// // v25 = -1ll; -// // do ++v25; -// // while (Core::Profile::Area::CHUNK_LOAD_SYSTEM_2[v25]); -// // std::string::assign(&v91, "Chunk load system", v25); -// // v70 = Core::Profile::findOrCreateGroup(&v91, 0xBC8F8Fu); -// // Core::Profile::GroupToken::GroupToken(&token_305, v70, v18->_Mypair._Myval2._Bx._Buf, 0xBC8F8Fu); -// // if (v91._Mypair._Myval2._Myres >= 0x10) { -// // v71 = v91._Mypair._Myval2._Myres + 1; -// // v72 = v91._Mypair._Myval2._Bx._Ptr; -// // if (v91._Mypair._Myval2._Myres + 1 >= 0x1000) { -// // v71 = v91._Mypair._Myval2._Myres + 40; -// // v72 = (char*)*((_QWORD*)v91._Mypair._Myval2._Bx._Ptr - 1); -// // if ((unsigned __int64)(v91._Mypair._Myval2._Bx._Ptr - v72 - 8) > 0x1F) -// // _invalid_parameter_noinfo_noreturn(); -// // } -// // operator delete(v72, v71); -// // } -// // j_atexit(TheEndGenerator::postProcess_::_31_::_dynamic_atexit_destructor_for__token_305__); -// // j__Init_thread_footer(&_TSS3); -// // } -// //} -// // Core::Profile::ProfileSectionGroup::ProfileSectionGroup(&ProfileSectionGroup13, &token_305, 0); -// // this->decorateWorldGenPostProcess(this, Biome, levelChunk._Ptr, &source, &v113); -// // Core::Profile::ProfileSectionGroup::~ProfileSectionGroup(&ProfileSectionGroup13); -// // memset(&spikes, 0, sizeof(spikes)); -// // TheEndSpikeHelper::getSpikesForLevel(&spikes, this->mLevel); -// // Myfirst = spikes._Mypair._Myval2._Myfirst; -// // Mylast = spikes._Mypair._Myval2._Mylast; -// // if (spikes._Mypair._Myval2._Myfirst != spikes._Mypair._Myval2._Mylast) { -// // do { -// // if (SpikeFeature::EndSpike::startsInChunk(Myfirst, &origin)) { -// // memset(&spikeFeature, 0, sizeof(spikeFeature)); -// // SpikeFeature::SpikeFeature(&spikeFeature, Myfirst); -// // CenterZ = SpikeFeature::EndSpike::getCenterZ(Myfirst); -// // pos.x = SpikeFeature::EndSpike::getCenterX(Myfirst); -// // pos.y = 45; -// // pos.z = CenterZ; -// // SpikeFeature::place(&spikeFeature, &source, &pos, &v113); -// // Feature::~Feature(&spikeFeature); -// // } -// // ++Myfirst; -// // } while (Myfirst != Mylast); -// // Myfirst = spikes._Mypair._Myval2._Myfirst; -// //} -// // if (Myfirst) { -// // v22 = 44 * (spikes._Mypair._Myval2._Myend - Myfirst); -// // v23 = Myfirst; -// // if (v22 >= 0x1000) { -// // v22 += 39ll; -// // Myfirst = *(SpikeFeature::EndSpike**)&Myfirst[-1].mTopBoundingBox.max.y; -// // if ((unsigned __int64)((char*)v23 - (char*)Myfirst - 8) > 0x1F) -// _invalid_parameter_noinfo_noreturn(); -// // } -// // operator delete(Myfirst, v22); -// //} -// // if (Position->x * (__int64)Position->x + Position->z * (__int64)Position->z > 4096) { -// // if (TheEndGenerator::getIslandHeightValue(this, Position->x, Position->z, 1, 1) < -20.0) { -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v26 = Core::Random::_genRandInt32(&v113.mRandom.mObject); -// // if (v26 == 14 * (v26 / 0xE)) { -// // v27 = &label_323; -// // if (_TSS5 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS5); -// // if (_TSS5 == -1) { -// // Core::Profile::constructLabel(&label_323, "TheEndGenerator::postProcess"); -// // j_atexit(TheEndGenerator::postProcess_::_45_::_dynamic_atexit_destructor_for__label_323__); -// // j__Init_thread_footer(&_TSS5); -// // } -// // } -// // if (_TSS6 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS6); -// // if (_TSS6 == -1) { -// // if (label_323._Mypair._Myval2._Myres >= 0x10) -// // v27 = (std::string*)label_323._Mypair._Myval2._Bx._Ptr; -// // v92._Mypair._Myval2._Bx._Ptr = 0ll; -// // v92._Mypair._Myval2._Mysize = 0ll; -// // v92._Mypair._Myval2._Myres = 15ll; -// // v31 = -1ll; -// // do ++v31; -// // while (Core::Profile::Area::CHUNK_LOAD_SYSTEM_2[v31]); -// // std::string::assign(&v92, "Chunk load system", v31); -// // v73 = Core::Profile::findOrCreateGroup(&v92, 0xBC8F8Fu); -// // Core::Profile::GroupToken::GroupToken( -// // &token_323, -// // v73, -// // v27->_Mypair._Myval2._Bx._Buf, -// // 0xBC8F8Fu -// // ); -// // if (v92._Mypair._Myval2._Myres >= 0x10) { -// // v74 = v92._Mypair._Myval2._Myres + 1; -// // v75 = v92._Mypair._Myval2._Bx._Ptr; -// // if (v92._Mypair._Myval2._Myres + 1 >= 0x1000) { -// // v74 = v92._Mypair._Myval2._Myres + 40; -// // v75 = (char*)*((_QWORD*)v92._Mypair._Myval2._Bx._Ptr - 1); -// // if ((unsigned __int64)(v92._Mypair._Myval2._Bx._Ptr - v75 - 8) > 0x1F) -// // _invalid_parameter_noinfo_noreturn(); -// // } -// // operator delete(v75, v74); -// // } -// // j_atexit(TheEndGenerator::postProcess_::_45_::_dynamic_atexit_destructor_for__token_323__); -// // j__Init_thread_footer(&_TSS6); -// // } -// // } -// // Core::Profile::ProfileSectionGroup::ProfileSectionGroup(&ProfileSectionGroup14, &token_323, 0); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v28 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 8; -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v29 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 55; -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v30 = Core::Random::_genRandInt32(&v113.mRandom.mObject); -// // featurePlacement.x = v28 + origin.x; -// // featurePlacement.y = v29 + origin.y; -// // featurePlacement.z = (v30 & 0xF) + 8 + origin.z; -// // memset(&endIslands, 0, sizeof(endIslands)); -// // Feature::Feature(&endIslands, 0ll); -// // endIslands.__vftable = (EndIslandFeature_vtbl*)EndIslandFeature::`vftable'; -// // EndIslandFeature::place( -// // &endIslands, -// // &source, -// // &featurePlacement, -// // &v113 -// // ); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // if ((Core::Random::_genRandInt32(&v113.mRandom.mObject) & 3) == 0) -// // EndIslandFeature::place(&endIslands, &source, &featurePlacement, &v113); -// // Feature::~Feature(&endIslands); -// // Core::Profile::ProfileSectionGroup::~ProfileSectionGroup(&ProfileSectionGroup14); -// // } -// // } -// // if (TheEndGenerator::getIslandHeightValue(this, Position->x, Position->z, 1, 1) > 40.0) { -// // v32 = &label_338; -// // if (_TSS7 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS7); -// // if (_TSS7 == -1) { -// // Core::Profile::constructLabel(&label_338, "TheEndGenerator::postProcess"); -// // j_atexit(TheEndGenerator::postProcess_::_51_::_dynamic_atexit_destructor_for__label_338__); -// // j__Init_thread_footer(&_TSS7); -// // } -// // } -// // if (_TSS8 > *(_DWORD*)(v10 + 1400)) { -// // j__Init_thread_header(&_TSS8); -// // if (_TSS8 == -1) { -// // if (label_338._Mypair._Myval2._Myres >= 0x10) -// // v32 = (std::string*)label_338._Mypair._Myval2._Bx._Ptr; -// // v93._Mypair._Myval2._Bx._Ptr = 0ll; -// // v93._Mypair._Myval2._Mysize = 0ll; -// // v93._Mypair._Myval2._Myres = 15ll; -// // v57 = -1ll; -// // do ++v57; -// // while (Core::Profile::Area::CHUNK_LOAD_SYSTEM_2[v57]); -// // std::string::assign(&v93, "Chunk load system", v57); -// // v76 = Core::Profile::findOrCreateGroup(&v93, 0xBC8F8Fu); -// // Core::Profile::GroupToken::GroupToken(&token_338, v76, v32->_Mypair._Myval2._Bx._Buf, -// // 0xBC8F8Fu); if (v93._Mypair._Myval2._Myres >= 0x10) { -// // v77 = v93._Mypair._Myval2._Myres + 1; -// // v78 = v93._Mypair._Myval2._Bx._Ptr; -// // if (v93._Mypair._Myval2._Myres + 1 >= 0x1000) { -// // v77 = v93._Mypair._Myval2._Myres + 40; -// // v78 = (char*)*((_QWORD*)v93._Mypair._Myval2._Bx._Ptr - 1); -// // if ((unsigned __int64)(v93._Mypair._Myval2._Bx._Ptr - v78 - 8) > 0x1F) -// // _invalid_parameter_noinfo_noreturn(); -// // } -// // operator delete(v78, v77); -// // } -// // j_atexit(TheEndGenerator::postProcess_::_51_::_dynamic_atexit_destructor_for__token_338__); -// // j__Init_thread_footer(&_TSS8); -// // } -// // } -// // Core::Profile::ProfileSectionGroup::ProfileSectionGroup(&ProfileSectionGroup15, &token_338, 0); -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v33 = Core::Random::_genRandInt32(&v113.mRandom.mObject) % 5; -// // v34 = 0; -// // if (v33 > 0) { -// // do { -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v35 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 8; -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v36 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 8; -// // v83.x = v35 + origin.x; -// // v83.y = origin.y; -// // v83.z = v36 + origin.z; -// // Heightmap = BlockSource::getHeightmap(&source, &v83); -// // if (Heightmap > 0) { -// // v38 = Heightmap - 1; -// // v84.x = v35 + origin.x; -// // v84.y = Heightmap + origin.y; -// // v84.z = v36 + origin.z; -// // if (BlockSource::isEmptyBlock(&source, &v84)) { -// // v85.x = v35 + origin.x; -// // v85.y = v38 + origin.y; -// // v85.z = v36 + origin.z; -// // v39 = BlockSource::getBlock(&source, &v85)->mLegacyBlock.ptr_; -// // if (!v39) gsl::details::terminate(0ll); -// // Hash = HashedString::getHash(&v39->mNameInfo.mFullName); -// // if (Hash == HashedString::getHash(&VanillaBlockTypeIds::EndStone)) { -// // target.x = v35 + origin.x; -// // target.y = v38 + origin.y + 1; -// // target.z = v36 + origin.z; -// // ChorusFlowerBlock::generatePlant(&source, &target, &v113, 8); -// // } -// // } -// // } -// // ++v34; -// // } while (v34 < v33); -// // v10 = *(_QWORD*)&gatewayPos.x; -// // } -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v41 = Core::Random::_genRandInt32(&v113.mRandom.mObject); -// // if (v41 == 700 * (v41 / 0x2BC)) { -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v42 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 8; -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v43 = (Core::Random::_genRandInt32(&v113.mRandom.mObject) & 0xF) + 8; -// // v87.x = v42 + origin.x; -// // v87.y = origin.y; -// // v87.z = v43 + origin.z; -// // v44 = BlockSource::getHeightmap(&source, &v87); -// // v45 = v44; -// // if (v44 > 0) { -// // Bedrock::Application::ThreadOwner::_assertSameThreadID(&v113.mRandom); -// // v46 = Core::Random::_genRandInt32(&v113.mRandom.mObject); -// // gatewayPos.x = v42 + origin.x; -// // gatewayPos.y = v45 + v46 % 7 + 3 + origin.y; -// // gatewayPos.z = v43 + origin.z; -// // memset(&v89, 0, sizeof(v89)); -// // Feature::Feature(&v89, 0ll); -// // v89.__vftable = (Feature_vtbl*)EndGatewayFeature::`vftable'; EndGatewayFeature::place( -// // (EndGatewayFeature*)&v89, -// // &source, -// // &gatewayPos, -// // &v113 -// // ); -// // Feature::~Feature(&v89); -// // BlockEntity = BlockSource::getBlockEntity(&source, &gatewayPos); -// // v48 = (EndGatewayBlockActor*)BlockEntity; -// // if (BlockEntity) { -// // if (*BlockActor::getType(BlockEntity) == 24) { -// // v49 = v88->mDimension->getSpawnPos(v88->mDimension, (BlockPos*)&v88); -// // EndGatewayBlockActor::setExitPosition(v48, v49); -// // } -// // } -// // } -// // } -// // Core::Profile::ProfileSectionGroup::~ProfileSectionGroup(&ProfileSectionGroup15); -// // } -// //} -// // v50 = &label_373; -// // BlockTickingQueue::tickAllPendingTicks(&instaTickQueue, &source, WorldGenerator::TICKING_QUEUE_PASS_LIMIT); -// // BlockTickingQueue::tickAllPendingTicks(&randomTickQueue, &source, -// WorldGenerator::TICKING_QUEUE_PASS_LIMIT); -// // TickQueue = LevelChunk::getTickQueue(levelChunk._Ptr); -// // BlockTickingQueue::acquireAllTicks(TickQueue, &instaTickQueue); -// // v52 = LevelChunk::getRandomTickQueue(levelChunk._Ptr); -// // BlockTickingQueue::acquireAllTicks(v52, &randomTickQueue); -// // mChunk = blockEntityLock._Mypair._Myval2._Myfirst; -// // v9 = 1; -// // return v9; -// } -// -// void loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad) { -// auto& position = levelchunk.getPosition(); -// -// auto& dimension = ChunkSource::getDimension(); -// WorldGenerator::prepareStructureFeatureBlueprints(dimension, position, *this->mBiomeSource, *this); -// -// ChunkLocalNoiseCache chunkLocalNoiseCache; -// -// this->mBiomeSource->fillBiomes(levelchunk, chunkLocalNoiseCache); -// -// ThreadData threadData{}; -// -// buffer_span_mut buffer{}; -// buffer.mBegin = &*threadData.mBlockBuffer.begin(); -// buffer.mEnd = &*threadData.mBlockBuffer.end(); -// BlockVolume box(buffer, 16, 128, 16, Block::tryGetFromRegistry("minecraft:air"), 0); -// -// this->prepareHeights(box, position, 1); -// buildSurfaces(&box, &position, &levelchunk); -// levelchunk.setBlockVolume(box, 0); -// levelchunk.recomputeHeightMap(0); -// if (!levelchunk.getGenerator()) levelchunk._setGenerator(this); -// levelchunk.changeState(ChunkState::Generating, ChunkState::Generated); -// } -// -// std::optional getPreliminarySurfaceLevel(DividedPos2d<4> worldQuartPos) const { -// float IslandHeightValue; -// BlockPos pos; -// -// pos.y = 0; -// pos.z = 4 * worldQuartPos.z; -// pos.x = 4 * worldQuartPos.x; -// ChunkPos chunkPos{pos}; -// IslandHeightValue = getIslandHeightValue(chunkPos.x, chunkPos.z, 1, 1); -// return mce::Math::floor(IslandHeightValue); -// } -// -// void prepareAndComputeHeights( -// BlockVolume& /*box*/, -// ChunkPos const& /*chunkPos*/, -// std::vector& ZXheights, -// bool /*factorInBeardsAndShavers*/, -// int /*skipTopN*/ -// ) {} -// -// virtual void prepareHeights(BlockVolume& box, ChunkPos const& chunkPos, bool factorInBeardsAndShavers) { -// signed int Height; -// const Block* block; -// int z; -// float val; -// uint32_t offs; -// int x; -// float _s1; -// float _s0; -// int y; -// float s3a; -// float s2a; -// float s1a; -// float s0a; -// float s3; -// float s2; -// float s1; -// float s0; -// int yc; -// int zc; -// int xc; -// int levelHeightBits; -// std::array noiseBuffer; -// uint64 v27; -// -// Height = getDimension().getHeight(); -// levelHeightBits = std::log((float)Height) / std::log(2.0f); -// getHeights(&noiseBuffer, 2 * chunkPos.x, 0, 2 * chunkPos.z); -// for (xc = 0; xc < 2; ++xc) { -// for (zc = 0; zc < 2; ++zc) { -// for (yc = 0; yc < 32; ++yc) { -// s0 = noiseBuffer.at(yc + 33 * (zc + 3 * xc)); -// s1 = noiseBuffer.at(yc + 33 * (zc + 3 * xc + 1)); -// s2 = noiseBuffer.at(yc + 33 * (zc + 3 * (xc + 1))); -// s3 = noiseBuffer.at(yc + 33 * (zc + 3 * (xc + 1) + 1)); -// s0a = (float)(noiseBuffer.at(yc + 33 * (zc + 3 * xc) + 1) - s0) * 0.25f; -// s1a = (float)(noiseBuffer.at(yc + 33 * (zc + 3 * xc + 1) + 1) - s1) * 0.25; -// s2a = (float)(noiseBuffer.at(yc + 33 * (zc + 3 * (xc + 1)) + 1) - s2) * 0.25; -// s3a = (float)(noiseBuffer.at(yc + 33 * (zc + 3 * (xc + 1) + 1) + 1) - s3) * 0.25; -// for (y = 0; y < 4; ++y) { -// _s0 = s0; -// _s1 = s1; -// for (x = 0; x < 8; ++x) { -// offs = -// (4 * yc + y) | ((8 * zc) << levelHeightBits) | ((8 * xc + x) << (levelHeightBits + -// 4)); -// val = _s0; -// for (z = 0; z < 8; ++z) { -// block = Block::tryGetFromRegistry("minecraft:air"); -// if (val > 0.0) block = Block::tryGetFromRegistry("minecraft:end_stone"); -// box.block(offs) = block; -// offs += 1 << levelHeightBits; -// val = (float)((float)(_s1 - _s0) * 0.125) + val; -// } -// _s0 = (float)((float)(s2 - s0) * 0.125) + _s0; -// _s1 = (float)((float)(s3 - s1) * 0.125) + _s1; -// } -// s0 = s0a + s0; -// s1 = s1a + s1; -// s2 = s2a + s2; -// s3 = s3a + s3; -// } -// } -// } -// } -// }; -// -// StructureFeatureType findStructureFeatureTypeAt(BlockPos const& blockPos) { -// return WorldGenerator::findStructureFeatureTypeAt(blockPos); -// }; -// -// bool isStructureFeatureTypeAt(const BlockPos& blockPos, ::StructureFeatureType type) const { -// return WorldGenerator::isStructureFeatureTypeAt(blockPos, type); -// } -// -// bool findNearestStructureFeature( -// ::StructureFeatureType type, -// BlockPos const& blockPos, -// BlockPos& blockPos1, -// bool mustBeInNewChunks, -// std::optional hash -// ) { -// return WorldGenerator::findNearestStructureFeature(type, blockPos, blockPos1, mustBeInNewChunks, hash); -// }; -// -// void garbageCollectBlueprints(buffer_span activeChunks) { -// return WorldGenerator::garbageCollectBlueprints(activeChunks); -// }; -// -// BlockPos findSpawnPosition() const { return {0, 16, 0}; }; -// -// virtual void buildSurfaces(BlockVolume* box, const ChunkPos* chunkPos, LevelChunk* levelChunk) { -// Random random(mLevel->getSeed(), 0); -// -// ChunkBlockPos p{0, 0, 0}; -// BlockPos t{0, 0, 0}; -// -// short seaLevel = getDimension().mSeaLevel; -// Dimension& dimension = ChunkSource::getDimension(); -// short v12 = dimension.getMinHeight(); -// Level& level = levelChunk->getLevel(); -// LevelData& levelData = level.getLevelData(); -// BaseGameVersion baseGameVersion = levelData.getBaseGameVersion(); -// -// bool useCCOrLater = baseGameVersion.isCompatibleWith(VanillaGameVersions::CavesAndCliffsUpdate); -// p.x = 0; -// do { -// p.z = 0; -// do { -// t = levelChunk->toWorldPos(p); -// t.y -= v12; -// BiomeSurfaceSystem::buildSurfaceAt(ISurfaceBuilder::BuildParameters( -// levelChunk->getBiome(p), -// random, -// *box, -// t, -// 0.0, -// seaLevel, -// std::move(this->mMaterialAdjNoise), -// ISurfaceBuilder::WaterLevelStrategy::GLOBAL, -// 0, -// levelChunk->getPreWorldGenHeightmap(), -// useCCOrLater -// )); -// ++p.z; -// } while (p.z < 0x10u); -// ++p.x; -// } while (p.x < 0x10u); -// } -// -// virtual BiomeArea getBiomeArea(const BoundingBox& area, uint scale) const { -// return mBiomeSource->getBiomeArea(area, scale); -// } -// -// virtual const BiomeSource& getBiomeSource(void) const { return *mBiomeSource; } -// -// virtual BlockVolumeDimensions getBlockVolumeDimensions(void) const { return {16, 16, 320}; } -// -// virtual void decorateWorldGenLoadChunk( -// const Biome& biome, -// LevelChunk& levelChunk, -// BlockVolumeTarget& target, -// Random& random, -// const ChunkPos& chunkPos -// ) const { -// ; -// } -// -// virtual void -// decorateWorldGenPostProcess(const Biome& biome, LevelChunk& levelChunk, BlockSource& blockSource, Random& random) -// const { -// std::vector vbp{&biome}; -// auto result = getLevel().getFeatureRegistry().getSmallFeaturePasses(); -// for (auto& v : result) { -// BiomeDecorationSystem::decorate(levelChunk, blockSource, random, vbp, v, *this); -// } -// } -// -// void getHeights(std::array* noiseBuffer, int x, int y, int z) { -// float v5; -// PerlinNoise* v6; -// PerlinNoise* v7; -// PerlinNoise* v8; -// float slide_0; -// float v; -// float val; -// float vala; -// float bb; -// int yy; -// float doffs; -// int zz; -// int xx; -// int p; -// Vec3 v22{1368.824, 684.41199, 1368.824}; -// Vec3 v24{1368.824, 684.41199, 1368.824}; -// Vec3 scale{1368.824 / 80.0, 684.41199 / 160.0, 1368.824 / 80.0}; -// BlockPos noisePos{x, y, z}; -// Vec3 pos{noisePos.x, noisePos.y, noisePos.z}; -// Vec3 v25{noisePos.x, noisePos.y, noisePos.z}; -// Vec3 v23{noisePos.x, noisePos.y, noisePos.z}; -// float noiseRegionB[297]; -// float noiseRegionA[297]; -// float noiseRegionPrimary[297]; -// uint64 v32; -// -// this->mPerlinNoise1->getRegion(noiseRegionPrimary, pos, 3, 33, 3, scale); -// this->mLPerlinNoise1->getRegion(noiseRegionA, v25, 3, 33, 3, v24); -// this->mLPerlinNoise2->getRegion(noiseRegionB, v23, 3, 33, 3, v22); -// p = 0; -// for (xx = 0; xx < 3; ++xx) { -// for (zz = 0; zz < 3; ++zz) { -// doffs = getIslandHeightValue(x / 2, z / 2, xx, zz); -// for (yy = 0; yy < 33; ++yy) { -// v = (float)((float)(noiseRegionPrimary[p] / 10.0) + 1.0) / 2.0; -// if (v >= 0.0) { -// if (v <= 1.0) { -// bb = noiseRegionA[p] / 512.0; -// val = bb + (float)((float)((float)(noiseRegionB[p] / 512.0) - bb) * v); -// } else { -// val = noiseRegionB[p] / 512.0; -// } -// } else { -// val = noiseRegionA[p] / 512.0; -// } -// vala = doffs + (float)(val - 8.0); -// if (yy > 14) { -// v5 = mce::Math::clamp((float)(yy - 14) / 64.0f, 0.0f, 1.0f); -// vala = (float)(vala * (float)(1.0 - v5)) + (float)(-3000.0 * v5); -// } -// if (yy < 8) { -// slide_0 = (float)(8 - yy) / (float)((float)8 - 1.0); -// vala = (float)(vala * (float)(1.0 - slide_0)) + (float)(-30.0 * slide_0); -// } -// noiseBuffer->at(p++) = vala; -// } -// } -// } -// } -// -// float getIslandHeightValue(int chunkX, int chunkZ, int subSectionX, int subSectionZ) const { -// float v5; -// float v7; -// int64 v9; -// SimplexNoise* v10; -// bool v11; -// float newDoffs; -// int64 totalChunkZ; -// int64 totalChunkX; -// int zo; -// int xo; -// float doffs; -// uint64 v22; -// -// v5 = mce::Math::sqrt( -// (float)((float)(subSectionX + 2 * chunkX) * (float)(subSectionX + 2 * chunkX)) -// + (float)((float)(subSectionZ + 2 * chunkZ) * (float)(subSectionZ + 2 * chunkZ)) -// ); -// doffs = mce::Math::clamp(float(100.0 - (float)(v5 * 8.0)), -100.0f, 80.0f); -// for (xo = -12; xo <= 12; ++xo) { -// for (zo = -12; zo <= 12; ++zo) { -// totalChunkX = xo + chunkX; -// totalChunkZ = zo + chunkZ; -// v11 = 0; -// if (totalChunkZ * totalChunkZ + totalChunkX * totalChunkX > 4096) { -// Vec2 vin((float)(int)totalChunkX, (float)(int)totalChunkZ); -// v11 = this->mIslandNoise->_getValue(vin) < -0.89999998; -// } -// if (v11) { -// v9 = 3439 * std::abs(totalChunkX); -// auto v6 = 147 * std::abs(totalChunkZ) + v9; -// v7 = mce::Math::sqrt( -// (float)((float)(subSectionX - 2 * xo) * (float)(subSectionX - 2 * xo)) -// + (float)((float)(subSectionZ - 2 * zo) * (float)(subSectionZ - 2 * zo)) -// ); -// newDoffs = mce::Math::clamp(float(100.0 - (float)(v7 * (float)(int)(v6 % 13 + 9))), -// -100.0f, 80.0f); if (newDoffs > doffs) doffs = newDoffs; -// } -// } -// } -// return doffs; -// } -// -// bool isOutsideCentralIslandArea(const ChunkPos* chunkPos) { -// return chunkPos->x * chunkPos->x + chunkPos->z * chunkPos->z > 4096; -// } -// -// virtual void postProcessMobsAt(BlockSource& blockSource, int chunkWestBlock, int chunkNorthBlock, Random& random) -// { -// BlockPos pos; -// -// Level& level = blockSource.getLevel(); -// std::vector spikes = TheEndSpikeHelper::getSpikesForLevel(level); -// for (auto& v : spikes) { -// bool v12 = v.getCenterX() >= chunkWestBlock && v.getCenterX() < chunkWestBlock + 16; -// bool v13 = v.getCenterZ() >= chunkNorthBlock && v.getCenterZ() < chunkNorthBlock + 16; -// if (v12 && v13) { -// SpikeFeature spikeFeature = SpikeFeature::SpikeFeature(v); -// int CenterZ = v.getCenterZ(); -// pos.x = v.getCenterX(); -// pos.y = 45; -// pos.z = CenterZ; -// spikeFeature.postProcessMobsAt(blockSource, pos, random); -// } -// } -// WorldGenerator::postProcessMobsAt(blockSource, chunkWestBlock, chunkNorthBlock, random); -// } -// -// virtual void prepareAndComputeHeights( -// BlockVolume& box, -// ChunkPos const& chunkPos, -// std::vector& ZXheights, -// bool factorInBeardsAndShavers, -// int skipTopN -// ) { -// prepareHeights(box, chunkPos, factorInBeardsAndShavers, ZXheights, skipTopN); -// } -// -// void -// prepareHeights(TheEndGenerator* this, BlockVolume* box, const ChunkPos* chunkPos, bool factorInBeardsAndShavers) { -// TheEndGenerator::_prepareHeights(this, box, chunkPos, factorInBeardsAndShavers, 0ll, 0); -// } -//}; -// -// LL_AUTO_TYPE_INSTANCE_HOOK( -// OverworldDimensionCreateGeneratorHook, -// ll::memory::HookPriority::Normal, -// OverworldDimension, -// "?createGenerator@OverworldDimension@@UEAA?AV?$unique_ptr@VWorldGenerator@@U?$default_delete@VWorldGenerator@@@std@" -// "@@std@@AEBVStructureSetRegistry@worldgen@br@@@Z", -// std::unique_ptr, -// br::worldgen::StructureSetRegistry const& structureSetRegistry -//) { -// // mSeaLevel = -61; -// -// // auto biome = level.getBiomeRegistry().lookupByName(levelData.getBiomeOverride()); -// // auto& layer = levelData.getFlatWorldGeneratorOptions(); -// // std::string layerstr = -// // R"({ -// // "biome_id": 4, -// // "world_version": "version.post_1_18", -// // "block_layers": [ -// // { -// // "block_name": "minecraft:bedrock", -// // "count": 1 -// // }, -// // { -// // "block_name": "minecraft:cherry_log", -// // "count": 2 -// // }, -// // { -// // "block_name": "minecraft:grass", -// // "count": 61 -// // } -// // ], -// // "encoding_version": 6, -// // "structure_options": null -// // })"; -// // Json::Value layer; -// // Json::Reader reader; -// // reader.parse(layerstr, layer, 0); -// // ll::getLogger().warn("Superflat worlds will be created based on the following option:{}", -// layer.toStyledString()); -// // return std::make_unique(*this, level.getSeed(), layer); -// -// std::unique_ptr worldGenerator; -// auto seed = getLevel().getSeed(); -// auto& levelData = getLevel().getLevelData(); -// -// worldGenerator = std::make_unique(*this, seed); -// std::vector> structureMap; -// for (auto iter = structureSetRegistry.begin(); iter != structureSetRegistry.end(); iter++) { -// structureMap.emplace_back(iter->second); -// } -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState.mSeed = seed; -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState.mSeed64 = -// LevelSeed64::fromUnsigned32(seed); -// -// /*worldGenerator->getStructureFeatureRegistry().mStructureFeatures.emplace_back( -// std::make_unique(seed, 9, 4) -// );*/ -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState = -// br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), structureMap); -// -// worldGenerator->init(); -// return std::move(worldGenerator); -//} diff --git a/src-test/server/customWorldGenerator/TestWorldGenerator.cpp b/src-test/server/customWorldGenerator/TestWorldGenerator.cpp deleted file mode 100644 index d88f129a95..0000000000 --- a/src-test/server/customWorldGenerator/TestWorldGenerator.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "ll/api/io/Logger.h" -#include "ll/api/memory/Hook.h" -#include "ll/api/memory/Memory.h" -#include "ll/api/service/Bedrock.h" -#include "ll/core/LeviLamina.h" -#include "mc/world/level/dimension/OverworldDimension.h" -#include "mc/world/level/levelgen/structure/VillageFeature.h" -#include "mc/world/level/levelgen/structure/registry/StructureSetRegistry.h" - -// LL_AUTO_TYPE_INSTANCE_HOOK( -// OverworldDimensionCreateGeneratorHook, -// ll::memory::HookPriority::Normal, -// OverworldDimension, -// "?createGenerator@OverworldDimension@@UEAA?AV?$unique_ptr@VWorldGenerator@@U?$default_delete@VWorldGenerator@@@std@" -// "@@std@@AEBVStructureSetRegistry@worldgen@br@@@Z", -// std::unique_ptr, -// br::worldgen::StructureSetRegistry const& structureSetRegistry -//) { -// mSeaLevel = -61; -// // auto biome = level.getBiomeRegistry().lookupByName(levelData.getBiomeOverride()); -// // auto& layer = levelData.getFlatWorldGeneratorOptions(); -// // std::string layerstr = -// // R"({ -// // "biome_id": 4, -// // "world_version": "version.post_1_18", -// // "block_layers": [ -// // { -// // "block_name": "minecraft:bedrock", -// // "count": 1 -// // }, -// // { -// // "block_name": "minecraft:cherry_log", -// // "count": 2 -// // }, -// // { -// // "block_name": "minecraft:grass", -// // "count": 61 -// // } -// // ], -// // "encoding_version": 6, -// // "structure_options": null -// // })"; -// // Json::Value layer; -// // Json::Reader reader; -// // reader.parse(layerstr, layer, 0); -// // ll::getLogger().warn("Superflat worlds will be created based on the following option:{}", -// layer.toStyledString()); -// // return std::make_unique(*this, level.getSeed(), layer); -// -// std::unique_ptr worldGenerator; -// auto seed = getLevel().getSeed(); -// auto& levelData = getLevel().getLevelData(); -// -// worldGenerator = std::make_unique(*this, seed, levelData.getFlatWorldGeneratorOptions()); -// std::vector> structureMap; -// for (auto iter = structureSetRegistry.begin(); iter != structureSetRegistry.end(); iter++) { -// structureMap.emplace_back(iter->second); -// } -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState.mSeed = seed; -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState.mSeed64 = -// LevelSeed64::fromUnsigned32(seed); -// -// worldGenerator->getStructureFeatureRegistry().mStructureFeatures.emplace_back( -// std::make_unique(seed, 9, 4) -// ); -// worldGenerator->getStructureFeatureRegistry().mChunkGeneratorStructureState = -// br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), structureMap); -// -// worldGenerator->init(); -// return std::move(worldGenerator); -// } - -// LL_AUTO_TYPE_INSTANCE_HOOK( -// OverworldGeneratorDecorateWorldGenLoadChunkHook, -// ll::memory::HookPriority::Normal, -// OverworldGenerator, -// "?decorateWorldGenLoadChunk@OverworldGenerator@@MEBAXAEAVBiome@@AEAVLevelChunk@@AEAVBlockVolumeTarget@@AEAVRandom@@AEBVChunkPos@@@Z", -// void, -// class Biome& biome, -// class LevelChunk& lc, -// class BlockVolumeTarget& target, -// class Random& random, -// class ChunkPos const& pos -//) { -// ll::getLogger().info("."); -// } diff --git a/src/ll/api/base/CompilerPredefine.h b/src/ll/api/base/CompilerPredefine.h index d7c6b086f8..ca91993886 100644 --- a/src/ll/api/base/CompilerPredefine.h +++ b/src/ll/api/base/CompilerPredefine.h @@ -189,7 +189,7 @@ typedef const struct _s__RTTICompleteObjectLocator { __RTTIClassHierarchyDescriptor* pClassDescriptor; // describes inheritance hierarchy } __RTTICompleteObjectLocator; -typedef const class type_info& __RTtypeidReturnType; +typedef class type_info const& __RTtypeidReturnType; extern "C" void* __cdecl __RTDynamicCast( void const* ptr, diff --git a/src/ll/api/base/FixedString.h b/src/ll/api/base/FixedString.h index 54e3736497..d2b5a9ce93 100644 --- a/src/ll/api/base/FixedString.h +++ b/src/ll/api/base/FixedString.h @@ -25,7 +25,7 @@ struct FixedString { [[nodiscard]] constexpr char& operator[](size_t idx) noexcept { return buf[idx]; } template - consteval auto operator+(const FixedString& other) noexcept { + consteval auto operator+(FixedString const& other) noexcept { FixedString res{}; std::copy_n(buf, N, res.buf); std::copy_n(other.buf, Ny, N + res.buf); diff --git a/src/ll/api/base/StdInt.h b/src/ll/api/base/StdInt.h index 0ab1e316d7..9dc7994bb5 100644 --- a/src/ll/api/base/StdInt.h +++ b/src/ll/api/base/StdInt.h @@ -10,7 +10,6 @@ using ullong = unsigned long long; using uchar = unsigned char; using schar = signed char; -using byte = uchar; using ldouble = long double; diff --git a/src/ll/api/coro/Collect.h b/src/ll/api/coro/Collect.h index e02ec59de2..85f7ddae36 100644 --- a/src/ll/api/coro/Collect.h +++ b/src/ll/api/coro/Collect.h @@ -21,8 +21,8 @@ struct CollectAllAwaiter { std::atomic_size_t counter; public: - CollectAllAwaiter(const CollectAllAwaiter&) = delete; - CollectAllAwaiter& operator=(const CollectAllAwaiter&) = delete; + CollectAllAwaiter(CollectAllAwaiter const&) = delete; + CollectAllAwaiter& operator=(CollectAllAwaiter const&) = delete; constexpr CollectAllAwaiter(Container&& input) : tasks(std::move(input)), @@ -65,8 +65,8 @@ class CollectAllTupleAwaiter { Result results; public: - CollectAllTupleAwaiter(const CollectAllTupleAwaiter&) = delete; - CollectAllTupleAwaiter& operator=(const CollectAllTupleAwaiter&) = delete; + CollectAllTupleAwaiter(CollectAllTupleAwaiter const&) = delete; + CollectAllTupleAwaiter& operator=(CollectAllTupleAwaiter const&) = delete; constexpr CollectAllTupleAwaiter(T&&... in) : tasks(std::move(in)...) {} constexpr CollectAllTupleAwaiter(Input&& in) : tasks(std::move(in)) {} diff --git a/src/ll/api/data/AnyFunction.h b/src/ll/api/data/AnyFunction.h index 13082a838a..105cfcd204 100644 --- a/src/ll/api/data/AnyFunction.h +++ b/src/ll/api/data/AnyFunction.h @@ -78,7 +78,7 @@ class AnyFunction { char soo[AnyFunctionObjBase::smallObjSize]; }; - constexpr bool isLarge() const noexcept { return dataPtr != static_cast(&soo); } + constexpr bool isLarge() const noexcept { return dataPtr != static_cast(&soo); } constexpr bool hasValue() const noexcept { return dataPtr; } diff --git a/src/ll/api/data/AnyObjBase.h b/src/ll/api/data/AnyObjBase.h index fcbfa5a561..905f062070 100644 --- a/src/ll/api/data/AnyObjBase.h +++ b/src/ll/api/data/AnyObjBase.h @@ -30,8 +30,8 @@ class AnyObjBase { public: AnyObjBase() = default; - AnyObjBase(const AnyObjBase&) = delete; - AnyObjBase& operator=(const AnyObjBase&) = delete; + AnyObjBase(AnyObjBase const&) = delete; + AnyObjBase& operator=(AnyObjBase const&) = delete; virtual ~AnyObjBase() = default; diff --git a/src/ll/api/data/ConcurrentPriorityQueue.h b/src/ll/api/data/ConcurrentPriorityQueue.h index 749a847fc9..3fafd21266 100644 --- a/src/ll/api/data/ConcurrentPriorityQueue.h +++ b/src/ll/api/data/ConcurrentPriorityQueue.h @@ -48,8 +48,8 @@ class atomic_backoff { atomic_backoff(bool) : count(1) { pause(); } //! No Copy - atomic_backoff(const atomic_backoff&) = delete; - atomic_backoff& operator=(const atomic_backoff&) = delete; + atomic_backoff(atomic_backoff const&) = delete; + atomic_backoff& operator=(atomic_backoff const&) = delete; //! Pause for a while. void pause() { @@ -67,7 +67,7 @@ class atomic_backoff { //! Spin WHILE the condition is true. /** T and U should be comparable types. */ template -T spin_wait_while(const std::atomic& location, C comp, std::memory_order order) { +T spin_wait_while(std::atomic const& location, C comp, std::memory_order order) { atomic_backoff backoff; T snapshot = location.load(order); while (comp(snapshot)) { @@ -81,7 +81,7 @@ T spin_wait_while(const std::atomic& location, C comp, std::memory_order orde /** T and U should be comparable types. */ template T spin_wait_while_eq( - const std::atomic& location, + std::atomic const& location, const U value, std::memory_order order = std::memory_order_acquire ) { @@ -92,7 +92,7 @@ T spin_wait_while_eq( /** T and U should be comparable types. */ template T spin_wait_until_eq( - const std::atomic& location, + std::atomic const& location, const U value, std::memory_order order = std::memory_order_acquire ) { @@ -215,7 +215,7 @@ class concurrent_priority_queue { public: using value_type = T; using reference = T&; - using const_reference = const T&; + using const_reference = T const&; using size_type = std::size_t; using difference_type = std::ptrdiff_t; @@ -228,11 +228,11 @@ class concurrent_priority_queue { public: concurrent_priority_queue() : concurrent_priority_queue(allocator_type{}) {} - explicit concurrent_priority_queue(const allocator_type& alloc) : mark(0), my_size(0), my_compare(), c(alloc) { + explicit concurrent_priority_queue(allocator_type const& alloc) : mark(0), my_size(0), my_compare(), c(alloc) { my_aggregator.initialize_handler(functor{this}); } - explicit concurrent_priority_queue(const Compare& compare, const allocator_type& alloc = allocator_type()) + explicit concurrent_priority_queue(Compare const& compare, allocator_type const& alloc = allocator_type()) : mark(0), my_size(0), my_compare(compare), @@ -240,7 +240,7 @@ class concurrent_priority_queue { my_aggregator.initialize_handler(functor{this}); } - explicit concurrent_priority_queue(size_type init_capacity, const allocator_type& alloc = allocator_type()) + explicit concurrent_priority_queue(size_type init_capacity, allocator_type const& alloc = allocator_type()) : mark(0), my_size(0), my_compare(), @@ -251,8 +251,8 @@ class concurrent_priority_queue { explicit concurrent_priority_queue( size_type init_capacity, - const Compare& compare, - const allocator_type& alloc = allocator_type() + Compare const& compare, + allocator_type const& alloc = allocator_type() ) : mark(0), my_size(0), @@ -266,8 +266,8 @@ class concurrent_priority_queue { concurrent_priority_queue( InputIterator begin, InputIterator end, - const Compare& compare, - const allocator_type& alloc = allocator_type() + Compare const& compare, + allocator_type const& alloc = allocator_type() ) : mark(0), my_compare(compare), @@ -278,20 +278,20 @@ class concurrent_priority_queue { } template - concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type& alloc = allocator_type()) + concurrent_priority_queue(InputIterator begin, InputIterator end, allocator_type const& alloc = allocator_type()) : concurrent_priority_queue(begin, end, Compare(), alloc) {} concurrent_priority_queue( std::initializer_list init, - const Compare& compare, - const allocator_type& alloc = allocator_type() + Compare const& compare, + allocator_type const& alloc = allocator_type() ) : concurrent_priority_queue(init.begin(), init.end(), compare, alloc) {} - concurrent_priority_queue(std::initializer_list init, const allocator_type& alloc = allocator_type()) + concurrent_priority_queue(std::initializer_list init, allocator_type const& alloc = allocator_type()) : concurrent_priority_queue(init, Compare(), alloc) {} - concurrent_priority_queue(const concurrent_priority_queue& other) + concurrent_priority_queue(concurrent_priority_queue const& other) : mark(other.mark), my_size(other.my_size.load(std::memory_order_relaxed)), my_compare(other.my_compare), @@ -299,7 +299,7 @@ class concurrent_priority_queue { my_aggregator.initialize_handler(functor{this}); } - concurrent_priority_queue(const concurrent_priority_queue& other, const allocator_type& alloc) + concurrent_priority_queue(concurrent_priority_queue const& other, allocator_type const& alloc) : mark(other.mark), my_size(other.my_size.load(std::memory_order_relaxed)), my_compare(other.my_compare), @@ -315,7 +315,7 @@ class concurrent_priority_queue { my_aggregator.initialize_handler(functor{this}); } - concurrent_priority_queue(concurrent_priority_queue&& other, const allocator_type& alloc) + concurrent_priority_queue(concurrent_priority_queue&& other, allocator_type const& alloc) : mark(other.mark), my_size(other.my_size.load(std::memory_order_relaxed)), my_compare(other.my_compare), @@ -323,7 +323,7 @@ class concurrent_priority_queue { my_aggregator.initialize_handler(functor{this}); } - concurrent_priority_queue& operator=(const concurrent_priority_queue& other) { + concurrent_priority_queue& operator=(concurrent_priority_queue const& other) { if (this != &other) { c = other.c; mark = other.mark; @@ -374,7 +374,7 @@ class concurrent_priority_queue { size_type size() const { return my_size.load(std::memory_order_relaxed); } /* This operation can be safely used concurrently with other push, try_pop or emplace operations. */ - void push(const value_type& value) + void push(value_type const& value) requires(std::is_copy_constructible_v) { cpq_operation op_data(value, PUSH_OP); @@ -456,7 +456,7 @@ class concurrent_priority_queue { function_data const* fn; value_type* elem; }; - cpq_operation(const value_type& value, operation_type t) : type(t), elem(const_cast(&value)) {} + cpq_operation(value_type const& value, operation_type t) : type(t), elem(const_cast(&value)) {} cpq_operation(function_data const& f, operation_type t) : type(t), fn(&f) {} }; @@ -644,7 +644,7 @@ class concurrent_priority_queue { protected: vector_type c; - friend bool operator==(const concurrent_priority_queue& lhs, const concurrent_priority_queue& rhs) { + friend bool operator==(concurrent_priority_queue const& lhs, concurrent_priority_queue const& rhs) { return lhs.c == rhs.c; } }; diff --git a/src/ll/api/data/DependencyGraph.h b/src/ll/api/data/DependencyGraph.h index 27b89463b2..902a8169dc 100644 --- a/src/ll/api/data/DependencyGraph.h +++ b/src/ll/api/data/DependencyGraph.h @@ -107,7 +107,7 @@ class DependencyGraph { } } for (size_t i = 0; i < sorted.size(); i++) { - for (const auto& node : data.at(sorted[i]).dependBy) { + for (auto const& node : data.at(sorted[i]).dependBy) { if (--csize[node] == 0) { sorted.push_back(node); } diff --git a/src/ll/api/event/player/PlayerAttackEvent.cpp b/src/ll/api/event/player/PlayerAttackEvent.cpp index 331f9e90b4..3614398461 100644 --- a/src/ll/api/event/player/PlayerAttackEvent.cpp +++ b/src/ll/api/event/player/PlayerAttackEvent.cpp @@ -25,7 +25,7 @@ LL_TYPE_INSTANCE_HOOK( bool, Actor& ac, ActorDamageCause const& cause, - bool doPredictiveSound + bool doPredictiveSound ) { auto ev = PlayerAttackEvent(*this, ac, cause); EventBus::getInstance().publish(ev); diff --git a/src/ll/api/event/player/PlayerUseItemEvent.cpp b/src/ll/api/event/player/PlayerUseItemEvent.cpp index 1f83a0db82..dbf33de37e 100644 --- a/src/ll/api/event/player/PlayerUseItemEvent.cpp +++ b/src/ll/api/event/player/PlayerUseItemEvent.cpp @@ -11,7 +11,7 @@ namespace ll::event::inline player { void PlayerUseItemEvent::serialize(CompoundTag& nbt) const { Cancellable::serialize(nbt); - nbt["item"] =serializeRefObj(item()); + nbt["item"] = serializeRefObj(item()); } ItemStack& PlayerUseItemEvent::item() const { return mItem; } diff --git a/src/ll/api/i18n/I18n.cpp b/src/ll/api/i18n/I18n.cpp index f6b6e36c8c..79af518cce 100644 --- a/src/ll/api/i18n/I18n.cpp +++ b/src/ll/api/i18n/I18n.cpp @@ -82,7 +82,7 @@ Expected<> I18n::load(std::filesystem::path const& path) noexcept try { if (!f.is_regular_file() || f.path().extension() != u8".json") { continue; } - auto localeCode = f.path().stem().string(); + auto localeCode = string_utils::u8str2str(f.path().stem().u8string()); nlohmann::json j; std::ifstream(f.path()) >> j; addNestedData(*this, localeCode, j); diff --git a/src/ll/api/io/PatternFormatter.cpp b/src/ll/api/io/PatternFormatter.cpp index 5d19beee8b..f8a20c5c05 100644 --- a/src/ll/api/io/PatternFormatter.cpp +++ b/src/ll/api/io/PatternFormatter.cpp @@ -10,7 +10,7 @@ template struct fmt::formatter, Char> : formatter { template auto format(BracketedArg const& arg, FormatContext& ctx) const -> decltype(ctx.out()) { - const auto& value = arg.value; + auto const& value = arg.value; auto out = ctx.out(); if (arg.bracketed) { *out++ = static_cast('['); diff --git a/src/ll/api/memory/Closure.cpp b/src/ll/api/memory/Closure.cpp index e7d83ec483..3a176d67c8 100644 --- a/src/ll/api/memory/Closure.cpp +++ b/src/ll/api/memory/Closure.cpp @@ -10,7 +10,7 @@ namespace ll::memory { extern "C" { // from trampoline -std::size_t generate_trampoline(void* jit_code_address, const void* call_target, int = 0); +std::size_t generate_trampoline(void* jit_code_address, void const* call_target, int = 0); void* _asm_get_this_pointer(); } void* ClosureBase::getClosureData() { return _asm_get_this_pointer(); } diff --git a/src/ll/api/memory/Hook.h b/src/ll/api/memory/Hook.h index 49c2e15677..881883d6b4 100644 --- a/src/ll/api/memory/Hook.h +++ b/src/ll/api/memory/Hook.h @@ -122,7 +122,7 @@ class HookRegistrar { HookRegistrar& operator=(HookRegistrar&&) noexcept = default; }; -struct LL_EBO Hook{}; +struct LL_EBO Hook {}; } // namespace ll::memory diff --git a/src/ll/api/utils/ErrorUtils_win.cpp b/src/ll/api/utils/ErrorUtils_win.cpp index 8ec1704c3b..770a3cf928 100644 --- a/src/ll/api/utils/ErrorUtils_win.cpp +++ b/src/ll/api/utils/ErrorUtils_win.cpp @@ -281,7 +281,7 @@ std::string makeExceptionString(std::exception_ptr ePtr) noexcept { std::exception_ptr yeptr; std::swap(ePtr, yeptr); std::rethrow_exception(yeptr); - } catch (const seh_exception& e) { + } catch (seh_exception const& e) { res += fmt::format( "[0x{:0>8X}:{}] {}", (uint)e.code().value(), @@ -293,7 +293,7 @@ std::string makeExceptionString(std::exception_ptr ePtr) noexcept { for (size_t i = 0; i < unkExc.NumberParameters; i++) { res += fmt::format("\nParameter {}: {}", i, (void*)unkExc.ExceptionInformation[i]); } - } catch (const std::system_error& e) { + } catch (std::system_error const& e) { res += fmt::format( "[0x{:0>8X}:{}] {}", (uint)e.code().value(), @@ -301,10 +301,10 @@ std::string makeExceptionString(std::exception_ptr ePtr) noexcept { string_utils::tou8str(e.what()) ); ePtr = getNested(e); - } catch (const std::exception& e) { + } catch (std::exception const& e) { res += string_utils::tou8str(e.what()); ePtr = getNested(e); - } catch (const std::string& e) { + } catch (std::string const& e) { res += string_utils::tou8str(e); } catch (char const* e) { res += string_utils::tou8str(e); diff --git a/src/ll/api/utils/FontUtils_win.cpp b/src/ll/api/utils/FontUtils_win.cpp index dd541939ba..d6c02ba040 100644 --- a/src/ll/api/utils/FontUtils_win.cpp +++ b/src/ll/api/utils/FontUtils_win.cpp @@ -35,7 +35,7 @@ static std::vector getFilePathFromIDWriteFontFace(IDWrite void* refKey{}; UINT32 refKeySize = 0; if (SUCCEEDED(hr)) { - hr = fontFile->GetReferenceKey((const void**)&refKey, &refKeySize); + hr = fontFile->GetReferenceKey((void const**)&refKey, &refKeySize); } CComPtr loader; if (SUCCEEDED(hr)) { diff --git a/src/ll/api/utils/StacktraceUtils_win.cpp b/src/ll/api/utils/StacktraceUtils_win.cpp index ef10f28646..6a6e6a0463 100644 --- a/src/ll/api/utils/StacktraceUtils_win.cpp +++ b/src/ll/api/utils/StacktraceUtils_win.cpp @@ -42,8 +42,8 @@ class [[nodiscard]] DbgEngData { ~DbgEngData() { ReleaseSRWLockExclusive(&srw); } - DbgEngData(const DbgEngData&) = delete; - DbgEngData& operator=(const DbgEngData&) = delete; + DbgEngData(DbgEngData const&) = delete; + DbgEngData& operator=(DbgEngData const&) = delete; void release() noexcept { // "Phoenix singleton" - destroy and set to null, so that it can be initialized later again @@ -125,7 +125,7 @@ class [[nodiscard]] DbgEngData { return attached; } - StackTraceEntryInfo getInfo(const void* const address) { + StackTraceEntryInfo getInfo(void const* const address) { std::optional displacement = 0; std::string name; std::optional line = 0; diff --git a/src/ll/api/utils/StringUtils.h b/src/ll/api/utils/StringUtils.h index ab7563dff9..648e01a2f3 100644 --- a/src/ll/api/utils/StringUtils.h +++ b/src/ll/api/utils/StringUtils.h @@ -191,11 +191,11 @@ LLNDAPI std::string } [[nodiscard]] inline std::string const& u8str2strConst(std::u8string const& str) { - return *reinterpret_cast(&str); + return *reinterpret_cast(&str); } [[nodiscard]] inline std::u8string const& str2u8strConst(std::string const& str) { - return *reinterpret_cast(&str); + return *reinterpret_cast(&str); } [[nodiscard]] inline std::string_view u8sv2sv(std::u8string_view str) { @@ -203,7 +203,7 @@ LLNDAPI std::string } [[nodiscard]] inline std::u8string_view sv2u8sv(std::string_view str) { - return {reinterpret_cast(str.data()), str.size()}; + return {reinterpret_cast(str.data()), str.size()}; } LLNDAPI Expected svtobool(std::string_view); diff --git a/src/ll/api/utils/SystemUtils.h b/src/ll/api/utils/SystemUtils.h index 0290f76ad7..74fdc825e1 100644 --- a/src/ll/api/utils/SystemUtils.h +++ b/src/ll/api/utils/SystemUtils.h @@ -11,6 +11,7 @@ #include "ll/api/base/Macro.h" #include "ll/api/base/StdInt.h" #include "ll/api/data/TmWithMs.h" +#include "ll/api/data/Version.h" namespace ll::inline utils::sys_utils { @@ -45,6 +46,8 @@ LLNDAPI bool isStdoutSupportAnsi(); LLNDAPI bool isWine(); +LLNDAPI data::Version getSystemVersion(); + class DynamicLibrary { HandleT lib = nullptr; diff --git a/src/ll/api/utils/SystemUtils_win.cpp b/src/ll/api/utils/SystemUtils_win.cpp index 9203cb0733..46a520383d 100644 --- a/src/ll/api/utils/SystemUtils_win.cpp +++ b/src/ll/api/utils/SystemUtils_win.cpp @@ -54,6 +54,33 @@ bool isWine() { return result; } +data::Version getSystemVersion() { + OSVERSIONINFOW osVersionInfoW = [] { + OSVERSIONINFOW osVersionInfoW{}; + HMODULE hMod = GetModuleHandle(L"ntdll.dll"); + if (hMod) { + using RtlGetVersionPtr = uint(WINAPI*)(POSVERSIONINFOW); + auto fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); + if (fxPtr != nullptr) { + osVersionInfoW.dwOSVersionInfoSize = sizeof(osVersionInfoW); + if (0 == fxPtr(&osVersionInfoW)) { + return osVersionInfoW; + } + } + } + return osVersionInfoW; + }(); + data::Version version{ + (uint16_t)osVersionInfoW.dwMajorVersion, + (uint16_t)osVersionInfoW.dwMinorVersion, + (uint16_t)osVersionInfoW.dwBuildNumber + }; + if (osVersionInfoW.szCSDVersion[0] != 0) { + version.preRelease.emplace(wstr2str(osVersionInfoW.szCSDVersion)); + } + return version; +} + std::span getImageRange(std::string_view name) { static auto process = GetCurrentProcess(); HMODULE rangeStart; diff --git a/src/ll/core/Config.h b/src/ll/core/Config.h index 1e500113d7..477ef8f610 100644 --- a/src/ll/core/Config.h +++ b/src/ll/core/Config.h @@ -15,7 +15,7 @@ namespace ll { struct LeviConfig { - int version = 31; + int version = 32; std::string language = "system"; struct { @@ -31,8 +31,9 @@ struct LeviConfig { CmdSetting modManageCommand{true, CommandPermissionLevel::Admin}; } command{}; struct { - bool enabled = true; - bool useBuiltin = true; + bool enabled = true; + bool builtin = false; + bool uploadToSentry = true; std::optional externalpath; } crashLogger{}; diff --git a/src/ll/core/CrashLogger_win.cpp b/src/ll/core/CrashLogger_win.cpp index c865837c2c..206949defe 100644 --- a/src/ll/core/CrashLogger_win.cpp +++ b/src/ll/core/CrashLogger_win.cpp @@ -10,12 +10,14 @@ #include "ll/api/io/Logger.h" #include "ll/api/io/LoggerRegistry.h" #include "ll/api/io/PatternFormatter.h" +#include "ll/api/mod/Mod.h" #include "ll/api/utils/ErrorUtils.h" #include "ll/api/utils/StacktraceUtils.h" #include "ll/api/utils/StringUtils.h" #include "ll/api/utils/SystemUtils.h" #include "ll/core/Config.h" #include "ll/core/LeviLamina.h" +#include "ll/core/SentryUploader.h" #include "ll/core/io/Output.h" #include "pl/Config.h" @@ -43,7 +45,6 @@ class CrashLoggerNew { static std::unique_ptr cln; - std::string toString(_CONTEXT const& c) { return fmt::format("RAX: 0x{:016X} RBX: 0x{:016X} RCX: 0x{:016X}\n", c.Rax, c.Rbx, c.Rcx) + fmt::format("RDX: 0x{:016X} RSI: 0x{:016X} RDI: 0x{:016X}\n", c.Rdx, c.Rsi, c.Rdi) @@ -64,6 +65,55 @@ std::string toString(_CONTEXT const& c) { ); } +bool saveCrashInfo( + std::filesystem::path const& logPath, + std::string const& minidumpName, + std::string const& traceName +) { + auto path = logPath / fmt::format("sentry_{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(_time64(nullptr))); + return file_utils::writeFile(path, fmt::format("{}\n{}", minidumpName, traceName)); +} + +// Read log and dump file path from logs/crash/sentry_xxx, then submit them to sentry +void submitCrashInfo() { + auto path = file_utils::u8path(pl::pl_log_path) / u8"crash"; + for (auto& entry : std::filesystem::directory_iterator(path)) { + if (entry.path().filename().native().starts_with(L"sentry_")) { + try { + auto content = file_utils::readFile(entry.path()); + if (!content) { + continue; + } + auto paths = string_utils::splitByPattern(*content, "\n"); + if (paths.size() != 2) { + continue; + } + auto dmpFilePath = file_utils::u8path(pl::pl_log_path) / u8"crash" / paths[0]; + auto logFilePath = file_utils::u8path(pl::pl_log_path) / u8"crash" / paths[1]; + SentryUploader sentryUploader{ + std::string(getServiceUuid()), + u8str2str(dmpFilePath.filename().u8string()), + u8str2str(dmpFilePath.u8string()), + u8str2str(logFilePath.filename().u8string()), + u8str2str(logFilePath.u8string()), + getLoaderVersion().to_string().find('+') != std::string::npos, + getLoaderVersion().to_string() + }; + sentryUploader.addModSentryInfo( + getSelfModIns()->getName(), + "https://43a888504c33385bfd2e570c9ac939aa@o4508652421906432.ingest.us.sentry.io/4508652563398656", + getLoaderVersion().to_string() + ); + sentryUploader.uploadAll(); + std::filesystem::remove(entry.path()); + } catch (...) { + getLogger().error("Fail to upload crash info {}:", entry.path().filename()); + error_utils::printCurrentException(getLogger()); + } + } + } +} + void CrashLogger::init() { auto& config = getLeviConfig(); @@ -74,8 +124,11 @@ void CrashLogger::init() { crashLoggerPtr->warn("Debugger detected, CrashLogger will not be enabled"_tr()); return; } - if (config.modules.crashLogger.useBuiltin) { + if (config.modules.crashLogger.builtin) { cln = std::make_unique(); + if (config.modules.crashLogger.uploadToSentry) { + submitCrashInfo(); + } return; } @@ -90,14 +143,25 @@ void CrashLogger::init() { sa.nLength = sizeof(SECURITY_ATTRIBUTES); std::wstring cmd = string_utils::str2wstr(fmt::format( - "{} {} \"{}\"", + R"({} -p {} -b "{}" --lv "{}" --isdev {} --username "{}" --moddir "{}" --enablesentry {})", getSelfModIns()->getModDir() / sv2u8sv(config.modules.crashLogger.externalpath.value_or("CrashLogger.exe")), GetCurrentProcessId(), - ll::getGameVersion().to_string() + getGameVersion().to_string(), + getLoaderVersion().to_string(), + getLoaderVersion().to_string().find('+') != std::string::npos, + getServiceUuid(), + mod::getModsRoot(), + config.modules.crashLogger.uploadToSentry )); + if (!CreateProcess(nullptr, cmd.data(), &sa, &sa, true, 0, nullptr, nullptr, &si, &pi)) { crashLoggerPtr->error("Couldn't Create CrashLogger Daemon Process"_tr()); error_utils::printException(error_utils::getLastSystemError(), *crashLoggerPtr); + // If failed to create CrashLogger Daemon Process, use built-in CrashLogger + cln = std::make_unique(); + if (config.modules.crashLogger.uploadToSentry) { + submitCrashInfo(); + } return; } @@ -105,53 +169,28 @@ void CrashLogger::init() { CloseHandle(pi.hThread); crashLoggerPtr->info("CrashLogger enabled successfully"_tr()); - return; } static struct CrashInfo { - HANDLE process{}; - HANDLE thread{}; - DWORD processId{}; - DWORD threadId{}; - std::string date; - std::shared_ptr loggerPtr; - io::Logger& logger; - std::filesystem::path path{}; - decltype(ll::getLeviConfig().modules.crashLogger) settings{}; + HANDLE process{}; + HANDLE thread{}; + DWORD processId{}; + DWORD threadId{}; + std::string date; + std::shared_ptr loggerPtr; + io::Logger& logger; + std::filesystem::path path{}; + decltype(getLeviConfig().modules.crashLogger) settings{}; CrashInfo() : loggerPtr(io::LoggerRegistry::getInstance().getOrCreate("CrashLogger")), logger(*loggerPtr) {} } crashInfo; static void dumpSystemInfo() { crashInfo.logger.info("System Info:"); - crashInfo.logger.info(" |OS Version: {} {}", sys_utils::getSystemName(), []() -> std::string { - RTL_OSVERSIONINFOW osVersionInfoW = [] { - RTL_OSVERSIONINFOW osVersionInfoW{}; - HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); - if (hMod) { - using RtlGetVersionPtr = uint(WINAPI*)(PRTL_OSVERSIONINFOW); - auto fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); - if (fxPtr != nullptr) { - osVersionInfoW.dwOSVersionInfoSize = sizeof(osVersionInfoW); - if (0 == fxPtr(&osVersionInfoW)) { - return osVersionInfoW; - } - } - } - return osVersionInfoW; - }(); - if (osVersionInfoW.dwMajorVersion == 0) { - return "Unknown"; - } - std::string osVersion = - std::to_string(osVersionInfoW.dwMajorVersion) + '.' + std::to_string(osVersionInfoW.dwMinorVersion); - if (osVersionInfoW.dwBuildNumber != 0) { - osVersion += '.' + std::to_string(osVersionInfoW.dwBuildNumber); - } - if (osVersionInfoW.szCSDVersion[0] != 0) { - osVersion += ' ' + wstr2str(osVersionInfoW.szCSDVersion); - } - return osVersion; - }() + (sys_utils::isWine() ? " (wine)" : "")); + crashInfo.logger.info( + " |OS Version: {} {}", + sys_utils::getSystemName(), + sys_utils::getSystemVersion().to_string() + (sys_utils::isWine() ? " (wine)" : "") + ); crashInfo.logger.info(" |CPU: {}", []() -> std::string { int cpuInfo[4] = {-1}; __cpuid(cpuInfo, (int)0x80000000); @@ -228,10 +267,7 @@ static BOOL CALLBACK dumpModules( return TRUE; } -static bool genMiniDumpFile(PEXCEPTION_POINTERS e) { - - auto dumpFilePath = crashInfo.path / string_utils::str2u8str("minidump_" + crashInfo.date + ".dmp"); - +static bool genMiniDumpFile(PEXCEPTION_POINTERS e, std::filesystem::path& dumpFilePath) { std::error_code ec; if (auto c = std::filesystem::canonical(dumpFilePath, ec); ec.value() == 0) { dumpFilePath = c; @@ -272,8 +308,19 @@ static bool genMiniDumpFile(PEXCEPTION_POINTERS e) { static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { try { crashInfo.date = fmt::format("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(_time64(nullptr))); - crashInfo.settings = ll::getLeviConfig().modules.crashLogger; + crashInfo.settings = getLeviConfig().modules.crashLogger; crashInfo.path = file_utils::u8path(pl::pl_log_path) / u8"crash"; + auto logFilePath = crashInfo.path / ("trace_" + crashInfo.date + ".log"); + auto dumpFilePath = crashInfo.path / string_utils::str2u8str("minidump_" + crashInfo.date + ".dmp"); + // Save log and dump file path to logs/crash/sentry_xxx for later use + if (getLeviConfig().modules.crashLogger.uploadToSentry) { + saveCrashInfo( + crashInfo.path, + u8str2str(dumpFilePath.filename().u8string()), + u8str2str(dumpFilePath.filename().u8string()) + ); + } + if (!std::filesystem::is_directory(crashInfo.path)) { std::filesystem::create_directory(crashInfo.path); } @@ -297,7 +344,7 @@ static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { }; crashInfo.logger.getSink(0)->setFormatter(std::move(formatter)); crashInfo.logger.addSink(std::make_shared( - crashInfo.path / ("trace_" + crashInfo.date + ".log"), + logFilePath, makePolymorphic("{tm:.3%F %T.} [{lvl}] {msg}", false) )); crashInfo.logger.setLevel(io::LogLevel::Trace); @@ -312,10 +359,10 @@ static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { crashInfo.logger.info("Process Crashed! Generating Stacktrace and MiniDump..."); try { - genMiniDumpFile(e); + genMiniDumpFile(e, dumpFilePath); } catch (...) { crashInfo.logger.error("!!! Error In GenMiniDumpFile !!!"); - ll::error_utils::printCurrentException(crashInfo.logger); + error_utils::printCurrentException(crashInfo.logger); } stacktrace_utils::SymbolLoader symbol{}; @@ -351,11 +398,11 @@ static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { } } catch (...) { crashInfo.logger.error("!!! Error in CrashLogger !!!"); - ll::error_utils::printCurrentException(crashInfo.logger); + error_utils::printCurrentException(crashInfo.logger); crashInfo.logger.error(""); - crashInfo.logger.error("\n{}", ll::stacktrace_utils::toString(Stacktrace::current())); + crashInfo.logger.error("\n{}", stacktrace_utils::toString(Stacktrace::current())); } - std::exit((int)e->ExceptionRecord->ExceptionCode); + std::quick_exit((int)e->ExceptionRecord->ExceptionCode); } static LONG uncatchableExceptionHandler(_In_ struct _EXCEPTION_POINTERS* e) { diff --git a/src/ll/core/LeviLamina.cpp b/src/ll/core/LeviLamina.cpp index 47521a7265..48b618826f 100644 --- a/src/ll/core/LeviLamina.cpp +++ b/src/ll/core/LeviLamina.cpp @@ -1,8 +1,11 @@ #include "ll/core/LeviLamina.h" #include "ll/api/Versions.h" #include "ll/api/i18n/I18n.h" +#include "ll/api/io/FileUtils.h" #include "ll/core/Version.h" +#include "mc/platform/UUID.h" + namespace ll { std::shared_ptr const& getSelfModIns() { static auto llSelf = std::make_shared( @@ -19,6 +22,18 @@ std::shared_ptr const& getSelfModIns() { } io::Logger& getLogger() { return getSelfModIns()->getLogger(); } +std::string_view getServiceUuid() { + static std::string serverUuid = [] { + auto uuidPath = getSelfModIns()->getDataDir() / u8"statisticsUuid"; + return *file_utils::readFile(uuidPath).or_else([&] { + std::string uuid = mce::UUID::random().asString(); + file_utils::writeFile(uuidPath, uuid); + return std::optional{std::move(uuid)}; + }); + }(); + return serverUuid; +} + data::Version getLoaderVersion() { static auto ver = [] { auto v = data::Version{ @@ -26,10 +41,14 @@ data::Version getLoaderVersion() { LL_VERSION_MINOR, LL_VERSION_PATCH, }; - v.build = LL_VERSION_TO_STRING(LL_VERSION_COMMIT_SHA); #ifdef LL_VERSION_PRERELEASE v.preRelease = ll::data::PreRelease{LL_VERSION_PRERELEASE}; #endif + +#ifndef LL_VERSION_PUBLISH + v.build = LL_VERSION_TO_STRING(LL_VERSION_COMMIT_SHA); +#endif + return v; }(); return ver; diff --git a/src/ll/core/LeviLamina.h b/src/ll/core/LeviLamina.h index f2b2576ab6..96089da0a5 100644 --- a/src/ll/core/LeviLamina.h +++ b/src/ll/core/LeviLamina.h @@ -8,6 +8,8 @@ constexpr const std::string_view selfModName = "LeviLamina"; std::shared_ptr const& getSelfModIns(); +std::string_view getServiceUuid(); + io::Logger& getLogger(); void printWelcomeMsg(); diff --git a/src/ll/core/SentryUploader.cpp b/src/ll/core/SentryUploader.cpp new file mode 100644 index 0000000000..634b4a2e75 --- /dev/null +++ b/src/ll/core/SentryUploader.cpp @@ -0,0 +1,204 @@ +#include +#include +#include + +#include + +#include "ll/api/i18n/I18n.h" +#include "ll/api/io/Logger.h" +#include "ll/api/io/LoggerRegistry.h" +#include "ll/api/utils/ErrorUtils.h" +#include "ll/api/utils/SystemUtils.h" +#include "ll/core/SentryUploader.h" +#include "mc/platform/UUID.h" + +using json = nlohmann::json; + +namespace ll { +auto sentryLogger = io::LoggerRegistry::getInstance().getOrCreate("SentryUploader"); + +std::string compressDataGzip(std::string const& data) { + std::string compressedBuffer; + z_stream deflateStream{}; + if (deflateInit2(&deflateStream, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + throw std::runtime_error("Failed to initialize compression stream"); + } + if (data.size() > std::numeric_limits::max()) { + deflateEnd(&deflateStream); + throw std::runtime_error("Data too large for compression"); + } + deflateStream.avail_in = static_cast(data.size()); + deflateStream.next_in = (Bytef*)data.data(); + size_t bufferSize = data.size(); + compressedBuffer.resize(bufferSize); + deflateStream.avail_out = static_cast(bufferSize); + deflateStream.next_out = (Bytef*)compressedBuffer.data(); + if (deflate(&deflateStream, Z_FINISH) != Z_STREAM_END) { + deflateEnd(&deflateStream); + throw std::runtime_error("Gzip compression failed"); + } + compressedBuffer.resize(deflateStream.total_out); + deflateEnd(&deflateStream); + return compressedBuffer; +} + +SentryUploader::SentryUploader( + std::string user, + std::string minidmpName, + std::string minidumpPath, + std::string traceName, + std::string tracePath, + bool isDev, + std::string leviLaminaVersion +) +: mIsDev(isDev), + mLeviLaminaVersion(std::move(leviLaminaVersion)), + mUser(std::move(user)), + mMiniDumpName(std::move(minidmpName)), + mMinidumpPath(std::move(minidumpPath)), + mTraceName(std::move(traceName)), + mTracePath(std::move(tracePath)) { + mMinidumpContent = readFile(mMinidumpPath); + mAdditionalFileContent = readFile(mTracePath); + mOSInfo.name = sys_utils::isWine() ? "Linux(Wine)" : "Windows"; + mOSInfo.version = sys_utils::getSystemVersion().to_string(); +} + +void SentryUploader::addModSentryInfo( + std::string const& modName, + std::string const& dsn, + std::string const& releaseVersion +) try { + auto protocolEnd = dsn.find("://"); + auto authEnd = dsn.find('@', protocolEnd + 3); + auto lastSlash = dsn.rfind('/'); + + if (protocolEnd == std::string::npos || authEnd == std::string::npos || lastSlash == std::string::npos) { + throw std::invalid_argument("Invalid DSN format"); + } + + SentryInfo::DSNInfo info; + info.protocol = dsn.substr(0, protocolEnd); + auto auth = dsn.substr(protocolEnd + 3, authEnd - protocolEnd - 3); + info.publicKey = auth.substr(0, auth.find(':')); + info.host = dsn.substr(authEnd + 1, lastSlash - authEnd - 1); + info.projectId = dsn.substr(lastSlash + 1); + + mModsSentryConfig.push_back({info, dsn, modName, releaseVersion}); +} catch (...) { + sentryLogger->error("Error adding mod sentry info:"); + error_utils::printCurrentException(*sentryLogger); + return; +} + +void SentryUploader::uploadAll() { + std::vector threads; + + threads.reserve(mModsSentryConfig.size()); + sentryLogger->info("Uploading crash report to Sentry..."_tr()); + for (auto const& sentryConfig : mModsSentryConfig) { + threads.emplace_back([=, this]() { + try { + std::string url = sentryConfig.dsnInfo.protocol + "://" + sentryConfig.dsnInfo.host + "/api/" + + sentryConfig.dsnInfo.projectId + "/envelope/"; + std::string eventId = mce::UUID::random().asString(); + + json envelopeHeader = { + {"event_id", eventId}, + { "dsn", sentryConfig.dsn} + }; + + json eventPayload = { + { "event_id", eventId }, + { "level", "fatal"}, + { "platform", "native"}, + { "sdk", {{"name", "crashLogger"}, {"version", "built-in"}}}, + { "release", sentryConfig.releaseVersion}, + {"environment", mIsDev ? "development" : "production"}, + { "user", {{"id", mUser}}}, + { "contexts", + {{"os", {{"name", mOSInfo.name}, {"version", mOSInfo.version}}}, + {"runtime", {{"type", "runtime"}, {"name", "LeviLamina"}, {"version", mLeviLaminaVersion}}}} }, + }; + + sendToSentry(sentryConfig, url, envelopeHeader, eventPayload); + } catch (...) { + sentryLogger->error("Error uploading to DSN: {}", sentryConfig.dsn); + error_utils::printCurrentException(*sentryLogger); + } + }); + } + + for (auto& thread : threads) { + thread.join(); + } +} + +std::string SentryUploader::readFile(std::string const& filePath) { + std::ifstream file(filePath, std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Failed to open file: " + filePath); + } + return {std::istreambuf_iterator(file), std::istreambuf_iterator()}; +} + +void SentryUploader::sendToSentry( + SentryInfo const& sentryInfo, + std::string const& url, + nlohmann::json const& envelopeHeader, + nlohmann::json const& eventPayload +) { + json eventHeader = { + { "type", "event"}, + {"length", static_cast(eventPayload.dump().size())} + }; + + json minidumpItemHeader = { + { "type", "attachment"}, + { "length", static_cast(mMinidumpContent.size())}, + { "filename", mMiniDumpName}, + {"attachment_type", "event.minidump"} + }; + + json traceFileItemHeader = { + { "type", "attachment"}, + { "length", static_cast(mAdditionalFileContent.size())}, + { "filename", mTraceName}, + {"attachment_type", "event.attachment"} + }; + + std::ostringstream envelopeStream; + + envelopeStream << envelopeHeader.dump() << "\n" + << eventHeader.dump() << "\n" + << eventPayload.dump() << "\n" + << minidumpItemHeader.dump() << "\n" + << mMinidumpContent << "\n" + << traceFileItemHeader.dump() << "\n" + << mAdditionalFileContent << "\n"; + + std::string compressedData = compressDataGzip(envelopeStream.str()); + + auto response = cpr::Post( + cpr::Url{ + url + }, + cpr::Header{ + {"Content-Type", "application/x-sentry-envelope"}, + {"Content-Encoding", "gzip"}, + {"X-Sentry-Auth", + "Sentry sentry_version=7,sentry_client=sentry.dofes/0.1,sentry_key=" + sentryInfo.dsnInfo.publicKey}, + }, + cpr::Body{compressedData} + ); + + if (response.status_code == 200) { + sentryLogger->info("Mod: {} uploaded successfully to Sentry"_tr(sentryInfo.modName)); + sentryLogger->info("Event ID: {}"_tr(to_string(json::parse(response.text)["id"]))); + } else { + sentryLogger->error("Mod: {} Failed to upload to Sentry"_tr(sentryInfo.modName)); + sentryLogger->error("Status Code: {}"_tr(response.status_code)); + sentryLogger->error("Response: {}"_tr(response.text)); + } +} +} // namespace ll diff --git a/src/ll/core/SentryUploader.h b/src/ll/core/SentryUploader.h new file mode 100644 index 0000000000..b220039724 --- /dev/null +++ b/src/ll/core/SentryUploader.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include + + +using json = nlohmann::json; + +namespace ll { +class SentryUploader { +public: + SentryUploader( + std::string user, + std::string minidmpName, + std::string minidumpPath, + std::string traceName, + std::string tracePath, + bool isDev, + std::string leviLaminaVersion + ); + + void addModSentryInfo(std::string const& modName, std::string const& dsn, std::string const& releaseVersion); + void uploadAll(); + +private: + struct SentryInfo { + struct DSNInfo { + std::string protocol; + std::string host; + std::string publicKey; + std::string projectId; + } dsnInfo; + std::string dsn; + std::string modName; + std::string releaseVersion; + }; + + std::string readFile(std::string const& filePath); + + void sendToSentry( + SentryInfo const& sentryInfo, + std::string const& url, + nlohmann::json const& envelopeHeader, + nlohmann::json const& eventPayload + ); + + struct { + std::string name; + std::string version; + } mOSInfo; + + bool mIsDev; + std::string mLeviLaminaVersion; + std::string mUser; + std::string mMiniDumpName; + std::string mMinidumpPath; + std::string mTraceName; + std::string mTracePath; + std::string mMinidumpContent; + std::string mAdditionalFileContent; + std::vector mModsSentryConfig; +}; +} // namespace ll diff --git a/src/ll/core/mod/NativeModManager.cpp b/src/ll/core/mod/NativeModManager.cpp index 54109bd2c0..b6144510e1 100644 --- a/src/ll/core/mod/NativeModManager.cpp +++ b/src/ll/core/mod/NativeModManager.cpp @@ -48,15 +48,15 @@ formatDependencyError(pl::dependency_walker::DependencyIssueItem const& item, st stream << indent << "module: "_tr() << string_utils::u8str2str(item.mPath.filename().u8string()) << '\n'; if (!item.mMissingModule.empty()) { stream << indent << "missing module:"_tr() << '\n'; - for (const auto& missingModule : item.mMissingModule) { + for (auto const& missingModule : item.mMissingModule) { stream << indent << "|- " << missingModule << '\n'; } } if (!item.mMissingProcedure.empty()) { stream << indent << "missing content:"_tr() << '\n'; - for (const auto& [module, missingProcedure] : item.mMissingProcedure) { + for (auto const& [module, missingProcedure] : item.mMissingProcedure) { stream << indent << "|- " << module << '\n'; - for (const auto& procedure : missingProcedure) { + for (auto const& procedure : missingProcedure) { stream << indent << "|---- " << memory::SymbolView(procedure).toString() << '\n'; } } diff --git a/src/ll/core/tweak/ModifyInfomation.cpp b/src/ll/core/tweak/ModifyInfomation.cpp index 523dd80906..114450e34e 100644 --- a/src/ll/core/tweak/ModifyInfomation.cpp +++ b/src/ll/core/tweak/ModifyInfomation.cpp @@ -40,7 +40,7 @@ LL_STATIC_HOOK( auto serverLogger = io::LoggerRegistry::getInstance().getOrCreate("Server"); -int printfbufc(const char* format, va_list const& pargs) { +int printfbufc(char const* format, va_list const& pargs) { int retval; va_list argcopy; va_copy(argcopy, pargs); @@ -136,7 +136,7 @@ LL_TYPE_INSTANCE_HOOK( RakNet::RakPeer, &RakNet::RakPeer::$SetOfflinePingResponse, void, - const char* data, + char const* data, uint dataSize ) { std::string_view dataView{data, dataSize}; diff --git a/src/mc/world/level/levelgen/structure/BoundingBox.h b/src/mc/world/level/levelgen/structure/BoundingBox.h index 5988abec14..6435e7e544 100644 --- a/src/mc/world/level/levelgen/structure/BoundingBox.h +++ b/src/mc/world/level/levelgen/structure/BoundingBox.h @@ -23,10 +23,10 @@ class BoundingBox : public ll::math::CommutativeGroup constexpr bool forEachPos(F&& todo) const { diff --git a/src/mc/world/level/levelgen/structure/StructureTemplate.cpp b/src/mc/world/level/levelgen/structure/StructureTemplate.cpp index f2f223c7eb..cbd65ab1e0 100644 --- a/src/mc/world/level/levelgen/structure/StructureTemplate.cpp +++ b/src/mc/world/level/levelgen/structure/StructureTemplate.cpp @@ -28,7 +28,7 @@ void StructureTemplate::placeInWorld( } -std::unique_ptr StructureTemplate::create(const std::string& name, CompoundTag const& tag) { +std::unique_ptr StructureTemplate::create(std::string_view name, CompoundTag const& tag) { return ll::service::getLevel() .transform([&](auto& level) { auto res = std::make_unique(name, level.getUnknownBlockTypeRegistry()); @@ -42,7 +42,7 @@ std::unique_ptr StructureTemplate::create(const std::string& } std::unique_ptr StructureTemplate::create( - const std::string& name, + std::string_view name, BlockSource& blockSource, BoundingBox const& boundingBox, bool ignoreBlocks, diff --git a/src/mc/world/level/levelgen/structure/StructureTemplate.h b/src/mc/world/level/levelgen/structure/StructureTemplate.h index 73b9a7327d..939525a657 100644 --- a/src/mc/world/level/levelgen/structure/StructureTemplate.h +++ b/src/mc/world/level/levelgen/structure/StructureTemplate.h @@ -40,10 +40,10 @@ class StructureTemplate : public ::IStructureTemplate { bool ignoreEntities = false ) const; - LLNDAPI static std::unique_ptr create(const std::string& name, CompoundTag const& tag); + LLNDAPI static std::unique_ptr create(std::string_view name, CompoundTag const& tag); LLNDAPI static std::unique_ptr create( - const std::string& name, + std::string_view name, BlockSource& blockSource, BoundingBox const& boundingBox, bool ignoreBlocks = false, diff --git a/tooth.json b/tooth.json index f665411b42..2423762aaf 100644 --- a/tooth.json +++ b/tooth.json @@ -11,7 +11,7 @@ "asset_url": "https://github.com/LiteLDev/LeviLamina/releases/download/v1.0.0-rc.3/levilamina-release-windows-x64.zip", "dependencies": { "github.com/LiteLDev/bds": "1.21.50", - "github.com/LiteLDev/CrashLogger": "1.1.x", + "github.com/LiteLDev/CrashLogger": "1.2.x", "github.com/LiteLDev/levilamina-loc": "1.5.x", "github.com/LiteLDev/PeEditor": "3.8.x", "github.com/LiteLDev/PreLoader": "1.12.x", diff --git a/xmake.lua b/xmake.lua index d9bd2cd574..d9ca7677c3 100644 --- a/xmake.lua +++ b/xmake.lua @@ -67,10 +67,16 @@ else end end +option("publish") + set_default(false) + set_showmenu(true) +option_end() + option("tests") set_default(false) set_showmenu(true) set_description("Enable tests") +option_end() option("target_type") set_default("server") @@ -282,6 +288,10 @@ target("LeviLamina") end) end + if has_config("publish") then + add_defines("LL_VERSION_PUBLISH") + end + if is_mode("debug") then add_defines("LL_DEBUG") end