mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2024-11-16 07:15:24 +01:00
Add serialisation and tests for Explosion, {Multi,}BlockChange, and CombatEvent packets.
This commit is contained in:
parent
92f2eff681
commit
709b80b539
@ -3,8 +3,8 @@ from minecraft.networking.packets import (
|
||||
)
|
||||
|
||||
from minecraft.networking.types import (
|
||||
Integer, UnsignedByte, Byte, Boolean, UUID, Short, Position,
|
||||
VarInt, Double, Float, String, Enum,
|
||||
Integer, UnsignedByte, Byte, Boolean, UUID, Short, VarInt, Double, Float,
|
||||
String, Enum,
|
||||
)
|
||||
|
||||
from .combat_event_packet import CombatEventPacket
|
||||
@ -13,6 +13,7 @@ from .player_list_item_packet import PlayerListItemPacket
|
||||
from .player_position_and_look_packet import PlayerPositionAndLookPacket
|
||||
from .spawn_object_packet import SpawnObjectPacket
|
||||
from .block_change_packet import BlockChangePacket, MultiBlockChangePacket
|
||||
from .explosion_packet import ExplosionPacket
|
||||
|
||||
|
||||
# Formerly known as state_playing_clientbound.
|
||||
@ -176,42 +177,6 @@ class UpdateHealthPacket(Packet):
|
||||
])
|
||||
|
||||
|
||||
class ExplosionPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x1D if context.protocol_version >= 345 else \
|
||||
0x1C if context.protocol_version >= 332 else \
|
||||
0x1D if context.protocol_version >= 318 else \
|
||||
0x1C if context.protocol_version >= 80 else \
|
||||
0x1B if context.protocol_version >= 67 else \
|
||||
0x27
|
||||
|
||||
packet_name = 'explosion'
|
||||
|
||||
class Record(Position):
|
||||
pass
|
||||
|
||||
def read(self, file_object):
|
||||
self.x = Float.read(file_object)
|
||||
self.y = Float.read(file_object)
|
||||
self.z = Float.read(file_object)
|
||||
self.radius = Float.read(file_object)
|
||||
records_count = VarInt.read(file_object)
|
||||
self.records = []
|
||||
for i in range(records_count):
|
||||
rec_x = Byte.read(file_object)
|
||||
rec_y = Byte.read(file_object)
|
||||
rec_z = Byte.read(file_object)
|
||||
record = ExplosionPacket.Record(rec_x, rec_y, rec_z)
|
||||
self.records.append(record)
|
||||
self.player_motion_x = Float.read(file_object)
|
||||
self.player_motion_y = Float.read(file_object)
|
||||
self.player_motion_z = Float.read(file_object)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PluginMessagePacket(AbstractPluginMessagePacket):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
|
@ -1,8 +1,6 @@
|
||||
from minecraft.networking.packets import (
|
||||
Packet, PacketBuffer
|
||||
)
|
||||
from minecraft.networking.packets import Packet
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Integer, UnsignedByte, Position
|
||||
VarInt, Integer, UnsignedByte, Position, Vector
|
||||
)
|
||||
|
||||
|
||||
@ -16,23 +14,25 @@ class BlockChangePacket(Packet):
|
||||
0x23
|
||||
|
||||
packet_name = 'block change'
|
||||
definition = [
|
||||
{'location': Position},
|
||||
{'block_state_id': VarInt}]
|
||||
block_state_id = 0
|
||||
|
||||
def read(self, file_object):
|
||||
self.location = Position.read(file_object)
|
||||
blockData = VarInt.read(file_object)
|
||||
if self.context.protocol_version >= 347:
|
||||
# See comments on MultiBlockChangePacket.OpaqueRecord.
|
||||
self.blockStateId = blockData
|
||||
else:
|
||||
self.blockId = (blockData >> 4)
|
||||
self.blockMeta = (blockData & 0xF)
|
||||
# For protocols < 347: an accessor for (block_state_id >> 4).
|
||||
def blockId(self, block_id):
|
||||
self.block_state_id = (self.block_state_id & 0xF) | (block_id << 4)
|
||||
blockId = property(lambda self: self.block_state_id >> 4, blockId)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
packet_buffer = PacketBuffer()
|
||||
Position.send(self.location, packet_buffer)
|
||||
blockData = ((self.blockId << 4) | (self.blockMeta & 0xF))
|
||||
VarInt.send(blockData)
|
||||
self._write_buffer(socket, packet_buffer, compression_threshold)
|
||||
# For protocols < 347: an accessor for (block_state_id & 0xF).
|
||||
def blockMeta(self, meta):
|
||||
self.block_state_id = (self.block_state_id & ~0xF) | (meta & 0xF)
|
||||
blockMeta = property(lambda self: self.block_state_id & 0xF, blockMeta)
|
||||
|
||||
# This alias is retained for backward compatibility.
|
||||
def blockStateId(self, block_state_id):
|
||||
self.block_state_id = block_state_id
|
||||
blockStateId = property(lambda self: self.block_state_id, blockStateId)
|
||||
|
||||
|
||||
class MultiBlockChangePacket(Packet):
|
||||
@ -46,60 +46,66 @@ class MultiBlockChangePacket(Packet):
|
||||
|
||||
packet_name = 'multi block change'
|
||||
|
||||
class BaseRecord(object):
|
||||
__slots__ = 'x', 'y', 'z'
|
||||
class Record(object):
|
||||
__slots__ = 'x', 'y', 'z', 'block_state_id'
|
||||
|
||||
def __init__(self, horizontal_position, y_coordinate):
|
||||
self.x = (horizontal_position & 0xF0) >> 4
|
||||
self.y = y_coordinate
|
||||
self.z = (horizontal_position & 0x0F)
|
||||
|
||||
@classmethod
|
||||
def get_subclass(cls, context):
|
||||
return MultiBlockChangePacket.OpaqueRecord \
|
||||
if context.protocol_version >= 347 else \
|
||||
MultiBlockChangePacket.Record
|
||||
|
||||
class Record(BaseRecord):
|
||||
__slots__ = 'blockId', 'blockMeta'
|
||||
|
||||
def __init__(self, h_position, y_coordinate, blockData):
|
||||
super(MultiBlockChangePacket.Record, self).__init__(
|
||||
h_position, y_coordinate)
|
||||
self.blockId = (blockData >> 4)
|
||||
self.blockMeta = (blockData & 0xF)
|
||||
def __init__(self, **kwds):
|
||||
self.block_state_id = 0
|
||||
for attr, value in kwds.items():
|
||||
setattr(self, attr, value)
|
||||
|
||||
def __repr__(self):
|
||||
return ('Record(x=%s, y=%s, z=%s, blockId=%s)'
|
||||
% (self.x, self.y, self.z, self.blockId))
|
||||
return '%s(%s)' % (type(self).__name__, ', '.join(
|
||||
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
|
||||
|
||||
'''The structure of the block data changed in protocol 347 (17w47b,
|
||||
between 1.12.2 and 1.13), which this class reflects: instead of a
|
||||
separate blockId and blockMeta number, there is a single opaque
|
||||
blockStateId whose meaning may change between minor versions.'''
|
||||
class OpaqueRecord(BaseRecord):
|
||||
__slots__ = 'blockStateId'
|
||||
def __eq__(self, other):
|
||||
return type(self) is type(other) and all(
|
||||
getattr(self, a) == getattr(other, a) for a in self.__slots__)
|
||||
|
||||
def __init__(self, h_position, y_coordinate, blockData):
|
||||
super(MultiBlockChangePacket.OpaqueRecord, self).__init__(
|
||||
h_position, y_coordinate)
|
||||
self.blockStateId = blockData
|
||||
# Access the 'x', 'y', 'z' fields as a Vector of ints.
|
||||
def position(self, position):
|
||||
self.x, self.y, self.z = position
|
||||
position = property(lambda r: Vector(r.x, r.y, r.z), position)
|
||||
|
||||
def __repr__(self):
|
||||
return ('OpaqueRecord(x=%s, y=%s, z=%s, blockStateId=%s)'
|
||||
% (self.x, self.y, self.z, self.blockStateId))
|
||||
# For protocols < 347: an accessor for (block_state_id >> 4).
|
||||
def blockId(self, block_id):
|
||||
self.block_state_id = self.block_state_id & 0xF | block_id << 4
|
||||
blockId = property(lambda r: r.block_state_id >> 4, blockId)
|
||||
|
||||
# For protocols < 347: an accessor for (block_state_id & 0xF).
|
||||
def blockMeta(self, meta):
|
||||
self.block_state_id = self.block_state_id & ~0xF | meta & 0xF
|
||||
blockMeta = property(lambda r: r.block_state_id & 0xF, blockMeta)
|
||||
|
||||
# This alias is retained for backward compatibility.
|
||||
def blockStateId(self, block_state_id):
|
||||
self.block_state_id = block_state_id
|
||||
blockStateId = property(lambda r: r.block_state_id, blockStateId)
|
||||
|
||||
def read(self, file_object):
|
||||
h_position = UnsignedByte.read(file_object)
|
||||
self.x, self.z = h_position >> 4, h_position & 0xF
|
||||
self.y = UnsignedByte.read(file_object)
|
||||
self.block_state_id = VarInt.read(file_object)
|
||||
|
||||
def write(self, packet_buffer):
|
||||
UnsignedByte.send(self.x << 4 | self.z & 0xF, packet_buffer)
|
||||
UnsignedByte.send(self.y, packet_buffer)
|
||||
VarInt.send(self.block_state_id, packet_buffer)
|
||||
|
||||
def read(self, file_object):
|
||||
self.chunk_x = Integer.read(file_object)
|
||||
self.chunk_z = Integer.read(file_object)
|
||||
records_count = VarInt.read(file_object)
|
||||
record_type = self.BaseRecord.get_subclass(self.context)
|
||||
self.records = []
|
||||
for i in range(records_count):
|
||||
record = record_type(h_position=UnsignedByte.read(file_object),
|
||||
y_coordinate=UnsignedByte.read(file_object),
|
||||
blockData=VarInt.read(file_object))
|
||||
record = self.Record()
|
||||
record.read(file_object)
|
||||
self.records.append(record)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
raise NotImplementedError
|
||||
def write_fields(self, packet_buffer):
|
||||
Integer.send(self.chunk_x, packet_buffer)
|
||||
Integer.send(self.chunk_z, packet_buffer)
|
||||
VarInt.send(len(self.records), packet_buffer)
|
||||
for record in self.records:
|
||||
record.write(packet_buffer)
|
||||
|
@ -19,48 +19,84 @@ class CombatEventPacket(Packet):
|
||||
|
||||
packet_name = 'combat event'
|
||||
|
||||
# The abstract type of the 'event' field of this packet.
|
||||
class EventType(object):
|
||||
def read(self, file_object):
|
||||
self._read(file_object)
|
||||
__slots__ = ()
|
||||
type_from_id_dict = {}
|
||||
|
||||
def _read(self, file_object):
|
||||
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(
|
||||
'This abstract method must be overridden in a subclass.')
|
||||
|
||||
# Write the fields of the event (not including the ID) to the buffer.
|
||||
def write(self, packet_buffer):
|
||||
raise NotImplementedError(
|
||||
'This abstract method must be overridden in a subclass.')
|
||||
|
||||
@classmethod
|
||||
def type_from_id(cls, event_id):
|
||||
subcls = {
|
||||
0: CombatEventPacket.EnterCombatEvent,
|
||||
1: CombatEventPacket.EndCombatEvent,
|
||||
2: CombatEventPacket.EntityDeadEvent
|
||||
}.get(event_id)
|
||||
subcls = cls.type_from_id_dict.get(event_id)
|
||||
if subcls is None:
|
||||
raise ValueError("Unknown combat event ID: %s."
|
||||
% event_id)
|
||||
raise ValueError('Unknown combat event ID: %s.' % event_id)
|
||||
return subcls
|
||||
|
||||
class EnterCombatEvent(EventType):
|
||||
def _read(self, file_object):
|
||||
__slots__ = ()
|
||||
id = 0
|
||||
|
||||
def read(self, file_object):
|
||||
pass
|
||||
|
||||
def write(self, packet_buffer):
|
||||
pass
|
||||
EventType.type_from_id_dict[EnterCombatEvent.id] = EnterCombatEvent
|
||||
|
||||
class EndCombatEvent(EventType):
|
||||
__slots__ = 'duration', 'entity_id'
|
||||
id = 1
|
||||
|
||||
def _read(self, file_object):
|
||||
def read(self, file_object):
|
||||
self.duration = VarInt.read(file_object)
|
||||
self.entity_id = Integer.read(file_object)
|
||||
|
||||
def write(self, packet_buffer):
|
||||
VarInt.send(self.duration, packet_buffer)
|
||||
Integer.send(self.entity_id, packet_buffer)
|
||||
EventType.type_from_id_dict[EndCombatEvent.id] = EndCombatEvent
|
||||
|
||||
class EntityDeadEvent(EventType):
|
||||
__slots__ = 'player_id', 'entity_id', 'message'
|
||||
id = 2
|
||||
|
||||
def _read(self, file_object):
|
||||
def read(self, file_object):
|
||||
self.player_id = VarInt.read(file_object)
|
||||
self.entity_id = Integer.read(file_object)
|
||||
self.message = String.read(file_object)
|
||||
|
||||
def write(self, packet_buffer):
|
||||
VarInt.send(self.player_id, packet_buffer)
|
||||
Integer.send(self.entity_id, packet_buffer)
|
||||
String.send(self.message, packet_buffer)
|
||||
EventType.type_from_id_dict[EntityDeadEvent.id] = EntityDeadEvent
|
||||
|
||||
def read(self, file_object):
|
||||
event_id = VarInt.read(file_object)
|
||||
self.event_type = CombatEventPacket.EventType.type_from_id(event_id)
|
||||
self.event = CombatEventPacket.EventType.type_from_id(event_id)()
|
||||
self.event.read(file_object)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
raise NotImplementedError
|
||||
def write_fields(self, packet_buffer):
|
||||
VarInt.send(self.event.id, packet_buffer)
|
||||
self.event.write(packet_buffer)
|
||||
|
@ -0,0 +1,67 @@
|
||||
from minecraft.networking.types import Vector, Float, Byte, Integer
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
|
||||
class ExplosionPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x1D if context.protocol_version >= 345 else \
|
||||
0x1C if context.protocol_version >= 332 else \
|
||||
0x1D if context.protocol_version >= 318 else \
|
||||
0x1C if context.protocol_version >= 80 else \
|
||||
0x1B if context.protocol_version >= 67 else \
|
||||
0x27
|
||||
|
||||
packet_name = 'explosion'
|
||||
|
||||
class Record(Vector):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
return Vector(self.x, self.y, self.x)
|
||||
|
||||
@position.setter
|
||||
def position(self, new_position):
|
||||
self.x, self.y, self.z = new_position
|
||||
|
||||
@property
|
||||
def player_motion(self):
|
||||
return Vector(self.player_motion_x, self.player_motion_y,
|
||||
self.player_motion_z)
|
||||
|
||||
@player_motion.setter
|
||||
def player_motion(self, new_player_motion):
|
||||
self.player_motion_x, self.player_motion_y, self.player_motion_z \
|
||||
= new_player_motion
|
||||
|
||||
def read(self, file_object):
|
||||
self.x = Float.read(file_object)
|
||||
self.y = Float.read(file_object)
|
||||
self.z = Float.read(file_object)
|
||||
self.radius = Float.read(file_object)
|
||||
records_count = Integer.read(file_object)
|
||||
self.records = []
|
||||
for i in range(records_count):
|
||||
rec_x = Byte.read(file_object)
|
||||
rec_y = Byte.read(file_object)
|
||||
rec_z = Byte.read(file_object)
|
||||
record = ExplosionPacket.Record(rec_x, rec_y, rec_z)
|
||||
self.records.append(record)
|
||||
self.player_motion_x = Float.read(file_object)
|
||||
self.player_motion_y = Float.read(file_object)
|
||||
self.player_motion_z = Float.read(file_object)
|
||||
|
||||
def write_fields(self, packet_buffer):
|
||||
Float.send(self.x, packet_buffer)
|
||||
Float.send(self.y, packet_buffer)
|
||||
Float.send(self.z, packet_buffer)
|
||||
Float.send(self.radius, packet_buffer)
|
||||
Integer.send(len(self.records), packet_buffer)
|
||||
for record in self.records:
|
||||
Byte.send(record.x, packet_buffer)
|
||||
Byte.send(record.y, packet_buffer)
|
||||
Byte.send(record.z, packet_buffer)
|
||||
Float.send(self.player_motion_x, packet_buffer)
|
||||
Float.send(self.player_motion_y, packet_buffer)
|
||||
Float.send(self.player_motion_z, packet_buffer)
|
@ -1,7 +1,4 @@
|
||||
from minecraft.networking.packets import (
|
||||
Packet, PacketBuffer
|
||||
)
|
||||
|
||||
from minecraft.networking.packets import Packet
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Byte, Boolean, UnsignedByte, VarIntPrefixedByteArray, String
|
||||
)
|
||||
@ -116,10 +113,7 @@ class MapPacket(Packet):
|
||||
map_set.maps_by_id[self.map_id] = map
|
||||
self.apply_to_map(map)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
packet_buffer = PacketBuffer()
|
||||
VarInt.send(self.id, packet_buffer)
|
||||
|
||||
def write_fields(self, packet_buffer):
|
||||
VarInt.send(self.map_id, packet_buffer)
|
||||
Byte.send(self.scale, packet_buffer)
|
||||
if self.context.protocol_version >= 107:
|
||||
@ -140,8 +134,6 @@ class MapPacket(Packet):
|
||||
UnsignedByte.send(self.offset[1], packet_buffer) # z
|
||||
VarIntPrefixedByteArray.send(self.pixels, packet_buffer)
|
||||
|
||||
self._write_buffer(socket, packet_buffer, compression_threshold)
|
||||
|
||||
def __repr__(self):
|
||||
return '%sMapPacket(%s)' % (
|
||||
('0x%02X ' % self.id) if self.id is not None else '',
|
||||
|
@ -156,5 +156,5 @@ class PlayerListItemPacket(Packet):
|
||||
for action in self.actions:
|
||||
action.apply(player_list)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
def write_fields(self, packet_buffer):
|
||||
raise NotImplementedError
|
||||
|
@ -72,5 +72,5 @@ class SpawnObjectPacket(Packet):
|
||||
self.velocity_y = Short.read(file_object)
|
||||
self.velocity_z = Short.read(file_object)
|
||||
|
||||
def write(self, socket, compression_threshold=None):
|
||||
def write_fields(self, packet_buffer):
|
||||
raise NotImplementedError
|
||||
|
@ -25,9 +25,9 @@ class Packet(object):
|
||||
# 2. Override `get_definition' in a subclass and return the correct
|
||||
# definition for the given ConnectionContext. This may be necessary
|
||||
# if the layout has changed across protocol versions, for example; or
|
||||
# 3. Override the methods `read' and/or `write' in a subclass. This may be
|
||||
# necessary if the packet layout cannot be described as a list of
|
||||
# fields.
|
||||
# 3. Override the methods `read' and/or `write_fields' in a subclass.
|
||||
# This may be necessary if the packet layout cannot be described as a
|
||||
# simple list of fields.
|
||||
@classmethod
|
||||
def get_definition(cls, context):
|
||||
return cls.definition
|
||||
@ -95,13 +95,17 @@ class Packet(object):
|
||||
# write packet's id right off the bat in the header
|
||||
VarInt.send(self.id, packet_buffer)
|
||||
# write every individual field
|
||||
self.write_fields(packet_buffer)
|
||||
self._write_buffer(socket, packet_buffer, compression_threshold)
|
||||
|
||||
def write_fields(self, packet_buffer):
|
||||
# Write the fields comprising the body of the packet (excluding the
|
||||
# length, packet ID, compression and encryption) into a PacketBuffer.
|
||||
for field in self.definition:
|
||||
for var_name, data_type in field.items():
|
||||
data = getattr(self, var_name)
|
||||
data_type.send(data, packet_buffer)
|
||||
|
||||
self._write_buffer(socket, packet_buffer, compression_threshold)
|
||||
|
||||
def __repr__(self):
|
||||
str = type(self).__name__
|
||||
if self.id is not None:
|
||||
|
@ -7,6 +7,11 @@ import uuid
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
# NOTE: subclasses of 'Vector' should have '__slots__ = ()' to avoid the
|
||||
# creation of a '__dict__' attribute, which would waste space.
|
||||
Vector = namedtuple('Vector', ('x', 'y', 'z'))
|
||||
|
||||
|
||||
class Type(object):
|
||||
__slots__ = ()
|
||||
|
||||
@ -241,7 +246,7 @@ class UUID(Type):
|
||||
socket.send(uuid.UUID(value).bytes)
|
||||
|
||||
|
||||
class Position(Type, namedtuple('Position', ('x', 'y', 'z'))):
|
||||
class Position(Type, Vector):
|
||||
__slots__ = ()
|
||||
|
||||
@staticmethod
|
||||
|
@ -1,5 +1,7 @@
|
||||
import unittest
|
||||
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.connection import ConnectionContext
|
||||
from minecraft.networking import packets
|
||||
from minecraft.networking import types
|
||||
from minecraft.networking.packets import clientbound
|
||||
@ -91,3 +93,11 @@ class ClassMemberAliasesTest(unittest.TestCase):
|
||||
types.AbsoluteHand.LEFT)
|
||||
self.assertEqual(serverbound.play.ClientSettingsPacket.Hand.RIGHT,
|
||||
types.AbsoluteHand.RIGHT)
|
||||
|
||||
def test_block_change_packet(self):
|
||||
context = ConnectionContext()
|
||||
context.protocol_version = SUPPORTED_PROTOCOL_VERSIONS[-1]
|
||||
bi, bm = 358, 9
|
||||
packet = clientbound.play.BlockChangePacket(blockId=bi, blockMeta=bm)
|
||||
self.assertEqual((packet.blockId, packet.blockMeta), (bi, bm))
|
||||
self.assertEqual(packet.blockStateId, packet.block_state_id)
|
||||
|
@ -6,9 +6,11 @@ from random import choice
|
||||
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.connection import ConnectionContext
|
||||
from minecraft.networking.types import VarInt, Enum, BitFieldEnum
|
||||
from minecraft.networking.types import VarInt, Enum, BitFieldEnum, Vector
|
||||
from minecraft.networking.packets import (
|
||||
Packet, PacketBuffer, PacketListener, KeepAlivePacket, serverbound)
|
||||
Packet, PacketBuffer, PacketListener, KeepAlivePacket, serverbound,
|
||||
clientbound,
|
||||
)
|
||||
|
||||
|
||||
class PacketBufferTest(unittest.TestCase):
|
||||
@ -35,7 +37,7 @@ class PacketBufferTest(unittest.TestCase):
|
||||
self.assertEqual(packet_buffer.get_writable(), message)
|
||||
|
||||
|
||||
class PacketSerializatonTest(unittest.TestCase):
|
||||
class PacketSerializationTest(unittest.TestCase):
|
||||
|
||||
def test_packet(self):
|
||||
for protocol_version in SUPPORTED_PROTOCOL_VERSIONS:
|
||||
@ -173,3 +175,58 @@ class BitFieldEnumTest(unittest.TestCase):
|
||||
list(map(Example2.name_from_value, range(9))),
|
||||
['0', 'ONE', 'TWO', 'ONE|TWO', 'FOUR',
|
||||
'ONE|FOUR', 'TWO|FOUR', 'ONE|TWO|FOUR', None])
|
||||
|
||||
|
||||
class TestReadWritePackets(unittest.TestCase):
|
||||
maxDiff = None
|
||||
|
||||
def setUp(self):
|
||||
self.context = ConnectionContext()
|
||||
self.context.protocol_version = SUPPORTED_PROTOCOL_VERSIONS[-1]
|
||||
|
||||
def tearDown(self):
|
||||
del self.context
|
||||
|
||||
def test_explosion_packet(self):
|
||||
Record = clientbound.play.ExplosionPacket.Record
|
||||
packet = clientbound.play.ExplosionPacket(
|
||||
position=Vector(787, -37, 0), radius=15,
|
||||
records=[Record(-14, -116, -5), Record(-77, 34, -36),
|
||||
Record(-35, -127, 95), Record(11, 113, -8)],
|
||||
player_motion=Vector(4, 5, 0))
|
||||
self._test_read_write_packet(packet)
|
||||
|
||||
def test_combat_event_packet(self):
|
||||
packet = clientbound.play.CombatEventPacket()
|
||||
for event in (
|
||||
packet.EnterCombatEvent(),
|
||||
packet.EndCombatEvent(duration=415, entity_id=91063502),
|
||||
packet.EntityDeadEvent(player_id=178, entity_id=36, message='RIP'),
|
||||
):
|
||||
packet.event = event
|
||||
self._test_read_write_packet(packet)
|
||||
|
||||
def test_multi_block_change_packet(self):
|
||||
Record = clientbound.play.MultiBlockChangePacket.Record
|
||||
packet = clientbound.play.MultiBlockChangePacket(
|
||||
chunk_x=167, chunk_z=15, records=[
|
||||
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], packet.records[1])
|
||||
self.assertEqual(packet.records[1], packet.records[2])
|
||||
self._test_read_write_packet(packet)
|
||||
|
||||
def _test_read_write_packet(self, packet_in):
|
||||
packet_in.context = self.context
|
||||
packet_buffer = PacketBuffer()
|
||||
packet_in.write(packet_buffer)
|
||||
packet_buffer.reset_cursor()
|
||||
VarInt.read(packet_buffer)
|
||||
packet_id = VarInt.read(packet_buffer)
|
||||
self.assertEqual(packet_id, packet_in.id)
|
||||
|
||||
packet_out = type(packet_in)(context=self.context)
|
||||
packet_out.read(packet_buffer)
|
||||
self.assertIs(type(packet_in), type(packet_out))
|
||||
self.assertEqual(packet_in.__dict__, packet_out.__dict__)
|
||||
|
Loading…
Reference in New Issue
Block a user