brought features out of aiocraft, added game managers

This commit is contained in:
əlemi 2022-03-08 01:38:14 +01:00
parent b41f2f6074
commit 88bfadd8cd
No known key found for this signature in database
GPG key ID: BBCBFE5D7244634E
7 changed files with 77 additions and 50 deletions

View file

@ -1,3 +1,4 @@
from .chat import ChatEvent
from .join_game import JoinGameEvent
from .death import DeathEvent
from .system import ConnectedEvent, DisconnectedEvent

View file

@ -1,25 +1,19 @@
from typing import Union
from aiocraft.client import MinecraftClient
from aiocraft.mc.proto.play.clientbound import PacketChat as PacketChatMessage
from aiocraft.mc.proto.play.serverbound import PacketChat
from ..events.chat import ChatEvent, MessageType
from ..scaffold import Scaffold
class GameChat(MinecraftClient):
class GameChat(Scaffold):
def on_chat(self, msg_type:Union[str, MessageType] = None):
if isinstance(msg_type, str):
msg_type = MessageType(msg_type)
def wrapper(fun):
async def process_chat_packet(packet:PacketChatMessage):
msg = ChatEvent(packet.message)
if not msg_type or msg.type == msg_type:
return await fun(msg)
self.register(PacketChatMessage, process_chat_packet)
return fun
return wrapper
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@self.on_packet(PacketChatMessage)
async def chat_event_callback(packet:PacketChatMessage):
self.run_callbacks(ChatEvent, ChatEvent(packet.message))
async def chat(self, message:str, whisper:str=None, wait:bool=False):
if whisper:
@ -32,5 +26,3 @@ class GameChat(MinecraftClient):
wait=wait
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View file

@ -1,11 +1,12 @@
from typing import List
from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import Item
from aiocraft.mc.proto.play.clientbound import PacketSetSlot, PacketHeldItemSlot as PacketHeldItemChange
from aiocraft.mc.proto.play.serverbound import PacketHeldItemSlot
class GameInventory(MinecraftClient):
from ..scaffold import Scaffold
class GameInventory(Scaffold):
slot : int
inventory : List[Item]
# TODO inventory

View file

@ -2,13 +2,14 @@ import asyncio
import datetime
import functools
from aiocraft.client import MinecraftClient
#from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import Gamemode, Dimension, Difficulty
from aiocraft.mc.proto import PacketRespawn, PacketLogin, PacketUpdateHealth, PacketExperience, PacketSettings, PacketClientCommand
from ..events import JoinGameEvent, DeathEvent
from ..events import JoinGameEvent, DeathEvent, ConnectedEvent, DisconnectedEvent
from ..scaffold import Scaffold
class GameState(MinecraftClient):
class GameState(Scaffold):
hp : float
food : float
xp : float
@ -26,24 +27,6 @@ class GameState(MinecraftClient):
difficulty : Difficulty
join_time : datetime.datetime
def on_death(self):
def decorator(fun):
@functools.wraps(fun)
async def wrapper():
event = DeathEvent()
return await fun(event)
return self.register(DeathEvent.SENTINEL, wrapper)
return decorator
def on_joined_world(self):
def decorator(fun):
@functools.wraps(fun)
async def wrapper():
event = JoinGameEvent()
return await fun(event)
return self.register(JoinGameEvent.SENTINEL, wrapper)
return decorator
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -58,8 +41,8 @@ class GameState(MinecraftClient):
self.xp = 0.0
self.lvl = 0
@self.on_disconnected()
async def disconnected_cb():
@self.on(DisconnectedEvent)
async def disconnected_cb(_):
self.in_game = False
@self.on_packet(PacketRespawn)

View file

