/// <summary> /// Passes the agent's quick chats to the other bots. /// </summary> /// <param name="teamOnly"> /// If true, only bots on the agent's team will be able to see the quick chat.<br/> /// If false, the quick chat sent is global and every bot will be able to see it. /// </param> /// <param name="quickChat">The quick chat that should be sent</param> /// <remarks> /// The agent is limited to 5 quick chats in a 2 second period starting from the first chat. /// This means you can spread your chats out to be even within that 2 second period. /// You could spam them in a short duration but they will be then throttled. /// </remarks> /// <exception cref="FlatbuffersPacketException">Throws when the game has not started yet.</exception> /// <example> /// Sample code to send "What a save!" globally: /// <code> /// SendQuickChatFromAgent(false, QuickChatSelection.Compliments_WhatASave); /// </code> /// </example> protected void SendQuickChatFromAgent(bool teamOnly, QuickChatSelection quickChat) { try { TimeSpan timeSinceLastChat = DateTime.Now - lastChatTime; if (!resetChatTime && timeSinceLastChat.TotalSeconds >= MaxChatRate) { resetChatTime = true; } if (resetChatTime) { lastChatTime = DateTime.Now; chatCounter = 0; resetChatTime = false; } if (chatCounter < MaxChatCount) { RLBotInterface.SendQuickChatFlat(index, teamOnly, quickChat); chatCounter++; } else { Console.WriteLine($"Quick chat disabled for {(int) (MaxChatRate - timeSinceLastChat.TotalSeconds)} seconds."); } } catch (FlatbuffersPacketException) { throw new FlatbuffersPacketException("The game did not send any information. " + "This could mean that the match has not started yet. " + "This happens when you run the bot before (or as soon as) RLBot.exe gets started " + "and the game has not started the match yet. This usually happens on the map loading screen."); } }
/// <summary> /// Calls the given bot's <see cref="Bot.GetOutput(GameTickPacket)"/> method and /// updates its input through the interface DLL. /// </summary> /// <param name="bot"></param> private void RunBot(Bot bot) { while (true) { try { GameTickPacket gameTickPacket = RLBotInterface.GetGameTickPacket(); Controller botInput = bot.GetOutput(gameTickPacket); RLBotInterface.SetBotInput(botInput, bot.index); } catch (FlatbuffersPacketException) { // Ignore if the packet size is too small. No need to warn the user. } catch (Exception e) { // Don't crash the bot and give the user the details of the exception instead. Console.WriteLine(e.GetType()); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } botRunEvent.WaitOne(); } }
/// <summary> /// Allows the bot to set the games' state just like in training mode. /// </summary> /// <param name="gameState"></param> protected void SetGameState(GameState.GameState gameState) { if (gameState == null) { throw new ArgumentNullException("gameState"); } RLBotInterface.SetGameStatePacket(gameState.BuildGameStatePacket()); }
/// <summary> /// Gets all messages that have been send since the last call to this method. /// </summary> /// <returns>List of new messages.</returns> public QuickChatMessages ReceiveQuickChat() { QuickChatMessages messages = RLBotInterface.ReceiveQuickChat(index, team, lastMessageId); if (messages.MessagesLength > 0) { lastMessageId = messages.Messages(messages.MessagesLength - 1).Value.MessageIndex; } return(messages); }
protected FieldInfo GetFieldInfo() { try { return(RLBotInterface.GetFieldInfo()); } catch (FlatbuffersPacketException) { throw new FlatbuffersPacketException("The game did not send any information. " + "This could mean that the match has not started yet. " + "This happens when you run the bot before (or as soon as) the RLBot DLL is injected " + "and the game has not started the match yet. This usually happens on the map loading screen."); } }
/// <summary> /// The main bot manager loop. This will continuously run the bots by setting <see cref="BotProcess.botRunEvent"/>. /// </summary> private void MainBotLoop() { if (frequency > 0) { // Retrieve packets at a fixed frequency. TimeSpan timerResolution = TimerResolutionInterop.CurrentResolution; TimeSpan targetSleepTime = new TimeSpan(10000000 / frequency); Stopwatch stopwatch = new Stopwatch(); while (true) { // Start the timer stopwatch.Restart(); // Set off events that end up running the bot code later down the line foreach (BotProcess proc in botProcesses) { proc.botRunEvent.Set(); } // Sleep efficiently (but inaccurately) for as long as we can TimeSpan maxInaccurateSleepTime = targetSleepTime - stopwatch.Elapsed - timerResolution; if (maxInaccurateSleepTime > TimeSpan.Zero) { Thread.Sleep(maxInaccurateSleepTime); } // We can sleep the rest of the time accurately with the use of a spin-wait, this will drastically reduce the amount of duplicate packets when running at higher frequencies. while (stopwatch.Elapsed < targetSleepTime) { ; } } } else { // Dynamically retrieve new packets. while (true) { RLBotInterface.WaitForFreshPacket(100, 0); foreach (BotProcess proc in botProcesses) { proc.botRunEvent.Set(); } } } }
protected void SendQuickChatFromAgent(bool teamOnly, QuickChatSelection quickChat) { /* * Passes the agents quick chats to the other bots. * This does perform limiting. * You are limited to 5 quick chats in a 2 second period starting from the first chat. * This means you can spread your chats out to be even within that 2 second period. * You could spam them in the first little bit but then will be throttled. */ try { TimeSpan timeSinceLastChat = DateTime.Now - lastChatTime; if (!resetChatTime && timeSinceLastChat.TotalSeconds >= MAX_CHAT_RATE) { resetChatTime = true; } if (resetChatTime) { lastChatTime = DateTime.Now; chatCounter = 0; resetChatTime = false; } if (chatCounter < MAX_CHAT_COUNT) { RLBotInterface.SendQuickChatFlat(index, teamOnly, quickChat); chatCounter++; } else { Console.WriteLine($"Quick chat disabled for {(int)(MAX_CHAT_RATE - timeSinceLastChat.TotalSeconds)} seconds."); } } catch (FlatbuffersPacketException) { throw new FlatbuffersPacketException("The game did not send any information. " + "This could mean that the match has not started yet. " + "This happens when you run the bot before (or as soon as) the RLBot DLL is injected " + "and the game has not started the match yet. This usually happens on the map loading screen."); } }
/// <summary> /// Calls the given bot's <see cref="Bot.GetOutput(GameTickPacket)"/> method and /// updates its input through the interface DLL. /// </summary> private void RunBot(Bot bot, AutoResetEvent botRunEvent) { BotLoopRenderer renderer = GetRendererForBot(bot); bot.Renderer = renderer; Console.WriteLine("Waiting for the RLBot Interface to initialize..."); while (!RLBotInterface.IsInitialized()) { Thread.Sleep(100); } Console.WriteLine("The RLBot Interface has been successfully initialized!"); Console.WriteLine("Running the bot loop..."); while (true) { try { renderer.StartPacket(); GameTickPacket gameTickPacket = RLBotInterface.GetGameTickPacket(); Controller botInput = bot.GetOutput(gameTickPacket); RLBotInterface.SetBotInput(botInput, bot.index); renderer.FinishAndSendIfDifferent(); } catch (FlatbuffersPacketException) { // Ignore if the packet size is too small. No need to warn the user. } catch (Exception e) { // Don't crash the bot and give the user the details of the exception instead. Console.WriteLine(e.GetType()); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } botRunEvent.WaitOne(); } }
protected RigidBodyTick GetRigidBodyTick() { return(RLBotInterface.GetRigidBodyTick()); }
protected BallPrediction GetBallPrediction() { return(RLBotInterface.GetBallPredictionData()); }
protected MatchSettings GetMatchSettings() { return(RLBotInterface.GetMatchSettingsData()); }
/// <summary> /// Sends the render packet to the RLBot interface. /// </summary> /// <param name="packet">The packet to send.</param> protected void SendPacket(RenderPacket packet) { RLBotInterface.RenderPacket(packet); }
protected void SetGameState(GameState.GameState gameState) { RLBotInterface.SetGameStatePacket(gameState.BuildGameStatePacket()); }