From ffce662c95f1263fbd6d581a33923debcab73c51 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 21 Nov 2020 23:45:27 -0700 Subject: [PATCH] transfer ship --- src/login/character.rs | 15 +++++++++++---- src/ship/packet/builder/mod.rs | 1 + src/ship/packet/builder/ship.rs | 29 +++++++++++++++++++++++++++++ src/ship/packet/handler/mod.rs | 1 + src/ship/packet/handler/ship.rs | 23 +++++++++++++++++++++++ src/ship/ship.rs | 24 ++++++++++++++++++++++-- 6 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 src/ship/packet/builder/ship.rs create mode 100644 src/ship/packet/handler/ship.rs diff --git a/src/login/character.rs b/src/login/character.rs index 57b0bee..895ce7e 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -32,7 +32,7 @@ use crate::login::login::{get_login_status, check_if_already_online}; use crate::common::interserver::AuthToken; pub const CHARACTER_PORT: u16 = 12001; -const SHIP_MENU_ID: u32 = 1; +pub const SHIP_MENU_ID: u32 = 1; #[derive(thiserror::Error, Debug)] #[error("")] @@ -173,7 +173,7 @@ impl ClientState { } } -#[derive(Clone)] +#[derive(Debug, Clone)] struct ConnectedClient { ship_id: Option, expires: Option>, @@ -591,7 +591,7 @@ impl ServerState for CharacterServerState { Box::new(self.character_preview(id, preview).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::MenuSelect(menuselect) => { - Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.select_ship(id, menuselect)?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::MenuDetail(menudetail) => { match menudetail.menu { @@ -635,7 +635,14 @@ impl InterserverActor for CharacterServerState { if self.authenticated_ships.contains(&id) { self.ships.insert(id, new_ship); } - Ok(Vec::new()) + + let ships = self.ships.iter().map(|(_, s)| s).cloned().collect::>(); + Ok(self.ships + .iter() + .map(|(id, _)| { + (*id, LoginMessage::ShipList{ ships: ships.clone() }) + }) + .collect()) }, ShipMessage::AddUser(new_user) => { if self.authenticated_ships.contains(&id) { diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs index 2ce4837..b1fa664 100644 --- a/src/ship/packet/builder/mod.rs +++ b/src/ship/packet/builder/mod.rs @@ -2,6 +2,7 @@ pub mod lobby; pub mod message; pub mod room; pub mod quest; +pub mod ship; use libpso::character::character::Inventory; use libpso::packet::ship::{PlayerHeader, PlayerInfo}; diff --git a/src/ship/packet/builder/ship.rs b/src/ship/packet/builder/ship.rs new file mode 100644 index 0000000..c80d562 --- /dev/null +++ b/src/ship/packet/builder/ship.rs @@ -0,0 +1,29 @@ +use libpso::packet::login::{ShipList, ShipListEntry}; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{ShipError, ClientState, Clients}; +use crate::ship::location::{ClientLocation, RoomId, AreaClient, ClientLocationError}; +use crate::ship::room::RoomState; +use crate::ship::items::ItemManager; +use crate::ship::packet::builder::{player_header, player_info}; +use libpso::utf8_to_utf16_array; + +use crate::common::interserver::Ship; +use libpso::packet::ship::BLOCK_MENU_ID; +use crate::login::character::SHIP_MENU_ID; + +pub fn ship_list(ships: &Vec) -> ShipList { + let ships = ships.iter() + .enumerate() + .map(|(i, ship)| { + ShipListEntry { + menu: SHIP_MENU_ID, + item: i as u32, + flags: 0, + name: utf8_to_utf16_array!(ship.name, 0x11) + } + }) + .collect(); + ShipList::new(ships) +} diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs index 192c8ab..02761f8 100644 --- a/src/ship/packet/handler/mod.rs +++ b/src/ship/packet/handler/mod.rs @@ -6,3 +6,4 @@ pub mod message; pub mod room; pub mod settings; pub mod quest; +pub mod ship; diff --git a/src/ship/packet/handler/ship.rs b/src/ship/packet/handler/ship.rs new file mode 100644 index 0000000..9916901 --- /dev/null +++ b/src/ship/packet/handler/ship.rs @@ -0,0 +1,23 @@ +use libpso::packet::ship::*; +use libpso::packet::login::RedirectClient; +use crate::common::serverstate::ClientId; +use crate::common::interserver::Ship; +use crate::ship::ship::{SendShipPacket, ShipError, Clients}; +use crate::ship::packet::builder; + +pub fn ship_list(id: ClientId, ship_list: &Vec) + -> Box + Send> { + Box::new(vec![(id, SendShipPacket::ShipList(builder::ship::ship_list(ship_list)))].into_iter()) +} + +pub fn block_list(id: ClientId, shipname: &str, num_blocks: usize) + -> Box + Send> { + Box::new(vec![(id, SendShipPacket::ShipBlockList(ShipBlockList::new(shipname, num_blocks)))].into_iter()) +} + +pub fn selected_ship(id: ClientId, menuselect: &MenuSelect, ship_list: &Vec) + -> Result + Send>, ShipError> { + let ship = ship_list.get(menuselect.item as usize).ok_or(ShipError::InvalidShip(menuselect.item as usize))?; + let ip = u32::from_ne_bytes(ship.ip.octets()); + Ok(Box::new(vec![(id, SendShipPacket::RedirectClient(RedirectClient::new(ip, ship.port)))].into_iter())) +} diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 6651999..89d3015 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -6,7 +6,7 @@ use rand::Rng; use thiserror::Error; use libpso::packet::ship::*; -use libpso::packet::login::{Login, LoginResponse, Session}; +use libpso::packet::login::{RedirectClient, Login, LoginResponse, Session, ShipList}; use libpso::packet::messages::*; use libpso::{PacketParseError, PSOPacket}; use libpso::crypto::bb::PSOBBCipher; @@ -18,6 +18,8 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState use crate::common::leveltable::CharacterLevelTable; use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage}; +use crate::login::character::SHIP_MENU_ID; + use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; use crate::entity::character::{CharacterEntity, SectionID}; @@ -67,6 +69,7 @@ pub enum ShipError { ShopError, GatewayError(#[from] GatewayError), UnknownMonster(crate::ship::monster::MonsterType), + InvalidShip(usize), } #[derive(Debug)] @@ -98,6 +101,8 @@ pub enum RecvShipPacket { DoneLoadingQuest(DoneLoadingQuest), FullCharacterData(Box), SaveOptions(SaveOptions), + RequestShipList(RequestShipList), + RequestShipBlockList(RequestShipBlockList), } impl RecvServerPacket for RecvShipPacket { @@ -131,6 +136,8 @@ impl RecvServerPacket for RecvShipPacket { 0x6F => Ok(RecvShipPacket::DoneBursting(DoneBursting::from_bytes(data)?)), 0x16F => Ok(RecvShipPacket::DoneBursting2(DoneBursting2::from_bytes(data)?)), 0x84 => Ok(RecvShipPacket::LobbySelect(LobbySelect::from_bytes(data)?)), + 0xA0 => Ok(RecvShipPacket::RequestShipList(RequestShipList::from_bytes(data)?)), + 0xA1 => Ok(RecvShipPacket::RequestShipBlockList(RequestShipBlockList::from_bytes(data)?)), 0xA2 => Ok(RecvShipPacket::RequestQuestList(RequestQuestList::from_bytes(data)?)), 0xAC => Ok(RecvShipPacket::DoneLoadingQuest(DoneLoadingQuest::from_bytes(data)?)), 0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))), @@ -144,6 +151,7 @@ impl RecvServerPacket for RecvShipPacket { pub enum SendShipPacket { ShipWelcome(ShipWelcome), LoginResponse(LoginResponse), + ShipList(ShipList), ShipBlockList(ShipBlockList), FullCharacter(Box), CharDataRequest(CharDataRequest), @@ -172,6 +180,7 @@ pub enum SendShipPacket { QuestChunk(QuestChunk), DoneLoadingQuest(DoneLoadingQuest), BankItemList(BankItemList), + RedirectClient(RedirectClient), } impl SendServerPacket for SendShipPacket { @@ -179,6 +188,7 @@ impl SendServerPacket for SendShipPacket { match self { SendShipPacket::ShipWelcome(pkt) => pkt.as_bytes(), SendShipPacket::LoginResponse(pkt) => pkt.as_bytes(), + SendShipPacket::ShipList(pkt) => pkt.as_bytes(), SendShipPacket::ShipBlockList(pkt) => pkt.as_bytes(), SendShipPacket::FullCharacter(pkt) => pkt.as_bytes(), SendShipPacket::CharDataRequest(pkt) => pkt.as_bytes(), @@ -207,6 +217,7 @@ impl SendServerPacket for SendShipPacket { SendShipPacket::QuestChunk(pkt) => pkt.as_bytes(), SendShipPacket::DoneLoadingQuest(pkt) => pkt.as_bytes(), SendShipPacket::BankItemList(pkt) => pkt.as_bytes(), + SendShipPacket::RedirectClient(pkt) => pkt.as_bytes(), } } } @@ -508,6 +519,7 @@ impl ServerState for ShipServerState { }, RecvShipPacket::MenuSelect(menuselect) => { match menuselect.menu { + SHIP_MENU_ID => handler::ship::selected_ship(id, menuselect, &self.ship_list)?, BLOCK_MENU_ID => Box::new(handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_manager, &self.level_table)?.into_iter().map(move |pkt| (id, pkt))), ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut self.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms)?, QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &self.quests)?, @@ -599,6 +611,12 @@ impl ServerState for ShipServerState { RecvShipPacket::SaveOptions(save_options) => { handler::settings::save_options(id, save_options, &mut self.clients, &mut self.entity_gateway).await }, + RecvShipPacket::RequestShipList(_) => { + handler::ship::ship_list(id, &self.ship_list) + }, + RecvShipPacket::RequestShipBlockList(_) => { + handler::ship::block_list(id, &self.name, 1) + } }) } @@ -654,7 +672,9 @@ impl InterserverActor for ShipServerState { ip: self.ip.clone(), port: self.port, block_count: 2, - })) ] + })), + (id, ShipMessage::RequestShipList) + ] } async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> {