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.

948 lines
44 KiB

5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
1 year 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
2 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
2 years ago
2 years ago
1 year ago
5 years ago
1 year 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
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
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
1 year ago
3 years ago
1 year ago
1 year ago
3 years ago
3 years ago
4 years ago
3 years ago
2 years ago
1 year ago
1 year ago
2 years ago
5 years ago
4 years ago
3 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
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
4 years ago
4 years ago
4 years ago
1 year ago
1 year ago
1 year ago
4 years ago
4 years ago
4 years ago
1 year ago
1 year 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
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
1 year ago
1 year ago
1 year ago
3 years ago
4 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 async_std::channel;
  5. use async_std::sync::{Arc, Mutex, RwLock};
  6. use rand::Rng;
  7. use thiserror::Error;
  8. use libpso::packet::ship::*;
  9. use libpso::packet::login::{RedirectClient, Login, LoginResponse, ShipList};
  10. use libpso::packet::messages::*;
  11. use libpso::{PacketParseError, PSOPacket};
  12. use libpso::crypto::bb::PSOBBCipher;
  13. use libpso::packet::ship::{BLOCK_MENU_ID, ROOM_MENU_ID};
  14. use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY};
  15. use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId};
  16. use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
  17. use crate::login::character::SHIP_MENU_ID;
  18. use crate::entity::gateway::{EntityGateway, GatewayError};
  19. use crate::entity::character::SectionID;
  20. use crate::entity::room::RoomNote;
  21. use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
  22. use crate::ship::drops::DropTable;
  23. use crate::ship::items;
  24. use crate::ship::room;
  25. use crate::ship::map::{Maps, MapsError, MapAreaError, generate_free_roam_maps};
  26. use crate::ship::packet::handler;
  27. use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop};
  28. use crate::ship::trade::TradeState;
  29. use crate::ship::chatcommand;
  30. // TODO: remove once stuff settles down
  31. pub use crate::ship::client::*;
  32. pub const SHIP_PORT: u16 = 23423;
  33. pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
  34. pub const QUEST_SELECT_MENU_ID: u32 = 0xA3;
  35. #[derive(Clone, Copy)]
  36. pub enum ShipEvent {
  37. None,
  38. Christmas,
  39. Valentines,
  40. Easter,
  41. Halloween,
  42. Sonic,
  43. NewYear,
  44. Summer,
  45. White,
  46. Wedding,
  47. Fall,
  48. Spring,
  49. Summer2,
  50. Spring2,
  51. }
  52. impl From<ShipEvent> for u32 {
  53. fn from(other: ShipEvent) -> u32 {
  54. u16::from(other) as u32
  55. }
  56. }
  57. impl From<ShipEvent> for u16 {
  58. fn from(other: ShipEvent) -> u16 {
  59. u8::from(other) as u16
  60. }
  61. }
  62. impl From<ShipEvent> for u8 {
  63. fn from(other: ShipEvent) -> u8 {
  64. match other {
  65. ShipEvent::None => 0,
  66. ShipEvent::Christmas => 1,
  67. ShipEvent::Valentines => 3,
  68. ShipEvent::Easter => 4,
  69. ShipEvent::Halloween => 5,
  70. ShipEvent::Sonic => 6,
  71. ShipEvent::NewYear => 7,
  72. ShipEvent::Summer => 8,
  73. ShipEvent::White => 9,
  74. ShipEvent::Wedding => 10,
  75. ShipEvent::Fall => 11,
  76. ShipEvent::Spring => 12,
  77. ShipEvent::Summer2 => 13,
  78. ShipEvent::Spring2 => 14,
  79. }
  80. }
  81. }
  82. #[derive(Error, Debug)]
  83. pub enum ShipError {
  84. #[error("client not found {0}")]
  85. ClientNotFound(ClientId),
  86. #[error("no character in slot {0} {1}")]
  87. NoCharacterInSlot(ClientId, u32),
  88. #[error("invalid slot {0} {1}")]
  89. InvalidSlot(ClientId, u32),
  90. #[error("too many clients")]
  91. TooManyClients,
  92. #[error("client location {0}")]
  93. ClientLocationError(ClientLocationError),
  94. #[error("maps error {0}")]
  95. MapsError(#[from] MapsError),
  96. #[error("map area error {0}")]
  97. MapAreaError(#[from] MapAreaError),
  98. #[error("invalid room {0}")]
  99. InvalidRoom(u32),
  100. #[error("monster already droppped item {0} {1}")]
  101. MonsterAlreadyDroppedItem(ClientId, u16),
  102. #[error("slice error {0}")]
  103. SliceError(#[from] std::array::TryFromSliceError),
  104. #[error("item error")]
  105. ItemError, // TODO: refine this
  106. #[error("pick up invalid item id {0}")]
  107. PickUpInvalidItemId(u32),
  108. #[error("drop invalid item id {0}")]
  109. DropInvalidItemId(u32),
  110. #[error("item state error {0}")]
  111. ItemStateError(#[from] items::state::ItemStateError),
  112. #[error("item drop location not set")]
  113. ItemDropLocationNotSet,
  114. #[error("box already dropped item {0} {1}")]
  115. BoxAlreadyDroppedItem(ClientId, u16),
  116. #[error("invalid quest category {0}")]
  117. InvalidQuestCategory(u16),
  118. #[error("invalid quest {0}")]
  119. InvalidQuest(u16),
  120. #[error("invalid quest filename {0}")]
  121. InvalidQuestFilename(String),
  122. #[error("io error {0}")]
  123. IoError(#[from] std::io::Error),
  124. #[error("not enough meseta {0} {1}")]
  125. NotEnoughMeseta(ClientId, u32),
  126. #[error("shop error")]
  127. ShopError,
  128. #[error("gateway error {0}")]
  129. GatewayError(#[from] GatewayError),
  130. #[error("unknown monster {0}")]
  131. UnknownMonster(crate::ship::monster::MonsterType),
  132. #[error("invalid ship {0}")]
  133. InvalidShip(usize),
  134. #[error("invalid block {0}")]
  135. InvalidBlock(usize),
  136. #[error("invalid item {0}")]
  137. InvalidItem(items::ClientItemId),
  138. #[error("trade error {0}")]
  139. TradeError(#[from] crate::ship::packet::handler::trade::TradeError),
  140. #[error("trade state error {0}")]
  141. TradeStateError(#[from] crate::ship::trade::TradeStateError),
  142. #[error("message error {0}")]
  143. MessageError(#[from] crate::ship::packet::handler::direct_message::MessageError),
  144. #[error("room creation error {0}")]
  145. RoomCreationError(#[from] room::RoomCreationError),
  146. #[error("channel send error {0}")]
  147. SendError(#[from] async_std::channel::SendError<ShipMessage>),
  148. }
  149. /*
  150. impl<I: Into<ClientLocationError>> From<I> for ShipError {
  151. fn from(other: I) -> ShipError {
  152. ShipError::ClientLocationError(other.into())
  153. }
  154. }
  155. */
  156. #[derive(Debug)]
  157. pub enum RecvShipPacket {
  158. Login(Login),
  159. MenuSelect(MenuSelect),
  160. RoomPasswordReq(RoomPasswordReq),
  161. CharData(CharData),
  162. Message(Message),
  163. DirectMessage(DirectMessage),
  164. PlayerChat(PlayerChat),
  165. CreateRoom(CreateRoom),
  166. RoomNameRequest(RoomNameRequest),
  167. ViewInfoboardRequest(ViewInfoboardRequest),
  168. WriteInfoboard(WriteInfoboard),
  169. RoomListRequest(RoomListRequest),
  170. Like62ButCooler(Like62ButCooler),
  171. ClientCharacterData(ClientCharacterData),
  172. DoneBursting(DoneBursting),
  173. DoneBursting2(DoneBursting2),
  174. LobbySelect(LobbySelect),
  175. RequestQuestList(RequestQuestList),
  176. MenuDetail(MenuDetail),
  177. QuestDetailRequest(QuestDetailRequest),
  178. QuestMenuSelect(QuestMenuSelect),
  179. QuestFileRequest(QuestFileRequest),
  180. QuestChunkAck(QuestChunkAck),
  181. DoneLoadingQuest(DoneLoadingQuest),
  182. FullCharacterData(Box<FullCharacterData>),
  183. SaveOptions(SaveOptions),
  184. RequestShipList(RequestShipList),
  185. RequestShipBlockList(RequestShipBlockList),
  186. ItemsToTrade(ItemsToTrade),
  187. TradeConfirmed(TradeConfirmed),
  188. KeyboardConfig(KeyboardConfig),
  189. GamepadConfig(GamepadConfig),
  190. UpdateConfig(UpdateConfig),
  191. UpdateTechMenu(UpdateTechMenu),
  192. }
  193. impl RecvServerPacket for RecvShipPacket {
  194. fn from_bytes(data: &[u8]) -> Result<RecvShipPacket, PacketParseError> {
  195. match u16::from_le_bytes([data[2], data[3]]) {
  196. 0x93 => Ok(RecvShipPacket::Login(Login::from_bytes(data)?)),
  197. 0x09 => match data[8] as u32 {
  198. QUEST_SELECT_MENU_ID => Ok(RecvShipPacket::QuestDetailRequest(QuestDetailRequest::from_bytes(data)?)),
  199. _ => Ok(RecvShipPacket::MenuDetail(MenuDetail::from_bytes(data)?)),
  200. }
  201. 0x10 => match (data[0], data[8] as u32) {
  202. (16, QUEST_SELECT_MENU_ID) => Ok(RecvShipPacket::QuestMenuSelect(QuestMenuSelect::from_bytes(data)?)),
  203. (16, _) => Ok(RecvShipPacket::MenuSelect(MenuSelect::from_bytes(data)?)),
  204. (48, _) => Ok(RecvShipPacket::RoomPasswordReq(RoomPasswordReq::from_bytes(data)?)),
  205. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())),
  206. },
  207. 0x13 => Ok(RecvShipPacket::QuestChunkAck(QuestChunkAck::from_bytes(data)?)),
  208. 0x44 => Ok(RecvShipPacket::QuestFileRequest(QuestFileRequest::from_bytes(data)?)),
  209. 0x61 => Ok(RecvShipPacket::CharData(CharData::from_bytes(data)?)),
  210. 0x60 => Ok(RecvShipPacket::Message(Message::from_bytes(data)?)),
  211. 0x62 => Ok(RecvShipPacket::DirectMessage(DirectMessage::from_bytes(data)?)),
  212. 0x06 => Ok(RecvShipPacket::PlayerChat(PlayerChat::from_bytes(data)?)),
  213. 0xC1 => Ok(RecvShipPacket::CreateRoom(CreateRoom::from_bytes(data)?)),
  214. 0x8A => Ok(RecvShipPacket::RoomNameRequest(RoomNameRequest::from_bytes(data)?)),
  215. 0xD8 => Ok(RecvShipPacket::ViewInfoboardRequest(ViewInfoboardRequest::from_bytes(data)?)),
  216. 0xD9 => Ok(RecvShipPacket::WriteInfoboard(WriteInfoboard::from_bytes(data)?)),
  217. 0x08 => Ok(RecvShipPacket::RoomListRequest(RoomListRequest::from_bytes(data)?)),
  218. 0x6D => Ok(RecvShipPacket::Like62ButCooler(Like62ButCooler::from_bytes(data)?)),
  219. 0x98 => Ok(RecvShipPacket::ClientCharacterData(ClientCharacterData::from_bytes(data)?)),
  220. 0x6F => Ok(RecvShipPacket::DoneBursting(DoneBursting::from_bytes(data)?)),
  221. 0x16F => Ok(RecvShipPacket::DoneBursting2(DoneBursting2::from_bytes(data)?)),
  222. 0x84 => Ok(RecvShipPacket::LobbySelect(LobbySelect::from_bytes(data)?)),
  223. 0xA0 => Ok(RecvShipPacket::RequestShipList(RequestShipList::from_bytes(data)?)),
  224. 0xA1 => Ok(RecvShipPacket::RequestShipBlockList(RequestShipBlockList::from_bytes(data)?)),
  225. 0xA2 => Ok(RecvShipPacket::RequestQuestList(RequestQuestList::from_bytes(data)?)),
  226. 0xAC => Ok(RecvShipPacket::DoneLoadingQuest(DoneLoadingQuest::from_bytes(data)?)),
  227. 0xD0 => Ok(RecvShipPacket::ItemsToTrade(ItemsToTrade::from_bytes(data)?)),
  228. 0xD2 => Ok(RecvShipPacket::TradeConfirmed(TradeConfirmed::from_bytes(data)?)),
  229. 0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))),
  230. 0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)),
  231. 0x4ED => Ok(RecvShipPacket::KeyboardConfig(KeyboardConfig::from_bytes(data)?)),
  232. 0x5ED => Ok(RecvShipPacket::GamepadConfig(GamepadConfig::from_bytes(data)?)),
  233. 0x6ED => Ok(RecvShipPacket::UpdateTechMenu(UpdateTechMenu::from_bytes(data)?)),
  234. 0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)),
  235. _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec()))
  236. }
  237. }
  238. }
  239. #[derive(Debug, Clone, PartialEq)]
  240. pub enum SendShipPacket {
  241. ShipWelcome(ShipWelcome),
  242. LoginResponse(LoginResponse),
  243. ShipList(ShipList),
  244. ShipBlockList(ShipBlockList),
  245. FullCharacter(Box<FullCharacter>),
  246. CharDataRequest(CharDataRequest),
  247. JoinLobby(JoinLobby),
  248. AddToLobby(AddToLobby),
  249. Message(Message),
  250. DirectMessage(DirectMessage),
  251. PlayerChat(PlayerChat),
  252. SmallDialog(SmallDialog),
  253. SmallLeftDialog(SmallLeftDialog),
  254. JoinRoom(JoinRoom),
  255. AddToRoom(AddToRoom),
  256. LeaveLobby(LeaveLobby),
  257. LeaveRoom(LeaveRoom),
  258. RoomNameResponse(RoomNameResponse),
  259. ViewInfoboardResponse(ViewInfoboardResponse),
  260. RoomListResponse(RoomListResponse),
  261. Like62ButCooler(Like62ButCooler),
  262. BurstDone72(BurstDone72),
  263. DoneBursting(DoneBursting),
  264. DoneBursting2(DoneBursting2),
  265. LobbyList(LobbyList),
  266. QuestCategoryList(QuestCategoryList),
  267. QuestOptionList(QuestOptionList),
  268. QuestDetail(QuestDetail),
  269. QuestHeader(QuestHeader),
  270. QuestChunk(QuestChunk),
  271. DoneLoadingQuest(DoneLoadingQuest),
  272. BankItemList(BankItemList),
  273. RedirectClient(RedirectClient),
  274. RareMonsterList(RareMonsterList),
  275. AcknowledgeTrade(AcknowledgeTrade),
  276. CancelTrade(CancelTrade),
  277. TradeSuccessful(TradeSuccessful),
  278. LobbyEvent(LobbyEvent),
  279. LargeDialog(LargeDialog),
  280. }
  281. impl SendServerPacket for SendShipPacket {
  282. fn as_bytes(&self) -> Vec<u8> {
  283. match self {
  284. SendShipPacket::ShipWelcome(pkt) => pkt.as_bytes(),
  285. SendShipPacket::LoginResponse(pkt) => pkt.as_bytes(),
  286. SendShipPacket::ShipList(pkt) => pkt.as_bytes(),
  287. SendShipPacket::ShipBlockList(pkt) => pkt.as_bytes(),
  288. SendShipPacket::FullCharacter(pkt) => pkt.as_bytes(),
  289. SendShipPacket::CharDataRequest(pkt) => pkt.as_bytes(),
  290. SendShipPacket::JoinLobby(pkt) => pkt.as_bytes(),
  291. SendShipPacket::AddToLobby(pkt) => pkt.as_bytes(),
  292. SendShipPacket::Message(pkt) => pkt.as_bytes(),
  293. SendShipPacket::DirectMessage(pkt) => pkt.as_bytes(),
  294. SendShipPacket::PlayerChat(pkt) => pkt.as_bytes(),
  295. SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
  296. SendShipPacket::SmallLeftDialog(pkt) => pkt.as_bytes(),
  297. SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
  298. SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
  299. SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(),
  300. SendShipPacket::LeaveRoom(pkt) => pkt.as_bytes(),
  301. SendShipPacket::RoomNameResponse(pkt) => pkt.as_bytes(),
  302. SendShipPacket::ViewInfoboardResponse(pkt) => pkt.as_bytes(),
  303. SendShipPacket::RoomListResponse(pkt) => pkt.as_bytes(),
  304. SendShipPacket::Like62ButCooler(pkt) => pkt.as_bytes(),
  305. SendShipPacket::BurstDone72(pkt) => pkt.as_bytes(),
  306. SendShipPacket::DoneBursting(pkt) => pkt.as_bytes(),
  307. SendShipPacket::DoneBursting2(pkt) => pkt.as_bytes(),
  308. SendShipPacket::LobbyList(pkt) => pkt.as_bytes(),
  309. SendShipPacket::QuestCategoryList(pkt) => pkt.as_bytes(),
  310. SendShipPacket::QuestOptionList(pkt) => pkt.as_bytes(),
  311. SendShipPacket::QuestDetail(pkt) => pkt.as_bytes(),
  312. SendShipPacket::QuestHeader(pkt) => pkt.as_bytes(),
  313. SendShipPacket::QuestChunk(pkt) => pkt.as_bytes(),
  314. SendShipPacket::DoneLoadingQuest(pkt) => pkt.as_bytes(),
  315. SendShipPacket::BankItemList(pkt) => pkt.as_bytes(),
  316. SendShipPacket::RedirectClient(pkt) => pkt.as_bytes(),
  317. SendShipPacket::RareMonsterList(pkt) => pkt.as_bytes(),
  318. SendShipPacket::AcknowledgeTrade(pkt) => pkt.as_bytes(),
  319. SendShipPacket::CancelTrade(pkt) => pkt.as_bytes(),
  320. SendShipPacket::TradeSuccessful(pkt) => pkt.as_bytes(),
  321. SendShipPacket::LobbyEvent(pkt) => pkt.as_bytes(),
  322. SendShipPacket::LargeDialog(pkt) => pkt.as_bytes(),
  323. }
  324. }
  325. }
  326. #[derive(Clone)]
  327. pub struct ItemShops {
  328. pub weapon_shop: HashMap<(room::Difficulty, SectionID), Arc<Mutex<WeaponShop<rand_chacha::ChaCha20Rng>>>>,
  329. pub tool_shop: Arc<Mutex<ToolShop<rand_chacha::ChaCha20Rng>>>,
  330. pub armor_shop: Arc<Mutex<ArmorShop<rand_chacha::ChaCha20Rng>>>,
  331. }
  332. impl Default for ItemShops {
  333. fn default() -> ItemShops {
  334. let difficulty = [room::Difficulty::Normal, room::Difficulty::Hard, room::Difficulty::VeryHard, room::Difficulty::Ultimate];
  335. let section_id = [SectionID::Viridia, SectionID::Greenill, SectionID::Skyly, SectionID::Bluefull, SectionID::Purplenum,
  336. SectionID::Pinkal, SectionID::Redria, SectionID::Oran, SectionID::Yellowboze, SectionID::Whitill];
  337. let mut weapon_shop = HashMap::new();
  338. for d in difficulty.iter() {
  339. for id in section_id.iter() {
  340. weapon_shop.insert((*d, *id), Arc::new(Mutex::new(WeaponShop::new(*d, *id))));
  341. }
  342. }
  343. ItemShops {
  344. weapon_shop,
  345. tool_shop: Arc::new(Mutex::new(ToolShop::default())),
  346. armor_shop: Arc::new(Mutex::new(ArmorShop::default())),
  347. }
  348. }
  349. }
  350. pub struct ShipServerStateBuilder<EG: EntityGateway + Clone + 'static> {
  351. entity_gateway: Option<EG>,
  352. name: Option<String>,
  353. ip: Option<Ipv4Addr>,
  354. port: Option<u16>,
  355. auth_token: Option<AuthToken>,
  356. event: Option<ShipEvent>,
  357. map_builder: Option<Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>>,
  358. drop_table_builder: Option<Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
  359. num_blocks: usize,
  360. }
  361. impl<EG: EntityGateway + Clone + 'static> Default for ShipServerStateBuilder<EG> {
  362. fn default() -> ShipServerStateBuilder<EG> {
  363. ShipServerStateBuilder {
  364. entity_gateway: None,
  365. name: None,
  366. ip: None,
  367. port: None,
  368. auth_token: None,
  369. event: None,
  370. map_builder: None,
  371. drop_table_builder: None,
  372. num_blocks: 2,
  373. }
  374. }
  375. }
  376. impl<EG: EntityGateway + Clone + 'static> ShipServerStateBuilder<EG> {
  377. #[must_use]
  378. pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder<EG> {
  379. self.entity_gateway = Some(entity_gateway);
  380. self
  381. }
  382. #[must_use]
  383. pub fn name(mut self, name: String) -> ShipServerStateBuilder<EG> {
  384. self.name = Some(name);
  385. self
  386. }
  387. #[must_use]
  388. pub fn ip(mut self, ip: Ipv4Addr) -> ShipServerStateBuilder<EG> {
  389. self.ip = Some(ip);
  390. self
  391. }
  392. #[must_use]
  393. pub fn port(mut self, port: u16) -> ShipServerStateBuilder<EG> {
  394. self.port = Some(port);
  395. self
  396. }
  397. #[must_use]
  398. pub fn auth_token(mut self, auth_token: AuthToken) -> ShipServerStateBuilder<EG> {
  399. self.auth_token = Some(auth_token);
  400. self
  401. }
  402. #[must_use]
  403. pub fn event(mut self, event: ShipEvent) -> ShipServerStateBuilder<EG> {
  404. self.event = Some(event);
  405. self
  406. }
  407. #[must_use]
  408. pub fn map_builder(mut self, map_builder: Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>) -> ShipServerStateBuilder<EG> {
  409. self.map_builder = Some(map_builder);
  410. self
  411. }
  412. #[must_use]
  413. pub fn drop_table_builder(mut self, drop_table_builder: Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>) -> ShipServerStateBuilder<EG> {
  414. self.drop_table_builder = Some(drop_table_builder);
  415. self
  416. }
  417. #[must_use]
  418. pub fn blocks(mut self, num_blocks: usize) -> ShipServerStateBuilder<EG> {
  419. self.num_blocks = num_blocks;
  420. self
  421. }
  422. pub fn build(self) -> ShipServerState<EG> {
  423. 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
  424. ShipServerState {
  425. entity_gateway: self.entity_gateway.unwrap(),
  426. clients: Clients::default(),
  427. name: self.name.unwrap_or_else(|| "NAMENOTSET".into()),
  428. item_state: items::state::ItemState::default(),
  429. ip: self.ip.unwrap_or_else(|| Ipv4Addr::new(127,0,0,1)),
  430. port: self.port.unwrap_or(SHIP_PORT),
  431. shops: ItemShops::default(),
  432. blocks: Blocks(blocks),
  433. event: self.event.unwrap_or(ShipEvent::None),
  434. map_builder: Arc::new(self.map_builder.unwrap_or(Box::new(generate_free_roam_maps))),
  435. drop_table_builder: Arc::new(self.drop_table_builder.unwrap_or(Box::new(DropTable::new))),
  436. auth_token: self.auth_token.unwrap_or_else(|| AuthToken("".into())),
  437. ship_list: Arc::new(RwLock::new(Vec::new())),
  438. shipgate_sender: None,
  439. trades: Default::default(),
  440. }
  441. }
  442. }
  443. #[derive(Clone, Default)]
  444. pub struct Block {
  445. client_location: ClientLocation,
  446. pub rooms: room::Rooms,
  447. }
  448. #[derive(Clone)]
  449. pub struct Blocks(pub Vec<Block>);
  450. impl Blocks {
  451. async fn get_from_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, anyhow::Error> {
  452. let block = clients.with(id, |client| Box::pin(async move {
  453. client.block
  454. })).await?;
  455. self.0
  456. .get_mut(block)
  457. .ok_or_else(|| ShipError::InvalidBlock(block).into())
  458. }
  459. }
  460. #[derive(Clone)]
  461. pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
  462. pub(crate) entity_gateway: EG,
  463. pub clients: Clients,
  464. name: String,
  465. pub(crate) item_state: items::state::ItemState,
  466. shops: ItemShops,
  467. pub blocks: Blocks,
  468. event: ShipEvent,
  469. ip: Ipv4Addr,
  470. port: u16,
  471. auth_token: AuthToken,
  472. ship_list: Arc<RwLock<Vec<Ship>>>,
  473. shipgate_sender: Option<channel::Sender<ShipMessage>>,
  474. trades: TradeState,
  475. map_builder: Arc<Box<dyn Fn(room::RoomMode, ShipEvent) -> Maps + Send + Sync>>,
  476. drop_table_builder: Arc<Box<dyn Fn(room::Episode, room::Difficulty, SectionID) -> DropTable + Send + Sync>>,
  477. }
  478. impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
  479. pub fn builder() -> ShipServerStateBuilder<EG> {
  480. ShipServerStateBuilder::default()
  481. }
  482. async fn message(&mut self, id: ClientId, msg: Message) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
  483. Ok(match msg.msg {
  484. GameMessage::RequestExp(request_exp) => {
  485. let block = self.blocks.get_from_client(id, &self.clients).await?;
  486. handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms).await?
  487. },
  488. GameMessage::PlayerDropItem(player_drop_item) => {
  489. let block = self.blocks.get_from_client(id, &self.clients).await?;
  490. handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await?
  491. },
  492. GameMessage::DropCoordinates(drop_coordinates) => {
  493. let block = self.blocks.get_from_client(id, &self.clients).await?;
  494. handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &self.clients, &block.rooms).await?
  495. },
  496. GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
  497. let block = self.blocks.get_from_client(id, &self.clients).await?;
  498. handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  499. },
  500. GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
  501. GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
  502. GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
  503. GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
  504. let block = self.blocks.get_from_client(id, &self.clients).await?;
  505. handler::message::update_player_position(id, msg, &self.clients, &block.client_location, &block.rooms).await?
  506. },
  507. GameMessage::ChargeAttack(charge_attack) => {
  508. let block = self.blocks.get_from_client(id, &self.clients).await?;
  509. handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  510. },
  511. GameMessage::PlayerUseItem(player_use_item) => {
  512. let block = self.blocks.get_from_client(id, &self.clients).await?;
  513. handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  514. },
  515. GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => {
  516. let block = self.blocks.get_from_client(id, &self.clients).await?;
  517. handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  518. },
  519. GameMessage::PlayerFeedMag(player_feed_mag) => {
  520. let block = self.blocks.get_from_client(id, &self.clients).await?;
  521. handler::message::player_feed_mag(id, player_feed_mag, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  522. },
  523. GameMessage::PlayerEquipItem(player_equip_item) => {
  524. handler::message::player_equips_item(id, player_equip_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
  525. },
  526. GameMessage::PlayerUnequipItem(player_unequip_item) => {
  527. handler::message::player_unequips_item(id, player_unequip_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
  528. },
  529. GameMessage::SortItems(sort_items) => {
  530. handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
  531. },
  532. GameMessage::PlayerSoldItem(player_sold_item) => {
  533. handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
  534. },
  535. GameMessage::FloorItemLimitItemDeletion(floor_item_limit_delete) => {
  536. let block = self.blocks.get_from_client(id, &self.clients).await?;
  537. handler::message::floor_item_limit_deletion(id, floor_item_limit_delete, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await?
  538. },
  539. _ => {
  540. let cmsg = msg.clone();
  541. let block = self.blocks.get_from_client(id, &self.clients).await?;
  542. block.client_location.get_client_neighbors(id).await.unwrap().into_iter()
  543. .map(move |client| {
  544. (client.client, SendShipPacket::Message(cmsg.clone()))
  545. })
  546. .collect()
  547. },
  548. })
  549. }
  550. async fn direct_message(&mut self, id: ClientId, msg: DirectMessage) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
  551. let target = msg.flag;
  552. let block = self.blocks.get_from_client(id, &self.clients).await?;
  553. Ok(match msg.msg {
  554. GameMessage::GuildcardSend(guildcard_send) => {
  555. handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients).await?
  556. },
  557. GameMessage::RequestItem(request_item) => {
  558. handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await?
  559. },
  560. GameMessage::PickupItem(pickup_item) => {
  561. handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  562. },
  563. GameMessage::BoxDropRequest(box_drop_request) => {
  564. handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await?
  565. },
  566. GameMessage::BankRequest(_bank_request) => {
  567. handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_state).await?
  568. },
  569. GameMessage::BankInteraction(bank_interaction) => {
  570. handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  571. },
  572. GameMessage::ShopRequest(shop_request) => {
  573. handler::direct_message::shop_request(id, shop_request, &block.client_location, &self.clients, &block.rooms, &self.shops).await?
  574. },
  575. GameMessage::BuyItem(buy_item) => {
  576. handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  577. },
  578. GameMessage::TekRequest(tek_request) => {
  579. handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
  580. },
  581. GameMessage::TekAccept(tek_accept) => {
  582. handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
  583. },
  584. GameMessage::TradeRequest(trade_request) => {
  585. handler::trade::trade_request(id, trade_request, target, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await?
  586. },
  587. _ => {
  588. let cmsg = msg.clone();
  589. block.client_location.get_all_clients_by_client(id).await.unwrap().into_iter()
  590. .filter(move |client| client.local_client.id() == target as u8)
  591. .map(move |client| {
  592. (client.client, SendShipPacket::DirectMessage(cmsg.clone()))
  593. })
  594. .collect()
  595. },
  596. })
  597. }
  598. }
  599. #[async_trait::async_trait]
  600. impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
  601. type SendPacket = SendShipPacket;
  602. type RecvPacket = RecvShipPacket;
  603. type Cipher = PSOBBCipher;
  604. type PacketError = anyhow::Error;
  605. async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket, Self::Cipher>>, anyhow::Error> {
  606. let mut rng = rand::thread_rng();
  607. let mut server_key = [0u8; 48];
  608. let mut client_key = [0u8; 48];
  609. rng.fill(&mut server_key[..]);
  610. rng.fill(&mut client_key[..]);
  611. Ok(vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))),
  612. OnConnect::Cipher(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key),
  613. PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))
  614. ])
  615. }
  616. async fn handle(&mut self, id: ClientId, pkt: RecvShipPacket) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
  617. if let Ok((char_id, char_playtime)) = self.clients.with_mut(id, |client| Box::pin(async move {
  618. client.update_playtime();
  619. (client.character.id, client.character.playtime)
  620. })).await {
  621. self.entity_gateway.set_character_playtime(&char_id, char_playtime).await?;
  622. }
  623. Ok(match pkt {
  624. RecvShipPacket::Login(login) => {
  625. handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_state, &self.shipgate_sender, &self.name, self.blocks.0.len())
  626. .await?
  627. .into_iter()
  628. .map(move |pkt| (id, pkt))
  629. .collect()
  630. },
  631. RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
  632. let block = self.blocks.get_from_client(id, &self.clients).await?;
  633. match questdetailrequest.menu {
  634. QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &block.rooms).await?,
  635. _ => unreachable!(),
  636. }
  637. },
  638. RecvShipPacket::MenuSelect(menuselect) => {
  639. let block = self.blocks.get_from_client(id, &self.clients).await?;
  640. match menuselect.menu {
  641. SHIP_MENU_ID => {
  642. let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().flatten();
  643. let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list).await?;
  644. leave_lobby.chain(select_ship).collect()
  645. }
  646. BLOCK_MENU_ID => {
  647. let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().flatten();
  648. let select_block = handler::lobby::block_selected(id, menuselect, &self.clients, &self.item_state).await?.into_iter();
  649. leave_lobby.chain(select_block).collect()
  650. }
  651. ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut self.entity_gateway, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, self.event).await?,
  652. QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &block.rooms).await?,
  653. _ => unreachable!(),
  654. }
  655. },
  656. RecvShipPacket::QuestMenuSelect(questmenuselect) => {
  657. let block = self.blocks.get_from_client(id, &self.clients).await?;
  658. handler::quest::player_chose_quest(id, questmenuselect, &self.clients, &block.client_location, &block.rooms, self.event).await?
  659. },
  660. RecvShipPacket::MenuDetail(menudetail) => {
  661. let block = self.blocks.get_from_client(id, &self.clients).await?;
  662. handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients).await?
  663. },
  664. RecvShipPacket::RoomPasswordReq(room_password_req) => {
  665. let block = self.blocks.get_from_client(id, &self.clients).await?;
  666. let room_password = block.rooms.with(RoomId(room_password_req.item as usize), |room| Box::pin(async move {
  667. room.password
  668. })).await?;
  669. if room_password_req.password == room_password {
  670. let menuselect = MenuSelect {
  671. menu: room_password_req.menu,
  672. item: room_password_req.item,
  673. };
  674. handler::room::join_room(id, menuselect, &mut self.entity_gateway, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, self.event).await?
  675. }
  676. else {
  677. vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))]
  678. }
  679. },
  680. RecvShipPacket::CharData(chardata) => {
  681. let block = self.blocks.get_from_client(id, &self.clients).await?;
  682. handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state, self.event).await?
  683. },
  684. RecvShipPacket::Message(msg) => {
  685. self.message(id, msg).await?
  686. },
  687. RecvShipPacket::DirectMessage(msg) => {
  688. self.direct_message(id, msg).await?
  689. },
  690. RecvShipPacket::PlayerChat(msg) => {
  691. match chatcommand::handle_chat_command(id, msg.clone(), self).await {
  692. Some(ccmd) => {
  693. match ccmd {
  694. Ok(pkts) => pkts,
  695. Err(msg) => vec![(id, SendShipPacket::LargeDialog(LargeDialog::new(msg)))]
  696. }
  697. },
  698. None => {
  699. let block = self.blocks.get_from_client(id, &self.clients).await?;
  700. handler::communication::player_chat(id, msg, &block.client_location, &self.clients).await?
  701. }
  702. }
  703. },
  704. RecvShipPacket::CreateRoom(create_room) => {
  705. let block = self.blocks.get_from_client(id, &self.clients).await?;
  706. handler::room::create_room(id, create_room, &mut self.entity_gateway, &mut block.client_location, &self.clients, &mut self.item_state,
  707. &block.rooms, self.map_builder.clone(), self.drop_table_builder.clone(), self.event).await?
  708. },
  709. RecvShipPacket::RoomNameRequest(_req) => {
  710. let block = self.blocks.get_from_client(id, &self.clients).await?;
  711. handler::room::room_name_request(id, &block.client_location, &block.rooms).await?
  712. },
  713. RecvShipPacket::UpdateTechMenu(pkt) => {
  714. handler::settings::update_tech_menu(id, pkt, &self.clients, &mut self.entity_gateway).await?
  715. },
  716. RecvShipPacket::UpdateConfig(pkt) => {
  717. handler::settings::update_config(id, pkt, &self.clients, &mut self.entity_gateway).await?
  718. },
  719. RecvShipPacket::ViewInfoboardRequest(_pkt) => {
  720. let block = self.blocks.get_from_client(id, &self.clients).await?;
  721. handler::communication::request_infoboard(id, &block.client_location, &self.clients).await?
  722. },
  723. RecvShipPacket::WriteInfoboard(pkt) => {
  724. handler::communication::write_infoboard(id, pkt, &self.clients, &mut self.entity_gateway).await?
  725. },
  726. RecvShipPacket::RoomListRequest(_req) => {
  727. let block = self.blocks.get_from_client(id, &self.clients).await?;
  728. handler::room::request_room_list(id, &block.client_location, &block.rooms).await
  729. },
  730. RecvShipPacket::Like62ButCooler(cool62) => {
  731. let block = self.blocks.get_from_client(id, &self.clients).await?;
  732. handler::room::cool_62(id, cool62, &block.client_location).await?
  733. },
  734. RecvShipPacket::ClientCharacterData(_) => {
  735. // TOOD: validate this in some way?
  736. Vec::new()
  737. },
  738. RecvShipPacket::DoneBursting(_) => {
  739. let block = self.blocks.get_from_client(id, &self.clients).await?;
  740. handler::room::done_bursting(id, &block.client_location, &block.rooms).await?
  741. },
  742. RecvShipPacket::DoneBursting2(_) => {
  743. let block = self.blocks.get_from_client(id, &self.clients).await?;
  744. handler::room::done_bursting(id, &block.client_location, &block.rooms).await?
  745. },
  746. RecvShipPacket::LobbySelect(pkt) => {
  747. let block = self.blocks.get_from_client(id, &self.clients).await?;
  748. handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, &mut self.entity_gateway, self.event).await?
  749. },
  750. RecvShipPacket::RequestQuestList(rql) => {
  751. let block = self.blocks.get_from_client(id, &self.clients).await?;
  752. handler::quest::send_quest_category_list(id, rql, &block.client_location, &block.rooms).await?
  753. },
  754. RecvShipPacket::QuestFileRequest(quest_file_request) => {
  755. let block = self.blocks.get_from_client(id, &self.clients).await?;
  756. handler::quest::quest_file_request(id, quest_file_request, &block.client_location, &mut block.rooms).await?
  757. },
  758. RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
  759. let block = self.blocks.get_from_client(id, &self.clients).await?;
  760. handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &block.rooms).await?
  761. },
  762. RecvShipPacket::DoneLoadingQuest(_) => {
  763. let block = self.blocks.get_from_client(id, &self.clients).await?;
  764. handler::quest::done_loading_quest(id, &self.clients, &block.client_location).await?
  765. },
  766. RecvShipPacket::FullCharacterData(_full_character_data) => {
  767. Vec::new()
  768. },
  769. RecvShipPacket::SaveOptions(save_options) => {
  770. handler::settings::save_options(id, save_options, &self.clients, &mut self.entity_gateway).await?
  771. },
  772. RecvShipPacket::RequestShipList(_) => {
  773. handler::ship::ship_list(id, &self.ship_list).await
  774. },
  775. RecvShipPacket::RequestShipBlockList(_) => {
  776. handler::ship::block_list(id, &self.name, self.blocks.0.len())
  777. },
  778. RecvShipPacket::ItemsToTrade(items_to_trade) => {
  779. let block = self.blocks.get_from_client(id, &self.clients).await?;
  780. handler::trade::items_to_trade(id, items_to_trade, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await?
  781. },
  782. RecvShipPacket::TradeConfirmed(_) => {
  783. let block = self.blocks.get_from_client(id, &self.clients).await?;
  784. handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await?
  785. },
  786. RecvShipPacket::KeyboardConfig(keyboard_config) => {
  787. handler::settings::keyboard_config(id, keyboard_config, &self.clients, &mut self.entity_gateway).await?
  788. },
  789. RecvShipPacket::GamepadConfig(gamepad_config) => {
  790. handler::settings::gamepad_config(id, gamepad_config, &self.clients, &mut self.entity_gateway).await?
  791. },
  792. })
  793. }
  794. async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
  795. let block = self.blocks.get_from_client(id, &self.clients).await?;
  796. let area_client = block.client_location.get_local_client(id).await?;
  797. let neighbors = block.client_location.get_client_neighbors(id).await?;
  798. let pkt = match block.client_location.get_area(id).await? {
  799. RoomLobby::Room(room) => {
  800. let character_id = self.clients.with(id, |client| Box::pin(async {
  801. client.character.id
  802. })).await?;
  803. block.rooms.with(room, |room| {
  804. let mut entity_gateway = self.entity_gateway.clone();
  805. Box::pin(async move {
  806. entity_gateway.add_room_note(room.room_id, RoomNote::PlayerJoin {
  807. character_id,
  808. }).await
  809. })}).await;
  810. if neighbors.is_empty() {
  811. block.rooms.remove(room).await;
  812. }
  813. let leader = block.client_location.get_room_leader(room).await?;
  814. SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id()))
  815. },
  816. RoomLobby::Lobby(lobby) => {
  817. let leader = block.client_location.get_lobby_leader(lobby).await?;
  818. SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))
  819. }
  820. };
  821. if let Some(mut client) = self.clients.remove(&id).await {
  822. client.user.at_ship = false;
  823. self.entity_gateway.save_user(&client.user).await;
  824. if let Some(shipgate_sender) = self.shipgate_sender.as_ref() {
  825. shipgate_sender.send(ShipMessage::RemoveUser(client.user.id)).await;
  826. }
  827. self.item_state.remove_character_from_room(&client.character).await
  828. }
  829. block.client_location.remove_client_from_area(id).await?;
  830. Ok(neighbors.into_iter().map(|n| {
  831. (n.client, pkt.clone())
  832. }).collect())
  833. }
  834. }
  835. #[async_trait::async_trait]
  836. impl<EG: EntityGateway + Clone> InterserverActor for ShipServerState<EG> {
  837. type SendMessage = ShipMessage;
  838. type RecvMessage = LoginMessage;
  839. type Error = ();
  840. async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  841. vec![
  842. (id, ShipMessage::Authenticate(self.auth_token.clone())),
  843. (id, ShipMessage::NewShip(Ship {
  844. name: self.name.clone(),
  845. ip: self.ip,
  846. port: self.port,
  847. block_count: 2,
  848. })),
  849. (id, ShipMessage::RequestShipList)
  850. ]
  851. }
  852. async fn on_action(&mut self, _id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
  853. match msg {
  854. LoginMessage::SendMail{..} => {
  855. Ok(Vec::new())
  856. },
  857. LoginMessage::ShipList{mut ships} => {
  858. let mut ship_list = self.ship_list
  859. .write()
  860. .await;
  861. ship_list.clear();
  862. ship_list.append(&mut ships);
  863. Ok(Vec::new())
  864. },
  865. LoginMessage::RequestUsers => {
  866. /*
  867. Ok(self.clients.iter()
  868. .map(|(_, client)| {
  869. (id, ShipMessage::AddUser(client.user.id))
  870. })
  871. .collect())
  872. */
  873. // TODO
  874. Ok(Vec::new())
  875. }
  876. }
  877. }
  878. async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
  879. Vec::new()
  880. }
  881. async fn set_sender(&mut self, _server_id: ServerId, sender: channel::Sender<Self::SendMessage>) {
  882. self.shipgate_sender = Some(sender);
  883. }
  884. }