From d80eca3940a08ba84e7ac8f359d7b463881868b3 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Fri, 30 Nov 2018 16:41:27 -0800 Subject: [PATCH] Get the protocol version to send from the ping packet (#20) The first step of https://github.com/iceiix/steven/issues/18 Enhance protocol support, instead of hardcoding a fixed version, the client now matches whatever the server sent. * Get the protocol version to send from the ping packet * Save/load server protocol versions to disk, server_versions.json * Fallback to default SUPPORTED_PROTOCOL if no ping response --- src/main.rs | 24 ++++++++++++++++++++++-- src/screen/server_list.rs | 11 +++++++++++ src/server/mod.rs | 4 ++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3050e12..81ff24a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ #![recursion_limit="300"] use std::time::{Instant, Duration}; -use log::info; +use log::{info, warn}; extern crate steven_shared as shared; #[macro_use] @@ -73,6 +73,8 @@ pub struct Game { chunk_builder: chunk_builder::ChunkBuilder, connect_reply: Option>>, + protocol_version: i32, + dpi_factor: f64, last_mouse_x: f64, last_mouse_y: f64, @@ -83,6 +85,23 @@ pub struct Game { impl Game { pub fn connect_to(&mut self, address: &str) { + // Read saved server protocol version from ping response TODO: get from memory? + use std::fs; + let file = match fs::File::open("server_versions.json") { + Ok(val) => val, + Err(_) => return, + }; + let server_versions_info: serde_json::Value = serde_json::from_reader(file).unwrap(); + let protocol_version = { + 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 + } + }; + + self.protocol_version = protocol_version; let (tx, rx) = mpsc::channel(); self.connect_reply = Some(rx); let address = address.to_owned(); @@ -93,7 +112,7 @@ impl Game { access_token: self.vars.get(auth::AUTH_TOKEN).clone(), }; thread::spawn(move || { - tx.send(server::Server::connect(resources, profile, &address)).unwrap(); + tx.send(server::Server::connect(resources, profile, &address, protocol_version)).unwrap(); }); } @@ -211,6 +230,7 @@ fn main() { should_close: false, chunk_builder: chunk_builder::ChunkBuilder::new(resource_manager, textures), connect_reply: None, + protocol_version: protocol::SUPPORTED_PROTOCOL, dpi_factor, last_mouse_x: 0.0, last_mouse_y: 0.0, diff --git a/src/screen/server_list.rs b/src/screen/server_list.rs index c82c01e..3051091 100644 --- a/src/screen/server_list.rs +++ b/src/screen/server_list.rs @@ -17,6 +17,7 @@ use std::thread; use std::sync::mpsc; use std::rc::Rc; use std::cell::RefCell; +use std::collections::HashMap; use crate::ui; use crate::render; @@ -36,6 +37,7 @@ pub struct ServerList { disconnect_reason: Option, needs_reload: Rc>, + server_protocol_versions: HashMap, } struct UIElements { @@ -68,6 +70,7 @@ struct Server { } struct PingInfo { + address: String, motd: format::Component, ping: Duration, exists: bool, @@ -94,6 +97,7 @@ impl ServerList { elements: None, disconnect_reason, needs_reload: Rc::new(RefCell::new(false)), + server_protocol_versions: HashMap::new(), } } @@ -271,6 +275,7 @@ impl ServerList { None }; drop(send.send(PingInfo { + address, motd: desc, ping: res.1, exists: true, @@ -286,6 +291,7 @@ impl ServerList { let mut msg = TextComponent::new(&e); msg.modifier.color = Some(format::Color::Red); let _ = send.send(PingInfo { + address, motd: Component::Text(msg), ping: Duration::new(99999, 0), exists: false, @@ -488,6 +494,11 @@ impl super::Screen for ServerList { format!("Out of date {}/{}", res.online, res.max) }; players.text = txt; + + // TODO: store in memory instead of disk? but where? + self.server_protocol_versions.insert(res.address, res.protocol_version); + let mut out = fs::File::create("server_versions.json").unwrap(); + serde_json::to_writer_pretty(&mut out, &self.server_protocol_versions).unwrap(); } let mut txt = TextComponent::new(&res.protocol_name); txt.modifier.color = Some(format::Color::Yellow); diff --git a/src/server/mod.rs b/src/server/mod.rs index e75cf5f..f737cba 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -103,13 +103,13 @@ macro_rules! handle_packet { impl Server { - pub fn connect(resources: Arc>, profile: mojang::Profile, address: &str) -> Result { + pub fn connect(resources: Arc>, profile: mojang::Profile, address: &str, protocol_version: i32) -> Result { let mut conn = protocol::Conn::new(address)?; let host = conn.host.clone(); let port = conn.port; conn.write_packet(protocol::packet::handshake::serverbound::Handshake { - protocol_version: protocol::VarInt(protocol::SUPPORTED_PROTOCOL), + protocol_version: protocol::VarInt(protocol_version), host, port, next: protocol::VarInt(2),