diff --git a/src/entity/character.rs b/src/entity/character.rs index a1cf2b3..2436d13 100644 --- a/src/entity/character.rs +++ b/src/entity/character.rs @@ -2,7 +2,7 @@ use std::convert::{From, Into, TryFrom, TryInto}; use std::collections::HashMap; use libpso::character::character; -use libpso::packet::ship::{UpdateConfig}; +use libpso::packet::ship::{UpdateConfig, WriteInfoboard}; #[derive(Copy, Clone, Hash, PartialEq, Eq)] pub enum CharacterClass { @@ -224,6 +224,27 @@ impl CharacterConfig { } } +#[derive(Clone)] +pub struct CharacterInfoboard { + board: [u16; 172], +} + +impl CharacterInfoboard { + fn new() -> CharacterInfoboard { + CharacterInfoboard { + board: [0; 172] + } + } + + pub fn as_bytes(&self) -> [u16; 172] { + self.board + } + + pub fn update_infoboard(&mut self, new_board: &WriteInfoboard) { + self.board = libpso::utf8_to_utf16_array!(new_board.message, 172); + } +} + #[derive(Clone)] pub struct Character { @@ -240,6 +261,7 @@ pub struct Character { pub appearance: CharacterAppearance, pub techs: CharacterTechniques, pub config: CharacterConfig, + pub info_board: CharacterInfoboard, } impl std::default::Default for Character { @@ -255,6 +277,7 @@ impl std::default::Default for Character { appearance: CharacterAppearance::default(), techs: CharacterTechniques::new(), config: CharacterConfig::new(), + info_board: CharacterInfoboard::new(), } } } diff --git a/src/ship/character.rs b/src/ship/character.rs index b85bc71..f6334bc 100644 --- a/src/ship/character.rs +++ b/src/ship/character.rs @@ -139,6 +139,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + pub fn build(self) -> character::FullCharacter { let character = self.character.unwrap(); let stats = self.stats.unwrap(); @@ -163,6 +164,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { joystick_config: *joystick_config, ..character::KeyTeamConfig::default() }, + info_board: character.info_board.as_bytes(), ..character::FullCharacter::default() } } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index b0c6668..ced4ba0 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -44,6 +44,8 @@ pub enum RecvShipPacket { CreateRoom(CreateRoom), RoomNameRequest(RoomNameRequest), UpdateConfig(UpdateConfig), + ViewInfoboardRequest(ViewInfoboardRequest), + WriteInfoboard(WriteInfoboard), } impl RecvServerPacket for RecvShipPacket { @@ -58,6 +60,8 @@ impl RecvServerPacket for RecvShipPacket { 0xC1 => Ok(RecvShipPacket::CreateRoom(CreateRoom::from_bytes(data)?)), 0x8A => Ok(RecvShipPacket::RoomNameRequest(RoomNameRequest::from_bytes(data)?)), 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)), + 0xD8 => Ok(RecvShipPacket::ViewInfoboardRequest(ViewInfoboardRequest::from_bytes(data)?)), + 0xD9 => Ok(RecvShipPacket::WriteInfoboard(WriteInfoboard::from_bytes(data)?)), _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())) } } @@ -81,6 +85,7 @@ pub enum SendShipPacket { LeaveLobby(LeaveLobby), LeaveRoom(LeaveRoom), RoomNameResponse(RoomNameResponse), + ViewInfoboardResponse(ViewInfoboardResponse), } impl SendServerPacket for SendShipPacket { @@ -102,6 +107,7 @@ impl SendServerPacket for SendShipPacket { SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(), SendShipPacket::LeaveRoom(pkt) => pkt.as_bytes(), SendShipPacket::RoomNameResponse(pkt) => pkt.as_bytes(), + SendShipPacket::ViewInfoboardResponse(pkt) => pkt.as_bytes(), } } } @@ -407,6 +413,32 @@ impl ShipServerState { self.entity_gateway.set_character(&client.character); Box::new(None.into_iter()) } + + fn request_infoboard(&mut self, id: ClientId, request_infoboard: &ViewInfoboardRequest) -> Box + Send> { + let lobby = self.client_location.get_area_by_user(id); + let clients = lobby.clients(); + let r = clients + .iter() + .filter(|c| c.client_id != id) + .filter_map(|c| { + self.clients.get(&c.client_id) + }) + .map(|c| { + InfoboardResponse { + name: libpso::utf8_to_utf16_array!(c.character.name, 16), + message: c.character.info_board.as_bytes(), + } + }) + .collect(); + Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter()) + } + + fn write_infoboard(&mut self, id: ClientId, new_infoboard: &WriteInfoboard) -> Box + Send> { + let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + client.character.info_board.update_infoboard(new_infoboard); + self.entity_gateway.set_character(&client.character); + Box::new(None.into_iter()) + } } @@ -463,6 +495,14 @@ impl ServerState for ShipServerState { RecvShipPacket::UpdateConfig(pkt) => { self.update_config(id, pkt) }, + + RecvShipPacket::ViewInfoboardRequest(pkt) => { + self.request_infoboard(id, pkt) + }, + + RecvShipPacket::WriteInfoboard(pkt) => { + self.write_infoboard(id, pkt) + }, }) }