Adds 1.14 (477) protocol support, based on: https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14723 * New packets: SetDifficulty, LockDifficulty, UpdateJigsawBlock, UpdateViewPosition, UpdateViewDistance * New metadata: Optional VarInt (17) and Pose (18) * Add new join game variant with view distance, without difficulty * Add new server difficulty variant, with locked boolean * Implement recipe parsing changes, add stonecutting recipe type
This commit is contained in:
parent
65ddb3b898
commit
f935afdeac
|
@ -38,7 +38,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; 12] = [404, 451, 452, 340, 316, 315, 210, 109, 107, 74, 47, 5];
|
pub const SUPPORTED_PROTOCOLS: [i32; 13] = [477, 452, 451, 404, 340, 316, 315, 210, 109, 107, 74, 47, 5];
|
||||||
|
|
||||||
// TODO: switch to using thread_local storage?, see https://doc.rust-lang.org/std/macro.thread_local.html
|
// TODO: switch to using thread_local storage?, see https://doc.rust-lang.org/std/macro.thread_local.html
|
||||||
pub static mut CURRENT_PROTOCOL_VERSION: i32 = SUPPORTED_PROTOCOLS[0];
|
pub static mut CURRENT_PROTOCOL_VERSION: i32 = SUPPORTED_PROTOCOLS[0];
|
||||||
|
|
|
@ -57,6 +57,9 @@ state_packets!(
|
||||||
field transaction_id: VarInt =,
|
field transaction_id: VarInt =,
|
||||||
field location: Position =,
|
field location: Position =,
|
||||||
}
|
}
|
||||||
|
packet SetDifficulty {
|
||||||
|
field new_difficulty: u8 =,
|
||||||
|
}
|
||||||
/// TabComplete is sent by the client when the client presses tab in
|
/// TabComplete is sent by the client when the client presses tab in
|
||||||
/// the chat box.
|
/// the chat box.
|
||||||
packet TabComplete {
|
packet TabComplete {
|
||||||
|
@ -202,6 +205,9 @@ state_packets!(
|
||||||
packet KeepAliveServerbound_i32 {
|
packet KeepAliveServerbound_i32 {
|
||||||
field id: i32 =,
|
field id: i32 =,
|
||||||
}
|
}
|
||||||
|
packet LockDifficulty {
|
||||||
|
field locked: bool =,
|
||||||
|
}
|
||||||
/// PlayerPosition is used to update the player's position.
|
/// PlayerPosition is used to update the player's position.
|
||||||
packet PlayerPosition {
|
packet PlayerPosition {
|
||||||
field x: f64 =,
|
field x: f64 =,
|
||||||
|
@ -370,6 +376,12 @@ state_packets!(
|
||||||
field slot: i16 =,
|
field slot: i16 =,
|
||||||
field clicked_item: Option<item::Stack> =,
|
field clicked_item: Option<item::Stack> =,
|
||||||
}
|
}
|
||||||
|
packet UpdateJigsawBlock {
|
||||||
|
field location: Position =,
|
||||||
|
field attachment_type: String =,
|
||||||
|
field target_pool: String =,
|
||||||
|
field final_state: String =,
|
||||||
|
}
|
||||||
packet UpdateStructureBlock {
|
packet UpdateStructureBlock {
|
||||||
field location: Position =,
|
field location: Position =,
|
||||||
field action: VarInt =,
|
field action: VarInt =,
|
||||||
|
@ -753,6 +765,10 @@ state_packets!(
|
||||||
packet ServerDifficulty {
|
packet ServerDifficulty {
|
||||||
field difficulty: u8 =,
|
field difficulty: u8 =,
|
||||||
}
|
}
|
||||||
|
packet ServerDifficulty_Locked {
|
||||||
|
field difficulty: u8 =,
|
||||||
|
field locked: bool =,
|
||||||
|
}
|
||||||
/// TabCompleteReply is sent as a reply to a tab completion request.
|
/// TabCompleteReply is sent as a reply to a tab completion request.
|
||||||
/// The matches should be possible completions for the command/chat the
|
/// The matches should be possible completions for the command/chat the
|
||||||
/// player sent.
|
/// player sent.
|
||||||
|
@ -1055,6 +1071,23 @@ state_packets!(
|
||||||
}
|
}
|
||||||
/// JoinGame is sent after completing the login process. This
|
/// JoinGame is sent after completing the login process. This
|
||||||
/// sets the initial state for the client.
|
/// sets the initial state for the client.
|
||||||
|
packet JoinGame_i32_ViewDistance {
|
||||||
|
/// The entity id the client will be referenced by
|
||||||
|
field entity_id: i32 =,
|
||||||
|
/// The starting gamemode of the client
|
||||||
|
field gamemode: u8 =,
|
||||||
|
/// The dimension the client is starting in
|
||||||
|
field dimension: i32 =,
|
||||||
|
/// The max number of players on the server
|
||||||
|
field max_players: u8 =,
|
||||||
|
/// The level type of the server
|
||||||
|
field level_type: String =,
|
||||||
|
/// The render distance (2-32)
|
||||||
|
field view_distance: VarInt =,
|
||||||
|
/// Whether the client should reduce the amount of debug
|
||||||
|
/// information it displays in F3 mode
|
||||||
|
field reduced_debug_info: bool =,
|
||||||
|
}
|
||||||
packet JoinGame_i32 {
|
packet JoinGame_i32 {
|
||||||
/// The entity id the client will be referenced by
|
/// The entity id the client will be referenced by
|
||||||
field entity_id: i32 =,
|
field entity_id: i32 =,
|
||||||
|
@ -1377,6 +1410,15 @@ state_packets!(
|
||||||
packet SetCurrentHotbarSlot {
|
packet SetCurrentHotbarSlot {
|
||||||
field slot: u8 =,
|
field slot: u8 =,
|
||||||
}
|
}
|
||||||
|
/// UpdateViewPosition is used to determine what chunks should be remain loaded.
|
||||||
|
packet UpdateViewPosition {
|
||||||
|
field chunk_x: VarInt =,
|
||||||
|
field chunk_z: VarInt =,
|
||||||
|
}
|
||||||
|
/// UpdateViewDistance is sent by the integrated server when changing render distance.
|
||||||
|
packet UpdateViewDistance {
|
||||||
|
field view_distance: VarInt =,
|
||||||
|
}
|
||||||
/// ScoreboardDisplay is used to set the display position of a scoreboard.
|
/// ScoreboardDisplay is used to set the display position of a scoreboard.
|
||||||
packet ScoreboardDisplay {
|
packet ScoreboardDisplay {
|
||||||
field position: u8 =,
|
field position: u8 =,
|
||||||
|
@ -2396,6 +2438,11 @@ pub enum RecipeData {
|
||||||
experience: f32,
|
experience: f32,
|
||||||
cooking_time: VarInt,
|
cooking_time: VarInt,
|
||||||
},
|
},
|
||||||
|
Stonecutting {
|
||||||
|
group: String,
|
||||||
|
ingredient: RecipeIngredient,
|
||||||
|
result: Option<item::Stack>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RecipeData {
|
impl Default for RecipeData {
|
||||||
|
@ -2413,8 +2460,35 @@ pub struct Recipe {
|
||||||
|
|
||||||
impl Serializable for Recipe {
|
impl Serializable for Recipe {
|
||||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error> {
|
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error> {
|
||||||
let id = String::read_from(buf)?;
|
let (id, ty, namespace) = {
|
||||||
let ty = String::read_from(buf)?;
|
let a = String::read_from(buf)?;
|
||||||
|
let b = String::read_from(buf)?;
|
||||||
|
|
||||||
|
let protocol_version = unsafe { crate::protocol::CURRENT_PROTOCOL_VERSION };
|
||||||
|
|
||||||
|
// 1.14+ swaps recipe identifier and type, and adds namespace to type
|
||||||
|
if protocol_version >= 477 {
|
||||||
|
let ty = a;
|
||||||
|
let id = b;
|
||||||
|
|
||||||
|
if let Some(at) = ty.find(':') {
|
||||||
|
let (namespace, ty) = ty.split_at(at + 1);
|
||||||
|
let ty: String = ty.into();
|
||||||
|
let namespace: String = namespace.into();
|
||||||
|
(id, ty, namespace)
|
||||||
|
} else {
|
||||||
|
(id, ty, "minecraft:".to_string())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let ty = b;
|
||||||
|
let id = a;
|
||||||
|
(id, ty, "minecraft:".to_string())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if namespace != "minecraft:" {
|
||||||
|
panic!("unrecognized recipe type namespace: {}", namespace);
|
||||||
|
}
|
||||||
|
|
||||||
let data =
|
let data =
|
||||||
match ty.as_ref() {
|
match ty.as_ref() {
|
||||||
|
@ -2473,13 +2547,18 @@ impl Serializable for Recipe {
|
||||||
experience: Serializable::read_from(buf)?,
|
experience: Serializable::read_from(buf)?,
|
||||||
cooking_time: Serializable::read_from(buf)?,
|
cooking_time: Serializable::read_from(buf)?,
|
||||||
},
|
},
|
||||||
"campfire" => RecipeData::Campfire {
|
"campfire" | "campfire_cooking" => RecipeData::Campfire {
|
||||||
group: Serializable::read_from(buf)?,
|
group: Serializable::read_from(buf)?,
|
||||||
ingredient: Serializable::read_from(buf)?,
|
ingredient: Serializable::read_from(buf)?,
|
||||||
result: Serializable::read_from(buf)?,
|
result: Serializable::read_from(buf)?,
|
||||||
experience: Serializable::read_from(buf)?,
|
experience: Serializable::read_from(buf)?,
|
||||||
cooking_time: Serializable::read_from(buf)?,
|
cooking_time: Serializable::read_from(buf)?,
|
||||||
},
|
},
|
||||||
|
"stonecutting" => RecipeData::Stonecutting {
|
||||||
|
group: Serializable::read_from(buf)?,
|
||||||
|
ingredient: Serializable::read_from(buf)?,
|
||||||
|
result: Serializable::read_from(buf)?,
|
||||||
|
},
|
||||||
_ => panic!("unrecognized recipe type: {}", ty)
|
_ => panic!("unrecognized recipe type: {}", ty)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::protocol::*;
|
use crate::protocol::*;
|
||||||
|
|
||||||
|
mod v1_14;
|
||||||
mod v19w02a;
|
mod v19w02a;
|
||||||
mod v18w50a;
|
mod v18w50a;
|
||||||
mod v1_13_2;
|
mod v1_13_2;
|
||||||
|
@ -16,6 +17,8 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir:
|
||||||
match version {
|
match version {
|
||||||
// https://wiki.vg/Protocol_History
|
// https://wiki.vg/Protocol_History
|
||||||
// https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite
|
// https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite
|
||||||
|
|
||||||
|
477 => v1_14::translate_internal_packet_id(state, dir, id, to_internal),
|
||||||
|
|
||||||
// 19w02a
|
// 19w02a
|
||||||
452 => v19w02a::translate_internal_packet_id(state, dir, id, to_internal),
|
452 => v19w02a::translate_internal_packet_id(state, dir, id, to_internal),
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
protocol_packet_ids!(
|
||||||
|
handshake Handshaking {
|
||||||
|
serverbound Serverbound {
|
||||||
|
0x00 => Handshake
|
||||||
|
}
|
||||||
|
clientbound Clientbound {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
play Play {
|
||||||
|
serverbound Serverbound {
|
||||||
|
0x00 => TeleportConfirm
|
||||||
|
0x01 => QueryBlockNBT
|
||||||
|
0x02 => SetDifficulty
|
||||||
|
0x03 => ChatMessage
|
||||||
|
0x04 => ClientStatus
|
||||||
|
0x05 => ClientSettings
|
||||||
|
0x06 => TabComplete
|
||||||
|
0x07 => ConfirmTransactionServerbound
|
||||||
|
//0x08 => EnchantItem
|
||||||
|
//0x08 => ClickWindowButton
|
||||||
|
0x09 => ClickWindow
|
||||||
|
0x0a => CloseWindow
|
||||||
|
0x0b => PluginMessageServerbound
|
||||||
|
0x0c => EditBook
|
||||||
|
0x0d => QueryEntityNBT
|
||||||
|
0x0e => UseEntity
|
||||||
|
0x0f => KeepAliveServerbound_i64
|
||||||
|
0x10 => LockDifficulty
|
||||||
|
0x11 => PlayerPosition
|
||||||
|
0x12 => PlayerPositionLook
|
||||||
|
0x13 => PlayerLook
|
||||||
|
0x14 => Player
|
||||||
|
0x15 => VehicleMove
|
||||||
|
0x16 => SteerBoat
|
||||||
|
0x17 => PickItem
|
||||||
|
0x18 => CraftRecipeRequest
|
||||||
|
0x19 => ClientAbilities
|
||||||
|
0x1a => PlayerDigging
|
||||||
|
0x1b => PlayerAction
|
||||||
|
0x1c => SteerVehicle
|
||||||
|
0x1d => CraftingBookData
|
||||||
|
0x1e => NameItem
|
||||||
|
0x1f => ResourcePackStatus
|
||||||
|
0x20 => AdvancementTab
|
||||||
|
0x21 => SelectTrade
|
||||||
|
0x22 => SetBeaconEffect
|
||||||
|
0x23 => HeldItemChange
|
||||||
|
0x24 => UpdateCommandBlock
|
||||||
|
0x25 => UpdateCommandBlockMinecart
|
||||||
|
0x26 => CreativeInventoryAction
|
||||||
|
0x27 => UpdateJigsawBlock
|
||||||
|
0x28 => UpdateStructureBlock
|
||||||
|
0x29 => SetSign
|
||||||
|
0x2a => ArmSwing
|
||||||
|
0x2b => SpectateTeleport
|
||||||
|
0x2c => PlayerBlockPlacement_f32
|
||||||
|
0x2d => UseItem
|
||||||
|
}
|
||||||
|
clientbound Clientbound {
|
||||||
|
0x00 => SpawnObject
|
||||||
|
0x01 => SpawnExperienceOrb
|
||||||
|
0x02 => SpawnGlobalEntity
|
||||||
|
0x03 => SpawnMob
|
||||||
|
0x04 => SpawnPainting
|
||||||
|
0x05 => SpawnPlayer_f64
|
||||||
|
0x06 => Animation
|
||||||
|
0x07 => Statistics
|
||||||
|
0x08 => BlockBreakAnimation
|
||||||
|
0x09 => UpdateBlockEntity
|
||||||
|
0x0a => BlockAction
|
||||||
|
0x0b => BlockChange_VarInt
|
||||||
|
0x0c => BossBar
|
||||||
|
0x0d => ServerDifficulty_Locked
|
||||||
|
0x0e => ServerMessage
|
||||||
|
0x0f => MultiBlockChange_VarInt
|
||||||
|
0x10 => TabCompleteReply
|
||||||
|
0x11 => DeclareCommands
|
||||||
|
0x12 => ConfirmTransaction
|
||||||
|
0x13 => WindowClose
|
||||||
|
0x14 => WindowItems
|
||||||
|
0x15 => WindowProperty
|
||||||
|
0x16 => WindowSetSlot
|
||||||
|
0x17 => SetCooldown
|
||||||
|
0x18 => PluginMessageClientbound
|
||||||
|
0x19 => NamedSoundEffect
|
||||||
|
0x1a => Disconnect
|
||||||
|
0x1b => EntityAction
|
||||||
|
0x1c => Explosion
|
||||||
|
0x1d => ChunkUnload
|
||||||
|
0x1e => ChangeGameState
|
||||||
|
0x1f => WindowOpenHorse
|
||||||
|
0x20 => KeepAliveClientbound_i64
|
||||||
|
0x21 => ChunkData_HeightMap
|
||||||
|
0x22 => Effect
|
||||||
|
0x23 => Particle_Data
|
||||||
|
0x24 => UpdateLight
|
||||||
|
0x25 => JoinGame_i32_ViewDistance
|
||||||
|
0x26 => Maps
|
||||||
|
0x27 => TradeList
|
||||||
|
0x28 => EntityMove_i16
|
||||||
|
0x29 => EntityLookAndMove_i16
|
||||||
|
0x2a => EntityLook_VarInt
|
||||||
|
0x2b => Entity
|
||||||
|
0x2c => VehicleTeleport
|
||||||
|
0x2d => OpenBook
|
||||||
|
0x2e => WindowOpen_VarInt
|
||||||
|
0x2f => SignEditorOpen
|
||||||
|
0x30 => CraftRecipeResponse
|
||||||
|
0x31 => PlayerAbilities
|
||||||
|
0x32 => CombatEvent
|
||||||
|
0x33 => PlayerInfo
|
||||||
|
0x34 => FacePlayer
|
||||||
|
0x35 => TeleportPlayer_WithConfirm
|
||||||
|
0x36 => UnlockRecipes_WithSmelting
|
||||||
|
0x37 => EntityDestroy
|
||||||
|
0x38 => EntityRemoveEffect
|
||||||
|
0x39 => ResourcePackSend
|
||||||
|
0x3a => Respawn
|
||||||
|
0x3b => EntityHeadLook
|
||||||
|
0x3c => SelectAdvancementTab
|
||||||
|
0x3d => WorldBorder
|
||||||
|
0x3e => Camera
|
||||||
|
0x3f => SetCurrentHotbarSlot
|
||||||
|
0x40 => UpdateViewPosition
|
||||||
|
0x41 => UpdateViewDistance
|
||||||
|
0x42 => ScoreboardDisplay
|
||||||
|
0x43 => EntityMetadata
|
||||||
|
0x44 => EntityAttach
|
||||||
|
0x45 => EntityVelocity
|
||||||
|
0x46 => EntityEquipment
|
||||||
|
0x47 => SetExperience
|
||||||
|
0x48 => UpdateHealth
|
||||||
|
0x49 => ScoreboardObjective
|
||||||
|
0x4a => SetPassengers
|
||||||
|
0x4b => Teams
|
||||||
|
0x4c => UpdateScore
|
||||||
|
0x4d => SpawnPosition
|
||||||
|
0x4e => TimeUpdate
|
||||||
|
0x4f => Title
|
||||||
|
0x50 => EntitySoundEffect
|
||||||
|
0x51 => SoundEffect
|
||||||
|
0x52 => StopSound
|
||||||
|
0x53 => PlayerListHeaderFooter
|
||||||
|
0x54 => NBTQueryResponse
|
||||||
|
0x55 => CollectItem
|
||||||
|
0x56 => EntityTeleport_f64
|
||||||
|
0x57 => Advancements
|
||||||
|
0x58 => EntityProperties
|
||||||
|
0x59 => EntityEffect
|
||||||
|
0x5a => DeclareRecipes
|
||||||
|
0x5b => TagsWithEntities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
login Login {
|
||||||
|
serverbound Serverbound {
|
||||||
|
0x00 => LoginStart
|
||||||
|
0x01 => EncryptionResponse
|
||||||
|
0x02 => LoginPluginResponse
|
||||||
|
}
|
||||||
|
clientbound Clientbound {
|
||||||
|
0x00 => LoginDisconnect
|
||||||
|
0x01 => EncryptionRequest
|
||||||
|
0x02 => LoginSuccess
|
||||||
|
0x03 => SetInitialCompression
|
||||||
|
0x04 => LoginPluginRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status Status {
|
||||||
|
serverbound Serverbound {
|
||||||
|
0x00 => StatusRequest
|
||||||
|
0x01 => StatusPing
|
||||||
|
}
|
||||||
|
clientbound Clientbound {
|
||||||
|
0x00 => StatusResponse
|
||||||
|
0x01 => StatusPong
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue