move interserver handler from login -> character and handle new ship messages
This commit is contained in:
		
							parent
							
								
									2926938201
								
							
						
					
					
						commit
						c8059edb42
					
				| @ -1,3 +1,4 @@ | ||||
| use std::net::Ipv4Addr; | ||||
| use std::time::SystemTime; | ||||
| use log::{info}; | ||||
| 
 | ||||
| @ -5,6 +6,7 @@ use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, | ||||
| use elseware::login::login::LoginServerState; | ||||
| use elseware::login::character::CharacterServerState; | ||||
| use elseware::ship::ship::ShipServerState; | ||||
| use elseware::ship::ship::ShipServerStateBuilder; | ||||
| use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity}; | ||||
| use elseware::entity::gateway::{EntityGateway, InMemoryGateway}; | ||||
| use elseware::entity::character::NewCharacterEntity; | ||||
| @ -196,18 +198,41 @@ fn main() { | ||||
|         let thread_entity_gateway = entity_gateway.clone(); | ||||
|         info!("[auth] starting server"); | ||||
|         let login_state = LoginServerState::new(thread_entity_gateway); | ||||
|         let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT, elseware::login::login::COMMUNICATION_PORT); | ||||
|         let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT); | ||||
| 
 | ||||
|         let thread_entity_gateway = entity_gateway.clone(); | ||||
|         info!("[character] starting server"); | ||||
|         let char_state = CharacterServerState::new(thread_entity_gateway); | ||||
|         let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT); | ||||
|         let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT); | ||||
| 
 | ||||
|         let thread_entity_gateway = entity_gateway.clone(); | ||||
|         info!("[ship] starting server"); | ||||
|         let ship_state = ShipServerState::new(thread_entity_gateway); | ||||
|         let ship_state = ShipServerStateBuilder::new() | ||||
|             .name("Sona-Nyl".into()) | ||||
|             .ip(Ipv4Addr::new(127,0,0,1)) | ||||
|             .port(elseware::ship::ship::SHIP_PORT) | ||||
|             .gateway(thread_entity_gateway) | ||||
|             .build(); | ||||
|         let ship_loop = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT); | ||||
| 
 | ||||
|         futures::future::join_all(vec![patch_loop, login_loop, character_loop, ship_loop]).await; | ||||
|         let thread_entity_gateway = entity_gateway.clone(); | ||||
|         let ship_state = ShipServerStateBuilder::new() | ||||
|             .name("Dylath-Leen".into()) | ||||
|             .ip(Ipv4Addr::new(127,0,0,1)) | ||||
|             .port(elseware::ship::ship::SHIP_PORT+2000) | ||||
|             .gateway(thread_entity_gateway) | ||||
|             .build(); | ||||
|         let ship_loop2 = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT+2000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT); | ||||
| 
 | ||||
|         let thread_entity_gateway = entity_gateway.clone(); | ||||
|         let ship_state = ShipServerStateBuilder::new() | ||||
|             .name("Thalarion".into()) | ||||
|             .ip(Ipv4Addr::new(127,0,0,1)) | ||||
|             .port(elseware::ship::ship::SHIP_PORT+3000) | ||||
|             .gateway(thread_entity_gateway) | ||||
|             .build(); | ||||
|         let ship_loop3 = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT+3000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT); | ||||
| 
 | ||||
|         futures::future::join_all(vec![patch_loop, login_loop, character_loop, ship_loop, ship_loop2, ship_loop3]).await; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| @ -1,17 +1,20 @@ | ||||
| use std::net::Ipv4Addr; | ||||
| use serde::{Serialize, Deserialize}; | ||||
| use serde::de::DeserializeOwned; | ||||
| use crate::entity::character::CharacterEntityId; | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] | ||||
| #[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub struct ServerId(pub usize); | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct AuthToken(pub String); | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct Ship { | ||||
|     name: String, | ||||
|     ip: String, | ||||
|     port: u16, | ||||
|     pub name: String, | ||||
|     //pub ip: String,
 | ||||
|     pub ip: Ipv4Addr, | ||||
|     pub port: u16, | ||||
|     pub block_count: u32, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
|  | ||||
| @ -14,7 +14,6 @@ use crate::common::mainloop::client::client_accept_mainloop; | ||||
| pub use crate::common::mainloop::client::NetworkError; | ||||
| 
 | ||||
