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
This commit is contained in:
iceiix 2018-11-30 16:41:27 -08:00 committed by GitHub
parent c099a68168
commit d80eca3940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 4 deletions

View File

@ -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<mpsc::Receiver<Result<server::Server, protocol::Error>>>,
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,

View File

@ -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<Component>,
needs_reload: Rc<RefCell<bool>>,
server_protocol_versions: HashMap<String, i32>,
}
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);

View File

@ -103,13 +103,13 @@ macro_rules! handle_packet {
impl Server {
pub fn connect(resources: Arc<RwLock<resources::Manager>>, profile: mojang::Profile, address: &str) -> Result<Server, protocol::Error> {
pub fn connect(resources: Arc<RwLock<resources::Manager>>, profile: mojang::Profile, address: &str, protocol_version: i32) -> Result<Server, protocol::Error> {
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),