From 85a6fad13959501365ea28aa0bab1a466538ba57 Mon Sep 17 00:00:00 2001 From: jyelon Date: Sun, 12 Apr 2026 23:08:09 -0400 Subject: [PATCH] Bugfix for wayland --- AGENTS.md | 87 +++++--------------------- Content/Testing/BP_Test.uasset | 4 +- Content/Widgets/WB_Hotkey_Image.uasset | 4 +- Content/Widgets/WB_Hotkeys.uasset | 4 +- Docs/Architecture-Summary.md | 59 +++++++++++++++++ EnginePatches/EnginePatch | 59 +++++++++++------ build.py | 2 +- 7 files changed, 124 insertions(+), 95 deletions(-) create mode 100644 Docs/Architecture-Summary.md diff --git a/AGENTS.md b/AGENTS.md index 4e027727..9477ee9c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,17 +1,18 @@ # Integration Project -This is **Luprex**, a game engine built on top of Unreal that uses Lua as its scripting language. -The system consists of two parts: +## Behavior Rules -1. The Luprex DLL. Stores the state of the world. Handles networking and lua scripting. The networking is automatic, scripters don't write networking code. The luprex DLL is event-driven, deterministic, OS-independent, no I/O. Pure standard-compliant C++. Organized as a library with struct `EngineWrapper` as the top-level API. +- Be Concise! + * Do not output multiple paragraphs. Doing so is very rude. + * You are having a conversation, give the other person a chance to speak. -2. The Unreal-based Driver. Its job is to peer into the luprex DLL and render whatever it sees. It is also responsible for sending OS events (like TCP/IP events) into the Luprex DLL. Uses struct EngineWrapper access the Luprex DLL. There's also a command-line driver for the game's server. +- Do not use git to make changes (no commit, no push, no stash, etc.) -The luprex DLL never calls into the Unreal driver. Output goes through polled buffers. This separation enables deterministic replay for debugging: the driver logs all events, and can replay them to reproduce crashes. +- Work at the user's pace. Do not start coding until the user says it is time. ## Build System -- Use `build.py` for all builds. Do NOT follow Epic's standard build instructions. +- Use `build.py` for all builds. Do NOT use UBT directly. - `build.py all` — full rebuild (engine, game, intellisense, project files) - `build.py c++` — lightweight rebuild (use if you've only edited c++ files) - Lua and Blueprint edits don't require any kind of build. @@ -19,78 +20,24 @@ The luprex DLL never calls into the Unreal driver. Output goes through polled bu ## Directory Structure - `luprex/` — The Luprex DLL. -- `Source/Integration/` — Game module C++ source (Unreal-side driver code) +- `Source/Integration/` — Unreal interface to Luprex. - `Content/` — Unreal assets -- `Docs/` — Documentation. When trying to understand this system, start with the markdown files in the Docs directory. +- `Docs/` — Documentation. - `Config/` — Unreal config files - `EnginePatches/` — Custom engine modifications - `Plugins/UEWingman/' - An MCP that gives you control over the unreal editor. - `../integration.UE/` - the unreal engine source tree -## Architecture: World Models and Predictive Reexecution - -There are four types of world models, each a separate `World` instance with its own Lua interpreter: - -- **Master** (server, one) — authoritative state, executes commands immediately when they arrive. -- **Server-synchronous** (server, one per client) — executes commands when the acknowledgement is issued. -- **Client-synchronous** (client, one) — executes commands when the same acknowledgement arrives; determinism keeps it in perfect sync with its server-synchronous counterpart. -- **Asynchronous** (client, one) — snapshot of client-synchronous with predictions applied for responsive rendering; rolled back when server confirms. - -The synchronous models lag behind the master but stay in lockstep with each other. The asynchronous model fills the latency gap for the player. - -Two update channels flow into the synchronous models: -1. **Command acknowledgements** — for the client's own actions, keeping the two synchronous models in lockstep. -2. **Difference transmission** — for everything else (other players' actions, server-side events, tangibles entering/leaving visibility). - -See `Docs/Predictive-Reexecution.md` for the full explanation. - -## Architecture: Lua / Unreal Separation - -Lua scripts have no access to the Unreal API whatsoever. The scripter works with plain Lua tables, animation queues of key-value tuples, and coroutines. There are no "unreal bindings." The Luprex DLL is engine-agnostic — Unreal (or any other front end) interprets the animation queues and renders accordingly. - -## Architecture: Tangibles - -Tangibles are game objects. Each has: -- A **Lua table** — the scripter stores arbitrary game data here. -- An **animation queue** — a fixed-length sequence of key-value animation steps. -- A **C++ tangible** — holds the ID, animation queue, positional tracker, etc. -- A **metatable** — engine-reserved; contains __id, __index (class), __threads. - -Animation steps contain **transient** values (like `action`) that don't propagate, and **persistent** values (like `xyz`, `facing`, `plane`) that carry forward automatically. - -On the Unreal side, **Tangible Actor blueprints** (TangibleStaticMesh, TangibleSkeletalMesh, TangibleCharacter) monitor the animation queue and perform the visual animations. Custom blueprints can interpret the queue in any way they want. - -## Architecture: Lua Environment - -- **Patched Lua runtime** — deterministic table iteration, deterministic table length, flag bits on tables, generalized less-than, C++ exceptions instead of longjmp, and more. See `Docs/A-Summary-of-our-Lua-Patches.md`. -- **LuaStack API** — custom C++ API replacing the standard Lua C API. Uses `LuaDefStack`/`LuaExtStack` with `LuaArg`/`LuaVar`/`LuaRet` slots mapped to stack positions. See `Docs/Our-In-House-Lua-API.md`. -- **LuaDefine macro** — declares Lua-callable C++ functions and auto-registers them in a global registry for automatic insertion into the Lua environment. -- **eng::malloc heap** — custom deterministic memory allocator for the driven portion, ensuring reproducible addresses during replay. - -## Architecture: GUI System - -Blueprints call into Lua via two mechanisms: -- **Invokes** — change world state, forwarded to server, executed in order per predictive reexecution rules. -- **Probes** — read-only, return data to blueprints, run locally on client. - -Look-at widgets, hotkeys, and menus are built on top of this. The menu system is implemented entirely in "user space" Lua and blueprint code. See `Docs/Displaying-Widget-Blueprints.md`. - -## Key Documentation - -Look in the Docs directory for important documentation. - -## Workflow - -- Do not use git to make changes (commit, push, branch, etc.). Read-only git commands (status, log, diff, etc.) are fine. -- Work at the user's pace. Do not start coding until the user says it is time. -- If an instruction ends with an ellipsis (`...`), the user has more to say. Wait for the next message before acting. -- Do not output multiple paragraphs. Doing so is very rude. You are having a conversation, give the other person a - chance to speak. For most questions, 3-4 sentences is the maximum, unless you've been asked to give a - detailed explanation. - ## Coding Conventions - Prefer early returns and `continue` to reduce nesting (never-nester style). - Do not use static functions in Unreal code. Use class methods instead. -- Use `LogLuprexIntegration` for log messages inside Source/. Use LogTemp inside Plugins/. + +## Special commands. + +You must learn these shorthands: + +- "bc" - be concise. You must rephrase your most recent + response in a more concise manner, and then, going forward, be + more concise in general. diff --git a/Content/Testing/BP_Test.uasset b/Content/Testing/BP_Test.uasset index fb02e8ed..bb5ce1a5 100644 --- a/Content/Testing/BP_Test.uasset +++ b/Content/Testing/BP_Test.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5ae97431b3c210858449639e2c4f3073037db42cda99d77881327d3154b67e5 -size 45291 +oid sha256:bbcf31978d230e3f317ba105da139139ff3dfe8511a4a083da1d59d0976cc576 +size 56301 diff --git a/Content/Widgets/WB_Hotkey_Image.uasset b/Content/Widgets/WB_Hotkey_Image.uasset index af0f3580..0171198f 100644 --- a/Content/Widgets/WB_Hotkey_Image.uasset +++ b/Content/Widgets/WB_Hotkey_Image.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23830a9f0cf927941588e7c966190212d5b15c85c34e634b3a3d8ea36268f42a -size 101608 +oid sha256:5437cb06ec6b2d6509de6d4049d30c69e35745502d650c03b34d0d2f22ba7baf +size 101565 diff --git a/Content/Widgets/WB_Hotkeys.uasset b/Content/Widgets/WB_Hotkeys.uasset index 990ee526..2a3a7852 100644 --- a/Content/Widgets/WB_Hotkeys.uasset +++ b/Content/Widgets/WB_Hotkeys.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6232b9c8443422d01e13a2a15940db36ea5ed8f5cf1be8ace5fb38694e149dc4 -size 347817 +oid sha256:602a372b5e164a5a33e06090523e4de6261699a7c46b5d1c4705ea3c549c8545 +size 260266 diff --git a/Docs/Architecture-Summary.md b/Docs/Architecture-Summary.md new file mode 100644 index 00000000..d72ef673 --- /dev/null +++ b/Docs/Architecture-Summary.md @@ -0,0 +1,59 @@ +# The Luprex System + +This is **Luprex**, a game engine built on top of Unreal that uses Lua as its scripting language. +The system consists of two parts: + +1. The Luprex DLL. Stores the state of the world. Handles networking and lua scripting. The networking is automatic, scripters don't write networking code. The luprex DLL is event-driven, deterministic, OS-independent, no I/O. Pure standard-compliant C++. Organized as a library with struct `EngineWrapper` as the top-level API. + +2. The Unreal-based Driver. Its job is to peer into the luprex DLL and render whatever it sees. It is also responsible for sending OS events (like TCP/IP events) into the Luprex DLL. Uses struct EngineWrapper access the Luprex DLL. There's also a command-line driver for the game's server. + +The luprex DLL never calls into the Unreal driver. Output goes through polled buffers. This separation enables deterministic replay for debugging: the driver logs all events, and can replay them to reproduce crashes. + +## Architecture: World Models and Predictive Reexecution + +There are four types of world models, each a separate `World` instance with its own Lua interpreter: + +- **Master** (server, one) — authoritative state, executes commands immediately when they arrive. +- **Server-synchronous** (server, one per client) — executes commands when the acknowledgement is issued. +- **Client-synchronous** (client, one) — executes commands when the same acknowledgement arrives; determinism keeps it in perfect sync with its server-synchronous counterpart. +- **Asynchronous** (client, one) — snapshot of client-synchronous with predictions applied for responsive rendering; rolled back when server confirms. + +The synchronous models lag behind the master but stay in lockstep with each other. The asynchronous model fills the latency gap for the player. + +Two update channels flow into the synchronous models: +1. **Command acknowledgements** — for the client's own actions, keeping the two synchronous models in lockstep. +2. **Difference transmission** — for everything else (other players' actions, server-side events, tangibles entering/leaving visibility). + +See `Docs/Predictive-Reexecution.md` for the full explanation. + +## Architecture: Lua / Unreal Separation + +Lua scripts have no access to the Unreal API whatsoever. The scripter works with plain Lua tables, animation queues of key-value tuples, and coroutines. There are no "unreal bindings." The Luprex DLL is engine-agnostic — Unreal (or any other front end) interprets the animation queues and renders accordingly. + +## Architecture: Tangibles + +Tangibles are game objects. Each has: +- A **Lua table** — the scripter stores arbitrary game data here. +- An **animation queue** — a fixed-length sequence of key-value animation steps. +- A **C++ tangible** — holds the ID, animation queue, positional tracker, etc. +- A **metatable** — engine-reserved; contains __id, __index (class), __threads. + +Animation steps contain **transient** values (like `action`) that don't propagate, and **persistent** values (like `xyz`, `facing`, `plane`) that carry forward automatically. + +On the Unreal side, **Tangible Actor blueprints** (TangibleStaticMesh, TangibleSkeletalMesh, TangibleCharacter) monitor the animation queue and perform the visual animations. Custom blueprints can interpret the queue in any way they want. + +## Architecture: Lua Environment + +- **Patched Lua runtime** — deterministic table iteration, deterministic table length, flag bits on tables, generalized less-than, C++ exceptions instead of longjmp, and more. See `Docs/A-Summary-of-our-Lua-Patches.md`. +- **LuaStack API** — custom C++ API replacing the standard Lua C API. Uses `LuaDefStack`/`LuaExtStack` with `LuaArg`/`LuaVar`/`LuaRet` slots mapped to stack positions. See `Docs/Our-In-House-Lua-API.md`. +- **LuaDefine macro** — declares Lua-callable C++ functions and auto-registers them in a global registry for automatic insertion into the Lua environment. +- **eng::malloc heap** — custom deterministic memory allocator for the driven portion, ensuring reproducible addresses during replay. + +## Architecture: GUI System + +Blueprints call into Lua via two mechanisms: +- **Invokes** — change world state, forwarded to server, executed in order per predictive reexecution rules. +- **Probes** — read-only, return data to blueprints, run locally on client. + +Look-at widgets, hotkeys, and menus are built on top of this. The menu system is implemented entirely in "user space" Lua and blueprint code. See `Docs/Displaying-Widget-Blueprints.md`. + diff --git a/EnginePatches/EnginePatch b/EnginePatches/EnginePatch index b3781f9b..66b65452 100644 --- a/EnginePatches/EnginePatch +++ b/EnginePatches/EnginePatch @@ -1,6 +1,5 @@ -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py /home/jyelon/integration.UE/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py ---- /home/jyelon/integration.UE.orig/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py 2025-09-08 15:15:35.242987722 -0400 +--- Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py.orig 2026-04-12 22:58:33.989318455 -0400 ++++ Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py 2025-11-10 23:34:18.481538118 -0500 @@ -32,7 +32,7 @@ if DataVal == 0: Val = 'NULL' @@ -22,9 +21,8 @@ diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '-- return Val def UESignedCharSummaryProvider(valobj,dict): -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp /home/jyelon/integration.UE/Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp ---- /home/jyelon/integration.UE.orig/Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp 2026-03-02 15:28:34.593675093 -0500 +--- Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp.orig 2026-04-12 22:58:34.075320964 -0400 ++++ Engine/Plugins/Developer/VisualStudioCodeSourceCodeAccess/Source/VisualStudioCodeSourceCodeAccess/Private/VisualStudioCodeSourceCodeAccessor.cpp 2026-04-12 23:03:40.139226303 -0400 @@ -149,7 +149,7 @@ FString SolutionDir = GetSolutionPath(); TArray Args; @@ -34,9 +32,8 @@ diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '-- return Launch(Args); } -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp /home/jyelon/integration.UE/Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp ---- /home/jyelon/integration.UE.orig/Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp 2026-03-02 15:37:59.934459864 -0500 +--- Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp.orig 2026-04-12 22:58:34.169323705 -0400 ++++ Engine/Source/Editor/UnrealEd/Private/SourceCodeNavigation.cpp 2026-04-12 23:04:02.208867909 -0400 @@ -463,7 +463,7 @@ ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked("SourceCodeAccess"); ISourceCodeAccessor& SourceCodeAccessor = SourceCodeAccessModule.GetAccessor(); @@ -57,9 +54,8 @@ diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '-- } -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp /home/jyelon/integration.UE/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp ---- /home/jyelon/integration.UE.orig/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp 2025-09-08 15:15:35.242987722 -0400 +--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp.orig 2026-04-12 22:58:34.254326184 -0400 ++++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp 2025-11-10 23:34:18.481701126 -0500 @@ -299,6 +299,9 @@ SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // When relative mouse mode is active, don't hide cursor. SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "0"); // Don't warp the cursor to the center in relative mouse mode. @@ -70,9 +66,37 @@ diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '-- // If we're rendering offscreen, use the "dummy" SDL video driver if (FParse::Param(FCommandLine::Get(), TEXT("RenderOffScreen")) && !getenv("SDL_VIDEODRIVER")) { -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp /home/jyelon/integration.UE/Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp ---- /home/jyelon/integration.UE.orig/Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp 2026-03-02 15:37:24.464156072 -0500 +--- Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp.orig 2026-04-12 22:58:34.538334467 -0400 ++++ Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxWindow.cpp 2026-04-12 22:48:15.848291098 -0400 +@@ -235,7 +235,26 @@ + + // The SDL window doesn't need to be reshaped. + // the size of the window you input is the sizeof the client. ++ ++ // Under XWayland, non-override-redirect popup windows don't receive input ++ // events from the compositor. SDL already sets override_redirect for ++ // tooltips and popup menus, but other borderless child windows (like ++ // notification popups and dialogs) also need it. We temporarily enable ++ // the SDL hint to force override_redirect for these windows. ++ bool bForceOverrideRedirect = !Definition->HasOSWindowBorder ++ && InParent.IsValid() ++ && !(WindowStyle & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)); ++ if (bForceOverrideRedirect) ++ { ++ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "1"); ++ } ++ + HWnd = SDL_CreateWindow( TCHAR_TO_ANSI( *Definition->Title ), X, Y, ClientWidth, ClientHeight, WindowStyle ); ++ ++ if (bForceOverrideRedirect) ++ { ++ SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "0"); ++ } + // produce a helpful message for common driver errors + if (HWnd == nullptr) + { +--- Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp.orig 2026-04-12 22:58:34.349328955 -0400 ++++ Engine/Source/Runtime/Core/Private/Unix/UnixPlatformStackWalk.cpp 2026-04-12 23:05:56.395187515 -0400 @@ -15,6 +15,7 @@ #include "HAL/ExceptionHandling.h" #include "HAL/PlatformProcess.h" @@ -151,9 +175,8 @@ diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '-- + + return false; +} -diff -u --recursive '--exclude=*.o' '--exclude=*.d' '--exclude=Intermediate' '--exclude=Binaries' '--exclude=Saved' '--exclude=DerivedDataCache' '--exclude=*.pyc' '--exclude=__pycache__' /home/jyelon/integration.UE.orig/Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h /home/jyelon/integration.UE/Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h ---- /home/jyelon/integration.UE.orig/Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h 2025-03-11 10:33:14.000000000 -0400 -+++ /home/jyelon/integration.UE/Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h 2026-03-02 15:36:22.690627000 -0500 +--- Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h.orig 2026-04-12 22:58:34.451331930 -0400 ++++ Engine/Source/Runtime/Core/Public/Unix/UnixPlatformStackWalk.h 2026-04-12 23:06:10.273590986 -0400 @@ -24,6 +24,8 @@ static CORE_API void ThreadStackWalkAndDump(ANSICHAR* HumanReadableString, SIZE_T HumanReadableStringSize, int32 IgnoreCount, uint32 ThreadId); static CORE_API int32 GetProcessModuleCount(); diff --git a/build.py b/build.py index 1944d740..01c31c7b 100755 --- a/build.py +++ b/build.py @@ -222,7 +222,7 @@ def unzip_unreal_engine_and_apply_patch(): with JZipFile(zipfn) as zf: zf.extractall(INTEGRATION) patchfile = f"{INTEGRATION}/EnginePatches/EnginePatch" - shell(extracted, f"patch -p1 < {patchfile}") + shell(extracted, f"patch -p0 < {patchfile}") Path(extracted).rename(UNREALENGINE) Path(touchfile).touch()