From e993d58d3fd48c79dfa77209938d02604bfd19d5 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Tue, 16 Jun 2026 11:33:33 -0500 Subject: [PATCH 1/4] Add FlatBuffers generation for macOS --- RLBotCS/RLBotCS.csproj | 7 +++++++ generate-flatbuffers-mac.sh | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100755 generate-flatbuffers-mac.sh diff --git a/RLBotCS/RLBotCS.csproj b/RLBotCS/RLBotCS.csproj index bf19692..ec069c3 100644 --- a/RLBotCS/RLBotCS.csproj +++ b/RLBotCS/RLBotCS.csproj @@ -84,6 +84,13 @@ > + + + diff --git a/generate-flatbuffers-mac.sh b/generate-flatbuffers-mac.sh new file mode 100755 index 0000000..45194b1 --- /dev/null +++ b/generate-flatbuffers-mac.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +cd "$(dirname "$0")" + +echo Generating flatbuffers header file... + +./flatbuffers-schema/binaries/flatc_mac --gen-all --csharp --gen-object-api --gen-onefile -o ./FlatBuffer ./flatbuffers-schema/schema/rlbot.fbs + +# the file produced is called rlbot_generated.cs, rename it to RLBot.cs after removing the old one +rm -f ./FlatBuffer/RLBot.cs +mv ./FlatBuffer/rlbot_generated.cs ./FlatBuffer/RLBot.cs +sed -i '' 's/rlbot\.flat/RLBot.Flat/g' ./FlatBuffer/RLBot.cs + +echo Done. From d75f6605ac93c2af99354df5b82835a8db410c4c Mon Sep 17 00:00:00 2001 From: VirxEC Date: Wed, 17 Jun 2026 11:48:36 -0500 Subject: [PATCH 2/4] Support agent environment variables --- RLBotCS/ManagerTools/ConfigParser.cs | 30 +++++++++++++++++++++++ RLBotCS/ManagerTools/ConfigValidator.cs | 2 ++ RLBotCS/ManagerTools/LaunchManager.cs | 19 ++++++++++++++ RLBotCSTests/ConfigParserTest.cs | 8 +++++- RLBotCSTests/TestTomls/normal.bot.toml | 4 +++ RLBotCSTests/TestTomls/normal.script.toml | 4 +++ flatbuffers-schema | 2 +- 7 files changed, 67 insertions(+), 2 deletions(-) diff --git a/RLBotCS/ManagerTools/ConfigParser.cs b/RLBotCS/ManagerTools/ConfigParser.cs index 0174e59..a5e01e1 100644 --- a/RLBotCS/ManagerTools/ConfigParser.cs +++ b/RLBotCS/ManagerTools/ConfigParser.cs @@ -76,6 +76,7 @@ public static class Fields public const string AgentRootDir = "root_dir"; public const string AgentRunCommand = "run_command"; public const string AgentRunCommandLinux = "run_command_linux"; + public const string AgentEnvironment = "environment"; public const string AgentHivemind = "hivemind"; public const string LoadoutBlueTable = "blue_loadout"; @@ -260,6 +261,33 @@ private string GetRunCommand(TomlTable runnableSettings) #endif } + private List GetEnvironment(TomlTable runnableSettings) + { + TomlTable environment = GetValue( + runnableSettings, + Fields.AgentEnvironment, + [] + ); + + List variables = []; + using (_context.Begin(Fields.AgentEnvironment)) + { + foreach (var (key, rawValue) in environment) + { + if (rawValue is not string value) + { + throw new InvalidCastException( + $"{_context.ToStringWithEnd(key)} has value {rawValue}, but a value of type String was expected." + ); + } + + variables.Add(new() { Name = key, Value = value }); + } + } + + return variables; + } + private ScriptConfigurationT LoadScriptConfig(string scriptConfigPath) { TomlTable scriptToml = LoadTomlFile(scriptConfigPath); @@ -276,6 +304,7 @@ private ScriptConfigurationT LoadScriptConfig(string scriptConfigPath) GetValue(settings, Fields.AgentRootDir, "") ), RunCommand = GetRunCommand(settings), + Environment = GetEnvironment(settings), AgentId = GetValue(settings, Fields.AgentAgentId, ""), }; } @@ -511,6 +540,7 @@ bool autoStart Name = nameOverride ?? GetValue(settings, Fields.AgentName, ""), Loadout = loadout, RunCommand = autoStart ? GetRunCommand(settings) : "", + Environment = GetEnvironment(settings), Hivemind = GetValue(settings, Fields.AgentHivemind, false), RootDir = rootDir, }; diff --git a/RLBotCS/ManagerTools/ConfigValidator.cs b/RLBotCS/ManagerTools/ConfigValidator.cs index 147bbdf..e7b00de 100644 --- a/RLBotCS/ManagerTools/ConfigValidator.cs +++ b/RLBotCS/ManagerTools/ConfigValidator.cs @@ -101,6 +101,7 @@ bool surpressWarnings bot.Name ??= ""; bot.RunCommand ??= ""; bot.RootDir ??= ""; + bot.Environment ??= []; bot.Loadout ??= new(); bot.Loadout.LoadoutPaint ??= new(); @@ -239,6 +240,7 @@ private static bool ValidateScripts( script.Name ??= ""; script.RunCommand ??= ""; script.RootDir ??= ""; + script.Environment ??= []; script.ScriptId = $"{script.AgentId}/{Team.Scripts}/{i}".GetHashCode(); if (agentIdTracker.TryGetValue(script.AgentId, out var existing)) diff --git a/RLBotCS/ManagerTools/LaunchManager.cs b/RLBotCS/ManagerTools/LaunchManager.cs index 6291410..46e8304 100644 --- a/RLBotCS/ManagerTools/LaunchManager.cs +++ b/RLBotCS/ManagerTools/LaunchManager.cs @@ -143,6 +143,23 @@ private static Process RunCommandInShell(string command) return process; } + private static void ApplyEnvironment( + ProcessStartInfo startInfo, + List? environment + ) + { + if (environment == null) + return; + + foreach (var variable in environment) + { + if (string.IsNullOrEmpty(variable.Name)) + continue; + + startInfo.EnvironmentVariables[variable.Name] = variable.Value ?? ""; + } + } + private static void LaunchGameViaLegendary() { Process legendary = RunCommandInShell( @@ -186,6 +203,7 @@ int rlbotSocketsPort Process botProcess = RunCommandInShell(details.RunCommand); botProcess.StartInfo.WorkingDirectory = details.RootDir; + ApplyEnvironment(botProcess.StartInfo, details.Environment); botProcess.StartInfo.EnvironmentVariables["RLBOT_AGENT_ID"] = details.AgentId; botProcess.StartInfo.EnvironmentVariables["RLBOT_SERVER_PORT"] = rlbotSocketsPort.ToString(); @@ -233,6 +251,7 @@ int rlbotSocketsPort if (script.RootDir != "") scriptProcess.StartInfo.WorkingDirectory = script.RootDir; + ApplyEnvironment(scriptProcess.StartInfo, script.Environment); scriptProcess.StartInfo.EnvironmentVariables["RLBOT_AGENT_ID"] = script.AgentId; scriptProcess.StartInfo.EnvironmentVariables["RLBOT_SERVER_PORT"] = rlbotSocketsPort.ToString(); diff --git a/RLBotCSTests/ConfigParserTest.cs b/RLBotCSTests/ConfigParserTest.cs index 1fd9619..107760f 100644 --- a/RLBotCSTests/ConfigParserTest.cs +++ b/RLBotCSTests/ConfigParserTest.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using RLBot.Flat; using RLBotCS.ManagerTools; @@ -179,10 +180,15 @@ public void Overrides() PlayerConfigurationT player = mc.PlayerConfigurations[0]; Assert.AreEqual("New Bot Name", player.Variety.AsCustomBot().Name); - Assert.IsNull(player.Variety.AsCustomBot().Loadout); + CustomBotT bot = player.Variety.AsCustomBot(); + Assert.IsNull(bot.Loadout); + Assert.AreEqual("bot-value", bot.Environment.Single(e => e.Name == "BOT_ENV").Value); + Assert.AreEqual("bot-shared", bot.Environment.Single(e => e.Name == "SHARED_ENV").Value); ScriptConfigurationT script = mc.ScriptConfigurations[0]; Assert.AreEqual("Normal Test Script", script.Name); // Not overriden + Assert.AreEqual("script-value", script.Environment.Single(e => e.Name == "SCRIPT_ENV").Value); + Assert.AreEqual("script-shared", script.Environment.Single(e => e.Name == "SHARED_ENV").Value); } [TestMethod] diff --git a/RLBotCSTests/TestTomls/normal.bot.toml b/RLBotCSTests/TestTomls/normal.bot.toml index d4b62c9..5ba9211 100644 --- a/RLBotCSTests/TestTomls/normal.bot.toml +++ b/RLBotCSTests/TestTomls/normal.bot.toml @@ -6,6 +6,10 @@ run_command_linux = "python bot.py" loadout_file = "loadout.toml" logo_file = "normal_logo.png" +[settings.environment] +BOT_ENV = "bot-value" +SHARED_ENV = "bot-shared" + [details] description = "This is a normal test bot" fun_fact = "knock knock ..." diff --git a/RLBotCSTests/TestTomls/normal.script.toml b/RLBotCSTests/TestTomls/normal.script.toml index 5a638c6..ff41c93 100644 --- a/RLBotCSTests/TestTomls/normal.script.toml +++ b/RLBotCSTests/TestTomls/normal.script.toml @@ -6,6 +6,10 @@ run_command_linux = "python script.py" loadout_file = "loadout.toml" logo_file = "normal_logo.png" +[settings.environment] +SCRIPT_ENV = "script-value" +SHARED_ENV = "script-shared" + [details] description = "This is a normal test script" fun_fact = "knock knock ..." diff --git a/flatbuffers-schema b/flatbuffers-schema index a83ce10..c2648b4 160000 --- a/flatbuffers-schema +++ b/flatbuffers-schema @@ -1 +1 @@ -Subproject commit a83ce106ed599303d8e5b5e6084687a0665f7edf +Subproject commit c2648b4fa30d9d3b228466d51746c84ee2f20a6c From 7cc035877bce1e4c2e1e1d54533f1a4d2927f218 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Wed, 17 Jun 2026 12:05:28 -0500 Subject: [PATCH 3/4] Format tests --- RLBotCSTests/ConfigParserTest.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/RLBotCSTests/ConfigParserTest.cs b/RLBotCSTests/ConfigParserTest.cs index 107760f..853ec95 100644 --- a/RLBotCSTests/ConfigParserTest.cs +++ b/RLBotCSTests/ConfigParserTest.cs @@ -183,12 +183,21 @@ public void Overrides() CustomBotT bot = player.Variety.AsCustomBot(); Assert.IsNull(bot.Loadout); Assert.AreEqual("bot-value", bot.Environment.Single(e => e.Name == "BOT_ENV").Value); - Assert.AreEqual("bot-shared", bot.Environment.Single(e => e.Name == "SHARED_ENV").Value); + Assert.AreEqual( + "bot-shared", + bot.Environment.Single(e => e.Name == "SHARED_ENV").Value + ); ScriptConfigurationT script = mc.ScriptConfigurations[0]; Assert.AreEqual("Normal Test Script", script.Name); // Not overriden - Assert.AreEqual("script-value", script.Environment.Single(e => e.Name == "SCRIPT_ENV").Value); - Assert.AreEqual("script-shared", script.Environment.Single(e => e.Name == "SHARED_ENV").Value); + Assert.AreEqual( + "script-value", + script.Environment.Single(e => e.Name == "SCRIPT_ENV").Value + ); + Assert.AreEqual( + "script-shared", + script.Environment.Single(e => e.Name == "SHARED_ENV").Value + ); } [TestMethod] From 9d4b26d709680fab686612f7d60bedf132bd7cd1 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Wed, 17 Jun 2026 15:36:14 -0500 Subject: [PATCH 4/4] Simplify `ApplyEnvironment` --- RLBotCS/ManagerTools/LaunchManager.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/RLBotCS/ManagerTools/LaunchManager.cs b/RLBotCS/ManagerTools/LaunchManager.cs index 46e8304..5a4f622 100644 --- a/RLBotCS/ManagerTools/LaunchManager.cs +++ b/RLBotCS/ManagerTools/LaunchManager.cs @@ -145,18 +145,12 @@ private static Process RunCommandInShell(string command) private static void ApplyEnvironment( ProcessStartInfo startInfo, - List? environment + List environment ) { - if (environment == null) - return; - foreach (var variable in environment) { - if (string.IsNullOrEmpty(variable.Name)) - continue; - - startInfo.EnvironmentVariables[variable.Name] = variable.Value ?? ""; + startInfo.EnvironmentVariables[variable.Name] = variable.Value; } }