Add support for Minecraft snapshots 17w43a-18w02a (protocol 341-353).

Add support declaration for Minecraft version 1.8.9 (protocol 47).
This commit is contained in:
joo 2018-01-13 01:03:04 +00:00
parent 258c1f2566
commit f492adfeff
10 changed files with 171 additions and 92 deletions

View File

@ -23,7 +23,7 @@ Supported Minecraft versions
----------------------------
pyCraft is compatible with the following Minecraft releases:
* 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 1.8.7, 1.8.8
* 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 1.8.7, 1.8.8, 1.8.9
* 1.9, 1.9.1, 1.9.2, 1.9.3, 1.9.4
* 1.10, 1.10.1, 1.10.2
* 1.11, 1.11.1, 1.11.2

View File

@ -15,6 +15,7 @@ SUPPORTED_MINECRAFT_VERSIONS = {
'1.8.6': 47,
'1.8.7': 47,
'1.8.8': 47,
'1.8.9': 47,
'1.9': 107,
'1.9.1': 108,
'1.9.2': 109,
@ -67,6 +68,19 @@ SUPPORTED_MINECRAFT_VERSIONS = {
'1.12.2-pre1': 339,
'1.12.2-pre2': 339,
'1.12.2': 340,
'17w43a': 341,
'17w43b': 342,
'17w45a': 343,
'17w45b': 344,
'17w46a': 345,
'17w47a': 346,
'17w47b': 347,
'17w48a': 348,
'17w49a': 349,
'17w49b': 350,
'17w50a': 351,
'18w01a': 352,
'18w02a': 353,
}
SUPPORTED_PROTOCOL_VERSIONS = \

View File

@ -1,5 +1,5 @@
from minecraft.networking.packets import (
Packet, PacketBuffer, AbstractKeepAlivePacket, AbstractPluginMessagePacket
Packet, AbstractKeepAlivePacket, AbstractPluginMessagePacket
)
from minecraft.networking.types import (
@ -12,6 +12,7 @@ from .map_packet import MapPacket
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
# Formerly known as state_playing_clientbound.
@ -44,7 +45,8 @@ def get_packets(context):
class KeepAlivePacket(AbstractKeepAlivePacket):
@staticmethod
def get_id(context):
return 0x1F if context.protocol_version >= 332 else \
return 0x20 if context.protocol_version >= 345 else \
0x1F if context.protocol_version >= 332 else \
0x20 if context.protocol_version >= 318 else \
0x1F if context.protocol_version >= 107 else \
0x00
@ -53,7 +55,8 @@ class KeepAlivePacket(AbstractKeepAlivePacket):
class JoinGamePacket(Packet):
@staticmethod
def get_id(context):
return 0x23 if context.protocol_version >= 332 else \
return 0x24 if context.protocol_version >= 345 else \
0x23 if context.protocol_version >= 332 else \
0x24 if context.protocol_version >= 318 else \
0x23 if context.protocol_version >= 107 else \
0x01
@ -72,7 +75,8 @@ class JoinGamePacket(Packet):
class ChatMessagePacket(Packet):
@staticmethod
def get_id(context):
return 0x0F if context.protocol_version >= 332 else \
return 0x0E if context.protocol_version >= 343 else \
0x0F if context.protocol_version >= 332 else \
0x10 if context.protocol_version >= 317 else \
0x0F if context.protocol_version >= 107 else \
0x02
@ -91,7 +95,8 @@ class ChatMessagePacket(Packet):
class DisconnectPacket(Packet):
@staticmethod
def get_id(context):
return 0x1A if context.protocol_version >= 332 else \
return 0x1B if context.protocol_version >= 345 else \
0x1A if context.protocol_version >= 332 else \
0x1B if context.protocol_version >= 318 else \
0x1A if context.protocol_version >= 107 else \
0x40
@ -133,7 +138,9 @@ class SpawnPlayerPacket(Packet):
class EntityVelocityPacket(Packet):
@staticmethod
def get_id(context):
return 0x3E if context.protocol_version >= 336 else \
return 0x40 if context.protocol_version >= 352 else \
0x3F if context.protocol_version >= 345 else \
0x3E if context.protocol_version >= 336 else \
0x3D if context.protocol_version >= 332 else \
0x3B if context.protocol_version >= 86 else \
0x3C if context.protocol_version >= 77 else \
@ -152,7 +159,9 @@ class EntityVelocityPacket(Packet):
class UpdateHealthPacket(Packet):
@staticmethod
def get_id(context):
return 0x41 if context.protocol_version >= 336 else \
return 0x43 if context.protocol_version >= 352 else \
0x42 if context.protocol_version >= 345 else \
0x41 if context.protocol_version >= 336 else \
0x40 if context.protocol_version >= 318 else \
0x3E if context.protocol_version >= 86 else \
0x3F if context.protocol_version >= 77 else \
@ -170,7 +179,8 @@ class UpdateHealthPacket(Packet):
class ExplosionPacket(Packet):
@staticmethod
def get_id(context):
return 0x1C if context.protocol_version >= 332 else \
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 \
@ -202,81 +212,11 @@ class ExplosionPacket(Packet):
raise NotImplementedError
class BlockChangePacket(Packet):
@staticmethod
def get_id(context):
return 0x0B if context.protocol_version >= 332 else \
0x0C if context.protocol_version >= 318 else \
0x0B if context.protocol_version >= 67 else \
0x24 if context.protocol_version >= 62 else \
0x23
packet_name = 'block change'
def read(self, file_object):
self.location = Position.read(file_object)
blockData = VarInt.read(file_object)
self.blockId = (blockData >> 4)
self.blockMeta = (blockData & 0xF)
def write(self, socket, compression_threshold=None):
packet_buffer = PacketBuffer()
(x, y, z) = self.location
Position.send(x, y, z, packet_buffer)
blockData = ((self.blockId << 4) | (self.blockMeta & 0xF))
VarInt.send(blockData)
self._write_buffer(socket, packet_buffer, compression_threshold)
class MultiBlockChangePacket(Packet):
@staticmethod
def get_id(context):
return 0x10 if context.protocol_version >= 332 else \
0x11 if context.protocol_version >= 318 else \
0x10 if context.protocol_version >= 67 else \
0x22
packet_name = 'multi block change'
class Record(object):
__slots__ = 'x', 'y', 'z', 'blockId', 'blockMeta'
def __init__(self, horizontal_position, y_coordinate, blockData):
self.x = (horizontal_position & 0xF0) >> 4
self.y = y_coordinate
self.z = (horizontal_position & 0x0F)
self.blockId = (blockData >> 4)
self.blockMeta = (blockData & 0xF)
def __repr__(self):
return ('Record(x=%s, y=%s, z=%s, blockId=%s)'
% (self.x, self.y, self.z, self.blockId))
def __str__(self):
return self.__repr__()
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)
self.records = []
for i in range(records_count):
rec_horizontal_position = UnsignedByte.read(file_object)
rec_y_coordinate = UnsignedByte.read(file_object)
rec_blockData = VarInt.read(file_object)
record = MultiBlockChangePacket.Record(
rec_horizontal_position,
rec_y_coordinate, rec_blockData)
self.records.append(record)
def write(self, socket, compression_threshold=None):
raise NotImplementedError
class PluginMessagePacket(AbstractPluginMessagePacket):
@staticmethod
def get_id(context):
return 0x18 if context.protocol_version >= 332 else \
return 0x19 if context.protocol_version >= 345 else \
0x18 if context.protocol_version >= 332 else \
0x19 if context.protocol_version >= 318 else \
0x18 if context.protocol_version >= 70 else \
0x3F

View File

@ -0,0 +1,109 @@
from minecraft.networking.packets import (
Packet, PacketBuffer
)
from minecraft.networking.types import (
VarInt, Integer, UnsignedByte, Position
)
class BlockChangePacket(Packet):
@staticmethod
def get_id(context):
return 0x0B if context.protocol_version >= 332 else \
0x0C if context.protocol_version >= 318 else \
0x0B if context.protocol_version >= 67 else \
0x24 if context.protocol_version >= 62 else \
0x23
packet_name = 'block change'
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)
def write(self, socket, compression_threshold=None):
packet_buffer = PacketBuffer()
(x, y, z) = self.location
Position.send(x, y, z, packet_buffer)
blockData = ((self.blockId << 4) | (self.blockMeta & 0xF))
VarInt.send(blockData)
self._write_buffer(socket, packet_buffer, compression_threshold)
class MultiBlockChangePacket(Packet):
@staticmethod
def get_id(context):
return 0x0F if context.protocol_version >= 343 else \
0x10 if context.protocol_version >= 332 else \
0x11 if context.protocol_version >= 318 else \
0x10 if context.protocol_version >= 67 else \
0x22
packet_name = 'multi block change'
class BaseRecord(object):
__slots__ = 'x', 'y', 'z'
def __init__(self, horizontal_position, y_coordinate):
self.x = (horizontal_position & 0xF0) >> 4
self.y = y_coordinate
self.z = (horizontal_position & 0x0F)
def __str__(self):
return self.__repr__()
@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 __repr__(self):
return ('Record(x=%s, y=%s, z=%s, blockId=%s)'
% (self.x, self.y, self.z, self.blockId))
'''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 __init__(self, h_position, y_coordinate, blockData):
super(MultiBlockChangePacket.OpaqueRecord, self).__init__(
h_position, y_coordinate)
self.blockStateId = blockData
def __repr__(self):
return ('OpaqueRecord(x=%s, y=%s, z=%s, blockStateId=%s)'
% (self.x, self.y, self.z, self.blockStateId))
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=VarInt.read(file_object),
blockData=VarInt.read(file_object))
self.records.append(record)
def write(self, socket, compression_threshold=None):
raise NotImplementedError

View File

@ -8,7 +8,8 @@ from minecraft.networking.types import (
class CombatEventPacket(Packet):
@staticmethod
def get_id(context):
return 0x2D if context.protocol_version >= 336 else \
return 0x2E if context.protocol_version >= 345 else \
0x2D if context.protocol_version >= 336 else \
0x2C if context.protocol_version >= 332 else \
0x2D if context.protocol_version >= 318 else \
0x2C if context.protocol_version >= 86 else \

View File

@ -10,7 +10,8 @@ from minecraft.networking.types import (
class MapPacket(Packet):
@staticmethod
def get_id(context):
return 0x24 if context.protocol_version >= 334 else \
return 0x25 if context.protocol_version >= 345 else \
0x24 if context.protocol_version >= 334 else \
0x25 if context.protocol_version >= 318 else \
0x24 if context.protocol_version >= 107 else \
0x34

View File

@ -8,7 +8,8 @@ from minecraft.networking.types import (
class PlayerListItemPacket(Packet):
@staticmethod
def get_id(context):
return 0x2E if context.protocol_version >= 336 else \
return 0x2F if context.protocol_version >= 345 else \
0x2E if context.protocol_version >= 336 else \
0x2D if context.protocol_version >= 332 else \
0x2E if context.protocol_version >= 318 else \
0x2D if context.protocol_version >= 107 else \

View File

@ -8,7 +8,9 @@ from minecraft.networking.types import (
class PlayerPositionAndLookPacket(Packet, BitFieldEnum):
@staticmethod
def get_id(context):
return 0x2F if context.protocol_version >= 336 else \
return 0x31 if context.protocol_version >= 352 else \
0x30 if context.protocol_version >= 345 else \
0x2F if context.protocol_version >= 336 else \
0x2E if context.protocol_version >= 332 else \
0x2F if context.protocol_version >= 318 else \
0x2E if context.protocol_version >= 70 else \

View File

@ -30,7 +30,9 @@ def get_packets(context):
class KeepAlivePacket(AbstractKeepAlivePacket):
@staticmethod
def get_id(context):
return 0x0B if context.protocol_version >= 336 else \
return 0x0B if context.protocol_version >= 345 else \
0x0A if context.protocol_version >= 343 else \
0x0B if context.protocol_version >= 336 else \
0x0C if context.protocol_version >= 318 else \
0x0B if context.protocol_version >= 107 else \
0x00
@ -39,7 +41,8 @@ class KeepAlivePacket(AbstractKeepAlivePacket):
class ChatPacket(Packet):
@staticmethod
def get_id(context):
return 0x02 if context.protocol_version >= 336 else \
return 0x01 if context.protocol_version >= 343 else \
0x02 if context.protocol_version >= 336 else \
0x03 if context.protocol_version >= 318 else \
0x02 if context.protocol_version >= 107 else \
0x01
@ -62,7 +65,9 @@ class ChatPacket(Packet):
class PositionAndLookPacket(Packet):
@staticmethod
def get_id(context):
return 0x0E if context.protocol_version >= 336 else \
return 0x0E if context.protocol_version >= 345 else \
0x0D if context.protocol_version >= 343 else \
0x0E if context.protocol_version >= 336 else \
0x0F if context.protocol_version >= 332 else \
0x0E if context.protocol_version >= 318 else \
0x0D if context.protocol_version >= 107 else \
@ -89,7 +94,9 @@ class TeleportConfirmPacket(Packet):
class AnimationPacket(Packet, Enum):
@staticmethod
def get_id(context):
return 0x1D if context.protocol_version >= 332 else \
return 0x1D if context.protocol_version >= 345 else \
0x1C if context.protocol_version >= 343 else \
0x1D if context.protocol_version >= 332 else \
0x1C if context.protocol_version >= 318 else \
0x1A if context.protocol_version >= 107 else \
0x0A
@ -107,7 +114,8 @@ class AnimationPacket(Packet, Enum):
class ClientStatusPacket(Packet, Enum):
@staticmethod
def get_id(context):
return 0x03 if context.protocol_version >= 336 else \
return 0x02 if context.protocol_version >= 343 else \
0x03 if context.protocol_version >= 336 else \
0x04 if context.protocol_version >= 318 else \
0x03 if context.protocol_version >= 80 else \
0x02 if context.protocol_version >= 67 else \
@ -129,7 +137,9 @@ class ClientStatusPacket(Packet, Enum):
class PluginMessagePacket(AbstractPluginMessagePacket):
@staticmethod
def get_id(context):
return 0x09 if context.protocol_version >= 336 else \
return 0x09 if context.protocol_version >= 345 else \
0x08 if context.protocol_version >= 343 else \
0x09 if context.protocol_version >= 336 else \
0x0A if context.protocol_version >= 317 else \
0x09 if context.protocol_version >= 94 else \
0x17

View File

@ -7,7 +7,8 @@ from minecraft.networking.types import (
class ClientSettingsPacket(Packet):
@staticmethod
def get_id(context):
return 0x04 if context.protocol_version >= 336 else \
return 0x03 if context.protocol_version >= 343 else \
0x04 if context.protocol_version >= 336 else \
0x05 if context.protocol_version >= 318 else \
0x04 if context.protocol_version >= 94 else \
0x15