@ -3,11 +3,13 @@ import datetime
from typing import Dict, List
from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import Item
from aiocraft.mc.proto import PacketPlayerInfo
class GameTablist(MinecraftClient):
from ..scaffold import Scaffold
from ..events import ConnectedEvent
class GameTablist(Scaffold):
tablist : Dict[uuid.UUID, dict]
def __init__(self, *args, **kwargs):
@ -15,8 +17,8 @@ class GameTablist(MinecraftClient):
self.tablist = {}
@self.on_connected()
async def connected_cb():
@self.on(ConnectedEvent)
async def connected_cb(_):
self.tablist.clear()
@self.on_packet(PacketPlayerInfo)

View file

@ -3,11 +3,13 @@ import datetime
from typing import Dict, List
from aiocraft.client import MinecraftClient
from aiocraft.mc.definitions import BlockPos
from aiocraft.mc.proto import PacketPosition, PacketTeleportConfirm
class GameWorld(MinecraftClient):
from ..scaffold import Scaffold
from ..events import ConnectedEvent
class GameWorld(Scaffold):
position : BlockPos
# TODO world
@ -16,8 +18,8 @@ class GameWorld(MinecraftClient):
self.position = BlockPos(0, 0, 0)
@self.on_connected()
async def connected_cb():
@self.on(ConnectedEvent)
async def connected_cb(_):
self.tablist.clear()
@self.on_packet(PacketPosition)

View file

@ -14,11 +14,19 @@ from configparser import ConfigParser
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from aiocraft.client import MinecraftClient
from aiocraft.util import helpers
from aiocraft.mc.packet import Packet
from aiocraft.mc.definitions import ConnectionState
from aiocraft.mc.proto import PacketSetCompression, PacketKickDisconnect
from aiocraft.mc.proto.play.clientbound import PacketKeepAlive
from aiocraft.mc.proto.play.serverbound import PacketKeepAlive as PacketKeepAliveResponse
from .scaffold import Scaffold
from .events import ConnectedEvent, DisconnectedEvent
from .storage import Storage, SystemState
from .notifier import Notifier
from .game import GameState, GameChat, GameInventory, GameTablist, GameWorld
from .traits import CallbacksHolder, Runnable
REMOVE_COLOR_FORMATS = re.compile(r"§[0-9a-z]")
@ -87,6 +95,8 @@ class Treepuncher(
modules : List[Addon]
ctx : Dict[Any, Any]
_processing : bool
def __init__(self, name:str, *args, config_file:str=None, notifier:Notifier=None, **kwargs):
super().__init__(*args, **kwargs)
self.ctx = dict()
@ -133,19 +143,55 @@ class Treepuncher(
self.storage._set_state(state)
async def start(self):
# if self.started: # TODO readd check
# return
await super().start()
await self.notifier.initialize()
for m in self.modules:
await m.initialize()
await super().start()
self._processing = True
self._worker = asyncio.get_event_loop().create_task(self._work())
self.scheduler.resume()
self._logger.info("Treepuncher started")
async def stop(self, force:bool=False):
self._processing = False
self.scheduler.pause()
await super().stop(force=force)
if self.dispatcher.connected:
await self.dispatcher.disconnect(block=not force)
if not force:
await self._worker
await self.join_callbacks()
for m in self.modules:
await m.cleanup()
await self.notifier.cleanup()
await super().stop()
self._logger.info("Treepuncher stopped")
def install(self, module:Type[Addon]) -> Type[Addon]:
self.modules.append(module(self))
return module
async def _work(self):
try:
server_data = await self.info(host=self.host, port=self.port)
except Exception:
return self._logger.exception("exception while pinging server")
while self._processing:
try:
await self.join(
host=self.host,
port=self.port,
proto=server_data['version']['protocol'],
packet_whitelist=self.callback_keys(filter=Packet),
)
except ConnectionRefusedError:
self._logger.error("Server rejected connection")
except OSError as e:
self._logger.error("Connection error : %s", str(e))
except Exception:
self._logger.exception("Unhandled exception")
break
await asyncio.sleep(5) # TODO setting
if self._processing:
await self.stop(force=True)