Skip to content

Sync upstream into main - #4

Open
github-actions[bot] wants to merge 74 commits into
mainfrom
master
Open

Sync upstream into main#4
github-actions[bot] wants to merge 74 commits into
mainfrom
master

Conversation

@github-actions

Copy link
Copy Markdown

Automated upstream sync hit conflicts. Merge master (now level with beyond-all-reason/RecoilEngine) into main and resolve here.

MarkKropf and others added 30 commits June 18, 2026 21:11
A handful of SolLua bindings still referenced sol::nil / sol::type::nil
while the rest of the same files already use sol::lua_nil. sol::nil is a
thin alias for lua_nil (see lib/sol2/sol.hpp) and collides with the `nil`
macro that Objective-C headers define, so lua_nil is the portable
spelling. This brings the remaining spots in line with the prevailing
convention.

Extracted from cc3cad9 in beyond-all-reason#2991; cross-platform, no behavior change.
float3.h included lib/streflop/streflop_cond.h directly, ahead of
FastMath.h. FastMath.h defines MATH_SQRT_OVERRIDE before it includes
streflop_cond.h (so streflop does not define its own math::sqrt(float) --
FastMath provides a faster one). The direct include meant streflop_cond.h
could be processed before that override was set.

Drop the direct include; FastMath.h pulls in streflop_cond.h transitively
with the override in place. creg_cond.h keeps its original position --
it does not pull in streflop, so it does not need to move.

