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.

828 lines
38 KiB

5 years ago
5 years ago
5 years ago
4 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
4 years ago
4 years ago
2 years ago
5 years ago
5 years ago
4 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
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
5 years ago
4 years ago
2 years ago
5 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
3 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
2 years ago
5 years ago
4 years ago
2 years ago
5 years ago
4 years ago
3 years ago
5 years ago
5 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
2 years ago
2 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
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
5 years ago
5 years ago
3 years ago
4 years ago
3 years ago
5 years ago
3 years ago
4 years ago
3 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::{RedirectClient, Login, LoginResponse, Session, ShipList};
  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::login::character::SHIP_MENU_ID;
  17. use crate::entity::gateway::{EntityGateway, GatewayError};
  18. use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
  19. use crate::entity::character::{CharacterEntity, SectionID};
  20. use crate::entity::item;
  21. use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError};
  22. use crate::ship::items;
  23. use crate::ship::room;
  24. use crate::ship::quests;
  25. use crate::ship::map::{MapsError, MapAreaError, MapArea};
  26. use crate::ship::packet::handler;
  27. use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem};
  28. use crate::ship::trade::TradeState;
  29. pub const SHIP_PORT: u16 = 23423;
  30. pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
  31. pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
  32. pub type Rooms = [Option<room::RoomState>; MAX_ROOMS];
  33. pub type Clients = HashMap<ClientId, ClientState>;
  34. #[derive(Error, Debug)]
  35. #[error("shiperror {0:?}")]
  36. pub enum ShipError {
  37. ClientNotFound(ClientId),
  38. NoCharacterInSlot(ClientId, u32),
  39. InvalidSlot(ClientId, u32),
  40. #[error("")]
  41. TooManyClients,
  42. ClientLocationError(#[from] ClientLocationError),
  43. GetNeighborError(#[from] GetNeighborError),
  44. GetClientsError(#[from] GetClientsError),
  45. GetAreaError(#[from] GetAreaError),
  46. MapsError(#[from] MapsError),
  47. MapAreaError(#[from] MapAreaError),
  48. InvalidRoom(u32),
  49. MonsterAlreadyDroppedItem(ClientId, u16),
  50. SliceError(#[from] std::array::TryFromSliceError),
  51. #[error("")]
  52. ItemError, // TODO: refine this
  53. PickUpInvalidItemId(u32),
  54. DropInvalidItemId(u32),
  55. ItemManagerError(#[from] items::ItemManagerError),
  56. #[error("")]
  57. ItemDropLocationNotSet,
  58. BoxAlreadyDroppedItem(ClientId, u16),
  59. InvalidQuestCategory(u32),
  60. InvalidQuest(u32),
  61. InvalidQuestFilename(String),
  62. IoError(#[from] std::io::Error),
  63. NotEnoughMeseta(ClientId, u32),
  64. #[error("")]
  65. ShopError,
  66. GatewayError(#[from] GatewayError),
  67. UnknownMonster(crate::ship::monster::MonsterType),
  68. InvalidShip(usize),
  69. InvalidBlock(usize),
  70. InvalidItem(items::ClientItemId),
  71. #[error("tradeerror {0}")]
  72. TradeError(#[from] crate::ship::packet::handler::trade::TradeError),
  73. }
  74. #[derive(Debug)]
  75. pub enum RecvShipPacket {
  76. Login(Login),
  77. MenuSelect(MenuSelect),
  78. RoomPasswordReq(RoomPasswordReq),
  79. CharData(CharData),
  80. Message(Message),
  81. DirectMessage(DirectMessage),
  82. PlayerChat(PlayerChat),
  83. CreateRoom(CreateRoom),
  84. RoomNameRequest(RoomNameRequest),
  85. UpdateConfig(UpdateConfig),
  86. ViewInfoboardRequest(ViewInfoboardRequest),
  87. WriteInfoboard(WriteInfoboard),
  88. RoomListRequest(RoomListRequest),
  89. Like62ButCooler(Like62ButCooler),
  90. ClientCharacterData(ClientCharacterData),
  91. DoneBursting(DoneBursting),
  92. DoneBursting2(DoneBursting2),
  93. LobbySelect(LobbySelect),
  94. RequestQuestList(RequestQuestList),
  95. MenuDetail(MenuDetail),
  96. QuestDetailRequest(QuestDetailRequest),
  97. QuestMenuSelect(QuestMenuSelect),
  98. QuestFileRequest(QuestFileRequest),
  99. QuestChunkAck(QuestChunkAck),
  100. DoneLoadingQuest(DoneLoadingQuest),
  101. FullCharacterData(Box<FullCharacterData>),
  102. SaveOptions(SaveOptions),
  103. RequestShipList(RequestShipList),
  104. RequestShipBlockList(RequestShipBlockList),
  105. ItemsToTrade(ItemsToTrade),
  106. TradeConfirmed(TradeConfirmed),
  107. }
  108. impl RecvServerPacket for RecvShipPacket {
  109. fn from_bytes(data: &[u8]) -> Result<RecvShipPacket, PacketParseError> {
  110. match u16::from_le_bytes([data[2], data[3]]) {
  111. 0x93 => Ok(RecvShipPacket::Login(Login::from_bytes(data)?)),
  112. 0x09 => match data[8] as u32 {
  113. QUEST_SELECT_MENU_ID => Ok(RecvShipPacket::QuestDetailRequest(QuestDetailRequest::from_bytes(data)?)),
  114. _ => Ok(RecvShipPacket::MenuDetail(MenuDetail::from_bytes(data)?)),
  115. }
  116. 0x10 => match (data[0], data[8] as u32) {
  117. (16, QUEST_SELECT_MENU_ID) => Ok(RecvShipPacket::QuestMenuSelect(QuestMenuSelect::from_bytes(data)?)),
  118. (16, _) => Ok(RecvShipPacket::MenuSelect(MenuSelect::from_bytes(data)?)),
  119. (48, _) => Ok(RecvShipPacket::RoomPasswordReq(RoomPasswordReq::from_bytes(data)?)),
  120. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())),
  121. },
  122. 0x13 => Ok(RecvShipPacket::QuestChunkAck(QuestChunkAck::from_bytes(data)?)),
  123. 0x44 => Ok(RecvShipPacket::QuestFileRequest(QuestFileRequest::from_bytes(data)?)),
  124. 0x61 => Ok(RecvShipPacket::CharData(CharData::from_bytes(data)?)),
  125. 0x60 => Ok(RecvShipPacket::Message(Message::from_bytes(data)?)),
  126. 0x62 => Ok(RecvShipPacket::DirectMessage(DirectMessage::from_bytes(data)?)),
  127. 0x06 => Ok(RecvShipPacket::PlayerChat(PlayerChat::from_bytes(data)?)),
  128. 0xC1 => Ok(RecvShipPacket::CreateRoom(CreateRoom::from_bytes(data)?)),
  129. 0x8A => Ok(RecvShipPacket::RoomNameRequest(RoomNameRequest::from_bytes(data)?)),
  130. 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)),
  131. 0xD8 => Ok(RecvShipPacket::ViewInfoboardRequest(ViewInfoboardRequest::from_bytes(data)?)),
  132. 0xD9 => Ok(RecvShipPacket::WriteInfoboard(WriteInfoboard::from_bytes(data)?)),
  133. 0x08 => Ok(RecvShipPacket::RoomListRequest(RoomListRequest::from_bytes(data)?)),
  134. 0x6D => Ok(RecvShipPacket::Like62ButCooler(Like62ButCooler::from_bytes(data)?)),
  135. 0x98 => Ok(RecvShipPacket::ClientCharacterData(ClientCharacterData::from_bytes(data)?)),
  136. 0x6F => Ok(RecvShipPacket::DoneBursting(DoneBursting::from_bytes(data)?)),
  137. 0x16F => Ok(RecvShipPacket::DoneBursting2(DoneBursting2::from_bytes(data)?)),
  138. 0x84 => Ok(RecvShipPacket::LobbySelect(LobbySelect::from_bytes(data)?)),
  139. 0xA0 => Ok(RecvShipPacket::RequestShipList(RequestShipList::from_bytes(data)?)),
  140. 0xA1 => Ok(RecvShipPacket::RequestShipBlockList(RequestShipBlockList::from_bytes(data)?)),
  141. 0xA2 => Ok(RecvShipPacket::RequestQuestList(RequestQuestList::from_bytes(data)?)),
  142. 0xAC => Ok(RecvShipPacket::DoneLoadingQuest(DoneLoadingQuest::from_bytes(data)?)),
  143. 0xD0 => Ok(RecvShipPacket::ItemsToTrade(ItemsToTrade::from_bytes(data)?)),
  144. 0xD2 => Ok(RecvShipPacket::TradeConfirmed(TradeConfirmed::from_bytes(data)?)),
  145. 0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))),
  146. 0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)),
  147. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec()))
  148. }
  149. }
  150. }
  151. #[derive(Debug, Clone)]
  152. pub enum SendShipPacket {
  153. ShipWelcome(ShipWelcome),
  154. LoginResponse(LoginResponse),
  155. ShipList(ShipList),
  156. ShipBlockList(ShipBlockList),
  157. FullCharacter(Box<FullCharacter>),
  158. CharDataRequest(CharDataRequest),
  159. JoinLobby(JoinLobby),
  160. AddToLobby(AddToLobby),
  161. Message(Message),
  162. DirectMessage(DirectMessage),
  163. PlayerChat(PlayerChat),
  164. SmallDialog(SmallDialog),
  165. JoinRoom(JoinRoom),
  166. AddToRoom(AddToRoom),
  167. LeaveLobby(LeaveLobby),
  168. LeaveRoom(LeaveRoom),
  169. RoomNameResponse(RoomNameResponse),
  170. ViewInfoboardResponse(ViewInfoboardResponse),
  171. RoomListResponse(RoomListResponse),
  172. Like62ButCooler(Like62ButCooler),
  173. BurstDone72(BurstDone72),
  174. DoneBursting(DoneBursting),
  175. DoneBursting2(DoneBursting2),
  176. LobbyList(LobbyList),
  177. QuestCategoryList(QuestCategoryList),
  178. QuestOptionList(QuestOptionList),
  179. QuestDetail(QuestDetail),
  180. QuestHeader(QuestHeader),
  181. QuestChunk(QuestChunk),
  182. DoneLoadingQuest(DoneLoadingQuest),
  183. BankItemList(BankItemList),
  184. RedirectClient(RedirectClient),
  185. RareMonsterList(RareMonsterList),
  186. AcknowledgeTrade(AcknowledgeTrade),
  187. CancelTrade(CancelTrade),
  188. TradeSuccessful(TradeSuccessful),
  189. }
  190. impl SendServerPacket for SendShipPacket {
  191. fn as_bytes(&self) -> Vec<u8> {
  192. match self {
  193. SendShipPacket::ShipWelcome(pkt) => pkt.as_bytes(),
  194. SendShipPacket::LoginResponse(pkt) => pkt.as_bytes(),
  195. SendShipPacket::ShipList(pkt) => pkt.as_bytes(),
  196. SendShipPacket::ShipBlockList(pkt) => pkt.as_bytes(),
  197. SendShipPacket::FullCharacter(pkt) => pkt.as_bytes(),
  198. SendShipPacket::CharDataRequest(pkt) => pkt.as_bytes(),
  199. SendShipPacket::JoinLobby(pkt) => pkt.as_bytes(),
  200. SendShipPacket::AddToLobby(pkt) => pkt.as_bytes(),
  201. SendShipPacket::Message(pkt) => pkt.as_bytes(),
  202. SendShipPacket::DirectMessage(pkt) => pkt.as_bytes(),
  203. SendShipPacket::PlayerChat(pkt) => pkt.as_bytes(),
  204. SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
  205. SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
  206. SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
  207. SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(),
  208. SendShipPacket::LeaveRoom(pkt) => pkt.as_bytes(),
  209. SendShipPacket::RoomNameResponse(pkt) => pkt.as_bytes(),
  210. SendShipPacket::ViewInfoboardResponse(pkt) => pkt.as_bytes(),
  211. SendShipPacket::RoomListResponse(pkt) => pkt.as_bytes(),
  212. SendShipPacket::Like62ButCooler(pkt) => pkt.as_bytes(),
  213. SendShipPacket::BurstDone72(pkt) => pkt.as_bytes(),
  214. SendShipPacket::DoneBursting(pkt) => pkt.as_bytes(),
  215. SendShipPacket::DoneBursting2(pkt) => pkt.as_bytes(),
  216. SendShipPacket::LobbyList(pkt) => pkt.as_bytes(),
  217. SendShipPacket::QuestCategoryList(pkt) => pkt.as_bytes(),
  218. SendShipPacket::QuestOptionList(pkt) => pkt.as_bytes(),
  219. SendShipPacket::QuestDetail(pkt) => pkt.as_bytes(),
  220. SendShipPacket::QuestHeader(pkt) => pkt.as_bytes(),
  221. SendShipPacket::QuestChunk(pkt) => pkt.as_bytes(),
  222. SendShipPacket::DoneLoadingQuest(pkt) => pkt.as_bytes(),
  223. SendShipPacket::BankItemList(pkt) => pkt.as_bytes(),
  224. SendShipPacket::RedirectClient(pkt) => pkt.as_bytes(),
  225. SendShipPacket::RareMonsterList(pkt) => pkt.as_bytes(),
  226. SendShipPacket::AcknowledgeTrade(pkt) => pkt.as_bytes(),
  227. SendShipPacket::CancelTrade(pkt) => pkt.as_bytes(),
  228. SendShipPacket::TradeSuccessful(pkt) => pkt.as_bytes(),
  229. }
  230. }
  231. }
  232. #[derive(Debug, Clone, Copy)]
  233. pub struct ItemDropLocation {
  234. pub map_area: MapArea,
  235. pub x: f32,
  236. pub z: f32,
  237. pub item_id: items::ClientItemId,
  238. }
  239. pub struct LoadingQuest {
  240. pub header_bin: Option<QuestHeader>,
  241. pub header_dat: Option<QuestHeader>,
  242. //pub quest_chunk_bin: Option<Box<dyn Iterator<Item = >>>,
  243. }
  244. pub struct ClientState {
  245. pub user: UserAccountEntity,
  246. pub settings: UserSettingsEntity,
  247. pub character: CharacterEntity,
  248. session: Session,
  249. //guildcard: GuildCard,
  250. pub block: usize,
  251. pub item_drop_location: Option<ItemDropLocation>,
  252. pub done_loading_quest: bool,
  253. //pub loading_quest: Option<LoadingQuest>,
  254. pub area: Option<MapArea>,
  255. pub x: f32,
  256. pub y: f32,
  257. pub z: f32,
  258. pub weapon_shop: Vec<WeaponShopItem>,
  259. pub tool_shop: Vec<ToolShopItem>,
  260. pub armor_shop: Vec<ArmorShopItem>,
  261. pub tek: Option<(items::ClientItemId, item::weapon::TekSpecialModifier, item::weapon::TekPercentModifier, i32)>,
  262. }
  263. impl ClientState {
  264. pub fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, session: Session) -> ClientState {
  265. ClientState {
  266. user,
  267. settings,
  268. character,
  269. session,
  270. block: 0,
  271. item_drop_location: None,
  272. done_loading_quest: false,
  273. area: None,
  274. x: 0.0,
  275. y: 0.0,
  276. z: 0.0,
  277. weapon_shop: Vec::new(),
  278. tool_shop: Vec::new(),
  279. armor_shop: Vec::new(),
  280. tek: None,
  281. }
  282. }
  283. }
  284. pub struct ItemShops {
  285. pub weapon_shop: HashMap<(room::Difficulty, SectionID), WeaponShop<rand_chacha::ChaCha20Rng>>,
  286. pub tool_shop: ToolShop<rand_chacha::ChaCha20Rng>,
  287. pub armor_shop: ArmorShop<rand_chacha::ChaCha20Rng>,
  288. }
  289. impl Default for ItemShops {
  290. fn default() -> ItemShops {
  291. let difficulty = [room::Difficulty::Normal, room::Difficulty::Hard, room::Difficulty::VeryHard, room::Difficulty::Ultimate];
  292. let section_id = [SectionID::Viridia, SectionID::Greenill, SectionID::Skyly, SectionID::Bluefull, SectionID::Purplenum,
  293. SectionID::Pinkal, SectionID::Redria, SectionID::Oran, SectionID::Yellowboze, SectionID::Whitill];
  294. let mut weapon_shop = HashMap::new();
  295. for d in difficulty.iter() {
  296. for id in section_id.iter() {
  297. weapon_shop.insert((*d, *id), WeaponShop::new(*d, *id));
  298. }
  299. }
  300. ItemShops {
  301. weapon_shop,
  302. tool_shop: ToolShop::default(),
  303. armor_shop: ArmorShop::default(),
  304. }
  305. }
  306. }
  307. pub struct ShipServerStateBuilder<EG: EntityGateway> {
  308. entity_gateway: Option<EG>,
  309. name: Option<String>,
  310. ip: Option<Ipv4Addr>,
  311. port: Option<u16>,
  312. auth_token: Option<AuthToken>,
  313. num_blocks: usize,
  314. }
  315. impl<EG: EntityGateway> Default for ShipServerStateBuilder<EG> {
  316. fn default() -> ShipServerStateBuilder<EG> {
  317. ShipServerStateBuilder {
  318. entity_gateway: None,
  319. name: None,
  320. ip: None,
  321. port: None,
  322. auth_token: None,
  323. num_blocks: 2,
  324. }
  325. }
  326. }
  327. impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
  328. #[must_use]
  329. pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder<EG> {
  330. self.entity_gateway = Some(entity_gateway);
  331. self
  332. }
  333. #[must_use]
  334. pub fn name(mut self, name: String) -> ShipServerStateBuilder<EG> {
  335. self.name = Some(name);
  336. self
  337. }
  338. #[must_use]
  339. pub fn ip(mut self, ip: Ipv4Addr) -> ShipServerStateBuilder<EG> {
  340. self.ip = Some(ip);
  341. self
  342. }
  343. #[must_use]
  344. pub fn port(mut self, port: u16) -> ShipServerStateBuilder<EG> {
  345. self.port = Some(port);
  346. self
  347. }
  348. #[must_use]
  349. pub fn auth_token(mut self, auth_token: AuthToken) -> ShipServerStateBuilder<EG> {
  350. self.auth_token = Some(auth_token);
  351. self
  352. }
  353. #[must_use]
  354. pub fn blocks(mut self, num_blocks: usize) -> ShipServerStateBuilder<EG> {
  355. self.num_blocks = num_blocks;
  356. self
  357. }
  358. pub fn build(self) -> ShipServerState<EG> {
  359. let blocks = std::iter::repeat_with(Block::default).take(self.num_blocks).collect(); // Block doesn't have a Clone impl which limits the easy ways to init this
  360. ShipServerState {
  361. entity_gateway: self.entity_gateway.unwrap(),
  362. clients: HashMap::new(),
  363. level_table: CharacterLevelTable::default(),
  364. name: self.name.unwrap_or_else(|| "NAMENOTSET".into()),
  365. item_manager: items::ItemManager::default(),
  366. quests: quests::load_quests("data/quests.toml".into()).unwrap(),
  367. ip: self.ip.unwrap_or_else(|| Ipv4Addr::new(127,0,0,1)),
  368. port: self.port.unwrap_or(SHIP_PORT),
  369. shops: Box::new(ItemShops::default()),
  370. blocks: Blocks(blocks),
  371. auth_token: self.auth_token.unwrap_or_else(|| AuthToken("".into())),
  372. ship_list: Vec::new(),
  373. shipgate_sender: None,
  374. trades: Default::default(),
  375. }
  376. }
  377. }
  378. pub struct Block {
  379. client_location: Box<ClientLocation>,
  380. pub rooms: Box<Rooms>,
  381. }
  382. impl Default for Block {
  383. fn default() -> Block {
  384. const SNONE: Option<room::RoomState> = None;
  385. const NONE: Rooms = [SNONE; MAX_ROOMS];
  386. Block {
  387. client_location: Box::new(ClientLocation::default()),
  388. rooms: Box::new(NONE),
  389. }
  390. }
  391. }
  392. pub struct Blocks(pub Vec<Block>);
  393. impl Blocks {
  394. fn with_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> {
  395. let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
  396. self.0.get_mut(client.block).ok_or(ShipError::InvalidBlock(client.block))
  397. }
  398. }
  399. pub struct ShipServerState<EG: EntityGateway> {
  400. entity_gateway: EG,
  401. pub clients: Clients,
  402. level_table: CharacterLevelTable,
  403. name: String,
  404. item_manager: items::ItemManager,
  405. quests: quests::QuestList,
  406. shops: Box<ItemShops>,
  407. pub blocks: Blocks,
  408. ip: Ipv4Addr,
  409. port: u16,
  410. auth_token: AuthToken,
  411. ship_list: Vec<Ship>,
  412. shipgate_sender: Option<Box<dyn Fn(ShipMessage) + Send + Sync>>,
  413. trades: TradeState,
  414. }
  415. impl<EG: EntityGateway> ShipServerState<EG> {
  416. pub fn builder() -> ShipServerStateBuilder<EG> {
  417. ShipServerStateBuilder::default()
  418. }
  419. pub fn set_sender(&mut self, sender: Box<dyn Fn(ShipMessage) + Send + Sync>) {
  420. self.shipgate_sender = Some(sender);
  421. }
  422. async fn message(&mut self, id: ClientId, msg: &Message) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
  423. Ok(match &msg.msg {
  424. GameMessage::RequestExp(request_exp) => {
  425. let block = self.blocks.with_client(id, &self.clients)?;
  426. handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &self.level_table).await?
  427. },
  428. GameMessage::PlayerDropItem(player_drop_item) => {
  429. let block = self.blocks.with_client(id, &self.clients)?;
  430. handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
  431. },
  432. GameMessage::DropCoordinates(drop_coordinates) => {
  433. let block = self.blocks.with_client(id, &self.clients)?;
  434. handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms)?
  435. },
  436. GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
  437. let block = self.blocks.with_client(id, &self.clients)?;
  438. handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  439. },
  440. GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
  441. GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
  442. GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
  443. GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
  444. let block = self.blocks.with_client(id, &self.clients)?;
  445. handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms)?
  446. },
  447. GameMessage::ChargeAttack(charge_attack) => {
  448. handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway, &mut self.item_manager).await?
  449. },
  450. GameMessage::PlayerUseItem(player_use_item) => {
  451. let block = self.blocks.with_client(id, &self.clients)?;
  452. handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  453. },
  454. GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => {
  455. handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
  456. },
  457. GameMessage::PlayerFeedMag(player_feed_mag) => {
  458. let block = self.blocks.with_client(id, &self.clients)?;
  459. handler::message::player_feed_mag(id, player_feed_mag, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_manager).await?
  460. },
  461. GameMessage::PlayerEquipItem(player_equip_item) => {
  462. handler::message::player_equips_item(id, player_equip_item, &mut self.entity_gateway, &self.clients, &mut self.item_manager).await?
  463. },
  464. GameMessage::PlayerUnequipItem(player_unequip_item) => {
  465. handler::message::player_unequips_item(id, player_unequip_item, &mut self.entity_gateway, &self.clients, &mut self.item_manager).await?
  466. },
  467. GameMessage::SortItems(sort_items) => {
  468. handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_manager).await?
  469. },
  470. GameMessage::PlayerSoldItem(player_sold_item) => {
  471. handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
  472. },
  473. _ => {
  474. let cmsg = msg.clone();
  475. let block = self.blocks.with_client(id, &self.clients)?;
  476. Box::new(block.client_location.get_client_neighbors(id).unwrap().into_iter()
  477. .map(move |client| {
  478. (client.client, SendShipPacket::Message(cmsg.clone()))
  479. }))
  480. },
  481. })
  482. }
  483. async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
  484. let target = msg.flag;
  485. let block = self.blocks.with_client(id, &self.clients)?;
  486. Ok(match &msg.msg {
  487. GameMessage::GuildcardSend(guildcard_send) => {
  488. handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients)
  489. },
  490. GameMessage::RequestItem(request_item) => {
  491. handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
  492. },
  493. GameMessage::PickupItem(pickup_item) => {
  494. handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  495. },
  496. GameMessage::BoxDropRequest(box_drop_request) => {
  497. handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
  498. },
  499. GameMessage::BankRequest(_bank_request) => {
  500. handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await?
  501. },
  502. GameMessage::BankInteraction(bank_interaction) => {
  503. handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  504. },
  505. GameMessage::ShopRequest(shop_request) => {
  506. handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await?
  507. },
  508. GameMessage::BuyItem(buy_item) => {
  509. handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  510. },
  511. GameMessage::TekRequest(tek_request) => {
  512. handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
  513. },
  514. GameMessage::TekAccept(tek_accept) => {
  515. handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
  516. },
  517. GameMessage::TradeRequest(trade_request) => {
  518. handler::trade::trade_request(id, trade_request, target, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
  519. },
  520. _ => {
  521. let cmsg = msg.clone();
  522. Box::new(block.client_location.get_all_clients_by_client(id).unwrap().into_iter()
  523. .filter(move |client| client.local_client.id() == target as u8)
  524. .map(move |client| {
  525. (client.client, SendShipPacket::DirectMessage(cmsg.clone()))
  526. }))
  527. },
  528. })
  529. }
  530. }
  531. #[async_trait::async_trait]
  532. impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
  533. type SendPacket = SendShipPacket;
  534. type RecvPacket = RecvShipPacket;
  535. type PacketError = anyhow::Error;
  536. async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, anyhow::Error> {
  537. let mut rng = rand::thread_rng();
  538. let mut server_key = [0u8; 48];
  539. let mut client_key = [0u8; 48];
  540. rng.fill(&mut server_key[..]);
  541. rng.fill(&mut client_key[..]);
  542. Ok(vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))),
  543. OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
  544. Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
  545. ])
  546. }
  547. async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
  548. -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
  549. Ok(match pkt {
  550. RecvShipPacket::Login(login) => {
  551. Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.shipgate_sender, &self.name, self.blocks.0.len())
  552. .await?.into_iter().map(move |pkt| (id, pkt)))
  553. },
  554. RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
  555. match questdetailrequest.menu {
  556. QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &self.quests)?,
  557. _ => unreachable!(),
  558. }
  559. },
  560. RecvShipPacket::MenuSelect(menuselect) => {
  561. let block = self.blocks.with_client(id, &self.clients)?;
  562. match menuselect.menu {
  563. SHIP_MENU_ID => {
  564. let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten();
  565. let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list)?;
  566. Box::new(leave_lobby.chain(select_ship))
  567. }
  568. BLOCK_MENU_ID => {
  569. let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten();
  570. let select_block = handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_manager, &self.level_table)?.into_iter();
  571. Box::new(leave_lobby.chain(select_block))
  572. }
  573. ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)?,
  574. QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &self.quests)?,
  575. _ => unreachable!(),
  576. }
  577. },
  578. RecvShipPacket::QuestMenuSelect(questmenuselect) => {
  579. let block = self.blocks.with_client(id, &self.clients)?;
  580. handler::quest::player_chose_quest(id, questmenuselect, &self.quests, &mut self.clients, &block.client_location, &mut block.rooms)?
  581. },
  582. RecvShipPacket::MenuDetail(_menudetail) => {
  583. //unreachable!();
  584. Box::new(Vec::new().into_iter())
  585. },
  586. RecvShipPacket::RoomPasswordReq(room_password_req) => {
  587. let block = self.blocks.with_client(id, &self.clients)?;
  588. if room_password_req.password == block.rooms[room_password_req.item as usize].as_ref()
  589. .ok_or(ShipError::InvalidRoom(room_password_req.item))?
  590. .password {
  591. let menuselect = MenuSelect {
  592. menu: room_password_req.menu,
  593. item: room_password_req.item,
  594. };
  595. handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)?
  596. }
  597. else {
  598. Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter())
  599. }
  600. },
  601. RecvShipPacket::CharData(chardata) => {
  602. let block = self.blocks.with_client(id, &self.clients)?;
  603. Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter())
  604. },
  605. RecvShipPacket::Message(msg) => {
  606. self.message(id, msg).await?
  607. },
  608. RecvShipPacket::DirectMessage(msg) => {
  609. self.direct_message(id, msg).await?
  610. },
  611. RecvShipPacket::PlayerChat(msg) => {
  612. let block = self.blocks.with_client(id, &self.clients)?;
  613. Box::new(handler::communication::player_chat(id, msg, &block.client_location, &self.clients)?)
  614. },
  615. RecvShipPacket::CreateRoom(create_room) => {
  616. let block = self.blocks.with_client(id, &self.clients)?;
  617. handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)?
  618. },
  619. RecvShipPacket::RoomNameRequest(_req) => {
  620. let block = self.blocks.with_client(id, &self.clients)?;
  621. handler::room::room_name_request(id, &block.client_location, &block.rooms)
  622. },
  623. RecvShipPacket::UpdateConfig(pkt) => {
  624. handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await
  625. },
  626. RecvShipPacket::ViewInfoboardRequest(_pkt) => {
  627. let block = self.blocks.with_client(id, &self.clients)?;
  628. handler::communication::request_infoboard(id, &block.client_location, &self.clients)
  629. },
  630. RecvShipPacket::WriteInfoboard(pkt) => {
  631. handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await
  632. },
  633. RecvShipPacket::RoomListRequest(_req) => {
  634. let block = self.blocks.with_client(id, &self.clients)?;
  635. handler::room::request_room_list(id, &block.client_location, &block.rooms)
  636. },
  637. RecvShipPacket::Like62ButCooler(cool62) => {
  638. let block = self.blocks.with_client(id, &self.clients)?;
  639. handler::room::cool_62(id, cool62, &block.client_location)
  640. },
  641. RecvShipPacket::ClientCharacterData(_) => {
  642. // TOOD: validate this in some way?
  643. Box::new(None.into_iter())
  644. },
  645. RecvShipPacket::DoneBursting(_) => {
  646. let block = self.blocks.with_client(id, &self.clients)?;
  647. handler::room::done_bursting(id, &block.client_location, &mut block.rooms)
  648. },
  649. RecvShipPacket::DoneBursting2(_) => {
  650. let block = self.blocks.with_client(id, &self.clients)?;
  651. handler::room::done_bursting(id, &block.client_location, &mut block.rooms)
  652. },
  653. RecvShipPacket::LobbySelect(pkt) => {
  654. let block = self.blocks.with_client(id, &self.clients)?;
  655. Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms, &mut self.entity_gateway).await?.into_iter())
  656. },
  657. RecvShipPacket::RequestQuestList(_) => {
  658. handler::quest::send_quest_category_list(id, &self.quests)?
  659. },
  660. RecvShipPacket::QuestFileRequest(quest_file_request) => {
  661. handler::quest::quest_file_request(id, quest_file_request, &self.quests)?
  662. },
  663. RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
  664. handler::quest::quest_chunk_ack(id, quest_chunk_ack, &self.quests)?
  665. },
  666. RecvShipPacket::DoneLoadingQuest(_) => {
  667. let block = self.blocks.with_client(id, &self.clients)?;
  668. handler::quest::done_loading_quest(id, &mut self.clients, &block.client_location)?
  669. },
  670. RecvShipPacket::FullCharacterData(_full_character_data) => {
  671. Box::new(None.into_iter())
  672. },
  673. RecvShipPacket::SaveOptions(save_options) => {
  674. handler::settings::save_options(id, save_options, &mut self.clients, &mut self.entity_gateway).await
  675. },
  676. RecvShipPacket::RequestShipList(_) => {
  677. handler::ship::ship_list(id, &self.ship_list)
  678. },
  679. RecvShipPacket::RequestShipBlockList(_) => {
  680. handler::ship::block_list(id, &self.name, self.blocks.0.len())
  681. },
  682. RecvShipPacket::ItemsToTrade(items_to_trade) => {
  683. let block = self.blocks.with_client(id, &self.clients)?;
  684. handler::trade::items_to_trade(id, items_to_trade, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
  685. },
  686. RecvShipPacket::TradeConfirmed(_) => {
  687. let block = self.blocks.with_client(id, &self.clients)?;
  688. handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager, &mut self.trades).await?
  689. },
  690. })
  691. }
  692. async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
  693. let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
  694. let block = self.blocks.with_client(id, &self.clients)?;
  695. let area_client = block.client_location.get_local_client(id)?;
  696. let neighbors = block.client_location.get_client_neighbors(id)?;
  697. let pkt = match block.client_location.get_area(id)? {
  698. RoomLobby::Room(room) => {
  699. if neighbors.is_empty() {
  700. block.rooms[room.0] = None;
  701. }
  702. let leader = block.client_location.get_room_leader(room)?;
  703. SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id()))
  704. },
  705. RoomLobby::Lobby(lobby) => {
  706. let leader = block.client_location.get_lobby_leader(lobby)?;
  707. SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))
  708. }
  709. };
  710. if let Some(shipgate_sender) = self.shipgate_sender.as_ref() {
  711. shipgate_sender(ShipMessage::RemoveUser(client.user.id));
  712. }
  713. block.client_location.remove_client_from_area(id);
  714. self.item_manager.remove_character_from_room(&client.character);
  715. if let Some(mut client) = self.clients.remove(&id) {
  716. client.user.at_ship = false;
  717. self.entity_gateway.save_user(&client.user).await;
  718. }
  719. Ok(neighbors.into_iter().map(|n| {
  720. (n.client, pkt.clone())
  721. }).collect())
  722. }
  723. }
  724. #[async_trait::async_trait]
  725. impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> {
  726. type SendMessage = ShipMessage;
  727. type RecvMessage = LoginMessage;
  728. type Error = ();
  729. async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  730. vec![
  731. (id, ShipMessage::Authenticate(self.auth_token.clone())),
  732. (id, ShipMessage::NewShip(Ship {
  733. name: self.name.clone(),
  734. ip: self.ip,
  735. port: self.port,
  736. block_count: 2,
  737. })),
  738. (id, ShipMessage::RequestShipList)
  739. ]
  740. }
  741. async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
  742. match msg {
  743. LoginMessage::SendMail{..} => {
  744. Ok(Vec::new())
  745. },
  746. LoginMessage::ShipList{ships} => {
  747. self.ship_list = ships;
  748. Ok(Vec::new())
  749. },
  750. LoginMessage::RequestUsers => {
  751. Ok(self.clients.iter()
  752. .map(|(_, client)| {
  753. (id, ShipMessage::AddUser(client.user.id))
  754. })
  755. .collect())
  756. }
  757. }
  758. }
  759. async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  760. Vec::new()
  761. }
  762. }