| use crate::patch::patch::PatchServerState; | ||||
| use crate::login::login::LoginServerState; | ||||
| use crate::login::character::CharacterServerState; | ||||
| use crate::ship::ship::ShipServerState; | ||||
| use crate::entity::gateway::entitygateway::EntityGateway; | ||||
| @ -181,7 +180,7 @@ where | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| pub fn login_listen_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<LoginServerState<EG>>>, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn login_listen_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<CharacterServerState<EG>>>, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
|     Box::pin(async_std::task::spawn(async move { | ||||
|         let listener = async_std::net::TcpListener::bind(&std::net::SocketAddr::from((std::net::Ipv4Addr::new(0,0,0,0), port))).await.unwrap(); | ||||
|         let mut id = 0; | ||||
|  | ||||
| @ -31,17 +31,17 @@ pub fn patch_mainloop(patch_state: PatchServerState, patch_port: u16) -> Pin<Box | ||||
|     Box::pin(client_mainloop) | ||||
| } | ||||
| 
 | ||||
| pub fn login_mainloop<EG: EntityGateway + 'static>(login_state: LoginServerState<EG>, login_port: u16, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn login_mainloop<EG: EntityGateway + 'static>(login_state: LoginServerState<EG>, login_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
|     let login_state = Arc::new(Mutex::new(login_state)); | ||||
|     let client_mainloop = client_accept_mainloop(login_state.clone(), login_port); | ||||
|     let ship_communication_mainloop = login_listen_mainloop(login_state.clone(), comm_port); | ||||
|     Box::pin(join_all(vec![client_mainloop, ship_communication_mainloop]).map(|_| ())) | ||||
|     Box::pin(client_mainloop) | ||||
| } | ||||
| 
 | ||||
| pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: CharacterServerState<EG>, character_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: CharacterServerState<EG>, character_port: u16, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
|     let character_state = Arc::new(Mutex::new(character_state)); | ||||
|     let client_mainloop = client_accept_mainloop(character_state, character_port); | ||||
|     Box::pin(client_mainloop) | ||||
|     let client_mainloop = client_accept_mainloop(character_state.clone(), character_port); | ||||
|     let ship_communication_mainloop = login_listen_mainloop(character_state.clone(), comm_port); | ||||
|     Box::pin(join_all(vec![client_mainloop, ship_communication_mainloop]).map(|_| ())) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| #![allow(dead_code, unused_assignments)] | ||||
| use std::io::Read; | ||||
| use std::collections::HashMap; | ||||
| use std::collections::{BTreeMap, HashMap}; | ||||
| use std::net::Ipv4Addr; | ||||
| use std::str::FromStr; | ||||
| 
 | ||||
| use rand::Rng; | ||||
| use crc::{crc32, Hasher32}; | ||||
| @ -13,6 +15,7 @@ use libpso::character::character; | ||||
| 
 | ||||
| use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; | ||||
| use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; | ||||
| use crate::common::interserver::{ServerId, InterserverActor, LoginMessage, ShipMessage, Ship}; | ||||
| use crate::common::leveltable::CharacterLevelTable; | ||||
| use libpso::{utf8_to_array, utf8_to_utf16_array}; | ||||
| 
 | ||||
| @ -162,14 +165,14 @@ impl ClientState { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct Ship { | ||||
| /*struct Ship {
 | ||||
|     flags: u32, | ||||
|     name: String, | ||||
|     ip: [u8; 4], | ||||
|     port: u16, | ||||
| } | ||||
| }*/ | ||||
| 
 | ||||
| impl Ship { | ||||
| /*impl Ship {
 | ||||
|     fn new(name: &str, ip: [u8; 4], port: u16) -> Ship { | ||||
|         Ship { | ||||
|             flags: 0, | ||||
| @ -178,14 +181,14 @@ impl Ship { | ||||
|             port: port, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| }*/ | ||||
| 
 | ||||
| pub struct CharacterServerState<EG: EntityGateway> { | ||||
|     entity_gateway: EG, | ||||
|     param_header: ParamDataHeader, | ||||
|     param_data: Vec<u8>, | ||||
|     clients: HashMap<ClientId, ClientState>, | ||||
|     ships: Vec<Ship>, | ||||
|     ships: BTreeMap<ServerId, Ship>, | ||||
|     level_table: CharacterLevelTable, | ||||
| } | ||||
| 
 | ||||
| @ -293,16 +296,16 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | ||||
|     pub fn new(entity_gateway: EG) -> CharacterServerState<EG> { | ||||
|         let (param_header, param_data) = generate_param_data("data/param/"); | ||||
| 
 | ||||
|         let ships = vec![Ship::new("Sona-Nyl", [127,0,0,1], 23423), | ||||
|         /*let ships = vec![Ship::new("Sona-Nyl", [127,0,0,1], 23423),
 | ||||
|                          Ship::new("Dylath-Leen", [127,0,0,1], 23424), | ||||
|                          Ship::new("Thalarion", [127,0,0,1], 23425), | ||||
|         ]; | ||||
|         ];*/ | ||||
|         CharacterServerState { | ||||
|             entity_gateway: entity_gateway, | ||||
|             param_header: param_header, | ||||
|             param_data: param_data, | ||||
|             clients: HashMap::new(), | ||||
|             ships: ships, | ||||
|             ships: BTreeMap::new(), | ||||
|             level_table: CharacterLevelTable::new(), | ||||
|         } | ||||
|     } | ||||
| @ -326,10 +329,10 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | ||||
| 
 | ||||
|     fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result<Vec<SendCharacterPacket>, CharacterError> { | ||||
|         Ok(vec![SendCharacterPacket::Timestamp(Timestamp::new(chrono::Utc::now())), | ||||
|                 SendCharacterPacket::ShipList(ShipList::new(self.ships.iter().enumerate().map(|(i, s)| { | ||||
|                 SendCharacterPacket::ShipList(ShipList::new(self.ships.iter().map(|(i, s)| { | ||||
|                     ShipListEntry { | ||||
|                         menu: SHIP_MENU_ID, | ||||
|                         item: i as u32, | ||||
|                         item: i.0 as u32, | ||||
|                         flags: 0, | ||||
|                         name: utf8_to_utf16_array!(s.name, 0x11) | ||||
|                     } | ||||
| @ -489,9 +492,9 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | ||||
|            return Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item)); | ||||
|         } | ||||
| 
 | ||||
|         let ship = self.ships.get(menuselect.item as usize) | ||||
|         let ship = self.ships.get(&ServerId(menuselect.item as usize)) | ||||
|                              .ok_or(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; | ||||
|         Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip), ship.port))]) | ||||
|         Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip.octets()), ship.port))]) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -566,6 +569,32 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> InterserverActor for CharacterServerState<EG> { | ||||
|     type SendMessage = LoginMessage; | ||||
|     type RecvMessage = ShipMessage; | ||||
|     type Error = (); | ||||
| 
 | ||||
|     async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||
|         Vec::new() | ||||
|     } | ||||
| 
 | ||||
|     async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> { | ||||
|         match msg { | ||||
|             ShipMessage::Authenticate(auth_token) => {}, | ||||
|             ShipMessage::NewShip(new_ship) => { | ||||
|                 self.ships.insert(id, new_ship); | ||||
|             }, | ||||
|             _ => {} | ||||
|         } | ||||
|         Ok(Vec::new()) | ||||
|     } | ||||
| 
 | ||||
|     async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||
|         Vec::new() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn new_character_from_preview(user: &UserAccountEntity, preview: &CharacterPreview) -> NewCharacterEntity { | ||||
|     let mut character = NewCharacterEntity::new(user.id); | ||||
|  | ||||
| @ -12,7 +12,6 @@ use libpso::util::array_to_utf8; | ||||
| 
 | ||||
| use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; | ||||
| use crate::common::serverstate::{SendServerPacket,  RecvServerPacket, ServerState, OnConnect, ClientId}; | ||||
| use crate::common::interserver::{ServerId, InterserverActor, LoginMessage, ShipMessage}; | ||||
| 
 | ||||
| use crate::entity::gateway::EntityGateway; | ||||
| use crate::entity::account::{UserAccountEntity}; | ||||
| @ -141,26 +140,6 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> InterserverActor for LoginServerState<EG> { | ||||
|     type SendMessage = LoginMessage; | ||||
|     type RecvMessage = ShipMessage; | ||||
|     type Error = (); | ||||
| 
 | ||||
|     async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||
|         Vec::new() | ||||
|     } | ||||
| 
 | ||||
|     async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> { | ||||
|         Ok(Vec::new()) | ||||
|     } | ||||
| 
 | ||||
|     async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||
|         Vec::new() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use std::time::SystemTime; | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| #![allow(dead_code, unused_must_use)] | ||||
| use std::net::Ipv4Addr; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| use rand::Rng; | ||||
| @ -15,7 +16,7 @@ use libpso::packet::ship::{BLOCK_MENU_ID, ROOM_MENU_ID}; | ||||
| use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; | ||||
| use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; | ||||
| use crate::common::leveltable::CharacterLevelTable; | ||||
| use crate::common::interserver::{ServerId, InterserverActor, LoginMessage, ShipMessage}; | ||||
| use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage}; | ||||
| 
 | ||||
| use crate::entity::gateway::EntityGateway; | ||||
| use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; | ||||
| @ -247,6 +248,58 @@ impl ClientState { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ShipServerStateBuilder<EG: EntityGateway> { | ||||
|     entity_gateway: Option<EG>, | ||||
|     name: Option<String>, | ||||
|     ip: Option<Ipv4Addr>, | ||||
|     port: Option<u16>, | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> ShipServerStateBuilder<EG> { | ||||
|     pub fn new() -> ShipServerStateBuilder<EG> { | ||||
|         ShipServerStateBuilder { | ||||
|             entity_gateway: None, | ||||
|             name: None, | ||||
|             ip: None, | ||||
|             port: None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder<EG> { | ||||
|         self.entity_gateway = Some(entity_gateway); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn name(mut self, name: String) -> ShipServerStateBuilder<EG> { | ||||
|         self.name = Some(name); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn ip(mut self, ip: Ipv4Addr) -> ShipServerStateBuilder<EG> { | ||||
|         self.ip = Some(ip); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn port(mut self, port: u16) -> ShipServerStateBuilder<EG> { | ||||
|         self.port = Some(port); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn build(self) -> ShipServerState<EG> { | ||||
|         ShipServerState { | ||||
|             entity_gateway: self.entity_gateway.unwrap(), | ||||
|             clients: HashMap::new(), | ||||
|             client_location: ClientLocation::new(), | ||||
|             level_table: CharacterLevelTable::new(), | ||||
|             name: self.name.unwrap(), | ||||
|             rooms: [None; MAX_ROOMS], | ||||
|             item_manager: items::ItemManager::new(), | ||||
|             quests: quests::load_quests("data/quests.toml".into()).unwrap(), | ||||
|             ip: self.ip.unwrap(), | ||||
|             port: self.port.unwrap(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ShipServerState<EG: EntityGateway> { | ||||
|     entity_gateway: EG, | ||||
| @ -257,10 +310,12 @@ pub struct ShipServerState<EG: EntityGateway> { | ||||
|     pub rooms: Rooms, | ||||
|     item_manager: items::ItemManager, | ||||
|     quests: quests::QuestList, | ||||
|     ip: Ipv4Addr, | ||||
|     port: u16, | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|     pub fn new(entity_gateway: EG) -> ShipServerState<EG> { | ||||
|     /*pub fn new(entity_gateway: EG) -> ShipServerState<EG> {
 | ||||
|         ShipServerState { | ||||
|             entity_gateway: entity_gateway, | ||||
|             clients: HashMap::new(), | ||||
| @ -271,7 +326,7 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|             item_manager: items::ItemManager::new(), | ||||
|             quests: quests::load_quests("data/quests.toml".into()).unwrap(), | ||||
|         } | ||||
|     } | ||||
|     }*/ | ||||
| 
 | ||||
|     async fn message(&mut self, id: ClientId, msg: &Message) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> { | ||||
|         match &msg.msg { | ||||
| @ -500,7 +555,12 @@ impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> { | ||||
|     type Error = (); | ||||
| 
 | ||||
|     async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||
|         Vec::new() | ||||
|         vec![ /* ShipMessage::Authenticate(AuthToken("hi".into())),  */ (id, ShipMessage::NewShip(Ship { | ||||
|             name: self.name.clone(), | ||||
|             ip: self.ip.clone(), | ||||
|             port: self.port, | ||||
|             block_count: 2, | ||||
|         })) ] | ||||
|     } | ||||
| 
 | ||||
|     async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user