Skip to content

Commit 4608d94

Browse files
committed
1.14 protocol support (477) (#132). Closes #72
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
1 parent 523a5e4 commit 4608d94

File tree

4 files changed

+266
-4
lines changed

4 files changed

+266
-4
lines changed

protocol/src/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use flate2::Compression;
3838
use std::time::{Instant, Duration};
3939
use crate::shared::Position;
4040

41-
pub const SUPPORTED_PROTOCOLS: [i32; 12] = [404, 451, 452, 340, 316, 315, 210, 109, 107, 74, 47, 5];
41+
pub const SUPPORTED_PROTOCOLS: [i32; 13] = [477, 452, 451, 404, 340, 316, 315, 210, 109, 107, 74, 47, 5];
4242

4343
// TODO: switch to using thread_local storage?, see https://doc.rust-lang.org/std/macro.thread_local.html
4444
pub static mut CURRENT_PROTOCOL_VERSION: i32 = SUPPORTED_PROTOCOLS[0];

protocol/src/packet.rs

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ state_packets!(
5757
field transaction_id: VarInt =,
5858
field location: Position =,
5959
}
60+
packet SetDifficulty {
61+
field new_difficulty: u8 =,
62+
}
6063
/// TabComplete is sent by the client when the client presses tab in
6164
/// the chat box.
6265
packet TabComplete {
@@ -202,6 +205,9 @@ state_packets!(
202205
packet KeepAliveServerbound_i32 {
203206
field id: i32 =,
204207
}
208+
packet LockDifficulty {
209+
field locked: bool =,
210+
}
205211
/// PlayerPosition is used to update the player's position.
206212
packet PlayerPosition {
207213
field x: f64 =,
@@ -370,6 +376,12 @@ state_packets!(
370376
field slot: i16 =,
371377
field clicked_item: Option<item::Stack> =,
372378
}
379+
packet UpdateJigsawBlock {
380+
field location: Position =,
381+
field attachment_type: String =,
382+
field target_pool: String =,
383+
field final_state: String =,
384+
}
373385
packet UpdateStructureBlock {
374386
field location: Position =,
375387
field action: VarInt =,
@@ -753,6 +765,10 @@ state_packets!(
753765
packet ServerDifficulty {
754766
field difficulty: u8 =,
755767
}
768+
packet ServerDifficulty_Locked {
769+
field difficulty: u8 =,
770+
field locked: bool =,
771+
}
756772
/// TabCompleteReply is sent as a reply to a tab completion request.
757773
/// The matches should be possible completions for the command/chat the
758774
/// player sent.
@@ -1055,6 +1071,23 @@ state_packets!(
10551071
}
10561072
/// JoinGame is sent after completing the login process. This
10571073
/// sets the initial state for the client.
1074+
packet JoinGame_i32_ViewDistance {
1075+
/// The entity id the client will be referenced by
1076+
field entity_id: i32 =,
1077+
/// The starting gamemode of the client
1078+
field gamemode: u8 =,
1079+
/// The dimension the client is starting in
1080+
field dimension: i32 =,
1081+
/// The max number of players on the server
1082+
field max_players: u8 =,
1083+
/// The level type of the server
1084+
field level_type: String =,
1085+
/// The render distance (2-32)
1086+
field view_distance: VarInt =,
1087+
/// Whether the client should reduce the amount of debug
1088+
/// information it displays in F3 mode
1089+
field reduced_debug_info: bool =,
1090+
}
10581091
packet JoinGame_i32 {
10591092
/// The entity id the client will be referenced by
10601093
field entity_id: i32 =,
@@ -1377,6 +1410,15 @@ state_packets!(
13771410
packet SetCurrentHotbarSlot {
13781411
field slot: u8 =,
13791412
}
1413+
/// UpdateViewPosition is used to determine what chunks should be remain loaded.
1414+
packet UpdateViewPosition {
1415+
field chunk_x: VarInt =,
1416+
field chunk_z: VarInt =,
1417+
}
1418+
/// UpdateViewDistance is sent by the integrated server when changing render distance.
1419+
packet UpdateViewDistance {
1420+
field view_distance: VarInt =,
1421+
}
13801422
/// ScoreboardDisplay is used to set the display position of a scoreboard.
13811423
packet ScoreboardDisplay {
13821424
field position: u8 =,
@@ -2396,6 +2438,11 @@ pub enum RecipeData {
23962438
experience: f32,
23972439
cooking_time: VarInt,
23982440
},
2441+
Stonecutting {
2442+
group: String,
2443+
ingredient: RecipeIngredient,
2444+
result: Option<item::Stack>,
2445+
},
23992446
}
24002447

24012448
impl Default for RecipeData {
@@ -2413,8 +2460,35 @@ pub struct Recipe {
24132460

24142461
impl Serializable for Recipe {
24152462
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error> {
2416-
let id = String::read_from(buf)?;
2417-
let ty = String::read_from(buf)?;
2463+
let (id, ty, namespace) = {
2464+
let a = String::read_from(buf)?;
2465+
let b = String::read_from(buf)?;
2466+
2467+
let protocol_version = unsafe { crate::protocol::CURRENT_PROTOCOL_VERSION };
2468+
2469+
// 1.14+ swaps recipe identifier and type, and adds namespace to type
2470+
if protocol_version >= 477 {
2471+
let ty = a;
2472+
let id = b;
2473+
2474+
if let Some(at) = ty.find(':') {
2475+
let (namespace, ty) = ty.split_at(at + 1);
2476+
let ty: String = ty.into();
2477+
let namespace: String = namespace.into();
2478+
(id, ty, namespace)
2479+
} else {
2480+
(id, ty, "minecraft:".to_string())
2481+
}
2482+
} else {
2483+
let ty = b;
2484+
let id = a;
2485+
(id, ty, "minecraft:".to_string())
2486+
}
2487+
};
2488+
2489+
if namespace != "minecraft:" {
2490+
panic!("unrecognized recipe type namespace: {}", namespace);
2491+
}
24182492

24192493
let data =
24202494
match ty.as_ref() {
@@ -2473,13 +2547,18 @@ impl Serializable for Recipe {
24732547
experience: Serializable::read_from(buf)?,
24742548
cooking_time: Serializable::read_from(buf)?,
24752549
},
2476-
"campfire" => RecipeData::Campfire {
2550+
"campfire" | "campfire_cooking" => RecipeData::Campfire {
24772551
group: Serializable::read_from(buf)?,
24782552
ingredient: Serializable::read_from(buf)?,
24792553
result: Serializable::read_from(buf)?,
24802554
experience: Serializable::read_from(buf)?,
24812555
cooking_time: Serializable::read_from(buf)?,
24822556
},
2557+
"stonecutting" => RecipeData::Stonecutting {
2558+
group: Serializable::read_from(buf)?,
2559+
ingredient: Serializable::read_from(buf)?,
2560+
result: Serializable::read_from(buf)?,
2561+
},
24832562
_ => panic!("unrecognized recipe type: {}", ty)
24842563
};
24852564

protocol/src/versions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::protocol::*;
22

3+
mod v1_14;
34
mod v19w02a;
45
mod v18w50a;
56
mod v1_13_2;
@@ -16,6 +17,8 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir:
1617
match version {
1718
// https://wiki.vg/Protocol_History
1819
// https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite
20+
21+
477 => v1_14::translate_internal_packet_id(state, dir, id, to_internal),
1922

2023
// 19w02a
2124
452 => v19w02a::translate_internal_packet_id(state, dir, id, to_internal),

protocol/src/versions/v1_14.rs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
protocol_packet_ids!(
2+
handshake Handshaking {
3+
serverbound Serverbound {
4+
0x00 => Handshake
5+
}
6+
clientbound Clientbound {
7+
}
8+
}
9+
play Play {
10+
serverbound Serverbound {
11+
0x00 => TeleportConfirm
12+
0x01 => QueryBlockNBT
13+
0x02 => SetDifficulty
14+
0x03 => ChatMessage
15+
0x04 => ClientStatus
16+
0x05 => ClientSettings
17+
0x06 => TabComplete
18+
0x07 => ConfirmTransactionServerbound
19+
//0x08 => EnchantItem
20+
//0x08 => ClickWindowButton
21+
0x09 => ClickWindow
22+
0x0a => CloseWindow
23+
0x0b => PluginMessageServerbound
24+
0x0c => EditBook
25+
0x0d => QueryEntityNBT
26+
0x0e => UseEntity
27+
0x0f => KeepAliveServerbound_i64
28+
0x10 => LockDifficulty
29+
0x11 => PlayerPosition
30+
0x12 => PlayerPositionLook
31+
0x13 => PlayerLook
32+
0x14 => Player
33+
0x15 => VehicleMove
34+
0x16 => SteerBoat
35+
0x17 => PickItem
36+
0x18 => CraftRecipeRequest
37+
0x19 => ClientAbilities
38+
0x1a => PlayerDigging
39+
0x1b => PlayerAction
40+
0x1c => SteerVehicle
41+
0x1d => CraftingBookData
42+
0x1e => NameItem
43+
0x1f => ResourcePackStatus
44+
0x20 => AdvancementTab
45+
0x21 => SelectTrade
46+
0x22 => SetBeaconEffect
47+
0x23 => HeldItemChange
48+
0x24 => UpdateCommandBlock
49+
0x25 => UpdateCommandBlockMinecart
50+
0x26 => CreativeInventoryAction
51+
0x27 => UpdateJigsawBlock
52+
0x28 => UpdateStructureBlock
53+
0x29 => SetSign
54+
0x2a => ArmSwing
55+
0x2b => SpectateTeleport
56+
0x2c => PlayerBlockPlacement_f32
57+
0x2d => UseItem
58+
}
59+
clientbound Clientbound {
60+
0x00 => SpawnObject
61+
0x01 => SpawnExperienceOrb
62+
0x02 => SpawnGlobalEntity
63+
0x03 => SpawnMob
64+
0x04 => SpawnPainting
65+
0x05 => SpawnPlayer_f64
66+
0x06 => Animation
67+
0x07 => Statistics
68+
0x08 => BlockBreakAnimation
69+
0x09 => UpdateBlockEntity
70+
0x0a => BlockAction
71+
0x0b => BlockChange_VarInt
72+
0x0c => BossBar
73+
0x0d => ServerDifficulty_Locked
74+
0x0e => ServerMessage
75+
0x0f => MultiBlockChange_VarInt
76+
0x10 => TabCompleteReply
77+
0x11 => DeclareCommands
78+
0x12 => ConfirmTransaction
79+
0x13 => WindowClose
80+
0x14 => WindowItems
81+
0x15 => WindowProperty
82+
0x16 => WindowSetSlot
83+
0x17 => SetCooldown
84+
0x18 => PluginMessageClientbound
85+
0x19 => NamedSoundEffect
86+
0x1a => Disconnect
87+
0x1b => EntityAction
88+
0x1c => Explosion
89+
0x1d => ChunkUnload
90+
0x1e => ChangeGameState
91+
0x1f => WindowOpenHorse
92+
0x20 => KeepAliveClientbound_i64
93+
0x21 => ChunkData_HeightMap
94+
0x22 => Effect
95+
0x23 => Particle_Data
96+
0x24 => UpdateLight
97+
0x25 => JoinGame_i32_ViewDistance
98+
0x26 => Maps
99+
0x27 => TradeList
100+
0x28 => EntityMove_i16
101+
0x29 => EntityLookAndMove_i16
102+
0x2a => EntityLook_VarInt
103+
0x2b => Entity
104+
0x2c => VehicleTeleport
105+
0x2d => OpenBook
106+
0x2e => WindowOpen_VarInt
107+
0x2f => SignEditorOpen
108+
0x30 => CraftRecipeResponse
109+
0x31 => PlayerAbilities
110+
0x32 => CombatEvent
111+
0x33 => PlayerInfo
112+
0x34 => FacePlayer
113+
0x35 => TeleportPlayer_WithConfirm
114+
0x36 => UnlockRecipes_WithSmelting
115+
0x37 => EntityDestroy
116+
0x38 => EntityRemoveEffect
117+
0x39 => ResourcePackSend
118+
0x3a => Respawn
119+
0x3b => EntityHeadLook
120+
0x3c => SelectAdvancementTab
121+
0x3d => WorldBorder
122+
0x3e => Camera
123+
0x3f => SetCurrentHotbarSlot
124+
0x40 => UpdateViewPosition
125+
0x41 => UpdateViewDistance
126+
0x42 => ScoreboardDisplay
127+
0x43 => EntityMetadata
128+
0x44 => EntityAttach
129+
0x45 => EntityVelocity
130+
0x46 => EntityEquipment
131+
0x47 => SetExperience
132+
0x48 => UpdateHealth
133+
0x49 => ScoreboardObjective
134+
0x4a => SetPassengers
135+
0x4b => Teams
136+
0x4c => UpdateScore
137+
0x4d => SpawnPosition
138+
0x4e => TimeUpdate
139+
0x4f => Title
140+
0x50 => EntitySoundEffect
141+
0x51 => SoundEffect
142+
0x52 => StopSound
143+
0x53 => PlayerListHeaderFooter
144+
0x54 => NBTQueryResponse
145+
0x55 => CollectItem
146+
0x56 => EntityTeleport_f64
147+
0x57 => Advancements
148+
0x58 => EntityProperties
149+
0x59 => EntityEffect
150+
0x5a => DeclareRecipes
151+
0x5b => TagsWithEntities
152+
}
153+
}
154+
login Login {
155+
serverbound Serverbound {
156+
0x00 => LoginStart
157+
0x01 => EncryptionResponse
158+
0x02 => LoginPluginResponse
159+
}
160+
clientbound Clientbound {
161+
0x00 => LoginDisconnect
162+
0x01 => EncryptionRequest
163+
0x02 => LoginSuccess
164+
0x03 => SetInitialCompression
165+
0x04 => LoginPluginRequest
166+
}
167+
}
168+
status Status {
169+
serverbound Serverbound {
170+
0x00 => StatusRequest
171+
0x01 => StatusPing
172+
}
173+
clientbound Clientbound {
174+
0x00 => StatusResponse
175+
0x01 => StatusPong
176+
}
177+
}
178+
);
179+
180+

0 commit comments

Comments
 (0)