mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2024-11-16 07:15:24 +01:00
Add serialisation and tests for SpawnObjectPacket.
This commit is contained in:
parent
709b80b539
commit
8578326c2f
@ -1,6 +1,6 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Integer, UnsignedByte, Position, Vector
|
||||
VarInt, Integer, UnsignedByte, Position, Vector, MutableRecord
|
||||
)
|
||||
|
||||
|
||||
@ -46,21 +46,12 @@ class MultiBlockChangePacket(Packet):
|
||||
|
||||
packet_name = 'multi block change'
|
||||
|
||||
class Record(object):
|
||||
class Record(MutableRecord):
|
||||
__slots__ = 'x', 'y', 'z', 'block_state_id'
|
||||
|
||||
def __init__(self, **kwds):
|
||||
self.block_state_id = 0
|
||||
for attr, value in kwds.items():
|
||||
setattr(self, attr, value)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (type(self).__name__, ', '.join(
|
||||
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) is type(other) and all(
|
||||
getattr(self, a) == getattr(other, a) for a in self.__slots__)
|
||||
super(MultiBlockChangePacket.Record, self).__init__(**kwds)
|
||||
|
||||
# Access the 'x', 'y', 'z' fields as a Vector of ints.
|
||||
def position(self, position):
|
||||
|
@ -1,7 +1,7 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Integer, String
|
||||
VarInt, Integer, String, MutableRecord
|
||||
)
|
||||
|
||||
|
||||
@ -20,22 +20,10 @@ class CombatEventPacket(Packet):
|
||||
packet_name = 'combat event'
|
||||
|
||||
# The abstract type of the 'event' field of this packet.
|
||||
class EventType(object):
|
||||
class EventType(MutableRecord):
|
||||
__slots__ = ()
|
||||
type_from_id_dict = {}
|
||||
|
||||
def __init__(self, **kwds):
|
||||
for attr, value in kwds.items():
|
||||
setattr(self, attr, value)
|
||||
|
||||
def __repr__(self, **kwds):
|
||||
return '%s(%s)' % (type(self).__name__, ', '.join(
|
||||
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) is type(other) and all(
|
||||
getattr(self, a) == getattr(other, a) for a in self.__slots__)
|
||||
|
||||
# Read the fields of the event (not including the ID) from the file.
|
||||
def read(self, file_object):
|
||||
raise NotImplementedError(
|
||||
|
@ -1,6 +1,7 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Byte, Boolean, UnsignedByte, VarIntPrefixedByteArray, String
|
||||
VarInt, Byte, Boolean, UnsignedByte, VarIntPrefixedByteArray, String,
|
||||
MutableRecord
|
||||
)
|
||||
|
||||
|
||||
@ -15,7 +16,7 @@ class MapPacket(Packet):
|
||||
|
||||
packet_name = 'map'
|
||||
|
||||
class MapIcon(object):
|
||||
class MapIcon(MutableRecord):
|
||||
__slots__ = 'type', 'direction', 'location', 'display_name'
|
||||
|
||||
def __init__(self, type, direction, location, display_name=None):
|
||||
@ -24,11 +25,7 @@ class MapPacket(Packet):
|
||||
self.location = location
|
||||
self.display_name = display_name
|
||||
|
||||
def __repr__(self):
|
||||
fs = ('%s=%r' % (at, getattr(self, at)) for at in self.__slots__)
|
||||
return 'MapIcon(%s)' % ', '.join(fs)
|
||||
|
||||
class Map(object):
|
||||
class Map(MutableRecord):
|
||||
__slots__ = ('id', 'scale', 'icons', 'pixels', 'width', 'height',
|
||||
'is_tracking_position')
|
||||
|
||||
@ -41,10 +38,6 @@ class MapPacket(Packet):
|
||||
self.pixels = bytearray(0 for i in range(width*height))
|
||||
self.is_tracking_position = True
|
||||
|
||||
def __repr__(self):
|
||||
fs = ('%s=%r' % (at, getattr(self, at)) for at in self.__slots__)
|
||||
return 'Map(%s)' % ', '.join(fs)
|
||||
|
||||
class MapSet(object):
|
||||
__slots__ = 'maps_by_id'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
from minecraft.networking.types import (
|
||||
Double, Float, Byte, VarInt, BitFieldEnum
|
||||
Double, Float, Byte, VarInt, BitFieldEnum, PositionAndLook
|
||||
)
|
||||
|
||||
|
||||
@ -36,12 +36,8 @@ class PlayerPositionAndLookPacket(Packet, BitFieldEnum):
|
||||
FLAG_REL_YAW = 0x08
|
||||
FLAG_REL_PITCH = 0x10
|
||||
|
||||
class PositionAndLook(object):
|
||||
__slots__ = 'x', 'y', 'z', 'yaw', 'pitch'
|
||||
|
||||
def __init__(self, **kwds):
|
||||
for attr in self.__slots__:
|
||||
setattr(self, attr, kwds.get(attr))
|
||||
# This alias is retained for backward compatibility.
|
||||
PositionAndLook = PositionAndLook
|
||||
|
||||
# Update a PositionAndLook instance using this packet.
|
||||
def apply(self, target):
|
||||
|
@ -1,7 +1,8 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
from minecraft.networking.types import (
|
||||
VarInt, UUID, Byte, Double, Integer, UnsignedByte, Short, Enum
|
||||
VarInt, UUID, Byte, Double, Integer, UnsignedByte, Short, Enum, Vector,
|
||||
PositionAndLook
|
||||
)
|
||||
|
||||
|
||||
@ -44,33 +45,65 @@ class SpawnObjectPacket(Packet):
|
||||
|
||||
def read(self, file_object):
|
||||
self.entity_id = VarInt.read(file_object)
|
||||
if self._context.protocol_version >= 49:
|
||||
self.objectUUID = UUID.read(file_object)
|
||||
type_id = Byte.read(file_object)
|
||||
self.type = SpawnObjectPacket.EntityType.name_from_value(type_id)
|
||||
if self.context.protocol_version >= 49:
|
||||
self.object_uuid = UUID.read(file_object)
|
||||
self.type_id = Byte.read(file_object)
|
||||
|
||||
if self._context.protocol_version >= 100:
|
||||
self.x = Double.read(file_object)
|
||||
self.y = Double.read(file_object)
|
||||
self.z = Double.read(file_object)
|
||||
else:
|
||||
self.x = Integer.read(file_object)
|
||||
self.y = Integer.read(file_object)
|
||||
self.z = Integer.read(file_object)
|
||||
xyz_type = Double if self.context.protocol_version >= 100 else Integer
|
||||
for attr in 'x', 'y', 'z':
|
||||
setattr(self, attr, xyz_type.read(file_object))
|
||||
for attr in 'pitch', 'yaw':
|
||||
setattr(self, attr, UnsignedByte.read(file_object))
|
||||
|
||||
self.pitch = UnsignedByte.read(file_object)
|
||||
self.yaw = UnsignedByte.read(file_object)
|
||||
self.data = Integer.read(file_object)
|
||||
|
||||
if self._context.protocol_version < 49:
|
||||
if self.data > 0:
|
||||
self.velocity_x = Short.read(file_object)
|
||||
self.velocity_y = Short.read(file_object)
|
||||
self.velocity_z = Short.read(file_object)
|
||||
else:
|
||||
self.velocity_x = Short.read(file_object)
|
||||
self.velocity_y = Short.read(file_object)
|
||||
self.velocity_z = Short.read(file_object)
|
||||
if self.context.protocol_version >= 49 or self.data > 0:
|
||||
for attr in 'velocity_x', 'velocity_y', 'velocity_z':
|
||||
setattr(self, attr, Short.read(file_object))
|
||||
|
||||
def write_fields(self, packet_buffer):
|
||||
raise NotImplementedError
|
||||
VarInt.send(self.entity_id, packet_buffer)
|
||||
if self.context.protocol_version >= 49:
|
||||
UUID.send(self.object_uuid, packet_buffer)
|
||||
Byte.send(self.type_id, packet_buffer)
|
||||
|
||||
xyz_type = Double if self.context.protocol_version >= 100 else Integer
|
||||
for coord in self.x, self.y, self.z:
|
||||
xyz_type.send(coord, packet_buffer)
|
||||
for coord in self.pitch, self.yaw:
|
||||
UnsignedByte.send(coord, packet_buffer)
|
||||
|
||||
Integer.send(self.data, packet_buffer)
|
||||
if self.context.protocol_version >= 49 or self.data > 0:
|
||||
for coord in self.velocity_x, self.velocity_y, self.velocity_z:
|
||||
Short.send(coord, packet_buffer)
|
||||
|
||||
# Access the entity type as a string, according to the EntityType enum.
|
||||
def type(self, type_name):
|
||||
self.type_id = getattr(self.EntityType, type_name)
|
||||
type = property(lambda p: p.EntityType.name_from_value(p.type_id), type)
|
||||
|
||||
# Access the fields 'x', 'y', 'z' as a Vector.
|
||||
def position(self, position):
|
||||
self.x, self.y, self.z = position
|
||||
position = property(lambda p: Vector(p.x, p.y, p.z), position)
|
||||
|
||||
# Access the fields 'x', 'y', 'z', 'yaw', 'pitch' as a PositionAndLook.
|
||||
# NOTE: modifying the object retrieved from this property will not change
|
||||
# the packet; it can only be changed by attribute or property assignment.
|
||||
def position_and_look(self, position_and_look):
|
||||
self.x, self.y, self.z = position_and_look.position
|
||||
self.yaw, self.pitch = position_and_look.look
|
||||
position_and_look = property(lambda p: PositionAndLook(
|
||||
x=p.x, y=p.y, z=p.z, yaw=p.yaw, pitch=p.pitch),
|
||||
position_and_look)
|
||||
|
||||
# Access the fields 'velocity_x', 'velocity_y', 'velocity_z' as a Vector.
|
||||
def velocity(self, velocity):
|
||||
self.velocity_x, self.velocity_y, self.velocity_z = velocity
|
||||
velocity = property(lambda p: Vector(p.velocity_x, p.velocity_y,
|
||||
p.velocity_z), velocity)
|
||||
|
||||
# This alias is retained for backward compatibility.
|
||||
def objectUUID(self, object_uuid):
|
||||
self.object_uuid = object_uuid
|
||||
objectUUID = property(lambda self: self.object_uuid, objectUUID)
|
||||
|
@ -12,6 +12,39 @@ from collections import namedtuple
|
||||
Vector = namedtuple('Vector', ('x', 'y', 'z'))
|
||||
|
||||
|
||||
class MutableRecord(object):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, **kwds):
|
||||
for attr, value in kwds.items():
|
||||
setattr(self, attr, value)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (type(self).__name__, ', '.join(
|
||||
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) is type(other) and \
|
||||
all(getattr(self, a) == getattr(other, a) for a in self.__slots__)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(getattr(self, a) for a in self.__slots__)
|
||||
|
||||
|
||||
class PositionAndLook(MutableRecord):
|
||||
__slots__ = 'x', 'y', 'z', 'yaw', 'pitch'
|
||||
|
||||
# Access the fields 'x', 'y', 'z' as a Vector.
|
||||
def position(self, position):
|
||||
self.x, self.y, self.z = position
|
||||
position = property(lambda self: Vector(self.x, self.y, self.z), position)
|
||||
|
||||
# Access the fields 'yaw', 'pitch' as a tuple.
|
||||
def look(self, look):
|
||||
self.yaw, self.pitch = look
|
||||
look = property(lambda self: (self.yaw, self.pitch), look)
|
||||
|
||||
|
||||
class Type(object):
|
||||
__slots__ = ()
|
||||
|
||||
|
@ -6,10 +6,12 @@ from random import choice
|
||||
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.connection import ConnectionContext
|
||||
from minecraft.networking.types import VarInt, Enum, BitFieldEnum, Vector
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Enum, BitFieldEnum, Vector, PositionAndLook
|
||||
)
|
||||
from minecraft.networking.packets import (
|
||||
Packet, PacketBuffer, PacketListener, KeepAlivePacket, serverbound,
|
||||
clientbound,
|
||||
clientbound
|
||||
)
|
||||
|
||||
|
||||
@ -213,10 +215,47 @@ class TestReadWritePackets(unittest.TestCase):
|
||||
Record(x=1, y=2, z=3, blockId=56, blockMeta=13),
|
||||
Record(position=Vector(1, 2, 3), block_state_id=909),
|
||||
Record(position=(1, 2, 3), blockStateId=909)])
|
||||
self.assertEqual(packet.records[0].blockId, 56)
|
||||
self.assertEqual(packet.records[0].blockMeta, 13)
|
||||
self.assertEqual(packet.records[0].blockStateId, 909)
|
||||
self.assertEqual(packet.records[0].position, Vector(1, 2, 3))
|
||||
self.assertEqual(packet.records[0], packet.records[1])
|
||||
self.assertEqual(packet.records[1], packet.records[2])
|
||||
self._test_read_write_packet(packet)
|
||||
|
||||
def test_spawn_object_packet(self):
|
||||
EntityType = clientbound.play.SpawnObjectPacket.EntityType
|
||||
|
||||
object_uuid = 'd9568851-85bc-4a10-8d6a-261d130626fa'
|
||||
pos_look = PositionAndLook(x=68.0, y=38.0, z=76.0, yaw=16, pitch=23)
|
||||
velocity = Vector(21, 55, 41)
|
||||
entity_id, type_name, type_id = 49846, 'EGG', EntityType.EGG
|
||||
|
||||
packet = clientbound.play.SpawnObjectPacket(
|
||||
x=pos_look.x, y=pos_look.y, z=pos_look.z,
|
||||
yaw=pos_look.yaw, pitch=pos_look.pitch,
|
||||
velocity_x=velocity.x, velocity_y=velocity.y,
|
||||
velocity_z=velocity.z, object_uuid=object_uuid,
|
||||
entity_id=entity_id, type_id=type_id, data=1)
|
||||
self.assertEqual(packet.position_and_look, pos_look)
|
||||
self.assertEqual(packet.position, pos_look.position)
|
||||
self.assertEqual(packet.velocity, velocity)
|
||||
self.assertEqual(packet.objectUUID, object_uuid)
|
||||
self.assertEqual(packet.type, type_name)
|
||||
|
||||
packet2 = clientbound.play.SpawnObjectPacket(
|
||||
position_and_look=pos_look, velocity=velocity,
|
||||
type=type_name, object_uuid=object_uuid,
|
||||
entity_id=entity_id, data=1)
|
||||
self.assertEqual(packet.__dict__, packet2.__dict__)
|
||||
|
||||
packet2.position = pos_look.position
|
||||
self.assertEqual(packet.position, packet2.position)
|
||||
|
||||
packet2.data = 0
|
||||
self._test_read_write_packet(packet)
|
||||
self._test_read_write_packet(packet2)
|
||||
|
||||
def _test_read_write_packet(self, packet_in):
|
||||
packet_in.context = self.context
|
||||
packet_buffer = PacketBuffer()
|
||||
|
Loading…
Reference in New Issue
Block a user