use std::error::Error; use protobuf::{Enum, Message}; use crate::message_c2s::{MessageC2SChat, MessageC2SGoodbye, MessageC2SHello, MessageC2SInput, MessageC2SPing}; use crate::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong}; use crate::planet::PlanetType; use crate::starkingdoms_protocol::PacketWrapper; include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); pub const PROTOCOL_VERSION: u32 = 1; #[derive(Debug)] pub enum MessageC2S { Hello(MessageC2SHello), Goodbye(MessageC2SGoodbye), Chat(MessageC2SChat), Ping(MessageC2SPing), Input(MessageC2SInput) } #[derive(Debug)] pub enum MessageS2C { Hello(MessageS2CHello), Goodbye(MessageS2CGoodbye), Chat(MessageS2CChat), Pong(MessageS2CPong), PlayersUpdate(MessageS2CPlayersUpdate), PlanetData(MessageS2CPlanetData) } impl TryFrom<&[u8]> for MessageC2S { type Error = Box; fn try_from(value: &[u8]) -> Result { let pkt = starkingdoms_protocol::PacketWrapper::parse_from_bytes(value)?; let deser_pkt = match pkt.packet_id { _id if _id == message_c2s::message_c2shello::Packet_info::type_.value() as i64 => { MessageC2S::Hello(MessageC2SHello::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_c2s::message_c2sgoodbye::Packet_info::type_.value() as i64 => { MessageC2S::Goodbye(MessageC2SGoodbye::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_c2s::message_c2schat::Packet_info::type_.value() as i64 => { MessageC2S::Chat(MessageC2SChat::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_c2s::message_c2sping::Packet_info::type_.value() as i64 => { MessageC2S::Ping(MessageC2SPing::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_c2s::message_c2sinput::Packet_info::type_.value() as i64 => { MessageC2S::Input(MessageC2SInput::parse_from_bytes(&pkt.packet_data)?) } _id => { return Err(format!("Unrecognized C2S packet {}", _id).into()); } }; Ok(deser_pkt) } } impl TryInto> for MessageC2S { type Error = Box; fn try_into(self) -> Result, Self::Error> { let (pkt_id, pkt_bytes) = match self { MessageC2S::Hello(p) => { (message_c2s::message_c2shello::Packet_info::type_.value(), p.write_to_bytes()?) } MessageC2S::Goodbye(p) => { (message_c2s::message_c2sgoodbye::Packet_info::type_.value(), p.write_to_bytes()?) } MessageC2S::Chat(p) => { (message_c2s::message_c2schat::Packet_info::type_.value(), p.write_to_bytes()?) } MessageC2S::Ping(p) => { (message_c2s::message_c2sping::Packet_info::type_.value(), p.write_to_bytes()?) } MessageC2S::Input(p) => { (message_c2s::message_c2sping::Packet_info::type_.value(), p.write_to_bytes()?) } }; let pkt = PacketWrapper { packet_id: pkt_id as i64, packet_data: pkt_bytes, special_fields: Default::default(), }; Ok(pkt.write_to_bytes()?) } } impl TryFrom<&[u8]> for MessageS2C { type Error = Box; fn try_from(value: &[u8]) -> Result { let pkt = PacketWrapper::parse_from_bytes(value)?; let deser_pkt = match pkt.packet_id { _id if _id == message_s2c::message_s2chello::Packet_info::type_.value() as i64 => { MessageS2C::Hello(MessageS2CHello::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_s2c::message_s2cgoodbye::Packet_info::type_.value() as i64 => { MessageS2C::Goodbye(MessageS2CGoodbye::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_s2c::message_s2cchat::Packet_info::type_.value() as i64 => { MessageS2C::Chat(MessageS2CChat::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_s2c::message_s2cpong::Packet_info::type_.value() as i64 => { MessageS2C::Pong(MessageS2CPong::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_s2c::message_s2cplayers_update::Packet_info::type_.value() as i64 => { MessageS2C::PlayersUpdate(MessageS2CPlayersUpdate::parse_from_bytes(&pkt.packet_data)?) }, _id if _id == message_s2c::message_s2cplanet_data::Packet_info::type_.value() as i64 => { MessageS2C::PlanetData(MessageS2CPlanetData::parse_from_bytes(&pkt.packet_data)?) }, _ => { return Err("Not a S2C packet".into()); } }; Ok(deser_pkt) } } impl TryInto> for MessageS2C { type Error = Box; fn try_into(self) -> Result, Self::Error> { let (pkt_id, pkt_bytes) = match self { MessageS2C::Hello(p) => { (message_s2c::message_s2chello::Packet_info::type_.value(), p.write_to_bytes()?) } MessageS2C::Goodbye(p) => { (message_s2c::message_s2cgoodbye::Packet_info::type_.value(), p.write_to_bytes()?) } MessageS2C::Chat(p) => { (message_s2c::message_s2cchat::Packet_info::type_.value(), p.write_to_bytes()?) } MessageS2C::Pong(p) => { (message_s2c::message_s2cpong::Packet_info::type_.value(), p.write_to_bytes()?) } MessageS2C::PlayersUpdate(p) => { (message_s2c::message_s2cplayers_update::Packet_info::type_.value(), p.write_to_bytes()?) } MessageS2C::PlanetData(p) => { (message_s2c::message_s2cplanet_data::Packet_info::type_.value(), p.write_to_bytes()?) } }; let pkt = PacketWrapper { packet_id: pkt_id as i64, packet_data: pkt_bytes, special_fields: Default::default(), }; Ok(pkt.write_to_bytes()?) } } impl planet::PlanetType { pub fn as_texture_id(&self) -> String { match self { PlanetType::Earth => "earth".to_string(), PlanetType::Moon => "moon".to_string() } } }