Skip to content

Commit b0c1b15

Browse files
Merge branch 'master' into load_configs
2 parents a96d31f + f6afeeb commit b0c1b15

File tree

15 files changed

+252
-139
lines changed

15 files changed

+252
-139
lines changed

.github/workflows/publish.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Upload Python Package
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
release-build:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.11"
21+
22+
- name: Install deps
23+
run: python -m pip install wheel build
24+
25+
- name: Test install
26+
run: python -m pip install .
27+
28+
- name: Build for distribution
29+
run: python -m build
30+
31+
- name: Upload distributions
32+
uses: actions/upload-artifact@v4
33+
with:
34+
name: release-dists
35+
path: dist/
36+
37+
pypi-publish:
38+
runs-on: ubuntu-latest
39+
needs:
40+
- release-build
41+
permissions:
42+
# IMPORTANT: this permission is mandatory for trusted publishing
43+
id-token: write
44+
45+
# Dedicated environments with protections for publishing are strongly recommended.
46+
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
47+
environment:
48+
name: pypi
49+
url: https://pypi.org/p/rlbot
50+
51+
steps:
52+
- name: Retrieve release distributions
53+
uses: actions/download-artifact@v4
54+
with:
55+
name: release-dists
56+
path: dist/
57+
58+
- name: Publish release distributions to PyPI
59+
uses: pypa/gh-action-pypi-publish@release/v1
60+
with:
61+
packages-dir: dist/

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ A high performance Python interface for communicating with RLBot v5.
66

77
See this video tutorial on YouTube for a quick start guide: <https://www.youtube.com/watch?v=GLqvodQ942A>
88

