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