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.

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