From 894af3981420c4b4df71a5879dc50c8e6179682a Mon Sep 17 00:00:00 2001 From: alemi Date: Thu, 30 Sep 2021 19:00:12 +0200 Subject: [PATCH] added initial types --- aiocraft/minecraft/protocol/types.py | 123 +++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 aiocraft/minecraft/protocol/types.py diff --git a/aiocraft/minecraft/protocol/types.py b/aiocraft/minecraft/protocol/types.py new file mode 100644 index 0000000..bd566af --- /dev/null +++ b/aiocraft/minecraft/protocol/types.py @@ -0,0 +1,123 @@ +import struct + +from typing import Any + +class Type(object): + _fmt : str + + @classmethod + def serialize(cls, data:Any) -> bytes: + return struct.pack(cls._fmt, data) + + @classmethod + def unserialize(cls, data:bytes) -> Any: + return struct.unpack(cls._fmt, data)[0] + +class Boolean(Type): + _fmt : str = ">?" + +class Byte(Type): + _fmt : str = ">b" + +class UnsignedByte(Type): + _fmt : str = ">B" + +class Short(Type): + _fmt : str = ">h" + +class UnsignedShort(Type): + _fmt : str = ">H" + +class Int(Type): + _fmt : str = ">i" + +class Long(Type): + _fmt : str = ">q" + +class Float(Type): + _fmt : str = ">f" + +class Double(Type): + _fmt : str = ">d" + +class VarInt(Type): + _maxBytes = 5 + @classmethod + def serialize(cls, data:int) -> bytes: + res : bytearray = bytearray() + count = 0 + while True: + if count >= cls._maxBytes: + break + buf = data >> (7*count) + val = (buf & 0b01111111) + if (buf & 0b0000000) != 0: + val |= 0b1000000 + res.extend(val.to_bytes(1, 'little')) + if (buf & 0b0000000) == 0: + break + count += 1 + return res + + @classmethod + def unserialize(cls, data:bytes) -> int: + numRead = 0 + result = 0 + pos = 0 + while True: + buf = data[0] + value = buf & 0b01111111 + result |= value << (7 * numRead) + numRead +=1 + if numRead > cls._maxBytes: + raise ValueError("VarInt is too big") + if buf & 0b10000000 == 0: + break + return result + +class VarLong(VarInt): + _maxBytes = 10 + +class String(Type): + @classmethod + def serialize(cls, data:str) -> bytes: + encoded = data.encode('utf-8') + return VarInt.serialize(len(encoded)) + struct.pack(f">{len(encoded)}s", encoded) + + @classmethod + def unserialize(cls, data:bytes) -> str: + length = VarInt.unserialize(data) + start_index = len(data) - length + return struct.unpack(f">{length}s", data[start_index:])[0] + +class Chat(String): + pass + +class Identifier(String): + pass + +class EntityMetadata(Type): + # TODO + pass + +class Slot(Type): + # TODO + pass + if buf & 0b10000000 == 0: + break + +class NBTTag(Type): + # TODO + pass + +class Position(Type): + # TODO + pass + +class Angle(Type): + # TODO + pass + +class UUID(Type): + # TODO + pass