Add support for Minecraft 1.9 (protocol 107). Miscellaneous bugfixes.

This commit is contained in:
joo 2016-03-07 06:22:42 +00:00
parent f178df5d8f
commit d966709204
3 changed files with 72 additions and 21 deletions

View File

@ -7,7 +7,7 @@ __version__ = "0.1.0"
SUPPORTED_PROTOCOL_VERSIONS = ( SUPPORTED_PROTOCOL_VERSIONS = (
47, 47,
# 107, # Not yet. 107,
) )
SUPPORTED_MINECRAFT_VERSIONS = { SUPPORTED_MINECRAFT_VERSIONS = {
@ -20,5 +20,5 @@ SUPPORTED_MINECRAFT_VERSIONS = {
'1.8.6': 47, '1.8.6': 47,
'1.8.7': 47, '1.8.7': 47,
'1.8.8': 47, '1.8.8': 47,
# '1.9': 107, # Not yet. '1.9': 107,
} }

View File

@ -410,7 +410,7 @@ class PlayingReactor(PacketReactor):
self.connection.options.compression_enabled = True self.connection.options.compression_enabled = True
if packet.packet_name == "keep alive": if packet.packet_name == "keep alive":
keep_alive_packet = packets.KeepAlivePacket() keep_alive_packet = packets.KeepAlivePacketServerbound()
keep_alive_packet.keep_alive_id = packet.keep_alive_id keep_alive_packet.keep_alive_id = packet.keep_alive_id
self.connection.write_packet(keep_alive_packet) self.connection.write_packet(keep_alive_packet)

View File

@ -76,8 +76,20 @@ class Packet(object):
def __init__(self, context=None, **kwargs): def __init__(self, context=None, **kwargs):
self.context = context self.context = context
self.id = self.get_id(context)
self.definition = self.get_definition(context) @property
def context(self):
return self._context
@context.setter
def context(self, _context):
self._context = _context
if _context is not None:
self.id = self.get_id(_context)
self.definition = self.get_definition(_context)
else:
self.id = None
self.definition = None
def set_values(self, **kwargs): def set_values(self, **kwargs):
for key, value in kwargs.items(): for key, value in kwargs.items():
@ -255,14 +267,24 @@ def state_login_serverbound(context):
# ============== # ==============
class KeepAlivePacket(Packet): class KeepAlivePacket(Packet):
id = 0x00
packet_name = "keep alive" packet_name = "keep alive"
definition = [ definition = [
{'keep_alive_id': VarInt}] {'keep_alive_id': VarInt}]
class KeepAlivePacketClientbound(KeepAlivePacket):
get_id = staticmethod(lambda context:
0x1F if context.protocol_version >= 107 else
0x00)
class KeepAlivePacketServerbound(KeepAlivePacket):
get_id = staticmethod(lambda context:
0x0B if context.protocol_version >= 107 else
0x00)
class JoinGamePacket(Packet): class JoinGamePacket(Packet):
id = 0x01 get_id = staticmethod(lambda context:
0x23 if context.protocol_version >= 107 else
0x01)
packet_name = "join game" packet_name = "join game"
definition = [ definition = [
{'entity_id': Integer}, {'entity_id': Integer},
@ -275,7 +297,9 @@ class JoinGamePacket(Packet):
class ChatMessagePacket(Packet): class ChatMessagePacket(Packet):
id = 0x02 get_id = staticmethod(lambda context:
0x0F if context.protocol_version >= 107 else
0x02)
packet_name = "chat message" packet_name = "chat message"
definition = [ definition = [
{'json_data': String}, {'json_data': String},
@ -283,19 +307,25 @@ class ChatMessagePacket(Packet):
class PlayerPositionAndLookPacket(Packet): class PlayerPositionAndLookPacket(Packet):
id = 0x08 get_id = staticmethod(lambda context:
0x2E if context.protocol_version >= 107 else
0x08)
packet_name = "player position and look" packet_name = "player position and look"
definition = [ get_definition = staticmethod(lambda context: [
{'x': Double}, {'x': Double},
{'y': Double}, {'y': Double},
{'z': Double}, {'z': Double},
{'yaw': Float}, {'yaw': Float},
{'pitch': Float}, {'pitch': Float},
{'flags': Byte}] {'flags': Byte},
{'teleport_id': VarInt} if context.protocol_version >= 107 else {},
])
class DisconnectPacketPlayState(Packet): class DisconnectPacketPlayState(Packet):
id = 0x40 get_id = staticmethod(lambda context:
0x1A if context.protocol_version >= 107 else
0x40)
packet_name = "disconnect" packet_name = "disconnect"
definition = [ definition = [
@ -303,13 +333,16 @@ class DisconnectPacketPlayState(Packet):
class SetCompressionPacketPlayState(Packet): class SetCompressionPacketPlayState(Packet):
# Note: removed between protocol versions 47 and 107.
id = 0x46 id = 0x46
packet_name = "set compression" packet_name = "set compression"
definition = [ definition = [
{'threshold': VarInt}] {'threshold': VarInt}]
class PlayerListItemPacket(Packet): class PlayerListItemPacket(Packet):
id = 0x38 get_id = staticmethod(lambda context:
0x2D if context.protocol_version >= 107 else
0x38)
packet_name = "player list item" packet_name = "player list item"
class PlayerList(object): class PlayerList(object):
@ -434,7 +467,9 @@ class PlayerListItemPacket(Packet):
raise NotImplementedError raise NotImplementedError
class MapPacket(Packet): class MapPacket(Packet):
id = 0x34 get_id = staticmethod(lambda context:
0x24 if context.protocol_version >= 107 else
0x34)
packet_name = 'map' packet_name = 'map'
class MapIcon(object): class MapIcon(object):
@ -450,7 +485,8 @@ class MapPacket(Packet):
return self.__repr__() return self.__repr__()
class Map(object): class Map(object):
__slots__ = 'id', 'scale', 'icons', 'pixels', 'width', 'height' __slots__ = ('id', 'scale', 'icons', 'pixels', 'width', 'height',
'is_tracking_position')
def __init__(self, id=None, scale=None, width=128, height=128): def __init__(self, id=None, scale=None, width=128, height=128):
self.id = id self.id = id
self.scale = scale self.scale = scale
@ -458,6 +494,7 @@ class MapPacket(Packet):
self.width = width self.width = width
self.height = height self.height = height
self.pixels = bytearray(0 for i in range(width*height)) self.pixels = bytearray(0 for i in range(width*height))
self.is_tracking_position = True
def __repr__(self): def __repr__(self):
return ('Map(id=%s, scale=%s, icons=%s, width=%s, height=%s)' return ('Map(id=%s, scale=%s, icons=%s, width=%s, height=%s)'
% (self.id, self.scale, self.icons, self.width, self.height)) % (self.id, self.scale, self.icons, self.width, self.height))
@ -476,6 +513,12 @@ class MapPacket(Packet):
def read(self, file_object): def read(self, file_object):
self.map_id = VarInt.read(file_object) self.map_id = VarInt.read(file_object)
self.scale = Byte.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
icon_count = VarInt.read(file_object) icon_count = VarInt.read(file_object)
self.icons = [] self.icons = []
for i in range(icon_count): for i in range(icon_count):
@ -505,6 +548,7 @@ class MapPacket(Packet):
x = self.offset[0] + i % self.width x = self.offset[0] + i % self.width
z = self.offset[1] + i / self.width z = self.offset[1] + i / self.width
map.pixels[x + map.width * z] = self.pixels[i] map.pixels[x + map.width * z] = self.pixels[i]
map.is_tracking_position = self.is_tracking_position
def apply_to_map_set(self, map_set): def apply_to_map_set(self, map_set):
map = map_set.maps_by_id.get(self.map_id) map = map_set.maps_by_id.get(self.map_id)
@ -525,27 +569,34 @@ class MapPacket(Packet):
return self.__repr__() return self.__repr__()
def state_playing_clientbound(context): def state_playing_clientbound(context):
return { packets = {
KeepAlivePacket, KeepAlivePacketClientbound,
JoinGamePacket, JoinGamePacket,
ChatMessagePacket, ChatMessagePacket,
PlayerPositionAndLookPacket, PlayerPositionAndLookPacket,
MapPacket, MapPacket,
PlayerListItemPacket, PlayerListItemPacket,
DisconnectPacketPlayState, DisconnectPacketPlayState,
SetCompressionPacketPlayState
} }
if context.protocol_version <= 47: packets |= {
SetCompressionPacketPlayState,
}
return packets
class ChatPacket(Packet): class ChatPacket(Packet):
id = 0x01 get_id = staticmethod(lambda context:
0x02 if context.protocol_version >= 107 else
0x01)
packet_name = "chat" packet_name = "chat"
definition = [ definition = [
{'message': String}] {'message': String}]
class PositionAndLookPacket(Packet): class PositionAndLookPacket(Packet):
id = 0x06 get_id = staticmethod(lambda context:
0x0D if context.protocol_version >= 107 else
0x06)
packet_name = "position and look" packet_name = "position and look"
definition = [ definition = [
{'x': Double}, {'x': Double},
@ -558,7 +609,7 @@ class PositionAndLookPacket(Packet):
def state_playing_serverbound(context): def state_playing_serverbound(context):
return { return {
KeepAlivePacket, KeepAlivePacketServerbound,
ChatPacket, ChatPacket,
PositionAndLookPacket PositionAndLookPacket
} }