fix for fixed len arrays

This commit is contained in:
əlemi 2021-12-10 13:03:48 +01:00
parent eab07320b5
commit 7e24764df5
3 changed files with 16 additions and 14 deletions

View file

@ -17,8 +17,6 @@ from .util import encryption
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
DIFFICULT_PACKETS = (28, 36, 77) # Explosion, Map, Advancements
class InvalidState(Exception): class InvalidState(Exception):
pass pass
@ -217,8 +215,6 @@ class Dispatcher:
buffer = io.BytesIO(decompressed_data) buffer = io.BytesIO(decompressed_data)
packet_id = VarInt.read(buffer) packet_id = VarInt.read(buffer)
if packet_id in DIFFICULT_PACKETS:
continue # don't try to parse, can't handle types this complex (yet! TODO)
cls = self._packet_type_from_registry(packet_id) cls = self._packet_type_from_registry(packet_id)
self._logger.debug("Deserializing packet %s | %s", str(cls), cls._state) self._logger.debug("Deserializing packet %s | %s", str(cls), cls._state)
packet = cls.deserialize(self.proto, buffer) packet = cls.deserialize(self.proto, buffer)

View file

@ -3,7 +3,7 @@ import struct
import asyncio import asyncio
import uuid import uuid
from typing import List, Tuple, Dict, Any, Optional, Type as Class from typing import List, Tuple, Dict, Any, Union, Optional, Type as Class
class Type(object): class Type(object):
pytype : type pytype : type
@ -109,7 +109,7 @@ class VarLenPrimitive(Type):
def deserialize(self, data:bytes) -> int: def deserialize(self, data:bytes) -> int:
buf = io.BytesIO(data) buf = io.BytesIO(data)
return self.read(buf, ctx=ctx) return self.read(buf)
VarInt = VarLenPrimitive(5) VarInt = VarLenPrimitive(5)
VarLong = VarLenPrimitive(10) VarLong = VarLenPrimitive(10)
@ -181,20 +181,23 @@ UUID = UUIDType()
class ArrayType(Type): class ArrayType(Type):
pytype : type = list pytype : type = list
counter : Type counter : Union[int, Type]
content : Type content : Type
def __init__(self, content:Type, counter:Type = VarInt): def __init__(self, content:Type, counter:Union[int, Type] = VarInt):
self.content = content self.content = content
self.counter = counter self.counter = counter
def write(self, data:List[Any], buffer:io.BytesIO, ctx:object=None): def write(self, data:List[Any], buffer:io.BytesIO, ctx:object=None):
if isinstance(self.counter, Type):
self.counter.write(len(data), buffer, ctx=ctx) self.counter.write(len(data), buffer, ctx=ctx)
for el in data: for i, el in enumerate(data):
self.content.write(el, buffer, ctx=ctx) self.content.write(el, buffer, ctx=ctx)
if isinstance(self.counter, int) and i >= self.counter:
break # jank but should do
def read(self, buffer:io.BytesIO, ctx:object=None) -> List[Any]: def read(self, buffer:io.BytesIO, ctx:object=None) -> List[Any]:
length = self.counter.read(buffer, ctx=ctx) length = self.counter if isinstance(self.counter, int) else self.counter.read(buffer, ctx=ctx)
return [ self.content.read(buffer, ctx=ctx) for _ in range(length) ] return [ self.content.read(buffer, ctx=ctx) for _ in range(length) ]
class OptionalType(Type): class OptionalType(Type):
@ -230,13 +233,13 @@ class SwitchType(Type):
elif self.default: elif self.default:
return self.default.write(data, buffer, ctx=ctx) return self.default.write(data, buffer, ctx=ctx)
def read(self, buffer:io.BytesIO, ctx:object=None) -> Dict[str, Any]: def read(self, buffer:io.BytesIO, ctx:object=None) -> Optional[Any]:
watched = getattr(ctx, self.field) watched = getattr(ctx, self.field)
if watched in self.mappings: if watched in self.mappings:
return self.mappings[watched].read(buffer, ctx=ctx) return self.mappings[watched].read(buffer, ctx=ctx)
elif self.default: elif self.default:
return self.default.read(buffer, ctx=ctx) return self.default.read(buffer, ctx=ctx)
return {} return None
class StructType(Type): class StructType(Type):
pytype : type = dict pytype : type = dict

View file

@ -123,7 +123,10 @@ def mctype(slot_type:Any) -> Ref:
return Ref('IntegerByteArray') return Ref('IntegerByteArray')
return Ref('ByteArray') return Ref('ByteArray')
elif t == "array": # Generic array elif t == "array": # Generic array
return Ref('ArrayType', mctype(v["type"]), (mctype(v["countType"]) if "countType" in v else Ref('VarInt'))) return Ref('ArrayType',
mctype(v["type"]),
(v["count"] if "count" in v else mctype(v["countType"]) if "countType" in v else Ref('VarInt'))
)
elif t == "container": # Struct elif t == "container": # Struct
return Ref('StructType', Ref(", ".join(format_tuple((p["name"], mctype(p["type"]))) for p in v if "name" in p))) # some fields are anonymous??? return Ref('StructType', Ref(", ".join(format_tuple((p["name"], mctype(p["type"]))) for p in v if "name" in p))) # some fields are anonymous???
elif t == "option": # Optional elif t == "option": # Optional