1.8.9 (47) multiprotocol support (#57)
Protocol 47 (1.8.9-1.8) is the biggest multiprotocol (https://github.com/iceiix/steven/issues/18) change yet: * New chunk format (load_chunk18) * New metadata format (Metadata18) * New packets and changes to 13 packets References: http://wiki.vg/index.php?title=Protocol&oldid=7368 https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite https://wiki.vg/Protocol_History#1.8 https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/protocol.json 1.8 chunk format: https://wiki.vg/index.php?title=Chunk_Format&oldid=6124 1.9 chunk format: https://wiki.vg/index.php?title=Chunk_Format&oldid=7411 1.8 vs 1.9: https://wiki.vg/index.php?title=Chunk_Format&diff=7411&oldid=6124 https://github.com/PrismarineJS/prismarine-chunk/blob/master/src/pc/1.8/section.js https://github.com/PrismarineJS/prismarine-chunk/blob/master/src/pc/1.8/chunk.js Details: * Add 1.8.9 packet IDs from https://github.com/iceiix/steven/pull/37 * Add ChunkDataBulk, parse the ChunkMeta and save data in Vec<u8> * Add EntityEquipment u16 variant, EntityStatus, ChunkData u16 variants * SpawnPlayer with added held item https://wiki.vg/Protocol_History#15w31a Removed Current Item short from Spawn Player (0x0C) * SpawnObject no UUID and optional velocity https://wiki.vg/index.php?title=Protocol&oldid=7368#Spawn_Object https://wiki.vg/Protocol_History#15w31a Added Entity UUID after entity ID to Spawn Object (0x0E) Spawn Object always sends velocity, even if data is 0 * SpawnMob no UUID variant https://wiki.vg/Protocol_History#15w31a Added Entity UUID after entity ID to Spawn Mob (0x0F) * Maps packet without tracking position boolean https://wiki.vg/index.php?title=Protocol&oldid=7368#Map https://wiki.vg/Protocol_History#15w34a Added tracking position boolean to Map (0x34) * Update Entity NBT was removed and Bossbar added (both 0x49) >1.8 https://wiki.vg/index.php?title=Protocol&oldid=7368#Update_Entity_NBT https://wiki.vg/Protocol_History#15w31a Removed Update Entity NBT Packet (0x49) Added Boss Bar packet (0x4 * Use entity without hands https://wiki.vg/index.php?title=Protocol&oldid=7368#Use_Entity https://wiki.vg/Protocol_History#15w31a Added VarInt enum for selected hand in Use Entity (0x02); only sent if type is interact or interact at * Player block placement, held item stack and face byte variant https://wiki.vg/index.php?title=Protocol&oldid=7368#Player_Block_Placement https://wiki.vg/Protocol_History#15w31a Face for Player Block Placement is now a VarInt enum instead of a byte Replaced held item (slot) with VarInt enum selected hand in Player Block Placement * Arm swing without hands, a packet with no fields, uses a ZST https://wiki.vg/index.php?title=Protocol&oldid=7368#Animation_2 https://github.com/iceiix/steven/pull/57#issuecomment-444289008 https://doc.rust-lang.org/nomicon/exotic-sizes.html * ClickWindow uses u8 mode, same as in 15w39c * ClientSettings without hands * SpectateTeleport is added before ResourcePackStatus * Copy load_chunk to load_chunk19 and load_chunk18 * 1.8 chunk reading implementation, load_chunk18 * Support both metadata formats, Metadata18/Metadata19 * Remove fmt::Debug * Implement formatting in MetadataBase and bounce through fmt::Debug
This commit is contained in:
parent
0c41b385f9
commit
afac493896
|
@ -37,7 +37,7 @@ use flate2::Compression;
|
|||
use std::time::{Instant, Duration};
|
||||
use crate::shared::Position;
|
||||
|
||||
pub const SUPPORTED_PROTOCOLS: [i32; 7] = [340, 316, 315, 210, 109, 107, 74];
|
||||
pub const SUPPORTED_PROTOCOLS: [i32; 8] = [340, 316, 315, 210, 109, 107, 74, 47];
|
||||
|
||||
|
||||
/// Helper macro for defining packets
|
||||
|
|
|
@ -92,6 +92,13 @@ state_packets!(
|
|||
field displayed_skin_parts: u8 =,
|
||||
field main_hand: VarInt =,
|
||||
}
|
||||
packet ClientSettings_u8_Handsfree {
|
||||
field locale: String =,
|
||||
field view_distance: u8 =,
|
||||
field chat_mode: u8 =,
|
||||
field chat_colors: bool =,
|
||||
field displayed_skin_parts: u8 =,
|
||||
}
|
||||
/// ConfirmTransactionServerbound is a reply to ConfirmTransaction.
|
||||
packet ConfirmTransactionServerbound {
|
||||
field id: u8 =,
|
||||
|
@ -141,6 +148,13 @@ state_packets!(
|
|||
field target_z: f32 = when(|p: &UseEntity| p.ty.0 == 2),
|
||||
field hand: VarInt = when(|p: &UseEntity| p.ty.0 == 0 || p.ty.0 == 2),
|
||||
}
|
||||
packet UseEntity_Handsfree {
|
||||
field target_id: VarInt =,
|
||||
field ty: VarInt =,
|
||||
field target_x: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2),
|
||||
field target_y: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2),
|
||||
field target_z: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2),
|
||||
}
|
||||
/// KeepAliveServerbound is sent by a client as a response to a
|
||||
/// KeepAliveClientbound. If the client doesn't reply the server
|
||||
/// may disconnect the client.
|
||||
|
@ -273,6 +287,9 @@ state_packets!(
|
|||
packet ArmSwing {
|
||||
field hand: VarInt =,
|
||||
}
|
||||
packet ArmSwing_Handsfree {
|
||||
field empty: () =,
|
||||
}
|
||||
/// SpectateTeleport is sent by clients in spectator mode to teleport to a player.
|
||||
packet SpectateTeleport {
|
||||
field target: UUID =,
|
||||
|
@ -294,6 +311,15 @@ state_packets!(
|
|||
field cursor_y: u8 =,
|
||||
field cursor_z: u8 =,
|
||||
}
|
||||
packet PlayerBlockPlacement_u8_Item {
|
||||
field location: Position =,
|
||||
field face: u8 =,
|
||||
field hand: Option<item::Stack> =,
|
||||
field cursor_x: u8 =,
|
||||
field cursor_y: u8 =,
|
||||
field cursor_z: u8 =,
|
||||
}
|
||||
|
||||
/// UseItem is sent when the client tries to use an item.
|
||||
packet UseItem {
|
||||
field hand: VarInt =,
|
||||
|
@ -330,6 +356,19 @@ state_packets!(
|
|||
field velocity_y: i16 =,
|
||||
field velocity_z: i16 =,
|
||||
}
|
||||
packet SpawnObject_i32_NoUUID {
|
||||
field entity_id: VarInt =,
|
||||
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 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0),
|
||||
field velocity_y: i16 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0),
|
||||
field velocity_z: i16 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0),
|
||||
}
|
||||
/// SpawnExperienceOrb spawns a single experience orb into the world when
|
||||
/// it is in range of the client. The count controls the amount of experience
|
||||
/// gained when collected.
|
||||
|
@ -378,7 +417,7 @@ state_packets!(
|
|||
field velocity_x: i16 =,
|
||||
field velocity_y: i16 =,
|
||||
field velocity_z: i16 =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet SpawnMob_u8 {
|
||||
field entity_id: VarInt =,
|
||||
|
@ -393,7 +432,7 @@ state_packets!(
|
|||
field velocity_x: i16 =,
|
||||
field velocity_y: i16 =,
|
||||
field velocity_z: i16 =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet SpawnMob_u8_i32 {
|
||||
field entity_id: VarInt =,
|
||||
|
@ -408,7 +447,21 @@ state_packets!(
|
|||
field velocity_x: i16 =,
|
||||
field velocity_y: i16 =,
|
||||
field velocity_z: i16 =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet SpawnMob_u8_i32_NoUUID_18 {
|
||||
field entity_id: VarInt =,
|
||||
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::Metadata18 =,
|
||||
}
|
||||
/// 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.
|
||||
|
@ -436,7 +489,7 @@ state_packets!(
|
|||
field z: f64 =,
|
||||
field yaw: i8 =,
|
||||
field pitch: i8 =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet SpawnPlayer_i32 {
|
||||
field entity_id: VarInt =,
|
||||
|
@ -446,7 +499,18 @@ state_packets!(
|
|||
field z: i32 =,
|
||||
field yaw: i8 =,
|
||||
field pitch: i8 =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet SpawnPlayer_i32_HeldItem_18 {
|
||||
field entity_id: VarInt =,
|
||||
field uuid: UUID =,
|
||||
field x: i32 =,
|
||||
field y: i32 =,
|
||||
field z: i32 =,
|
||||
field yaw: i8 =,
|
||||
field pitch: i8 =,
|
||||
field current_item: u16 =,
|
||||
field metadata: types::Metadata18 =,
|
||||
}
|
||||
/// Animation is sent by the server to play an animation on a specific entity.
|
||||
packet Animation {
|
||||
|
@ -664,6 +728,18 @@ state_packets!(
|
|||
field bitmask: VarInt =,
|
||||
field data: LenPrefixedBytes<VarInt> =,
|
||||
}
|
||||
packet ChunkData_NoEntities_u16 {
|
||||
field chunk_x: i32 =,
|
||||
field chunk_z: i32 =,
|
||||
field new: bool =,
|
||||
field bitmask: u16 =,
|
||||
field data: LenPrefixedBytes<VarInt> =,
|
||||
}
|
||||
packet ChunkDataBulk {
|
||||
field skylight: bool =,
|
||||
field chunk_meta: LenPrefixed<VarInt, packet::ChunkMeta> =,
|
||||
field chunk_data: Vec<u8> =,
|
||||
}
|
||||
/// Effect plays a sound effect or particle at the target location with the
|
||||
/// volume (of sounds) being relative to the player's position unless
|
||||
/// DisableRelative is set to true.
|
||||
|
@ -737,6 +813,16 @@ state_packets!(
|
|||
field z: Option<u8> = when(|p: &Maps| p.columns > 0),
|
||||
field data: Option<LenPrefixedBytes<VarInt>> = when(|p: &Maps| p.columns > 0),
|
||||
}
|
||||
packet Maps_NoTracking {
|
||||
field item_damage: VarInt =,
|
||||
field scale: i8 =,
|
||||
field icons: LenPrefixed<VarInt, packet::MapIcon> =,
|
||||
field columns: u8 =,
|
||||
field rows: Option<u8> = when(|p: &Maps_NoTracking| p.columns > 0),
|
||||
field x: Option<u8> = when(|p: &Maps_NoTracking| p.columns > 0),
|
||||
field z: Option<u8> = when(|p: &Maps_NoTracking| p.columns > 0),
|
||||
field data: Option<LenPrefixedBytes<VarInt>> = when(|p: &Maps_NoTracking| p.columns > 0),
|
||||
}
|
||||
/// EntityMove moves the entity with the id by the offsets provided.
|
||||
packet EntityMove_i16 {
|
||||
field entity_id: VarInt =,
|
||||
|
@ -782,6 +868,11 @@ state_packets!(
|
|||
packet Entity {
|
||||
field entity_id: VarInt =,
|
||||
}
|
||||
/// EntityUpdateNBT updates the entity named binary tag.
|
||||
packet EntityUpdateNBT {
|
||||
field entity_id: VarInt =,
|
||||
field nbt: Option<nbt::NamedTag> =,
|
||||
}
|
||||
/// Teleports the player's vehicle
|
||||
packet VehicleTeleport {
|
||||
field x: f64 =,
|
||||
|
@ -881,6 +972,10 @@ state_packets!(
|
|||
field entity_id: VarInt =,
|
||||
field head_yaw: i8 =,
|
||||
}
|
||||
packet EntityStatus {
|
||||
field entity_id: i32 =,
|
||||
field entity_status: i8 =,
|
||||
}
|
||||
/// SelectAdvancementTab indicates the client should switch the advancement tab.
|
||||
packet SelectAdvancementTab {
|
||||
field has_id: bool =,
|
||||
|
@ -915,7 +1010,11 @@ state_packets!(
|
|||
/// EntityMetadata updates the metadata for an entity.
|
||||
packet EntityMetadata {
|
||||
field entity_id: VarInt =,
|
||||
field metadata: types::Metadata =,
|
||||
field metadata: types::Metadata19 =,
|
||||
}
|
||||
packet EntityMetadata_18 {
|
||||
field entity_id: VarInt =,
|
||||
field metadata: types::Metadata18 =,
|
||||
}
|
||||
/// EntityAttach attaches to entities together, either by mounting or leashing.
|
||||
/// -1 can be used at the EntityID to deattach.
|
||||
|
@ -944,6 +1043,11 @@ state_packets!(
|
|||
field slot: VarInt =,
|
||||
field item: Option<item::Stack> =,
|
||||
}
|
||||
packet EntityEquipment_u16 {
|
||||
field entity_id: VarInt =,
|
||||
field slot: u16 =,
|
||||
field item: Option<item::Stack> =,
|
||||
}
|
||||
/// SetExperience updates the experience bar on the client.
|
||||
packet SetExperience {
|
||||
field experience_bar: f32 =,
|
||||
|
@ -1266,6 +1370,29 @@ impl Serializable for BlockChangeRecord {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ChunkMeta {
|
||||
pub x: i32,
|
||||
pub z: i32,
|
||||
pub bitmask: u16,
|
||||
}
|
||||
|
||||
impl Serializable for ChunkMeta {
|
||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error> {
|
||||
Ok(ChunkMeta {
|
||||
x: Serializable::read_from(buf)?,
|
||||
z: Serializable::read_from(buf)?,
|
||||
bitmask: Serializable::read_from(buf)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), Error> {
|
||||
self.x.write_to(buf)?;
|
||||
self.z.write_to(buf)?;
|
||||
self.bitmask.write_to(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ExplosionRecord {
|
||||
pub x: i8,
|
||||
|
|
|
@ -6,6 +6,7 @@ mod v1_10_2;
|
|||
mod v1_9_2;
|
||||
mod v1_9;
|
||||
mod v15w39c;
|
||||
mod v1_8_9;
|
||||
|
||||
pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 {
|
||||
match version {
|
||||
|
@ -32,6 +33,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir:
|
|||
// 15w39a/b/c
|
||||
74 => v15w39c::translate_internal_packet_id(state, dir, id, to_internal),
|
||||
|
||||
// 1.8.9 - 1.8
|
||||
47 => v1_8_9::translate_internal_packet_id(state, dir, id, to_internal),
|
||||
|
||||
_ => panic!("unsupported protocol version"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
protocol_packet_ids!(
|
||||
handshake Handshaking {
|
||||
serverbound Serverbound {
|
||||
0x00 => Handshake
|
||||
}
|
||||
clientbound Clientbound {
|
||||
}
|
||||
}
|
||||
play Play {
|
||||
serverbound Serverbound {
|
||||
0x00 => KeepAliveServerbound_VarInt
|
||||
0x01 => ChatMessage
|
||||
0x02 => UseEntity_Handsfree
|
||||
0x03 => Player
|
||||
0x04 => PlayerPosition
|
||||
0x05 => PlayerLook
|
||||
0x06 => PlayerPositionLook
|
||||
0x07 => PlayerDigging_u8
|
||||
0x08 => PlayerBlockPlacement_u8_Item
|
||||
0x09 => HeldItemChange
|
||||
0x0a => ArmSwing_Handsfree
|
||||
0x0b => PlayerAction
|
||||
0x0c => SteerVehicle
|
||||
0x0d => CloseWindow
|
||||
0x0e => ClickWindow_u8
|
||||
0x0f => ConfirmTransactionServerbound
|
||||
0x10 => CreativeInventoryAction
|
||||
0x11 => EnchantItem
|
||||
0x12 => SetSign
|
||||
0x13 => ClientAbilities
|
||||
0x14 => TabComplete_NoAssume
|
||||
0x15 => ClientSettings_u8_Handsfree
|
||||
0x16 => ClientStatus
|
||||
0x17 => PluginMessageServerbound
|
||||
0x18 => SpectateTeleport
|
||||
0x19 => ResourcePackStatus
|
||||
}
|
||||
clientbound Clientbound {
|
||||
0x00 => KeepAliveClientbound_VarInt
|
||||
0x01 => JoinGame_i8
|
||||
0x02 => ServerMessage
|
||||
0x03 => TimeUpdate
|
||||
0x04 => EntityEquipment_u16
|
||||
0x05 => SpawnPosition
|
||||
0x06 => UpdateHealth
|
||||
0x07 => Respawn
|
||||
0x08 => TeleportPlayer_NoConfirm
|
||||
0x09 => SetCurrentHotbarSlot
|
||||
0x0a => EntityUsedBed
|
||||
0x0b => Animation
|
||||
0x0c => SpawnPlayer_i32_HeldItem_18
|
||||
0x0d => CollectItem_nocount
|
||||
0x0e => SpawnObject_i32_NoUUID
|
||||
0x0f => SpawnMob_u8_i32_NoUUID_18
|
||||
0x10 => SpawnPainting_NoUUID
|
||||
0x11 => SpawnExperienceOrb_i32
|
||||
0x12 => EntityVelocity
|
||||
0x13 => EntityDestroy
|
||||
0x14 => Entity
|
||||
0x15 => EntityMove_i8
|
||||
0x16 => EntityLook
|
||||
0x17 => EntityLookAndMove_i8
|
||||
0x18 => EntityTeleport_i32
|
||||
0x19 => EntityHeadLook
|
||||
0x1a => EntityStatus
|
||||
0x1b => EntityAttach_leashed
|
||||
0x1c => EntityMetadata_18
|
||||
0x1d => EntityEffect
|
||||
0x1e => EntityRemoveEffect
|
||||
0x1f => SetExperience
|
||||
0x20 => EntityProperties
|
||||
0x21 => ChunkData_NoEntities_u16
|
||||
0x22 => MultiBlockChange
|
||||
0x23 => BlockChange
|
||||
0x24 => BlockAction
|
||||
0x25 => BlockBreakAnimation
|
||||
0x26 => ChunkDataBulk
|
||||
0x27 => Explosion
|
||||
0x28 => Effect
|
||||
0x29 => NamedSoundEffect_u8_NoCategory
|
||||
0x2a => Particle
|
||||
0x2b => ChangeGameState
|
||||
0x2c => SpawnGlobalEntity_i32
|
||||
0x2d => WindowOpen
|
||||
0x2e => WindowClose
|
||||
0x2f => WindowSetSlot
|
||||
0x30 => WindowItems
|
||||
0x31 => WindowProperty
|
||||
0x32 => ConfirmTransaction
|
||||
0x33 => UpdateSign
|
||||
0x34 => Maps_NoTracking
|
||||
0x35 => UpdateBlockEntity
|
||||
0x36 => SignEditorOpen
|
||||
0x37 => Statistics
|
||||
0x38 => PlayerInfo
|
||||
0x39 => PlayerAbilities
|
||||
0x3a => TabCompleteReply
|
||||
0x3b => ScoreboardObjective
|
||||
0x3c => UpdateScore
|
||||
0x3d => ScoreboardDisplay
|
||||
0x3e => Teams
|
||||
0x3f => PluginMessageClientbound
|
||||
0x40 => Disconnect
|
||||
0x41 => ServerDifficulty
|
||||
0x42 => CombatEvent
|
||||
0x43 => Camera
|
||||
0x44 => WorldBorder
|
||||
0x45 => Title_notext_component
|
||||
0x46 => SetCompression
|
||||
0x47 => PlayerListHeaderFooter
|
||||
0x48 => ResourcePackSend
|
||||
0x49 => EntityUpdateNBT
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue