Handle packets from the server

main
Avery 4 weeks ago
parent 188e2b7610
commit ead62f7036
Signed by: Avery
GPG Key ID: 4E53F4CB69B2CC8D

@ -20,6 +20,7 @@ impl Server<Status> {
mut stream, mut stream,
addr, addr,
port, port,
lang,
state: state:
Status { Status {
typ, typ,
@ -235,6 +236,7 @@ impl Server<Status> {
stream, stream,
addr, addr,
port, port,
lang,
state: Connected { state: Connected {
typ, typ,
description, description,

File diff suppressed because it is too large Load Diff

@ -0,0 +1,20 @@
use std::collections::HashMap;
const LANG: &'static str = include_str!("./en_US.lang");
pub type Lang = HashMap<&'static str, &'static str>;
fn parse_lang(lang_src: &'static str) -> HashMap<&'static str, &'static str> {
let mut lang = HashMap::new();
for line in lang_src.lines() {
let Some((key, val)) = line.split_once('=') else {
continue;
};
lang.insert(key, val);
}
lang
}
pub fn get_lang() -> HashMap<&'static str, &'static str> {
parse_lang(LANG)
}

@ -1,22 +1,17 @@
mod connect; mod connect;
mod error; mod error;
mod lang;
mod readers; mod readers;
mod run;
mod status; mod status;
mod text; mod text;
mod writers; mod writers;
use std::{ use std::{collections::HashMap, fmt::Debug, net::TcpStream};
collections::HashMap,
fmt::Debug,
io::{Read, Write},
net::TcpStream,
};
use error::Result; use error::Result;
use readers::read_string; use lang::{Lang, get_lang};
use status::ServerType; use status::ServerType;
use text::Message;
use varint_rs::{VarintReader, VarintWriter};
pub trait ServerState {} pub trait ServerState {}
@ -45,6 +40,7 @@ pub struct Server<S: ServerState + Debug> {
stream: TcpStream, stream: TcpStream,
addr: String, addr: String,
port: u16, port: u16,
lang: Lang,
state: S, state: S,
} }
@ -54,6 +50,7 @@ impl Server<Disconnected> {
stream: TcpStream::connect(format!("{addr}:{port}"))?, stream: TcpStream::connect(format!("{addr}:{port}"))?,
addr, addr,
port, port,
lang: get_lang(),
state: Disconnected, state: Disconnected,
}) })
} }
@ -69,26 +66,5 @@ fn main() -> Result<()> {
let server = server.connect()?; let server = server.connect()?;
dbg!(&server); dbg!(&server);
Ok(()) server.run()
}
fn handle_keepalive(stream: &mut TcpStream, mut packet: &[u8]) {
let _packetid = packet.read_usize_varint().unwrap();
let mut id = [0u8; 4];
packet.read_exact(&mut id).unwrap();
let mut buf: Vec<u8> = Vec::new();
buf.write_u8_varint(0).unwrap();
buf.write_all(&id).unwrap();
stream.write_usize_varint(buf.len()).unwrap();
stream.write_all(&buf).unwrap();
}
fn handle_chat(mut packet: &[u8]) {
let _packetid = packet.read_usize_varint().unwrap();
let msg = read_string(&mut packet);
let msg = Message::from_string(msg.unwrap());
dbg!(msg);
} }

@ -0,0 +1,73 @@
use std::{
io::{Read as _, Write as _},
net::TcpStream,
};
use varint_rs::{VarintReader, VarintWriter as _};
use crate::{
Connected, Server,
error::Result,
readers::{read_packet, read_string},
text::Message,
};
pub enum Packet {
KeepAlive([u8; 4]),
Chat(Vec<Message>),
Disconnect,
Other(usize, Vec<u8>),
}
impl Server<Connected> {
pub fn run(self) -> Result<()> {
let Self {
mut stream,
lang,
state: Connected { .. },
..
} = self;
loop {
let packet = read_packet(&mut stream, parse_packet)?;
match packet {
Packet::KeepAlive(id) => handle_keepalive(&mut stream, id)?,
Packet::Chat(m) => {
for m in m {
println!("{}", m.format(&lang))
}
}
Packet::Disconnect => break,
Packet::Other(_, _) => {}
}
}
Ok(())
}
}
fn parse_packet(packet: &mut &[u8]) -> Result<Packet> {
let id = packet.read_usize_varint()?;
match id {
0x00 => {
let mut id = [0u8; 4];
packet.read_exact(&mut id)?;
Ok(Packet::KeepAlive(id))
}
0x02 => {
let msg = read_string(packet)?;
let msg = Message::from_string(msg).unwrap();
Ok(Packet::Chat(msg))
}
0x40 => Ok(Packet::Disconnect),
i => Ok(Packet::Other(i, packet.to_vec())),
}
}
fn handle_keepalive(stream: &mut TcpStream, id: [u8; 4]) -> Result<()> {
let mut buf: Vec<u8> = Vec::new();
buf.write_u8_varint(0)?;
buf.write_all(&id)?;
stream.write_usize_varint(buf.len())?;
stream.write_all(&buf)?;
Ok(())
}

