Add 15w39c (74) multiprotocol support (#56)

Closes https://github.com/iceiix/steven/pull/17
This is the biggest multi-protocol change yet, adding many new packet variants and implementing the most, necessitating a respectable amount of refactoring. The last of the "easy" protocols (already implemented, and cribbed from Steven commit history).
For https://github.com/iceiix/steven/issues/18 Enhance protocol support

* Add 15w39c packet IDs

* Add 15w39c packet changes

* Implement EntityMove i16 and i8 packet variants

* Implement EntityLookAndMove i16 and i8 packet variants

* Implement TeleportPlayer no confirm / with confirm packet variants

* Implement EntityTeleport f64 and i32 packet variants

* Implement SpawnPlayer f64 and i32 packet variants
This commit is contained in:
iceiix 2018-12-03 19:29:02 -08:00 committed by GitHub
parent b6de7103a7
commit 3f5024d4ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 420 additions and 81 deletions

View File

@ -37,7 +37,7 @@ use flate2::Compression;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use crate::shared::Position; use crate::shared::Position;
pub const SUPPORTED_PROTOCOLS: [i32; 6] = [340, 316, 315, 210, 109, 107]; pub const SUPPORTED_PROTOCOLS: [i32; 7] = [340, 316, 315, 210, 109, 107, 74];
/// Helper macro for defining packets /// Helper macro for defining packets

View File

@ -61,6 +61,11 @@ state_packets!(
field has_target: bool =, field has_target: bool =,
field target: Option<Position> = when(|p: &TabComplete| p.has_target), field target: Option<Position> = when(|p: &TabComplete| p.has_target),
} }
packet TabComplete_NoAssume {
field text: String =,
field has_target: bool =,
field target: Option<Position> = when(|p: &TabComplete_NoAssume| p.has_target),
}
/// ChatMessage is sent by the client when it sends a chat message or /// ChatMessage is sent by the client when it sends a chat message or
/// executes a command (prefixed by '/'). /// executes a command (prefixed by '/').
packet ChatMessage { packet ChatMessage {
@ -79,6 +84,14 @@ state_packets!(
field displayed_skin_parts: u8 =, field displayed_skin_parts: u8 =,
field main_hand: VarInt =, field main_hand: VarInt =,
} }
packet ClientSettings_u8 {
field locale: String =,
field view_distance: u8 =,
field chat_mode: u8 =,
field chat_colors: bool =,
field displayed_skin_parts: u8 =,
field main_hand: VarInt =,
}
/// ConfirmTransactionServerbound is a reply to ConfirmTransaction. /// ConfirmTransactionServerbound is a reply to ConfirmTransaction.
packet ConfirmTransactionServerbound { packet ConfirmTransactionServerbound {
field id: u8 =, field id: u8 =,
@ -99,6 +112,14 @@ state_packets!(
field mode: VarInt =, field mode: VarInt =,
field clicked_item: Option<item::Stack> =, field clicked_item: Option<item::Stack> =,
} }
packet ClickWindow_u8 {
field id: u8 =,
field slot: i16 =,
field button: u8 =,
field action_number: u16 =,
field mode: u8 =,
field clicked_item: Option<item::Stack> =,
}
/// CloseWindow is sent when the client closes a window. /// CloseWindow is sent when the client closes a window.
packet CloseWindow { packet CloseWindow {
field id: u8 =, field id: u8 =,
@ -189,6 +210,11 @@ state_packets!(
field location: Position =, field location: Position =,
field face: u8 =, field face: u8 =,
} }
packet PlayerDigging_u8 {
field status: u8 =,
field location: Position =,
field face: u8 =,
}
/// PlayerAction is sent when a player preforms various actions. /// PlayerAction is sent when a player preforms various actions.
packet PlayerAction { packet PlayerAction {
field entity_id: VarInt =, field entity_id: VarInt =,
@ -290,6 +316,20 @@ state_packets!(
field velocity_y: i16 =, field velocity_y: i16 =,
field velocity_z: i16 =, field velocity_z: i16 =,
} }
packet SpawnObject_i32 {
field entity_id: VarInt =,
field uuid: UUID =,
field ty: u8 =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field pitch: i8 =,
field yaw: i8 =,
field data: i32 =,
field velocity_x: i16 =,
field velocity_y: i16 =,
field velocity_z: i16 =,
}
/// SpawnExperienceOrb spawns a single experience orb into the world when /// SpawnExperienceOrb spawns a single experience orb into the world when
/// it is in range of the client. The count controls the amount of experience /// it is in range of the client. The count controls the amount of experience
/// gained when collected. /// gained when collected.
@ -300,6 +340,13 @@ state_packets!(
field z: f64 =, field z: f64 =,
field count: i16 =, field count: i16 =,
} }
packet SpawnExperienceOrb_i32 {
field entity_id: VarInt =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field count: i16 =,
}
/// SpawnGlobalEntity spawns an entity which is visible from anywhere in the /// SpawnGlobalEntity spawns an entity which is visible from anywhere in the
/// world. Currently only used for lightning. /// world. Currently only used for lightning.
packet SpawnGlobalEntity { packet SpawnGlobalEntity {
@ -309,6 +356,13 @@ state_packets!(
field y: f64 =, field y: f64 =,
field z: f64 =, field z: f64 =,
} }
packet SpawnGlobalEntity_i32 {
field entity_id: VarInt =,
field ty: u8 =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
}
/// SpawnMob is used to spawn a living entity into the world when it is in /// SpawnMob is used to spawn a living entity into the world when it is in
/// range of the client. /// range of the client.
packet SpawnMob { packet SpawnMob {
@ -341,6 +395,21 @@ state_packets!(
field velocity_z: i16 =, field velocity_z: i16 =,
field metadata: types::Metadata =, field metadata: types::Metadata =,
} }
packet SpawnMob_u8_i32 {
field entity_id: VarInt =,
field uuid: UUID =,
field ty: u8 =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field yaw: i8 =,
field pitch: i8 =,
field head_pitch: i8 =,
field velocity_x: i16 =,
field velocity_y: i16 =,
field velocity_z: i16 =,
field metadata: types::Metadata =,
}
/// SpawnPainting spawns a painting into the world when it is in range of /// SpawnPainting spawns a painting into the world when it is in range of
/// the client. The title effects the size and the texture of the painting. /// the client. The title effects the size and the texture of the painting.
packet SpawnPainting { packet SpawnPainting {
@ -350,10 +419,16 @@ state_packets!(
field location: Position =, field location: Position =,
field direction: u8 =, field direction: u8 =,
} }
packet SpawnPainting_NoUUID {
field entity_id: VarInt =,
field title: String =,
field location: Position =,
field direction: u8 =,
}
/// SpawnPlayer is used to spawn a player when they are in range of the client. /// SpawnPlayer is used to spawn a player when they are in range of the client.
/// This packet alone isn't enough to display the player as the skin and username /// This packet alone isn't enough to display the player as the skin and username
/// information is in the player information packet. /// information is in the player information packet.
packet SpawnPlayer { packet SpawnPlayer_f64 {
field entity_id: VarInt =, field entity_id: VarInt =,
field uuid: UUID =, field uuid: UUID =,
field x: f64 =, field x: f64 =,
@ -363,6 +438,16 @@ state_packets!(
field pitch: i8 =, field pitch: i8 =,
field metadata: types::Metadata =, field metadata: types::Metadata =,
} }
packet SpawnPlayer_i32 {
field entity_id: VarInt =,
field uuid: UUID =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field yaw: i8 =,
field pitch: i8 =,
field metadata: types::Metadata =,
}
/// Animation is sent by the server to play an animation on a specific entity. /// Animation is sent by the server to play an animation on a specific entity.
packet Animation { packet Animation {
field entity_id: VarInt =, field entity_id: VarInt =,
@ -506,6 +591,14 @@ state_packets!(
field volume: f32 =, field volume: f32 =,
field pitch: u8 =, field pitch: u8 =,
} }
packet NamedSoundEffect_u8_NoCategory {
field name: String =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field volume: f32 =,
field pitch: u8 =,
}
/// Disconnect causes the client to disconnect displaying the passed reason. /// Disconnect causes the client to disconnect displaying the passed reason.
packet Disconnect { packet Disconnect {
field reason: format::Component =, field reason: format::Component =,
@ -534,6 +627,10 @@ state_packets!(
field x: i32 =, field x: i32 =,
field z: i32 =, field z: i32 =,
} }
/// SetCompression updates the compression threshold.
packet SetCompression {
field threshold: VarInt =,
}
/// ChangeGameState is used to modify the game's state like gamemode or /// ChangeGameState is used to modify the game's state like gamemode or
/// weather. /// weather.
packet ChangeGameState { packet ChangeGameState {
@ -641,15 +738,22 @@ state_packets!(
field data: Option<LenPrefixedBytes<VarInt>> = when(|p: &Maps| p.columns > 0), field data: Option<LenPrefixedBytes<VarInt>> = when(|p: &Maps| p.columns > 0),
} }
/// EntityMove moves the entity with the id by the offsets provided. /// EntityMove moves the entity with the id by the offsets provided.
packet EntityMove { packet EntityMove_i16 {
field entity_id: VarInt =, field entity_id: VarInt =,
field delta_x: i16 =, field delta_x: i16 =,
field delta_y: i16 =, field delta_y: i16 =,
field delta_z: i16 =, field delta_z: i16 =,
field on_ground: bool =, field on_ground: bool =,
} }
packet EntityMove_i8 {
field entity_id: VarInt =,
field delta_x: i8 =,
field delta_y: i8 =,
field delta_z: i8 =,
field on_ground: bool =,
}
/// EntityLookAndMove is a combination of EntityMove and EntityLook. /// EntityLookAndMove is a combination of EntityMove and EntityLook.
packet EntityLookAndMove { packet EntityLookAndMove_i16 {
field entity_id: VarInt =, field entity_id: VarInt =,
field delta_x: i16 =, field delta_x: i16 =,
field delta_y: i16 =, field delta_y: i16 =,
@ -658,6 +762,15 @@ state_packets!(
field pitch: i8 =, field pitch: i8 =,
field on_ground: bool =, field on_ground: bool =,
} }
packet EntityLookAndMove_i8 {
field entity_id: VarInt =,
field delta_x: i8 =,
field delta_y: i8 =,
field delta_z: i8 =,
field yaw: i8 =,
field pitch: i8 =,
field on_ground: bool =,
}
/// EntityLook rotates the entity to the new angles provided. /// EntityLook rotates the entity to the new angles provided.
packet EntityLook { packet EntityLook {
field entity_id: VarInt =, field entity_id: VarInt =,
@ -711,7 +824,7 @@ state_packets!(
/// TeleportPlayer is sent to change the player's position. The client is expected /// TeleportPlayer is sent to change the player's position. The client is expected
/// to reply to the server with the same positions as contained in this packet /// to reply to the server with the same positions as contained in this packet
/// otherwise will reject future packets. /// otherwise will reject future packets.
packet TeleportPlayer { packet TeleportPlayer_WithConfirm {
field x: f64 =, field x: f64 =,
field y: f64 =, field y: f64 =,
field z: f64 =, field z: f64 =,
@ -720,6 +833,14 @@ state_packets!(
field flags: u8 =, field flags: u8 =,
field teleport_id: VarInt =, field teleport_id: VarInt =,
} }
packet TeleportPlayer_NoConfirm {
field x: f64 =,
field y: f64 =,
field z: f64 =,
field yaw: f32 =,
field pitch: f32 =,
field flags: u8 =,
}
/// EntityUsedBed is sent by the server when a player goes to bed. /// EntityUsedBed is sent by the server when a player goes to bed.
packet EntityUsedBed { packet EntityUsedBed {
field entity_id: VarInt =, field entity_id: VarInt =,
@ -802,6 +923,11 @@ state_packets!(
field entity_id: i32 =, field entity_id: i32 =,
field vehicle: i32 =, field vehicle: i32 =,
} }
packet EntityAttach_leashed {
field entity_id: i32 =,
field vehicle: i32 =,
field leash: bool =,
}
/// EntityVelocity sets the velocity of an entity in 1/8000 of a block /// EntityVelocity sets the velocity of an entity in 1/8000 of a block
/// per a tick. /// per a tick.
packet EntityVelocity { packet EntityVelocity {
@ -894,6 +1020,14 @@ state_packets!(
field fade_stay: Option<i32> = when(|p: &Title_notext| p.action.0 == 2), field fade_stay: Option<i32> = when(|p: &Title_notext| p.action.0 == 2),
field fade_out: Option<i32> = when(|p: &Title_notext| p.action.0 == 2), field fade_out: Option<i32> = when(|p: &Title_notext| p.action.0 == 2),
} }
packet Title_notext_component {
field action: VarInt =,
field title: Option<format::Component> = when(|p: &Title_notext_component| p.action.0 == 0),
field sub_title: Option<format::Component> = when(|p: &Title_notext_component| p.action.0 == 1),
field fade_in: Option<format::Component> = when(|p: &Title_notext_component| p.action.0 == 2),
field fade_stay: Option<format::Component> = when(|p: &Title_notext_component| p.action.0 == 2),
field fade_out: Option<format::Component> = when(|p: &Title_notext_component| p.action.0 == 2),
}
/// UpdateSign sets or changes the text on a sign. /// UpdateSign sets or changes the text on a sign.
packet UpdateSign { packet UpdateSign {
field location: Position =, field location: Position =,
@ -939,7 +1073,7 @@ state_packets!(
} }
/// EntityTeleport teleports the entity to the target location. This is /// EntityTeleport teleports the entity to the target location. This is
/// sent if the entity moves further than EntityMove allows. /// sent if the entity moves further than EntityMove allows.
packet EntityTeleport { packet EntityTeleport_f64 {
field entity_id: VarInt =, field entity_id: VarInt =,
field x: f64 =, field x: f64 =,
field y: f64 =, field y: f64 =,
@ -948,6 +1082,15 @@ state_packets!(
field pitch: i8 =, field pitch: i8 =,
field on_ground: bool =, field on_ground: bool =,
} }
packet EntityTeleport_i32 {
field entity_id: VarInt =,
field x: i32 =,
field y: i32 =,
field z: i32 =,
field yaw: i8 =,
field pitch: i8 =,
field on_ground: bool =,
}
packet Advancements { packet Advancements {
field reset_clear: bool =, field reset_clear: bool =,
field mapping: LenPrefixed<VarInt, packet::Advancement> =, field mapping: LenPrefixed<VarInt, packet::Advancement> =,

View File

@ -5,6 +5,7 @@ mod v1_11_2;
mod v1_10_2; mod v1_10_2;
mod v1_9_2; mod v1_9_2;
mod v1_9; mod v1_9;
mod v15w39c;
pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 {
match version { match version {
@ -28,6 +29,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir:
// 1.9 // 1.9
107 => v1_9::translate_internal_packet_id(state, dir, id, to_internal), 107 => v1_9::translate_internal_packet_id(state, dir, id, to_internal),
// 15w39a/b/c
74 => v15w39c::translate_internal_packet_id(state, dir, id, to_internal),
_ => panic!("unsupported protocol version"), _ => panic!("unsupported protocol version"),
} }
} }

View File

@ -0,0 +1,141 @@
protocol_packet_ids!(
handshake Handshaking {
serverbound Serverbound {
0x00 => Handshake
}
clientbound Clientbound {
}
}
play Play {
serverbound Serverbound {
0x00 => TabComplete_NoAssume
0x01 => ChatMessage
0x02 => ClientStatus
0x03 => ClientSettings_u8
0x04 => ConfirmTransactionServerbound
0x05 => EnchantItem
0x06 => ClickWindow_u8
0x07 => CloseWindow
0x08 => PluginMessageServerbound
0x09 => UseEntity
0x0a => KeepAliveServerbound_VarInt
0x0b => PlayerPosition
0x0c => PlayerPositionLook
0x0d => PlayerLook
0x0e => Player
0x0f => ClientAbilities
0x10 => PlayerDigging_u8
0x11 => PlayerAction
0x12 => SteerVehicle
0x13 => ResourcePackStatus
0x14 => HeldItemChange
0x15 => CreativeInventoryAction
0x16 => SetSign
0x17 => ArmSwing
0x18 => SpectateTeleport
0x19 => PlayerBlockPlacement_u8
0x1a => UseItem
}
clientbound Clientbound {
0x00 => SpawnObject_i32
0x01 => SpawnExperienceOrb_i32
0x02 => SpawnGlobalEntity_i32
0x03 => SpawnMob_u8_i32
0x04 => SpawnPainting_NoUUID
0x05 => SpawnPlayer_i32
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 => Disconnect
0x1a => EntityAction
0x1b => Explosion
0x1c => ChunkUnload
0x1d => SetCompression
0x1e => ChangeGameState
0x1f => KeepAliveClientbound_VarInt
0x20 => ChunkData_NoEntities
0x21 => Effect
0x22 => Particle
0x23 => NamedSoundEffect_u8_NoCategory
0x24 => JoinGame_i8
0x25 => Maps
0x26 => EntityMove_i8
0x27 => EntityLookAndMove_i8
0x28 => EntityLook
0x29 => Entity
0x2a => SignEditorOpen
0x2b => PlayerAbilities
0x2c => CombatEvent
0x2d => PlayerInfo
0x2e => TeleportPlayer_NoConfirm
0x2f => EntityUsedBed
0x30 => EntityDestroy
0x31 => EntityRemoveEffect
0x32 => ResourcePackSend
0x33 => Respawn
0x34 => EntityHeadLook
0x35 => WorldBorder
0x36 => Camera
0x37 => SetCurrentHotbarSlot
0x38 => ScoreboardDisplay
0x39 => EntityMetadata
0x3a => EntityAttach_leashed
0x3b => EntityVelocity
0x3c => EntityEquipment
0x3d => SetExperience
0x3e => UpdateHealth
0x3f => ScoreboardObjective
0x40 => Teams
0x41 => UpdateScore
0x42 => SpawnPosition
0x43 => TimeUpdate
0x44 => Title_notext_component
0x45 => UpdateSign
0x46 => PlayerListHeaderFooter
0x47 => CollectItem_nocount
0x48 => EntityTeleport_i32
0x49 => EntityProperties
0x4a => 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
}
}
);

View File

@ -45,7 +45,7 @@ protocol_packet_ids!(
0x02 => SpawnGlobalEntity 0x02 => SpawnGlobalEntity
0x03 => SpawnMob_u8 0x03 => SpawnMob_u8
0x04 => SpawnPainting 0x04 => SpawnPainting
0x05 => SpawnPlayer 0x05 => SpawnPlayer_f64
0x06 => Animation 0x06 => Animation
0x07 => Statistics 0x07 => Statistics
0x08 => BlockBreakAnimation 0x08 => BlockBreakAnimation
@ -77,8 +77,8 @@ protocol_packet_ids!(
0x22 => Particle 0x22 => Particle
0x23 => JoinGame_i32 0x23 => JoinGame_i32
0x24 => Maps 0x24 => Maps
0x25 => EntityMove 0x25 => EntityMove_i16
0x26 => EntityLookAndMove 0x26 => EntityLookAndMove_i16
0x27 => EntityLook 0x27 => EntityLook
0x28 => Entity 0x28 => Entity
0x29 => VehicleTeleport 0x29 => VehicleTeleport
@ -86,7 +86,7 @@ protocol_packet_ids!(
0x2b => PlayerAbilities 0x2b => PlayerAbilities
0x2c => CombatEvent 0x2c => CombatEvent
0x2d => PlayerInfo 0x2d => PlayerInfo
0x2e => TeleportPlayer 0x2e => TeleportPlayer_WithConfirm
0x2f => EntityUsedBed 0x2f => EntityUsedBed
0x30 => EntityDestroy 0x30 => EntityDestroy
0x31 => EntityRemoveEffect 0x31 => EntityRemoveEffect
@ -113,7 +113,7 @@ protocol_packet_ids!(
0x46 => SoundEffect 0x46 => SoundEffect
0x47 => PlayerListHeaderFooter 0x47 => PlayerListHeaderFooter
0x48 => CollectItem_nocount 0x48 => CollectItem_nocount
0x49 => EntityTeleport 0x49 => EntityTeleport_f64
0x4a => EntityProperties 0x4a => EntityProperties
0x4b => EntityEffect 0x4b => EntityEffect
} }

View File

@ -45,7 +45,7 @@ protocol_packet_ids!(
0x02 => SpawnGlobalEntity 0x02 => SpawnGlobalEntity
0x03 => SpawnMob 0x03 => SpawnMob
0x04 => SpawnPainting 0x04 => SpawnPainting
0x05 => SpawnPlayer 0x05 => SpawnPlayer_f64
0x06 => Animation 0x06 => Animation
0x07 => Statistics 0x07 => Statistics
0x08 => BlockBreakAnimation 0x08 => BlockBreakAnimation
@ -77,8 +77,8 @@ protocol_packet_ids!(
0x22 => Particle 0x22 => Particle
0x23 => JoinGame_i32 0x23 => JoinGame_i32
0x24 => Maps 0x24 => Maps
0x25 => EntityMove 0x25 => EntityMove_i16
0x26 => EntityLookAndMove 0x26 => EntityLookAndMove_i16
0x27 => EntityLook 0x27 => EntityLook
0x28 => Entity 0x28 => Entity
0x29 => VehicleTeleport 0x29 => VehicleTeleport
@ -86,7 +86,7 @@ protocol_packet_ids!(
0x2b => PlayerAbilities 0x2b => PlayerAbilities
0x2c => CombatEvent 0x2c => CombatEvent
0x2d => PlayerInfo 0x2d => PlayerInfo
0x2e => TeleportPlayer 0x2e => TeleportPlayer_WithConfirm
0x2f => EntityUsedBed 0x2f => EntityUsedBed
0x30 => EntityDestroy 0x30 => EntityDestroy
0x31 => EntityRemoveEffect 0x31 => EntityRemoveEffect
@ -113,7 +113,7 @@ protocol_packet_ids!(
0x46 => SoundEffect 0x46 => SoundEffect
0x47 => PlayerListHeaderFooter 0x47 => PlayerListHeaderFooter
0x48 => CollectItem 0x48 => CollectItem
0x49 => EntityTeleport 0x49 => EntityTeleport_f64
0x4a => EntityProperties 0x4a => EntityProperties
0x4b => EntityEffect 0x4b => EntityEffect
} }

View File

@ -48,7 +48,7 @@ protocol_packet_ids!(
0x02 => SpawnGlobalEntity 0x02 => SpawnGlobalEntity
0x03 => SpawnMob 0x03 => SpawnMob
0x04 => SpawnPainting 0x04 => SpawnPainting
0x05 => SpawnPlayer 0x05 => SpawnPlayer_f64
0x06 => Animation 0x06 => Animation
0x07 => Statistics 0x07 => Statistics
0x08 => BlockBreakAnimation 0x08 => BlockBreakAnimation
@ -81,8 +81,8 @@ protocol_packet_ids!(
0x23 => JoinGame_i32 0x23 => JoinGame_i32
0x24 => Maps 0x24 => Maps
0x25 => Entity 0x25 => Entity
0x26 => EntityMove 0x26 => EntityMove_i16
0x27 => EntityLookAndMove 0x27 => EntityLookAndMove_i16
0x28 => EntityLook 0x28 => EntityLook
0x29 => VehicleTeleport 0x29 => VehicleTeleport
0x2a => SignEditorOpen 0x2a => SignEditorOpen
@ -90,7 +90,7 @@ protocol_packet_ids!(
0x2c => PlayerAbilities 0x2c => PlayerAbilities
0x2d => CombatEvent 0x2d => CombatEvent
0x2e => PlayerInfo 0x2e => PlayerInfo
0x2f => TeleportPlayer 0x2f => TeleportPlayer_WithConfirm
0x30 => EntityUsedBed 0x30 => EntityUsedBed
0x31 => UnlockRecipes 0x31 => UnlockRecipes
0x32 => EntityDestroy 0x32 => EntityDestroy
@ -119,7 +119,7 @@ protocol_packet_ids!(
0x49 => SoundEffect 0x49 => SoundEffect
0x4a => PlayerListHeaderFooter 0x4a => PlayerListHeaderFooter
0x4b => CollectItem 0x4b => CollectItem
0x4c => EntityTeleport 0x4c => EntityTeleport_f64
0x4d => Advancements 0x4d => Advancements
0x4e => EntityProperties 0x4e => EntityProperties
0x4f => EntityEffect 0x4f => EntityEffect

View File

@ -45,7 +45,7 @@ protocol_packet_ids!(
0x02 => SpawnGlobalEntity 0x02 => SpawnGlobalEntity
0x03 => SpawnMob_u8 0x03 => SpawnMob_u8
0x04 => SpawnPainting 0x04 => SpawnPainting
0x05 => SpawnPlayer 0x05 => SpawnPlayer_f64
0x06 => Animation 0x06 => Animation
0x07 => Statistics 0x07 => Statistics
0x08 => BlockBreakAnimation 0x08 => BlockBreakAnimation
@ -77,8 +77,8 @@ protocol_packet_ids!(
0x22 => Particle 0x22 => Particle
0x23 => JoinGame_i8 0x23 => JoinGame_i8
0x24 => Maps 0x24 => Maps
0x25 => EntityMove 0x25 => EntityMove_i16
0x26 => EntityLookAndMove 0x26 => EntityLookAndMove_i16
0x27 => EntityLook 0x27 => EntityLook
0x28 => Entity 0x28 => Entity
0x29 => VehicleTeleport 0x29 => VehicleTeleport
@ -86,7 +86,7 @@ protocol_packet_ids!(
0x2b => PlayerAbilities 0x2b => PlayerAbilities
0x2c => CombatEvent 0x2c => CombatEvent
0x2d => PlayerInfo 0x2d => PlayerInfo
0x2e => TeleportPlayer 0x2e => TeleportPlayer_WithConfirm
0x2f => EntityUsedBed 0x2f => EntityUsedBed
0x30 => EntityDestroy 0x30 => EntityDestroy
0x31 => EntityRemoveEffect 0x31 => EntityRemoveEffect
@ -114,7 +114,7 @@ protocol_packet_ids!(
0x47 => SoundEffect_u8 0x47 => SoundEffect_u8
0x48 => PlayerListHeaderFooter 0x48 => PlayerListHeaderFooter
0x49 => CollectItem_nocount 0x49 => CollectItem_nocount
0x4a => EntityTeleport 0x4a => EntityTeleport_f64
0x4b => EntityProperties 0x4b => EntityProperties
0x4c => EntityEffect 0x4c => EntityEffect
} }

View File

@ -45,7 +45,7 @@ protocol_packet_ids!(
0x02 => SpawnGlobalEntity 0x02 => SpawnGlobalEntity
0x03 => SpawnMob_u8 0x03 => SpawnMob_u8
0x04 => SpawnPainting 0x04 => SpawnPainting
0x05 => SpawnPlayer 0x05 => SpawnPlayer_f64
0x06 => Animation 0x06 => Animation
0x07 => Statistics 0x07 => Statistics
0x08 => BlockBreakAnimation 0x08 => BlockBreakAnimation
@ -77,8 +77,8 @@ protocol_packet_ids!(
0x22 => Particle 0x22 => Particle
0x23 => JoinGame_i32 0x23 => JoinGame_i32
0x24 => Maps 0x24 => Maps
0x25 => EntityMove 0x25 => EntityMove_i16
0x26 => EntityLookAndMove 0x26 => EntityLookAndMove_i16
0x27 => EntityLook 0x27 => EntityLook
0x28 => Entity 0x28 => Entity
0x29 => VehicleTeleport 0x29 => VehicleTeleport
@ -86,7 +86,7 @@ protocol_packet_ids!(
0x2b => PlayerAbilities 0x2b => PlayerAbilities
0x2c => CombatEvent 0x2c => CombatEvent
0x2d => PlayerInfo 0x2d => PlayerInfo
0x2e => TeleportPlayer 0x2e => TeleportPlayer_WithConfirm
0x2f => EntityUsedBed 0x2f => EntityUsedBed
0x30 => EntityDestroy 0x30 => EntityDestroy
0x31 => EntityRemoveEffect 0x31 => EntityRemoveEffect
@ -114,7 +114,7 @@ protocol_packet_ids!(
0x47 => SoundEffect_u8 0x47 => SoundEffect_u8
0x48 => PlayerListHeaderFooter 0x48 => PlayerListHeaderFooter
0x49 => CollectItem_nocount 0x49 => CollectItem_nocount
0x4a => EntityTeleport 0x4a => EntityTeleport_f64
0x4b => EntityProperties 0x4b => EntityProperties
0x4c => EntityEffect 0x4c => EntityEffect
} }

View File

@ -385,7 +385,8 @@ impl Server {
ChunkUnload => on_chunk_unload, ChunkUnload => on_chunk_unload,
BlockChange => on_block_change, BlockChange => on_block_change,
MultiBlockChange => on_multi_block_change, MultiBlockChange => on_multi_block_change,
TeleportPlayer => on_teleport, TeleportPlayer_WithConfirm => on_teleport_player_withconfirm,
TeleportPlayer_NoConfirm => on_teleport_player_noconfirm,
TimeUpdate => on_time_update, TimeUpdate => on_time_update,
ChangeGameState => on_game_state_change, ChangeGameState => on_game_state_change,
UpdateBlockEntity => on_block_entity_update, UpdateBlockEntity => on_block_entity_update,
@ -394,11 +395,15 @@ impl Server {
Disconnect => on_disconnect, Disconnect => on_disconnect,
// Entities // Entities
EntityDestroy => on_entity_destroy, EntityDestroy => on_entity_destroy,
SpawnPlayer => on_player_spawn, SpawnPlayer_f64 => on_player_spawn_f64,
EntityTeleport => on_entity_teleport, SpawnPlayer_i32 => on_player_spawn_i32,
EntityMove => on_entity_move, EntityTeleport_f64 => on_entity_teleport_f64,
EntityTeleport_i32 => on_entity_teleport_i32,
EntityMove_i16 => on_entity_move_i16,
EntityMove_i8 => on_entity_move_i8,
EntityLook => on_entity_look, EntityLook => on_entity_look,
EntityLookAndMove => on_entity_look_and_move, EntityLookAndMove_i16 => on_entity_look_and_move_i16,
EntityLookAndMove_i8 => on_entity_look_and_move_i8,
} }
}, },
Err(err) => panic!("Err: {:?}", err), Err(err) => panic!("Err: {:?}", err),
@ -647,25 +652,41 @@ impl Server {
} }
} }
fn on_entity_teleport(&mut self, entity_telport: packet::play::clientbound::EntityTeleport) { fn on_entity_teleport_f64(&mut self, entity_telport: packet::play::clientbound::EntityTeleport_f64) {
self.on_entity_teleport(entity_telport.entity_id.0, entity_telport.x, entity_telport.y, entity_telport.z, entity_telport.yaw as f64, entity_telport.pitch as f64, entity_telport.on_ground)
}
fn on_entity_teleport_i32(&mut self, entity_telport: packet::play::clientbound::EntityTeleport_i32) {
self.on_entity_teleport(entity_telport.entity_id.0, entity_telport.x as f64, entity_telport.y as f64, entity_telport.z as f64, entity_telport.yaw as f64, entity_telport.pitch as f64, entity_telport.on_ground)
}
fn on_entity_teleport(&mut self, entity_id: i32, x: f64, y: f64, z: f64, yaw: f64, pitch: f64, _on_ground: bool) {
use std::f64::consts::PI; use std::f64::consts::PI;
if let Some(entity) = self.entity_map.get(&entity_telport.entity_id.0) { if let Some(entity) = self.entity_map.get(&entity_id) {
let target_position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); let target_position = self.entities.get_component_mut(*entity, self.target_position).unwrap();
let target_rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); let target_rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap();
target_position.position.x = entity_telport.x; target_position.position.x = x;
target_position.position.y = entity_telport.y; target_position.position.y = y;
target_position.position.z = entity_telport.z; target_position.position.z = z;
target_rotation.yaw = -((entity_telport.yaw as f64) / 256.0) * PI * 2.0; target_rotation.yaw = -(yaw / 256.0) * PI * 2.0;
target_rotation.pitch = -((entity_telport.pitch as f64) / 256.0) * PI * 2.0; target_rotation.pitch = -(pitch / 256.0) * PI * 2.0;
} }
} }
fn on_entity_move(&mut self, m: packet::play::clientbound::EntityMove) { fn on_entity_move_i16(&mut self, m: packet::play::clientbound::EntityMove_i16) {
if let Some(entity) = self.entity_map.get(&m.entity_id.0) { self.on_entity_move(m.entity_id.0, m.delta_x as f64, m.delta_y as f64, m.delta_z as f64)
}
fn on_entity_move_i8(&mut self, m: packet::play::clientbound::EntityMove_i8) {
self.on_entity_move(m.entity_id.0, m.delta_x as f64, m.delta_y as f64, m.delta_z as f64)
}
fn on_entity_move(&mut self, entity_id: i32, delta_x: f64, delta_y: f64, delta_z: f64) {
if let Some(entity) = self.entity_map.get(&entity_id) {
let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); let position = self.entities.get_component_mut(*entity, self.target_position).unwrap();
position.position.x += m.delta_x as f64 / (32.0 * 128.0); position.position.x += delta_x / (32.0 * 128.0);
position.position.y += m.delta_y as f64 / (32.0 * 128.0); position.position.y += delta_y / (32.0 * 128.0);
position.position.z += m.delta_z as f64 / (32.0 * 128.0); position.position.z += delta_z / (32.0 * 128.0);
} }
} }
@ -678,78 +699,108 @@ impl Server {
} }
} }
fn on_entity_look_and_move(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove) { fn on_entity_look_and_move_i16(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove_i16) {
self.on_entity_look_and_move(lookmove.entity_id.0,
lookmove.delta_x as f64, lookmove.delta_y as f64, lookmove.delta_z as f64,
lookmove.yaw as f64, lookmove.pitch as f64)
}
fn on_entity_look_and_move_i8(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove_i8) {
self.on_entity_look_and_move(lookmove.entity_id.0,
lookmove.delta_x as f64, lookmove.delta_y as f64, lookmove.delta_z as f64,
lookmove.yaw as f64, lookmove.pitch as f64)
}
fn on_entity_look_and_move(&mut self, entity_id: i32, delta_x: f64, delta_y: f64, delta_z: f64, yaw: f64, pitch: f64) {
use std::f64::consts::PI; use std::f64::consts::PI;
if let Some(entity) = self.entity_map.get(&lookmove.entity_id.0) { if let Some(entity) = self.entity_map.get(&entity_id) {
let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); let position = self.entities.get_component_mut(*entity, self.target_position).unwrap();
let rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); let rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap();
position.position.x += lookmove.delta_x as f64 / (32.0 * 128.0); position.position.x += delta_x / (32.0 * 128.0);
position.position.y += lookmove.delta_y as f64 / (32.0 * 128.0); position.position.y += delta_y / (32.0 * 128.0);
position.position.z += lookmove.delta_z as f64 / (32.0 * 128.0); position.position.z += delta_z / (32.0 * 128.0);
rotation.yaw = -((lookmove.yaw as f64) / 256.0) * PI * 2.0; rotation.yaw = -(yaw / 256.0) * PI * 2.0;
rotation.pitch = -((lookmove.pitch as f64) / 256.0) * PI * 2.0; rotation.pitch = -(pitch / 256.0) * PI * 2.0;
} }
} }
fn on_player_spawn(&mut self, spawn: packet::play::clientbound::SpawnPlayer) { fn on_player_spawn_f64(&mut self, spawn: packet::play::clientbound::SpawnPlayer_f64) {
self.on_player_spawn(spawn.entity_id.0, spawn.uuid, spawn.x, spawn.y, spawn.z, spawn.yaw as f64, spawn.pitch as f64)
}
fn on_player_spawn_i32(&mut self, spawn: packet::play::clientbound::SpawnPlayer_i32) {
self.on_player_spawn(spawn.entity_id.0, spawn.uuid, spawn.x as f64, spawn.y as f64, spawn.z as f64, spawn.yaw as f64, spawn.pitch as f64)
}
fn on_player_spawn(&mut self, entity_id: i32, uuid: protocol::UUID, x: f64, y: f64, z: f64, pitch: f64, yaw: f64) {
use std::f64::consts::PI; use std::f64::consts::PI;
if let Some(entity) = self.entity_map.remove(&spawn.entity_id.0) { if let Some(entity) = self.entity_map.remove(&entity_id) {
self.entities.remove_entity(entity); self.entities.remove_entity(entity);
} }
let entity = entity::player::create_remote(&mut self.entities, self.players.get(&spawn.uuid).map_or("MISSING", |v| &v.name)); let entity = entity::player::create_remote(&mut self.entities, self.players.get(&uuid).map_or("MISSING", |v| &v.name));
let position = self.entities.get_component_mut(entity, self.position).unwrap(); let position = self.entities.get_component_mut(entity, self.position).unwrap();
let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap(); let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap();
let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap(); let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap();
let target_rotation = self.entities.get_component_mut(entity, self.target_rotation).unwrap(); let target_rotation = self.entities.get_component_mut(entity, self.target_rotation).unwrap();
position.position.x = spawn.x; position.position.x = x;
position.position.y = spawn.y; position.position.y = y;
position.position.z = spawn.z; position.position.z = z;
target_position.position.x = spawn.x; target_position.position.x = x;
target_position.position.y = spawn.y; target_position.position.y = y;
target_position.position.z = spawn.z; target_position.position.z = z;
rotation.yaw = -((spawn.yaw as f64) / 256.0) * PI * 2.0; rotation.yaw = -(yaw / 256.0) * PI * 2.0;
rotation.pitch = -((spawn.pitch as f64) / 256.0) * PI * 2.0; rotation.pitch = -(pitch / 256.0) * PI * 2.0;
target_rotation.yaw = rotation.yaw; target_rotation.yaw = rotation.yaw;
target_rotation.pitch = rotation.pitch; target_rotation.pitch = rotation.pitch;
if let Some(info) = self.players.get(&spawn.uuid) { if let Some(info) = self.players.get(&uuid) {
let model = self.entities.get_component_mut_direct::<entity::player::PlayerModel>(entity).unwrap(); let model = self.entities.get_component_mut_direct::<entity::player::PlayerModel>(entity).unwrap();
model.set_skin(info.skin_url.clone()); model.set_skin(info.skin_url.clone());
} }
self.entity_map.insert(spawn.entity_id.0, entity); self.entity_map.insert(entity_id, entity);
} }
fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) { fn on_teleport_player_withconfirm(&mut self, teleport: packet::play::clientbound::TeleportPlayer_WithConfirm) {
self.on_teleport_player(teleport.x, teleport.y, teleport.z, teleport.yaw as f64, teleport.pitch as f64, teleport.flags, Some(teleport.teleport_id))
}
fn on_teleport_player_noconfirm(&mut self, teleport: packet::play::clientbound::TeleportPlayer_NoConfirm) {
self.on_teleport_player(teleport.x, teleport.y, teleport.z, teleport.yaw as f64, teleport.pitch as f64, teleport.flags, None)
}
fn on_teleport_player(&mut self, x: f64, y: f64, z: f64, yaw: f64, pitch: f64, flags: u8, teleport_id: Option<protocol::VarInt>) {
use std::f64::consts::PI; use std::f64::consts::PI;
if let Some(player) = self.player { if let Some(player) = self.player {
let position = self.entities.get_component_mut(player, self.target_position).unwrap(); let position = self.entities.get_component_mut(player, self.target_position).unwrap();
let rotation = self.entities.get_component_mut(player, self.rotation).unwrap(); let rotation = self.entities.get_component_mut(player, self.rotation).unwrap();
let velocity = self.entities.get_component_mut(player, self.velocity).unwrap(); let velocity = self.entities.get_component_mut(player, self.velocity).unwrap();
position.position.x = calculate_relative_teleport(TeleportFlag::RelX, teleport.flags, position.position.x, teleport.x); position.position.x = calculate_relative_teleport(TeleportFlag::RelX, flags, position.position.x, x);
position.position.y = calculate_relative_teleport(TeleportFlag::RelY, teleport.flags, position.position.y, teleport.y); position.position.y = calculate_relative_teleport(TeleportFlag::RelY, flags, position.position.y, y);
position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, teleport.flags, position.position.z, teleport.z); position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, flags, position.position.z, z);
rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, teleport.flags, rotation.yaw, -teleport.yaw as f64 * (PI / 180.0)); rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, flags, rotation.yaw, -yaw as f64 * (PI / 180.0));
rotation.pitch = -((calculate_relative_teleport( rotation.pitch = -((calculate_relative_teleport(
TeleportFlag::RelPitch, TeleportFlag::RelPitch,
teleport.flags, flags,
(-rotation.pitch) * (180.0 / PI) + 180.0, (-rotation.pitch) * (180.0 / PI) + 180.0,
teleport.pitch as f64 pitch
) - 180.0) * (PI / 180.0)); ) - 180.0) * (PI / 180.0));
if (teleport.flags & (TeleportFlag::RelX as u8)) == 0 { if (flags & (TeleportFlag::RelX as u8)) == 0 {
velocity.velocity.x = 0.0; velocity.velocity.x = 0.0;
} }
if (teleport.flags & (TeleportFlag::RelY as u8)) == 0 { if (flags & (TeleportFlag::RelY as u8)) == 0 {
velocity.velocity.y = 0.0; velocity.velocity.y = 0.0;
} }
if (teleport.flags & (TeleportFlag::RelZ as u8)) == 0 { if (flags & (TeleportFlag::RelZ as u8)) == 0 {
velocity.velocity.z = 0.0; velocity.velocity.z = 0.0;
} }
self.write_packet(packet::play::serverbound::TeleportConfirm { if let Some(teleport_id) = teleport_id {
teleport_id: teleport.teleport_id, self.write_packet(packet::play::serverbound::TeleportConfirm {
}); teleport_id,
});
}
} }
} }