chore: updated aiocraft

This commit is contained in:
əlemi 2023-11-20 17:52:49 +01:00
parent bd97b891f4
commit f9c97c0c34
Signed by: alemi
GPG key ID: A4895B84D311642C
16 changed files with 80 additions and 151 deletions

View file

@ -1,8 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import re
import sys
import asyncio
import logging import logging
import argparse import argparse
import inspect import inspect
@ -20,8 +17,8 @@ from .scaffold import ConfigObject
from .helpers import configure_logging from .helpers import configure_logging
def main(): def main():
root = Path(os.getcwd())
# TODO would be cool if it was possible to configure addons path, but we need to load addons before doing argparse so we can do helptext # TODO would be cool if it was possible to configure addons path, but we need to load addons before doing argparse so we can do helptext
#root = Path(os.getcwd())
#addon_path = Path(args.path) if args.addon_path else ( root/'addons' ) #addon_path = Path(args.path) if args.addon_path else ( root/'addons' )
addon_path = Path('addons') addon_path = Path('addons')
addons : Set[Type[Addon]] = set() addons : Set[Type[Addon]] = set()
@ -34,7 +31,7 @@ def main():
obj = getattr(m, obj_name) obj = getattr(m, obj_name)
if obj != Addon and inspect.isclass(obj) and issubclass(obj, Addon): if obj != Addon and inspect.isclass(obj) and issubclass(obj, Addon):
addons.add(obj) addons.add(obj)
except Exception as e: except Exception:
print(f"Exception importing addon {py_path}") print(f"Exception importing addon {py_path}")
traceback.print_exc() traceback.print_exc()
pass pass

View file

@ -1,4 +1,4 @@
from aiocraft.mc.definitions import BlockPos from aiocraft.types import BlockPos
from .base import BaseEvent from .base import BaseEvent

View file

@ -1,4 +1,4 @@
from aiocraft.mc.definitions import Player from aiocraft.types import Player
from .base import BaseEvent from .base import BaseEvent
class PlayerJoinEvent(BaseEvent): class PlayerJoinEvent(BaseEvent):

View file

@ -1,4 +1,4 @@
from aiocraft.mc.definitions import Dimension, Difficulty, Gamemode from aiocraft.types import Dimension, Difficulty, Gamemode
from .base import BaseEvent from .base import BaseEvent

View file

@ -1,4 +1,4 @@
from aiocraft.mc.packet import Packet from aiocraft.packet import Packet
from .base import BaseEvent from .base import BaseEvent

View file

@ -4,4 +4,3 @@ from .tablist import GameTablist
from .chat import GameChat from .chat import GameChat
from .world import GameWorld from .world import GameWorld
from .container import GameContainer from .container import GameContainer
from .position import GamePosition

View file

@ -1,9 +1,7 @@
from typing import Union from aiocraft.proto.play.clientbound import PacketChat as PacketChatMessage
from aiocraft.proto.play.serverbound import PacketChat
from aiocraft.mc.proto.play.clientbound import PacketChat as PacketChatMessage from ..events.chat import ChatEvent
from aiocraft.mc.proto.play.serverbound import PacketChat
from ..events.chat import ChatEvent, MessageType
from ..scaffold import Scaffold from ..scaffold import Scaffold
class GameChat(Scaffold): class GameChat(Scaffold):
@ -15,14 +13,11 @@ class GameChat(Scaffold):
async def chat_event_callback(packet:PacketChatMessage): async def chat_event_callback(packet:PacketChatMessage):
self.run_callbacks(ChatEvent, ChatEvent(packet.message)) self.run_callbacks(ChatEvent, ChatEvent(packet.message))
async def chat(self, message:str, whisper:str=None, wait:bool=False): async def chat(self, message:str, whisper:str="", wait:bool=False):
if whisper: if whisper:
message = f"/w {whisper} {message}" message = f"/w {whisper} {message}"
await self.dispatcher.write( await self.dispatcher.write(
PacketChat( PacketChat(message=message),
self.dispatcher.proto,
message=message
),
wait=wait wait=wait
) )

View file

