summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Schmid <dominikschmid93@gmail.com>2019-04-18 00:57:31 +1000
committerDominik Schmid <dominikschmid93@gmail.com>2019-04-18 00:57:31 +1000
commit5be54b53ae6738105bd7f1068c99bfbf20095b57 (patch)
tree82438c3fe927c56fec9ac1dde3f8dcb1fa39fb2f
parent6d066d2e72561b21c00c3a769b222c643690e889 (diff)
First cut at getting an agent to connect to a server within setup_manager.pywebsocket-matchcomms
-rw-r--r--src/main/python/rlbot/agents/base_agent.py17
-rw-r--r--src/main/python/rlbot/botmanager/bot_manager.py13
-rw-r--r--src/main/python/rlbot/botmanager/bot_manager_flatbuffer.py7
-rw-r--r--src/main/python/rlbot/botmanager/bot_manager_independent.py7
-rw-r--r--src/main/python/rlbot/botmanager/bot_manager_struct.py7
-rw-r--r--src/main/python/rlbot/setup_manager.py42
6 files changed, 56 insertions, 37 deletions
diff --git a/src/main/python/rlbot/agents/base_agent.py b/src/main/python/rlbot/agents/base_agent.py
index abb9219e..844ff2f7 100644
--- a/src/main/python/rlbot/agents/base_agent.py
+++ b/src/main/python/rlbot/agents/base_agent.py
@@ -1,4 +1,8 @@
+from typing import Optional
+from urllib.parse import ParseResult as URL
+
from rlbot.botmanager.helper_process_request import HelperProcessRequest
+from rlbot.matchcomms.client import MatchcommsClient
from rlbot.parsing.custom_config import ConfigObject
from rlbot.utils.game_state_util import GameState
from rlbot.utils.logging_utils import get_logger
@@ -65,12 +69,11 @@ class BaseAgent:
# passed in by the bot manager
__quick_chat_func = None
-
- # passed in by the bot manager
__field_info_func = None
__game_state_func = None
__get_rigid_body_tick_func = None
renderer: RenderingManager = None
+ matchcomms_root: URL = None
def __init__(self, name, team, index):
self.name = name
@@ -136,6 +139,16 @@ class BaseAgent:
"""Fetches a prediction of where the ball will go during the next few seconds."""
return self.__ball_prediction_struct_func()
+ _matchcomms_client: Optional[MatchcommsClient] = None
+ @property
+ def matchcomms_client(self) -> MatchcommsClient:
+ """
+ Gets a client to send and recieve messages to other participants in the match (e.g. bots, trainer)
+ """
+ if self._matchcomms_client is None:
+ self._matchcomms_client = MatchcommsClient(self.matchcomms_root)
+ return self._matchcomms_client # note: _matchcomms_client.close() is called by the bot_manager.
+
def load_config(self, config_object_header):
"""
Loads a config object this is called after the constructor but before anything else inside the bot.
diff --git a/src/main/python/rlbot/botmanager/bot_manager.py b/src/main/python/rlbot/botmanager/bot_manager.py
index 0ec979cd..6d984176 100644
--- a/src/main/python/rlbot/botmanager/bot_manager.py
+++ b/src/main/python/rlbot/botmanager/bot_manager.py
@@ -3,9 +3,11 @@ import time
import traceback
from datetime import datetime, timedelta
import multiprocessing as mp
+from urllib.parse import ParseResult as URL
from rlbot.agents.base_agent import BaseAgent
from rlbot.botmanager.agent_metadata import AgentMetadata
+from rlbot.matchconfig.match_config import MatchConfig
from rlbot.utils import rate_limiter
from rlbot.utils.game_state_util import GameState
from rlbot.utils.logging_utils import get_logger
@@ -25,7 +27,8 @@ MAX_CARS = 10
class BotManager:
def __init__(self, terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder, match_config):
+ name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder, match_config: MatchConfig,
+ matchcomms_root: URL):
"""
:param terminate_request_event: an Event (multiprocessing) which will be set from the outside when the program is trying to terminate
:param termination_complete_event: an Event (multiprocessing) which should be set from inside this class when termination has completed successfully
@@ -39,6 +42,8 @@ class BotManager:
:param agent_class_wrapper: The ExternalClassWrapper object that can be used to load and reload the bot
:param agent_metadata_queue: a Queue (multiprocessing) which expects to receive AgentMetadata once available.
:param quick_chat_queue_holder: A data structure which helps the bot send and receive quickchat
+ :param match_config: Describes the match that is being played.
+ :param matchcomms_root: The server to connect to if you want to communicate to other participants in the match.
"""
self.terminate_request_event = terminate_request_event
self.termination_complete_event = termination_complete_event
@@ -61,6 +66,7 @@ class BotManager:
self.ball_prediction = None
self.rigid_body_tick = None
self.match_config = match_config
+ self.matchcomms_root = matchcomms_root
def send_quick_chat_from_agent(self, team_only, quick_chat):
"""
@@ -101,6 +107,7 @@ class BotManager:
agent._register_ball_prediction(self.get_ball_prediction)
agent._register_ball_prediction_struct(self.get_ball_prediction_struct)
agent._register_get_rigid_body_tick(self.get_rigid_body_tick)
+ agent.matchcomms_root = self.matchcomms_root
if self.quick_chat_quit_event:
self.quick_chat_quit_event.set()
self.quick_chat_quit_event = mp.Event()
@@ -222,6 +229,10 @@ class BotManager:
self.game_interface.update_player_input(PlayerInput(), self.index)
self.quick_chat_quit_event.set() # Shut down quick chat.
+ # Don't trust the agent to shut down its own client in retire().
+ if agent._matchcomms_client is not None:
+ agent._matchcomms_client.close()
+
# If terminated, send callback
self.termination_complete_event.set()
diff --git a/src/main/python/rlbot/botmanager/bot_manager_flatbuffer.py b/src/main/python/rlbot/botmanager/bot_manager_flatbuffer.py
index 54b9f179..16639f27 100644
--- a/src/main/python/rlbot/botmanager/bot_manager_flatbuffer.py
+++ b/src/main/python/rlbot/botmanager/bot_manager_flatbuffer.py
@@ -3,14 +3,11 @@ from rlbot.messages.flat import GameTickPacket
class BotManagerFlatbuffer(BotManager):
- def __init__(self, terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder, match_config):
+ def __init__(self, *args, **kwargs):
"""
See documentation on BotManager.
"""
- super().__init__(terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder,
- match_config)
+ super().__init__(*args, **kwargs)
self.game_tick_flat = None
self.game_tick_flat_binary = None
diff --git a/src/main/python/rlbot/botmanager/bot_manager_independent.py b/src/main/python/rlbot/botmanager/bot_manager_independent.py
index 69dc9467..5ec75940 100644
--- a/src/main/python/rlbot/botmanager/bot_manager_independent.py
+++ b/src/main/python/rlbot/botmanager/bot_manager_independent.py
@@ -2,14 +2,11 @@ from rlbot.botmanager.bot_manager import BotManager
class BotManagerIndependent(BotManager):
- def __init__(self, terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder, match_config):
+ def __init__(self, *args, **kwargs):
"""
See documentation on BotManager.
"""
- super().__init__(terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder,
- match_config)
+ super().__init__(*args, **kwargs)
def run(self):
# Get bot module
diff --git a/src/main/python/rlbot/botmanager/bot_manager_struct.py b/src/main/python/rlbot/botmanager/bot_manager_struct.py
index 4692004c..1debfc7d 100644
--- a/src/main/python/rlbot/botmanager/bot_manager_struct.py
+++ b/src/main/python/rlbot/botmanager/bot_manager_struct.py
@@ -8,14 +8,11 @@ from rlbot.utils.structures.rigid_body_struct import RigidBodyTick
class BotManagerStruct(BotManager):
- def __init__(self, terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder, match_config):
+ def __init__(self, *args, **kwargs):
"""
See documentation on BotManager.
"""
- super().__init__(terminate_request_event, termination_complete_event, reload_request_event, bot_configuration,
- name, team, index, agent_class_wrapper, agent_metadata_queue, quick_chat_queue_holder,
- match_config)
+ super().__init__(*args, **kwargs)
self.rigid_body_tick = None
def prepare_for_run(self):
diff --git a/src/main/python/rlbot/setup_manager.py b/src/main/python/rlbot/setup_manager.py
index 35bf647e..3bdd600d 100644
--- a/src/main/python/rlbot/setup_manager.py
+++ b/src/main/python/rlbot/setup_manager.py
@@ -1,14 +1,15 @@
-from typing import List
from contextlib import contextmanager
from datetime import datetime, timedelta
+from typing import List
+from urllib.parse import ParseResult as URL
import msvcrt
import multiprocessing as mp
import os
+import psutil
import queue
import time
import webbrowser
-import psutil
from rlbot import version
from rlbot.base_extension import BaseExtension
from rlbot.botmanager.bot_manager_flatbuffer import BotManagerFlatbuffer
@@ -17,6 +18,7 @@ from rlbot.botmanager.bot_manager_struct import BotManagerStruct
from rlbot.botmanager.helper_process_manager import HelperProcessManager
from rlbot.matchconfig.conversions import parse_match_config
from rlbot.matchconfig.match_config import MatchConfig
+from rlbot.matchcomms.server import launch_matchcomms_server
from rlbot.parsing.agent_config_parser import load_bot_appearance
from rlbot.parsing.bot_config_bundle import get_bot_config_bundle
from rlbot.parsing.custom_config import ConfigObject
@@ -80,18 +82,6 @@ class SetupManager:
extension = None
bot_processes: List[mp.Process] = []
- _matchcomms_address: str = None
- _matchcomms_process: mp.Process = None
- @property
- def foo(self):
- if self._matchcomms_address is not None:
- return self._matchcomms_address
-
- self._matchcomms_address =
- return self._matchcomms_address
- return self._foo
-
-
def __init__(self):
self.logger = get_logger(DEFAULT_LOGGER)
@@ -104,6 +94,7 @@ class SetupManager:
self.agent_metadata_map = {}
self.ball_prediction_process = None
self.match_config: MatchConfig = None
+ self.matchcomms_server: MatchcommsServerThread = None
def connect_to_game(self):
if self.has_started:
@@ -202,6 +193,10 @@ class SetupManager:
self.logger.debug("Launching bot processes")
self.kill_bot_processes()
+ # Start matchcomms here as it's only required for the bots.
+ self.kill_matchcomms_server()
+ self.matchcomms_server = launch_matchcomms_server()
+
# Launch processes
for i in range(self.num_participants):
if self.start_match_configuration.player_configuration[i].rlbot_controlled:
@@ -214,7 +209,7 @@ class SetupManager:
args=(self.quit_event, quit_callback, reload_request, self.parameters[i],
str(self.start_match_configuration.player_configuration[i].name),
self.teams[i], i, self.python_files[i], self.agent_metadata_queue,
- queue_holder, self.match_config))
+ queue_holder, self.match_config, self.matchcomms_server.root_url))
process.start()
self.bot_processes.append(process)
@@ -301,6 +296,8 @@ class SetupManager:
if kill_all_pids:
self.kill_agent_process_ids()
+ self.kill_matchcomms_server()
+
# The quit event can only be set once. Let's reset to our initial state
self.quit_event = mp.Event()
self.helper_process_manager = HelperProcessManager(self.quit_event)
@@ -318,19 +315,22 @@ class SetupManager:
@staticmethod
def run_agent(terminate_event, callback_event, reload_request, config_file, name, team, index, python_file,
- agent_telemetry_queue, queue_holder, match_config: MatchConfig):
+ agent_telemetry_queue, queue_holder, match_config: MatchConfig, matchcomms_root: URL):
agent_class_wrapper = import_agent(python_file)
if hasattr(agent_class_wrapper.get_loaded_class(), "run_independently"):
bm = BotManagerIndependent(terminate_event, callback_event, reload_request, config_file, name, team, index,
- agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config)
+ agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config,
+ matchcomms_root)
elif hasattr(agent_class_wrapper.get_loaded_class(), "get_output_flatbuffer"):
bm = BotManagerFlatbuffer(terminate_event, callback_event, reload_request, config_file, name, team, index,
- agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config)
+ agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config,
+ matchcomms_root)
else:
bm = BotManagerStruct(terminate_event, callback_event, reload_request, config_file, name, team, index,
- agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config)
+ agent_class_wrapper, agent_telemetry_queue, queue_holder, match_config,
+ matchcomms_root)
bm.run()
def kill_bot_processes(self):
@@ -359,6 +359,10 @@ class SetupManager:
except psutil.NoSuchProcess:
self.logger.info("Can't fetch parent process, already dead.")
+ def kill_matchcomms_server(self):
+ if self.matchcomms_server:
+ self.matchcomms_server.close()
+ self.matchcomms_server = None
def load_bot_parameters(config_bundle) -> ConfigObject:
"""