chore: updated aiocraft
This commit is contained in:
parent
bd97b891f4
commit
f9c97c0c34
16 changed files with 80 additions and 151 deletions
|
@ -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
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from aiocraft.mc.definitions import BlockPos
|
from aiocraft.types import BlockPos
|
||||||
|
|
||||||
from .base import BaseEvent
|
from .base import BaseEvent
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from aiocraft.mc.packet import Packet
|
from aiocraft.packet import Packet
|
||||||
|
|
||||||
from .base import BaseEvent
|
from .base import BaseEvent
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
|
@ -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
|
|
||||||
)
|
|
||||||
)
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue