You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

638 lines
29 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. #![allow(dead_code, unused_must_use)]
  2. use std::net::Ipv4Addr;
  3. use std::collections::HashMap;
  4. use rand::Rng;
  5. use thiserror::Error;
  6. use libpso::packet::ship::*;
  7. use libpso::packet::login::{Login, LoginResponse, Session};
  8. use libpso::packet::messages::*;
  9. use libpso::{PacketParseError, PSOPacket};
  10. use libpso::crypto::bb::PSOBBCipher;
  11. use libpso::packet::ship::{BLOCK_MENU_ID, ROOM_MENU_ID};
  12. use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
  13. use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
  14. use crate::common::leveltable::CharacterLevelTable;
  15. use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
  16. use crate::entity::gateway::{EntityGateway, GatewayError};
  17. use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
  18. use crate::entity::character::{CharacterEntity, SectionID};
  19. use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError};
  20. use crate::ship::items;
  21. use crate::ship::room;
  22. use crate::ship::quests;
  23. use crate::ship::map::{MapsError, MapAreaError, MapArea};
  24. use crate::ship::packet::handler;
  25. use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem};
  26. pub const SHIP_PORT: u16 = 23423;
  27. pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
  28. pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
  29. pub type Rooms = [Option<room::RoomState>; MAX_ROOMS];
  30. pub type Clients = HashMap<ClientId, ClientState>;
  31. #[derive(Error, Debug)]
  32. #[error("")]
  33. pub enum ShipError {
  34. ClientNotFound(ClientId),
  35. NoCharacterInSlot(ClientId, u32),
  36. InvalidSlot(ClientId, u32),
  37. TooManyClients,
  38. ClientLocationError(#[from] ClientLocationError),
  39. MapsError(#[from] MapsError),
  40. MapAreaError(#[from] MapAreaError),
  41. InvalidRoom(u32),
  42. MonsterAlreadyDroppedItem(ClientId, u16),
  43. SliceError(#[from] std::array::TryFromSliceError),
  44. ItemError, // TODO: refine this
  45. PickUpInvalidItemId(u32),
  46. DropInvalidItemId(u32),
  47. ItemManagerError(#[from] items::ItemManagerError),
  48. ItemDropLocationNotSet,
  49. BoxAlreadyDroppedItem(ClientId, u16),
  50. InvalidQuestCategory(u32),
  51. InvalidQuest(u32),
  52. InvalidQuestFilename(String),
  53. IoError(#[from] std::io::Error),
  54. NotEnoughMeseta(ClientId, u32),
  55. ShopError,
  56. GatewayError(#[from] GatewayError),
  57. }
  58. #[derive(Debug)]
  59. pub enum RecvShipPacket {
  60. Login(Login),
  61. MenuSelect(MenuSelect),
  62. RoomPasswordReq(RoomPasswordReq),
  63. CharData(CharData),
  64. Message(Message),
  65. DirectMessage(DirectMessage),
  66. PlayerChat(PlayerChat),
  67. CreateRoom(CreateRoom),
  68. RoomNameRequest(RoomNameRequest),
  69. UpdateConfig(UpdateConfig),
  70. ViewInfoboardRequest(ViewInfoboardRequest),
  71. WriteInfoboard(WriteInfoboard),
  72. RoomListRequest(RoomListRequest),
  73. Like62ButCooler(Like62ButCooler),
  74. ClientCharacterData(ClientCharacterData),
  75. DoneBursting(DoneBursting),
  76. DoneBursting2(DoneBursting2),
  77. LobbySelect(LobbySelect),
  78. RequestQuestList(RequestQuestList),
  79. MenuDetail(MenuDetail),
  80. QuestDetailRequest(QuestDetailRequest),
  81. QuestMenuSelect(QuestMenuSelect),
  82. QuestFileRequest(QuestFileRequest),
  83. QuestChunkAck(QuestChunkAck),
  84. DoneLoadingQuest(DoneLoadingQuest),
  85. FullCharacterData(Box<FullCharacterData>),
  86. SaveOptions(SaveOptions),
  87. }
  88. impl RecvServerPacket for RecvShipPacket {
  89. fn from_bytes(data: &[u8]) -> Result<RecvShipPacket, PacketParseError> {
  90. match u16::from_le_bytes([data[2], data[3]]) {
  91. 0x93 => Ok(RecvShipPacket::Login(Login::from_bytes(data)?)),
  92. 0x09 => match data[8] as u32 {
  93. QUEST_SELECT_MENU_ID => Ok(RecvShipPacket::QuestDetailRequest(QuestDetailRequest::from_bytes(data)?)),
  94. _ => Ok(RecvShipPacket::MenuDetail(MenuDetail::from_bytes(data)?)),
  95. }
  96. 0x10 => match (data[0], data[8] as u32) {
  97. (16, QUEST_SELECT_MENU_ID) => Ok(RecvShipPacket::QuestMenuSelect(QuestMenuSelect::from_bytes(data)?)),
  98. (16, _) => Ok(RecvShipPacket::MenuSelect(MenuSelect::from_bytes(data)?)),
  99. (48, _) => Ok(RecvShipPacket::RoomPasswordReq(RoomPasswordReq::from_bytes(data)?)),
  100. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())),
  101. },
  102. 0x13 => Ok(RecvShipPacket::QuestChunkAck(QuestChunkAck::from_bytes(data)?)),
  103. 0x44 => Ok(RecvShipPacket::QuestFileRequest(QuestFileRequest::from_bytes(data)?)),
  104. 0x61 => Ok(RecvShipPacket::CharData(CharData::from_bytes(data)?)),
  105. 0x60 => Ok(RecvShipPacket::Message(Message::from_bytes(data)?)),
  106. 0x62 => Ok(RecvShipPacket::DirectMessage(DirectMessage::from_bytes(data)?)),
  107. 0x06 => Ok(RecvShipPacket::PlayerChat(PlayerChat::from_bytes(data)?)),
  108. 0xC1 => Ok(RecvShipPacket::CreateRoom(CreateRoom::from_bytes(data)?)),
  109. 0x8A => Ok(RecvShipPacket::RoomNameRequest(RoomNameRequest::from_bytes(data)?)),
  110. 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)),
  111. 0xD8 => Ok(RecvShipPacket::ViewInfoboardRequest(ViewInfoboardRequest::from_bytes(data)?)),
  112. 0xD9 => Ok(RecvShipPacket::WriteInfoboard(WriteInfoboard::from_bytes(data)?)),
  113. 0x08 => Ok(RecvShipPacket::RoomListRequest(RoomListRequest::from_bytes(data)?)),
  114. 0x6D => Ok(RecvShipPacket::Like62ButCooler(Like62ButCooler::from_bytes(data)?)),
  115. 0x98 => Ok(RecvShipPacket::ClientCharacterData(ClientCharacterData::from_bytes(data)?)),
  116. 0x6F => Ok(RecvShipPacket::DoneBursting(DoneBursting::from_bytes(data)?)),
  117. 0x16F => Ok(RecvShipPacket::DoneBursting2(DoneBursting2::from_bytes(data)?)),
  118. 0x84 => Ok(RecvShipPacket::LobbySelect(LobbySelect::from_bytes(data)?)),
  119. 0xA2 => Ok(RecvShipPacket::RequestQuestList(RequestQuestList::from_bytes(data)?)),
  120. 0xAC => Ok(RecvShipPacket::DoneLoadingQuest(DoneLoadingQuest::from_bytes(data)?)),
  121. 0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))),
  122. 0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)),
  123. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec()))
  124. }
  125. }
  126. }
  127. #[derive(Debug, Clone)]
  128. pub enum SendShipPacket {
  129. ShipWelcome(ShipWelcome),
  130. LoginResponse(LoginResponse),
  131. ShipBlockList(ShipBlockList),
  132. FullCharacter(FullCharacter),
  133. CharDataRequest(CharDataRequest),
  134. JoinLobby(JoinLobby),
  135. AddToLobby(AddToLobby),
  136. Message(Message),
  137. DirectMessage(DirectMessage),
  138. PlayerChat(PlayerChat),
  139. SmallDialog(SmallDialog),
  140. JoinRoom(JoinRoom),
  141. AddToRoom(AddToRoom),
  142. LeaveLobby(LeaveLobby),
  143. LeaveRoom(LeaveRoom),
  144. RoomNameResponse(RoomNameResponse),
  145. ViewInfoboardResponse(ViewInfoboardResponse),
  146. RoomListResponse(RoomListResponse),
  147. Like62ButCooler(Like62ButCooler),
  148. BurstDone72(BurstDone72),
  149. DoneBursting(DoneBursting),
  150. DoneBursting2(DoneBursting2),
  151. LobbyList(LobbyList),
  152. QuestCategoryList(QuestCategoryList),
  153. QuestOptionList(QuestOptionList),
  154. QuestDetail(QuestDetail),
  155. QuestHeader(QuestHeader),
  156. QuestChunk(QuestChunk),
  157. DoneLoadingQuest(DoneLoadingQuest),
  158. BankItemList(BankItemList),
  159. }
  160. impl SendServerPacket for SendShipPacket {
  161. fn as_bytes(&self) -> Vec<u8> {
  162. match self {
  163. SendShipPacket::ShipWelcome(pkt) => pkt.as_bytes(),
  164. SendShipPacket::LoginResponse(pkt) => pkt.as_bytes(),
  165. SendShipPacket::ShipBlockList(pkt) => pkt.as_bytes(),
  166. SendShipPacket::FullCharacter(pkt) => pkt.as_bytes(),
  167. SendShipPacket::CharDataRequest(pkt) => pkt.as_bytes(),
  168. SendShipPacket::JoinLobby(pkt) => pkt.as_bytes(),
  169. SendShipPacket::AddToLobby(pkt) => pkt.as_bytes(),
  170. SendShipPacket::Message(pkt) => pkt.as_bytes(),
  171. SendShipPacket::DirectMessage(pkt) => pkt.as_bytes(),
  172. SendShipPacket::PlayerChat(pkt) => pkt.as_bytes(),
  173. SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
  174. SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
  175. SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
  176. SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(),
  177. SendShipPacket::LeaveRoom(pkt) => pkt.as_bytes(),
  178. SendShipPacket::RoomNameResponse(pkt) => pkt.as_bytes(),
  179. SendShipPacket::ViewInfoboardResponse(pkt) => pkt.as_bytes(),
  180. SendShipPacket::RoomListResponse(pkt) => pkt.as_bytes(),
  181. SendShipPacket::Like62ButCooler(pkt) => pkt.as_bytes(),
  182. SendShipPacket::BurstDone72(pkt) => pkt.as_bytes(),
  183. SendShipPacket::DoneBursting(pkt) => pkt.as_bytes(),
  184. SendShipPacket::DoneBursting2(pkt) => pkt.as_bytes(),
  185. SendShipPacket::LobbyList(pkt) => pkt.as_bytes(),
  186. SendShipPacket::QuestCategoryList(pkt) => pkt.as_bytes(),
  187. SendShipPacket::QuestOptionList(pkt) => pkt.as_bytes(),
  188. SendShipPacket::QuestDetail(pkt) => pkt.as_bytes(),
  189. SendShipPacket::QuestHeader(pkt) => pkt.as_bytes(),
  190. SendShipPacket::QuestChunk(pkt) => pkt.as_bytes(),
  191. SendShipPacket::DoneLoadingQuest(pkt) => pkt.as_bytes(),
  192. SendShipPacket::BankItemList(pkt) => pkt.as_bytes(),
  193. }
  194. }
  195. }
  196. #[derive(Debug, Clone, Copy)]
  197. pub struct ItemDropLocation {
  198. pub map_area: MapArea,
  199. pub x: f32,
  200. pub z: f32,
  201. pub item_id: items::ClientItemId,
  202. }
  203. pub struct LoadingQuest {
  204. pub header_bin: Option<QuestHeader>,
  205. pub header_dat: Option<QuestHeader>,
  206. //pub quest_chunk_bin: Option<Box<dyn Iterator<Item = >>>,
  207. }
  208. pub struct ClientState {
  209. pub user: UserAccountEntity,
  210. pub settings: UserSettingsEntity,
  211. pub character: CharacterEntity,
  212. session: Session,
  213. //guildcard: GuildCard,
  214. pub block: u32,
  215. pub item_drop_location: Option<ItemDropLocation>,
  216. pub done_loading_quest: bool,
  217. //pub loading_quest: Option<LoadingQuest>,
  218. pub area: Option<MapArea>,
  219. pub x: f32,
  220. pub y: f32,
  221. pub z: f32,
  222. pub weapon_shop: Vec<WeaponShopItem>,
  223. pub tool_shop: Vec<ToolShopItem>,
  224. pub armor_shop: Vec<ArmorShopItem>,
  225. }
  226. impl ClientState {
  227. pub fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, session: Session) -> ClientState {
  228. ClientState {
  229. user: user,
  230. settings: settings,
  231. character: character,
  232. session: session,
  233. block: 1,
  234. item_drop_location: None,
  235. done_loading_quest: false,
  236. area: None,
  237. x: 0.0,
  238. y: 0.0,
  239. z: 0.0,
  240. weapon_shop: Vec::new(),
  241. tool_shop: Vec::new(),
  242. armor_shop: Vec::new(),
  243. }
  244. }
  245. }
  246. pub struct ItemShops {
  247. pub weapon_shop: HashMap<(room::Difficulty, SectionID), WeaponShop<rand_chacha::ChaCha20Rng>>,
  248. pub tool_shop: ToolShop<rand_chacha::ChaCha20Rng>,
  249. pub armor_shop: ArmorShop<rand_chacha::ChaCha20Rng>,
  250. }
  251. impl ItemShops {
  252. pub fn new() -> ItemShops {
  253. let difficulty = [room::Difficulty::Normal, room::Difficulty::Hard, room::Difficulty::VeryHard, room::Difficulty::Ultimate];
  254. let section_id = [SectionID::Viridia, SectionID::Greenill, SectionID::Skyly, SectionID::Bluefull, SectionID::Purplenum,
  255. SectionID::Pinkal, SectionID::Redria, SectionID::Oran, SectionID::Yellowboze, SectionID::Whitill];
  256. let mut weapon_shop = HashMap::new();
  257. for d in difficulty.iter() {
  258. for id in section_id.iter() {
  259. weapon_shop.insert((*d, *id), WeaponShop::new(*d, *id));
  260. }
  261. }
  262. ItemShops {
  263. weapon_shop: weapon_shop,
  264. tool_shop: ToolShop::new(),
  265. armor_shop: ArmorShop::new(),
  266. }
  267. }
  268. }
  269. pub struct ShipServerStateBuilder<EG: EntityGateway> {
  270. entity_gateway: Option<EG>,
  271. name: Option<String>,
  272. ip: Option<Ipv4Addr>,
  273. port: Option<u16>,
  274. }
  275. impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
  276. pub fn new() -> ShipServerStateBuilder<EG> {
  277. ShipServerStateBuilder {
  278. entity_gateway: None,
  279. name: None,
  280. ip: None,
  281. port: None,
  282. }
  283. }
  284. pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder<EG> {
  285. self.entity_gateway = Some(entity_gateway);
  286. self
  287. }
  288. pub fn name(mut self, name: String) -> ShipServerStateBuilder<EG> {
  289. self.name = Some(name);
  290. self
  291. }
  292. pub fn ip(mut self, ip: Ipv4Addr) -> ShipServerStateBuilder<EG> {
  293. self.ip = Some(ip);
  294. self
  295. }
  296. pub fn port(mut self, port: u16) -> ShipServerStateBuilder<EG> {
  297. self.port = Some(port);
  298. self
  299. }
  300. pub fn build(self) -> ShipServerState<EG> {
  301. ShipServerState {
  302. entity_gateway: self.entity_gateway.unwrap(),
  303. clients: HashMap::new(),
  304. client_location: ClientLocation::new(),
  305. level_table: CharacterLevelTable::new(),
  306. name: self.name.unwrap_or("NAMENOTSET".into()),
  307. rooms: [None; MAX_ROOMS],
  308. item_manager: items::ItemManager::new(),
  309. quests: quests::load_quests("data/quests.toml".into()).unwrap(),
  310. ip: self.ip.unwrap_or(Ipv4Addr::new(127,0,0,1)),
  311. port: self.port.unwrap_or(SHIP_PORT),
  312. shops: Box::new(ItemShops::new()),
  313. }
  314. }
  315. }
  316. pub struct ShipServerState<EG: EntityGateway> {
  317. entity_gateway: EG,
  318. pub clients: Clients,
  319. client_location: ClientLocation,
  320. level_table: CharacterLevelTable,
  321. name: String,
  322. pub rooms: Rooms,
  323. item_manager: items::ItemManager,
  324. quests: quests::QuestList,
  325. ip: Ipv4Addr,
  326. port: u16,
  327. shops: Box<ItemShops>,
  328. }
  329. impl<EG: EntityGateway> ShipServerState<EG> {
  330. pub fn builder() -> ShipServerStateBuilder<EG> {
  331. ShipServerStateBuilder::new()
  332. }
  333. async fn message(&mut self, id: ClientId, msg: &Message) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
  334. match &msg.msg {
  335. GameMessage::RequestExp(request_exp) => {
  336. handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.rooms, &self.level_table).await
  337. },
  338. GameMessage::PlayerDropItem(player_drop_item) => {
  339. handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
  340. },
  341. GameMessage::DropCoordinates(drop_coordinates) => {
  342. handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)
  343. },
  344. GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
  345. handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
  346. },
  347. GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
  348. GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
  349. GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
  350. GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
  351. handler::message::update_player_position(id, &msg, &mut self.clients, &mut self.client_location, &self.rooms)
  352. },
  353. GameMessage::ChargeAttack(charge_attack) => {
  354. handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway).await
  355. },
  356. GameMessage::PlayerUseItem(player_use_item) => {
  357. handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
  358. },
  359. GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => {
  360. handler::message::player_used_medical_center(id, &player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await
  361. },
  362. GameMessage::PlayerFeedMag(player_feed_mag) => {
  363. handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
  364. },
  365. GameMessage::PlayerEquipItem(player_equip_item) => {
  366. handler::message::player_equips_item(id, &player_equip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await
  367. },
  368. GameMessage::PlayerUnequipItem(player_unequip_item) => {
  369. handler::message::player_unequips_item(id, &player_unequip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await
  370. },
  371. _ => {
  372. let cmsg = msg.clone();
  373. Ok(Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter()
  374. .map(move |client| {
  375. (client.client, SendShipPacket::Message(cmsg.clone()))
  376. })))
  377. },
  378. }
  379. }
  380. async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
  381. let target = msg.flag;
  382. match &msg.msg {
  383. GameMessage::GuildcardSend(guildcard_send) => {
  384. Ok(handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients))
  385. },
  386. GameMessage::RequestItem(request_item) => {
  387. handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
  388. },
  389. GameMessage::PickupItem(pickup_item) => {
  390. handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
  391. },
  392. GameMessage::BoxDropRequest(box_drop_request) => {
  393. handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
  394. },
  395. GameMessage::BankRequest(_bank_request) => {
  396. handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await
  397. },
  398. GameMessage::BankInteraction(bank_interaction) => {
  399. handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await
  400. },
  401. GameMessage::ShopRequest(shop_request) => {
  402. handler::direct_message::shop_request(id, shop_request, &self.client_location, &mut self.clients, &self.rooms, &self.level_table, &mut self.shops).await
  403. },
  404. GameMessage::BuyItem(buy_item) => {
  405. handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await
  406. },
  407. _ => {
  408. let cmsg = msg.clone();
  409. Ok(Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter()
  410. .filter(move |client| client.local_client.id() == target as u8)
  411. .map(move |client| {
  412. (client.client, SendShipPacket::DirectMessage(cmsg.clone()))
  413. })))
  414. },
  415. }
  416. }
  417. }
  418. #[async_trait::async_trait]
  419. impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
  420. type SendPacket = SendShipPacket;
  421. type RecvPacket = RecvShipPacket;
  422. type PacketError = ShipError;
  423. async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, ShipError> {
  424. let mut rng = rand::thread_rng();
  425. let mut server_key = [0u8; 48];
  426. let mut client_key = [0u8; 48];
  427. rng.fill(&mut server_key[..]);
  428. rng.fill(&mut client_key[..]);
  429. Ok(vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))),
  430. OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
  431. Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
  432. ])
  433. }
  434. async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
  435. -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
  436. Ok(match pkt {
  437. RecvShipPacket::Login(login) => {
  438. Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name).await?.into_iter().map(move |pkt| (id, pkt)))
  439. },
  440. RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
  441. match questdetailrequest.menu {
  442. QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &self.quests)?,
  443. _ => unreachable!(),
  444. }
  445. },
  446. RecvShipPacket::MenuSelect(menuselect) => {
  447. match menuselect.menu {
  448. 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))),
  449. 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)?,
  450. QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &self.quests)?,
  451. _ => unreachable!(),
  452. }
  453. },
  454. RecvShipPacket::QuestMenuSelect(questmenuselect) => {
  455. handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &self.client_location, &mut self.rooms)?
  456. },
  457. RecvShipPacket::MenuDetail(_menudetail) => {
  458. //unreachable!();
  459. Box::new(Vec::new().into_iter())
  460. },
  461. RecvShipPacket::RoomPasswordReq(room_password_req) => {
  462. if room_password_req.password == self.rooms[room_password_req.item as usize].as_ref()
  463. .ok_or(ShipError::InvalidRoom(room_password_req.item))?
  464. .password {
  465. let menuselect = MenuSelect {
  466. menu: room_password_req.menu,
  467. item: room_password_req.item,
  468. };
  469. handler::room::join_room(id, &menuselect, &mut self.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms)?
  470. }
  471. else {
  472. Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter())
  473. }
  474. },
  475. RecvShipPacket::CharData(chardata) => {
  476. Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter())
  477. },
  478. RecvShipPacket::Message(msg) => {
  479. self.message(id, msg).await?
  480. },
  481. RecvShipPacket::DirectMessage(msg) => {
  482. self.direct_message(id, msg).await?
  483. },
  484. RecvShipPacket::PlayerChat(msg) => {
  485. Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter())
  486. },
  487. RecvShipPacket::CreateRoom(create_room) => {
  488. handler::room::create_room(id, create_room, &mut self.client_location, &mut self.clients, &mut self.item_manager, &mut self.rooms)?
  489. },
  490. RecvShipPacket::RoomNameRequest(_req) => {
  491. handler::room::room_name_request(id, &self.client_location, &self.rooms)
  492. },
  493. RecvShipPacket::UpdateConfig(pkt) => {
  494. handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await
  495. },
  496. RecvShipPacket::ViewInfoboardRequest(_pkt) => {
  497. handler::communication::request_infoboard(id, &self.client_location, &self.clients)
  498. },
  499. RecvShipPacket::WriteInfoboard(pkt) => {
  500. handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await
  501. },
  502. RecvShipPacket::RoomListRequest(_req) => {
  503. handler::room::request_room_list(id, &self.client_location, &self.rooms)
  504. },
  505. RecvShipPacket::Like62ButCooler(cool62) => {
  506. handler::room::cool_62(id, cool62, &self.client_location)
  507. },
  508. RecvShipPacket::ClientCharacterData(_) => {
  509. // TOOD: validate this in some way?
  510. Box::new(None.into_iter())
  511. },
  512. RecvShipPacket::DoneBursting(_) => {
  513. handler::room::done_bursting(id, &self.client_location, &mut self.rooms)
  514. },
  515. RecvShipPacket::DoneBursting2(_) => {
  516. handler::room::done_bursting(id, &self.client_location, &mut self.rooms)
  517. },
  518. RecvShipPacket::LobbySelect(pkt) => {
  519. Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway).await?.into_iter())
  520. },
  521. RecvShipPacket::RequestQuestList(_) => {
  522. handler::quest::send_quest_category_list(id, &self.quests)?
  523. },
  524. RecvShipPacket::QuestFileRequest(quest_file_request) => {
  525. handler::quest::quest_file_request(id, quest_file_request, &self.quests)?
  526. },
  527. RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
  528. handler::quest::quest_chunk_ack(id, quest_chunk_ack, &self.quests)?
  529. },
  530. RecvShipPacket::DoneLoadingQuest(_) => {
  531. handler::quest::done_loading_quest(id, &mut self.clients, &self.client_location)?
  532. },
  533. RecvShipPacket::FullCharacterData(_full_character_data) => {
  534. Box::new(None.into_iter())
  535. },
  536. RecvShipPacket::SaveOptions(save_options) => {
  537. handler::settings::save_options(id, save_options, &mut self.clients, &mut self.entity_gateway).await
  538. },
  539. })
  540. }
  541. async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
  542. // TODO: don't unwrap!
  543. let client = self.clients.get(&id).unwrap();
  544. let area_client = self.client_location.get_local_client(id).unwrap();
  545. let neighbors = self.client_location.get_client_neighbors(id).unwrap();
  546. let pkt = match self.client_location.get_area(id).unwrap() {
  547. RoomLobby::Room(room) => {
  548. if neighbors.len() == 0 {
  549. self.rooms[room.0] = None;
  550. }
  551. let leader = self.client_location.get_room_leader(room).unwrap();
  552. SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id()))
  553. },
  554. RoomLobby::Lobby(lobby) => {
  555. let leader = self.client_location.get_lobby_leader(lobby).unwrap();
  556. SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))
  557. }
  558. };
  559. self.client_location.remove_client_from_area(id);
  560. self.item_manager.remove_character_from_room(&client.character);
  561. if let Some(mut client) = self.clients.remove(&id) {
  562. client.user.at_ship = false;
  563. self.entity_gateway.save_user(&client.user).await;
  564. }
  565. Ok(neighbors.into_iter().map(|n| {
  566. (n.client, pkt.clone())
  567. }).collect())
  568. }
  569. }
  570. #[async_trait::async_trait]
  571. impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> {
  572. type SendMessage = ShipMessage;
  573. type RecvMessage = LoginMessage;
  574. type Error = ();
  575. async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  576. vec![ /* ShipMessage::Authenticate(AuthToken("hi".into())), */ (id, ShipMessage::NewShip(Ship {
  577. name: self.name.clone(),
  578. ip: self.ip.clone(),
  579. port: self.port,
  580. block_count: 2,
  581. })) ]
  582. }
  583. async fn action(&mut self, _id: ServerId, _msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
  584. Ok(Vec::new())
  585. }
  586. async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  587. Vec::new()
  588. }
  589. }