9+
Also see the [main RLBot wiki](https://wiki.rlbot.org/) (make sure to avoid info on v4) and also see [this project's wiki](https://github.com/VirxEC/python-interface/wiki)
10+
911
## Dev setup
1012

1113
The following is how to setup a development environment for this project, NOT how to create a bot using this interface!
@@ -23,12 +25,13 @@ The following is how to setup a development environment for this project, NOT ho
2325
will be reflected in the installed package without
2426
having to run the command again
2527
- If you are making changes involving the flatbuffer schema and
26-
[rlbot_flatbuffers_py](https://github.com/VirxEC/rlbot_flatbuffers_py),
28+
[rlbot_flatbuffers_py](https://github.com/VirxEC/rlbot_flatbuffers_py),
2729
also install your local copy of that package in editable mode:
2830
- `pip uninstall rlbot_flatbuffers`
2931
- `pip install --editable <path/to/rlbot_flatbuffers>`
3032

3133
This project is formatted using [Black](https://github.com/psf/black).
34+
3235
- Install: `pip install black`.
3336
- Use: `black .`
3437

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ dependencies = [
1212
"psutil==6.*",
1313
]
1414
readme = "README.md"
15+
license = {text = "Unlicense"}
16+
authors = [
17+
{name = "RLBot Community", email = "[email protected]" }
18+
]
19+
keywords = ["rocket-league"]
1520

1621
[project.urls]
1722
Repository = "https://github.com/VirxEC/python-interface"

rlbot/interface.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import time
33
from collections.abc import Callable
4+
from dataclasses import dataclass
45
from enum import IntEnum
56
from pathlib import Path
67
from socket import IPPROTO_TCP, TCP_NODELAY, socket
@@ -41,10 +42,10 @@ class SocketDataType(IntEnum):
4142
CONTROLLABLE_TEAM_INFO = 15
4243

4344

45+
@dataclass(repr=False, eq=False, frozen=True, match_args=False, slots=True)
4446
class SocketMessage:
45-
def __init__(self, type: int, data: bytes):
46-
self.type = SocketDataType(type)
47-
self.data = data
47+
type: SocketDataType
48+
data: bytes
4849

4950

5051
class MsgHandlingResult(IntEnum):
@@ -104,9 +105,11 @@ def _read_int(self) -> int:
104105

105106
def _read_exact(self, n: int) -> bytes:
106107
buff = bytearray(n)
108+
view = memoryview(buff)
109+
107110
pos = 0
108111
while pos < n:
109-
cr = self.socket.recv_into(memoryview(buff)[pos:])
112+
cr = self.socket.recv_into(view[pos:])
110113
if cr == 0:
111114
raise EOFError
112115
pos += cr
@@ -116,7 +119,7 @@ def read_message(self) -> SocketMessage:
116119
type_int = self._read_int()
117120
size = self._read_int()
118121
data = self._read_exact(size)
119-
return SocketMessage(type_int, data)
122+
return SocketMessage(SocketDataType(type_int), data)
120123

121124
def send_bytes(self, data: bytes, data_type: SocketDataType):
122125
assert self.is_connected, "Connection has not been established"

rlbot/managers/bot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def set_game_state(
250250
balls: dict[int, flat.DesiredBallState] = {},
251251
cars: dict[int, flat.DesiredCarState] = {},
252252
match_info: Optional[flat.DesiredMatchInfo] = None,
253-
commands: list[flat.ConsoleCommand] = [],
253+
commands: list[str] = [],
254254
):
255255
"""
256256
Sets the game to the desired state.

rlbot/managers/hivemind.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,18 @@ def _packet_processor(self, packet: flat.GamePacket):
170170

171171
def _run(self):
172172
running = True
173-
has_more_messages = True
174173

175174
while running:
176175
# If there might be more messages,
177176
# check for another one with blocking=False
178177
# if there are no more messages, process the latest packet
179178
# then wait for the next message with blocking=True
180179
match self._game_interface.handle_incoming_messages(
181-
blocking=not has_more_messages
180+
blocking=self._latest_packet is None
182181
):
183182
case MsgHandlingResult.TERMINATED:
184183
running = False
185184
case MsgHandlingResult.NO_INCOMING_MSGS:
186-
has_more_messages = False
187-
188185
if self._latest_packet is not None:
189186
self._packet_processor(self._latest_packet)
190187
self._latest_packet = None
@@ -267,7 +264,7 @@ def set_game_state(
267264
balls: dict[int, flat.DesiredBallState] = {},
268265
cars: dict[int, flat.DesiredCarState] = {},
269266
match_info: Optional[flat.DesiredMatchInfo] = None,
270-
commands: list[flat.ConsoleCommand] = [],
267+
commands: list[str] = [],
271268
):
272269
"""
273270
Sets the game to the desired state.

rlbot/managers/match.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import psutil
66

7-
from rlbot import flat, version
7+
from rlbot import flat
88
from rlbot.interface import RLBOT_SERVER_IP, RLBOT_SERVER_PORT, SocketRelay
99
from rlbot.utils import fill_desired_game_state, gateway
1010
from rlbot.utils.logging import DEFAULT_LOGGER
@@ -26,17 +26,13 @@ def __init__(
2626
self,
2727
main_executable_path: Optional[Path] = None,
2828
main_executable_name: str = MAIN_EXECUTABLE_NAME,
29-
print_version_info: bool = True,
3029
):
3130
self.main_executable_path = main_executable_path
3231
self.main_executable_name = main_executable_name
3332

3433
self.rlbot_interface: SocketRelay = SocketRelay("")
3534
self.rlbot_interface.packet_handlers.append(self._packet_reporter)
3635

37-
if print_version_info:
38-
version.print_current_release_notes()
39-
4036
def ensure_server_started(self):
4137
"""
4238
Ensures that RLBotServer is running, starting it if it is not.
@@ -143,7 +139,7 @@ def set_game_state(
143139
balls: dict[int, flat.DesiredBallState] = {},
144140
cars: dict[int, flat.DesiredCarState] = {},
145141
match_info: Optional[flat.DesiredMatchInfo] = None,
146-
commands: list[flat.ConsoleCommand] = [],
142+
commands: list[str] = [],
147143
):
148144
"""
149145
Sets the game to the desired state.

rlbot/managers/script.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,18 @@ def _packet_processor(self, packet: flat.GamePacket):
127127

128128
def _run(self):
129129
running = True
130-
has_more_messages = True
131130

132131
while running:
133132
# If there might be more messages,
134133
# check for another one with blocking=False
135134
# if there are no more messages, process the latest packet
136135
# then wait for the next message with blocking=True
137136
match self._game_interface.handle_incoming_messages(
138-
blocking=not has_more_messages
137+
blocking=self._latest_packet is None
139138
):
140139
case MsgHandlingResult.TERMINATED:
141140
running = False
142141
case MsgHandlingResult.NO_INCOMING_MSGS:
143-
has_more_messages = False
144-
145142
if self._latest_packet is not None:
146143
self._packet_processor(self._latest_packet)
147144
self._latest_packet = None
@@ -220,7 +217,7 @@ def set_game_state(
220217
balls: dict[int, flat.DesiredBallState] = {},
221218
cars: dict[int, flat.DesiredCarState] = {},
222219
match_info: Optional[flat.DesiredMatchInfo] = None,
223-
commands: list[flat.ConsoleCommand] = [],
220+
commands: list[str] = [],
224221
):
225222
"""
226223
Sets the game to the desired state.

rlbot/utils/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ def fill_desired_game_state(
77
balls: dict[int, flat.DesiredBallState] = {},
88
cars: dict[int, flat.DesiredCarState] = {},
99
match_info: Optional[flat.DesiredMatchInfo] = None,
10-
commands: list[flat.ConsoleCommand] = [],
10+
commands: list[str] = [],
1111
) -> flat.DesiredGameState:
1212
"""
13-
# Converts the dictionaries to a DesiredGameState by
14-
# filling in the blanks with empty states that do nothing.
13+
Converts the dictionaries to a DesiredGameState by
14+
filling in the blanks with empty states that do nothing.
1515
"""
1616

17-
game_state = flat.DesiredGameState(match_info=match_info, console_commands=commands)
17+
game_state = flat.DesiredGameState(
18+
match_info=match_info,
19+
console_commands=[flat.ConsoleCommand(cmd) for cmd in commands],
20+
)
1821

1922
if balls:
2023
max_entry = max(balls.keys())

rlbot/utils/logging.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
import logging
2+
import os
23
import sys
34

45
DEFAULT_LOGGER_NAME = "rlbot"
56
DEFAULT_LOGGER = None # Set later
6-
LOGGING_LEVEL = logging.INFO
7+
8+
match os.environ.get("RLBOT_LOG_LEVEL"):
9+
case "debug":
10+
LOGGING_LEVEL = logging.DEBUG
11+
case "info":
12+
LOGGING_LEVEL = logging.INFO
13+
case "warn":
14+
LOGGING_LEVEL = logging.WARNING
15+
case "error":
16+
LOGGING_LEVEL = logging.ERROR
17+
case "critical":
18+
LOGGING_LEVEL = logging.CRITICAL
19+
case _:
20+
LOGGING_LEVEL = logging.INFO
721

822
logging.getLogger().setLevel(logging.NOTSET)
923

0 commit comments

Comments
 (0)