2018-01-13 02:03:04 +01:00
|
|
|
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),
|
2018-01-13 18:04:39 +01:00
|
|
|
y_coordinate=UnsignedByte.read(file_object),
|
2018-01-13 02:03:04 +01:00
|
|
|
blockData=VarInt.read(file_object))
|
|
|
|
self.records.append(record)
|
|
|
|
|
|
|
|
def write(self, socket, compression_threshold=None):
|
|
|
|
raise NotImplementedError
|