Handle packets from the server

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

@ -20,6 +20,7 @@ impl Server<Status> {
mut stream,
addr,
port,
lang,
state:
Status {
typ,
@ -235,6 +236,7 @@ impl Server<Status> {
stream,
addr,
port,
lang,
state: Connected {
typ,
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 error;
mod lang;
mod readers;
mod run;
mod status;
mod text;
mod writers;
use std::{
collections::HashMap,
fmt::Debug,
io::{Read, Write},
net::TcpStream,
};
use std::{collections::HashMap, fmt::Debug, net::TcpStream};
use error::Result;
use readers::read_string;
use lang::{Lang, get_lang};
use status::ServerType;
use text::Message;
use varint_rs::{VarintReader, VarintWriter};
pub trait ServerState {}
@ -45,6 +40,7 @@ pub struct Server<S: ServerState + Debug> {
stream: TcpStream,
addr: String,
port: u16,
lang: Lang,
state: S,
}
@ -54,6 +50,7 @@ impl Server<Disconnected> {
stream: TcpStream::connect(format!("{addr}:{port}"))?,
addr,
port,
lang: get_lang(),
state: Disconnected,
})
}
@ -69,26 +66,5 @@ fn main() -> Result<()> {
let server = server.connect()?;
dbg!(&server);
Ok(())
}
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);
server.run()
}

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

@ -1,4 +1,6 @@
use serde_json::Value;
use serde_json::{Value, to_string};
use crate::lang::Lang;
#[derive(Debug)]
pub struct Message {
@ -6,12 +8,13 @@ pub struct Message {
}
#[derive(Debug)]
#[allow(unused)]
pub enum MessageContent {
Text(String),
Translate {
translate: String,
fallback: Option<String>,
with: Option<Vec<Value>>,
with: Option<Vec<Message>>,
},
Score {
name: String,
@ -31,15 +34,46 @@ pub enum MessageContent {
}
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()?;
Self::from_json(json)
}
fn from_json(message: Value) -> Option<Self> {
fn from_json(message: Value) -> Option<Vec<Self>> {
let message = message.as_object()?;
match message.get("type") {
let msg = match message.get("type") {
Some(typ) => match typ.as_str()? {
"text" => Some(Message {
content: MessageContent::Text(message.get("text")?.as_str()?.to_string()),
@ -51,7 +85,26 @@ impl Message {
.get("fallback")
.map(|v| v.as_str().map(str::to_string))
.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" => {
@ -107,7 +160,28 @@ impl Message {
.get("fallback")
.map(|v| v.as_str().map(str::to_string))
.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") {
@ -154,6 +228,28 @@ impl Message {
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