2018-05-27 14:28:01 +02:00
|
|
|
from minecraft.networking.packets import Packet
|
2017-08-08 15:07:33 +02:00
|
|
|
from minecraft.networking.types import (
|
2018-05-27 16:36:13 +02:00
|
|
|
VarInt, Byte, Boolean, UnsignedByte, VarIntPrefixedByteArray, String,
|
|
|
|
MutableRecord
|
2017-08-08 15:07:33 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class MapPacket(Packet):
|
|
|
|
@staticmethod
|
|
|
|
def get_id(context):
|
2018-07-19 02:59:48 +02:00
|
|
|
return 0x26 if context.protocol_version >= 389 else \
|
|
|
|
0x25 if context.protocol_version >= 345 else \
|
2018-01-13 02:03:04 +01:00
|
|
|
0x24 if context.protocol_version >= 334 else \
|
2017-08-08 15:07:33 +02:00
|
|
|
0x25 if context.protocol_version >= 318 else \
|
|
|
|
0x24 if context.protocol_version >= 107 else \
|
|
|
|
0x34
|
|
|
|
|
|
|
|
packet_name = 'map'
|
|
|
|
|
2018-05-27 16:36:13 +02:00
|
|
|
class MapIcon(MutableRecord):
|
2018-05-19 19:04:48 +02:00
|
|
|
__slots__ = 'type', 'direction', 'location', 'display_name'
|
2017-08-08 15:07:33 +02:00
|
|
|
|
2018-05-19 19:04:48 +02:00
|
|
|
def __init__(self, type, direction, location, display_name=None):
|
2017-08-08 15:07:33 +02:00
|
|
|
self.type = type
|
|
|
|
self.direction = direction
|
|
|
|
self.location = location
|
2018-05-19 19:04:48 +02:00
|
|
|
self.display_name = display_name
|
2017-08-08 15:07:33 +02:00
|
|
|
|
2018-05-27 16:36:13 +02:00
|
|
|
class Map(MutableRecord):
|
2017-08-08 15:07:33 +02:00
|
|
|
__slots__ = ('id', 'scale', 'icons', 'pixels', 'width', 'height',
|
2019-05-11 08:43:08 +02:00
|
|
|
'is_tracking_position', 'is_locked')
|
2017-08-08 15:07:33 +02:00
|
|
|
|
|
|
|
def __init__(self, id=None, scale=None, width=128, height=128):
|
|
|
|
self.id = id
|
|
|
|
self.scale = scale
|
|
|
|
self.icons = []
|
|
|
|
self.width = width
|
|
|
|
self.height = height
|
|
|
|
self.pixels = bytearray(0 for i in range(width*height))
|
|
|
|
self.is_tracking_position = True
|
2019-05-11 08:43:08 +02:00
|
|
|
self.is_locked = False
|
2017-08-08 15:07:33 +02:00
|
|
|
|
|
|
|
class MapSet(object):
|
|
|
|
__slots__ = 'maps_by_id'
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.maps_by_id = dict()
|
|
|
|
|
|
|
|
def __repr__(self):
|
2018-05-19 19:04:48 +02:00
|
|
|
maps = (str(map) for map in self.maps_by_id.values())
|
2017-08-08 15:07:33 +02:00
|
|
|
return 'MapSet(%s)' % ', '.join(maps)
|
|
|
|
|
|
|
|
def read(self, file_object):
|
|
|
|
self.map_id = VarInt.read(file_object)
|
|
|
|
self.scale = Byte.read(file_object)
|
|
|
|
|
|
|
|
if self.context.protocol_version >= 107:
|
|
|
|
self.is_tracking_position = Boolean.read(file_object)
|
|
|
|
else:
|
|
|
|
self.is_tracking_position = True
|
|
|
|
|
2019-05-11 08:43:08 +02:00
|
|
|
if self.context.protocol_version >= 452:
|
|
|
|
self.is_locked = Boolean.read(file_object)
|
|
|
|
else:
|
|
|
|
self.is_locked = False
|
|
|
|
|
2017-08-08 15:07:33 +02:00
|
|
|
icon_count = VarInt.read(file_object)
|
|
|
|
self.icons = []
|
|
|
|
for i in range(icon_count):
|
2018-05-19 19:04:48 +02:00
|
|
|
if self.context.protocol_version >= 373:
|
|
|
|
type = VarInt.read(file_object)
|
|
|
|
else:
|
|
|
|
type, direction = divmod(UnsignedByte.read(file_object), 16)
|
2017-08-08 15:07:33 +02:00
|
|
|
x = Byte.read(file_object)
|
|
|
|
z = Byte.read(file_object)
|
2018-05-19 19:04:48 +02:00
|
|
|
if self.context.protocol_version >= 373:
|
|
|
|
direction = UnsignedByte.read(file_object)
|
|
|
|
if self.context.protocol_version >= 364:
|
|
|
|
has_name = Boolean.read(file_object)
|
|
|
|
display_name = String.read(file_object) if has_name else None
|
|
|
|
else:
|
|
|
|
display_name = None
|
|
|
|
icon = MapPacket.MapIcon(type, direction, (x, z), display_name)
|
2017-08-08 15:07:33 +02:00
|
|
|
self.icons.append(icon)
|
2018-05-19 19:04:48 +02:00
|
|
|
|
2017-08-08 15:07:33 +02:00
|
|
|
self.width = UnsignedByte.read(file_object)
|
|
|
|
if self.width:
|
|
|
|
self.height = UnsignedByte.read(file_object)
|
|
|
|
x = Byte.read(file_object)
|
|
|
|
z = Byte.read(file_object)
|
|
|
|
self.offset = (x, z)
|
|
|
|
self.pixels = VarIntPrefixedByteArray.read(file_object)
|
|
|
|
else:
|
|
|
|
self.height = 0
|
|
|
|
self.offset = None
|
|
|
|
self.pixels = None
|
|
|
|
|
|
|
|
def apply_to_map(self, map):
|
|
|
|
map.id = self.map_id
|
|
|
|
map.scale = self.scale
|
|
|
|
map.icons[:] = self.icons
|
|
|
|
if self.pixels is not None:
|
|
|
|
for i in range(len(self.pixels)):
|
|
|
|
x = self.offset[0] + i % self.width
|
|
|
|
z = self.offset[1] + i // self.width
|
|
|
|
map.pixels[x + map.width * z] = self.pixels[i]
|
|
|
|
map.is_tracking_position = self.is_tracking_position
|
2019-05-11 08:43:08 +02:00
|
|
|
map.is_locked = self.is_locked
|
2017-08-08 15:07:33 +02:00
|
|
|
|
|
|
|
def apply_to_map_set(self, map_set):
|
|
|
|
map = map_set.maps_by_id.get(self.map_id)
|
|
|
|
if map is None:
|
|
|
|
map = MapPacket.Map(self.map_id)
|
|
|
|
map_set.maps_by_id[self.map_id] = map
|
|
|
|
self.apply_to_map(map)
|
|
|
|
|
2018-05-27 14:28:01 +02:00
|
|
|
def write_fields(self, packet_buffer):
|
2017-08-08 15:07:33 +02:00
|
|
|
VarInt.send(self.map_id, packet_buffer)
|
|
|
|
Byte.send(self.scale, packet_buffer)
|
|
|
|
if self.context.protocol_version >= 107:
|
|
|
|
Boolean.send(self.is_tracking_position, packet_buffer)
|
|
|
|
|
|
|
|
VarInt.send(len(self.icons), packet_buffer)
|
|
|
|
for icon in self.icons:
|
2018-05-27 18:12:50 +02:00
|
|
|
if self.context.protocol_version >= 373:
|
|
|
|
VarInt.send(icon.type, packet_buffer)
|
|
|
|
else:
|
|
|
|
type_and_direction = (icon.type << 4) & 0xF0
|
|
|
|
type_and_direction |= (icon.direction & 0xF)
|
|
|
|
UnsignedByte.send(type_and_direction, packet_buffer)
|
2017-08-08 15:07:33 +02:00
|
|
|
Byte.send(icon.location[0], packet_buffer)
|
|
|
|
Byte.send(icon.location[1], packet_buffer)
|
2018-05-27 18:12:50 +02:00
|
|
|
if self.context.protocol_version >= 373:
|
|
|
|
UnsignedByte.send(icon.direction, packet_buffer)
|
|
|
|
if self.context.protocol_version >= 364:
|
|
|
|
Boolean.send(icon.display_name is not None, packet_buffer)
|
|
|
|
if icon.display_name is not None:
|
|
|
|
String.send(icon.display_name, packet_buffer)
|
2017-08-08 15:07:33 +02:00
|
|
|
|
|
|
|
UnsignedByte.send(self.width, packet_buffer)
|
|
|
|
if self.width:
|
|
|
|
UnsignedByte.send(self.height, packet_buffer)
|
|
|
|
UnsignedByte.send(self.offset[0], packet_buffer) # x
|
|
|
|
UnsignedByte.send(self.offset[1], packet_buffer) # z
|
|
|
|
VarIntPrefixedByteArray.send(self.pixels, packet_buffer)
|
|
|
|
|
|
|
|
def __repr__(self):
|
2018-05-19 19:04:48 +02:00
|
|
|
return '%sMapPacket(%s)' % (
|
|
|
|
('0x%02X ' % self.id) if self.id is not None else '',
|
|
|
|
', '.join('%s=%r' % (k, v) for (k, v) in self.__dict__.items()
|
|
|
|
if k not in ('pixels', '_context', 'id', 'definition')))
|