65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
import socket
|
|
import asyncio
|
|
from select import select # This is straight up magic
|
|
|
|
from ..struct.server import ServerConfig
|
|
from ..client import Client
|
|
|
|
from .compression import Compressor
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class Server:
|
|
def __init__(self, config: ServerConfig):
|
|
self.config = config
|
|
self.clients = {}
|
|
self.rcon_clients = {}
|
|
|
|
self.compressor = Compressor(self.config)
|
|
|
|
async def create_socket(self):
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
self.socket.bind((self.config.host, self.config.port))
|
|
self.socket.setblocking(0) # TODO: Check if needed? I dont fully understand this "feature"
|
|
logger.debug("Socket created")
|
|
|
|
async def on_command(self, cmd: str):
|
|
logger.debug("on_command(%s)" % cmd)
|
|
# TODO: When commands return a reponse we also want to forward this to potential rcon clients
|
|
|
|
async def get_online_players(self): # TODO: Get data from server's client objects
|
|
return [
|
|
{"nick": b"Sunpy", "score": 64, "ping": 8, "id": 1} # replace id with function to get player's id
|
|
]
|
|
|
|
async def get_rules(self): # TODO
|
|
return {b"Rule name sample": b"Rule value", b"weburl": b"https://git.osufx.com/Sunpy/sampy"}
|
|
|
|
async def get_players_scores(self): # TODO
|
|
return {b"Sunpy": 64, b"username": 123}
|
|
|
|
async def main(self):
|
|
await self.create_socket()
|
|
|
|
while True:
|
|
(incomming, _, _) = select([self.socket], [], [], 0) # How this works is beyond me, but this sets `incomming` to be true~y if socket has awaiting data
|
|
|
|
if incomming:
|
|
data, addr = self.socket.recvfrom(0xFFFF)
|
|
|
|
if addr not in self.clients:
|
|
ip, port = addr
|
|
self.clients[addr] = Client(self, ip, port)
|
|
await (self.clients[addr].onpacket(data)) #await self.clients[addr].on_packet(data)
|
|
|
|
disconnected = [c for c in self.clients.values() if c.connected == False]
|
|
for c in disconnected: # Remove dead connections
|
|
addr = (c.ip, c.port)
|
|
if addr in self.clients:
|
|
del self.clients[addr]
|
|
logger.debug("free(%s)" % c)
|
|
|
|
await asyncio.sleep(0)
|