Add UDP send;

Remove rights to spawn unicycle (For now);
Minor updates;
This commit is contained in:
Maxim Khomutov 2023-07-19 03:48:57 +03:00
parent 77ee76c0c0
commit 47cca3a0d8
2 changed files with 62 additions and 37 deletions

View File

@ -103,57 +103,75 @@ class Client:
if type(data) == str: if type(data) == str:
data = bytes(data, "utf-8") data = bytes(data, "utf-8")
if writer is None:
writer = self.__writer
if to_all: if to_all:
code = chr(data[0]) code = chr(data[0])
for client in self.__Core.clients: for client in self.__Core.clients:
if not client or (client is self and not to_self): if not client or (client is self and not to_self):
continue continue
if not to_udp or code in ['V', 'W', 'Y', 'E']: if not to_udp or code in ['V', 'W', 'Y', 'E']:
if code in ['O', 'T'] or len(data) > 1000:
await client._send(data) await client._send(data)
else: else:
await client._send(data) await client._send(data, to_udp=to_udp)
else:
# TODO: UDP send
self.log.debug(f"UDP Part not ready: {code}")
return return
if not self.__alive:
return False
if writer is None:
writer = self.__writer
if len(data) > 400: if len(data) > 400:
data = b"ABG:" + zlib.compress(data, level=zlib.Z_BEST_COMPRESSION) data = b"ABG:" + zlib.compress(data, level=zlib.Z_BEST_COMPRESSION)
if to_udp:
udp_sock = self._udp_sock[0]
udp_addr = self._udp_sock[1]
# self.log.debug(f'[UDP] len: {len(data)}; send: {data!r}')
if udp_sock and udp_addr:
try:
if not udp_sock.is_closing():
# self.log.debug(f'[UDP] {data!r}')
udp_sock.sendto(data, udp_addr)
except OSError:
self.log.debug("[UDP] Error sending")
except Exception as e:
self.log.debug(f"[UDP] Error sending: {e}")
self.log.exception(e)
return
header = len(data).to_bytes(4, "little", signed=True) header = len(data).to_bytes(4, "little", signed=True)
self.log.debug(f'len: {len(data)}; send: {header + data!r}') self.log.debug(f'[TCP] {header + data!r}')
try: try:
writer.write(header + data) writer.write(header + data)
await writer.drain() await writer.drain()
return True
except ConnectionError: except ConnectionError:
self.log.debug('_send: Disconnected') self.log.debug('[TCP] Disconnected')
self.__alive = False self.__alive = False
await self._remove_me() await self._remove_me()
return False
async def __handle_packet(self, data, int_header): # async def __handle_packet(self, data, int_header):
self.log.debug(f"int_header: {int_header}; data: {data};") # self.log.debug(f"int_header: {int_header}; data: {data};")
if len(data) != int_header: # if len(data) != int_header:
self.log.debug(f"WARN Expected to read {int_header} bytes, instead got {len(data)}") # self.log.debug(f"WARN Expected to read {int_header} bytes, instead got {len(data)}")
#
recv2 = data[int_header:] # recv2 = data[int_header:]
header2 = recv2[:4] # header2 = recv2[:4]
data2 = recv2[4:] # data2 = recv2[4:]
int_header2 = int.from_bytes(header2, byteorder='little', signed=True) # int_header2 = int.from_bytes(header2, byteorder='little', signed=True)
t = asyncio.create_task(self.__handle_packet(data2, int_header2)) # t = asyncio.create_task(self.__handle_packet(data2, int_header2))
self.__tasks.append(t) # self.__tasks.append(t)
data = data[:4 + int_header] # data = data[:4 + int_header]
#
abg = b"ABG:" # abg = b"ABG:"
if len(data) > len(abg) and data.startswith(abg): # if len(data) > len(abg) and data.startswith(abg):
data = zlib.decompress(data[len(abg):]) # data = zlib.decompress(data[len(abg):])
self.log.debug(f"ABG Packet: {len(data)}") # self.log.debug(f"ABG Packet: {len(data)}")
#
self.__packets_queue.append(data) # self.__packets_queue.append(data)
self.log.debug(f"Packets in queue: {len(self.__packets_queue)}") # self.log.debug(f"Packets in queue: {len(self.__packets_queue)}")
async def _recv(self, one=False): async def _recv(self, one=False):
while self.__alive: while self.__alive:
@ -283,7 +301,7 @@ class Client:
else: else:
await self._send(bytes(mod_list, "utf-8")) await self._send(bytes(mod_list, "utf-8"))
elif data == b"Done": elif data == b"Done":
for c in range(config.Game['max_cars']): for c in range(int(config.Game['max_cars'] * 2.3)):
self._cars.append(None) self._cars.append(None)
await self._send(b"M/levels/" + bytes(config.Game['map'], 'utf-8') + b"/info.json") await self._send(b"M/levels/" + bytes(config.Game['map'], 'utf-8') + b"/info.json")
break break
@ -310,7 +328,7 @@ class Client:
self.log.debug(f"Invalid packet: Could not parse pid/vid from packet: '{data}'") self.log.debug(f"Invalid packet: Could not parse pid/vid from packet: '{data}'")
return -1, -1 return -1, -1
async def _handle_vehicle_codes(self, dta): async def _handle_car_codes(self, dta):
if len(dta) < 6: if len(dta) < 6:
return return
sub_code = dta[1] sub_code = dta[1]
@ -336,7 +354,9 @@ class Client:
# TODO: Call event onCarSpawn # TODO: Call event onCarSpawn
pkt = f"Os:{self.roles}:{self.nick}:{self.cid}-{car_id}:{car_data}" pkt = f"Os:{self.roles}:{self.nick}:{self.cid}-{car_id}:{car_data}"
unicycle = car_json.get("jbm") == "unicycle" unicycle = car_json.get("jbm") == "unicycle"
if (allow and (config.Game['max_cars'] > car_id or unicycle)) or over_spawn: # FIXME: unicycle
# if (allow and (config.Game['max_cars'] > car_id or unicycle)) or over_spawn:
if config.Game['max_cars'] > car_id and not unicycle:
self.log.debug(f"Car spawn accepted.") self.log.debug(f"Car spawn accepted.")
self._cars[car_id] = { self._cars[car_id] = {
"packet": pkt, "packet": pkt,
@ -416,8 +436,10 @@ class Client:
data = data.decode() data = data.decode()
except UnicodeDecodeError: except UnicodeDecodeError:
self.log.debug(f"UnicodeDecodeError: {data}") self.log.debug(f"UnicodeDecodeError: {data}")
return
code = data[0] code = data[0]
# Codes: p, Z in udp_server.py
match code: match code:
case "H": case "H":
# Client connected # Client connected
@ -437,7 +459,10 @@ class Client:
await self._send(car['packet']) await self._send(car['packet'])
case "C": # Chat handler case "C": # Chat handler
msg = data[4 + len(self.nick):] sup = data.find(":", 2)
if sup == -1:
await self._send("C:Server: Invalid message.")
msg = data[sup+2:]
if not msg: if not msg:
self.log.debug("Tried to send an empty event, ignoring") self.log.debug("Tried to send an empty event, ignoring")
return return
@ -468,7 +493,7 @@ class Client:
await self._send(data, to_all=True) await self._send(data, to_all=True)
case "O": # Cars handler case "O": # Cars handler
await self._handle_vehicle_codes(data) await self._handle_car_codes(data)
case "E": # Client events handler case "E": # Client events handler
# TODO: HandleEvent # TODO: HandleEvent

View File

@ -57,7 +57,7 @@ class Client:
async def _recv(self, one=False) -> bytes | None: ... async def _recv(self, one=False) -> bytes | None: ...
async def _split_load(self, start: int, end: int, d_sock: bool, filename: str) -> None: ... async def _split_load(self, start: int, end: int, d_sock: bool, filename: str) -> None: ...
async def _get_cid_vid(self, s: str) -> Tuple[int, int]: ... async def _get_cid_vid(self, s: str) -> Tuple[int, int]: ...
async def _handle_vehicle_codes(self, data) -> None: ... async def _handle_car_codes(self, data) -> None: ...
async def _handle_codes(self, data) -> None: ... async def _handle_codes(self, data) -> None: ...
async def _looper(self) -> None: ... async def _looper(self) -> None: ...
def _update_logger(self) -> None: ... def _update_logger(self) -> None: ...