This commit is contained in:
Advik 2022-04-14 04:29:19 +00:00 committed by GitHub
commit 30234a991a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 211 additions and 224 deletions

View File

@ -11,7 +11,7 @@ pyCraft
Minecraft Python Client Library!
This projects aims to be a modern, Python3-compatible, well-documented library for
communication with a MineCraft server.
communication with a Minecraft server.
Detailed information for developers can be found here:
`<http://pycraft.readthedocs.org/en/latest/>`_.

View File

@ -13,7 +13,7 @@ print("language: python")
print("python: 3.5")
print("env:")
for env in parseconfig(None, 'tox').envlist:
print(" - TOX_ENV=%s" % env)
print(f" - TOX_ENV={env}")
print("install:")
print(" - pip install tox")
print(" - pip install python-coveralls")

View File

@ -31,8 +31,7 @@ class Profile(object):
raise AttributeError("Profile is not yet populated.")
def __bool__(self):
bool_state = self.id_ is not None and self.name is not None
return bool_state
return self.id_ is not None and self.name is not None
# Python 2 support
def __nonzero__(self):
@ -277,9 +276,12 @@ def _make_request(server, endpoint, data):
Returns:
A `requests.Request` object.
"""
res = requests.post(server + "/" + endpoint, data=json.dumps(data),
headers=HEADERS, timeout=15)
return res
return requests.post(
f"{server}/{endpoint}",
data=json.dumps(data),
headers=HEADERS,
timeout=15,
)
def _raise_from_response(res):
@ -295,7 +297,7 @@ def _raise_from_response(res):
try:
json_resp = res.json()
if not ("error" in json_resp and "errorMessage" in json_resp):
if "error" not in json_resp or "errorMessage" not in json_resp:
raise ValueError
except ValueError:
message = "[{status_code}] Malformed error message: '{response_text}'"

View File

@ -269,10 +269,16 @@ class Connection(object):
"""
outgoing = kwds.pop('outgoing', False)
early = kwds.pop('early', False)
target = self.packet_listeners if not early and not outgoing \
else self.early_packet_listeners if early and not outgoing \
else self.outgoing_packet_listeners if not early \
target = (
self.packet_listeners
if not early and not outgoing
else self.early_packet_listeners
if early and not outgoing
else self.early_outgoing_packet_listeners
if early
else self.outgoing_packet_listeners
)
target.append(packets.PacketListener(method, *packet_types, **kwds))
def register_exception_handler(self, handler_func, *exc_types, **kwds):
@ -314,19 +320,10 @@ class Connection(object):
self._exception_handlers.append((handler_func, exc_types))
def _pop_packet(self):
# Pops the topmost packet off the outgoing queue and writes it out
# through the socket
#
# Mostly an internal convenience function, caller should make sure
# they have the write lock acquired to avoid issues caused by
# asynchronous access to the socket.
# This should be the only method that removes elements from the
# outbound queue
if len(self._outgoing_packet_queue) == 0:
return False
else:
self._write_packet(self._outgoing_packet_queue.popleft())
return True
self._write_packet(self._outgoing_packet_queue.popleft())
return True
def _write_packet(self, packet):
# Immediately writes the given packet to the network. The caller must
@ -543,11 +540,12 @@ class Connection(object):
server_protocol = KNOWN_MINECRAFT_VERSIONS.get(server_version)
if server_protocol is None:
vs = 'version' if server_version is None else \
('version of %s' % server_version)
vs = 'version' if server_version is None else f'version of {server_version}'
else:
vs = ('protocol version of %d' % server_protocol) + \
('' if server_version is None else ' (%s)' % server_version)
vs = 'protocol version of %d' % server_protocol + (
'' if server_version is None else f' ({server_version})'
)
ss = 'supported, but not allowed for this connection' \
if server_protocol in SUPPORTED_PROTOCOL_VERSIONS \
else 'not supported'
@ -615,11 +613,7 @@ class NetworkingThread(threading.Thread):
# If any packets remain to be written, resume writing as soon
# as possible after reading any available packets; otherwise,
# wait for up to 50ms (1 tick) for new packets to arrive.
if self.connection._outgoing_packet_queue:
read_timeout = 0
else:
read_timeout = 0.05
read_timeout = 0 if self.connection._outgoing_packet_queue else 0.05
# Read and react to as many as 50 packets.
while num_packets < 50 and not self.interrupt:
packet = self.connection.reactor.read_packet(
@ -658,49 +652,44 @@ class PacketReactor(object):
for packet in self.__class__.get_clientbound_packets(context)}
def read_packet(self, stream, timeout=0):
# Block for up to `timeout' seconds waiting for `stream' to become
# readable, returning `None' if the timeout elapses.
ready_to_read = select.select([stream], [], [], timeout)[0]
if ready_to_read:
length = VarInt.read(stream)
packet_data = packets.PacketBuffer()
packet_data.send(stream.read(length))
# Ensure we read all the packet
while len(packet_data.get_writable()) < length:
packet_data.send(
stream.read(length - len(packet_data.get_writable())))
packet_data.reset_cursor()
if self.connection.options.compression_enabled:
decompressed_size = VarInt.read(packet_data)
if decompressed_size > 0:
decompressor = zlib.decompressobj()
decompressed_packet = decompressor.decompress(
packet_data.read())
assert len(decompressed_packet) == decompressed_size, \
'decompressed length %d, but expected %d' % \
(len(decompressed_packet), decompressed_size)
packet_data.reset()
packet_data.send(decompressed_packet)
packet_data.reset_cursor()
packet_id = VarInt.read(packet_data)
# If we know the structure of the packet, attempt to parse it
# otherwise, just return an instance of the base Packet class.
if packet_id in self.clientbound_packets:
packet = self.clientbound_packets[packet_id]()
packet.context = self.connection.context
packet.read(packet_data)
else:
packet = packets.Packet()
packet.context = self.connection.context
packet.id = packet_id
return packet
else:
if not (ready_to_read := select.select([stream], [], [], timeout)[0]):
return None
length = VarInt.read(stream)
packet_data = packets.PacketBuffer()
packet_data.send(stream.read(length))
# Ensure we read all the packet
while len(packet_data.get_writable()) < length:
packet_data.send(
stream.read(length - len(packet_data.get_writable())))
packet_data.reset_cursor()
if self.connection.options.compression_enabled:
decompressed_size = VarInt.read(packet_data)
if decompressed_size > 0:
decompressor = zlib.decompressobj()
decompressed_packet = decompressor.decompress(
packet_data.read())
assert len(decompressed_packet) == decompressed_size, \
'decompressed length %d, but expected %d' % \
(len(decompressed_packet), decompressed_size)
packet_data.reset()
packet_data.send(decompressed_packet)
packet_data.reset_cursor()
packet_id = VarInt.read(packet_data)
# If we know the structure of the packet, attempt to parse it
# otherwise, just return an instance of the base Packet class.
if packet_id in self.clientbound_packets:
packet = self.clientbound_packets[packet_id]()
packet.context = self.connection.context
packet.read(packet_data)
else:
packet = packets.Packet()
packet.context = self.connection.context
packet.id = packet_id
return packet
def react(self, packet):
"""Called with each incoming packet after early packet listeners are
@ -760,9 +749,11 @@ class LoginReactor(PacketReactor):
msg = json.loads(packet.json_data)['text']
except (ValueError, TypeError, KeyError):
msg = packet.json_data
match = re.match(r"Outdated (client! Please use|server!"
r" I'm still on) (?P<ver>\S+)$", msg)
if match:
if match := re.match(
r"Outdated (client! Please use|server!"
r" I'm still on) (?P<ver>\S+)$",
msg,
):
ver = match.group('ver')
self.connection._version_mismatch(server_version=ver)
raise LoginDisconnect('The server rejected our login attempt '

View File

@ -11,9 +11,11 @@ def generate_shared_secret():
def create_AES_cipher(shared_secret):
cipher = Cipher(algorithms.AES(shared_secret), modes.CFB8(shared_secret),
backend=default_backend())
return cipher
return Cipher(
algorithms.AES(shared_secret),
modes.CFB8(shared_secret),
backend=default_backend(),
)
def encrypt_token_and_secret(pubkey, verification_token, shared_secret):

View File

@ -128,7 +128,7 @@ class MultiBlockChangePacket(Packet):
return record
@classmethod
def send_with_context(self, record, socket, context):
def send_with_context(cls, record, socket, context):
if context.protocol_later_eq(741):
value = record.block_state_id << 12 | \
(record.x & 0xF) << 8 | \

View File

@ -55,7 +55,7 @@ class CombatEventPacket(Packet):
def type_from_id(cls, event_id):
subcls = cls.type_from_id_dict.get(event_id)
if subcls is None:
raise ValueError('Unknown combat event ID: %s.' % event_id)
raise ValueError(f'Unknown combat event ID: {event_id}.')
return subcls
class EnterCombatEvent(EventType):

View File

@ -28,7 +28,7 @@ class ExplosionPacket(Packet):
@classmethod
def read(cls, file_object):
return cls(*(Byte.read(file_object) for i in range(3)))
return cls(*(Byte.read(file_object) for _ in range(3)))
@classmethod
def send(cls, record, socket):

View File

@ -34,8 +34,7 @@ class FacePlayerPacket(Packet):
self.x = Double.read(file_object)
self.y = Double.read(file_object)
self.z = Double.read(file_object)
is_entity = Boolean.read(file_object)
if is_entity:
if is_entity := Boolean.read(file_object):
# If the entity given by entity ID cannot be found,
# this packet should be treated as if is_entity was false.
self.entity_id = VarInt.read(file_object)
@ -64,15 +63,15 @@ class FacePlayerPacket(Packet):
else:
Boolean.send(False, packet_buffer)
else: # Protocol version 352
if self.entity_id is not None:
Boolean.send(True, packet_buffer)
VarInt.send(self.entity_id, packet_buffer)
else:
Boolean.send(False, packet_buffer)
Double.send(self.x, packet_buffer)
Double.send(self.y, packet_buffer)
Double.send(self.z, packet_buffer)
elif self.entity_id is None:
Boolean.send(False, packet_buffer)
Double.send(self.x, packet_buffer)
Double.send(self.y, packet_buffer)
Double.send(self.z, packet_buffer)
else:
Boolean.send(True, packet_buffer)
VarInt.send(self.entity_id, packet_buffer)
# These aliases declare the Enum type corresponding to each field:
Origin = OriginPoint

View File

@ -26,8 +26,7 @@ def nbt_to_snbt(tag):
pynbt.TAG_Long_Array: 'L',
}
if type(tag) in arrays:
return '[' + arrays[type(tag)] + ';' + \
','.join(map(repr, tag.value)) + ']'
return ((f'[{arrays[type(tag)]};' + ','.join(map(repr, tag.value))) + ']')
if isinstance(tag, pynbt.TAG_String):
return repr(tag.value)
@ -36,8 +35,10 @@ def nbt_to_snbt(tag):
return '[' + ','.join(map(nbt_to_snbt, tag.value)) + ']'
if isinstance(tag, pynbt.TAG_Compound):
return '{' + ','.join(n + ':' + nbt_to_snbt(v)
for (n, v) in tag.items()) + '}'
return (
'{' + ','.join(f'{n}:{nbt_to_snbt(v)}' for (n, v) in tag.items())
) + '}'
raise TypeError('Unknown NBT tag type: %r' % type(tag))

View File

@ -55,7 +55,7 @@ class MapPacket(Packet):
self.icons = []
self.width = width
self.height = height
self.pixels = bytearray(0 for i in range(width*height))
self.pixels = bytearray(0 for _ in range(width*height))
self.is_tracking_position = True
self.is_locked = False
@ -67,7 +67,7 @@ class MapPacket(Packet):
def __repr__(self):
maps = (repr(map) for map in self.maps_by_id.values())
return 'MapSet(%s)' % ', '.join(maps)
return f"MapSet({', '.join(maps)})"
def read(self, file_object):
self.map_id = VarInt.read(file_object)
@ -88,7 +88,7 @@ class MapPacket(Packet):
icon_count = VarInt.read(file_object)
self.icons = []
for i in range(icon_count):
for _ in range(icon_count):
if self.context.protocol_later_eq(373):
type = VarInt.read(file_object)
else:

View File

@ -48,8 +48,7 @@ class PlayerListItemPacket(Packet):
def read(self, file_object):
self.name = String.read(file_object)
self.value = String.read(file_object)
is_signed = Boolean.read(file_object)
if is_signed:
if is_signed := Boolean.read(file_object):
self.signature = String.read(file_object)
else:
self.signature = None
@ -87,7 +86,7 @@ class PlayerListItemPacket(Packet):
for subcls in cls.__subclasses__():
if subcls.action_id == action_id:
return subcls
raise ValueError("Unknown player list action ID: %s." % action_id)
raise ValueError(f"Unknown player list action ID: {action_id}.")
class AddPlayerAction(Action):
__slots__ = 'name', 'properties', 'gamemode', 'ping', 'display_name'
@ -103,8 +102,7 @@ class PlayerListItemPacket(Packet):
self.properties.append(property)
self.gamemode = VarInt.read(file_object)
self.ping = VarInt.read(file_object)
has_display_name = Boolean.read(file_object)
if has_display_name:
if has_display_name := Boolean.read(file_object):
self.display_name = String.read(file_object)
else:
self.display_name = None
@ -143,8 +141,7 @@ class PlayerListItemPacket(Packet):
VarInt.send(self.gamemode, packet_buffer)
def apply(self, player_list):
player = player_list.players_by_uuid.get(self.uuid)
if player:
if player := player_list.players_by_uuid.get(self.uuid):
player.gamemode = self.gamemode
class UpdateLatencyAction(Action):
@ -158,8 +155,7 @@ class PlayerListItemPacket(Packet):
VarInt.send(self.ping, packet_buffer)
def apply(self, player_list):
player = player_list.players_by_uuid.get(self.uuid)
if player:
if player := player_list.players_by_uuid.get(self.uuid):
player.ping = self.ping
class UpdateDisplayNameAction(Action):
@ -167,8 +163,7 @@ class PlayerListItemPacket(Packet):
action_id = 3
def _read(self, file_object):
has_display_name = Boolean.read(file_object)
if has_display_name:
if has_display_name := Boolean.read(file_object):
self.display_name = String.read(file_object)
else:
self.display_name = None
@ -181,8 +176,7 @@ class PlayerListItemPacket(Packet):
Boolean.send(False, packet_buffer)
def apply(self, player_list):
player = player_list.players_by_uuid.get(self.uuid)
if player:
if player := player_list.players_by_uuid.get(self.uuid):
player.display_name = self.display_name
class RemovePlayerAction(Action):
@ -203,7 +197,7 @@ class PlayerListItemPacket(Packet):
self.action_type = PlayerListItemPacket.Action.type_from_id(action_id)
action_count = VarInt.read(file_object)
self.actions = []
for i in range(action_count):
for _ in range(action_count):
action = self.action_type()
action.read(file_object)
self.actions.append(action)

View File

@ -62,7 +62,7 @@ class SoundEffectPacket(Packet):
class EffectPosition(Type):
@classmethod
def read(cls, file_object):
return Vector(*(Integer.read(file_object) / 8.0 for i in range(3)))
return Vector(*(Integer.read(file_object) / 8.0 for _ in range(3)))
@classmethod
def send(cls, value, socket):

View File

@ -7,11 +7,10 @@ from minecraft.networking.types import (
# Formerly known as state_status_clientbound.
def get_packets(context):
packets = {
return {
ResponsePacket,
PingResponsePacket,
}
return packets
class ResponsePacket(Packet):

View File

@ -117,9 +117,11 @@ class Packet(object):
str = '0x%02X %s' % (self.id, str)
fields = self.fields
if fields is not None:
inner_str = ', '.join('%s=%s' % (a, self.field_string(a))
for a in fields if hasattr(self, a))
str = '%s(%s)' % (str, inner_str)
inner_str = ', '.join(
f'{a}={self.field_string(a)}' for a in fields if hasattr(self, a)
)
str = f'{str}({inner_str})'
return str
@property

View File

@ -4,10 +4,7 @@ from .packet import Packet
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)
self.packets_to_listen = [arg for arg in args if issubclass(arg, Packet)]
def call_packet(self, packet):
for packet_type in self.packets_to_listen:

View File

@ -7,10 +7,7 @@ from minecraft.networking.types import (
# Formerly known as state_handshake_serverbound.
def get_packets(context):
packets = {
HandShakePacket
}
return packets
return {HandShakePacket}
class HandShakePacket(Packet):

View File

@ -63,10 +63,7 @@ class PluginResponsePacket(Packet):
def read(self, file_object):
self.message_id = VarInt.read(file_object)
self.successful = Boolean.read(file_object)
if self.successful:
self.data = TrailingByteArray.read(file_object)
else:
self.data = None
self.data = TrailingByteArray.read(file_object) if self.successful else None
def write_fields(self, packet_buffer):
VarInt.send(self.message_id, packet_buffer)

View File

@ -7,11 +7,7 @@ from minecraft.networking.types import (
# Formerly known as state_status_serverbound.
def get_packets(context):
packets = {
RequestPacket,
PingPacket
}
return packets
return {RequestPacket, PingPacket}
class RequestPacket(Packet):

View File

@ -25,12 +25,12 @@ class Type(object):
__slots__ = ()
@class_and_instancemethod
def read_with_context(cls_or_self, file_object, _context):
return cls_or_self.read(file_object)
def read_with_context(self, file_object, _context):
return self.read(file_object)
@class_and_instancemethod
def send_with_context(cls_or_self, value, socket, _context):
return cls_or_self.send(value, socket)
def send_with_context(self, value, socket, _context):
return self.send(value, socket)
@classmethod
def read(cls, file_object):
@ -249,7 +249,7 @@ class ShortPrefixedByteArray(Type):
@staticmethod
def read(file_object):
length = Short.read(file_object)
return struct.unpack(str(length) + "s", file_object.read(length))[0]
return struct.unpack(f"{str(length)}s", file_object.read(length))[0]
@staticmethod
def send(value, socket):
@ -261,12 +261,12 @@ class VarIntPrefixedByteArray(Type):
@staticmethod
def read(file_object):
length = VarInt.read(file_object)
return struct.unpack(str(length) + "s", file_object.read(length))[0]
return struct.unpack(f"{str(length)}s", file_object.read(length))[0]
@staticmethod
def send(value, socket):
VarInt.send(len(value), socket)
socket.send(struct.pack(str(len(value)) + "s", value))
socket.send(struct.pack(f"{len(value)}s", value))
class TrailingByteArray(Type):
@ -379,7 +379,7 @@ class PrefixedArray(Type):
def __read(self, file_object, element_read):
length = self.length_type.read(file_object)
return [element_read(file_object) for i in range(length)]
return [element_read(file_object) for _ in range(length)]
def __send(self, value, socket, element_send):
self.length_type.send(len(value), socket)

View File

@ -21,12 +21,18 @@ class Vector(namedtuple('BaseVector', ('x', 'y', 'z'))):
__slots__ = ()
def __add__(self, other):
return NotImplemented if not isinstance(other, Vector) else \
type(self)(self.x + other.x, self.y + other.y, self.z + other.z)
return (
type(self)(self.x + other.x, self.y + other.y, self.z + other.z)
if isinstance(other, Vector)
else NotImplemented
)
def __sub__(self, other):
return NotImplemented if not isinstance(other, Vector) else \
type(self)(self.x - other.x, self.y - other.y, self.z - other.z)
return (
type(self)(self.x - other.x, self.y - other.y, self.z - other.z)
if isinstance(other, Vector)
else NotImplemented
)
def __neg__(self):
return type(self)(-self.x, -self.y, -self.z)
@ -83,9 +89,7 @@ class MutableRecord(object):
def _all_slots(cls):
for supcls in reversed(cls.__mro__):
slots = supcls.__dict__.get('__slots__', ())
slots = (slots,) if isinstance(slots, str) else slots
for slot in slots:
yield slot
yield from (slots,) if isinstance(slots, str) else slots
Direction = namedtuple('Direction', ('yaw', 'pitch'))

View File

@ -15,48 +15,52 @@ MAIN_AUTHORS = ["Ammar Askar <ammar@ammaraskar.com>",
URL = "https://github.com/ammaraskar/pyCraft"
setup(name="pyCraft",
version=__version__,
description="Python MineCraft library",
long_description=read("README.rst"),
url=URL,
download_url=URL + "/tarball/" + __version__,
author=", ".join(MAIN_AUTHORS),
install_requires=["cryptography>=1.5",
"requests",
"pynbt",
],
packages=["minecraft",
"minecraft.networking",
"minecraft.networking.packets",
"minecraft.networking.packets.clientbound",
"minecraft.networking.packets.clientbound.status",
"minecraft.networking.packets.clientbound.handshake",
"minecraft.networking.packets.clientbound.login",
"minecraft.networking.packets.clientbound.play",
"minecraft.networking.packets.serverbound",
"minecraft.networking.packets.serverbound.status",
"minecraft.networking.packets.serverbound.handshake",
"minecraft.networking.packets.serverbound.login",
"minecraft.networking.packets.serverbound.play",
"minecraft.networking.types",
],
keywords=["MineCraft", "networking", "pyCraft", "minecraftdev", "mc"],
classifiers=["Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Topic :: Games/Entertainment",
"Topic :: Software Development :: Libraries",
"Topic :: Utilities"
]
)
setup(
name="pyCraft",
version=__version__,
description="Python MineCraft library",
long_description=read("README.rst"),
url=URL,
download_url=f"{URL}/tarball/{__version__}",
author=", ".join(MAIN_AUTHORS),
install_requires=[
"cryptography>=1.5",
"requests",
"pynbt",
],
packages=[
"minecraft",
"minecraft.networking",
"minecraft.networking.packets",
"minecraft.networking.packets.clientbound",
"minecraft.networking.packets.clientbound.status",
"minecraft.networking.packets.clientbound.handshake",
"minecraft.networking.packets.clientbound.login",
"minecraft.networking.packets.clientbound.play",
"minecraft.networking.packets.serverbound",
"minecraft.networking.packets.serverbound.status",
"minecraft.networking.packets.serverbound.handshake",
"minecraft.networking.packets.serverbound.login",
"minecraft.networking.packets.serverbound.play",
"minecraft.networking.types",
],
keywords=["MineCraft", "networking", "pyCraft", "minecraftdev", "mc"],
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Topic :: Games/Entertainment",
"Topic :: Software Development :: Libraries",
"Topic :: Utilities",
],
)

View File

@ -54,8 +54,8 @@ def get_options():
r"(:(?P<port>\d+))?$", options.server)
if match is None:
raise ValueError("Invalid server address: '%s'." % options.server)
options.address = match.group("host") or match.group("addr")
options.port = int(match.group("port") or 25565)
options.address = match["host"] or match["addr"]
options.port = int(match["port"] or 25565)
return options
@ -85,12 +85,12 @@ def main():
# that it is a packet of unknown type, so we do not print it
# unless explicitly requested by the user.
if options.dump_unknown:
print('--> [unknown packet] %s' % packet, file=sys.stderr)
print(f'--> [unknown packet] {packet}', file=sys.stderr)
else:
print('--> %s' % packet, file=sys.stderr)
print(f'--> {packet}', file=sys.stderr)
def print_outgoing(packet):
print('<-- %s' % packet, file=sys.stderr)
print(f'<-- {packet}', file=sys.stderr)
connection.register_packet_listener(
print_incoming, Packet, early=True)
@ -104,8 +104,9 @@ def main():
handle_join_game, clientbound.play.JoinGamePacket)
def print_chat(chat_packet):
print("Message (%s): %s" % (
chat_packet.field_string('position'), chat_packet.json_data))
print(
f"Message ({chat_packet.field_string('position')}): {chat_packet.json_data}"
)
connection.register_packet_listener(
print_chat, clientbound.play.ChatMessagePacket)

View File

@ -102,8 +102,12 @@ class FakeClientHandler(object):
# compression and encryption, if applicable, have been set up. The
# client's LoginStartPacket is given as an argument.
self.user_name = login_start_packet.name
self.user_uuid = uuid.UUID(bytes=hashlib.md5(
('OfflinePlayer:%s' % self.user_name).encode('utf8')).digest())
self.user_uuid = uuid.UUID(
bytes=hashlib.md5(
f'OfflinePlayer:{self.user_name}'.encode('utf8')
).digest()
)
self.write_packet(clientbound.login.LoginSuccessPacket(
UUID=str(self.user_uuid), Username=self.user_name))
@ -202,7 +206,7 @@ class FakeClientHandler(object):
def write_packet(self, packet):
# Send and log a clientbound packet.
packet.context = self.server.context
logging.debug('[S-> ] %s' % packet)
logging.debug(f'[S-> ] {packet}')
packet.write(self.socket, **(
{'compression_threshold': self.server.compression_threshold}
if self.compression_enabled else {}))
@ -217,7 +221,7 @@ class FakeClientHandler(object):
packet.read(buffer)
else:
packet = packets.Packet(self.server.context, id=packet_id)
logging.debug('[ ->S] %s' % packet)
logging.debug(f'[ ->S] {packet}')
return packet
def _run_handshake(self):
@ -234,7 +238,7 @@ class FakeClientHandler(object):
elif packet.next_state == 2:
self._run_handshake_play(packet)
else:
raise AssertionError('Unknown state: %s' % packet.next_state)
raise AssertionError(f'Unknown state: {packet.next_state}')
except FakeServerDisconnect:
pass
@ -248,8 +252,7 @@ class FakeClientHandler(object):
msg = "Outdated server! I'm still on %s" \
% self.server.minecraft_version
else:
msg = 'Outdated client! Please use %s' \
% self.server.minecraft_version
msg = f'Outdated client! Please use {self.server.minecraft_version}'
self.handle_login_server_disconnect(msg)
def _run_login(self):
@ -341,8 +344,7 @@ class FakeClientHandler(object):
data_length = types.VarInt.read(buffer)
if data_length > 0:
data = zlib.decompress(buffer.read())
assert len(data) == data_length, \
'%s != %s' % (len(data), data_length)
assert len(data) == data_length, f'{len(data)} != {data_length}'
buffer.reset()
buffer.send(data)
buffer.reset_cursor()
@ -432,9 +434,9 @@ class FakeServer(object):
while True:
try:
client_socket, addr = self.listen_socket.accept()
logging.debug('[ ++ ] Client %s connected.' % (addr,))
logging.debug(f'[ ++ ] Client {addr} connected.')
self.client_handler_type(self, client_socket).run()
logging.debug('[ -- ] Client %s disconnected.' % (addr,))
logging.debug(f'[ -- ] Client {addr} disconnected.')
except socket.timeout:
pass
with self.lock:
@ -566,11 +568,11 @@ class _FakeServerTest(unittest.TestCase):
@client.listener(packets.Packet, early=True)
def handle_incoming_packet(packet):
logging.debug('[ ->C] %s' % packet)
logging.debug(f'[ ->C] {packet}')
@client.listener(packets.Packet, early=True, outgoing=True)
def handle_outgoing_packet(packet):
logging.debug('[C-> ] %s' % packet)
logging.debug(f'[C-> ] {packet}')
server_thread = threading.Thread(
name='FakeServer',

View File

@ -370,11 +370,10 @@ class ExceptionReconnectTest(ConnectTest):
def _start_client(self, client):
@client.listener(clientbound.play.JoinGamePacket)
def handle_join_game(packet):
if self.phase == 0:
self.phase += 1
raise self.CustomException
else:
if self.phase != 0:
raise fake_server.FakeServerTestSuccess
self.phase += 1
raise self.CustomException
@client.exception_handler(self.CustomException, early=True)
def handle_custom_exception(exc, exc_info):

View File

@ -77,7 +77,7 @@ class PacketSerializationTest(unittest.TestCase):
logging.debug('protocol_version = %r' % protocol_version)
context = ConnectionContext(protocol_version=protocol_version)
msg = ''.join(choice(string.ascii_lowercase) for i in range(500))
msg = ''.join(choice(string.ascii_lowercase) for _ in range(500))
packet = serverbound.play.ChatPacket(context)
packet.message = msg

View File

@ -27,7 +27,7 @@ TEST_DATA = {
UnsignedShort: [0, 400],
UnsignedLong: [0, 400],
Integer: [-1000, 1000],
FixedPointInteger: [float(-13098.3435), float(-0.83), float(1000)],
FixedPointInteger: [-13098.3435, -0.83, float(1000)],
Angle: [0, 360.0, 720, 47.12947238973, -108.7],
VarInt: [1, 250, 50000, 10000000],
Long: [50000000],
@ -44,7 +44,7 @@ TEST_DATA = {
for x in [-0x200000, -123, -1, 0, 123, 0x1FFFFF]
for z in [-0x200000, -456, -1, 0, 456, 0x1FFFFF]
for y in [-0x80000, -789, -1, 0, 789, 0x7FFFF]
]
],
}