@ -1,27 +1,22 @@
import asyncio from aiocraft.types import Item
import datetime from aiocraft.proto.play.clientbound import PacketTransaction
from typing import List, Optional from aiocraft.proto.play.serverbound import PacketTransaction as PacketTransactionServerbound
from aiocraft.proto import (
#from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import Item
from aiocraft.mc.proto.play.clientbound import PacketTransaction
from aiocraft.mc.proto.play.serverbound import PacketTransaction as PacketTransactionServerbound
from aiocraft.mc.proto import (
PacketOpenWindow, PacketCloseWindow, PacketSetSlot PacketOpenWindow, PacketCloseWindow, PacketSetSlot
) )
from ..events import JoinGameEvent, DeathEvent, ConnectedEvent, DisconnectedEvent from ..events import DisconnectedEvent
from ..scaffold import Scaffold from ..scaffold import Scaffold
class WindowContainer: class WindowContainer:
id: int id: int
title: str title: str
type: str type: str
entity_id: Optional[int] entity_id: int | None
transaction_id: int transaction_id: int
inventory: List[Optional[Item]] inventory: list[Item | None]
def __init__(self, id:int, title: str, type: str, entity_id:int = None, slot_count:int = 27): def __init__(self, id:int, title: str, type: str, entity_id:int | None = None, slot_count:int = 27):
self.id = id self.id = id
self.title = title self.title = title
self.type = type self.type = type
@ -37,7 +32,7 @@ class WindowContainer:
return self.transaction_id return self.transaction_id
class GameContainer(Scaffold): class GameContainer(Scaffold):
window: Optional[WindowContainer] window: WindowContainer | None
@property @property
def is_container_open(self) -> bool: def is_container_open(self) -> bool:
@ -85,7 +80,6 @@ class GameContainer(Scaffold):
if not packet.accepted: # apologize to server automatically if not packet.accepted: # apologize to server automatically
await self.dispatcher.write( await self.dispatcher.write(
PacketTransactionServerbound( PacketTransactionServerbound(
self.dispatcher.proto,
windowId=packet.windowId, windowId=packet.windowId,
action=packet.action, action=packet.action,
accepted=packet.accepted, accepted=packet.accepted,

View file

@ -1,8 +1,8 @@
from typing import List from typing import List
from aiocraft.mc.definitions import Item from aiocraft.types import Item
from aiocraft.mc.proto.play.clientbound import PacketSetSlot, PacketHeldItemSlot as PacketHeldItemChange from aiocraft.proto.play.clientbound import PacketSetSlot, PacketHeldItemSlot as PacketHeldItemChange
from aiocraft.mc.proto.play.serverbound import PacketHeldItemSlot from aiocraft.proto.play.serverbound import PacketHeldItemSlot
from ..scaffold import Scaffold from ..scaffold import Scaffold
@ -13,7 +13,7 @@ class GameInventory(Scaffold):
async def set_slot(self, slot:int): async def set_slot(self, slot:int):
self.slot = slot self.slot = slot
await self.dispatcher.write(PacketHeldItemSlot(self.dispatcher.proto, slotId=slot)) await self.dispatcher.write(PacketHeldItemSlot(slotId=slot))
@property @property
def hotbar(self) -> List[Item]: def hotbar(self) -> List[Item]:

View file

@ -1,53 +0,0 @@
from typing import Optional
from aiocraft.mc.definitions import BlockPos
from aiocraft.mc.proto import PacketPosition, PacketSetPassengers, PacketEntityTeleport, PacketTeleportConfirm
from ..scaffold import Scaffold
class GamePosition(Scaffold):
position : BlockPos
vehicle_id : Optional[int]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.position = BlockPos(0, 0, 0)
self.vehicle_id = None
@self.on_packet(PacketSetPassengers)
async def player_enters_vehicle_cb(packet:PacketSetPassengers):
if self.vehicle_id is None: # might get mounted on a vehicle
for entity_id in packet.passengers:
if entity_id == self.entity_id:
self.vehicle_id = packet.entityId
else: # might get dismounted from vehicle
if packet.entityId == self.vehicle_id:
if self.entity_id not in packet.passengers:
self.vehicle_id = None
@self.on_packet(PacketEntityTeleport)
async def entity_rubberband_cb(packet:PacketEntityTeleport):
if self.vehicle_id is None:
return
if self.vehicle_id != packet.entityId:
return
self.position = BlockPos(packet.x, packet.y, packet.z)
self.logger.info(
"Position synchronized : (x:%.0f,y:%.0f,z:%.0f) (vehicle)",
self.position.x, self.position.y, self.position.z
)
@self.on_packet(PacketPosition)
async def player_rubberband_cb(packet:PacketPosition):
self.position = BlockPos(packet.x, packet.y, packet.z)
self.logger.info(
"Position synchronized : (x:%.0f,y:%.0f,z:%.0f)",
self.position.x, self.position.y, self.position.z
)
await self.dispatcher.write(
PacketTeleportConfirm(
self.dispatcher.proto,
teleportId=packet.teleportId
)
)

View file

@ -3,8 +3,8 @@ import datetime
import json import json
#from aiocraft.client import MinecraftClient #from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import Gamemode, Dimension, Difficulty from aiocraft.types import Gamemode, Dimension, Difficulty
from aiocraft.mc.proto import ( from aiocraft.proto import (
PacketRespawn, PacketLogin, PacketUpdateHealth, PacketExperience, PacketSettings, PacketRespawn, PacketLogin, PacketUpdateHealth, PacketExperience, PacketSettings,
PacketClientCommand, PacketAbilities, PacketDifficulty PacketClientCommand, PacketAbilities, PacketDifficulty
) )
@ -58,7 +58,7 @@ class GameState(Scaffold):
async def on_player_respawning(packet:PacketRespawn): async def on_player_respawning(packet:PacketRespawn):
self.gamemode = Gamemode(packet.gamemode) self.gamemode = Gamemode(packet.gamemode)
if isinstance(packet.dimension, dict): if isinstance(packet.dimension, dict):
self.logger.info("Received dimension data: %s", json.dumps(packet.dimensionCodec, indent=2)) self.logger.info("Received dimension data: %s", json.dumps(packet.dimension, indent=2))
self.dimension = Dimension.from_str(packet.dimension['effects']) self.dimension = Dimension.from_str(packet.dimension['effects'])
else: else:
self.dimension = Dimension(packet.dimension) self.dimension = Dimension(packet.dimension)
@ -106,7 +106,6 @@ class GameState(Scaffold):
self.run_callbacks(JoinGameEvent, JoinGameEvent(self.dimension, self.difficulty, self.gamemode)) self.run_callbacks(JoinGameEvent, JoinGameEvent(self.dimension, self.difficulty, self.gamemode))
await self.dispatcher.write( await self.dispatcher.write(
PacketSettings( PacketSettings(
self.dispatcher.proto,
locale="en_US", locale="en_US",
viewDistance=4, viewDistance=4,
chatFlags=0, chatFlags=0,
@ -115,7 +114,7 @@ class GameState(Scaffold):
mainHand=0, mainHand=0,
) )
) )
await self.dispatcher.write(PacketClientCommand(self.dispatcher.proto, actionId=0)) await self.dispatcher.write(PacketClientCommand(actionId=0))
@self.on_packet(PacketUpdateHealth) @self.on_packet(PacketUpdateHealth)
async def player_hp_cb(packet:PacketUpdateHealth): async def player_hp_cb(packet:PacketUpdateHealth):
@ -132,7 +131,7 @@ class GameState(Scaffold):
self.logger.warning("Died, attempting to respawn") self.logger.warning("Died, attempting to respawn")
await asyncio.sleep(0.5) # TODO make configurable await asyncio.sleep(0.5) # TODO make configurable
await self.dispatcher.write( await self.dispatcher.write(
PacketClientCommand(self.dispatcher.proto, actionId=0) # respawn PacketClientCommand(actionId=0) # respawn
) )
@self.on_packet(PacketExperience) @self.on_packet(PacketExperience)

View file

@ -2,10 +2,9 @@ import uuid
import datetime import datetime
from enum import Enum from enum import Enum
from typing import Dict, List
from aiocraft.mc.definitions import Player from aiocraft.types import Player
from aiocraft.mc.proto import PacketPlayerInfo from aiocraft.proto import PacketPlayerInfo
from ..scaffold import Scaffold from ..scaffold import Scaffold
from ..events import ConnectedEvent, PlayerJoinEvent, PlayerLeaveEvent from ..events import ConnectedEvent, PlayerJoinEvent, PlayerLeaveEvent
@ -18,7 +17,7 @@ class ActionType(Enum): # TODO move this in aiocraft
REMOVE_PLAYER = 4 REMOVE_PLAYER = 4
class GameTablist(Scaffold): class GameTablist(Scaffold):
tablist : Dict[uuid.UUID, Player] tablist : dict[uuid.UUID, Player]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View file

@ -1,13 +1,13 @@
import json import json
from time import time from time import time
from aiocraft.mc.definitions import BlockPos from aiocraft.types import BlockPos
from aiocraft.mc.proto import ( from aiocraft.proto import (
PacketMapChunk, PacketBlockChange, PacketMultiBlockChange, PacketSetPassengers, PacketEntityTeleport, PacketMapChunk, PacketBlockChange, PacketMultiBlockChange, PacketSetPassengers, PacketEntityTeleport,
PacketSteerVehicle, PacketRelEntityMove, PacketTeleportConfirm PacketSteerVehicle, PacketRelEntityMove, PacketTeleportConfirm
) )
from aiocraft.mc.proto.play.clientbound import PacketPosition from aiocraft.proto.play.clientbound import PacketPosition
from aiocraft.mc.types import twos_comp from aiocraft.primitives import twos_comp
from aiocraft import Chunk, World # TODO these imports will hopefully change! from aiocraft import Chunk, World # TODO these imports will hopefully change!
@ -70,12 +70,7 @@ class GameWorld(Scaffold):
if time() - self._last_steer_vehicle >= 5: if time() - self._last_steer_vehicle >= 5:
self._last_steer_vehicle = time() self._last_steer_vehicle = time()
await self.dispatcher.write( await self.dispatcher.write(
PacketSteerVehicle( PacketSteerVehicle(forward=0, sideways=0, jump=0)
self.dispatcher.proto,
forward=0,
sideways=0,
jump=0
)
) )
@self.on_packet(PacketPosition) @self.on_packet(PacketPosition)
@ -86,10 +81,7 @@ class GameWorld(Scaffold):
self.position.x, self.position.y, self.position.z self.position.x, self.position.y, self.position.z
) )
await self.dispatcher.write( await self.dispatcher.write(
PacketTeleportConfirm( PacketTeleportConfirm(teleportId=packet.teleportId)
self.dispatcher.proto,
teleportId=packet.teleportId
)
) )
# Since this might require more resources, allow to disable it # Since this might require more resources, allow to disable it
@ -118,7 +110,7 @@ class GameWorld(Scaffold):
x_off = (entry['horizontalPos'] >> 4 ) & 15 x_off = (entry['horizontalPos'] >> 4 ) & 15
z_off = entry['horizontalPos'] & 15 z_off = entry['horizontalPos'] & 15
pos = BlockPos(x_off + chunk_x_off, entry['y'], z_off + chunk_z_off) pos = BlockPos(x_off + chunk_x_off, entry['y'], z_off + chunk_z_off)
self.world.put_block(pos.x,pos.y, pos.z, entry['blockId']) self.world.put_block(pos.i_x, pos.i_y, pos.i_z, entry['blockId'])
self.run_callbacks(BlockUpdateEvent, BlockUpdateEvent(pos, entry['blockId'])) self.run_callbacks(BlockUpdateEvent, BlockUpdateEvent(pos, entry['blockId']))
elif self.dispatcher.proto < 760: elif self.dispatcher.proto < 760:
x = twos_comp((packet.chunkCoordinates >> 42) & 0x3FFFFF, 22) x = twos_comp((packet.chunkCoordinates >> 42) & 0x3FFFFF, 22)
@ -130,7 +122,7 @@ class GameWorld(Scaffold):
dz = ((loc & 0x0FFF) >> 4 ) & 0x0F dz = ((loc & 0x0FFF) >> 4 ) & 0x0F
dy = ((loc & 0x0FFF) ) & 0x0F dy = ((loc & 0x0FFF) ) & 0x0F
pos = BlockPos(16*x + dx, 16*y + dy, 16*z + dz) pos = BlockPos(16*x + dx, 16*y + dy, 16*z + dz)
self.world.put_block(pos.x, pos.y, pos.z, state) self.world.put_block(pos.i_x, pos.i_y, pos.i_z, state)
self.run_callbacks(BlockUpdateEvent, BlockUpdateEvent(pos, state)) self.run_callbacks(BlockUpdateEvent, BlockUpdateEvent(pos, state))
else: else:
self.logger.error("Cannot process MultiBlockChange for protocol %d", self.dispatcher.proto) self.logger.error("Cannot process MultiBlockChange for protocol %d", self.dispatcher.proto)

View file

@ -2,13 +2,13 @@ from configparser import ConfigParser, SectionProxy
from typing import Type, Any from typing import Type, Any
from aiocraft.client import MinecraftClient from aiocraft.client import AbstractMinecraftClient
from aiocraft.util import helpers from aiocraft.util import helpers
from aiocraft.mc.packet import Packet from aiocraft.packet import Packet
from aiocraft.mc.definitions import ConnectionState from aiocraft.types import ConnectionState
from aiocraft.mc.proto import PacketKickDisconnect, PacketSetCompression from aiocraft.proto import PacketKickDisconnect, PacketSetCompression
from aiocraft.mc.proto.play.clientbound import PacketKeepAlive from aiocraft.proto.play.clientbound import PacketKeepAlive
from aiocraft.mc.proto.play.serverbound import PacketKeepAlive as PacketKeepAliveResponse from aiocraft.proto.play.serverbound import PacketKeepAlive as PacketKeepAliveResponse
from .traits import CallbacksHolder, Runnable from .traits import CallbacksHolder, Runnable
from .events import ConnectedEvent, DisconnectedEvent from .events import ConnectedEvent, DisconnectedEvent
@ -21,7 +21,7 @@ class ConfigObject:
class Scaffold( class Scaffold(
CallbacksHolder, CallbacksHolder,
Runnable, Runnable,
MinecraftClient, AbstractMinecraftClient,
): ):
entity_id : int entity_id : int
@ -43,16 +43,17 @@ class Scaffold(
#Override #Override
async def _play(self) -> bool: async def _play(self) -> bool:
self.dispatcher.set_state(ConnectionState.PLAY) assert self.dispatcher is not None
self.dispatcher.promote(ConnectionState.PLAY)
self.run_callbacks(ConnectedEvent, ConnectedEvent()) self.run_callbacks(ConnectedEvent, ConnectedEvent())
async for packet in self.dispatcher.packets(): async for packet in self.dispatcher.packets():
self.logger.debug("[ * ] Processing %s", packet.__class__.__name__) self.logger.debug("[ * ] Processing %s", packet.__class__.__name__)
if isinstance(packet, PacketSetCompression): if isinstance(packet, PacketSetCompression):
self.logger.info("Compression updated") self.logger.info("Compression updated")
self.dispatcher.set_compression(packet.threshold) self.dispatcher.update_compression_threshold(packet.threshold)
elif isinstance(packet, PacketKeepAlive): elif isinstance(packet, PacketKeepAlive):
if self.cfg.getboolean("send_keep_alive", fallback=True): if self.cfg.getboolean("send_keep_alive", fallback=True):
keep_alive_packet = PacketKeepAliveResponse(self.dispatcher._proto, keepAliveId=packet.keepAliveId) keep_alive_packet = PacketKeepAliveResponse(keepAliveId=packet.keepAliveId)
await self.dispatcher.write(keep_alive_packet) await self.dispatcher.write(keep_alive_packet)
elif isinstance(packet, PacketKickDisconnect): elif isinstance(packet, PacketKickDisconnect):
self.logger.error("Kicked while in game : %s", helpers.parse_chat(packet.reason)) self.logger.error("Kicked while in game : %s", helpers.parse_chat(packet.reason))

View file

@ -5,8 +5,6 @@ import logging
from inspect import isclass from inspect import isclass
from typing import Dict, List, Set, Any, Callable, Type from typing import Dict, List, Set, Any, Callable, Type
from ..events.base import BaseEvent
class CallbacksHolder: class CallbacksHolder:
_callbacks : Dict[Any, List[Callable]] _callbacks : Dict[Any, List[Callable]]
@ -17,7 +15,7 @@ class CallbacksHolder:
self._callbacks = {} self._callbacks = {}
self._tasks = {} self._tasks = {}
def callback_keys(self, filter:Type = None) -> Set[Any]: def callback_keys(self, filter:Type | None = None) -> Set[Any]:
return set(x for x in self._callbacks.keys() if not filter or (isclass(x) and issubclass(x, filter))) return set(x for x in self._callbacks.keys() if not filter or (isclass(x) and issubclass(x, filter)))
def register(self, key:Any, callback:Callable): def register(self, key:Any, callback:Callable):

View file

@ -4,18 +4,18 @@ import asyncio
import datetime import datetime
import pkg_resources import pkg_resources
from typing import List, Dict, Any, Type, Optional from typing import Any, Type
from time import time from time import time
from configparser import ConfigParser from configparser import ConfigParser
from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.asyncio import AsyncIOScheduler
from aiocraft.mc.packet import Packet from aiocraft.packet import Packet
from aiocraft.mc.auth import AuthInterface, AuthException, MojangAuthenticator, MicrosoftAuthenticator, OfflineAuthenticator from aiocraft.auth import AuthInterface, AuthException, MojangAuthenticator, MicrosoftAuthenticator, OfflineAuthenticator
from aiocraft.mc.auth.microsoft import InvalidStateError from aiocraft.auth.microsoft import InvalidStateError
from .storage import StorageDriver, SystemState, AuthenticatorState from .storage import StorageDriver, SystemState, AuthenticatorState
from .game import GameState, GameChat, GameInventory, GameTablist, GameWorld, GameContainer, GamePosition from .game import GameState, GameChat, GameInventory, GameTablist, GameWorld, GameContainer
from .addon import Addon from .addon import Addon
from .notifier import Notifier, Provider from .notifier import Notifier, Provider
@ -42,10 +42,13 @@ class Treepuncher(
notifier: Notifier notifier: Notifier
scheduler: AsyncIOScheduler scheduler: AsyncIOScheduler
modules: List[Addon] modules: list[Addon]
ctx: Dict[Any, Any] ctx: dict[Any, Any]
_processing: bool _processing: bool
_proto_override: int
_host: str
_port: int
def __init__( def __init__(
self, self,
@ -61,7 +64,7 @@ class Treepuncher(
authenticator : AuthInterface authenticator : AuthInterface
def opt(k:str, required=False, default=None, t:type=str) -> Optional[Any]: def opt(k, required=False, default=None, t=str):
v = kwargs.get(k) v = kwargs.get(k)
if v is None: if v is None:
v = self.cfg.get(k) v = self.cfg.get(k)
@ -95,13 +98,19 @@ class Treepuncher(
) )
super().__init__( super().__init__(
opt('server', required=True),
authenticator=authenticator, authenticator=authenticator,
online_mode=opt('online_mode', default=True, t=bool), online_mode=opt('online_mode', default=True, t=bool),
force_port=opt('force_port', default=0, t=int),
resolve_srv=opt('resolve_srv', default=True, t=bool),
) )
self._proto_override = opt('force_proto', t=int)
self._host = opt('server', required=True)
if ":" in self._host:
h, p = self._host.split(":", 1)
self._host = h
self._port = int(p)
else:
self._host, self._port = self.resolve_srv(self._host)
self.storage = StorageDriver(opt('session_file') or f"data/{name}.session") # TODO wrap with pathlib self.storage = StorageDriver(opt('session_file') or f"data/{name}.session") # TODO wrap with pathlib
self.notifier = Notifier(self) self.notifier = Notifier(self)
@ -199,22 +208,21 @@ class Treepuncher(
async def _work(self): async def _work(self):
self.logger.debug("Worker started") self.logger.debug("Worker started")
try: try:
if "force_proto" in self.cfg: log_ignored_packets = self.cfg.getboolean('log_ignored_packets', fallback=False)
self.dispatcher.set_proto(self.cfg.getint('force_proto')) whitelist = self.callback_keys(filter=Packet)
if self._proto_override:
proto = self._proto_override
else: else:
try: try:
server_data = await self.info() server_data = await self.info(self._host, self._port, whitelist=whitelist, log_ignored_packets=log_ignored_packets)
if "version" in server_data and "protocol" in server_data["version"]: if "version" in server_data and "protocol" in server_data["version"]:
self.dispatcher.set_proto(server_data['version']['protocol']) proto = server_data['version']['protocol']
except OSError as e: except OSError as e:
self.logger.error("Connection error : %s", str(e)) self.logger.error("Connection error : %s", str(e))
self.dispatcher.whitelist(self.callback_keys(filter=Packet))
self.dispatcher.log_ignored_packets(self.cfg.getboolean('log_ignored_packets', fallback=False))
while self._processing: while self._processing:
try: try:
await self.join() await self.join(self._host, self._port, proto, whitelist=whitelist, log_ignored_packets=log_ignored_packets)
except OSError as e: except OSError as e:
self.logger.error("Connection error : %s", str(e)) self.logger.error("Connection error : %s", str(e))