From eae6e5c9cd9a13f3be9d7f9b270f9d87374ee382 Mon Sep 17 00:00:00 2001 From: joo Date: Tue, 1 Sep 2020 00:39:49 +0200 Subject: [PATCH] Fix EntityPositionDeltaPacket format for 1.8.9; closes #190 --- .../packets/clientbound/play/__init__.py | 32 ++++++++++++++----- minecraft/networking/types/utility.py | 15 ++++++--- tests/test_backward_compatible.py | 12 +++++++ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/minecraft/networking/packets/clientbound/play/__init__.py b/minecraft/networking/packets/clientbound/play/__init__.py index 58e1596..3624357 100644 --- a/minecraft/networking/packets/clientbound/play/__init__.py +++ b/minecraft/networking/packets/clientbound/play/__init__.py @@ -5,7 +5,7 @@ from minecraft.networking.packets import ( from minecraft.networking.types import ( FixedPoint, Integer, Angle, UnsignedByte, Byte, Boolean, UUID, Short, VarInt, Double, Float, String, Enum, Difficulty, Long, Vector, Direction, - PositionAndLook, multi_attribute_alias, + PositionAndLook, multi_attribute_alias, attribute_transform, ) from .combat_event_packet import CombatEventPacket @@ -225,13 +225,29 @@ class EntityPositionDeltaPacket(Packet): 0x15 packet_name = "entity position delta" - get_definition = staticmethod(lambda context: [ - {'entity_id': VarInt}, - {'delta_x': Short}, - {'delta_y': Short}, - {'delta_z': Short}, - {'on_ground': Boolean} - ]) + + @staticmethod + def get_definition(context): + delta_type = FixedPoint(Short, 12) \ + if context.protocol_version >= 106 else \ + FixedPoint(Byte) + return [ + {'entity_id': VarInt}, + {'delta_x_float': delta_type}, + {'delta_y_float': delta_type}, + {'delta_z_float': delta_type}, + {'on_ground': Boolean}, + ] + + # The following transforms are retained for backward compatibility; + # they represent the delta values as fixed-point integers with 5 bits + # of fractional part, regardless of the protocol version. + delta_x = attribute_transform('delta_x_float', lambda x: int(x * 32), + lambda x: x / 32) + delta_y = attribute_transform('delta_y_float', lambda y: int(y * 32), + lambda y: y / 32) + delta_z = attribute_transform('delta_z_float', lambda z: int(z * 32), + lambda z: z / 32) class TimeUpdatePacket(Packet): diff --git a/minecraft/networking/types/utility.py b/minecraft/networking/types/utility.py index c7ad5a7..bf3fa04 100644 --- a/minecraft/networking/types/utility.py +++ b/minecraft/networking/types/utility.py @@ -10,7 +10,7 @@ from itertools import chain __all__ = ( 'Vector', 'MutableRecord', 'Direction', 'PositionAndLook', 'descriptor', 'overridable_descriptor', 'overridable_property', 'attribute_alias', - 'multi_attribute_alias', + 'multi_attribute_alias', 'attribute_transform', ) @@ -92,13 +92,20 @@ class MutableRecord(object): yield slot +def attribute_transform(name, from_orig, to_orig): + """An attribute descriptor that provides a view of a different attribute + with a given name via a given transformation and its given inverse.""" + return property( + fget=(lambda self: from_orig(getattr(self, name))), + fset=(lambda self, value: setattr(self, name, to_orig(value))), + fdel=(lambda self: delattr(self, name))) + + def attribute_alias(name): """An attribute descriptor that redirects access to a different attribute with a given name. """ - return property(fget=(lambda self: getattr(self, name)), - fset=(lambda self, value: setattr(self, name, value)), - fdel=(lambda self: delattr(self, name))) + return attribute_transform(name, lambda x: x, lambda x: x) def multi_attribute_alias(container, *arg_names, **kwd_names): diff --git a/tests/test_backward_compatible.py b/tests/test_backward_compatible.py index db9ef3b..023114f 100644 --- a/tests/test_backward_compatible.py +++ b/tests/test_backward_compatible.py @@ -160,3 +160,15 @@ class ClassMemberAliasesTest(unittest.TestCase): with self.assertRaises(AttributeError): del packet.pure_game_mode + + def test_entity_position_delta_packet(self): + packet = clientbound.play.EntityPositionDeltaPacket() + packet.delta_x = -128 + packet.delta_y = 33 + packet.delta_z = 127 + self.assertEqual(packet.delta_x_float, -4.0) + self.assertEqual(packet.delta_y_float, 1.03125) + self.assertEqual(packet.delta_z_float, 3.96875) + self.assertEqual(packet.delta_x, -128) + self.assertEqual(packet.delta_y, 33) + self.assertEqual(packet.delta_z, 127)