mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2025-04-19 18:46:49 +02:00
fix flake error as suggested
This commit is contained in:
parent
7eef61bfde
commit
2f0dbf5cbb
@ -1,166 +1,6 @@
|
|||||||
# flake8: noqa
|
from .packet import Packet
|
||||||
|
from .packet_buffer import PacketBuffer
|
||||||
from io import BytesIO
|
from .keep_alive_packet import KeepAlivePacket
|
||||||
from zlib import compress
|
|
||||||
|
|
||||||
from minecraft.networking.types import (
|
|
||||||
VarInt
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PacketBuffer(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.bytes = BytesIO()
|
|
||||||
|
|
||||||
def send(self, value):
|
|
||||||
"""
|
|
||||||
Writes the given bytes to the buffer, designed to emulate socket.send
|
|
||||||
:param value: The bytes to write
|
|
||||||
"""
|
|
||||||
self.bytes.write(value)
|
|
||||||
|
|
||||||
def read(self, length=None):
|
|
||||||
return self.bytes.read(length)
|
|
||||||
|
|
||||||
def recv(self, length=None):
|
|
||||||
return self.read(length)
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.bytes = BytesIO()
|
|
||||||
|
|
||||||
def reset_cursor(self):
|
|
||||||
self.bytes.seek(0)
|
|
||||||
|
|
||||||
def get_writable(self):
|
|
||||||
return self.bytes.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
class PacketListener(object):
|
|
||||||
def __init__(self, callback, *args):
|
|
||||||
self.callback = callback
|
|
||||||
self.packets_to_listen = []
|
|
||||||
for arg in args:
|
|
||||||
if issubclass(arg, Packet):
|
|
||||||
self.packets_to_listen.append(arg)
|
|
||||||
|
|
||||||
def call_packet(self, packet):
|
|
||||||
for packet_type in self.packets_to_listen:
|
|
||||||
if isinstance(packet, packet_type):
|
|
||||||
self.callback(packet)
|
|
||||||
|
|
||||||
|
|
||||||
class Packet(object):
|
|
||||||
packet_name = "base"
|
|
||||||
id = None
|
|
||||||
definition = None
|
|
||||||
|
|
||||||
# To define the packet ID, either:
|
|
||||||
# 1. Define the attribute `id', of type int, in a subclass; or
|
|
||||||
# 2. Override `get_id' in a subclass and return the correct packet ID
|
|
||||||
# for the given ConnectionContext. This is necessary if the packet ID
|
|
||||||
# has changed across protocol versions, for example.
|
|
||||||
@classmethod
|
|
||||||
def get_id(cls, context):
|
|
||||||
return cls.id
|
|
||||||
|
|
||||||
# To define the network data layout of a packet, either:
|
|
||||||
# 1. Define the attribute `definition', a list of fields, each of which
|
|
||||||
# is a dict mapping attribute names to data types; or
|
|
||||||
# 2. Override `get_definition' in a subclass and return the correct
|
|
||||||
# definition for the given ConnectionContext. This may be necessary
|
|
||||||
# if the layout has changed across protocol versions, for example; or
|
|
||||||
# 3. Override the methods `read' and/or `write' in a subclass. This may be
|
|
||||||
# necessary if the packet layout cannot be described as a list of
|
|
||||||
# fields.
|
|
||||||
@classmethod
|
|
||||||
def get_definition(cls, context):
|
|
||||||
return cls.definition
|
|
||||||
|
|
||||||
def __init__(self, context=None, **kwargs):
|
|
||||||
self.context = context
|
|
||||||
self.set_values(**kwargs)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def context(self):
|
|
||||||
return self._context
|
|
||||||
|
|
||||||
@context.setter
|
|
||||||
def context(self, _context):
|
|
||||||
self._context = _context
|
|
||||||
self._context_changed()
|
|
||||||
|
|
||||||
def _context_changed(self):
|
|
||||||
if self._context is not None:
|
|
||||||
self.id = self.get_id(self._context)
|
|
||||||
self.definition = self.get_definition(self._context)
|
|
||||||
else:
|
|
||||||
self.id = None
|
|
||||||
self.definition = None
|
|
||||||
|
|
||||||
def set_values(self, **kwargs):
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
setattr(self, key, value)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def read(self, file_object):
|
|
||||||
for field in self.definition:
|
|
||||||
for var_name, data_type in field.items():
|
|
||||||
value = data_type.read(file_object)
|
|
||||||
setattr(self, var_name, value)
|
|
||||||
|
|
||||||
# Writes a packet buffer to the socket with the appropriate headers
|
|
||||||
# and compressing the data if necessary
|
|
||||||
def _write_buffer(self, socket, packet_buffer, compression_threshold):
|
|
||||||
# compression_threshold of None means compression is disabled
|
|
||||||
if compression_threshold is not None:
|
|
||||||
if len(packet_buffer.get_writable()) > compression_threshold != -1:
|
|
||||||
# compress the current payload
|
|
||||||
packet_data = packet_buffer.get_writable()
|
|
||||||
compressed_data = compress(packet_data)
|
|
||||||
packet_buffer.reset()
|
|
||||||
# write out the length of the uncompressed payload
|
|
||||||
VarInt.send(len(packet_data), packet_buffer)
|
|
||||||
# write the compressed payload itself
|
|
||||||
packet_buffer.send(compressed_data)
|
|
||||||
else:
|
|
||||||
# write out a 0 to indicate uncompressed data
|
|
||||||
packet_data = packet_buffer.get_writable()
|
|
||||||
packet_buffer.reset()
|
|
||||||
VarInt.send(0, packet_buffer)
|
|
||||||
packet_buffer.send(packet_data)
|
|
||||||
|
|
||||||
VarInt.send(len(packet_buffer.get_writable()), socket) # Packet Size
|
|
||||||
socket.send(packet_buffer.get_writable()) # Packet Payload
|
|
||||||
|
|
||||||
def write(self, socket, compression_threshold=None):
|
|
||||||
# buffer the data since we need to know the length of each packet's
|
|
||||||
# payload
|
|
||||||
packet_buffer = PacketBuffer()
|
|
||||||
# write packet's id right off the bat in the header
|
|
||||||
VarInt.send(self.id, packet_buffer)
|
|
||||||
# write every individual field
|
|
||||||
for field in self.definition:
|
|
||||||
for var_name, data_type in field.items():
|
|
||||||
data = getattr(self, var_name)
|
|
||||||
data_type.send(data, packet_buffer)
|
|
||||||
|
|
||||||
self._write_buffer(socket, packet_buffer, compression_threshold)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
str = type(self).__name__
|
|
||||||
if self.id is not None:
|
|
||||||
str = '0x%02X %s' % (self.id, str)
|
|
||||||
if self.definition is not None:
|
|
||||||
fields = {a: getattr(self, a) for d in self.definition for a in d}
|
|
||||||
str = '%s %s' % (str, fields)
|
|
||||||
return str
|
|
||||||
|
|
||||||
|
|
||||||
class KeepAlivePacket(Packet):
|
|
||||||
packet_name = "keep alive"
|
|
||||||
definition = [
|
|
||||||
{'keep_alive_id': VarInt}]
|
|
||||||
|
|
||||||
|
|
||||||
# For backward compatibility, re-export any old names from before the change:
|
# For backward compatibility, re-export any old names from before the change:
|
||||||
|
|
||||||
@ -207,3 +47,35 @@ from .serverbound.play import PositionAndLookPacket
|
|||||||
from .serverbound.play import TeleportConfirmPacket
|
from .serverbound.play import TeleportConfirmPacket
|
||||||
from .serverbound.play import AnimationPacket as AnimationPacketServerbound
|
from .serverbound.play import AnimationPacket as AnimationPacketServerbound
|
||||||
from .serverbound.play import get_packets as state_playing_serverbound
|
from .serverbound.play import get_packets as state_playing_serverbound
|
||||||
|
|
||||||
|
__all_legacy_packets__ = [
|
||||||
|
state_handshake_clientbound, HandShakePacket,
|
||||||
|
state_handshake_serverbound, ResponsePacket,
|
||||||
|
PingPacketResponse, state_status_clientbound,
|
||||||
|
RequestPacket, PingPacket, state_status_serverbound,
|
||||||
|
DisconnectPacket, EncryptionRequestPacket, LoginSuccessPacket,
|
||||||
|
SetCompressionPacket, state_login_clientbound,
|
||||||
|
LoginStartPacket, EncryptionResponsePacket,
|
||||||
|
state_login_serverbound, KeepAlivePacketClientbound,
|
||||||
|
KeepAlivePacketServerbound, JoinGamePacket, ChatMessagePacket,
|
||||||
|
PlayerPositionAndLookPacket, DisconnectPacketPlayState,
|
||||||
|
SetCompressionPacketPlayState, PlayerListItemPacket,
|
||||||
|
MapPacket, state_playing_clientbound, ChatPacket,
|
||||||
|
PositionAndLookPacket, TeleportConfirmPacket,
|
||||||
|
AnimationPacketServerbound, state_playing_serverbound,
|
||||||
|
Packet, PacketBuffer, KeepAlivePacket
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PacketListener(object):
|
||||||
|
def __init__(self, callback, *args):
|
||||||
|
self.callback = callback
|
||||||
|
self.packets_to_listen = []
|
||||||
|
for arg in args:
|
||||||
|
if issubclass(arg, Packet):
|
||||||
|
self.packets_to_listen.append(arg)
|
||||||
|
|
||||||
|
def call_packet(self, packet):
|
||||||
|
for packet_type in self.packets_to_listen:
|
||||||
|
if isinstance(packet, packet_type):
|
||||||
|
self.callback(packet)
|
||||||
|
11
minecraft/networking/packets/keep_alive_packet.py
Normal file
11
minecraft/networking/packets/keep_alive_packet.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from .packet import Packet
|
||||||
|
|
||||||
|
from minecraft.networking.types import (
|
||||||
|
VarInt
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KeepAlivePacket(Packet):
|
||||||
|
packet_name = "keep alive"
|
||||||
|
definition = [
|
||||||
|
{'keep_alive_id': VarInt}]
|
112
minecraft/networking/packets/packet.py
Normal file
112
minecraft/networking/packets/packet.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from .packet_buffer import PacketBuffer
|
||||||
|
from zlib import compress
|
||||||
|
from minecraft.networking.types import (
|
||||||
|
VarInt
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Packet(object):
|
||||||
|
packet_name = "base"
|
||||||
|
id = None
|
||||||
|
definition = None
|
||||||
|
|
||||||
|
# To define the packet ID, either:
|
||||||
|
# 1. Define the attribute `id', of type int, in a subclass; or
|
||||||
|
# 2. Override `get_id' in a subclass and return the correct packet ID
|
||||||
|
# for the given ConnectionContext. This is necessary if the packet ID
|
||||||
|
# has changed across protocol versions, for example.
|
||||||
|
@classmethod
|
||||||
|
def get_id(cls, context):
|
||||||
|
return cls.id
|
||||||
|
|
||||||
|
# To define the network data layout of a packet, either:
|
||||||
|
# 1. Define the attribute `definition', a list of fields, each of which
|
||||||
|
# is a dict mapping attribute names to data types; or
|
||||||
|
# 2. Override `get_definition' in a subclass and return the correct
|
||||||
|
# definition for the given ConnectionContext. This may be necessary
|
||||||
|
# if the layout has changed across protocol versions, for example; or
|
||||||
|
# 3. Override the methods `read' and/or `write' in a subclass. This may be
|
||||||
|
# necessary if the packet layout cannot be described as a list of
|
||||||
|
# fields.
|
||||||
|
@classmethod
|
||||||
|
def get_definition(cls, context):
|
||||||
|
return cls.definition
|
||||||
|
|
||||||
|
def __init__(self, context=None, **kwargs):
|
||||||
|
self.context = context
|
||||||
|
self.set_values(**kwargs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self):
|
||||||
|
return self._context
|
||||||
|
|
||||||
|
@context.setter
|
||||||
|
def context(self, _context):
|
||||||
|
self._context = _context
|
||||||
|
self._context_changed()
|
||||||
|
|
||||||
|
def _context_changed(self):
|
||||||
|
if self._context is not None:
|
||||||
|
self.id = self.get_id(self._context)
|
||||||
|
self.definition = self.get_definition(self._context)
|
||||||
|
else:
|
||||||
|
self.id = None
|
||||||
|
self.definition = None
|
||||||
|
|
||||||
|
def set_values(self, **kwargs):
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
setattr(self, key, value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def read(self, file_object):
|
||||||
|
for field in self.definition:
|
||||||
|
for var_name, data_type in field.items():
|
||||||
|
value = data_type.read(file_object)
|
||||||
|
setattr(self, var_name, value)
|
||||||
|
|
||||||
|
# Writes a packet buffer to the socket with the appropriate headers
|
||||||
|
# and compressing the data if necessary
|
||||||
|
def _write_buffer(self, socket, packet_buffer, compression_threshold):
|
||||||
|
# compression_threshold of None means compression is disabled
|
||||||
|
if compression_threshold is not None:
|
||||||
|
if len(packet_buffer.get_writable()) > compression_threshold != -1:
|
||||||
|
# compress the current payload
|
||||||
|
packet_data = packet_buffer.get_writable()
|
||||||
|
compressed_data = compress(packet_data)
|
||||||
|
packet_buffer.reset()
|
||||||
|
# write out the length of the uncompressed payload
|
||||||
|
VarInt.send(len(packet_data), packet_buffer)
|
||||||
|
# write the compressed payload itself
|
||||||
|
packet_buffer.send(compressed_data)
|
||||||
|
else:
|
||||||
|
# write out a 0 to indicate uncompressed data
|
||||||
|
packet_data = packet_buffer.get_writable()
|
||||||
|
packet_buffer.reset()
|
||||||
|
VarInt.send(0, packet_buffer)
|
||||||
|
packet_buffer.send(packet_data)
|
||||||
|
|
||||||
|
VarInt.send(len(packet_buffer.get_writable()), socket) # Packet Size
|
||||||
|
socket.send(packet_buffer.get_writable()) # Packet Payload
|
||||||
|
|
||||||
|
def write(self, socket, compression_threshold=None):
|
||||||
|
# buffer the data since we need to know the length of each packet's
|
||||||
|
# payload
|
||||||
|
packet_buffer = PacketBuffer()
|
||||||
|
# write packet's id right off the bat in the header
|
||||||
|
VarInt.send(self.id, packet_buffer)
|
||||||
|
# write every individual field
|
||||||
|
for field in self.definition:
|
||||||
|
for var_name, data_type in field.items():
|
||||||
|
data = getattr(self, var_name)
|
||||||
|
data_type.send(data, packet_buffer)
|
||||||
|
|
||||||
|
self._write_buffer(socket, packet_buffer, compression_threshold)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
str = type(self).__name__
|
||||||
|
if self.id is not None:
|
||||||
|
str = '0x%02X %s' % (self.id, str)
|
||||||
|
if self.definition is not None:
|
||||||
|
fields = {a: getattr(self, a) for d in self.definition for a in d}
|
||||||
|
str = '%s %s' % (str, fields)
|
||||||
|
return str
|
28
minecraft/networking/packets/packet_buffer.py
Normal file
28
minecraft/networking/packets/packet_buffer.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
|
||||||
|
class PacketBuffer(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.bytes = BytesIO()
|
||||||
|
|
||||||
|
def send(self, value):
|
||||||
|
"""
|
||||||
|
Writes the given bytes to the buffer, designed to emulate socket.send
|
||||||
|
:param value: The bytes to write
|
||||||
|
"""
|
||||||
|
self.bytes.write(value)
|
||||||
|
|
||||||
|
def read(self, length=None):
|
||||||
|
return self.bytes.read(length)
|
||||||
|
|
||||||
|
def recv(self, length=None):
|
||||||
|
return self.read(length)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.bytes = BytesIO()
|
||||||
|
|
||||||
|
def reset_cursor(self):
|
||||||
|
self.bytes.seek(0)
|
||||||
|
|
||||||
|
def get_writable(self):
|
||||||
|
return self.bytes.getvalue()
|
Loading…
Reference in New Issue
Block a user