Surfaced by the macOS port (beyond-all-reason#2991, commit cc3cad9).

Co-authored-by: Mark Kropf <markkropf@gmail.com>
…son#3025)

`SafeUtil.h` uses `<memory>` for `std::addressof`, and `<type_traits>`
for `std::is_trivially_copyable` / `std::is_trivially_constructible_v`,
but pulled them in only transitively. Include them directly so the header
is self-contained and does not rely on include order elsewhere. Also use
`std::is_trivially_default_constructible` for the default-construction.

Extracted from cc3cad9 in beyond-all-reason#2991; cross-platform, no behavior change.

Co-authored-by: Mark Kropf <markkropf@gmail.com>
Co-authored-by: sprunk <spr.ng@o2.pl>
LuaTextures::Create returned an empty string on glTexImage failure with
no diagnostics. Log target/size/format/dataFormat/dataType/glError so
texture-creation failures can be diagnosed.

Extracted from 1e75080 in beyond-all-reason#2991; cross-platform, no behavior change
beyond the added log.
Engine crash thread: https://discordapp.com/channels/549281623154229250/1516994684591931535

Bugged Scenario: A reclaimer A is guarding another reclaimer B, while both reclaiming the same wreck. A can be notified of wreck death BEFORE the guarded unit B is notified, leading to trying to reclaim the same (actively-deleting) wreck because B's reference hasn't been cleaned up yet.

This leads to an eventual segfault.

So: the short term/easy fix is to skip reclaiming of a dead/dying target.
util_fileSelector was declared with a non-const struct dirent* on
__APPLE__ and const elsewhere. macOS scandir() expects the selector
argument as int(*)(const struct dirent*), so the non-const Apple variant
failed to compile under GCC:

  Util.c:500: error: passing argument 3 of 'scandir' from incompatible
  pointer type

Both branches were otherwise identical, so drop the __APPLE__ split and
use const struct dirent* unconditionally (matches POSIX scandir). No
effect on Linux/Windows.

Assisted by Claude Code; verified by compiling the macOS headless build.
The legacy build did find_package(X11 REQUIRED) under a plain if(UNIX)
guard. macOS is UNIX in CMake but does not use X11 (it uses Cocoa), so
configuring the engine on macOS failed at find_package(X11). An if(APPLE)
block already follows for Foundation, so exclude Apple from the X11
branch: if(UNIX AND NOT APPLE).

Surfaced configuring the spring-headless target on macOS (which reuses
the legacy Game target). No effect on Linux/Windows.

Assisted by Claude Code; verified by configuring the macOS build.
Modern 7-Zip ships its CLI as '7zz' (Homebrew's 'sevenzip' formula
installs /opt/homebrew/bin/7zz; recent Linux distros likewise package
'7zz'). FindSevenZip only searched for '7z'/'7za', so configure failed
with 'Could NOT find SevenZip (missing: SEVENZIP_BIN)' on such systems.

Add '7zz' to the searched NAMES. No effect where 7z/7za already exist.
rts/System/Platform/Mac/SDLMain.m and SDLMain.h are the classic SDL 1.2
Cocoa main wrapper (the Darrell Walisser / Max Horn template). They are:

- not listed in any CMakeLists (never compiled)
- not #included by any source file
- built on Carbon (<Carbon/Carbon.h>), which is 32-bit-only and
  unavailable on modern macOS / Apple Silicon

SDL2 provides its own SDL_main, so this wrapper is obsolete. Remove the
dead files so the macOS platform layer reflects what is actually built.
Updated the link for the SplinterFaction card to include the 'https://' prefix.

This has been broken for a very long time. I've asked Skyrbunny to fix it multiple times, but it has never gotten fixed.
beyond-all-reason#3052)

setMinLevel() only searched for an existing entry on the "set back to default" (erase) path. Setting a section to a *non-default* level appended a new row unconditionally, so repeatedly changing one section's level (e.g. via Spring.SetLogSectionFilterLevel) accumulated duplicate entries and eventually filled the fixed 64-slot sectionMinLevels table -- after which every section-level change silently failed with "too many section-levels".

Fix: Look the section up before appending and, if it already has an entry, update it in place. This bounds the table at one entry per section.

This likely never happens in practice but this was found while writing other tests

Co-authored-by: Bruno Da Silva <Bruno-DaSilva@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The original code relied on implicit null-termination which is not guaranteed.
Aligns forward declarations with definitions to silence MSVC warnings.
SpringApp.cpp included <X11/Xlib.h> for every non-Windows platform, but
macOS has no X11 headers by default, breaking the native build. The only
user of it, XInitThreads(), is already excluded on __APPLE__ at its call
site, so guard the include the same way.
glad_glx.c includes X11/X.h to provide the GLX windowing-system bindings,
but macOS has no X11/GLX. The Glad CMakeLists added glad_glx.c for every
UNIX-and-not-MinGW platform, so building any GL-enabled target (e.g.
engine-legacy) on macOS failed:

    fatal error: X11/X.h: No such file or directory

macOS resolves GL entry points without GLX (the engine's glxHandler is
already #ifdef'd out on __APPLE__), so exclude glad_glx.c on Apple and
build only the core glad.c there.
…eyond-all-reason#2919)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These three headers use std:: algorithms but rely on <algorithm> being
pulled in transitively. libstdc++ does so; libc++ (clang/macOS) does not,
so they can fail to compile under libc++ depending on the version.

Symbols that require the include:
- rts/System/Matrix44f.h    -> std::copy
- rts/System/SpringHashMap.hpp -> std::fill_n
- rts/System/SpringHashSet.hpp -> std::fill_n

Adding the include is "include what you use" correctness and is a no-op on
toolchains that already provide it transitively. No functional change.

Cherry-picked from ExaDev/RecoilEngine (0ed29d5, 0b4bd10, 3adabd0).

AI assistance: changes identified and applied with Claude (Anthropic);
verified by a human (compiled under clang/libc++, no regression).
DemoTool compiles engine FileSystem sources (FileHandler, FileSystem)
that include nowide/fstream.hpp and fmt/printf.h, but its
target_link_libraries omitted the nowide and fmt targets. The engine
builds obtain those include directories transitively through the
nowide::nowide and fmt::fmt INTERFACE targets; DemoTool linked neither,
so the build failed when the headers were not on a default search path
(observed building the demotool target on macOS).

Link nowide::nowide and fmt::fmt so their INTERFACE include directories
propagate to the demotool target.

Co-authored-by: Robert Burnham <burnhamrobertp@gmail.com>
* avoid parenthesised aggregate init and name
  the type explicitly (not supported everywhere)

* avoid narrowing conversions.
 * adds `Spring.TraceRayBetweenPositions(xA, yA, zA, xB, yB, zB, type)`
 * adds `Spring.TraceRayInDirection(x, y, z, dx, dy, dz, length, type)`
 * type is a string, "unit", "feature", or "both"
 * both return an array of `{distance, objID, objType}` sorted by increasing distance
 * these no longer did anything and just polluted the interface.
 * also removed example gadgetry using them from basecontent.
burnhamrobertp and others added 30 commits July 15, 2026 03:11
A bunch of functions to emulate key presses and mouse clicks
added to the debug library, mostly for headless testing of UI.
When `AIFloat3` had virtual methods - it required non-trivial copy constructor.
It is a leftover that spoils AngelScript bindings to `float3` math methods that return `float3` as result.

Insinuations: while AngelScript expects copying through registers (`this == nullptr`), non-trivial copy constructor makes it in memory trying to dereference nullptr.

This is the 1st part of planned `AIFloat3` refactor. In 2nd part (as separate PR) `AIFloat3` will become a copy of `float3` interface and implementation with inheritance removed.
…reason#3064)

The macOS crash handler hardcoded '-arch x86_64' when invoking atos
(ADDR2LINE), so backtrace symbolication produced no useful output on
Apple Silicon binaries. Select '-arch arm64' at compile time on
aarch64/arm64 targets, keeping x86_64 for Intel.

Also fix the debug log of the frame address: stackFrame.ip is a void*,
but it was printed with '0x%lx', a format/argument mismatch. Use %p.
Passes a table: { [teamID] = {metal, energy, ...} }
The resources are the amount over the storage max,
accumulated over the frame. Called at the end of
every frame, contains data for every team.

Return true to take over engine handling; otherwise
the native behaviour of buffering it until the next
slowupdate will take place.
Mostly for use with the new ResourceExcess callin.
The rest of the changelog is not yet up to date.
This is an old entry that had waited a bit too long.
Expose the sim frame checksum information to lua so we can update the synctest widget/gadget combo to grab it every sim frame and dump it to a file at the end of each synctest run.
Engine moved the sync feature flag.
`/unbind` couldn't handle chained keysets: bind accepts "a,b" but unbind
parsed the key string as a single keyset, so unbinding a keychain always
failed with "could not parse key". This parses the key string with the
same keychain parser bind uses and looks the binding up under the chain's
last keyset, which is where bind stores it. Removal matching is unchanged.
Rebuild the hotkey map on actual binding changes.
 * fix forward-only map shaders never activating
 * fix stale uniforms remaining after shader swap
 * add `Engine.FeatureSupport.reliableLuaMapShaders` feature flag
…eason#2986)

Add string literal overloads for LuaPushNamedFoo that enable a compile time hash.
Remove legacy hashing macros and replace callsites with corresponding LuaPushNamedFoo.
 * blank_map_splatdetailtex
 * blank_map_splatdistr
 * blank_map_splattexscale1 .. 4
 * blank_map_splattexmult1 .. 4
 * blank_map_splatdetailnormaltex1 .. 4
 * blank_map_splatdetailnormaldiffusealpha
…ason#3124)

disable luaui, and pass an explicit start frame to the synctest command so the run anchors to a fixed sim frame instead of whenever the message reaches synced code.
…reason#3077)

Every <simdjson.h> consumer already links simdjson::simdjson (GLTFParser
via engineCommonLibraries; fastgltf links it privately), and that in-tree
target exports the vendored include as a normal -I dir. DevIL's imported
target is the only thing putting /opt/homebrew/include on the line, and as
an imported target its include is emitted -isystem, which the compiler
searches after every -I dir - so the vendored simdjson header wins on its
own. The manual include_directories entry was redundant.

Per review feedback (p2004a).
* Support alternate file extensions for replays

---------

Co-authored-by: sprunk <spr.ng@o2.pl>
…beyond-all-reason#3139)

* Fix Windows build: link test_DemoFileExtension against ZLIB::ZLIB

The DemoFileExtension test target linked the bare library name `z`, which
expands to `-lz`. That works on Linux where zlib sits in the default
library search path, but the mingw cross-linker fails with
"cannot find -lz" because on Windows zlib is supplied by mingwlibs64.

Use the ZLIB::ZLIB imported target instead, matching how the engine,
unitsync and DemoTool link zlib. find_package is needed here because
imported targets are directory-scoped and test/ is a sibling of rts/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FuDx3RoNDdSDMTx7Nkw8ss

* Apply suggestion from @sprunk

Co-authored-by: sprunk <spr.ng@o2.pl>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: TarnishedKnight <lostsquirrel43@gmail.com>
Co-authored-by: sprunk <spr.ng@o2.pl>
…nc) (beyond-all-reason#3075)

* Sim/COB: avoid UB in float-to-short angle casts (fixes arm64/x86 desync)

Casting a floating-point heading/pitch expression directly to `short` is
undefined behaviour when the truncated value does not fit in `short`, and
this is genuinely reached: `heading * RAD2TAANG` equals +-32768 at
heading = +-pi, one past short's 32767 maximum.

Because the result is UB, arm64 and x86 produced different values at the
angle extremes, which was observed as an arm64/x86 multiplayer desync.
x86 already lowers `short(float)` as float->int->short (cvttss2si into a
32-bit register, then narrow), so making the `int()` step explicit leaves
the already-correct x86 result unchanged while pinning arm64 (whose fcvtzs
saturated differently) to the same value. The int->short narrowing is the
intended 16-bit TA-angle wraparound.

Sites fixed in CobInstance.cpp: WindChanged, StartBuilding, AimWeapon.
Sibling casts were checked and left untouched: UnitScript.cpp:1058 casts
asin(...)*RAD2TAANG (range +-16384, always fits short, no UB) and lines
1095/1099 already route through int; CobThread.cpp has no such casts.

Pure correctness fix to synced simulation code; it does not alter results
on the platform that was already correct. Cross-arch sync validation is
recommended. Origin: discussed in PR beyond-all-reason#2991's review (credit BambaDamba).

AI assistance: implemented with Claude Code (Anthropic) from a written
plan; reasoning and build verification reviewed by a human.

* address review: extract RadAngleToCobShort helper with explanatory comment

sprunk asked for a comment and a named helper around the float->short angle
cast. Wrap the conversion in RadAngleToCobShort() and document why it exists:
COB angles are circular 16-bit TA units (full turn == COBSCALE), so values
past a half turn intentionally wrap modulo 2^16 via the int->short narrowing.
The float->int step stays because the wrap is the desired behaviour and is
deterministic across arm64/x86; clamping the range (as suggested) would break
angles past a half turn rather than wrapping them. No behavioural change vs the
previous short(int(...)) form.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.