Multiprotocol support: 1.12.2 and 1.11.2 (#54)
Adds support for connecting to both 1.12.2 and 1.11.2 (protocols 340 and 316) servers https://github.com/iceiix/steven/issues/18 Enhance protocol support Closes https://github.com/iceiix/steven/pull/48 1.11.2 protocol support (316) * Restore create_ids!() macro in packet identifiers * Add translate_packet_id() function to map external 1.12.2 packet ids to internal sequential ids * Implement translate_internal_packet_id() from a new protocol_packet_ids! macro * Move packet IDs to separate file, v1_12_2.rs * Change supported protocols constant to an array * Add v1_11_2 protocol packet IDs (from https://github.com/iceiix/steven/pull/48) * Add keep alive packet variants: _i64 (>=1.12.2) and _VarInt (<=1.11.2) * Abstract protocol versions, can now connect to both 1.12.2 and 1.11.2 * Send protocol version in handshake packet * Restore 1.11 (315) protocol support as in original (https://github.com/thinkofname/steven) Steven
This commit is contained in:
parent
be6e1f79f1
commit
d03f102bb8
|
@ -96,8 +96,8 @@ impl Game {
|
|||
if let Some(v) = server_versions_info.get(address) {
|
||||
v.as_i64().unwrap() as i32
|
||||
} else {
|
||||
warn!("Server protocol version not known for {} (no ping response?), defaulting to {}", address, protocol::SUPPORTED_PROTOCOL);
|
||||
protocol::SUPPORTED_PROTOCOL
|
||||
warn!("Server protocol version not known for {} (no ping response?), defaulting to {}", address, protocol::SUPPORTED_PROTOCOLS[0]);
|
||||
protocol::SUPPORTED_PROTOCOLS[0]
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -230,7 +230,7 @@ fn main() {
|
|||
should_close: false,
|
||||
chunk_builder: chunk_builder::ChunkBuilder::new(resource_manager, textures),
|
||||
connect_reply: None,
|
||||
protocol_version: protocol::SUPPORTED_PROTOCOL,
|
||||
protocol_version: protocol::SUPPORTED_PROTOCOLS[0],
|
||||
dpi_factor,
|
||||
last_mouse_x: 0.0,
|
||||
last_mouse_y: 0.0,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use aes::Aes128;
|
||||
use cfb8::Cfb8;
|
||||
|
@ -36,7 +37,7 @@ use flate2::Compression;
|
|||
use std::time::{Instant, Duration};
|
||||
use crate::shared::Position;
|
||||
|
||||
pub const SUPPORTED_PROTOCOL: i32 = 340;
|
||||
pub const SUPPORTED_PROTOCOLS: [i32; 3] = [340, 316, 315];
|
||||
|
||||
|
||||
/// Helper macro for defining packets
|
||||
|
@ -83,130 +84,7 @@ macro_rules! state_packets {
|
|||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub mod internal_ids {
|
||||
pub const Handshake: i32 = 0x00;
|
||||
pub const TeleportConfirm: i32 = 0x00;
|
||||
pub const TabComplete: i32 = 0x01;
|
||||
pub const ChatMessage: i32 = 0x02;
|
||||
pub const ClientStatus: i32 = 0x03;
|
||||
pub const ClientSettings: i32 = 0x04;
|
||||
pub const ConfirmTransactionServerbound: i32 = 0x05;
|
||||
pub const EnchantItem: i32 = 0x06;
|
||||
pub const ClickWindow: i32 = 0x07;
|
||||
pub const CloseWindow: i32 = 0x08;
|
||||
pub const PluginMessageServerbound: i32 = 0x09;
|
||||
pub const UseEntity: i32 = 0x0a;
|
||||
pub const KeepAliveServerbound: i32 = 0x0b;
|
||||
pub const Player: i32 = 0x0c;
|
||||
pub const PlayerPosition: i32 = 0x0d;
|
||||
pub const PlayerPositionLook: i32 = 0x0e;
|
||||
pub const PlayerLook: i32 = 0x0f;
|
||||
pub const VehicleMove: i32 = 0x10;
|
||||
pub const SteerBoat: i32 = 0x11;
|
||||
pub const CraftRecipeRequest: i32 = 0x12;
|
||||
pub const ClientAbilities: i32 = 0x13;
|
||||
pub const PlayerDigging: i32 = 0x14;
|
||||
pub const PlayerAction: i32 = 0x15;
|
||||
pub const SteerVehicle: i32 = 0x16;
|
||||
pub const CraftingBookData: i32 = 0x17;
|
||||
pub const ResourcePackStatus: i32 = 0x18;
|
||||
pub const AdvancementTab: i32 = 0x19;
|
||||
pub const HeldItemChange: i32 = 0x1a;
|
||||
pub const CreativeInventoryAction: i32 = 0x1b;
|
||||
pub const SetSign: i32 = 0x1c;
|
||||
pub const ArmSwing: i32 = 0x1d;
|
||||
pub const SpectateTeleport: i32 = 0x1e;
|
||||
pub const PlayerBlockPlacement: i32 = 0x1f;
|
||||
pub const UseItem: i32 = 0x20;
|
||||
pub const SpawnObject: i32 = 0x00;
|
||||
pub const SpawnExperienceOrb: i32 = 0x01;
|
||||
pub const SpawnGlobalEntity: i32 = 0x02;
|
||||
pub const SpawnMob: i32 = 0x03;
|
||||
pub const SpawnPainting: i32 = 0x04;
|
||||
pub const SpawnPlayer: i32 = 0x05;
|
||||
pub const Animation: i32 = 0x06;
|
||||
pub const Statistics: i32 = 0x07;
|
||||
pub const BlockBreakAnimation: i32 = 0x08;
|
||||
pub const UpdateBlockEntity: i32 = 0x09;
|
||||
pub const BlockAction: i32 = 0x0a;
|
||||
pub const BlockChange: i32 = 0x0b;
|
||||
pub const BossBar: i32 = 0x0c;
|
||||
pub const ServerDifficulty: i32 = 0x0d;
|
||||
pub const TabCompleteReply: i32 = 0x0e;
|
||||
pub const ServerMessage: i32 = 0x0f;
|
||||
pub const MultiBlockChange: i32 = 0x10;
|
||||
pub const ConfirmTransaction: i32 = 0x11;
|
||||
pub const WindowClose: i32 = 0x12;
|
||||
pub const WindowOpen: i32 = 0x13;
|
||||
pub const WindowItems: i32 = 0x14;
|
||||
pub const WindowProperty: i32 = 0x15;
|
||||
pub const WindowSetSlot: i32 = 0x16;
|
||||
pub const SetCooldown: i32 = 0x17;
|
||||
pub const PluginMessageClientbound: i32 = 0x18;
|
||||
pub const NamedSoundEffect: i32 = 0x19;
|
||||
pub const Disconnect: i32 = 0x1a;
|
||||
pub const EntityAction: i32 = 0x1b;
|
||||
pub const Explosion: i32 = 0x1c;
|
||||
pub const ChunkUnload: i32 = 0x1d;
|
||||
pub const ChangeGameState: i32 = 0x1e;
|
||||
pub const KeepAliveClientbound: i32 = 0x1f;
|
||||
pub const ChunkData: i32 = 0x20;
|
||||
pub const Effect: i32 = 0x21;
|
||||
pub const Particle: i32 = 0x22;
|
||||
pub const JoinGame: i32 = 0x23;
|
||||
pub const Maps: i32 = 0x24;
|
||||
pub const Entity: i32 = 0x25;
|
||||
pub const EntityMove: i32 = 0x26;
|
||||
pub const EntityLookAndMove: i32 = 0x27;
|
||||
pub const EntityLook: i32 = 0x28;
|
||||
pub const VehicleTeleport: i32 = 0x29;
|
||||
pub const SignEditorOpen: i32 = 0x2a;
|
||||
pub const CraftRecipeResponse: i32 = 0x2b;
|
||||
pub const PlayerAbilities: i32 = 0x2c;
|
||||
pub const CombatEvent: i32 = 0x2d;
|
||||
pub const PlayerInfo: i32 = 0x2e;
|
||||
pub const TeleportPlayer: i32 = 0x2f;
|
||||
pub const EntityUsedBed: i32 = 0x30;
|
||||
pub const UnlockRecipes: i32 = 0x31;
|
||||
pub const EntityDestroy: i32 = 0x32;
|
||||
pub const EntityRemoveEffect: i32 = 0x33;
|
||||
pub const ResourcePackSend: i32 = 0x34;
|
||||
pub const Respawn: i32 = 0x35;
|
||||
pub const EntityHeadLook: i32 = 0x36;
|
||||
pub const SelectAdvancementTab: i32 = 0x37;
|
||||
pub const WorldBorder: i32 = 0x38;
|
||||
pub const Camera: i32 = 0x39;
|
||||
pub const SetCurrentHotbarSlot: i32 = 0x3a;
|
||||
pub const ScoreboardDisplay: i32 = 0x3b;
|
||||
pub const EntityMetadata: i32 = 0x3c;
|
||||
pub const EntityAttach: i32 = 0x3d;
|
||||
pub const EntityVelocity: i32 = 0x3e;
|
||||
pub const EntityEquipment: i32 = 0x3f;
|
||||
pub const SetExperience: i32 = 0x40;
|
||||
pub const UpdateHealth: i32 = 0x41;
|
||||
pub const ScoreboardObjective: i32 = 0x42;
|
||||
pub const SetPassengers: i32 = 0x43;
|
||||
pub const Teams: i32 = 0x44;
|
||||
pub const UpdateScore: i32 = 0x45;
|
||||
pub const SpawnPosition: i32 = 0x46;
|
||||
pub const TimeUpdate: i32 = 0x47;
|
||||
pub const Title: i32 = 0x48;
|
||||
pub const SoundEffect: i32 = 0x49;
|
||||
pub const PlayerListHeaderFooter: i32 = 0x4a;
|
||||
pub const CollectItem: i32 = 0x4b;
|
||||
pub const EntityTeleport: i32 = 0x4c;
|
||||
pub const Advancements: i32 = 0x4d;
|
||||
pub const EntityProperties: i32 = 0x4e;
|
||||
pub const EntityEffect: i32 = 0x4f;
|
||||
pub const LoginStart: i32 = 0x00;
|
||||
pub const EncryptionResponse: i32 = 0x01;
|
||||
pub const LoginDisconnect: i32 = 0x00;
|
||||
pub const EncryptionRequest: i32 = 0x01;
|
||||
pub const LoginSuccess: i32 = 0x02;
|
||||
pub const SetInitialCompression: i32 = 0x03;
|
||||
pub const StatusRequest: i32 = 0x00;
|
||||
pub const StatusPing: i32 = 0x01;
|
||||
pub const StatusResponse: i32 = 0x00;
|
||||
pub const StatusPong: i32 = 0x01;
|
||||
create_ids!(i32, $($name),*);
|
||||
}
|
||||
|
||||
$(
|
||||
|
@ -217,7 +95,9 @@ pub const StatusPong: i32 = 0x01;
|
|||
|
||||
impl PacketType for $name {
|
||||
|
||||
fn packet_id(&self) -> i32 { internal_ids::$name }
|
||||
fn packet_id(&self, version: i32) -> i32 {
|
||||
packet::versions::translate_internal_packet_id_for_version(version, State::$stateName, Direction::$dirName, internal_ids::$name, false)
|
||||
}
|
||||
|
||||
fn write<W: io::Write>(self, buf: &mut W) -> Result<(), Error> {
|
||||
$(
|
||||
|
@ -237,14 +117,15 @@ pub const StatusPong: i32 = 0x01;
|
|||
|
||||
/// Returns the packet for the given state, direction and id after parsing the fields
|
||||
/// from the buffer.
|
||||
pub fn packet_by_id<R: io::Read>(state: State, dir: Direction, id: i32, mut buf: &mut R) -> Result<Option<Packet>, Error> {
|
||||
pub fn packet_by_id<R: io::Read>(version: i32, state: State, dir: Direction, id: i32, mut buf: &mut R) -> Result<Option<Packet>, Error> {
|
||||
match state {
|
||||
$(
|
||||
State::$stateName => {
|
||||
match dir {
|
||||
$(
|
||||
Direction::$dirName => {
|
||||
match id {
|
||||
let internal_id = packet::versions::translate_internal_packet_id_for_version(version, state, dir, id, true);
|
||||
match internal_id {
|
||||
$(
|
||||
self::$state::$dir::internal_ids::$name => {
|
||||
use self::$state::$dir::$name;
|
||||
|
@ -269,8 +150,52 @@ pub const StatusPong: i32 = 0x01;
|
|||
}
|
||||
}
|
||||
|
||||
pub mod packet;
|
||||
#[macro_export]
|
||||
macro_rules! protocol_packet_ids {
|
||||
($($state:ident $stateName:ident {
|
||||
$($dir:ident $dirName:ident {
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
$id:expr => $name:ident
|
||||
)*
|
||||
})+
|
||||
})+) => {
|
||||
use crate::protocol::*;
|
||||
|
||||
pub fn translate_internal_packet_id(state: State, dir: Direction, id: i32, to_internal: bool) -> i32 {
|
||||
match state {
|
||||
$(
|
||||
State::$stateName => {
|
||||
match dir {
|
||||
$(
|
||||
Direction::$dirName => {
|
||||
if to_internal {
|
||||
match id {
|
||||
$(
|
||||
$id => crate::protocol::packet::$state::$dir::internal_ids::$name,
|
||||
)*
|
||||
_ => panic!("bad packet id $id in $dir $state"),
|
||||
}
|
||||
} else {
|
||||
match id {
|
||||
$(
|
||||
crate::protocol::packet::$state::$dir::internal_ids::$name => $id,
|
||||
)*
|
||||
_ => panic!("bad packet internal id $id in $dir $state"),
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod packet;
|
||||
pub mod versions;
|
||||
pub trait Serializable: Sized {
|
||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error>;
|
||||
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), Error>;
|
||||
|
@ -868,6 +793,7 @@ pub struct Conn {
|
|||
pub host: String,
|
||||
pub port: u16,
|
||||
direction: Direction,
|
||||
pub protocol_version: i32,
|
||||
pub state: State,
|
||||
|
||||
cipher: Option<Aes128Cfb>,
|
||||
|
@ -878,7 +804,7 @@ pub struct Conn {
|
|||
}
|
||||
|
||||
impl Conn {
|
||||
pub fn new(target: &str) -> Result<Conn, Error> {
|
||||
pub fn new(target: &str, protocol_version: i32) -> Result<Conn, Error> {
|
||||
// TODO SRV record support
|
||||
let mut parts = target.split(':').collect::<Vec<&str>>();
|
||||
let address = if parts.len() == 1 {
|
||||
|
@ -894,6 +820,7 @@ impl Conn {
|
|||
port: parts[1].parse().unwrap(),
|
||||
direction: Direction::Serverbound,
|
||||
state: State::Handshaking,
|
||||
protocol_version,
|
||||
cipher: Option::None,
|
||||
compression_threshold: -1,
|
||||
compression_read: Option::None,
|
||||
|
@ -903,7 +830,7 @@ impl Conn {
|
|||
|
||||
pub fn write_packet<T: PacketType>(&mut self, packet: T) -> Result<(), Error> {
|
||||
let mut buf = Vec::new();
|
||||
VarInt(packet.packet_id()).write_to(&mut buf)?;
|
||||
VarInt(packet.packet_id(self.protocol_version)).write_to(&mut buf)?;
|
||||
packet.write(&mut buf)?;
|
||||
|
||||
let mut extra = if self.compression_threshold >= 0 {
|
||||
|
@ -963,7 +890,7 @@ impl Conn {
|
|||
Direction::Serverbound => Direction::Clientbound,
|
||||
};
|
||||
|
||||
let packet = packet::packet_by_id(self.state, dir, id, &mut buf)?;
|
||||
let packet = packet::packet_by_id(self.protocol_version, self.state, dir, id, &mut buf)?;
|
||||
|
||||
match packet {
|
||||
Some(val) => {
|
||||
|
@ -998,7 +925,7 @@ impl Conn {
|
|||
let host = self.host.clone();
|
||||
let port = self.port;
|
||||
self.write_packet(Handshake {
|
||||
protocol_version: VarInt(SUPPORTED_PROTOCOL),
|
||||
protocol_version: VarInt(self.protocol_version),
|
||||
host,
|
||||
port,
|
||||
next: VarInt(1),
|
||||
|
@ -1131,6 +1058,7 @@ impl Clone for Conn {
|
|||
port: self.port,
|
||||
direction: self.direction,
|
||||
state: self.state,
|
||||
protocol_version: self.protocol_version,
|
||||
cipher: Option::None,
|
||||
compression_threshold: self.compression_threshold,
|
||||
compression_read: Option::None,
|
||||
|
@ -1140,7 +1068,7 @@ impl Clone for Conn {
|
|||
}
|
||||
|
||||
pub trait PacketType {
|
||||
fn packet_id(&self) -> i32;
|
||||
fn packet_id(&self, protocol_version: i32) -> i32;
|
||||
|
||||
fn write<W: io::Write>(self, buf: &mut W) -> Result<(), Error>;
|
||||
}
|
||||
|
|
|
@ -123,9 +123,12 @@ state_packets!(
|
|||
/// KeepAliveServerbound is sent by a client as a response to a
|
||||
/// KeepAliveClientbound. If the client doesn't reply the server
|
||||
/// may disconnect the client.
|
||||
packet KeepAliveServerbound {
|
||||
packet KeepAliveServerbound_i64 {
|
||||
field id: i64 =,
|
||||
}
|
||||
packet KeepAliveServerbound_VarInt {
|
||||
field id: VarInt =,
|
||||
}
|
||||
/// PlayerPosition is used to update the player's position.
|
||||
packet PlayerPosition {
|
||||
field x: f64 =,
|
||||
|
@ -505,9 +508,12 @@ state_packets!(
|
|||
/// client is still responding and keep the connection open.
|
||||
/// The client should reply with the KeepAliveServerbound
|
||||
/// packet setting ID to the same as this one.
|
||||
packet KeepAliveClientbound {
|
||||
packet KeepAliveClientbound_i64 {
|
||||
field id: i64 =,
|
||||
}
|
||||
packet KeepAliveClientbound_VarInt {
|
||||
field id: VarInt =,
|
||||
}
|
||||
/// ChunkData sends or updates a single chunk on the client. If New is set
|
||||
/// then biome data should be sent too.
|
||||
packet ChunkData {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
use crate::protocol::*;
|
||||
|
||||
mod v1_12_2;
|
||||
mod v1_11_2;
|
||||
|
||||
pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 {
|
||||
match version {
|
||||
// https://wiki.vg/Protocol_History
|
||||
// https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite
|
||||
// 1.12.2
|
||||
340 => v1_12_2::translate_internal_packet_id(state, dir, id, to_internal),
|
||||
|
||||
// 1.11.2
|
||||
316 => v1_11_2::translate_internal_packet_id(state, dir, id, to_internal),
|
||||
|
||||
// 1.11
|
||||
315 => v1_11_2::translate_internal_packet_id(state, dir, id, to_internal),
|
||||
|
||||
_ => panic!("unsupported protocol version"),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
protocol_packet_ids!(
|
||||
handshake Handshaking {
|
||||
serverbound Serverbound {
|
||||
0x00 => Handshake
|
||||
}
|
||||
clientbound Clientbound {
|
||||
}
|
||||
}
|
||||
play Play {
|
||||
serverbound Serverbound {
|
||||
0x00 => TeleportConfirm
|
||||
0x01 => TabComplete
|
||||
0x02 => ChatMessage
|
||||
0x03 => ClientStatus
|
||||
0x04 => ClientSettings
|
||||
0x05 => ConfirmTransactionServerbound
|
||||
0x06 => EnchantItem
|
||||
0x07 => ClickWindow
|
||||
0x08 => CloseWindow
|
||||
0x09 => PluginMessageServerbound
|
||||
0x0a => UseEntity
|
||||
0x0b => KeepAliveServerbound_VarInt
|
||||
0x0c => PlayerPosition
|
||||
0x0d => PlayerPositionLook
|
||||
0x0e => PlayerLook
|
||||
0x0f => Player
|
||||
0x10 => VehicleMove
|
||||
0x11 => SteerBoat
|
||||
0x12 => ClientAbilities
|
||||
0x13 => PlayerDigging
|
||||
0x14 => PlayerAction
|
||||
0x15 => SteerVehicle
|
||||
0x16 => ResourcePackStatus
|
||||
0x17 => HeldItemChange
|
||||
0x18 => CreativeInventoryAction
|
||||
0x19 => SetSign
|
||||
0x1a => ArmSwing
|
||||
0x1b => SpectateTeleport
|
||||
0x1c => PlayerBlockPlacement
|
||||
0x1d => UseItem
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => SpawnObject
|
||||
0x01 => SpawnExperienceOrb
|
||||
0x02 => SpawnGlobalEntity
|
||||
0x03 => SpawnMob
|
||||
0x04 => SpawnPainting
|
||||
0x05 => SpawnPlayer
|
||||
0x06 => Animation
|
||||
0x07 => Statistics
|
||||
0x08 => BlockBreakAnimation
|
||||
0x09 => UpdateBlockEntity
|
||||
0x0a => BlockAction
|
||||
0x0b => BlockChange
|
||||
0x0c => BossBar
|
||||
0x0d => ServerDifficulty
|
||||
0x0e => TabCompleteReply
|
||||
0x0f => ServerMessage
|
||||
0x10 => MultiBlockChange
|
||||
0x11 => ConfirmTransaction
|
||||
0x12 => WindowClose
|
||||
0x13 => WindowOpen
|
||||
0x14 => WindowItems
|
||||
0x15 => WindowProperty
|
||||
0x16 => WindowSetSlot
|
||||
0x17 => SetCooldown
|
||||
0x18 => PluginMessageClientbound
|
||||
0x19 => NamedSoundEffect
|
||||
0x1a => Disconnect
|
||||
0x1b => EntityAction
|
||||
0x1c => Explosion
|
||||
0x1d => ChunkUnload
|
||||
0x1e => ChangeGameState
|
||||
0x1f => KeepAliveClientbound_VarInt
|
||||
0x20 => ChunkData
|
||||
0x21 => Effect
|
||||
0x22 => Particle
|
||||
0x23 => JoinGame
|
||||
0x24 => Maps
|
||||
0x25 => EntityMove
|
||||
0x26 => EntityLookAndMove
|
||||
0x27 => EntityLook
|
||||
0x28 => Entity
|
||||
0x29 => VehicleTeleport
|
||||
0x2a => SignEditorOpen
|
||||
0x2b => PlayerAbilities
|
||||
0x2c => CombatEvent
|
||||
0x2d => PlayerInfo
|
||||
0x2e => TeleportPlayer
|
||||
0x2f => EntityUsedBed
|
||||
0x30 => EntityDestroy
|
||||
0x31 => EntityRemoveEffect
|
||||
0x32 => ResourcePackSend
|
||||
0x33 => Respawn
|
||||
0x34 => EntityHeadLook
|
||||
0x35 => WorldBorder
|
||||
0x36 => Camera
|
||||
0x37 => SetCurrentHotbarSlot
|
||||
0x38 => ScoreboardDisplay
|
||||
0x39 => EntityMetadata
|
||||
0x3a => EntityAttach
|
||||
0x3b => EntityVelocity
|
||||
0x3c => EntityEquipment
|
||||
0x3d => SetExperience
|
||||
0x3e => UpdateHealth
|
||||
0x3f => ScoreboardObjective
|
||||
0x40 => SetPassengers
|
||||
0x41 => Teams
|
||||
0x42 => UpdateScore
|
||||
0x43 => SpawnPosition
|
||||
0x44 => TimeUpdate
|
||||
0x45 => Title
|
||||
0x46 => SoundEffect
|
||||
0x47 => PlayerListHeaderFooter
|
||||
0x48 => CollectItem
|
||||
0x49 => EntityTeleport
|
||||
0x4a => EntityProperties
|
||||
0x4b => EntityEffect
|
||||
}
|
||||
}
|
||||
login Login {
|
||||
serverbound Serverbound {
|
||||
0x00 => LoginStart
|
||||
0x01 => EncryptionResponse
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => LoginDisconnect
|
||||
0x01 => EncryptionRequest
|
||||
0x02 => LoginSuccess
|
||||
0x03 => SetInitialCompression
|
||||
}
|
||||
}
|
||||
status Status {
|
||||
serverbound Serverbound {
|
||||
0x00 => StatusRequest
|
||||
0x01 => StatusPing
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => StatusResponse
|
||||
0x01 => StatusPong
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
protocol_packet_ids!(
|
||||
handshake Handshaking {
|
||||
serverbound Serverbound {
|
||||
0x00 => Handshake
|
||||
}
|
||||
clientbound Clientbound {
|
||||
}
|
||||
}
|
||||
play Play {
|
||||
serverbound Serverbound {
|
||||
0x00 => TeleportConfirm
|
||||
0x01 => TabComplete
|
||||
0x02 => ChatMessage
|
||||
0x03 => ClientStatus
|
||||
0x04 => ClientSettings
|
||||
0x05 => ConfirmTransactionServerbound
|
||||
0x06 => EnchantItem
|
||||
0x07 => ClickWindow
|
||||
0x08 => CloseWindow
|
||||
0x09 => PluginMessageServerbound
|
||||
0x0a => UseEntity
|
||||
0x0b => KeepAliveServerbound_i64
|
||||
0x0c => Player
|
||||
0x0d => PlayerPosition
|
||||
0x0e => PlayerPositionLook
|
||||
0x0f => PlayerLook
|
||||
0x10 => VehicleMove
|
||||
0x11 => SteerBoat
|
||||
0x12 => CraftRecipeRequest
|
||||
0x13 => ClientAbilities
|
||||
0x14 => PlayerDigging
|
||||
0x15 => PlayerAction
|
||||
0x16 => SteerVehicle
|
||||
0x17 => CraftingBookData
|
||||
0x18 => ResourcePackStatus
|
||||
0x19 => AdvancementTab
|
||||
0x1a => HeldItemChange
|
||||
0x1b => CreativeInventoryAction
|
||||
0x1c => SetSign
|
||||
0x1d => ArmSwing
|
||||
0x1e => SpectateTeleport
|
||||
0x1f => PlayerBlockPlacement
|
||||
0x20 => UseItem
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => SpawnObject
|
||||
0x01 => SpawnExperienceOrb
|
||||
0x02 => SpawnGlobalEntity
|
||||
0x03 => SpawnMob
|
||||
0x04 => SpawnPainting
|
||||
0x05 => SpawnPlayer
|
||||
0x06 => Animation
|
||||
0x07 => Statistics
|
||||
0x08 => BlockBreakAnimation
|
||||
0x09 => UpdateBlockEntity
|
||||
0x0a => BlockAction
|
||||
0x0b => BlockChange
|
||||
0x0c => BossBar
|
||||
0x0d => ServerDifficulty
|
||||
0x0e => TabCompleteReply
|
||||
0x0f => ServerMessage
|
||||
0x10 => MultiBlockChange
|
||||
0x11 => ConfirmTransaction
|
||||
0x12 => WindowClose
|
||||
0x13 => WindowOpen
|
||||
0x14 => WindowItems
|
||||
0x15 => WindowProperty
|
||||
0x16 => WindowSetSlot
|
||||
0x17 => SetCooldown
|
||||
0x18 => PluginMessageClientbound
|
||||
0x19 => NamedSoundEffect
|
||||
0x1a => Disconnect
|
||||
0x1b => EntityAction
|
||||
0x1c => Explosion
|
||||
0x1d => ChunkUnload
|
||||
0x1e => ChangeGameState
|
||||
0x1f => KeepAliveClientbound_i64
|
||||
0x20 => ChunkData
|
||||
0x21 => Effect
|
||||
0x22 => Particle
|
||||
0x23 => JoinGame
|
||||
0x24 => Maps
|
||||
0x25 => Entity
|
||||
0x26 => EntityMove
|
||||
0x27 => EntityLookAndMove
|
||||
0x28 => EntityLook
|
||||
0x29 => VehicleTeleport
|
||||
0x2a => SignEditorOpen
|
||||
0x2b => CraftRecipeResponse
|
||||
0x2c => PlayerAbilities
|
||||
0x2d => CombatEvent
|
||||
0x2e => PlayerInfo
|
||||
0x2f => TeleportPlayer
|
||||
0x30 => EntityUsedBed
|
||||
0x31 => UnlockRecipes
|
||||
0x32 => EntityDestroy
|
||||
0x33 => EntityRemoveEffect
|
||||
0x34 => ResourcePackSend
|
||||
0x35 => Respawn
|
||||
0x36 => EntityHeadLook
|
||||
0x37 => SelectAdvancementTab
|
||||
0x38 => WorldBorder
|
||||
0x39 => Camera
|
||||
0x3a => SetCurrentHotbarSlot
|
||||
0x3b => ScoreboardDisplay
|
||||
0x3c => EntityMetadata
|
||||
0x3d => EntityAttach
|
||||
0x3e => EntityVelocity
|
||||
0x3f => EntityEquipment
|
||||
0x40 => SetExperience
|
||||
0x41 => UpdateHealth
|
||||
0x42 => ScoreboardObjective
|
||||
0x43 => SetPassengers
|
||||
0x44 => Teams
|
||||
0x45 => UpdateScore
|
||||
0x46 => SpawnPosition
|
||||
0x47 => TimeUpdate
|
||||
0x48 => Title
|
||||
0x49 => SoundEffect
|
||||
0x4a => PlayerListHeaderFooter
|
||||
0x4b => CollectItem
|
||||
0x4c => EntityTeleport
|
||||
0x4d => Advancements
|
||||
0x4e => EntityProperties
|
||||
0x4f => EntityEffect
|
||||
}
|
||||
}
|
||||
login Login {
|
||||
serverbound Serverbound {
|
||||
0x00 => LoginStart
|
||||
0x01 => EncryptionResponse
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => LoginDisconnect
|
||||
0x01 => EncryptionRequest
|
||||
0x02 => LoginSuccess
|
||||
0x03 => SetInitialCompression
|
||||
}
|
||||
}
|
||||
status Status {
|
||||
serverbound Serverbound {
|
||||
0x00 => StatusRequest
|
||||
0x01 => StatusPing
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => StatusResponse
|
||||
0x01 => StatusPong
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ impl ServerList {
|
|||
|
||||
// Don't block the main thread whilst pinging the server
|
||||
thread::spawn(move || {
|
||||
match protocol::Conn::new(&address).and_then(|conn| conn.do_status()) {
|
||||
match protocol::Conn::new(&address, protocol::SUPPORTED_PROTOCOLS[0]).and_then(|conn| conn.do_status()) {
|
||||
Ok(res) => {
|
||||
let mut desc = res.0.description;
|
||||
format::convert_legacy(&mut desc);
|
||||
|
@ -484,7 +484,7 @@ impl super::Screen for ServerList {
|
|||
if res.exists {
|
||||
{
|
||||
let mut players = s.players.borrow_mut();
|
||||
let txt = if res.protocol_version == protocol::SUPPORTED_PROTOCOL {
|
||||
let txt = if protocol::SUPPORTED_PROTOCOLS.contains(&res.protocol_version) {
|
||||
players.colour.1 = 255;
|
||||
players.colour.2 = 255;
|
||||
format!("{}/{}", res.online, res.max)
|
||||
|
|
|
@ -104,7 +104,7 @@ macro_rules! handle_packet {
|
|||
impl Server {
|
||||
|
||||
pub fn connect(resources: Arc<RwLock<resources::Manager>>, profile: mojang::Profile, address: &str, protocol_version: i32) -> Result<Server, protocol::Error> {
|
||||
let mut conn = protocol::Conn::new(address)?;
|
||||
let mut conn = protocol::Conn::new(address, protocol_version)?;
|
||||
|
||||
let host = conn.host.clone();
|
||||
let port = conn.port;
|
||||
|
@ -374,7 +374,8 @@ impl Server {
|
|||
self pck {
|
||||
JoinGame => on_game_join,
|
||||
Respawn => on_respawn,
|
||||
KeepAliveClientbound => on_keep_alive,
|
||||
KeepAliveClientbound_i64 => on_keep_alive_i64,
|
||||
KeepAliveClientbound_VarInt => on_keep_alive_varint,
|
||||
ChunkData => on_chunk_data,
|
||||
ChunkUnload => on_chunk_unload,
|
||||
BlockChange => on_block_change,
|
||||
|
@ -536,8 +537,14 @@ impl Server {
|
|||
let _ = self.conn.as_mut().unwrap().write_packet(p); // TODO handle errors
|
||||
}
|
||||
|
||||
fn on_keep_alive(&mut self, keep_alive: packet::play::clientbound::KeepAliveClientbound) {
|
||||
self.write_packet(packet::play::serverbound::KeepAliveServerbound {
|
||||
fn on_keep_alive_i64(&mut self, keep_alive: packet::play::clientbound::KeepAliveClientbound_i64) {
|
||||
self.write_packet(packet::play::serverbound::KeepAliveServerbound_i64 {
|
||||
id: keep_alive.id,
|
||||
});
|
||||
}
|
||||
|
||||
fn on_keep_alive_varint(&mut self, keep_alive: packet::play::clientbound::KeepAliveClientbound_VarInt) {
|
||||
self.write_packet(packet::play::serverbound::KeepAliveServerbound_VarInt {
|
||||
id: keep_alive.id,
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue