pyCraft/minecraft/networking/packets/__init__.py
joo 969419da3f Fix: non-monotonic protocol versions are not correctly handled
After 1.16.3, Mojang started publishing snapshot, pre-release and release
candidate versions of Minecraft with protocol version numbers of the form
`(1 << 30) | n' where 'n' is a small non-negative integer increasing with each
such version; the release versions continued to use the old format. For
example, these are the last 8 published Minecraft versions as of this commit:

release           1.16.3      uses protocol version 753
pre-release       1.16.4-pre1 uses protocol version 1073741825 == (1 << 30) | 1
pre-release       1.16.4-pre2 uses protocol version 1073741826 == (1 << 30) | 2
release candidate 1.16.4-rc1  uses protocol version 1073741827 == (1 << 30) | 3
release           1.16.4      uses protocol version 754
snapshot          20w45a      uses protocol version 1073741829 == (1 << 30) | 5
snapshot          20w46a      uses protocol version 1073741830 == (1 << 30) | 6
snapshot          20w48a      uses protocol version 1073741831 == (1 << 30) | 7

This means that protocol versions no longer increase monotonically with respect
to publication history, a property that was assumed to hold in much of
pyCraft's code relating to support of multiple protocol versions. This commit
rectifies the issue by replacing any comparison of protocol versions by their
numerical value with a comparison based on their publication time.

Newly defined is the dictionary `minecraft.PROTOCOL_VERSION_INDICES', which
maps each known protocol version to its index in the protocol chronology. As
such, the bound method `minecraft.PROTOCOL_VERSION_INDICES.get` can be used as
a key function for the built-in `sorted`, `min` and `max` functions to collate
protocol versions chronologically.

Two utility functions are provided for direct comparison of protocol versions:
    `minecraft.utility.protocol_earlier` and
    `minecraft.utility.protocol_earlier_eq`.

Additionally, four methods are added to the `ConnectionContext` type to ease
the most common cases where the protocol of a given context must be compared to
a given version number:
    `minecraft.connection.ConnectionContext.protocol_earlier`,
    `minecraft.connection.ConnectionContext.protocol_earlier_eq`,
    `minecraft.connection.ConnectionContext.protocol_later` and
    `minecraft.connection.ConnectionContext.protocol_later_eq`.
2020-12-02 15:11:39 +01:00

63 lines
2.7 KiB
Python

'''
NOTE: The packet classes exported by this module are included only for backward
compatibility, and should not be used in new code, as (1) they do not include
all packets present in pyCraft, and (2) some are named oddly, for historical
reasons.
Use the packet classes under packets.clientbound.* and
packets.serverbound.* instead.
'''
# Packet-Related Utilities
from .packet_buffer import PacketBuffer
from .packet_listener import PacketListener
# Abstract Packet Classes
from .packet import Packet
from .keep_alive_packet import AbstractKeepAlivePacket
from .plugin_message_packet import AbstractPluginMessagePacket
# Legacy Packets (Handshake State)
from .clientbound.handshake import get_packets as state_handshake_clientbound
from .serverbound.handshake import HandShakePacket
from .serverbound.handshake import get_packets as state_handshake_serverbound
# Legacy Packets (Status State)
from .clientbound.status import ResponsePacket
from .clientbound.status import PingResponsePacket as PingPacketResponse
from .clientbound.status import get_packets as state_status_clientbound
from .serverbound.status import RequestPacket
from .serverbound.status import PingPacket
from .serverbound.status import get_packets as state_status_serverbound
# Legacy Packets (Login State)
from .clientbound.login import DisconnectPacket
from .clientbound.login import EncryptionRequestPacket
from .clientbound.login import LoginSuccessPacket
from .clientbound.login import SetCompressionPacket
from .clientbound.login import get_packets as state_login_clientbound
from .serverbound.login import LoginStartPacket
from .serverbound.login import EncryptionResponsePacket
from .serverbound.login import get_packets as state_login_serverbound
# Legacy Packets (Playing State)
from .keep_alive_packet import KeepAlivePacket
from .clientbound.play import KeepAlivePacket as KeepAlivePacketClientbound
from .serverbound.play import KeepAlivePacket as KeepAlivePacketServerbound
from .clientbound.play import JoinGamePacket
from .clientbound.play import ChatMessagePacket
from .clientbound.play import PlayerPositionAndLookPacket
from .clientbound.play import DisconnectPacket as DisconnectPacketPlayState
from .clientbound.play import (
SetCompressionPacket as SetCompressionPacketPlayState
)
from .clientbound.play import PlayerListItemPacket
from .clientbound.play import MapPacket
from .clientbound.play import get_packets as state_playing_clientbound
from .serverbound.play import ChatPacket
from .serverbound.play import PositionAndLookPacket
from .serverbound.play import TeleportConfirmPacket
from .serverbound.play import AnimationPacket as AnimationPacketServerbound
from .serverbound.play import get_packets as state_playing_serverbound