2023-03-15 07:12:47 +01:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
from typing import TYPE_CHECKING, Tuple, Type
|
|
|
|
|
|
|
|
from sampy.client.player import Player
|
|
|
|
from sampy.config import Config
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from sampy.network.protocol import Protocol
|
|
|
|
|
|
|
|
|
|
|
|
class UDPProtocol:
|
|
|
|
transport: asyncio.transports.DatagramTransport
|
|
|
|
|
|
|
|
def __init__(self, protocol: Protocol, local_addr: Tuple[str, int]):
|
|
|
|
self.protocol = protocol
|
|
|
|
self.local_addr = local_addr
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
connect = loop.create_datagram_endpoint(
|
|
|
|
lambda: self,
|
|
|
|
local_addr=self.local_addr,
|
|
|
|
)
|
|
|
|
loop.run_until_complete(connect)
|
|
|
|
|
|
|
|
def stop(self): # TODO: Shutdown code
|
|
|
|
if self.transport is None:
|
|
|
|
raise Exception("Cannot stop a server that hasn't been started")
|
|
|
|
|
|
|
|
self.transport.close()
|
|
|
|
|
|
|
|
def connection_made(self, transport: asyncio.transports.DatagramTransport):
|
|
|
|
self.transport = transport
|
|
|
|
|
2023-03-15 07:27:33 +01:00
|
|
|
def connection_lost(self, exc: Exception | None):
|
|
|
|
pass
|
|
|
|
|
2023-03-15 07:12:47 +01:00
|
|
|
def datagram_received(self, data: bytes, addr: Tuple[str, int]):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def sendto(self, data: bytes | bytearray | memoryview, addr: Tuple[str, int]):
|
|
|
|
self.transport.sendto(data, addr)
|
|
|
|
|
|
|
|
|
|
|
|
class Server(UDPProtocol):
|
|
|
|
config: Config
|
|
|
|
|
|
|
|
def __init__(self, protocol: Type[Protocol], config: Config = Config()):
|
|
|
|
super().__init__(
|
|
|
|
protocol=protocol(),
|
|
|
|
local_addr=(
|
|
|
|
config.get("sampy", "host"),
|
|
|
|
config.getint("sampy", "port"),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
self.config = config
|
|
|
|
|
|
|
|
def datagram_received(self, data: bytes, addr: Tuple[str, int]):
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
loop.create_task(self.protocol.on_packet(self, data, addr))
|
|
|
|
|
|
|
|
@property
|
|
|
|
def players(self) -> list[Player]: # TODO
|
|
|
|
return []
|
2023-03-15 07:27:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
class InteractiveServer(Server):
|
|
|
|
def __init__(self, protocol: Type[Protocol], config: Config = Config()):
|
|
|
|
super().__init__(protocol=protocol, config=config)
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
loop.create_task(self.run_input_loop())
|
|
|
|
|
|
|
|
async def run_input_loop(self):
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
while True:
|
|
|
|
command = await loop.run_in_executor(None, input)
|
|
|
|
|
|
|
|
if command in ("quit", "exit", "stop"):
|
|
|
|
self.stop()
|
|
|
|
loop.stop()
|
|
|
|
return
|