import asyncio import logging import struct logger = logging.getLogger(__name__) RCON_TYPE_COMMAND = 2 RCON_TYPE_AUTH = 3 RCON_TYPE_RESPONSE = 0 class McRconClient: def __init__(self, host: str, port: int, password: str): self.host = host self.port = port self.password = password self._reader: asyncio.StreamReader | None = None self._writer: asyncio.StreamWriter | None = None self._request_id = 0 async def connect(self) -> bool: try: self._reader, self._writer = await asyncio.wait_for( asyncio.open_connection(self.host, self.port), timeout=10 ) except Exception: logger.exception("RCON connection failed to %s:%d", self.host, self.port) return False self._request_id += 1 success = await self._send_packet(RCON_TYPE_AUTH, self.password) if not success: logger.error("RCON authentication failed") return False return True async def execute(self, command: str) -> str: if not self._writer or self._writer.is_closing(): if not await self.connect(): return "RCON connection failed" self._request_id += 1 return await self._send_packet(RCON_TYPE_COMMAND, command) async def _send_packet(self, ptype: int, payload: str) -> str: req_id = self._request_id packet = struct.pack("