pyCraft/tests/test_packets_with_logic.py
joodicator 612fa8e324 Add support for Minecraft 18w43a to 1.14 (protocols 441 to 477)
This commit introduces two backward-incompatible changes which may break
existing code:

(1) `networking.packets.clientbound.play.SpawnObjectPacket.EntityType'
is no longer accessible as an attribute of the the `SpawnObjectPacket'
class: the values now depend on a `ConnectionContext`, and must be
accessed through an instance, or using `SpawnObjectPacket.field_enum'.
See the text of the `AttributeError` raised from the descriptor for
`SpawnObjectPacket.EntityType` for the full details.

(2) For some subclasses of `networking.types.Type', it is necessary to
call the methods `read_with_context' and `send_with_context' instead of
`read' and `send', supplying a `ConnectionContext' for those data types
- currently only `Position` - whose layout depends on it.
2019-05-11 08:43:51 +02:00

245 lines
8.7 KiB
Python

import unittest
from minecraft.networking.types import (UUID, VarInt, String, Boolean)
from minecraft.networking.packets import PacketBuffer
from minecraft.networking.packets.clientbound.play import (
PlayerPositionAndLookPacket, PlayerListItemPacket, MapPacket
)
from minecraft.networking.connection import ConnectionContext
class PlayerPositionAndLookTest(unittest.TestCase):
def test_position_and_look(self):
current_position = PlayerPositionAndLookPacket.PositionAndLook(
x=999, y=999, z=999, yaw=999, pitch=999)
packet = PlayerPositionAndLookPacket()
packet.x = 1.0
packet.y = 2.0
packet.z = 3.0
packet.yaw = 4.0
packet.pitch = 5.0
# First do an absolute move to these cordinates
packet.flags = 0
packet.apply(current_position)
self.assertEqual(current_position.x, 1.0)
self.assertEqual(current_position.y, 2.0)
self.assertEqual(current_position.z, 3.0)
self.assertEqual(current_position.yaw, 4.0)
self.assertEqual(current_position.pitch, 5.0)
# Now a relative move
packet.flags = 0b11111
packet.apply(current_position)
self.assertEqual(current_position.x, 2.0)
self.assertEqual(current_position.y, 4.0)
self.assertEqual(current_position.z, 6.0)
self.assertEqual(current_position.yaw, 8.0)
self.assertEqual(current_position.pitch, 10.0)
class MapPacketTest(unittest.TestCase):
@staticmethod
def make_map_packet(
context, width=2, height=2, offset=(2, 2), pixels=b"this"):
packet = MapPacket(context)
packet.map_id = 1
packet.scale = 42
packet.is_tracking_position = True
packet.is_locked = False
packet.icons = []
d_name = u'Marshmallow' if context.protocol_version >= 364 else None
packet.icons.append(MapPacket.MapIcon(
type=2, direction=2, location=(1, 1), display_name=d_name
))
packet.icons.append(MapPacket.MapIcon(
type=3, direction=3, location=(3, 3)
))
packet.width = width
packet.height = height if width else 0
packet.offset = offset if width else None
packet.pixels = pixels if width else None
return packet
def packet_roundtrip(self, context, **kwds):
packet = self.make_map_packet(context, **kwds)
packet_buffer = PacketBuffer()
packet.write(packet_buffer)
packet_buffer.reset_cursor()
# Read the length and packet id
VarInt.read(packet_buffer)
packet_id = VarInt.read(packet_buffer)
self.assertEqual(packet_id, packet.id)
p = MapPacket(context)
p.read(packet_buffer)
self.assertEqual(p.map_id, packet.map_id)
self.assertEqual(p.scale, packet.scale)
self.assertEqual(p.is_tracking_position, packet.is_tracking_position)
self.assertEqual(p.width, packet.width)
self.assertEqual(p.height, packet.height)
self.assertEqual(p.offset, packet.offset)
self.assertEqual(p.pixels, packet.pixels)
self.assertEqual(str(p.icons[0]), str(packet.icons[0]))
self.assertEqual(str(p.icons[1]), str(packet.icons[1]))
self.assertEqual(str(p), str(packet))
def test_packet_roundtrip(self):
self.packet_roundtrip(ConnectionContext(protocol_version=106))
self.packet_roundtrip(ConnectionContext(protocol_version=107))
self.packet_roundtrip(ConnectionContext(protocol_version=379))
self.packet_roundtrip(ConnectionContext(protocol_version=379),
width=0)
def test_map_set(self):
map_set = MapPacket.MapSet()
context = ConnectionContext(protocol_version=107)
packet = self.make_map_packet(context)
packet.apply_to_map_set(map_set)
self.assertEqual(len(map_set.maps_by_id), 1)
packet = self.make_map_packet(
context, width=1, height=0, offset=(2, 2), pixels=b"x"
)
packet.apply_to_map_set(map_set)
map = map_set.maps_by_id[1]
self.assertIn(b"xh", map.pixels)
self.assertIn(b"is", map.pixels)
self.assertIsNotNone(str(map_set))
fake_uuid = "12345678-1234-5678-1234-567812345678"
class PlayerListItemTest(unittest.TestCase):
def test_base_action(self):
packet_buffer = PacketBuffer()
UUID.send(fake_uuid, packet_buffer)
packet_buffer.reset_cursor()
with self.assertRaises(NotImplementedError):
action = PlayerListItemPacket.Action()
action.read(packet_buffer)
def test_invalid_action(self):
packet_buffer = PacketBuffer()
VarInt.send(200, packet_buffer) # action_id
packet_buffer.reset_cursor()
with self.assertRaises(ValueError):
PlayerListItemPacket().read(packet_buffer)
@staticmethod
def make_add_player_packet(display_name=True):
packet_buffer = PacketBuffer()
VarInt.send(0, packet_buffer) # action_id
VarInt.send(1, packet_buffer) # action count
UUID.send(fake_uuid, packet_buffer) # uuid
String.send("player", packet_buffer) # player name
VarInt.send(2, packet_buffer) # number of properties
String.send("property1", packet_buffer)
String.send("value1", packet_buffer)
Boolean.send(False, packet_buffer) # is signed
String.send("property2", packet_buffer)
String.send("value2", packet_buffer)
Boolean.send(True, packet_buffer) # is signed
String.send("signature", packet_buffer)
VarInt.send(42, packet_buffer) # game mode
VarInt.send(69, packet_buffer) # ping
Boolean.send(display_name, packet_buffer) # has display name
if display_name:
String.send("display", packet_buffer) # display name
packet_buffer.reset_cursor()
return packet_buffer
def test_add_player_action(self):
player_list = PlayerListItemPacket.PlayerList()
packet_buffer = self.make_add_player_packet()
packet = PlayerListItemPacket()
packet.read(packet_buffer)
packet.apply(player_list)
self.assertIn(fake_uuid, player_list.players_by_uuid)
player = player_list.players_by_uuid[fake_uuid]
self.assertEqual(player.name, "player")
self.assertEqual(player.properties[0].name, "property1")
self.assertIsNone(player.properties[0].signature)
self.assertEqual(player.properties[1].value, "value2")
self.assertEqual(player.properties[1].signature, "signature")
self.assertEqual(player.gamemode, 42)
self.assertEqual(player.ping, 69)
self.assertEqual(player.display_name, "display")
@staticmethod
def make_action_base(action_id):
packet_buffer = PacketBuffer()
VarInt.send(action_id, packet_buffer)
VarInt.send(1, packet_buffer) # action count
UUID.send(fake_uuid, packet_buffer)
return packet_buffer
def read_and_apply(self, packet_buffer, player_list):
packet_buffer.reset_cursor()
packet = PlayerListItemPacket()
packet.read(packet_buffer)
packet.apply(player_list)
def test_add_and_others(self):
player_list = PlayerListItemPacket.PlayerList()
by_uuid = player_list.players_by_uuid
packet_buffer = self.make_add_player_packet(display_name=False)
self.read_and_apply(packet_buffer, player_list)
self.assertEqual(by_uuid[fake_uuid].gamemode, 42)
self.assertEqual(by_uuid[fake_uuid].ping, 69)
self.assertIsNone(by_uuid[fake_uuid].display_name)
# Change the game mode
packet_buffer = self.make_action_base(1)
VarInt.send(43, packet_buffer) # gamemode
self.read_and_apply(packet_buffer, player_list)
self.assertEqual(by_uuid[fake_uuid].gamemode, 43)
# Change the ping
packet_buffer = self.make_action_base(2)
VarInt.send(70, packet_buffer) # ping
self.read_and_apply(packet_buffer, player_list)
self.assertEqual(by_uuid[fake_uuid].ping, 70)
# Change the display name
packet_buffer = self.make_action_base(3)
Boolean.send(True, packet_buffer)
String.send("display2", packet_buffer)
self.read_and_apply(packet_buffer, player_list)
self.assertEqual(by_uuid[fake_uuid].display_name, "display2")
# Remove the display name
packet_buffer = self.make_action_base(3)
Boolean.send(False, packet_buffer)
self.read_and_apply(packet_buffer, player_list)
self.assertIsNone(by_uuid[fake_uuid].display_name)
# Remove the player
packet_buffer = self.make_action_base(4)
self.read_and_apply(packet_buffer, player_list)
self.assertNotIn(fake_uuid, player_list.players_by_uuid)