mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2025-01-22 15:41:29 +01:00
Add support for Minecraft 1.13 and 1.13-pre3 to pre10 (protocols 385 to 393).
Add clientbound.login.PluginRequestPacket and serverbound.login.PluginResponsePacket.
This commit is contained in:
parent
745aa054b0
commit
adc8d15ddc
@ -28,6 +28,7 @@ pyCraft is compatible with the following Minecraft releases:
|
||||
* 1.10, 1.10.1, 1.10.2
|
||||
* 1.11, 1.11.1, 1.11.2
|
||||
* 1.12, 1.12.1, 1.12.2
|
||||
* 1.13
|
||||
|
||||
In addition, some development snapshots and pre-release versions are supported:
|
||||
`<minecraft/__init__.py>`_ contains a full list of supported Minecraft versions
|
||||
|
@ -112,6 +112,15 @@ SUPPORTED_MINECRAFT_VERSIONS = {
|
||||
'18w22c': 382,
|
||||
'1.13-pre1': 383,
|
||||
'1.13-pre2': 384,
|
||||
'1.13-pre3': 385,
|
||||
'1.13-pre4': 386,
|
||||
'1.13-pre5': 387,
|
||||
'1.13-pre6': 388,
|
||||
'1.13-pre7': 389,
|
||||
'1.13-pre8': 390,
|
||||
'1.13-pre9': 391,
|
||||
'1.13-pre10': 392,
|
||||
'1.13': 393,
|
||||
}
|
||||
|
||||
SUPPORTED_PROTOCOL_VERSIONS = \
|
||||
|
@ -568,13 +568,18 @@ class PacketReactor(object):
|
||||
return None
|
||||
|
||||
def react(self, packet):
|
||||
"""Called with each incoming packet after early packet listeners are
|
||||
run (if none of them raise 'IgnorePacket'), but before regular
|
||||
packet listeners are run. If this method raises 'IgnorePacket', no
|
||||
subsequent packet listeners will be called for this packet.
|
||||
"""
|
||||
raise NotImplementedError("Call to base reactor")
|
||||
|
||||
""" Called when an exception is raised in the networking thread. If this
|
||||
method returns True, the default action will be prevented and the
|
||||
exception ignored (but the networking thread will still terminate).
|
||||
"""
|
||||
def handle_exception(self, exc, exc_info):
|
||||
"""Called when an exception is raised in the networking thread. If this
|
||||
method returns True, the default action will be prevented and the
|
||||
exception ignored (but the networking thread will still terminate).
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
@ -613,7 +618,7 @@ class LoginReactor(PacketReactor):
|
||||
encryption.EncryptedFileObjectWrapper(
|
||||
self.connection.file_object, decryptor)
|
||||
|
||||
if packet.packet_name == "disconnect":
|
||||
elif packet.packet_name == "disconnect":
|
||||
# Receiving a disconnect packet in the login state indicates an
|
||||
# abnormal condition. Raise an exception explaining the situation.
|
||||
try:
|
||||
@ -628,13 +633,24 @@ class LoginReactor(PacketReactor):
|
||||
raise LoginDisconnect('The server rejected our login attempt '
|
||||
'with: "%s".' % msg)
|
||||
|
||||
if packet.packet_name == "login success":
|
||||
elif packet.packet_name == "login success":
|
||||
self.connection.reactor = PlayingReactor(self.connection)
|
||||
|
||||
if packet.packet_name == "set compression":
|
||||
elif packet.packet_name == "set compression":
|
||||
self.connection.options.compression_threshold = packet.threshold
|
||||
self.connection.options.compression_enabled = True
|
||||
|
||||
elif packet.packet_name == "login plugin request":
|
||||
self.connection.write_packet(
|
||||
serverbound.login.PluginResponsePacket(
|
||||
message_id=packet.message_id, successful=False))
|
||||
|
||||
def react_not_handled(self, packet):
|
||||
if packet.name == "login plugin request":
|
||||
self.connection.write_packet(
|
||||
serverbound.login.PluginResponsePacket(
|
||||
message_id=packet.message_id, successful=False))
|
||||
|
||||
|
||||
class PlayingReactor(PacketReactor):
|
||||
get_clientbound_packets = staticmethod(clientbound.play.get_packets)
|
||||
@ -644,12 +660,12 @@ class PlayingReactor(PacketReactor):
|
||||
self.connection.options.compression_threshold = packet.threshold
|
||||
self.connection.options.compression_enabled = True
|
||||
|
||||
if packet.packet_name == "keep alive":
|
||||
elif packet.packet_name == "keep alive":
|
||||
keep_alive_packet = serverbound.play.KeepAlivePacket()
|
||||
keep_alive_packet.keep_alive_id = packet.keep_alive_id
|
||||
self.connection.write_packet(keep_alive_packet)
|
||||
|
||||
if packet.packet_name == "player position and look":
|
||||
elif packet.packet_name == "player position and look":
|
||||
if self.connection.context.protocol_version >= 107:
|
||||
teleport_confirm = serverbound.play.TeleportConfirmPacket()
|
||||
teleport_confirm.teleport_id = packet.teleport_id
|
||||
@ -665,7 +681,7 @@ class PlayingReactor(PacketReactor):
|
||||
self.connection.write_packet(position_response)
|
||||
self.connection.spawned = True
|
||||
|
||||
if packet.packet_name == "disconnect":
|
||||
elif packet.packet_name == "disconnect":
|
||||
self.connection.disconnect()
|
||||
|
||||
|
||||
@ -689,10 +705,11 @@ class StatusReactor(PacketReactor):
|
||||
self.connection.disconnect()
|
||||
self.handle_status(status_dict)
|
||||
|
||||
elif packet.packet_name == "ping" and self.do_ping:
|
||||
now = int(1000 * timeit.default_timer())
|
||||
self.connection.disconnect()
|
||||
self.handle_ping(now - packet.time)
|
||||
elif packet.packet_name == "ping":
|
||||
if self.do_ping:
|
||||
now = int(1000 * timeit.default_timer())
|
||||
self.connection.disconnect()
|
||||
self.handle_ping(now - packet.time)
|
||||
|
||||
def handle_status(self, status_dict):
|
||||
print(status_dict)
|
||||
|
@ -1,7 +1,7 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
from minecraft.networking.types import (
|
||||
String, VarIntPrefixedByteArray, VarInt
|
||||
VarInt, String, VarIntPrefixedByteArray, TrailingByteArray
|
||||
)
|
||||
|
||||
|
||||
@ -11,20 +11,34 @@ def get_packets(context):
|
||||
DisconnectPacket,
|
||||
EncryptionRequestPacket,
|
||||
LoginSuccessPacket,
|
||||
SetCompressionPacket
|
||||
SetCompressionPacket,
|
||||
}
|
||||
if context.protocol_version >= 385:
|
||||
packets |= {
|
||||
PluginRequestPacket,
|
||||
}
|
||||
return packets
|
||||
|
||||
|
||||
class DisconnectPacket(Packet):
|
||||
id = 0x00
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x00 if context.protocol_version >= 391 else \
|
||||
0x01 if context.protocol_version >= 385 else \
|
||||
0x00
|
||||
|
||||
packet_name = "disconnect"
|
||||
definition = [
|
||||
{'json_data': String}]
|
||||
|
||||
|
||||
class EncryptionRequestPacket(Packet):
|
||||
id = 0x01
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x01 if context.protocol_version >= 391 else \
|
||||
0x02 if context.protocol_version >= 385 else \
|
||||
0x01
|
||||
|
||||
packet_name = "encryption request"
|
||||
definition = [
|
||||
{'server_id': String},
|
||||
@ -33,7 +47,12 @@ class EncryptionRequestPacket(Packet):
|
||||
|
||||
|
||||
class LoginSuccessPacket(Packet):
|
||||
id = 0x02
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x02 if context.protocol_version >= 391 else \
|
||||
0x03 if context.protocol_version >= 385 else \
|
||||
0x02
|
||||
|
||||
packet_name = "login success"
|
||||
definition = [
|
||||
{'UUID': String},
|
||||
@ -41,7 +60,39 @@ class LoginSuccessPacket(Packet):
|
||||
|
||||
|
||||
class SetCompressionPacket(Packet):
|
||||
id = 0x03
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x03 if context.protocol_version >= 391 else \
|
||||
0x04 if context.protocol_version >= 385 else \
|
||||
0x03
|
||||
|
||||
packet_name = "set compression"
|
||||
definition = [
|
||||
{'threshold': VarInt}]
|
||||
|
||||
|
||||
class PluginRequestPacket(Packet):
|
||||
""" NOTE: pyCraft's default behaviour on receiving a 'PluginRequestPacket'
|
||||
is to send a corresponding 'PluginResponsePacket' with
|
||||
'successful=False'. To override this, set a packet listener that:
|
||||
|
||||
(1) has the keyword argument 'early=True' set when calling
|
||||
'register_packet_listener'; and
|
||||
|
||||
(2) raises 'minecraft.networking.connection.IgnorePacket' after
|
||||
sending a corresponding 'PluginResponsePacket'.
|
||||
|
||||
Otherwise, one 'PluginRequestPacket' may result in multiple responses,
|
||||
which contravenes Minecraft's protocol.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x04 if context.protocol_version >= 391 else \
|
||||
0x00
|
||||
|
||||
packet_name = 'login plugin request'
|
||||
definition = [
|
||||
{'message_id': VarInt},
|
||||
{'channel': String},
|
||||
{'data': TrailingByteArray}]
|
||||
|
@ -46,7 +46,8 @@ def get_packets(context):
|
||||
class KeepAlivePacket(AbstractKeepAlivePacket):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x20 if context.protocol_version >= 345 else \
|
||||
return 0x21 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -56,7 +57,8 @@ class KeepAlivePacket(AbstractKeepAlivePacket):
|
||||
class JoinGamePacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x24 if context.protocol_version >= 345 else \
|
||||
return 0x25 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -142,7 +144,8 @@ class SpawnPlayerPacket(Packet):
|
||||
class EntityVelocityPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x40 if context.protocol_version >= 352 else \
|
||||
return 0x41 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -163,7 +166,8 @@ class EntityVelocityPacket(Packet):
|
||||
class UpdateHealthPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x43 if context.protocol_version >= 352 else \
|
||||
return 0x44 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -8,7 +8,8 @@ from minecraft.networking.types import (
|
||||
class CombatEventPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x2E if context.protocol_version >= 345 else \
|
||||
return 0x2F if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -5,7 +5,8 @@ from minecraft.networking.packets import Packet
|
||||
class ExplosionPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x1D if context.protocol_version >= 345 else \
|
||||
return 0x1E if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -8,7 +8,8 @@ from minecraft.networking.types import (
|
||||
class MapPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x25 if context.protocol_version >= 345 else \
|
||||
return 0x26 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -8,7 +8,8 @@ from minecraft.networking.types import (
|
||||
class PlayerListItemPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x2F if context.protocol_version >= 345 else \
|
||||
return 0x30 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -8,7 +8,8 @@ from minecraft.networking.types import (
|
||||
class PlayerPositionAndLookPacket(Packet, BitFieldEnum):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x31 if context.protocol_version >= 352 else \
|
||||
return 0x32 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -110,12 +110,17 @@ class Packet(object):
|
||||
str = type(self).__name__
|
||||
if self.id is not None:
|
||||
str = '0x%02X %s' % (self.id, str)
|
||||
if self.definition is not None:
|
||||
str = '%s(%s)' % (str, ', '.join(
|
||||
'%s=%s' % (a, self.field_string(a))
|
||||
for d in self.definition for a in d))
|
||||
fields = self.fields
|
||||
if fields is not None:
|
||||
str = '%s(%s)' % (str, ', '.join('%s=%s' %
|
||||
(a, self.field_string(a)) for a in fields))
|
||||
return str
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
""" An iterable of the names of the packet's fields, or None. """
|
||||
return (field for defn in self.definition for field in defn)
|
||||
|
||||
def field_string(self, field):
|
||||
""" The string representation of the value of a the given named field
|
||||
of this packet. Override to customise field value representation.
|
||||
|
@ -13,3 +13,5 @@ class PacketListener(object):
|
||||
for packet_type in self.packets_to_listen:
|
||||
if isinstance(packet, packet_type):
|
||||
self.callback(packet)
|
||||
return True
|
||||
return False
|
||||
|
@ -3,6 +3,10 @@ from minecraft.networking.types import String, TrailingByteArray
|
||||
|
||||
|
||||
class AbstractPluginMessagePacket(Packet):
|
||||
"""NOTE: Plugin channels were significantly changed, including changing the
|
||||
names of channels, between Minecraft 1.12 and 1.13 - see <http://wiki.vg
|
||||
/index.php?title=Pre-release_protocol&oldid=14132#Plugin_Channels>.
|
||||
"""
|
||||
definition = [
|
||||
{'channel': String},
|
||||
{'data': TrailingByteArray}]
|
||||
|
@ -1,7 +1,7 @@
|
||||
from minecraft.networking.packets import Packet
|
||||
|
||||
from minecraft.networking.types import (
|
||||
String, VarIntPrefixedByteArray
|
||||
VarInt, Boolean, String, VarIntPrefixedByteArray, TrailingByteArray
|
||||
)
|
||||
|
||||
|
||||
@ -11,19 +11,67 @@ def get_packets(context):
|
||||
LoginStartPacket,
|
||||
EncryptionResponsePacket
|
||||
}
|
||||
if context.protocol_version >= 385:
|
||||
packets |= {
|
||||
PluginResponsePacket
|
||||
}
|
||||
return packets
|
||||
|
||||
|
||||
class LoginStartPacket(Packet):
|
||||
id = 0x00
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x00 if context.protocol_version >= 391 else \
|
||||
0x01 if context.protocol_version >= 385 else \
|
||||
0x00
|
||||
|
||||
packet_name = "login start"
|
||||
definition = [
|
||||
{'name': String}]
|
||||
|
||||
|
||||
class EncryptionResponsePacket(Packet):
|
||||
id = 0x01
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x01 if context.protocol_version >= 391 else \
|
||||
0x02 if context.protocol_version >= 385 else \
|
||||
0x01
|
||||
|
||||
packet_name = "encryption response"
|
||||
definition = [
|
||||
{'shared_secret': VarIntPrefixedByteArray},
|
||||
{'verify_token': VarIntPrefixedByteArray}]
|
||||
|
||||
|
||||
class PluginResponsePacket(Packet):
|
||||
""" NOTE: see comments on 'clientbound.login.PluginRequestPacket' for
|
||||
important information on the usage of this packet.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x02 if context.protocol_version >= 391 else \
|
||||
0x00
|
||||
|
||||
packet_name = 'login plugin response'
|
||||
fields = (
|
||||
'message_id', # str
|
||||
'successful', # bool
|
||||
'data', # bytes, or None if 'successful' is False
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
def write_fields(self, packet_buffer):
|
||||
VarInt.send(self.message_id, packet_buffer)
|
||||
successful = getattr(self, 'data', None) is not None
|
||||
successful = getattr(self, 'successful', successful)
|
||||
Boolean.send(successful, packet_buffer)
|
||||
if successful:
|
||||
TrailingByteArray.send(self.data, packet_buffer)
|
||||
|
@ -32,7 +32,9 @@ def get_packets(context):
|
||||
class KeepAlivePacket(AbstractKeepAlivePacket):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x0B if context.protocol_version >= 345 else \
|
||||
return 0x0E if context.protocol_version >= 389 else \
|
||||
0x0C if context.protocol_version >= 386 else \
|
||||
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 \
|
||||
@ -43,7 +45,8 @@ class KeepAlivePacket(AbstractKeepAlivePacket):
|
||||
class ChatPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x01 if context.protocol_version >= 343 else \
|
||||
return 0x02 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -67,7 +70,9 @@ class ChatPacket(Packet):
|
||||
class PositionAndLookPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x0E if context.protocol_version >= 345 else \
|
||||
return 0x11 if context.protocol_version >= 389 else \
|
||||
0x0F if context.protocol_version >= 386 else \
|
||||
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 \
|
||||
@ -96,7 +101,9 @@ class TeleportConfirmPacket(Packet):
|
||||
class AnimationPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x1D if context.protocol_version >= 345 else \
|
||||
return 0x27 if context.protocol_version >= 389 else \
|
||||
0x25 if context.protocol_version >= 386 else \
|
||||
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 \
|
||||
@ -114,7 +121,8 @@ class AnimationPacket(Packet):
|
||||
class ClientStatusPacket(Packet, Enum):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x02 if context.protocol_version >= 343 else \
|
||||
return 0x03 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -137,7 +145,8 @@ class ClientStatusPacket(Packet, Enum):
|
||||
class PluginMessagePacket(AbstractPluginMessagePacket):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x09 if context.protocol_version >= 345 else \
|
||||
return 0x0A if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
@ -161,7 +170,9 @@ class PlayerBlockPlacementPacket(Packet):
|
||||
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x1F if context.protocol_version >= 345 else \
|
||||
return 0x29 if context.protocol_version >= 389 else \
|
||||
0x27 if context.protocol_version >= 386 else \
|
||||
0x1F if context.protocol_version >= 345 else \
|
||||
0x1E if context.protocol_version >= 343 else \
|
||||
0x1F if context.protocol_version >= 332 else \
|
||||
0x1E if context.protocol_version >= 318 else \
|
||||
|
@ -8,7 +8,8 @@ from minecraft.networking.types import (
|
||||
class ClientSettingsPacket(Packet):
|
||||
@staticmethod
|
||||
def get_id(context):
|
||||
return 0x03 if context.protocol_version >= 343 else \
|
||||
return 0x04 if context.protocol_version >= 389 else \
|
||||
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 \
|
||||
|
@ -89,11 +89,11 @@ class FakeClientHandler(object):
|
||||
# Handshake packet, which is provided as an argument.
|
||||
pass
|
||||
|
||||
def handle_login(self, join_game_packet):
|
||||
def handle_login(self, login_start_packet):
|
||||
# Called to transition from the login state to the play state, after
|
||||
# compression and encryption, if applicable, have been set up. The
|
||||
# client's LoginStartPacket is given as an argument.
|
||||
self.user_name = join_game_packet.name
|
||||
self.user_name = login_start_packet.name
|
||||
self.user_uuid = uuid.UUID(bytes=hashlib.md5(
|
||||
('OfflinePlayer:%s' % self.user_name).encode('utf8')).digest())
|
||||
self.write_packet(clientbound.login.LoginSuccessPacket(
|
||||
|
@ -1,9 +1,9 @@
|
||||
from minecraft import SUPPORTED_MINECRAFT_VERSIONS
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.packets import clientbound, serverbound
|
||||
from minecraft.networking.connection import Connection, IgnorePacket
|
||||
from minecraft.networking.connection import Connection
|
||||
from minecraft.exceptions import (
|
||||
VersionMismatch, LoginDisconnect, InvalidState
|
||||
VersionMismatch, LoginDisconnect, InvalidState, IgnorePacket
|
||||
)
|
||||
from minecraft.compat import unicode
|
||||
|
||||
@ -134,6 +134,51 @@ class ConnectStatusTest(ConnectTwiceTest):
|
||||
client.status()
|
||||
|
||||
|
||||
class LoginPluginTest(fake_server._FakeServerTest):
|
||||
class client_handler_type(fake_server.FakeClientHandler):
|
||||
def handle_login(self, login_start_packet):
|
||||
request = clientbound.login.PluginRequestPacket(
|
||||
message_id=1, channel='pyCraft:tests/fail', data=b'ignored')
|
||||
self.write_packet(request)
|
||||
response = self.read_packet()
|
||||
assert isinstance(response, serverbound.login.PluginResponsePacket)
|
||||
assert response.message_id == request.message_id
|
||||
assert response.successful is False
|
||||
assert response.data is None
|
||||
|
||||
request = clientbound.login.PluginRequestPacket(
|
||||
message_id=2, channel='pyCraft:tests/echo', data=b'hello')
|
||||
self.write_packet(request)
|
||||
response = self.read_packet()
|
||||
assert isinstance(response, serverbound.login.PluginResponsePacket)
|
||||
assert response.message_id == request.message_id
|
||||
assert response.successful is True
|
||||
assert response.data == request.data
|
||||
|
||||
super(LoginPluginTest.client_handler_type, self) \
|
||||
.handle_login(login_start_packet)
|
||||
|
||||
def handle_play_start(self):
|
||||
super(LoginPluginTest.client_handler_type, self) \
|
||||
.handle_play_start()
|
||||
raise fake_server.FakeServerDisconnect
|
||||
|
||||
def _start_client(self, client):
|
||||
def handle_plugin_request(packet):
|
||||
if packet.channel == 'pyCraft:tests/echo':
|
||||
client.write_packet(serverbound.login.PluginResponsePacket(
|
||||
message_id=packet.message_id, data=packet.data))
|
||||
raise IgnorePacket
|
||||
client.register_packet_listener(
|
||||
handle_plugin_request, clientbound.login.PluginRequestPacket,
|
||||
early=True)
|
||||
|
||||
super(LoginPluginTest, self)._start_client(client)
|
||||
|
||||
def test_login_plugin_messages(self):
|
||||
self._test_connect()
|
||||
|
||||
|
||||
class EarlyPacketListenerTest(ConnectTest):
|
||||
""" Early packet listeners should be called before ordinary ones, even when
|
||||
the early packet listener is registered afterwards.
|
||||
|
@ -3,17 +3,23 @@ try:
|
||||
from unittest import mock
|
||||
except ImportError:
|
||||
import mock
|
||||
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.connection import (
|
||||
LoginReactor, PlayingReactor, ConnectionContext
|
||||
)
|
||||
from minecraft.networking.packets import clientbound
|
||||
|
||||
|
||||
max_proto_ver = max(SUPPORTED_PROTOCOL_VERSIONS)
|
||||
|
||||
|
||||
class LoginReactorTest(unittest.TestCase):
|
||||
|
||||
@mock.patch('minecraft.networking.connection.encryption')
|
||||
def test_encryption_online_server(self, encrypt):
|
||||
connection = mock.MagicMock()
|
||||
connection.context = ConnectionContext(protocol_version=max_proto_ver)
|
||||
reactor = LoginReactor(connection)
|
||||
|
||||
packet = clientbound.login.EncryptionRequestPacket()
|
||||
@ -37,6 +43,7 @@ class LoginReactorTest(unittest.TestCase):
|
||||
@mock.patch('minecraft.networking.connection.encryption')
|
||||
def test_encryption_offline_server(self, encrypt):
|
||||
connection = mock.MagicMock()
|
||||
connection.context = ConnectionContext(protocol_version=max_proto_ver)
|
||||
reactor = LoginReactor(connection)
|
||||
|
||||
packet = clientbound.login.EncryptionRequestPacket()
|
||||
|
Loading…
Reference in New Issue
Block a user