added super basic callbacks hooks to server

This commit is contained in:
əlemi 2021-11-22 00:35:42 +01:00
parent 23418c06d0
commit c2e8e80806

View file

@ -6,7 +6,7 @@ from asyncio import Task, StreamReader, StreamWriter
from asyncio.base_events import Server # just for typing from asyncio.base_events import Server # just for typing
from enum import Enum from enum import Enum
from typing import Dict, List, Callable, Type, Optional, Tuple, AsyncIterator from typing import Dict, List, Callable, Coroutine, Type, Optional, Tuple, AsyncIterator
from .dispatcher import Dispatcher from .dispatcher import Dispatcher
from .mc.packet import Packet from .mc.packet import Packet
@ -36,6 +36,10 @@ class MinecraftServer:
_logger : logging.Logger _logger : logging.Logger
_disconnect_handlers : List[Callable]
_connect_handlers : List[Callable]
_packet_handlers : List[Callable]
def __init__( def __init__(
self, self,
host:str, host:str,
@ -48,6 +52,7 @@ class MinecraftServer:
self.options = options or { self.options = options or {
"poll-timeout" : 1, "poll-timeout" : 1,
"online-mode" : False, "online-mode" : False,
"spawn-player" : True,
} }
self._dispatcher_pool = [] self._dispatcher_pool = []
@ -55,10 +60,32 @@ class MinecraftServer:
self._logger = LOGGER.getChild(f"@({self.host}:{self.port})") self._logger = LOGGER.getChild(f"@({self.host}:{self.port})")
self._disconnect_handlers = []
self._connect_handlers = []
self._packet_handlers = []
@property @property
def started(self) -> bool: def started(self) -> bool:
return self._processing return self._processing
def on_client_connect(self, *args):
def wrapper(fun):
self._connect_handlers.append(fun)
return fun
return wrapper
def on_client_disconnect(self, *args):
def wrapper(fun):
self._disconnect_handlers.append(fun)
return fun
return wrapper
def on_client_packet(self, *args):
def wrapper(fun):
self._packet_handlers.append(fun)
return fun
return wrapper
def run(self): def run(self):
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
@ -89,9 +116,8 @@ class MinecraftServer:
async def stop(self, block=True, wait_tasks=True): async def stop(self, block=True, wait_tasks=True):
self._processing = False self._processing = False
# if self.dispatcher.connected:
# await self.dispatcher.disconnect(block=block)
self._server.close() self._server.close()
await asyncio.gather(*[d.disconnect(block=block) for d in self._dispatcher_pool])
if block: if block:
await self._server.wait_closed() await self._server.wait_closed()
# if block and wait_tasks: # TODO wait for client workers # if block and wait_tasks: # TODO wait for client workers
@ -104,16 +130,8 @@ class MinecraftServer:
await dispatcher.write(PacketKickDisconnect(dispatcher.proto, reason="Connection terminated")) await dispatcher.write(PacketKickDisconnect(dispatcher.proto, reason="Connection terminated"))
async def _server_worker(self, reader:StreamReader, writer:StreamWriter): async def _server_worker(self, reader:StreamReader, writer:StreamWriter):
if not self._processing:
if not writer.is_closing() and writer.can_write_eof():
try:
writer.write_eof()
except OSError as e:
self._logger.error("Failed to write EOF to connecting client : %s", str(e))
writer.close()
return await writer.wait_closed()
dispatcher = Dispatcher(server=True) dispatcher = Dispatcher(server=True)
self._dispatcher_pool.append(dispatcher)
self._logger.debug("Starting dispatcher for client") self._logger.debug("Starting dispatcher for client")
await dispatcher.connect( await dispatcher.connect(
@ -189,45 +207,52 @@ class MinecraftServer:
async def _play(self, dispatcher:Dispatcher) -> bool: async def _play(self, dispatcher:Dispatcher) -> bool:
self._logger.info("Player connected") self._logger.info("Player connected")
await dispatcher.write( if self.options["spawn-player"]:
PacketLogin( await dispatcher.write(
dispatcher.proto, PacketLogin(
gameMode=3, dispatcher.proto,
isFlat=False, gameMode=3,
worldNames=b'', isFlat=False,
worldName='aiocraft', worldNames=b'',
previousGameMode=3, worldName='aiocraft',
entityId=1, previousGameMode=3,
isHardcore=False, entityId=1,
difficulty=0, isHardcore=False,
isDebug=True, difficulty=0,
enableRespawnScreen=False, isDebug=True,
maxPlayers=1, enableRespawnScreen=False,
dimension=1, maxPlayers=1,
levelType='aiocraft', dimension=1,
reducedDebugInfo=False, levelType='aiocraft',
hashedSeed=1234, reducedDebugInfo=False,
viewDistance=4 hashedSeed=1234,
viewDistance=4
)
) )
)
await dispatcher.write( await dispatcher.write(
PacketPosition( PacketPosition(
dispatcher.proto, dispatcher.proto,
dismountVehicle=True, dismountVehicle=True,
x=0, x=0,
y=120, y=120,
flags=0, flags=0,
yaw=0.0, yaw=0.0,
onGround=False, onGround=False,
teleportId=1, teleportId=1,
pitch=0.0, pitch=0.0,
z=0, z=0,
)
) )
)
await asyncio.gather(*[cb(dispatcher) for cb in self._connect_handlers])
async for packet in dispatcher.packets(): async for packet in dispatcher.packets():
for cb in self._packet_handlers:
asyncio.get_event_loop().create_task(cb(dispatcher, packet))
pass # TODO handle play pass # TODO handle play
await asyncio.gather(*[cb(dispatcher) for cb in self._disconnect_handlers])
return False return False