@ -70,6 +70,7 @@ pub enum ShipError {
GatewayError ( #[ from ] GatewayError ) ,
UnknownMonster ( crate ::ship ::monster ::MonsterType ) ,
InvalidShip ( usize ) ,
InvalidBlock ( usize ) ,
}
#[ derive(Debug) ]
@ -242,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>,
@ -310,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 > {
@ -320,6 +322,7 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
ip : None ,
port : None ,
auth_token : None ,
num_blocks : 2 ,
}
}
@ -348,19 +351,26 @@ 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 ,
@ -368,20 +378,44 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
}
}
struct Block {
client_location : Box < ClientLocation > ,
rooms : Box < Rooms > ,
}
impl Default for Block {
fn default ( ) -> Block {
Block {
client_location : Box ::new ( ClientLocation ::default ( ) ) ,
rooms : Box ::new ( [ None ; MAX_ROOMS ] ) ,
}
}
}
struct Blocks ( 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 > ,
blocks : Blocks ,
ip : Ipv4Addr ,
port : u16 ,
shops : Box < ItemShops > ,
auth_token : AuthToken ,
auth_token : AuthToken ,
ship_list : Vec < Ship > ,
shipgate_sender : Option < Box < dyn Fn ( ShipMessage ) + Send + Sync > > ,
}
@ -398,34 +432,41 @@ impl<EG: EntityGateway> ShipServerState<EG> {
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 ?
@ -438,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 ( ) ) )
} ) )
@ -450,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 ( ) ) )
@ -509,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 . shipgate_sender , & 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 {
@ -518,37 +569,41 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
}
} ,
RecvShipPacket ::MenuSelect ( menuselect ) = > {
let block = self . blocks . with_client ( id , & self . clients ) ? ;
match menuselect . menu {
SHIP_MENU_ID = > handler ::ship ::selected_ship ( id , menuselect , & self . ship_list ) ? ,
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 ) ? ,
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 ?
@ -557,41 +612,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 ) ?
@ -603,7 +667,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 ( ) )
@ -622,19 +687,20 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
async fn on_disconnect ( & mut self , id : ClientId ) -> Result < Vec < ( ClientId , SendShipPacket ) > , anyhow ::Error > {
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 ) ? ;
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 ) ? ;
let leader = block . client_location . get_lobby_leader ( lobby ) ? ;
SendShipPacket ::LeaveLobby ( LeaveLobby ::new ( area_client . local_client . id ( ) , leader . local_client . id ( ) ) )
}
} ;
@ -643,7 +709,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
shipgate_sender ( ShipMessage ::RemoveUser ( client . user . id . clone ( ) ) ) ;
}
self . client_location . remove_client_from_area ( id ) ;
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 ) {