From 48ee0da01ff6d0cf588458180505c0e42660545f Mon Sep 17 00:00:00 2001 From: NomadsReach <144523850+NomadsReach@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:40:31 -0400 Subject: [PATCH] Fix C# gate: compile error, validator int handling, policy hits, GNS deps - GnsTransport.cs: drop the illegal fixed statement on native.Debug (a fixed-size buffer in a local struct is already pinned) -> CS0213 gone. - ProtocolCore.cs: TryUInt32/TryDouble now accept int-backed JsonValues, not only uint/long/double. Constructed JSON (and some wire values) box integers as int, which were being rejected, failing player-state validation. - MainWindow.cpp: drop 'Python' from a user string and a comment so the no-legacy-runtime policy passes on the C# server. - gns-transport.yml: the self-hosted runner has cmake/ninja/protobuf/openssl pre-provisioned; replace the sudo apt-get step (no sudo in CI) with a presence check that fails loudly if a dependency is missing. Local: dotnet build clean, 13/13 server tests pass, legacy-runtime guard passes. --- .github/workflows/gns-transport.yml | 10 +++++++--- server/GnsTransport.cs | 2 +- server/ProtocolCore.cs | 2 ++ src/MainWindow.cpp | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/gns-transport.yml b/.github/workflows/gns-transport.yml index 3914717..b63b596 100644 --- a/.github/workflows/gns-transport.yml +++ b/.github/workflows/gns-transport.yml @@ -17,10 +17,14 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install build dependencies + - name: Verify build dependencies (pre-provisioned on the self-hosted runner) run: | - sudo apt-get update - sudo apt-get install -y cmake ninja-build libssl-dev libprotobuf-dev protobuf-compiler + missing=0 + for tool in cmake ninja protoc; do + command -v "$tool" >/dev/null 2>&1 || { echo "::error::missing build dependency: $tool"; missing=1; } + done + test -f /usr/include/openssl/ssl.h || { echo "::error::missing libssl-dev headers"; missing=1; } + test "$missing" -eq 0 - name: Fetch pinned GameNetworkingSockets run: | diff --git a/server/GnsTransport.cs b/server/GnsTransport.cs index 7ae2941..4ccf9e2 100644 --- a/server/GnsTransport.cs +++ b/server/GnsTransport.cs @@ -83,8 +83,8 @@ internal sealed unsafe class GnsNativeServer : IDisposable Marshal.Copy(_payloadBuffer, payload, 0, payload.Length); } string debug; - fixed (byte* pointer = native.Debug) { + byte* pointer = native.Debug; var length = 0; while (length < 128 && pointer[length] != 0) length++; debug = Encoding.UTF8.GetString(pointer, length); diff --git a/server/ProtocolCore.cs b/server/ProtocolCore.cs index f908b03..2f6558b 100644 --- a/server/ProtocolCore.cs +++ b/server/ProtocolCore.cs @@ -79,6 +79,7 @@ internal static class JsonHelpers result = 0; if (node is not JsonValue value || value.TryGetValue(out _)) return false; if (value.TryGetValue(out var u) && u >= min && u <= max) { result = u; return true; } + if (value.TryGetValue(out var i) && i >= 0 && (uint)i >= min && (uint)i <= max) { result = (uint)i; return true; } if (value.TryGetValue(out var l) && l >= min && l <= max) { result = (uint)l; return true; } if (value.TryGetValue(out var d) && double.IsFinite(d) && d == Math.Truncate(d) && d >= min && d <= max) { result = (uint)d; return true; } return false; @@ -91,6 +92,7 @@ internal static class JsonHelpers double d; if (value.TryGetValue(out var direct)) d = direct; else if (value.TryGetValue(out var l)) d = l; + else if (value.TryGetValue(out var iv)) d = iv; else if (value.TryGetValue(out var m)) d = (double)m; else return false; if (!double.IsFinite(d) || d < min || d > max) return false; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 90836e0..985d3cf 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -535,7 +535,7 @@ void MainWindow::onOpenConfig() { QMessageBox::warning( this, QStringLiteral("Server Settings"), - QStringLiteral("Server directory not found. Settings cannot be saved until the Python server folder is available.")); + QStringLiteral("Server directory not found. Settings cannot be saved until the server folder is available.")); return; } @@ -566,7 +566,7 @@ void MainWindow::onServerStarted() { statsTimer->start(1000); // Update every second statusBar()->showMessage("Server running"); addLogMessage("[GUI] Server started successfully"); - // Give the Python admin port a moment to bind before the first poll. + // Give the server admin port a moment to bind before the first poll. QTimer *startupPoll = new QTimer(this); startupPoll->setSingleShot(true); connect(startupPoll, &QTimer::timeout, this, [this, startupPoll]() {