From 43f4eb3517baa936b1bd2195d7d25fab8077b9e1 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Wed, 23 Sep 2020 00:00:28 -0600 Subject: [PATCH] Handle entity metadata --- game.py | 16 +++++++++++++++- monkey_patch.py | 1 + protocol/packets.py | 25 +++++++++++++++++++++++-- protocol/types.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/game.py b/game.py index b114d93..72a7538 100644 --- a/game.py +++ b/game.py @@ -10,7 +10,7 @@ from panda3d.core import LPoint3f from minecraft.networking.packets import Packet, clientbound, serverbound from minecraft.networking.types import BlockFace -from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket, OpenWindowPacket, ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket, ClientWindowConfirmationPacket +from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket, HeldItemChangePacket, PickItemPacket, OpenWindowPacket, ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket, ClientWindowConfirmationPacket, EntityMetadataPacket from protocol.types import Slot import utils @@ -188,6 +188,10 @@ class Game: register(self.handle_break_ack, AcknowledgePlayerDiggingPacket) register(self.handle_window, OpenWindowPacket) register(self.handle_window_confirmation, ClientWindowConfirmationPacket) + register(self.handle_spawn_object, clientbound.play.SpawnObjectPacket) + register(self.handle_entity_metadata, EntityMetadataPacket) + + #register(self.handle_packet, Packet, early=True) self.g.chat.set_handler(self.handle_chat) @@ -492,6 +496,16 @@ class Game: packet2.accepted = packet.accepted self.g.connection.write_packet(packet2) + def handle_spawn_object(self, packet): + print(packet) + print(packet.type_id) + + def handle_entity_metadata(self, packet): + print(packet) + + def handle_packet(self, packet): + print(packet) + def tick(self): if self.g.breaking: self.animate() diff --git a/monkey_patch.py b/monkey_patch.py index c4eaf81..0ecf959 100644 --- a/monkey_patch.py +++ b/monkey_patch.py @@ -20,6 +20,7 @@ def get_packets(old_get_packets): mc_packets.add(packets.ClickWindowPacket) mc_packets.add(packets.ClientWindowConfirmationPacket) mc_packets.add(packets.ServerWindowConfirmationPacket) + mc_packets.add(packets.EntityMetadataPacket) return mc_packets return lambda x: wrapper(old_get_packets, x) diff --git a/protocol/packets.py b/protocol/packets.py index f2f5ce9..bcc65d0 100644 --- a/protocol/packets.py +++ b/protocol/packets.py @@ -4,10 +4,11 @@ from minecraft.networking.packets import Packet, PacketBuffer from minecraft.networking.types import ( VarInt, Integer, UnsignedByte, Position, Vector, MutableRecord, attribute_alias, multi_attribute_alias, Long, Boolean, VarLong, - Short, UnsignedLong, Byte, BlockFace, String + Short, UnsignedLong, Byte, BlockFace, String, UUID, Angle, Double, + Float, ) -from protocol.types import Nbt, Slot +from protocol.types import Nbt, Slot, Entry class ChunkDataPacket(Packet): @@ -286,3 +287,23 @@ class ServerWindowConfirmationPacket(Packet): {'action_number': Short}, {'accepted': Boolean}, ] + + +class EntityMetadataPacket(Packet): + # Updates one or more metadata properties for an existing entity + # https://wiki.vg/Protocol#Entity_Metadata + + id = 0x44 + packet_name = 'entity metadata' + fields = 'entity_id', 'metadata' + + class Entry: + __slots__ = 'index', 'type', 'value' + + def read(self, file_object): + self.entity_id = VarInt.read(file_object) + self.metadata = [] + for _ in range(99): + entry = Entry.read(file_object) + if not entry: break + self.metadata.append(entry) diff --git a/protocol/types.py b/protocol/types.py index fd2de9e..861ff5f 100644 --- a/protocol/types.py +++ b/protocol/types.py @@ -4,7 +4,8 @@ import struct from minecraft.networking.types.basic import ( Type, Byte, Short, Integer, Long, Float, Double, - ShortPrefixedByteArray, Boolean, VarInt, TrailingByteArray + ShortPrefixedByteArray, Boolean, VarInt, TrailingByteArray, + Position, String, UnsignedByte ) from minecraft.networking.types.utility import Vector @@ -39,6 +40,8 @@ class Nbt(Type): @staticmethod def read(file_object): type_id = Byte.read(file_object) + if type_id == TAG_End: + return None if type_id != TAG_Compound: raise Exception("Invalid NBT header") name = ShortPrefixedByteArray.read(file_object).decode('utf-8') @@ -118,7 +121,8 @@ class Slot(Type): present = Boolean.read(file_object) item_id = VarInt.read(file_object) if present else None item_count = Byte.read(file_object) if present else None - nbt = TrailingByteArray.read(file_object) if present else None + print('slot read', present, item_id, item_count) + nbt = Nbt.read(file_object) if present else None return Slot(present, item_id, item_count, nbt) @staticmethod @@ -127,3 +131,37 @@ class Slot(Type): VarInt.send(value.item_id, socket) Byte.send(value.item_count, socket) TrailingByteArray.send(value.nbt, socket) + + +class Entry(Type): + types = { + 0: Byte, + 1: VarInt, + 2: Float, + 3: String, + 6: Slot, + 7: Boolean, + 9: Position, + } + + def __init__(self, index, type, value): + self.index = index + self.type = type + self.value = value + + def __str__(self): + return str(self.__dict__) + def __repr__(self): + return 'Entry(index={}, type={}, value={}'.format( + self.index, self.type, self.value) + + @staticmethod + def read(file_object): + index = UnsignedByte.read(file_object) + if index == 0xff: return None + type = VarInt.read(file_object) + try: + value = Entry.types[type].read(file_object) + except KeyError: + return None + return Entry(index, type, value)