@ -6,7 +6,7 @@ use rand::Rng;
use thiserror ::Error ;
use libpso ::packet ::ship ::* ;
use libpso ::packet ::login ::{ Login , LoginResponse , Session } ;
use libpso ::packet ::login ::{ RedirectClient , Login , LoginResponse , Session , ShipList } ;
use libpso ::packet ::messages ::* ;
use libpso ::{ PacketParseError , PSOPacket } ;
use libpso ::crypto ::bb ::PSOBBCipher ;
@ -18,6 +18,8 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState
use crate ::common ::leveltable ::CharacterLevelTable ;
use crate ::common ::interserver ::{ AuthToken , Ship , ServerId , InterserverActor , LoginMessage , ShipMessage } ;
use crate ::login ::character ::SHIP_MENU_ID ;
use crate ::entity ::gateway ::{ EntityGateway , GatewayError } ;
use crate ::entity ::account ::{ UserAccountEntity , UserSettingsEntity } ;
use crate ::entity ::character ::{ CharacterEntity , SectionID } ;
@ -67,6 +69,8 @@ pub enum ShipError {
ShopError ,
GatewayError ( #[ from ] GatewayError ) ,
UnknownMonster ( crate ::ship ::monster ::MonsterType ) ,
InvalidShip ( usize ) ,
InvalidBlock ( usize ) ,
}
#[ derive(Debug) ]
@ -98,6 +102,8 @@ pub enum RecvShipPacket {
DoneLoadingQuest ( DoneLoadingQuest ) ,
FullCharacterData ( Box < FullCharacterData > ) ,
SaveOptions ( SaveOptions ) ,
RequestShipList ( RequestShipList ) ,
RequestShipBlockList ( RequestShipBlockList ) ,
}
impl RecvServerPacket for RecvShipPacket {
@ -131,6 +137,8 @@ impl RecvServerPacket for RecvShipPacket {
0x6F = > Ok ( RecvShipPacket ::DoneBursting ( DoneBursting ::from_bytes ( data ) ? ) ) ,
0x16F = > Ok ( RecvShipPacket ::DoneBursting2 ( DoneBursting2 ::from_bytes ( data ) ? ) ) ,
0x84 = > Ok ( RecvShipPacket ::LobbySelect ( LobbySelect ::from_bytes ( data ) ? ) ) ,
0xA0 = > Ok ( RecvShipPacket ::RequestShipList ( RequestShipList ::from_bytes ( data ) ? ) ) ,
0xA1 = > Ok ( RecvShipPacket ::RequestShipBlockList ( RequestShipBlockList ::from_bytes ( data ) ? ) ) ,
0xA2 = > Ok ( RecvShipPacket ::RequestQuestList ( RequestQuestList ::from_bytes ( data ) ? ) ) ,
0xAC = > Ok ( RecvShipPacket ::DoneLoadingQuest ( DoneLoadingQuest ::from_bytes ( data ) ? ) ) ,
0xE7 = > Ok ( RecvShipPacket ::FullCharacterData ( Box ::new ( FullCharacterData ::from_bytes ( data ) ? ) ) ) ,
@ -144,6 +152,7 @@ impl RecvServerPacket for RecvShipPacket {
pub enum SendShipPacket {
ShipWelcome ( ShipWelcome ) ,
LoginResponse ( LoginResponse ) ,
ShipList ( ShipList ) ,
ShipBlockList ( ShipBlockList ) ,
FullCharacter ( Box < FullCharacter > ) ,
CharDataRequest ( CharDataRequest ) ,
@ -172,6 +181,7 @@ pub enum SendShipPacket {
QuestChunk ( QuestChunk ) ,
DoneLoadingQuest ( DoneLoadingQuest ) ,
BankItemList ( BankItemList ) ,
RedirectClient ( RedirectClient ) ,
}
impl SendServerPacket for SendShipPacket {
@ -179,6 +189,7 @@ impl SendServerPacket for SendShipPacket {
match self {
SendShipPacket ::ShipWelcome ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::LoginResponse ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::ShipList ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::ShipBlockList ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::FullCharacter ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::CharDataRequest ( pkt ) = > pkt . as_bytes ( ) ,
@ -207,6 +218,7 @@ impl SendServerPacket for SendShipPacket {
SendShipPacket ::QuestChunk ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::DoneLoadingQuest ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::BankItemList ( pkt ) = > pkt . as_bytes ( ) ,
SendShipPacket ::RedirectClient ( pkt ) = > pkt . as_bytes ( ) ,
}
}
}
@ -231,7 +243,7 @@ pub struct ClientState {
pub character : CharacterEntity ,
session : Session ,
//guildcard: GuildCard,
pub block : u32 ,
pub block : usize ,
pub item_drop_location : Option < ItemDropLocation > ,
pub done_loading_quest : bool ,
//pub loading_quest: Option<LoadingQuest>,
@ -251,7 +263,7 @@ impl ClientState {
settings : settings ,
character : character ,
session : session ,
block : 1 ,
block : 0 ,
item_drop_location : None ,
done_loading_quest : false ,
area : None ,
@ -299,6 +311,7 @@ pub struct ShipServerStateBuilder<EG: EntityGateway> {
ip : Option < Ipv4Addr > ,
port : Option < u16 > ,
auth_token : Option < AuthToken > ,
num_blocks : usize ,
}
impl < EG : EntityGateway > ShipServerStateBuilder < EG > {
@ -309,6 +322,7 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
ip : None ,
port : None ,
auth_token : None ,
num_blocks : 2 ,
}
}
@ -337,37 +351,73 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
self
}
pub fn blocks ( mut self , num_blocks : usize ) -> ShipServerStateBuilder < EG > {
self . num_blocks = num_blocks ;
self
}
pub fn build ( self ) -> ShipServerState < EG > {
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
ShipServerState {
entity_gateway : self . entity_gateway . unwrap ( ) ,
clients : HashMap ::new ( ) ,
client_location : Box ::new ( ClientLocation ::new ( ) ) ,
level_table : CharacterLevelTable ::new ( ) ,
name : self . name . unwrap_or ( "NAMENOTSET" . into ( ) ) ,
rooms : Box ::new ( [ None ; MAX_ROOMS ] ) ,
item_manager : items ::ItemManager ::new ( ) ,
quests : quests ::load_quests ( "data/quests.toml" . into ( ) ) . unwrap ( ) ,
ip : self . ip . unwrap_or ( Ipv4Addr ::new ( 127 , 0 , 0 , 1 ) ) ,
port : self . port . unwrap_or ( SHIP_PORT ) ,
shops : Box ::new ( ItemShops ::new ( ) ) ,
blocks : Blocks ( blocks ) ,
auth_token : self . auth_token . unwrap_or ( AuthToken ( "" . into ( ) ) ) ,
ship_list : Vec ::new ( ) ,
shipgate_sender : None ,
}
}
}
pub struct Block {
client_location : Box < ClientLocation > ,
pub rooms : Box < Rooms > ,
}
impl Default for Block {
fn default ( ) -> Block {
Block {
client_location : Box ::new ( ClientLocation ::default ( ) ) ,
rooms : Box ::new ( [ None ; MAX_ROOMS ] ) ,
}
}
}
pub struct Blocks ( pub Vec < Block > ) ;
impl Blocks {
fn with_client ( & mut self , id : ClientId , clients : & Clients ) -> Result < & mut Block , ShipError > {
let client = clients . get ( & id ) . ok_or ( ShipError ::ClientNotFound ( id ) ) ? ;
self . 0. get_mut ( client . block ) . ok_or ( ShipError ::InvalidBlock ( client . block ) )
}
}
pub struct ShipServerState < EG : EntityGateway > {
entity_gateway : EG ,
pub clients : Clients ,
client_location : Box < ClientLocation > ,
level_table : CharacterLevelTable ,
name : String ,
pub rooms : Box < Rooms > ,
item_manager : items ::ItemManager ,
quests : quests ::QuestList ,
shops : Box < ItemShops > ,
pub blocks : Blocks ,
ip : Ipv4Addr ,
port : u16 ,
shops : Box < ItemShops > ,
auth_token : AuthToken ,
ship_list : Vec < Ship > ,
shipgate_sender : Option < Box < dyn Fn ( ShipMessage ) + Send + Sync > > ,
}
impl < EG : EntityGateway > ShipServerState < EG > {
@ -375,37 +425,48 @@ impl<EG: EntityGateway> ShipServerState<EG> {
ShipServerStateBuilder ::new ( )
}
pub fn set_sender ( & mut self , sender : Box < dyn Fn ( ShipMessage ) + Send + Sync > ) {
self . shipgate_sender = Some ( sender ) ;
}
async fn message ( & mut self , id : ClientId , msg : & Message ) -> Result < Box < dyn Iterator < Item = ( ClientId , SendShipPacket ) > + Send > , anyhow ::Error > {
Ok ( match & msg . msg {
GameMessage ::RequestExp ( request_exp ) = > {
handler ::message ::request_exp ( id , request_exp , & mut self . entity_gateway , & self . client_location , & mut self . clients , & mut self . rooms , & self . level_table ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::request_exp ( id , request_exp , & mut self . entity_gateway , & block . client_location , & mut self . clients , & mut block . rooms , & self . level_table ) . await ?
} ,
GameMessage ::PlayerDropItem ( player_drop_item ) = > {
handler ::message ::player_drop_item ( id , player_drop_item , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . rooms , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::player_drop_item ( id , player_drop_item , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut block . rooms , & mut self . item_manager ) . await ?
} ,
GameMessage ::DropCoordinates ( drop_coordinates ) = > {
handler ::message ::drop_coordinates ( id , drop_coordinates , & self . client_location , & mut self . clients , & self . rooms ) ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::drop_coordinates ( id , drop_coordinates , & block . client_location , & mut self . clients , & block . rooms ) ?
} ,
GameMessage ::PlayerNoLongerHasItem ( no_longer_has_item ) = > {
handler ::message ::split_item_stack ( id , no_longer_has_item , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::split_item_stack ( id , no_longer_has_item , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::PlayerChangedMap ( _ ) | GameMessage ::PlayerChangedMap2 ( _ ) | GameMessage ::TellOtherPlayerMyLocation ( _ ) |
GameMessage ::PlayerWarpingToFloor ( _ ) | GameMessage ::PlayerTeleported ( _ ) | GameMessage ::PlayerStopped ( _ ) |
GameMessage ::PlayerLoadedIn ( _ ) | GameMessage ::PlayerWalking ( _ ) | GameMessage ::PlayerRunning ( _ ) |
GameMessage ::PlayerWarped ( _ ) | GameMessage ::PlayerChangedFloor ( _ ) | GameMessage ::InitializeSpeechNpc ( _ ) = > {
handler ::message ::update_player_position ( id , & msg , & mut self . clients , & mut self . client_location , & self . rooms ) ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::update_player_position ( id , & msg , & mut self . clients , & mut block . client_location , & block . rooms ) ?
} ,
GameMessage ::ChargeAttack ( charge_attack ) = > {
handler ::message ::charge_attack ( id , charge_attack , & mut self . clients , & mut self . entity_gateway ) . await ?
} ,
GameMessage ::PlayerUseItem ( player_use_item ) = > {
handler ::message ::use_item ( id , player_use_item , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::use_item ( id , player_use_item , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::PlayerUsedMedicalCenter ( player_used_medical_center ) = > {
handler ::message ::player_used_medical_center ( id , & player_used_medical_center , & mut self . entity_gateway , & mut self . clients ) . await ?
} ,
GameMessage ::PlayerFeedMag ( player_feed_mag ) = > {
handler ::message ::player_feed_mag ( id , & player_feed_mag , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::message ::player_feed_mag ( id , & player_feed_mag , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::PlayerEquipItem ( player_equip_item ) = > {
handler ::message ::player_equips_item ( id , & player_equip_item , & mut self . entity_gateway , & mut self . clients , & mut self . item_manager ) . await ?
@ -418,7 +479,8 @@ impl<EG: EntityGateway> ShipServerState<EG> {
} ,
_ = > {
let cmsg = msg . clone ( ) ;
Box ::new ( self . client_location . get_client_neighbors ( id ) . unwrap ( ) . into_iter ( )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
Box ::new ( block . client_location . get_client_neighbors ( id ) . unwrap ( ) . into_iter ( )
. map ( move | client | {
( client . client , SendShipPacket ::Message ( cmsg . clone ( ) ) )
} ) )
@ -430,32 +492,40 @@ impl<EG: EntityGateway> ShipServerState<EG> {
let target = msg . flag ;
Ok ( match & msg . msg {
GameMessage ::GuildcardSend ( guildcard_send ) = > {
handler ::direct_message ::guildcard_send ( id , guildcard_send , target , & self . client_location , & self . clients )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::guildcard_send ( id , guildcard_send , target , & block . client_location , & self . clients )
} ,
GameMessage ::RequestItem ( request_item ) = > {
handler ::direct_message ::request_item ( id , request_item , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . rooms , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::request_item ( id , request_item , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut block . rooms , & mut self . item_manager ) . await ?
} ,
GameMessage ::PickupItem ( pickup_item ) = > {
handler ::direct_message ::pickup_item ( id , pickup_item , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::pickup_item ( id , pickup_item , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::BoxDropRequest ( box_drop_request ) = > {
handler ::direct_message ::request_box_item ( id , box_drop_request , & mut self . entity_gateway , & mut self . client_location , & mut self . clients , & mut self . rooms , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::request_box_item ( id , box_drop_request , & mut self . entity_gateway , & mut block . client_location , & mut self . clients , & mut block . rooms , & mut self . item_manager ) . await ?
} ,
GameMessage ::BankRequest ( _bank_request ) = > {
handler ::direct_message ::send_bank_list ( id , & self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::BankInteraction ( bank_interaction ) = > {
handler ::direct_message ::bank_interaction ( id , bank_interaction , & mut self . entity_gateway , & self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::bank_interaction ( id , bank_interaction , & mut self . entity_gateway , & block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
GameMessage ::ShopRequest ( shop_request ) = > {
handler ::direct_message ::shop_request ( id , shop_request , & self . client_location , & mut self . clients , & self . rooms , & self . level_table , & mut self . shops ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::shop_request ( id , shop_request , & block . client_location , & mut self . clients , & block . rooms , & self . level_table , & mut self . shops ) . await ?
} ,
GameMessage ::BuyItem ( buy_item ) = > {
handler ::direct_message ::buy_item ( id , buy_item , & mut self . entity_gateway , & self . client_location , & mut self . clients , & mut self . item_manager ) . await ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::direct_message ::buy_item ( id , buy_item , & mut self . entity_gateway , & block . client_location , & mut self . clients , & mut self . item_manager ) . await ?
} ,
_ = > {
let cmsg = msg . clone ( ) ;
Box ::new ( self . client_location . get_all_clients_by_client ( id ) . unwrap ( ) . into_iter ( )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
Box ::new ( block . client_location . get_all_clients_by_client ( id ) . unwrap ( ) . into_iter ( )
. filter ( move | client | client . local_client . id ( ) = = target as u8 )
. map ( move | client | {
( client . client , SendShipPacket ::DirectMessage ( cmsg . clone ( ) ) )
@ -489,7 +559,8 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
-> Result < Box < dyn Iterator < Item = ( ClientId , SendShipPacket ) > + Send > , anyhow ::Error > {
Ok ( match pkt {
RecvShipPacket ::Login ( login ) = > {
Box ::new ( handler ::auth ::validate_login ( id , login , & mut self . entity_gateway , & mut self . clients , & mut self . item_manager , & self . name ) . await ? . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
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 ( ) )
. await ? . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) )
} ,
RecvShipPacket ::QuestDetailRequest ( questdetailrequest ) = > {
match questdetailrequest . menu {
@ -498,36 +569,49 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
}
} ,
RecvShipPacket ::MenuSelect ( menuselect ) = > {
let block = self . blocks . with_client ( id , & self . clients ) ? ;
match menuselect . menu {
BLOCK_MENU_ID = > Box ::new ( handler ::lobby ::block_selected ( id , menuselect , & mut self . clients , & self . item_manager , & self . level_table ) ? . into_iter ( ) . map ( move | pkt | ( id , pkt ) ) ) ,
ROOM_MENU_ID = > handler ::room ::join_room ( id , menuselect , & mut self . client_location , & mut self . clients , & mut self . item_manager , & self . level_table , & mut self . rooms ) ? ,
SHIP_MENU_ID = > {
let leave_lobby = handler ::lobby ::remove_from_lobby ( id , & mut block . client_location ) . into_iter ( ) . into_iter ( ) . flatten ( ) ;
let select_ship = handler ::ship ::selected_ship ( id , menuselect , & self . ship_list ) ? ;
Box ::new ( leave_lobby . chain ( select_ship ) )
}
BLOCK_MENU_ID = > {
let leave_lobby = handler ::lobby ::remove_from_lobby ( id , & mut block . client_location ) . into_iter ( ) . into_iter ( ) . flatten ( ) ;
let select_block = handler ::lobby ::block_selected ( id , menuselect , & mut self . clients , & self . item_manager , & self . level_table ) ? . into_iter ( ) ;
Box ::new ( leave_lobby . chain ( select_block ) )
}
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 ) ? ,
QUEST_CATEGORY_MENU_ID = > handler ::quest ::select_quest_category ( id , menuselect , & self . quests ) ? ,
_ = > unreachable ! ( ) ,
}
} ,
RecvShipPacket ::QuestMenuSelect ( questmenuselect ) = > {
handler ::quest ::load_quest ( id , questmenuselect , & self . quests , & mut self . clients , & self . client_location , & mut self . rooms ) ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::quest ::load_quest ( id , questmenuselect , & self . quests , & mut self . clients , & block . client_location , & mut block . rooms ) ?
} ,
RecvShipPacket ::MenuDetail ( _menudetail ) = > {
//unreachable!();
Box ::new ( Vec ::new ( ) . into_iter ( ) )
} ,
RecvShipPacket ::RoomPasswordReq ( room_password_req ) = > {
if room_password_req . password = = self . rooms [ room_password_req . item as usize ] . as_ref ( )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
if room_password_req . password = = block . rooms [ room_password_req . item as usize ] . as_ref ( )
. ok_or ( ShipError ::InvalidRoom ( room_password_req . item ) ) ?
. password {
let menuselect = MenuSelect {
menu : room_password_req . menu ,
item : room_password_req . item ,
} ;
handler ::room ::join_room ( id , & menuselect , & mut self . client_location , & mut self . clients , & mut self . item_manager , & self . level_table , & mut self . rooms ) ?
}
let menuselect = MenuSelect {
menu : room_password_req . menu ,
item : room_password_req . item ,
} ;
handler ::room ::join_room ( id , & menuselect , & mut block . client_location , & mut self . clients , & mut self . item_manager , & self . level_table , & mut block . rooms ) ?
}
else {
Box ::new ( vec ! [ ( id , SendShipPacket ::SmallDialog ( SmallDialog ::new ( "Incorrect password" . into ( ) ) ) ) ] . into_iter ( ) )
}
} ,
RecvShipPacket ::CharData ( chardata ) = > {
Box ::new ( handler ::lobby ::send_player_to_lobby ( id , chardata , & mut self . client_location , & self . clients , & self . item_manager , & self . level_table ) ? . into_iter ( ) )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
Box ::new ( handler ::lobby ::send_player_to_lobby ( id , chardata , & mut block . client_location , & self . clients , & self . item_manager , & self . level_table ) ? . into_iter ( ) )
} ,
RecvShipPacket ::Message ( msg ) = > {
self . message ( id , msg ) . await ?
@ -536,41 +620,50 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
self . direct_message ( id , msg ) . await ?
} ,
RecvShipPacket ::PlayerChat ( msg ) = > {
Box ::new ( handler ::communication ::player_chat ( id , msg , & self . client_location , & self . clients ) ? . into_iter ( ) )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
Box ::new ( handler ::communication ::player_chat ( id , msg , & block . client_location , & self . clients ) ? . into_iter ( ) )
} ,
RecvShipPacket ::CreateRoom ( create_room ) = > {
handler ::room ::create_room ( id , create_room , & mut self . client_location , & mut self . clients , & mut self . item_manager , & mut self . rooms ) ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::create_room ( id , create_room , & mut block . client_location , & mut self . clients , & mut self . item_manager , & mut block . rooms ) ?
} ,
RecvShipPacket ::RoomNameRequest ( _req ) = > {
handler ::room ::room_name_request ( id , & self . client_location , & self . rooms )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::room_name_request ( id , & block . client_location , & block . rooms )
} ,
RecvShipPacket ::UpdateConfig ( pkt ) = > {
handler ::settings ::update_config ( id , pkt , & mut self . clients , & mut self . entity_gateway ) . await
} ,
RecvShipPacket ::ViewInfoboardRequest ( _pkt ) = > {
handler ::communication ::request_infoboard ( id , & self . client_location , & self . clients )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::communication ::request_infoboard ( id , & block . client_location , & self . clients )
} ,
RecvShipPacket ::WriteInfoboard ( pkt ) = > {
handler ::communication ::write_infoboard ( id , pkt , & mut self . clients , & mut self . entity_gateway ) . await
} ,
RecvShipPacket ::RoomListRequest ( _req ) = > {
handler ::room ::request_room_list ( id , & self . client_location , & self . rooms )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::request_room_list ( id , & block . client_location , & block . rooms )
} ,
RecvShipPacket ::Like62ButCooler ( cool62 ) = > {
handler ::room ::cool_62 ( id , cool62 , & self . client_location )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::cool_62 ( id , cool62 , & block . client_location )
} ,
RecvShipPacket ::ClientCharacterData ( _ ) = > {
// TOOD: validate this in some way?
Box ::new ( None . into_iter ( ) )
} ,
RecvShipPacket ::DoneBursting ( _ ) = > {
handler ::room ::done_bursting ( id , & self . client_location , & mut self . rooms )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::done_bursting ( id , & block . client_location , & mut block . rooms )
} ,
RecvShipPacket ::DoneBursting2 ( _ ) = > {
handler ::room ::done_bursting ( id , & self . client_location , & mut self . rooms )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::room ::done_bursting ( id , & block . client_location , & mut block . rooms )
} ,
RecvShipPacket ::LobbySelect ( pkt ) = > {
Box ::new ( handler ::lobby ::change_lobby ( id , pkt . lobby , & mut self . client_location , & self . clients , & mut self . item_manager , & self . level_table , & mut self . rooms , & mut self . entity_gateway ) . await ? . into_iter ( ) )
let block = self . blocks . with_client ( id , & self . clients ) ? ;
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 ( ) )
} ,
RecvShipPacket ::RequestQuestList ( _ ) = > {
handler ::quest ::send_quest_category_list ( id , & self . quests ) ?
@ -582,7 +675,8 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
handler ::quest ::quest_chunk_ack ( id , quest_chunk_ack , & self . quests ) ?
} ,
RecvShipPacket ::DoneLoadingQuest ( _ ) = > {
handler ::quest ::done_loading_quest ( id , & mut self . clients , & self . client_location ) ?
let block = self . blocks . with_client ( id , & self . clients ) ? ;
handler ::quest ::done_loading_quest ( id , & mut self . clients , & block . client_location ) ?
} ,
RecvShipPacket ::FullCharacterData ( _full_character_data ) = > {
Box ::new ( None . into_iter ( ) )
@ -590,30 +684,40 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
RecvShipPacket ::SaveOptions ( save_options ) = > {
handler ::settings ::save_options ( id , save_options , & mut self . clients , & mut self . entity_gateway ) . await
} ,
RecvShipPacket ::RequestShipList ( _ ) = > {
handler ::ship ::ship_list ( id , & self . ship_list )
} ,
RecvShipPacket ::RequestShipBlockList ( _ ) = > {
handler ::ship ::block_list ( id , & self . name , self . blocks . 0. len ( ) )
}
} )
}
async fn on_disconnect ( & mut self , id : ClientId ) -> Result < Vec < ( ClientId , SendShipPacket ) > , anyhow ::Error > {
// TODO: don't unwrap!
let client = self . clients . get ( & id ) . ok_or ( ShipError ::ClientNotFound ( id ) ) ? ;
let area_client = self . client_location . get_local_client ( id ) ? ;
let neighbors = self . client_location . get_client_neighbors ( id ) ? ;
let block = self . blocks . with_client ( id , & self . clients ) ? ;
let area_client = block . client_location . get_local_client ( id ) ? ;
let neighbors = block . client_location . get_client_neighbors ( id ) ? ;
let pkt = match self . client_location . get_area ( id ) ? {
let pkt = match block . client_location . get_area ( id ) ? {
RoomLobby ::Room ( room ) = > {
if neighbors . len ( ) = = 0 {
self . rooms [ room . 0 ] = None ;
block . rooms [ room . 0 ] = None ;
}
let leader = self . client_location . get_room_leader ( room ) . unwrap ( ) ;
let leader = block . client_location . get_room_leader ( room ) ? ;
SendShipPacket ::LeaveRoom ( LeaveRoom ::new ( area_client . local_client . id ( ) , leader . local_client . id ( ) ) )
} ,
RoomLobby ::Lobby ( lobby ) = > {
let leader = self . client_location . get_lobby_leader ( lobby ) . unwrap ( ) ;
let leader = block . client_location . get_lobby_leader ( lobby ) ? ;
SendShipPacket ::LeaveLobby ( LeaveLobby ::new ( area_client . local_client . id ( ) , leader . local_client . id ( ) ) )
}
} ;
self . client_location . remove_client_from_area ( id ) ;
if let Some ( shipgate_sender ) = self . shipgate_sender . as_ref ( ) {
shipgate_sender ( ShipMessage ::RemoveUser ( client . user . id . clone ( ) ) ) ;
}
block . client_location . remove_client_from_area ( id ) ;
self . item_manager . remove_character_from_room ( & client . character ) ;
if let Some ( mut client ) = self . clients . remove ( & id ) {
@ -642,11 +746,28 @@ impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> {
ip : self . ip . clone ( ) ,
port : self . port ,
block_count : 2 ,
} ) ) ]
} ) ) ,
( id , ShipMessage ::RequestShipList )
]
}
async fn action ( & mut self , _id : ServerId , _msg : Self ::RecvMessage ) -> Result < Vec < ( ServerId , Self ::SendMessage ) > , Self ::Error > {
Ok ( Vec ::new ( ) )
async fn action ( & mut self , id : ServerId , msg : Self ::RecvMessage ) -> Result < Vec < ( ServerId , Self ::SendMessage ) > , Self ::Error > {
match msg {
LoginMessage ::SendMail { . . } = > {
Ok ( Vec ::new ( ) )
} ,
LoginMessage ::ShipList { ships } = > {
self . ship_list = ships ;
Ok ( Vec ::new ( ) )
} ,
LoginMessage ::RequestUsers = > {
Ok ( self . clients . iter ( )
. map ( | ( _ , client ) | {
( id , ShipMessage ::AddUser ( client . user . id . clone ( ) ) )
} )
. collect ( ) )
}
}
}
async fn on_disconnect ( & mut self , _id : ServerId ) -> Vec < ( ServerId , Self ::SendMessage ) > {