diff --git a/minecraft/networking/packets/clientbound/play/face_player_packet.py b/minecraft/networking/packets/clientbound/play/face_player_packet.py index a9a9abf..39b76ec 100644 --- a/minecraft/networking/packets/clientbound/play/face_player_packet.py +++ b/minecraft/networking/packets/clientbound/play/face_player_packet.py @@ -1,5 +1,5 @@ from minecraft.networking.types import ( - VarInt, Double, Boolean, OriginPoint + VarInt, Double, Boolean, OriginPoint, Vector, multi_attribute_alias ) from minecraft.networking.packets import Packet @@ -15,6 +15,9 @@ class FacePlayerPacket(Packet): packet_name = 'face player' + # Access the 'x', 'y', 'z' fields as a Vector. + target = multi_attribute_alias(Vector, 'x', 'y', 'z') + def read(self, file_object): if self.context.protocol_version >= 353: self.origin = VarInt.read(file_object) @@ -27,6 +30,8 @@ class FacePlayerPacket(Packet): # this packet should be treated as if is_entity was false. self.entity_id = VarInt.read(file_object) self.entity_origin = VarInt.read(file_object) + else: + self.entity_id = None else: # Protocol version 352 is_entity = Boolean.read(file_object) @@ -42,12 +47,15 @@ class FacePlayerPacket(Packet): Double.send(self.x, packet_buffer) Double.send(self.y, packet_buffer) Double.send(self.z, packet_buffer) - if self.entity_id: + if self.entity_id is not None: + Boolean.send(True, packet_buffer) VarInt.send(self.entity_id, packet_buffer) VarInt.send(self.entity_origin, packet_buffer) + else: + Boolean.send(False, packet_buffer) else: # Protocol version 352 - if self.entity_id: + if self.entity_id is not None: Boolean.send(True, packet_buffer) VarInt.send(self.entity_id, packet_buffer) else: @@ -56,5 +64,6 @@ class FacePlayerPacket(Packet): Double.send(self.y, packet_buffer) Double.send(self.z, packet_buffer) - # FacePlayerPacket.OriginPoint is an alias for OriginPoint - OriginPoint = OriginPoint + # These aliases declare the Enum type corresponding to each field: + Origin = OriginPoint + EntityOrigin = OriginPoint diff --git a/tests/test_packets.py b/tests/test_packets.py index 045cda8..3db2fb2 100644 --- a/tests/test_packets.py +++ b/tests/test_packets.py @@ -9,7 +9,7 @@ from random import choice from minecraft import SUPPORTED_PROTOCOL_VERSIONS, RELEASE_PROTOCOL_VERSIONS from minecraft.networking.connection import ConnectionContext from minecraft.networking.types import ( - VarInt, Enum, Vector, PositionAndLook + VarInt, Enum, Vector, PositionAndLook, OriginPoint, ) from minecraft.networking.packets import ( Packet, PacketBuffer, PacketListener, KeepAlivePacket, serverbound, @@ -199,8 +199,8 @@ class TestReadWritePackets(unittest.TestCase): 'type_id', context) pos_look = PositionAndLook( - position=(Vector(68.0, 38.0, 76.0) if context.protocol_version - >= 100 else Vector(68, 38, 76)), + position=(Vector(68.0, 38.0, 76.0) if protocol_version >= 100 + else Vector(68, 38, 76)), yaw=263.494, pitch=180) velocity = Vector(21, 55, 41) entity_id, type_name, type_id = 49846, 'EGG', EntityType.EGG @@ -212,7 +212,7 @@ class TestReadWritePackets(unittest.TestCase): velocity_x=velocity.x, velocity_y=velocity.y, velocity_z=velocity.z, entity_id=entity_id, type_id=type_id, data=1) - if context.protocol_version >= 49: + if protocol_version >= 49: object_uuid = 'd9568851-85bc-4a10-8d6a-261d130626fa' packet.object_uuid = object_uuid self.assertEqual(packet.objectUUID, object_uuid) @@ -225,7 +225,7 @@ class TestReadWritePackets(unittest.TestCase): context=context, position_and_look=pos_look, velocity=velocity, type=type_name, entity_id=entity_id, data=1) - if context.protocol_version >= 49: + if protocol_version >= 49: packet2.object_uuid = object_uuid self.assertEqual(packet.__dict__, packet2.__dict__) @@ -233,7 +233,7 @@ class TestReadWritePackets(unittest.TestCase): self.assertEqual(packet.position, packet2.position) packet2.data = 0 - if context.protocol_version < 49: + if protocol_version < 49: del packet2.velocity self._test_read_write_packet(packet, context, yaw=360/256, pitch=360/256) @@ -247,7 +247,7 @@ class TestReadWritePackets(unittest.TestCase): packet = clientbound.play.SoundEffectPacket( sound_id=545, effect_position=Vector(0.125, 300.0, 50.5), volume=0.75) - if context.protocol_version >= 201: + if protocol_version >= 201: packet.pitch = struct.unpack('f', struct.pack('f', 1.5))[0] else: packet.pitch = int(1.5 / 63.5) * 63.5 @@ -256,6 +256,24 @@ class TestReadWritePackets(unittest.TestCase): clientbound.play.SoundEffectPacket.SoundCategory.NEUTRAL self._test_read_write_packet(packet, context) + def test_face_player_packet(self): + for protocol_version in TEST_VERSIONS: + context = ConnectionContext(protocol_version=protocol_version) + + packet = clientbound.play.FacePlayerPacket() + packet.target = 1.0, -2.0, 3.5 + packet.entity_id = None + if protocol_version >= 353: + packet.origin = OriginPoint.EYES + self._test_read_write_packet(packet, context) + + packet.entity_id = 123 + if protocol_version >= 353: + packet.entity_origin = OriginPoint.FEET + else: + del packet.target + self._test_read_write_packet(packet, context) + def _test_read_write_packet(self, packet_in, context=None, **kwargs): """ If kwargs are specified, the key will be tested against the diff --git a/tests/test_serialization.py b/tests/test_serialization.py index b991913..6c1ae70 100644 --- a/tests/test_serialization.py +++ b/tests/test_serialization.py @@ -1,9 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import division + import unittest + from minecraft.networking.types import ( - Type, Boolean, UnsignedByte, Byte, Short, UnsignedShort, - Integer, FixedPointInteger, Angle, VarInt, Long, Float, Double, + Type, Boolean, UnsignedByte, Byte, Short, UnsignedShort, Integer, + FixedPointInteger, Angle, VarInt, Long, Float, Double, Angle, ShortPrefixedByteArray, VarIntPrefixedByteArray, UUID, String as StringType, Position, TrailingByteArray, UnsignedLong, ) @@ -36,6 +39,8 @@ TEST_DATA = { UUID: ["12345678-1234-5678-1234-567812345678"], StringType: ["hello world"], Position: [(758, 0, 691), (-500, -12, -684)], + Angle: {0.0:0.0, 1/256:1/256, 255/256:255/256, 360.0:0.0, -90.0:270.0, + -1890.0:270.0, 1890.0:90.0}, } @@ -47,26 +52,30 @@ class SerializationTest(unittest.TestCase): for data_type in Type.__subclasses__(): if data_type in TEST_DATA: test_cases = TEST_DATA[data_type] + test_cases = test_cases.items() \ + if isinstance(test_cases, dict) else \ + map(lambda x: (x, x), test_cases) - for test_data in test_cases: + for write_data, expected_read_data in test_cases: packet_buffer = PacketBuffer() data_type.send_with_context( - test_data, packet_buffer, context) + write_data, packet_buffer, context) packet_buffer.reset_cursor() deserialized = data_type.read_with_context( packet_buffer, context) if data_type is FixedPointInteger: self.assertAlmostEqual( - test_data, deserialized, delta=1.0/32.0) + expected_read_data, deserialized, delta=1/32) elif data_type is Angle: - self.assertAlmostEqual(test_data % 360, + self.assertAlmostEqual(expected_read_data % 360, deserialized, delta=360/256) elif data_type is Float or data_type is Double: - self.assertAlmostEqual(test_data, deserialized, 3) + self.assertAlmostEqual( + expected_read_data, deserialized, 3) else: - self.assertEqual(test_data, deserialized) + self.assertEqual(expected_read_data, deserialized) def test_exceptions(self): base_type = Type()