From 917eab8e94625815900fae6b46110da60b4feea6 Mon Sep 17 00:00:00 2001 From: Virx Date: Wed, 12 Mar 2025 22:44:12 -0400 Subject: [PATCH 1/8] Enable `SetLoadout` to work mid-match --- RLBotCS/ManagerTools/MatchStarter.cs | 9 +-- RLBotCS/Server/BridgeMessage/SpawnBot.cs | 10 +-- .../Server/BridgeMessage/StateSetLoadout.cs | 58 ++++++++++++++++++ RLBotCS/Server/FlatBuffersSession.cs | 39 +++++++----- RLBotCS/lib/Bridge.dll | Bin 137728 -> 137728 bytes 5 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 RLBotCS/Server/BridgeMessage/StateSetLoadout.cs diff --git a/RLBotCS/ManagerTools/MatchStarter.cs b/RLBotCS/ManagerTools/MatchStarter.cs index e8934bd..2b963a9 100644 --- a/RLBotCS/ManagerTools/MatchStarter.cs +++ b/RLBotCS/ManagerTools/MatchStarter.cs @@ -428,12 +428,7 @@ private bool SpawnCars(MatchConfigurationT matchConfig, bool force = false) { case PlayerClass.CustomBot: bridge.TryWrite( - new SpawnBot( - playerConfig, - BotSkill.Custom, - (uint)(i - indexOffset), - true - ) + new SpawnBot(playerConfig, BotSkill.Custom, (uint)(i - indexOffset)) ); break; @@ -451,7 +446,7 @@ private bool SpawnCars(MatchConfigurationT matchConfig, bool force = false) }; bridge.TryWrite( - new SpawnBot(playerConfig, skillEnum, (uint)(i - indexOffset), false) + new SpawnBot(playerConfig, skillEnum, (uint)(i - indexOffset)) ); break; diff --git a/RLBotCS/Server/BridgeMessage/SpawnBot.cs b/RLBotCS/Server/BridgeMessage/SpawnBot.cs index a4d30b5..38e429e 100644 --- a/RLBotCS/Server/BridgeMessage/SpawnBot.cs +++ b/RLBotCS/Server/BridgeMessage/SpawnBot.cs @@ -6,12 +6,8 @@ namespace RLBotCS.Server.BridgeMessage; -record SpawnBot( - PlayerConfigurationT Config, - BotSkill Skill, - uint DesiredIndex, - bool IsCustomBot -) : IBridgeMessage +record SpawnBot(PlayerConfigurationT Config, BotSkill Skill, uint DesiredIndex) + : IBridgeMessage { public void HandleMessage(BridgeContext context) { @@ -41,7 +37,7 @@ public void HandleMessage(BridgeContext context) CommandId = commandId, SpawnId = Config.SpawnId, DesiredPlayerIndex = DesiredIndex, - IsCustomBot = IsCustomBot, + IsCustomBot = Skill == BotSkill.Custom, IsBot = true, } ); diff --git a/RLBotCS/Server/BridgeMessage/StateSetLoadout.cs b/RLBotCS/Server/BridgeMessage/StateSetLoadout.cs new file mode 100644 index 0000000..40395a9 --- /dev/null +++ b/RLBotCS/Server/BridgeMessage/StateSetLoadout.cs @@ -0,0 +1,58 @@ +using Bridge.Models.Command; +using Bridge.Models.Message; +using Bridge.State; +using Microsoft.Extensions.Logging; +using rlbot.flat; +using RLBotCS.Conversion; + +namespace RLBotCS.Server.BridgeMessage; + +record StateSetLoadout(PlayerLoadoutT Loadout, uint Index) : IBridgeMessage +{ + public void HandleMessage(BridgeContext context) + { + PlayerMetadata? meta = context + .GameState.PlayerMapping.GetKnownPlayers() + .FirstOrDefault(kp => Index == kp.PlayerIndex); + if (meta == null) + return; + + // todo: Psyonix bot support - + // requires additional work to figure out the proper BotSkill + if (!meta.IsCustomBot) + { + context.Logger.LogWarning( + "Player {0} is not controlled by RLBot, cannot set loadout.", + meta.PlayerIndex + ); + return; + } + + context.MatchCommandSender.AddDespawnCommand(meta.ActorId); + + Loadout.LoadoutPaint ??= new LoadoutPaintT(); + + var player = context.GameState.GameCars[meta.PlayerIndex]; + Loadout loadout = FlatToModel.ToLoadout(Loadout, player.Team); + + ushort commandId = context.MatchCommandSender.AddBotSpawnCommand( + player.Name, + (int)player.Team, + BotSkill.Custom, + loadout + ); + + context.GameState.PlayerMapping.AddPendingSpawn( + new SpawnTracker + { + CommandId = commandId, + SpawnId = meta.SpawnId, + DesiredPlayerIndex = meta.PlayerIndex, + IsCustomBot = true, + IsBot = true, + } + ); + + context.MatchCommandSender.Send(); + } +} diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index 6fe642e..6bcbfc3 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -135,26 +135,37 @@ await _rlbotServer.WriteAsync( var setLoadout = SetLoadout.GetRootAsSetLoadout(byteBuffer).UnPack(); - // ensure the provided index is a bot we control, - // and map the index to the spawn id - PlayerIdPair? maybeIdPair = _playerIdPairs.FirstOrDefault(idPair => - idPair.Index == setLoadout.Index - ); - - if (maybeIdPair is { } pair) + if (_isReady) { - await _rlbotServer.WriteAsync( - new SpawnLoadout(setLoadout.Loadout, pair.SpawnId) + // state setting is enabled, + // allow setting the loadout of any bots post-init + await _bridge.WriteAsync( + new StateSetLoadout(setLoadout.Loadout, setLoadout.Index) ); } else { - var owned = string.Join(", ", _playerIdPairs.Select(p => p.Index)); - Logger.LogWarning( - $"Client sent loadout unowned player" - + $"(index(es) owned: {owned}," - + $"index got: {setLoadout.Index})" + // ensure the provided index is a bot we control, + // and map the index to the spawn id + PlayerIdPair? maybeIdPair = _playerIdPairs.FirstOrDefault(idPair => + idPair.Index == setLoadout.Index ); + + if (maybeIdPair is { } pair) + { + await _rlbotServer.WriteAsync( + new SpawnLoadout(setLoadout.Loadout, pair.SpawnId) + ); + } + else + { + var owned = string.Join(", ", _playerIdPairs.Select(p => p.Index)); + Logger.LogWarning( + $"Client sent loadout unowned player" + + $"(index(es) owned: {owned}," + + $"index got: {setLoadout.Index})" + ); + } } break; diff --git a/RLBotCS/lib/Bridge.dll b/RLBotCS/lib/Bridge.dll index 28175576ec3b686cccf20ec98f67615d5624bdb0..e44442a8105f9d6fbae5f50e93559a942a60fe19 100644 GIT binary patch delta 3458 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 Z?#+-gb}`1p+-AyCJ^Co-4!Et#e*=&7Sd;(& delta 3362 zcmaKv3s6+o8OP6e?(VX}uH4<_{ZJ6m)fL>wy$eLGu~DPM`UvrnL=!23d6`u~#?DHC z(kfb;VZDymHa4TtBqq@+!nhI>s#EQ>@r40HBOpqA0BWg3B?M~wox6|5&~|6e|9rpy z_kHKwb7${9%4)S`wc4smRZeE}7oM#NknZ_#@$e=qC5s8Zo}^?c=Seo{mQ$ibK8A?| zDVa`?o`9QT zkFmyGh+23OomA?+hH=SGlvItoh{ZdUSjuk6%FwviAcPsgybVZbn%-CKI)h*dLDz#p z$=kl(wXAm+itB96@s>1zb5d99)#2x{Bpfy@!$efc1*y4h7c@vkSGL2&nqlpy0jCRB zR{?w>P3dq$qg2;%8ZJtuUpGRNlyiM4T#^o7e=+(?TqM-8%1F%37~#Dzaz>T;Z_=n6 z%i$}j;>Ir%*)|ppbx)-1-07&%>3Yu1wsl{q8GUm+K#Mf*)<|fraox%WXp=taOol5` zYv(p-mt0*bVR)B9b(Rdg&)1~icSR?4Ag89O#za`uE<9qW`D-RCP_7Uxx-K@uiLR`!IGKM>#hG@pW!QK$C<=ooKv*+)i+n-dl|iU zLiXc|DGPJRmD>k>D}}cP?Ja26 z%J+&O-k^OHSalDYOCI@Z`7#3j&Ca2%1$p&4h!2N=*^cHN#f%GIPXq1%x(8$zR`RcK z0dtk(AnfBg)|{ZyO7=p(mtfhARR<%QD_HQtUZd<<)=}6lj9J? z;nyc29z6PW$6=Tpq&`PAypn)llfGo4Pz|Sok*vhKEi0;wiBElkY);^UpBHPae4DJO^w1 z^trxHxCEu%)9c~s=tKia)BH)*%GK%f#}9IgRLiw@I6Y+9?{KqWiafCjqBH94o9Upj zQ_;KjR_+sHx>0_So(q1 zKtP+8c8%VR%#}Z=f)v|aVUCiRqjYb@?haKyJrjLK?57dKo5knUhxI+;cEw-HVtJqn zL~zSC4QSJM4uU+L>;V5?OaP&BcFh-~s znuWg$oERlq#UgRLSRlZ`VphM^_3~z`qyy0pVGqJifO~q!qtVf;dsDRI#nbYzbzB- z$9po4M54i2gL4Q;^j3TdACBNh?#!(#UMFSmb{58MIqI6}o!kO{u_c9taK>`8v23fM ze6*H;v0}BMd|zk?HU45S(jbD?E9mJVwb_ Date: Sat, 15 Mar 2025 01:15:05 -0400 Subject: [PATCH 2/8] Ensure `AgentId` isn't null --- RLBotCS/Server/FlatBuffersSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index 6bcbfc3..087976f 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -108,7 +108,7 @@ private async Task ParseClientMessage(TypedPayload message) case DataType.ConnectionSettings when !_connectionEstablished: var readyMsg = ConnectionSettings.GetRootAsConnectionSettings(byteBuffer); - _agentId = readyMsg.AgentId; + _agentId = readyMsg.AgentId ?? ""; _wantsBallPredictions = readyMsg.WantsBallPredictions; _wantsComms = readyMsg.WantsComms; _closeBetweenMatches = readyMsg.CloseBetweenMatches; From 0bd50ca6bdd092b810d810497885b6069d4e9ca5 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Tue, 18 Mar 2025 15:39:55 -0400 Subject: [PATCH 3/8] Add session before starting thread --- RLBotCS/Server/FlatBuffersServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersServer.cs b/RLBotCS/Server/FlatBuffersServer.cs index 9f601f0..2504d37 100644 --- a/RLBotCS/Server/FlatBuffersServer.cs +++ b/RLBotCS/Server/FlatBuffersServer.cs @@ -59,9 +59,9 @@ private void AddSession(TcpClient client) session.Cleanup(); } }); - sessionThread.Start(); _context.Sessions.Add(clientId, (sessionChannel.Writer, sessionThread, 0)); + sessionThread.Start(); } private async Task HandleIncomingMessages() From 4c8532f9bb418e4c95b1c4acce50dede6ba05052 Mon Sep 17 00:00:00 2001 From: VirxEC Date: Tue, 18 Mar 2025 18:37:46 -0400 Subject: [PATCH 4/8] If state setting is enabled, accept all player inputs --- RLBotCS/Server/FlatBuffersSession.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index 087976f..a076de2 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -212,7 +212,8 @@ await _rlbotServer.WriteAsync( // ensure the provided index is a bot we control if ( - !_playerIdPairs.Any(playerInfo => + !_stateSettingIsEnabled + && !_playerIdPairs.Any(playerInfo => playerInfo.Index == playerInputMsg.PlayerIndex ) ) @@ -220,8 +221,8 @@ await _rlbotServer.WriteAsync( var owned = string.Join(", ", _playerIdPairs.Select(p => p.Index)); Logger.LogWarning( $"Client sent player input unowned player" - + $"(index(es) owned: {owned}," - + $"index got: {playerInputMsg.PlayerIndex})" + + $" (index(es) owned: {owned}," + + $" index got: {playerInputMsg.PlayerIndex})" ); break; } From d707a85e916bb584082d140369c6a63cbe8d6b9e Mon Sep 17 00:00:00 2001 From: Eric Veilleux Date: Thu, 20 Mar 2025 17:09:30 -0400 Subject: [PATCH 5/8] Update RLBotCS/Server/FlatBuffersSession.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolaj 'Eastvillage' Ø Jensen --- RLBotCS/Server/FlatBuffersSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index a076de2..d45481b 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -161,7 +161,7 @@ await _rlbotServer.WriteAsync( { var owned = string.Join(", ", _playerIdPairs.Select(p => p.Index)); Logger.LogWarning( - $"Client sent loadout unowned player" + $"Client tried to set loadout of player it does not own " + $"(index(es) owned: {owned}," + $"index got: {setLoadout.Index})" ); From 5834bd313a0c637dd1085101cbab4058b4ea814d Mon Sep 17 00:00:00 2001 From: Eric Veilleux Date: Thu, 20 Mar 2025 17:09:35 -0400 Subject: [PATCH 6/8] Update RLBotCS/Server/FlatBuffersSession.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolaj 'Eastvillage' Ø Jensen --- RLBotCS/Server/FlatBuffersSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index d45481b..ff11384 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -163,7 +163,7 @@ await _rlbotServer.WriteAsync( Logger.LogWarning( $"Client tried to set loadout of player it does not own " + $"(index(es) owned: {owned}," - + $"index got: {setLoadout.Index})" + + $" got: {setLoadout.Index})" ); } } From 044a23a1c3c2b02a0dff4a0d3a6ca8f271ec22a5 Mon Sep 17 00:00:00 2001 From: Eric Veilleux Date: Thu, 20 Mar 2025 17:09:43 -0400 Subject: [PATCH 7/8] Update RLBotCS/Server/FlatBuffersSession.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolaj 'Eastvillage' Ø Jensen --- RLBotCS/Server/FlatBuffersSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index ff11384..915bbde 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -220,7 +220,7 @@ await _rlbotServer.WriteAsync( { var owned = string.Join(", ", _playerIdPairs.Select(p => p.Index)); Logger.LogWarning( - $"Client sent player input unowned player" + $"Client tried to set loadout of player it does not own" + $" (index(es) owned: {owned}," + $" index got: {playerInputMsg.PlayerIndex})" ); From 926c4bce4b6a2ec41530fdb5b9be30626f21c858 Mon Sep 17 00:00:00 2001 From: Eric Veilleux Date: Thu, 20 Mar 2025 17:09:50 -0400 Subject: [PATCH 8/8] Update RLBotCS/Server/FlatBuffersSession.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolaj 'Eastvillage' Ø Jensen --- RLBotCS/Server/FlatBuffersSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RLBotCS/Server/FlatBuffersSession.cs b/RLBotCS/Server/FlatBuffersSession.cs index 915bbde..3ddd266 100644 --- a/RLBotCS/Server/FlatBuffersSession.cs +++ b/RLBotCS/Server/FlatBuffersSession.cs @@ -222,7 +222,7 @@ await _rlbotServer.WriteAsync( Logger.LogWarning( $"Client tried to set loadout of player it does not own" + $" (index(es) owned: {owned}," - + $" index got: {playerInputMsg.PlayerIndex})" + + $" got: {playerInputMsg.PlayerIndex})" ); break; }