@ -24,6 +24,7 @@ impl Server<Disconnected> {
mut stream, mut stream,
addr, addr,
port, port,
lang,
.. ..
} = self; } = self;
@ -108,6 +109,7 @@ impl Server<Disconnected> {
stream: TcpStream::connect(format!("{addr}:{port}"))?, stream: TcpStream::connect(format!("{addr}:{port}"))?,
addr, addr,
port, port,
lang,
state: Status { state: Status {
typ, typ,
description, description,

@ -1,4 +1,6 @@
use serde_json::Value; use serde_json::{Value, to_string};
use crate::lang::Lang;
#[derive(Debug)] #[derive(Debug)]
pub struct Message { pub struct Message {
@ -6,12 +8,13 @@ pub struct Message {
} }
#[derive(Debug)] #[derive(Debug)]
#[allow(unused)]
pub enum MessageContent { pub enum MessageContent {
Text(String), Text(String),
Translate { Translate {
translate: String, translate: String,
fallback: Option<String>, fallback: Option<String>,
with: Option<Vec<Value>>, with: Option<Vec<Message>>,
}, },
Score { Score {
name: String, name: String,
@ -31,15 +34,46 @@ pub enum MessageContent {
} }
impl Message { impl Message {
pub fn from_string(string: String) -> Option<Self> { pub fn format(self, lang: &Lang) -> String {
let Self { content } = self;
match content {
MessageContent::Text(t) => t,
MessageContent::Translate {
translate,
fallback: _,
with,
} => {
if let Some(template) = lang.get(translate.as_str()) {
let mut template = template.to_string();
if let Some(with) = with {
for subst in with.into_iter().map(|m| m.format(lang)) {
if template.contains("%s") {
template = template.replacen("%s", &subst, 1);
} else {
break;
}
}
template
} else {
template
}
} else {
translate
}
}
m => format!("{:?}", m),
}
}
pub fn from_string(string: String) -> Option<Vec<Self>> {
let json: Value = serde_json::from_str(&string).ok()?; let json: Value = serde_json::from_str(&string).ok()?;
Self::from_json(json) Self::from_json(json)
} }
fn from_json(message: Value) -> Option<Self> { fn from_json(message: Value) -> Option<Vec<Self>> {
let message = message.as_object()?; let message = message.as_object()?;
match message.get("type") { let msg = match message.get("type") {
Some(typ) => match typ.as_str()? { Some(typ) => match typ.as_str()? {
"text" => Some(Message { "text" => Some(Message {
content: MessageContent::Text(message.get("text")?.as_str()?.to_string()), content: MessageContent::Text(message.get("text")?.as_str()?.to_string()),
@ -51,7 +85,26 @@ impl Message {
.get("fallback") .get("fallback")
.map(|v| v.as_str().map(str::to_string)) .map(|v| v.as_str().map(str::to_string))
.flatten(), .flatten(),
with: message.get("with").map(|a| a.as_array().cloned()).flatten(), with: message
.get("with")
.map(|a| {
a.as_array().cloned().map(|a| {
a.into_iter()
.map(|v| {
if let Some(s) = v.as_str() {
vec![Message {
content: MessageContent::Text(s.to_string()),
}]
} else {
Message::from_json(v).unwrap()
}
.into_iter()
})
.flatten()
.collect()
})
})
.flatten(),
}, },
}), }),
"score" => { "score" => {
@ -107,7 +160,28 @@ impl Message {
.get("fallback") .get("fallback")
.map(|v| v.as_str().map(str::to_string)) .map(|v| v.as_str().map(str::to_string))
.flatten(), .flatten(),
with: message.get("with").map(|a| a.as_array().cloned()).flatten(), with: message
.get("with")
.map(|a| {
a.as_array().cloned().map(|a| {
a.into_iter()
.map(|v| {
if let Some(s) = v.as_str() {
vec![Message {
content: MessageContent::Text(
s.to_string(),
),
}]
} else {
Message::from_json(v).unwrap()
}
.into_iter()
})
.flatten()
.collect()
})
})
.flatten(),
}, },
}) })
} else if let Some(score) = message.get("score") { } else if let Some(score) = message.get("score") {
@ -154,6 +228,28 @@ impl Message {
None None
} }
} }
} }?;
let mut extra = if let Some(extra) = message.get("extra") {
let extra = extra.as_array()?;
let extra: Vec<Message> = extra
.into_iter()
.map(|v| {
if let Some(s) = v.as_str() {
vec![Message {
content: MessageContent::Text(s.to_string()),
}]
} else {
Message::from_json(v.clone()).unwrap()
}
.into_iter()
})
.flatten()
.collect();
extra
} else {
Vec::new()
};
extra.push(msg);
Some(extra)
} }
} }

Loading…
Cancel
Save