Compare commits
4 Commits
fdce44cdd8
...
192ff967e6
Author | SHA1 | Date | |
---|---|---|---|
192ff967e6 | |||
4b1ded6f7d | |||
9843274bd8 | |||
3a50cd7ba1 |
@ -1,12 +1,10 @@
|
||||
use log::{info};
|
||||
//use elseware::entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::login::login::LoginServerState;
|
||||
use elseware::login::character::CharacterServerState;
|
||||
//use elseware::common::mainloop::{login_mainloop, character_mainloop};
|
||||
//use elseware::common::interserver::AuthToken;
|
||||
use elseware::common::interserver::AuthToken;
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
let colors = fern::colors::ColoredLevelConfig::new()
|
||||
.error(fern::colors::Color::Red)
|
||||
.warn(fern::colors::Color::Yellow)
|
||||
@ -38,16 +36,23 @@ fn main() {
|
||||
let shipgate_token = std::env::var("SHIPGATE_TOKEN").unwrap();
|
||||
let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let login_state = LoginServerState::new(thread_entity_gateway, charserv_ip);
|
||||
let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT);
|
||||
|
||||
let login_state = LoginServerState::new(entity_gateway.clone(), charserv_ip);
|
||||
let login_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
});
|
||||
|
||||
let char_state = CharacterServerState::new(entity_gateway, AuthToken(shipgate_token));
|
||||
let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT);
|
||||
let sub_char_state = char_state.clone();
|
||||
let character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
});
|
||||
|
||||
let inter_character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_listen(char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
info!("[auth/character] starting server");
|
||||
async_std::task::block_on(async move {
|
||||
futures::future::join_all(vec![login_loop, character_loop]).await
|
||||
futures::future::join_all(vec![login_loop, character_loop, inter_character_loop]).await
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
144
src/bin/main.rs
144
src/bin/main.rs
@ -1,21 +1,18 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use log::{info};
|
||||
use async_std::channel;
|
||||
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
||||
use elseware::common::interserver::AuthToken;
|
||||
use elseware::login::login::LoginServerState;
|
||||
use elseware::login::character::CharacterServerState;
|
||||
//use elseware::ship::ship::ShipServerStateBuilder;
|
||||
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
//use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||
use elseware::entity::character::NewCharacterEntity;
|
||||
use elseware::entity::item::{NewItemEntity, ItemDetail, InventoryItemEntity};
|
||||
use elseware::common::interserver::AuthToken;
|
||||
|
||||
use elseware::entity::item;
|
||||
use elseware::common::mainloop::*;
|
||||
|
||||
fn setup_logger() {
|
||||
let colors = fern::colors::ColoredLevelConfig::new()
|
||||
@ -327,60 +324,14 @@ fn main() {
|
||||
};
|
||||
entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap();
|
||||
|
||||
let inventory = item::InventoryEntity::new(vec![InventoryItemEntity::from(item0), item1.into(), item2_w.into(), item3.into(), item4.into(), item5_m.into(), item6.into(), item6_1.into(), item7_a.into(), item8_s.into(), item9_u0.into(), item10_u1.into(), item11_u2.into(), item12_u3.into(), item13.into(), item14.into(), monomates.into()]);
|
||||
let inventory = item::InventoryEntity::new(vec![InventoryItemEntity::from(item0), item1.into(), item2_w.into(), item3.into(),
|
||||
item4.into(), item5_m.into(), item6.into(), item6_1.into(), item7_a.into(),
|
||||
item8_s.into(), item9_u0.into(), item10_u1.into(), item11_u2.into(), item12_u3.into(),
|
||||
item13.into(), item14.into(), monomates.into()]);
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap();
|
||||
entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), &item::BankName("".into())).await.unwrap();
|
||||
}
|
||||
|
||||
/*
|
||||
info!("[patch] starting server");
|
||||
let patch_config = load_config();
|
||||
let patch_motd = load_motd();
|
||||
let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str());
|
||||
let patch_state = Box::new(PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd));
|
||||
let patch_loop = patch_mainloop(*patch_state, patch_config.port);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
info!("[auth] starting server");
|
||||
let login_state = Box::new(LoginServerState::new(thread_entity_gateway, "127.0.0.1".parse().unwrap()));
|
||||
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 = Box::new(CharacterServerState::new(thread_entity_gateway, AuthToken("".into())));
|
||||
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 = Box::new(ShipServerStateBuilder::default()
|
||||
.name("US/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);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = Box::new(ShipServerStateBuilder::default()
|
||||
.name("EU/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 = Box::new(ShipServerStateBuilder::default()
|
||||
.name("JP/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;
|
||||
*/
|
||||
|
||||
info!("[patch] starting server");
|
||||
let patch_config = load_config();
|
||||
let patch_motd = load_motd();
|
||||
@ -391,15 +342,13 @@ fn main() {
|
||||
});
|
||||
|
||||
info!("[auth] starting server");
|
||||
let auth_entity_gateway = entity_gateway.clone();
|
||||
let login_state = LoginServerState::new(auth_entity_gateway, "127.0.0.1".parse().unwrap());
|
||||
let login_state = LoginServerState::new(entity_gateway.clone(), "127.0.0.1".parse().unwrap());
|
||||
let login_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(login_state, elseware::login::login::LOGIN_PORT).await;
|
||||
});
|
||||
|
||||
info!("[character] starting server");
|
||||
let character_entity_gateway = entity_gateway.clone();
|
||||
let char_state = CharacterServerState::new(character_entity_gateway, AuthToken("".into()));
|
||||
let char_state = CharacterServerState::new(entity_gateway.clone(), AuthToken("".into()));
|
||||
let sub_char_state = char_state.clone();
|
||||
let character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_char_state, elseware::login::character::CHARACTER_PORT).await;
|
||||
@ -409,66 +358,55 @@ fn main() {
|
||||
let inter_character_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_listen(sub_char_state, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
/*
|
||||
let inter_character_loop_recv = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_interserver_receiver(char_state, elseware::login::character::COMMUNICATION_PORT).await
|
||||
});
|
||||
let inter_character_loop_send = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_interserver_sender(char_state, interserver_rx).await
|
||||
*/
|
||||
|
||||
let ship_entity_gateway = entity_gateway.clone();
|
||||
info!("[ship] starting server");
|
||||
|
||||
//let (interserver_tx, interserver_rx) = async_std::channel::unbounded();
|
||||
/*
|
||||
info!("[ship] starting servers");
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
.name("US/Sona-Nyl".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT)
|
||||
.gateway(thread_entity_gateway)
|
||||
.interserver_sender(|msg| async move {
|
||||
interserver_tx.send(msg).await
|
||||
})
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT);
|
||||
let ship_loop1 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
});
|
||||
/*
|
||||
/*, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT*/
|
||||
let inter_ship_loop = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_interserver_receiver(ship_state, elseware::login::login::COMMUNICATION_PORT);
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop1 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
*/
|
||||
|
||||
let ship_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = Box::new(ShipServerStateBuilder::default()
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
.name("EU/Dylath-Leen".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+2000)
|
||||
.gateway(thread_entity_gateway)
|
||||
.build());
|
||||
.port(elseware::ship::ship::SHIP_PORT+200)
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop2 = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT);
|
||||
let ship_loop2 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+2000).await;
|
||||
});
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop2 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = Box::new(ShipServerStateBuilder::default()
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
.name("JP/Thalarion".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+3000)
|
||||
.gateway(thread_entity_gateway)
|
||||
.build());
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop3 = async_std::task::spawn(|| async {
|
||||
crate::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT);
|
||||
let ship_loop3 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT+3000).await;
|
||||
});
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let inter_ship_loop3 = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(sub_ship_state, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
futures::future::join_all(vec![patch_loop, login_loop, character_loop, ship_loop, ship_loop2, ship_loop3]).await;
|
||||
*/
|
||||
|
||||
futures::future::join_all(vec![patch_loop, login_loop, character_loop, inter_character_loop]).await;
|
||||
|
||||
futures::future::join_all(vec![patch_loop, login_loop, character_loop, inter_character_loop,
|
||||
ship_loop1, ship_loop2, ship_loop3,
|
||||
inter_ship_loop1, inter_ship_loop2, inter_ship_loop3]).await;
|
||||
});
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config_env, load_motd};
|
||||
use log::{info};
|
||||
//use elseware::common::mainloop::patch_mainloop;
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
info!("[patch] starting server");
|
||||
let patch_config = load_config_env();
|
||||
let patch_motd = load_motd();
|
||||
let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str());
|
||||
let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd);
|
||||
let patch_loop = patch_mainloop(patch_state, patch_config.port);
|
||||
|
||||
let patch_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(patch_state, patch_config.port).await;
|
||||
});
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
patch_loop.await
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use log::{info};
|
||||
//use elseware::entity::gateway::postgres::PostgresGateway;
|
||||
//use elseware::ship::ship::ShipServerStateBuilder;
|
||||
//use elseware::common::mainloop::ship_mainloop;
|
||||
//use elseware::common::interserver::AuthToken;
|
||||
use elseware::entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
use elseware::common::interserver::AuthToken;
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
let colors = fern::colors::ColoredLevelConfig::new()
|
||||
.error(fern::colors::Color::Red)
|
||||
.warn(fern::colors::Color::Yellow)
|
||||
@ -38,6 +36,7 @@ fn main() {
|
||||
let shipgate_token = std::env::var("SHIPGATE_TOKEN").unwrap();
|
||||
let ship_name = std::env::var("SHIP_NAME").unwrap().parse().unwrap();
|
||||
let ip = std::env::var("SELF_IP").unwrap().parse().unwrap();
|
||||
|
||||
let ship_state = ShipServerStateBuilder::default()
|
||||
.name(ship_name)
|
||||
.ip(ip)
|
||||
@ -47,11 +46,17 @@ fn main() {
|
||||
.build();
|
||||
|
||||
let shipgate_ip = std::env::var("SHIPGATE_IP").unwrap().parse().unwrap();
|
||||
let ship_loop = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT, shipgate_ip, elseware::login::login::COMMUNICATION_PORT);
|
||||
|
||||
|
||||
let sub_ship_state = ship_state.clone();
|
||||
let ship_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
|
||||
});
|
||||
let inter_ship_loop = async_std::task::spawn(async move {
|
||||
elseware::common::mainloop::run_interserver_connect(ship_state, shipgate_ip, elseware::login::login::COMMUNICATION_PORT).await;
|
||||
});
|
||||
|
||||
info!("[auth/character] starting server");
|
||||
async_std::task::block_on(async move {
|
||||
ship_loop.await
|
||||
futures::future::join_all(vec![ship_loop, inter_ship_loop]).await;
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use async_std::sync::Arc;
|
||||
use async_std::channel;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::de::DeserializeOwned;
|
||||
@ -56,6 +55,5 @@ pub trait InterserverActor: Clone {
|
||||
async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)>;
|
||||
async fn on_action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error>;
|
||||
async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)>;
|
||||
//fn set_sender(&mut self, server_id: ServerId, func: Arc<Box<dyn Fn(Self::SendMessage) -> Box<dyn futures::future::Future<Output = ()>>>>);
|
||||
fn set_sender(&mut self, server_id: ServerId, tx: channel::Sender<Self::SendMessage>);
|
||||
async fn set_sender(&mut self, server_id: ServerId, tx: channel::Sender<Self::SendMessage>);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use std::pin::pin;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use async_std::channel;
|
||||
use async_std::io::prelude::{ReadExt, WriteExt};
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use futures::future::Future;
|
||||
use log::{trace, info, warn};
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use async_std::io::prelude::{ReadExt, WriteExt};
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
|
||||
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
||||
use libpso::PacketParseError;
|
||||
@ -42,7 +42,6 @@ impl From<PacketParseError> for NetworkError {
|
||||
|
||||
pub struct PacketReceiver<C: PSOCipher> {
|
||||
socket: async_std::net::TcpStream,
|
||||
//cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
cipher: C,
|
||||
recv_buffer: Vec<u8>,
|
||||
incoming_data: Vec<u8>,
|
||||
@ -115,209 +114,160 @@ impl<C: PSOCipher> PacketReceiver<C> {
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
async fn send_pkt<S: SendServerPacket + Send + std::fmt::Debug>(socket: Arc<async_std::net::TcpStream>,
|
||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>, pkt: S)
|
||||
-> Result<(), NetworkError>
|
||||
async fn recv_loop<STATE, S, R, C, E>(mut state: STATE,
|
||||
socket: async_std::net::TcpStream,
|
||||
client_id: ClientId,
|
||||
cipher: C,
|
||||
clients: Arc<RwLock<HashMap<ClientId, channel::Sender<S>>>>)
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, Cipher=C, PacketError=E> + Send,
|
||||
S: SendServerPacket + Debug + Send,
|
||||
R: RecvServerPacket + Debug + Send,
|
||||
C: PSOCipher + Send,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
let mut pkt_receiver = PacketReceiver::new(socket, cipher);
|
||||
loop {
|
||||
match pkt_receiver.recv_pkts::<R>().await {
|
||||
Ok(pkts) => {
|
||||
for pkt in pkts {
|
||||
info!("[recv from {:?}] {:#?}", client_id, pkt);
|
||||
match state.handle(client_id, pkt).await {
|
||||
Ok(response) => {
|
||||
for resp in response {
|
||||
clients
|
||||
.read()
|
||||
.await
|
||||
.get(&resp.0)
|
||||
.unwrap()
|
||||
.send(resp.1)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client recv {:?}] error {:?} ", client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
match err {
|
||||
NetworkError::ClientDisconnected => {
|
||||
info!("[client recv {:?}] disconnected", client_id);
|
||||
for pkt in state.on_disconnect(client_id).await.unwrap() {
|
||||
clients
|
||||
.read()
|
||||
.await
|
||||
.get(&pkt.0)
|
||||
.unwrap()
|
||||
.send(pkt.1)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
clients
|
||||
.write()
|
||||
.await
|
||||
.remove(&client_id);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
warn!("[client {:?} recv error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn send_pkt<S, C>(socket: &mut async_std::net::TcpStream,
|
||||
cipher: &mut C,
|
||||
pkt: &S)
|
||||
-> Result<(), NetworkError>
|
||||
where
|
||||
S: SendServerPacket + std::fmt::Debug,
|
||||
C: PSOCipher,
|
||||
{
|
||||
let buf = pkt.as_bytes();
|
||||
trace!("[send buf] {:?}", buf);
|
||||
let cbuf = cipher.lock().await.encrypt(&buf)?;
|
||||
let mut ssock = &*socket;
|
||||
ssock.write_all(&cbuf).await?;
|
||||
let cbuf = cipher.encrypt(&buf)?;
|
||||
socket.write_all(&cbuf).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
enum ClientAction<S, R> {
|
||||
NewClient(ClientId, async_std::channel::Sender<S>),
|
||||
Packet(ClientId, R),
|
||||
Disconnect(ClientId),
|
||||
}
|
||||
|
||||
enum ServerStateAction<S> {
|
||||
Cipher(Box<dyn PSOCipher + Send + Sync>, Box<dyn PSOCipher + Send + Sync>),
|
||||
Packet(S),
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
fn client_recv_loop<S, R>(client_id: ClientId,
|
||||
socket: Arc<async_std::net::TcpStream>,
|
||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
server_sender: async_std::channel::Sender<ClientAction<ServerStateAction<S>, R>>,
|
||||
client_sender: async_std::channel::Sender<ServerStateAction<S>>)
|
||||
async fn send_loop<S, C>(mut socket: async_std::net::TcpStream, client_id: ClientId, mut cipher: C, packet_queue: channel::Receiver<S>)
|
||||
where
|
||||
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
R: RecvServerPacket + std::fmt::Debug + Send + 'static,
|
||||
S: SendServerPacket + std::fmt::Debug,
|
||||
C: PSOCipher,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
server_sender.send(ClientAction::NewClient(client_id, client_sender)).await.unwrap();
|
||||
/*
|
||||
let mut pkt_receiver = PacketReceiver::new(*socket, cipher);
|
||||
loop {
|
||||
match packet_queue.recv().await {
|
||||
Ok(pkt) => {
|
||||
if let Err(err) = send_pkt(&mut socket, &mut cipher, &pkt).await {
|
||||
warn!("error sending pkt {:#?} to {:?} {:?}", pkt, client_id, err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
info!("send to {:?} failed: {:?}", client_id, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match pkt_receiver.recv_pkts().await {
|
||||
Ok(pkts) => {
|
||||
for pkt in pkts {
|
||||
info!("[recv from {:?}] {:#?}", client_id, pkt);
|
||||
server_sender.send(ClientAction::Packet(client_id, pkt)).await.unwrap();
|
||||
}
|
||||
pub async fn run_server<STATE, S, R, C, E>(mut state: STATE, port: u16)
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, Cipher=C, PacketError=E> + Send + 'static,
|
||||
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
R: RecvServerPacket + std::fmt::Debug + Send,
|
||||
C: PSOCipher + Send + 'static,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
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;
|
||||
|
||||
let clients = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
loop {
|
||||
let (mut socket, addr) = listener.accept().await.unwrap();
|
||||
id += 1;
|
||||
|
||||
let client_id = crate::common::serverstate::ClientId(id);
|
||||
info!("new client {:?} {:?} {:?}", client_id, socket, addr);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
|
||||
clients
|
||||
.write()
|
||||
.await
|
||||
.insert(client_id, client_tx.clone());
|
||||
|
||||
let mut cipher_in: Option<C> = None;
|
||||
let mut cipher_out: Option<C> = None;
|
||||
|
||||
for action in state.on_connect(client_id).await.unwrap() {
|
||||
match action {
|
||||
OnConnect::Cipher(cin, cout) => {
|
||||
cipher_in = Some(cin);
|
||||
cipher_out = Some(cout);
|
||||
},
|
||||
Err(err) => {
|
||||
match err {
|
||||
NetworkError::ClientDisconnected => {
|
||||
trace!("[client disconnected] {:?}", client_id);
|
||||
server_sender.send(ClientAction::Disconnect(client_id)).await.unwrap();
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
warn!("[client {:?} recv error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
OnConnect::Packet(pkt) => {
|
||||
send_pkt(&mut socket, &mut NullCipher {}, &pkt).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
let rclients = clients.clone();
|
||||
async_std::task::spawn(async move {
|
||||
recv_loop(rstate, rsocket, client_id, cipher_in.unwrap(), rclients).await
|
||||
});
|
||||
|
||||
async_std::task::spawn(async move {
|
||||
send_loop(socket, client_id, cipher_out.unwrap(), client_rx).await
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn client_send_loop<S>(client_id: ClientId,
|
||||
socket: Arc<async_std::net::TcpStream>,
|
||||
cipher_in: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
cipher_out: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
client_receiver: async_std::channel::Receiver<ServerStateAction<S>>)
|
||||
where
|
||||
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
loop {
|
||||
let action = client_receiver.recv().await.unwrap();
|
||||
match action {
|
||||
ServerStateAction::Cipher(inc, outc) => {
|
||||
*cipher_in.lock().await = inc;
|
||||
*cipher_out.lock().await = outc;
|
||||
}
|
||||
ServerStateAction::Packet(pkt) => {
|
||||
info!("[send to {:?}] {:#?}", client_id, pkt);
|
||||
if let Err(err) = send_pkt(socket.clone(), cipher_out.clone(), pkt).await {
|
||||
warn!("[client {:?} send error ] {:?}", client_id, err);
|
||||
}
|
||||
},
|
||||
ServerStateAction::Disconnect => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
||||
server_state_receiver: async_std::channel::Receiver<ClientAction<ServerStateAction<S>, R>>) where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, PacketError=E> + Send + 'static,
|
||||
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
R: RecvServerPacket + std::fmt::Debug + Send + 'static,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
let mut clients = HashMap::new();
|
||||
|
||||
loop {
|
||||
let action = server_state_receiver.recv().await.unwrap();
|
||||
let mut state = state.lock().await;
|
||||
|
||||
match action {
|
||||
ClientAction::NewClient(client_id, sender) => {
|
||||
let actions = state.on_connect(client_id).await;
|
||||
match actions {
|
||||
Ok(actions) => {
|
||||
for action in actions {
|
||||
match action {
|
||||
OnConnect::Cipher((inc, outc)) => {
|
||||
sender.send(ServerStateAction::Cipher(inc, outc)).await.unwrap();
|
||||
},
|
||||
OnConnect::Packet(pkt) => {
|
||||
sender.send(ServerStateAction::Packet(pkt)).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client {:?} state on_connect error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
clients.insert(client_id, sender);
|
||||
},
|
||||
ClientAction::Packet(client_id, pkt) => {
|
||||
let pkts = state.handle(client_id, &pkt).await;
|
||||
match pkts {
|
||||
Ok(pkts) => {
|
||||
for (client_id, pkt) in pkts {
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Packet(pkt)).await.unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client {:?} state handler error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientAction::Disconnect(client_id) => {
|
||||
let pkts = state.on_disconnect(client_id).await;
|
||||
match pkts {
|
||||
Ok(pkts) => {
|
||||
for (client_id, pkt) in pkts {
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Packet(pkt)).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Disconnect).await.unwrap();
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("[client {:?} state on_disconnect error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
pub fn client_accept_mainloop<STATE, S, R, E>(state: Arc<Mutex<STATE>>, client_port: u16) -> Pin<Box<dyn Future<Output = ()>>>
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, PacketError=E> + Send + 'static,
|
||||
S: SendServerPacket + std::fmt::Debug + Send + Sync + 'static,
|
||||
R: RecvServerPacket + std::fmt::Debug + Send + Sync + 'static,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
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), client_port))).await.unwrap();
|
||||
let mut id = 0;
|
||||
|
||||
let (server_state_sender, server_state_receiver) = async_std::channel::bounded(1024);
|
||||
state_client_loop(state, server_state_receiver);
|
||||
|
||||
loop {
|
||||
let (sock, addr) = listener.accept().await.unwrap();
|
||||
id += 1;
|
||||
let client_id = crate::common::serverstate::ClientId(id);
|
||||
|
||||
info!("new client {:?} {:?} {:?}", client_id, sock, addr);
|
||||
|
||||
let (client_sender, client_receiver) = async_std::channel::bounded(64);
|
||||
let socket = Arc::new(sock);
|
||||
let cipher_in: Arc<Mutex<Box<dyn PSOCipher + Send>>> = Arc::new(Mutex::new(Box::new(NullCipher {})));
|
||||
let cipher_out: Arc<Mutex<Box<dyn PSOCipher + Send>>> = Arc::new(Mutex::new(Box::new(NullCipher {})));
|
||||
|
||||
client_recv_loop(client_id, socket.clone(), cipher_in.clone(), server_state_sender.clone(), client_sender);
|
||||
client_send_loop(client_id, socket.clone(), cipher_in.clone(), cipher_out.clone(), client_receiver);
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@ use std::time::Duration;
|
||||
use std::pin::Pin;
|
||||
use futures::future::Future;
|
||||
use log::{info, warn};
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use async_std::io::prelude::{ReadExt, WriteExt};
|
||||
use std::collections::HashMap;
|
||||
use serde::Serialize;
|
||||
@ -17,6 +17,8 @@ use crate::login::character::CharacterServerState;
|
||||
use crate::entity::gateway::entitygateway::EntityGateway;
|
||||
|
||||
use async_std::channel;
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MessageReceiverError {
|
||||
@ -37,7 +39,7 @@ impl MessageReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
async fn recv<R: DeserializeOwned + std::fmt::Debug + Send>(&mut self) -> Result<R, MessageReceiverError> {
|
||||
async fn recv<R: serde::de::DeserializeOwned + std::fmt::Debug>(&mut self) -> Result<R, MessageReceiverError> {
|
||||
let mut size_buf = [0u8; 4];
|
||||
self.socket.read_exact(&mut size_buf).await.map_err(|_| MessageReceiverError::Disconnected)?;
|
||||
let size = u32::from_le_bytes(size_buf) as usize;
|
||||
@ -50,219 +52,182 @@ impl MessageReceiver {
|
||||
Ok(msg)
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
#[derive(Debug)]
|
||||
enum InterserverInputAction<S, R> {
|
||||
NewConnection(ServerId, async_std::channel::Sender<S>),
|
||||
Message(ServerId, R),
|
||||
Disconnect(ServerId),
|
||||
}
|
||||
|
||||
async fn interserver_state_loop<A, S, R>(state: Arc<Mutex<A>>, action_receiver: async_std::channel::Receiver<InterserverInputAction<S, R>>)
|
||||
async fn interserver_recv_loop<STATE, S, R, E>(mut state: STATE, server_id: ServerId, socket: async_std::net::TcpStream, ships: Arc<RwLock<HashMap<ServerId, channel::Sender<S>>>>)
|
||||
where
|
||||
A: InterserverActor<SendMessage=S, RecvMessage=R, Error=()> + Send + 'static,
|
||||
S: Serialize + Send + 'static,
|
||||
R: DeserializeOwned + Send + 'static,
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send,
|
||||
S: serde::Serialize + Debug + Send,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
let mut ships = HashMap::new();
|
||||
let mut msg_receiver = MessageReceiver::new(socket);
|
||||
|
||||
loop {
|
||||
info!("interserver loop");
|
||||
let action = match action_receiver.recv().await {
|
||||
Ok(action) => action,
|
||||
Err(err) => {
|
||||
warn!("error in iterserver state loop {:?}", err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let mut state = state.lock().await;
|
||||
|
||||
match action {
|
||||
InterserverInputAction::NewConnection(server_id, ship_action_sender) => {
|
||||
ships.insert(server_id, ship_action_sender);
|
||||
for (server, action) in state.on_connect(server_id).await {
|
||||
if let Some(sender) = ships.get_mut(&server) {
|
||||
sender.send(action).await.unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
InterserverInputAction::Message(server_id, message) => {
|
||||
let actions = state.action(server_id, message).await;
|
||||
match actions {
|
||||
Ok(actions) => {
|
||||
for (server, action) in actions{
|
||||
if let Some(sender) = ships.get_mut(&server) {
|
||||
sender.send(action).await.unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[server {:?} state handler error] {:?}", server_id, err);
|
||||
}
|
||||
}
|
||||
},
|
||||
InterserverInputAction::Disconnect(server_id) => {
|
||||
let actions = state.on_disconnect(server_id).await;
|
||||
ships.remove(&server_id);
|
||||
for (server, action) in actions {
|
||||
if let Some(sender) = ships.get_mut(&server) {
|
||||
sender.send(action).await.unwrap();
|
||||
loop {
|
||||
match msg_receiver.recv::<R>().await {
|
||||
Ok(msg) => {
|
||||
info!("[interserver recv {:?}] {:?}", server_id, msg);
|
||||
match state.on_action(server_id, msg).await {
|
||||
Ok(response) => {
|
||||
for resp in response {
|
||||
ships
|
||||
.read()
|
||||
.await
|
||||
.get(&resp.0)
|
||||
.unwrap()
|
||||
.send(resp.1)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[interserver recv {:?}] error {:?}", server_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn login_recv_loop<S, R>(server_id: ServerId,
|
||||
socket: async_std::net::TcpStream,
|
||||
state_loop_sender: async_std::channel::Sender<InterserverInputAction<S, R>>,
|
||||
output_loop_sender: async_std::channel::Sender<S>)
|
||||
where
|
||||
S: Serialize + std::fmt::Debug + Send + 'static,
|
||||
R: DeserializeOwned + std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
state_loop_sender.send(InterserverInputAction::NewConnection(server_id, output_loop_sender)).await.unwrap();
|
||||
let mut msg_receiver = MessageReceiver::new(socket);
|
||||
|
||||
loop {
|
||||
info!("login recv loop");
|
||||
match msg_receiver.recv().await {
|
||||
Ok(msg) => {
|
||||
info!("[login recv loop msg] {:?}", msg);
|
||||
state_loop_sender.send(InterserverInputAction::Message(server_id, msg)).await.unwrap();
|
||||
},
|
||||
Err(err) => {
|
||||
if let MessageReceiverError::Disconnected = err {
|
||||
info!("[login recv loop disconnect] {:?}", server_id);
|
||||
state_loop_sender.send(InterserverInputAction::Disconnect(server_id)).await.unwrap();
|
||||
break;
|
||||
}
|
||||
info!("[login recv loop err] {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn interserver_send_loop<S>(server_id: ServerId,
|
||||
mut socket: async_std::net::TcpStream,
|
||||
output_loop_receiver: async_std::channel::Receiver<S>)
|
||||
where
|
||||
S: Serialize + std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
async_std::task::spawn(async move {
|
||||
loop {
|
||||
info!("login send loop");
|
||||
match output_loop_receiver.recv().await {
|
||||
Ok(msg) => {
|
||||
let payload = serde_json::to_string(&msg);
|
||||
if let Ok(payload) = payload {
|
||||
let len_bytes = u32::to_le_bytes(payload.len() as u32);
|
||||
|
||||
if let Err(err) = socket.write_all(&len_bytes).await {
|
||||
warn!("interserver send failed: {:?}", err);
|
||||
break;
|
||||
}
|
||||
if let Err(err) = socket.write_all(payload.as_bytes()).await {
|
||||
warn!("intserserver send failed: {:?}", err);
|
||||
break;
|
||||
},
|
||||
Err(err) => {
|
||||
if let MessageReceiverError::Disconnected = err {
|
||||
info!("[interserver recv {:?}] disconnected", server_id);
|
||||
for (_, _sender) in ships.read().await.iter() {
|
||||
for pkt in state.on_disconnect(server_id).await {
|
||||
ships
|
||||
.read()
|
||||
.await
|
||||
.get(&pkt.0)
|
||||
.unwrap()
|
||||
.send(pkt.1)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("error in send_loop: {:?}, {:?}", server_id, err);
|
||||
ships
|
||||
.write()
|
||||
.await
|
||||
.remove(&server_id);
|
||||
break;
|
||||
}
|
||||
info!("[interserver recv {:?}] error {:?}", server_id, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async fn interserver_send_loop<S>(server_id: ServerId, mut socket: async_std::net::TcpStream, to_send: channel::Receiver<S>)
|
||||
where
|
||||
S: serde::Serialize + std::fmt::Debug,
|
||||
{
|
||||
loop {
|
||||
let msg = to_send.recv().await.unwrap();
|
||||
let payload = serde_json::to_string(&msg);
|
||||
|
||||
|
||||
pub fn login_listen_mainloop<EG: EntityGateway + Clone + '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;
|
||||
|
||||
let (server_state_sender, server_state_receiver) = async_std::channel::bounded(1024);
|
||||
interserver_state_loop(state.clone(), server_state_receiver).await;
|
||||
|
||||
loop {
|
||||
let (socket, addr) = listener.accept().await.unwrap();
|
||||
info!("new ship server: {:?} {:?}", socket, addr);
|
||||
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
let (client_sender, client_receiver) = async_std::channel::bounded(64);
|
||||
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
let local_sender = client_sender.clone();
|
||||
state.set_sender(server_id, Box::new(move |message| {
|
||||
async_std::task::block_on(local_sender.send(message)).unwrap();
|
||||
}))
|
||||
if let Ok(payload) = payload {
|
||||
let len_bytes = u32::to_le_bytes(payload.len() as u32);
|
||||
if let Err(err) = socket.write_all(&len_bytes).await {
|
||||
warn!("[interserver send {:?}] failed: {:?}", server_id, err);
|
||||
break;
|
||||
}
|
||||
if let Err(err) = socket.write_all(payload.as_bytes()).await {
|
||||
warn!("[interserver send {:?}] failed: {:?}", server_id, err);
|
||||
break;
|
||||
}
|
||||
|
||||
login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await;
|
||||
interserver_send_loop(server_id, socket.clone(), client_receiver).await;
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
pub fn ship_connect_mainloop<EG: EntityGateway + Clone + 'static>(state: Arc<Mutex<ShipServerState<EG>>>, ip: std::net::Ipv4Addr, port: u16) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(async_std::task::spawn(async move {
|
||||
let mut id = 0;
|
||||
let (server_state_sender, server_state_receiver) = async_std::channel::bounded(1024);
|
||||
pub async fn run_interserver_listen<STATE, S, R, E>(mut state: STATE, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send + 'static,
|
||||
S: serde::Serialize + Debug + Send + 'static,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
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;
|
||||
let ships = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
interserver_state_loop(state.clone(), server_state_receiver).await;
|
||||
loop {
|
||||
let (socket, addr) = listener.accept().await.unwrap();
|
||||
info!("[interserver listen] new server: {:?} {:?}", socket, addr);
|
||||
|
||||
loop {
|
||||
info!("trying to connect to loginserv");
|
||||
let socket = match async_std::net::TcpStream::connect((ip, port)).await {
|
||||
Ok(socket) => socket,
|
||||
Err(err) => {
|
||||
info!("err trying to connect to loginserv {:?}", err);
|
||||
async_std::task::sleep(Duration::from_secs(10)).await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
info!("found loginserv: {:?} {:?}", server_id, socket);
|
||||
let (client_sender, client_receiver) = async_std::channel::bounded(64);
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
state.set_sender(server_id, client_tx.clone()).await;
|
||||
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
let local_sender = client_sender.clone();
|
||||
state.set_sender(Box::new(move |message| {
|
||||
async_std::task::block_on(local_sender.send(message)).unwrap();
|
||||
}))
|
||||
ships
|
||||
.write()
|
||||
.await
|
||||
.insert(server_id, client_tx.clone());
|
||||
|
||||
for msg in state.on_connect(server_id).await {
|
||||
if let Some(ship_sender) = ships.read().await.get(&msg.0) {
|
||||
ship_sender.send(msg.1).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await;
|
||||
interserver_send_loop(server_id, socket.clone(), client_receiver).await;
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
let rships = ships.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_recv_loop(rstate, server_id, rsocket, rships).await;
|
||||
});
|
||||
async_std::task::spawn(async move {
|
||||
interserver_send_loop(server_id, socket, client_rx).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut buf = [0u8; 1];
|
||||
loop {
|
||||
let peek = socket.peek(&mut buf).await;
|
||||
match peek {
|
||||
Ok(len) if len == 0 => {
|
||||
break
|
||||
},
|
||||
_ => {
|
||||
}
|
||||
pub async fn run_interserver_connect<STATE, S, R, E>(mut state: STATE, ip: std::net::Ipv4Addr, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send + 'static,
|
||||
S: serde::Serialize + Debug + Send + 'static,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
let mut id = 0;
|
||||
|
||||
loop {
|
||||
info!("[interserver connect] trying to connect to server");
|
||||
let socket = match async_std::net::TcpStream::connect((ip, port)).await {
|
||||
Ok(socket) => socket,
|
||||
Err(err) => {
|
||||
info!("err trying to connect to loginserv {:?}", err);
|
||||
async_std::task::sleep(std::time::Duration::from_secs(10)).await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
info!("[interserver connect] found loginserv: {:?} {:?}", server_id, socket);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
state.set_sender(server_id, client_tx.clone()).await;
|
||||
|
||||
for msg in state.on_connect(server_id).await {
|
||||
client_tx.send(msg.1).await.unwrap();
|
||||
}
|
||||
|
||||
let other_server = vec![(server_id, client_tx.clone())].into_iter().collect();
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_recv_loop(rstate, server_id, rsocket, Arc::new(RwLock::new(other_server))).await;
|
||||
});
|
||||
let ssocket = socket.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_send_loop(server_id, ssocket, client_rx).await;
|
||||
});
|
||||
|
||||
let mut buf = [0u8; 1];
|
||||
loop {
|
||||
let peek = socket.peek(&mut buf).await;
|
||||
match peek {
|
||||
Ok(len) if len == 0 => {
|
||||
break
|
||||
},
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
@ -2,547 +2,5 @@
|
||||
mod client;
|
||||
mod interserver;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use log::{trace, info, warn};
|
||||
use std::pin::Pin;
|
||||
use futures::future::{Future, join_all, FutureExt};
|
||||
use async_std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use async_std::io::prelude::{ReadExt, WriteExt};
|
||||
//use crate::common::mainloop::client::client_accept_mainloop;
|
||||
//use crate::common::mainloop::interserver::{ship_connect_mainloop, login_listen_mainloop};
|
||||
pub use crate::common::mainloop::client::NetworkError;
|
||||
use crate::common::mainloop::client::PacketReceiver;
|
||||
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect};
|
||||
|
||||
use crate::common::interserver::{ServerId, InterserverActor};
|
||||
|
||||
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;
|
||||
|
||||
use libpso::crypto::{PSOCipher, NullCipher, CipherError};
|
||||
|
||||
use async_std::channel;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
pub fn patch_mainloop(patch_state: PatchServerState, patch_port: u16) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
let patch_state = Arc::new(Mutex::new(patch_state));
|
||||
let client_mainloop = client_accept_mainloop(patch_state, patch_port);
|
||||
Box::pin(client_mainloop)
|
||||
}
|
||||
|
||||
pub fn login_mainloop<EG: EntityGateway + Clone + '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, login_port);
|
||||
Box::pin(client_mainloop)
|
||||
}
|
||||
|
||||
pub fn character_mainloop<EG: EntityGateway + Clone + '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.clone(), character_port);
|
||||
let ship_communication_mainloop = login_listen_mainloop(character_state, comm_port);
|
||||
Box::pin(join_all(vec![client_mainloop, ship_communication_mainloop]).map(|_| ()))
|
||||
}
|
||||
|
||||
|
||||
pub fn ship_mainloop<EG: EntityGateway + Clone + 'static>(ship_state: ShipServerState<EG>, ship_port: u16, comm_ip: std::net::Ipv4Addr, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
let ship_state = Arc::new(Mutex::new(ship_state));
|
||||
let client_mainloop = client_accept_mainloop(ship_state.clone(), ship_port);
|
||||
let login_communication_mainloop = ship_connect_mainloop(ship_state, comm_ip, comm_port);
|
||||
Box::pin(join_all(vec![client_mainloop, login_communication_mainloop]).map(|_| ()))
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MessageReceiverError {
|
||||
//InvalidSize,
|
||||
InvalidPayload,
|
||||
//NetworkError(std::io::Error),
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
struct MessageReceiver {
|
||||
socket: async_std::net::TcpStream,
|
||||
}
|
||||
|
||||
impl MessageReceiver {
|
||||
fn new(socket: async_std::net::TcpStream) -> MessageReceiver {
|
||||
MessageReceiver {
|
||||
socket,
|
||||
}
|
||||
}
|
||||
|
||||
async fn recv<R: serde::de::DeserializeOwned + std::fmt::Debug>(&mut self) -> Result<R, MessageReceiverError> {
|
||||
let mut size_buf = [0u8; 4];
|
||||
self.socket.read_exact(&mut size_buf).await.map_err(|_| MessageReceiverError::Disconnected)?;
|
||||
let size = u32::from_le_bytes(size_buf) as usize;
|
||||
|
||||
let mut payload = vec![0u8; size];
|
||||
self.socket.read_exact(&mut payload).await.map_err(|_| MessageReceiverError::Disconnected)?;
|
||||
let payload = String::from_utf8(payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
||||
|
||||
let msg = serde_json::from_str(&payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
||||
Ok(msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
enum ServerAction<S> {
|
||||
NewClient(ClientId, channel::Sender<S>),
|
||||
Packet(ClientId, S),
|
||||
Disconnect(ClientId),
|
||||
}
|
||||
*/
|
||||
|
||||
async fn recv_loop<STATE, S, R, C, E>(mut state: STATE,
|
||||
socket: async_std::net::TcpStream,
|
||||
client_id: ClientId,
|
||||
cipher: C,
|
||||
clients: Arc<RwLock<HashMap<ClientId, channel::Sender<S>>>>)
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, Cipher=C, PacketError=E> + Send,
|
||||
S: SendServerPacket + Debug + Send,
|
||||
R: RecvServerPacket + Debug + Send,
|
||||
C: PSOCipher + Send,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
let mut pkt_receiver = PacketReceiver::new(socket, cipher);
|
||||
loop {
|
||||
match pkt_receiver.recv_pkts::<R>().await {
|
||||
Ok(pkts) => {
|
||||
for pkt in pkts {
|
||||
info!("[recv from {:?}] {:#?}", client_id, pkt);
|
||||
match state.handle(client_id, pkt).await {
|
||||
Ok(response) => {
|
||||
for resp in response {
|
||||
clients
|
||||
.read()
|
||||
.await
|
||||
.get(&resp.0)
|
||||
.unwrap()
|
||||
.send(resp.1)
|
||||
.await;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client recv {:?}] error {:?} ", client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
match err {
|
||||
NetworkError::ClientDisconnected => {
|
||||
info!("[client recv {:?}] disconnected", client_id);
|
||||
for pkt in state.on_disconnect(client_id).await.unwrap() {
|
||||
clients
|
||||
.read()
|
||||
.await
|
||||
.get(&pkt.0)
|
||||
.unwrap()
|
||||
.send(pkt.1)
|
||||
.await;
|
||||
}
|
||||
clients
|
||||
.write()
|
||||
.await
|
||||
.remove(&client_id);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
warn!("[client {:?} recv error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn send_pkt<S, C>(socket: &mut async_std::net::TcpStream,
|
||||
cipher: &mut C,
|
||||
pkt: &S)
|
||||
-> Result<(), NetworkError>
|
||||
where
|
||||
S: SendServerPacket + std::fmt::Debug,
|
||||
C: PSOCipher,
|
||||
{
|
||||
let buf = pkt.as_bytes();
|
||||
trace!("[send buf] {:?}", buf);
|
||||
let cbuf = cipher.encrypt(&buf)?;
|
||||
socket.write_all(&cbuf).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_loop<S, C>(mut socket: async_std::net::TcpStream, client_id: ClientId, mut cipher: C, packet_queue: channel::Receiver<S>)
|
||||
where
|
||||
S: SendServerPacket + std::fmt::Debug,
|
||||
C: PSOCipher,
|
||||
{
|
||||
loop {
|
||||
let pkt = packet_queue.recv().await.unwrap();
|
||||
if let Err(err) = send_pkt(&mut socket, &mut cipher, &pkt).await {
|
||||
warn!("error sending pkt {:#?} to {:?} {:?}", pkt, client_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub async fn server_multiplex<STATE, S, R, E>(state: STATE, packet_queue: channel::Receiver<ServerAction<S>>)
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, PacketError=E>,
|
||||
S: SendServerPacket + std::fmt::Debug,
|
||||
R: RecvServerPacket + std::fmt::Debug,
|
||||
E: std::fmt::Debug,
|
||||
{
|
||||
let mut clients = HashMap::new();
|
||||
loop {
|
||||
let action = packet_queue.recv().await.unwrap();
|
||||
|
||||
match action {
|
||||
ServerAction::NewClient(client_id, sender) => {
|
||||
clients.insert(client_id, sender);
|
||||
},
|
||||
ServerAction::Packet(client_id, pkt) => {
|
||||
if let Some(sender) = clients.get(&client_id) {
|
||||
sender.send(pkt).await;
|
||||
}
|
||||
},
|
||||
ServerAction::Disconnect(client_id) => {
|
||||
clients.remove(&client_id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
pub async fn run_server<STATE, S, R, C, E>(mut state: STATE, port: u16)
|
||||
where
|
||||
STATE: ServerState<SendPacket=S, RecvPacket=R, Cipher=C, PacketError=E> + Send + 'static,
|
||||
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
R: RecvServerPacket + std::fmt::Debug + Send,
|
||||
C: PSOCipher + Send + 'static,
|
||||
E: std::fmt::Debug + Send,
|
||||
{
|
||||
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;
|
||||
//let (packet_sender, packet_receiver) = async_std::channel::unbounded();
|
||||
|
||||
let clients = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
//let cstate = state.clone();
|
||||
/*
|
||||
async_std::task::spawn(async move {
|
||||
server_multiplex(cstate, packet_receiver).await
|
||||
});
|
||||
*/
|
||||
|
||||
loop {
|
||||
let (mut socket, addr) = listener.accept().await.unwrap();
|
||||
id += 1;
|
||||
|
||||
let client_id = crate::common::serverstate::ClientId(id);
|
||||
info!("new client {:?} {:?} {:?}", client_id, socket, addr);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
//packet_sender.send(ServerAction::NewClient()).await;
|
||||
|
||||
clients
|
||||
.write()
|
||||
.await
|
||||
.insert(client_id, client_tx.clone());
|
||||
|
||||
let mut cipher_in: Option<C> = None;
|
||||
let mut cipher_out: Option<C> = None;
|
||||
|
||||
for action in state.on_connect(client_id).await.unwrap() {
|
||||
match action {
|
||||
OnConnect::Cipher(cin, cout) => {
|
||||
cipher_in = Some(cin);
|
||||
cipher_out = Some(cout);
|
||||
},
|
||||
OnConnect::Packet(pkt) => {
|
||||
send_pkt(&mut socket, &mut NullCipher {}, &pkt).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
let rclients = clients.clone();
|
||||
async_std::task::spawn(async move {
|
||||
/*
|
||||
rstate;
|
||||
rsocket;
|
||||
client_id;
|
||||
cipher_in.unwrap();
|
||||
rclients;
|
||||
*/
|
||||
//client_tx.send(12).await
|
||||
recv_loop(rstate, rsocket, client_id, cipher_in.unwrap(), rclients).await
|
||||
//recv_loop2(rstate, rsocket, client_id, cipher_in.unwrap()).await
|
||||
});
|
||||
|
||||
//let sstate = state.clone();
|
||||
async_std::task::spawn(async move {
|
||||
send_loop(socket, client_id, cipher_out.unwrap(), client_rx).await
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub async fn listen_interserver<STATE, S, R, C, E>(state: STATE, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E>,
|
||||
S: serde::Serialize,
|
||||
R: serde::de::DeserializeOwned,
|
||||
{
|
||||
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;
|
||||
|
||||
loop {
|
||||
let (socket, addr) = listener.accept().await.unwrap();
|
||||
info!("new interserver connection: {:?} {:?}", socket, addr);
|
||||
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn run_interserver_receiver<STATE, S, R, E>(state: STATE, ip: std::net::Ipv4Addr, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E>,
|
||||
S: serde::Serialize,
|
||||
R: serde::de::DeserializeOwned,
|
||||
{
|
||||
loop {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
pub async fn run_interserver_sender<STATE, S, R, E>(state: STATE, to_send: channel::Receiver<S>)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E>,
|
||||
S: serde::Serialize,
|
||||
R: serde::de::DeserializeOwned,
|
||||
{
|
||||
loop {
|
||||
let msg = to_send.recv().await.unwrap();
|
||||
|
||||
let response = state.on_action(msg);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
async fn interserver_recv_loop<STATE, S, R, E>(mut state: STATE, server_id: ServerId, socket: async_std::net::TcpStream, ships: Arc<RwLock<HashMap<ServerId, channel::Sender<S>>>>)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send,
|
||||
S: serde::Serialize + Debug + Send,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
let mut msg_receiver = MessageReceiver::new(socket);
|
||||
|
||||
loop {
|
||||
match msg_receiver.recv::<R>().await {
|
||||
Ok(msg) => {
|
||||
info!("[interserver recv {:?}] {:?}", server_id, msg);
|
||||
match state.on_action(server_id, msg).await {
|
||||
Ok(response) => {
|
||||
for resp in response {
|
||||
ships
|
||||
.read()
|
||||
.await
|
||||
.get(&resp.0)
|
||||
.unwrap()
|
||||
.send(resp.1)
|
||||
.await;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[interserver recv {:?}] error {:?}", server_id, err);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
if let MessageReceiverError::Disconnected = err {
|
||||
info!("[interserver recv {:?}] disconnected", server_id);
|
||||
for (_, sender) in ships.read().await.iter() {
|
||||
for pkt in state.on_disconnect(server_id).await {
|
||||
ships
|
||||
.read()
|
||||
.await
|
||||
.get(&pkt.0)
|
||||
.unwrap()
|
||||
.send(pkt.1)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
ships
|
||||
.write()
|
||||
.await
|
||||
.remove(&server_id);
|
||||
break;
|
||||
}
|
||||
info!("[interserver recv {:?}] error {:?}", server_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn interserver_send_loop<S>(server_id: ServerId, mut socket: async_std::net::TcpStream, to_send: channel::Receiver<S>)
|
||||
where
|
||||
S: serde::Serialize + std::fmt::Debug,
|
||||
{
|
||||
loop {
|
||||
let msg = to_send.recv().await.unwrap();
|
||||
let payload = serde_json::to_string(&msg);
|
||||
|
||||
if let Ok(payload) = payload {
|
||||
let len_bytes = u32::to_le_bytes(payload.len() as u32);
|
||||
if let Err(err) = socket.write_all(&len_bytes).await {
|
||||
warn!("[interserver send {:?}] failed: {:?}", server_id, err);
|
||||
break;
|
||||
}
|
||||
if let Err(err) = socket.write_all(payload.as_bytes()).await {
|
||||
warn!("[interserver send {:?}] failed: {:?}", server_id, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_interserver_listen<STATE, S, R, E>(mut state: STATE, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send + 'static,
|
||||
S: serde::Serialize + Debug + Send + 'static,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
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;
|
||||
let ships = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
loop {
|
||||
let (socket, addr) = listener.accept().await.unwrap();
|
||||
info!("[interserver listen] new server: {:?} {:?}", socket, addr);
|
||||
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
|
||||
//let sclient_tx = client_tx.clone();
|
||||
/*
|
||||
state.set_sender(server_id, Arc::new(Box::new(move |msg| {
|
||||
let sclient_tx = sclient_tx.clone();
|
||||
Box::new(async move {
|
||||
sclient_tx.send(msg).await;
|
||||
})})));
|
||||
*/
|
||||
state.set_sender(server_id, client_tx.clone());
|
||||
|
||||
ships
|
||||
.write()
|
||||
.await
|
||||
.insert(server_id, client_tx.clone());
|
||||
|
||||
for msg in state.on_connect(server_id).await {
|
||||
if let Some(ship_sender) = ships.read().await.get(&msg.0) {
|
||||
ship_sender.send(msg.1).await;
|
||||
}
|
||||
}
|
||||
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
let rships = ships.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_recv_loop(rstate, server_id, rsocket, rships).await;
|
||||
});
|
||||
async_std::task::spawn(async move {
|
||||
interserver_send_loop(server_id, socket, client_rx).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_interserver_connect<STATE, S, R, E>(mut state: STATE, ip: std::net::Ipv4Addr, port: u16)
|
||||
where
|
||||
STATE: InterserverActor<SendMessage=S, RecvMessage=R, Error=E> + Send + 'static,
|
||||
S: serde::Serialize + Debug + Send + 'static,
|
||||
R: serde::de::DeserializeOwned + Debug + Send,
|
||||
E: Debug + Send,
|
||||
{
|
||||
let mut id = 0;
|
||||
|
||||
loop {
|
||||
info!("[interserver connect] trying to connect to server");
|
||||
let socket = match async_std::net::TcpStream::connect((ip, port)).await {
|
||||
Ok(socket) => socket,
|
||||
Err(err) => {
|
||||
info!("err trying to connect to loginserv {:?}", err);
|
||||
async_std::task::sleep(std::time::Duration::from_secs(10)).await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
id += 1;
|
||||
let server_id = crate::common::interserver::ServerId(id);
|
||||
info!("[interserver connect] found loginserv: {:?} {:?}", server_id, socket);
|
||||
|
||||
let (client_tx, client_rx) = async_std::channel::unbounded();
|
||||
|
||||
state.set_sender(server_id, client_tx.clone());
|
||||
/*
|
||||
let sclient_tx = client_tx.clone();
|
||||
state.set_sender(server_id, Arc::new(Box::new(move |msg| {
|
||||
let sclient_tx = sclient_tx.clone();
|
||||
Box::new(async move {
|
||||
sclient_tx.send(msg).await;
|
||||
})})));
|
||||
*/
|
||||
|
||||
let other_server = vec![(server_id, client_tx.clone())].into_iter().collect();
|
||||
|
||||
let rstate = state.clone();
|
||||
let rsocket = socket.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_recv_loop(rstate, server_id, rsocket, Arc::new(RwLock::new(other_server))).await;
|
||||
});
|
||||
let ssocket = socket.clone();
|
||||
async_std::task::spawn(async move {
|
||||
interserver_send_loop(server_id, ssocket, client_rx).await;
|
||||
});
|
||||
|
||||
let mut buf = [0u8; 1];
|
||||
loop {
|
||||
let peek = socket.peek(&mut buf).await;
|
||||
match peek {
|
||||
Ok(len) if len == 0 => {
|
||||
break
|
||||
},
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pub use self::client::*;
|
||||
pub use self::interserver::*;
|
||||
|
@ -675,18 +675,18 @@ impl From<PgItemNoteDetail> for ItemNote {
|
||||
fn from(other: PgItemNoteDetail) -> ItemNote {
|
||||
match other {
|
||||
PgItemNoteDetail::CharacterCreation{character_id} => ItemNote::CharacterCreation {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
},
|
||||
PgItemNoteDetail::EnemyDrop{character_id, map_area, x, y, z} => ItemNote::EnemyDrop {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
map_area,
|
||||
x,y,z,
|
||||
},
|
||||
PgItemNoteDetail::Pickup{character_id} => ItemNote::Pickup {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
},
|
||||
PgItemNoteDetail::PlayerDrop{character_id, map_area, x, y, z} => ItemNote::PlayerDrop {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
map_area,
|
||||
x,y,z,
|
||||
},
|
||||
@ -699,16 +699,16 @@ impl From<PgItemNoteDetail> for ItemNote {
|
||||
},
|
||||
PgItemNoteDetail::SoldToShop => ItemNote::SoldToShop,
|
||||
PgItemNoteDetail::Trade {trade_id, character_to, character_from} => ItemNote::Trade {
|
||||
trade_id: TradeId(trade_id as u32),
|
||||
character_to: CharacterEntityId(character_to as u32),
|
||||
character_from: CharacterEntityId(character_from as u32),
|
||||
trade_id: TradeId(trade_id),
|
||||
character_to: CharacterEntityId(character_to),
|
||||
character_from: CharacterEntityId(character_from),
|
||||
},
|
||||
PgItemNoteDetail::Withdraw{character_id, bank} => ItemNote::Withdraw {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
bank: BankName(bank),
|
||||
},
|
||||
PgItemNoteDetail::Deposit{character_id, bank} => ItemNote::Deposit {
|
||||
character_id: CharacterEntityId(character_id as u32),
|
||||
character_id: CharacterEntityId(character_id),
|
||||
bank: BankName(bank),
|
||||
},
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
use std::io::Read;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
|
||||
use async_std::sync::Arc;
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use async_std::channel;
|
||||
|
||||
use rand::Rng;
|
||||
@ -186,16 +186,14 @@ struct ConnectedClient {
|
||||
pub struct CharacterServerState<EG: EntityGateway + Clone> {
|
||||
entity_gateway: EG,
|
||||
param_header: ParamDataHeader,
|
||||
param_data: Vec<u8>,
|
||||
clients: HashMap<ClientId, ClientState>,
|
||||
ships: BTreeMap<ServerId, Ship>,
|
||||
//level_table: CharacterLevelTable,
|
||||
param_data: Arc<Vec<u8>>,
|
||||
clients: Arc<RwLock<HashMap<ClientId, ClientState>>>,
|
||||
ships: Arc<RwLock<BTreeMap<ServerId, Ship>>>,
|
||||
auth_token: AuthToken,
|
||||
|
||||
connected_clients: BTreeMap<UserAccountId, ConnectedClient>,
|
||||
authenticated_ships: BTreeSet<ServerId>,
|
||||
//ship_sender: BTreeMap<ServerId, Arc<Box<dyn Fn(LoginMessage) -> Box<dyn futures::future::Future<Output = ()>> + Send>>>,
|
||||
ship_sender: BTreeMap<ServerId, channel::Sender<LoginMessage>>,
|
||||
connected_clients: Arc<RwLock<BTreeMap<UserAccountId, ConnectedClient>>>,
|
||||
authenticated_ships: Arc<RwLock<BTreeSet<ServerId>>>,
|
||||
ship_sender: Arc<RwLock<BTreeMap<ServerId, channel::Sender<LoginMessage>>>>,
|
||||
}
|
||||
|
||||
|
||||
@ -318,21 +316,21 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
CharacterServerState {
|
||||
entity_gateway,
|
||||
param_header,
|
||||
param_data,
|
||||
clients: HashMap::new(),
|
||||
ships: BTreeMap::new(),
|
||||
param_data: Arc::new(param_data),
|
||||
clients: Default::default(),
|
||||
ships: Default::default(),
|
||||
//level_table: CharacterLevelTable::default(),
|
||||
auth_token,
|
||||
authenticated_ships: BTreeSet::new(),
|
||||
ship_sender: BTreeMap::new(),
|
||||
connected_clients: BTreeMap::new(),
|
||||
authenticated_ships: Default::default(),
|
||||
ship_sender: Default::default(),
|
||||
connected_clients: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
match get_login_status(&mut self.entity_gateway, pkt).await {
|
||||
Ok(user) => {
|
||||
if let Some(connected_client) = self.connected_clients.get(&user.id) {
|
||||
if let Some(connected_client) = self.connected_clients.read().await.get(&user.id) {
|
||||
if let Some(expires) = connected_client.expires {
|
||||
if expires > chrono::Utc::now() {
|
||||
return Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_status(AccountStatus::AlreadyOnline, Session::new()))]);
|
||||
@ -345,11 +343,12 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
|
||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||
response.guildcard = user.guildcard;
|
||||
response.team_id = user.team_id.map_or(0, |ti| ti) as u32;
|
||||
response.team_id = user.team_id.map_or(0, |ti| ti);
|
||||
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
|
||||
self.connected_clients.insert(user.id, ConnectedClient {
|
||||
self.connected_clients.write().await.insert(user.id, ConnectedClient {
|
||||
ship_id: None,
|
||||
expires: None, //Some(chrono::Utc::now() + chrono::Duration::minutes(1)),
|
||||
});
|
||||
@ -364,9 +363,9 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
}
|
||||
}
|
||||
|
||||
fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
async fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
Ok(vec![SendCharacterPacket::Timestamp(Timestamp::new(chrono::Utc::now())),
|
||||
SendCharacterPacket::ShipList(ShipList::new(self.ships.iter().map(|(i, s)| {
|
||||
SendCharacterPacket::ShipList(ShipList::new(self.ships.read().await.iter().map(|(i, s)| {
|
||||
ShipListEntry {
|
||||
menu: SHIP_MENU_ID,
|
||||
item: i.0 as u32,
|
||||
@ -378,7 +377,8 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn get_settings(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
let user = client.user.as_ref().unwrap();
|
||||
|
||||
let settings = match self.entity_gateway.get_user_settings_by_user(user).await {
|
||||
@ -397,7 +397,8 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
if client.characters.is_none() {
|
||||
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadCharacters)?);
|
||||
}
|
||||
@ -443,7 +444,8 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadGuildcard)?;
|
||||
|
||||
let bytes = guildcard_data.guildcard.as_bytes();
|
||||
@ -454,15 +456,16 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
Ok(vec![SendCharacterPacket::GuildcardDataHeader(GuildcardDataHeader::new(bytes.len(), crc.sum32()))])
|
||||
}
|
||||
|
||||
fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
async fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
Ok(if again != 0 {
|
||||
let start = chunk as usize * GUILD_CARD_CHUNK_SIZE;
|
||||
let len = std::cmp::min(GUILD_CARD_CHUNK_SIZE, client.guildcard_data_buffer.as_ref().unwrap().len() as usize - start);
|
||||
let len = std::cmp::min(GUILD_CARD_CHUNK_SIZE, client.guildcard_data_buffer.as_ref().unwrap().len() - start);
|
||||
let end = start + len;
|
||||
|
||||
let mut buf = [0u8; GUILD_CARD_CHUNK_SIZE as usize];
|
||||
buf[..len as usize].copy_from_slice(&client.guildcard_data_buffer.as_ref().unwrap()[start..end]);
|
||||
let mut buf = [0u8; GUILD_CARD_CHUNK_SIZE];
|
||||
buf[..len].copy_from_slice(&client.guildcard_data_buffer.as_ref().unwrap()[start..end]);
|
||||
|
||||
vec![SendCharacterPacket::GuildcardDataChunk(Box::new(GuildcardDataChunk::new(chunk, buf, len)))]
|
||||
} else {
|
||||
@ -471,15 +474,17 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
let mut user = client.user.as_mut().unwrap();
|
||||
user.flags = setflag.flags;
|
||||
self.entity_gateway.save_user(user).await.unwrap();
|
||||
Ok(None.into_iter())
|
||||
}
|
||||
|
||||
fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
async fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
let chunk = client.param_index;
|
||||
client.param_index += 1;
|
||||
|
||||
@ -500,7 +505,8 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
|
||||
// TODO: move USERFLAGS over to SessionAction
|
||||
async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut client = self.clients.write().await;
|
||||
let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?;
|
||||
let mut user = client.user.as_mut().unwrap();
|
||||
if user.flags == USERFLAG_NEWCHAR {
|
||||
new_character(&mut self.entity_gateway, user, preview).await?
|
||||
@ -523,26 +529,30 @@ impl<EG: EntityGateway + Clone> CharacterServerState<EG> {
|
||||
])
|
||||
}
|
||||
|
||||
fn select_ship(&mut self, id: ClientId, menuselect: &MenuSelect) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
async fn select_ship(&mut self, id: ClientId, menuselect: &MenuSelect) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
if menuselect.menu != SHIP_MENU_ID {
|
||||
return Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item).into());
|
||||
}
|
||||
|
||||
if let Some(client) = self.clients.get(&id) {
|
||||
if let Some(client) = self.clients.read().await.get(&id) {
|
||||
if let Some(user) = &client.user {
|
||||
if let Some(cc) = self.connected_clients.get_mut(&user.id) {
|
||||
if let Some(cc) = self.connected_clients.write().await.get_mut(&user.id) {
|
||||
cc.ship_id = Some(ServerId(menuselect.item as usize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ship = self.ships.get(&ServerId(menuselect.item as usize))
|
||||
.ok_or(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?;
|
||||
let ship = self.ships.read().await;
|
||||
let ship = ship.get(&ServerId(menuselect.item as usize))
|
||||
.ok_or_else(|| CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?;
|
||||
Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip.octets()), ship.port))])
|
||||
}
|
||||
|
||||
fn ship_detail(&mut self, menudetail: &MenuDetail) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let players = self.connected_clients.iter()
|
||||
async fn ship_detail(&mut self, menudetail: &MenuDetail) -> Result<Vec<SendCharacterPacket>, anyhow::Error> {
|
||||
let players = self.connected_clients
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.filter(|(_, client)| {
|
||||
client.ship_id == Some(ServerId(menudetail.item as usize))
|
||||
})
|
||||
@ -560,7 +570,7 @@ impl<EG: EntityGateway + Clone> ServerState for CharacterServerState<EG> {
|
||||
type PacketError = anyhow::Error;
|
||||
|
||||
async fn on_connect(&mut self, id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket, Self::Cipher>>, anyhow::Error> {
|
||||
self.clients.insert(id, ClientState::new());
|
||||
self.clients.write().await.insert(id, ClientState::new());
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
@ -581,7 +591,7 @@ impl<EG: EntityGateway + Clone> ServerState for CharacterServerState<EG> {
|
||||
Ok(match pkt {
|
||||
RecvCharacterPacket::Login(login) => {
|
||||
if login.session.action == SessionAction::SelectCharacter {
|
||||
self.send_ship_list(id, &login)?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
self.send_ship_list(id, &login).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
}
|
||||
else {
|
||||
self.validate_login(id, &login).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
@ -600,7 +610,7 @@ impl<EG: EntityGateway + Clone> ServerState for CharacterServerState<EG> {
|
||||
self.guildcard_data_header(id).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::GuildcardDataChunkRequest(request) => {
|
||||
self.guildcard_data_chunk(id, request.chunk, request.again)?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
self.guildcard_data_chunk(id, request.chunk, request.again).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::ParamDataRequest(_request) => {
|
||||
vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
@ -609,17 +619,17 @@ impl<EG: EntityGateway + Clone> ServerState for CharacterServerState<EG> {
|
||||
self.set_flag(id, &flag).await?.map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::ParamDataChunkRequest(request) => {
|
||||
self.param_data_chunk_request(id, &request)?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
self.param_data_chunk_request(id, &request).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::CharacterPreview(preview) => {
|
||||
self.character_preview(id, &preview).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::MenuSelect(menuselect) => {
|
||||
self.select_ship(id, &menuselect)?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
self.select_ship(id, &menuselect).await?.into_iter().map(move |pkt| (id, pkt)).collect()
|
||||
},
|
||||
RecvCharacterPacket::MenuDetail(menudetail) => {
|
||||
match menudetail.menu {
|
||||
SHIP_MENU_ID => self.ship_detail(&menudetail)?.into_iter().map(move |pkt| (id, pkt)).collect(),
|
||||
SHIP_MENU_ID => self.ship_detail(&menudetail).await?.into_iter().map(move |pkt| (id, pkt)).collect(),
|
||||
_ => Vec::new()
|
||||
}
|
||||
}
|
||||
@ -627,9 +637,9 @@ impl<EG: EntityGateway + Clone> ServerState for CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendCharacterPacket)>, anyhow::Error> {
|
||||
if let Some(client) = self.clients.remove(&id) {
|
||||
if let Some(client) = self.clients.write().await.remove(&id) {
|
||||
if let Some(user) = client.user {
|
||||
self.connected_clients.remove(&user.id);
|
||||
self.connected_clients.write().await.remove(&user.id);
|
||||
}
|
||||
}
|
||||
Ok(Vec::new())
|
||||
@ -647,20 +657,25 @@ impl<EG: EntityGateway + Clone> InterserverActor for CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn on_action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
|
||||
dbg!(&id, &msg);
|
||||
match msg {
|
||||
ShipMessage::Authenticate(auth_token) => {
|
||||
if self.auth_token == auth_token {
|
||||
self.authenticated_ships.insert(id);
|
||||
self.authenticated_ships.write().await.insert(id);
|
||||
}
|
||||
Ok(Vec::new())
|
||||
},
|
||||
ShipMessage::NewShip(new_ship) => {
|
||||
if self.authenticated_ships.contains(&id) {
|
||||
self.ships.insert(id, new_ship);
|
||||
dbg!("adding ship", &id, &new_ship);
|
||||
if self.authenticated_ships.read().await.contains(&id) {
|
||||
self.ships.write().await.insert(id, new_ship);
|
||||
}
|
||||
dbg!("ship list", &self.authenticated_ships);
|
||||
|
||||
let ships = self.ships.iter().map(|(_, s)| s).cloned().collect::<Vec<_>>();
|
||||
let ships = self.ships.read().await.iter().map(|(_, s)| s).cloned().collect::<Vec<_>>();
|
||||
Ok(self.ships
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|(id, _)| {
|
||||
(*id, LoginMessage::ShipList{ ships: ships.clone() })
|
||||
@ -668,8 +683,8 @@ impl<EG: EntityGateway + Clone> InterserverActor for CharacterServerState<EG> {
|
||||
.collect())
|
||||
},
|
||||
ShipMessage::AddUser(new_user) => {
|
||||
if self.authenticated_ships.contains(&id) {
|
||||
self.connected_clients.insert(new_user, ConnectedClient {
|
||||
if self.authenticated_ships.read().await.contains(&id) {
|
||||
self.connected_clients.write().await.insert(new_user, ConnectedClient {
|
||||
ship_id: Some(id),
|
||||
expires: None,
|
||||
});
|
||||
@ -677,15 +692,18 @@ impl<EG: EntityGateway + Clone> InterserverActor for CharacterServerState<EG> {
|
||||
Ok(Vec::new())
|
||||
},
|
||||
ShipMessage::RemoveUser(new_user) => {
|
||||
if self.authenticated_ships.contains(&id) {
|
||||
self.connected_clients.remove(&new_user);
|
||||
if self.authenticated_ships.read().await.contains(&id) {
|
||||
self.connected_clients.write().await.remove(&new_user);
|
||||
}
|
||||
Ok(Vec::new())
|
||||
},
|
||||
ShipMessage::RequestShipList => {
|
||||
if self.authenticated_ships.contains(&id) {
|
||||
dbg!("request ship list", &self.authenticated_ships);
|
||||
if self.authenticated_ships.read().await.contains(&id) {
|
||||
Ok(vec![(id, LoginMessage::ShipList {
|
||||
ships: self.ships
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|(_, ship)| {
|
||||
ship
|
||||
@ -705,18 +723,19 @@ impl<EG: EntityGateway + Clone> InterserverActor for CharacterServerState<EG> {
|
||||
}
|
||||
|
||||
async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
self.ships.remove(&id);
|
||||
self.ship_sender.remove(&id);
|
||||
self.connected_clients = self.connected_clients.clone().into_iter()
|
||||
.filter(|(_, client)| {
|
||||
self.ships.write().await.remove(&id);
|
||||
self.ship_sender.write().await.remove(&id);
|
||||
self.connected_clients
|
||||
.write()
|
||||
.await
|
||||
.retain(|_, client| {
|
||||
client.ship_id != Some(id)
|
||||
})
|
||||
.collect();
|
||||
});
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn set_sender(&mut self, server_id: ServerId, sender: channel::Sender<LoginMessage>) {
|
||||
self.ship_sender.insert(server_id, sender);
|
||||
async fn set_sender(&mut self, server_id: ServerId, sender: channel::Sender<LoginMessage>) {
|
||||
self.ship_sender.write().await.insert(server_id, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@ -845,7 +864,7 @@ mod test {
|
||||
at_character: false,
|
||||
at_ship: false,
|
||||
});
|
||||
server.clients.insert(ClientId(5), clientstate);
|
||||
server.clients.write().await.insert(ClientId(5), clientstate);
|
||||
|
||||
let send = server.handle(ClientId(5), RecvCharacterPacket::RequestSettings(RequestSettings{})).await.unwrap();
|
||||
assert!(send.len() == 1);
|
||||
@ -892,7 +911,7 @@ mod test {
|
||||
});
|
||||
|
||||
let mut server = CharacterServerState::new(test_data.clone(), AuthToken("".into()));
|
||||
server.clients.insert(ClientId(1), fake_user.clone());
|
||||
server.clients.write().await.insert(ClientId(1), fake_user.clone());
|
||||
let mut send = server.handle(ClientId(1), RecvCharacterPacket::SetFlag(SetFlag {flags: 1})).await.unwrap();
|
||||
assert!(test_data.get_user_by_id(UserAccountId(3)).await.unwrap().flags == 1);
|
||||
send = server.handle(ClientId(1), RecvCharacterPacket::CharacterPreview(CharacterPreview {slot: 1, character: character::SelectScreenCharacter {
|
||||
|
@ -190,9 +190,8 @@ impl ServerState for PatchServerState {
|
||||
.collect()
|
||||
},
|
||||
RecvPatchPacket::FileInfoReply(pkt) => {
|
||||
self.patch_file_info.push(pkt.clone());
|
||||
self.patch_file_info.push(pkt);
|
||||
Vec::new()
|
||||
//None.into_iter().map(move |pkt| (id, pkt))
|
||||
},
|
||||
RecvPatchPacket::FileInfoListEnd(_pkt) => {
|
||||
let need_update = self.patch_file_info.iter()
|
||||
|
@ -77,7 +77,7 @@ impl<'a> CharacterBytesBuilder<'a> {
|
||||
prop_y: character.appearance.prop_y,
|
||||
config: character.config.as_bytes(),
|
||||
techniques: character.techs.as_bytes(),
|
||||
meseta: meseta.0 as u32,
|
||||
meseta: meseta.0,
|
||||
exp: character.exp,
|
||||
..character::Character::default()
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub(super) fn take_item_from_floor(character_id: CharacterEntityId, item_id: Cli
|
||||
move |(mut item_state, transaction): (ItemStateProxy<'_>, Box<dyn EntityGatewayTransaction + '_>) , _| {
|
||||
Box::pin(async move {
|
||||
let mut floor = item_state.floor(&character_id).await?;
|
||||
let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?;
|
||||
let item = floor.take_item(&item_id).ok_or_else(|| ItemStateError::NoFloorItem(item_id))?;
|
||||
item_state.set_floor(floor).await;
|
||||
|
||||
Ok(((item_state, transaction), item))
|
||||
@ -88,7 +88,7 @@ pub(super) fn take_item_from_inventory(character_id: CharacterEntityId, item_id:
|
||||
move |(mut item_state, mut transaction), _| {
|
||||
Box::pin(async move {
|
||||
let mut inventory = item_state.inventory(&character_id).await?;
|
||||
let item = inventory.take_item(&item_id, amount).ok_or (ItemStateError::NoFloorItem(item_id))?;
|
||||
let item = inventory.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoFloorItem(item_id))?;
|
||||
|
||||
transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?;
|
||||
item_state.set_inventory(inventory);
|
||||
@ -238,7 +238,7 @@ pub(super) fn take_item_from_bank(character_id: CharacterEntityId, item_id: Clie
|
||||
move |(mut item_state, mut transaction), _| {
|
||||
Box::pin(async move {
|
||||
let mut bank = item_state.bank(&character_id).await?;
|
||||
let item = bank.take_item(&item_id, amount).ok_or(ItemStateError::NoBankItem(item_id))?;
|
||||
let item = bank.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoBankItem(item_id))?;
|
||||
transaction.gateway().set_character_bank(&character_id, &bank.as_bank_entity(), &bank.name).await?;
|
||||
item_state.set_bank(bank);
|
||||
|
||||
@ -407,10 +407,10 @@ pub(super) fn feed_mag_item(character: CharacterEntity, mag_item_id: ClientItemI
|
||||
Box::pin(async move {
|
||||
let mut inventory = item_state.inventory(&character.id).await?;
|
||||
let mag_entity = inventory.get_by_client_id_mut(&mag_item_id)
|
||||
.ok_or(ItemStateError::InvalidItemId(mag_item_id))?
|
||||
.ok_or_else(|| ItemStateError::InvalidItemId(mag_item_id))?
|
||||
.item
|
||||
.as_individual_mut()
|
||||
.ok_or(ItemStateError::NotAMag(mag_item_id))?;
|
||||
.ok_or_else(|| ItemStateError::NotAMag(mag_item_id))?;
|
||||
let mag_entity_id = mag_entity.entity_id;
|
||||
|
||||
let mut transaction = tool.with_entity_id(transaction, |mut transaction, entity_id| {
|
||||
@ -426,13 +426,13 @@ pub(super) fn feed_mag_item(character: CharacterEntity, mag_item_id: ClientItemI
|
||||
let food_tool = tool
|
||||
.item
|
||||
.stacked()
|
||||
.ok_or(ItemStateError::NotMagFood(tool.item_id))?
|
||||
.ok_or_else(|| ItemStateError::NotMagFood(tool.item_id))?
|
||||
.tool
|
||||
.tool;
|
||||
|
||||
let mag_entity = mag_entity
|
||||
.as_mag_mut()
|
||||
.ok_or(ItemStateError::NotAMag(mag_item_id))?;
|
||||
.ok_or_else(|| ItemStateError::NotAMag(mag_item_id))?;
|
||||
|
||||
mag_entity.feed(food_tool);
|
||||
|
||||
|
@ -1,23 +1,19 @@
|
||||
use std::collections::HashMap;
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankName};
|
||||
|
||||
use futures::future::join_all;
|
||||
|
||||
|
||||
|
||||
use crate::ship::location::{AreaClient, RoomId};
|
||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankName};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::entity::item::weapon::Weapon;
|
||||
use crate::entity::item::mag::Mag;
|
||||
use crate::ship::drops::ItemDrop;
|
||||
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::items::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState};
|
||||
use crate::ship::items::floor::{FloorState, FloorItem, LocalFloor, SharedFloor, FloorType};
|
||||
use crate::ship::items::bank::{Bank, BankState, BankItem, BankItemDetail, BankError};
|
||||
use crate::ship::location::{AreaClient, RoomId};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ItemStateError {
|
||||
@ -27,55 +23,38 @@ pub enum ItemStateError {
|
||||
NoRoom(RoomId),
|
||||
#[error("floor item {0} not found")]
|
||||
NoFloorItem(ClientItemId),
|
||||
|
||||
#[error("expected {0} to be a tool")]
|
||||
NotATool(ClientItemId),
|
||||
|
||||
#[error("bank item {0} not found")]
|
||||
NoBankItem(ClientItemId),
|
||||
|
||||
#[error("inventory error {0}")]
|
||||
InventoryError(#[from] InventoryError),
|
||||
|
||||
#[error("bank error {0}")]
|
||||
BankError(#[from] BankError),
|
||||
|
||||
#[error("invalid item id {0}")]
|
||||
InvalidItemId(ClientItemId),
|
||||
|
||||
#[error("invalid drop? {0:?} (this shouldn't occur)")]
|
||||
BadItemDrop(ItemDrop),
|
||||
|
||||
#[error("idk")]
|
||||
Dummy,
|
||||
|
||||
#[error("gateway")]
|
||||
GatewayError(#[from] GatewayError),
|
||||
|
||||
#[error("tried to remove more meseta than exists: {0}")]
|
||||
InvalidMesetaRemoval(u32),
|
||||
|
||||
#[error("tried to add meseta when there is no more room")]
|
||||
FullOfMeseta,
|
||||
|
||||
#[error("stacked item")]
|
||||
StackedItemError(Vec<ItemEntity>),
|
||||
|
||||
#[error("apply item {0}")]
|
||||
ApplyItemError(#[from] crate::ship::items::apply_item::ApplyItemError),
|
||||
|
||||
#[error("item is not a mag {0}")]
|
||||
NotAMag(ClientItemId),
|
||||
|
||||
#[error("item is not mag food {0}")]
|
||||
NotMagFood(ClientItemId),
|
||||
|
||||
#[error("item is not sellable")]
|
||||
ItemNotSellable,
|
||||
|
||||
#[error("could not modify item")]
|
||||
InvalidModifier,
|
||||
|
||||
#[error("wrong item type ")]
|
||||
WrongItemType(ClientItemId),
|
||||
}
|
||||
@ -137,7 +116,6 @@ impl StackedItemDetail {
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum AddItemResult {
|
||||
NewItem,
|
||||
@ -177,7 +155,7 @@ impl ItemState {
|
||||
.read()
|
||||
.await
|
||||
.get(&character.id)
|
||||
.ok_or(ItemStateError::NoCharacter(character.id))?
|
||||
.ok_or_else(|| ItemStateError::NoCharacter(character.id))?
|
||||
.read()
|
||||
.await
|
||||
.clone())
|
||||
@ -188,7 +166,7 @@ impl ItemState {
|
||||
.read()
|
||||
.await
|
||||
.get(&character.id)
|
||||
.ok_or(ItemStateError::NoCharacter(character.id))?
|
||||
.ok_or_else(|| ItemStateError::NoCharacter(character.id))?
|
||||
.read()
|
||||
.await
|
||||
.clone())
|
||||
@ -197,7 +175,6 @@ impl ItemState {
|
||||
|
||||
impl ItemState {
|
||||
async fn new_item_id(&mut self) -> Result<ClientItemId, ItemStateError> {
|
||||
//self.room_item_id_counter += 1;
|
||||
*self.room_item_id_counter
|
||||
.write()
|
||||
.await += 1;
|
||||
@ -300,7 +277,6 @@ impl ItemState {
|
||||
|
||||
pub async fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
||||
let base_inventory_id = ((area_client.local_client.id() as u32) << 21) | 0x10000;
|
||||
//let inventory = self.character_inventory.get_mut(&character.id).unwrap();
|
||||
self.character_inventory
|
||||
.read()
|
||||
.await
|
||||
@ -309,9 +285,7 @@ impl ItemState {
|
||||
.write()
|
||||
.await
|
||||
.initialize_item_ids(base_inventory_id);
|
||||
//inventory.initialize_item_ids(base_inventory_id);
|
||||
let base_bank_id = ((area_client.local_client.id() as u32) << 21) | 0x20000;
|
||||
//let default_bank = self.character_bank.get_mut(&character.id);
|
||||
self.character_bank
|
||||
.read()
|
||||
.await
|
||||
@ -320,9 +294,6 @@ impl ItemState {
|
||||
.write()
|
||||
.await
|
||||
.initialize_item_ids(base_bank_id);
|
||||
//if let Some(default_bank) = default_bank {
|
||||
//default_bank.initialize_item_ids(base_bank_id);
|
||||
//}
|
||||
self.character_room
|
||||
.write()
|
||||
.await
|
||||
@ -369,7 +340,7 @@ impl ItemState {
|
||||
.await;
|
||||
let local_floor = local_floors
|
||||
.get(character_id)
|
||||
.ok_or(ItemStateError::NoCharacter(*character_id))?
|
||||
.ok_or_else(|| ItemStateError::NoCharacter(*character_id))?
|
||||
.read()
|
||||
.await;
|
||||
let rooms = self.character_room
|
||||
@ -377,13 +348,13 @@ impl ItemState {
|
||||
.await;
|
||||
let room = rooms
|
||||
.get(character_id)
|
||||
.ok_or(ItemStateError::NoCharacter(*character_id))?;
|
||||
.ok_or_else(||ItemStateError::NoCharacter(*character_id))?;
|
||||
let shared_floors = self.room_floor
|
||||
.read()
|
||||
.await;
|
||||
let shared_floor = shared_floors
|
||||
.get(room)
|
||||
.ok_or(ItemStateError::NoCharacter(*character_id))?
|
||||
.ok_or_else(||ItemStateError::NoCharacter(*character_id))?
|
||||
.read()
|
||||
.await;
|
||||
|
||||
@ -397,7 +368,7 @@ impl ItemState {
|
||||
.find(|item| item.item_id == *item_id)
|
||||
.map(|item| (item.clone(), FloorType::Shared))
|
||||
})
|
||||
.ok_or(ItemStateError::NoFloorItem(*item_id))
|
||||
.ok_or_else(|| ItemStateError::NoFloorItem(*item_id))
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,12 +386,10 @@ struct ProxiedItemState {
|
||||
pub struct ItemStateProxy<'a> {
|
||||
item_state: &'a mut ItemState,
|
||||
proxied_state: ProxiedItemState,
|
||||
//_a: std::marker::PhantomData<&'a ()>, // TODO: remove
|
||||
}
|
||||
|
||||
impl<'a> ItemStateProxy<'a> {
|
||||
pub async fn commit(self) {
|
||||
|
||||
async fn copy_back<K, V>(master: &Arc<RwLock<HashMap<K, RwLock<V>>>>,
|
||||
proxy: HashMap<K, V>)
|
||||
where
|
||||
@ -443,43 +412,6 @@ impl<'a> ItemStateProxy<'a> {
|
||||
//copy_back(self.item_state.character_room, self.proxied_state.character_room).await;
|
||||
copy_back(&self.item_state.character_floor, self.proxied_state.character_floor).await;
|
||||
copy_back(&self.item_state.room_floor, self.proxied_state.room_floor).await;
|
||||
|
||||
|
||||
/*
|
||||
self.item_state.character_inventory
|
||||
.write()
|
||||
.await
|
||||
.extend(self.proxied_state.character_inventory.clone());
|
||||
self.item_state.character_bank
|
||||
.write()
|
||||
.await
|
||||
.extend(self.proxied_state.character_bank.clone());
|
||||
self.item_state.character_room
|
||||
.write()
|
||||
.await
|
||||
.extend(self.proxied_state.character_room.clone());
|
||||
self.item_state.character_floor
|
||||
.write()
|
||||
.await
|
||||
.extend(self.proxied_state.character_floor.clone());
|
||||
self.item_state.room_floor
|
||||
.write()
|
||||
.await
|
||||
.extend(self.proxied_state.room_floor);
|
||||
*/
|
||||
/*
|
||||
for (character_id, character_inventory) in self.proxied_state.character_inventory {
|
||||
if let Some(inventory) = self.item_state.character_inventory
|
||||
.read()
|
||||
.await
|
||||
.get(&character_id) {
|
||||
*inventory
|
||||
.write()
|
||||
.await = character_inventory;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,11 +424,6 @@ where
|
||||
K: Eq + std::hash::Hash + Copy,
|
||||
V: Clone
|
||||
{
|
||||
/*
|
||||
let existing_element = master.get(&key).ok_or_else(|| err(key))?;
|
||||
Ok(proxy.entry(key)
|
||||
.or_insert_with(|| existing_element.clone()).clone())
|
||||
*/
|
||||
let existing_element = master
|
||||
.read()
|
||||
.await
|
||||
@ -516,7 +443,6 @@ impl<'a> ItemStateProxy<'a> {
|
||||
ItemStateProxy {
|
||||
item_state,
|
||||
proxied_state: Default::default(),
|
||||
//_a: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,7 +469,6 @@ impl<'a> ItemStateProxy<'a> {
|
||||
}
|
||||
|
||||
pub async fn floor(&mut self, character_id: &CharacterEntityId) -> Result<FloorState, ItemStateError> {
|
||||
//let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, *character_id, ItemStateError::NoCharacter)?;
|
||||
let room_id = *self.item_state.character_room.read().await.get(character_id).unwrap();
|
||||
Ok(FloorState {
|
||||
character_id: *character_id,
|
||||
@ -553,7 +478,6 @@ impl<'a> ItemStateProxy<'a> {
|
||||
}
|
||||
|
||||
pub async fn set_floor(&mut self, floor: FloorState) {
|
||||
//let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, floor.character_id, ItemStateError::NoCharacter).unwrap();
|
||||
let room_id = *self.item_state.character_room.read().await.get(&floor.character_id).unwrap();
|
||||
self.proxied_state.character_floor.insert(floor.character_id, floor.local);
|
||||
self.proxied_state.room_floor.insert(room_id, floor.shared);
|
||||
|
@ -320,7 +320,7 @@ pub struct MapAreaLookup(HashMap<u16, MapArea>);
|
||||
impl MapAreaLookup {
|
||||
pub fn get_area_map(&self, map_area: u16) -> Result<MapArea, MapAreaError> {
|
||||
self.0.get(&map_area)
|
||||
.map(|a| *a)
|
||||
.copied()
|
||||
.ok_or(MapAreaError::UnknownMapArea(map_area))
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ pub async fn join_lobby(id: ClientId,
|
||||
block: client_block,
|
||||
event: 0,
|
||||
padding: 0,
|
||||
playerinfo: playerinfo,
|
||||
playerinfo,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -23,20 +23,21 @@ where
|
||||
Ok(match get_login_status(entity_gateway, &pkt).await {
|
||||
Ok(user) => {
|
||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||
response.guildcard = user.id.0 as u32;
|
||||
response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
|
||||
response.guildcard = user.id.0;
|
||||
response.team_id = user.team_id.map_or(31, |ti| ti);
|
||||
let characters = entity_gateway.get_characters_by_user(&user).await?;
|
||||
let character = characters
|
||||
.get(pkt.session.character_slot as usize)
|
||||
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref()
|
||||
.ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?
|
||||
.as_ref()
|
||||
.ok_or_else(|| ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
|
||||
.clone();
|
||||
let settings = entity_gateway.get_user_settings_by_user(&user).await?;
|
||||
|
||||
item_state.load_character(entity_gateway, &character).await?;
|
||||
|
||||
if let Some(shipgate_sender) = shipgate_sender.as_ref() {
|
||||
shipgate_sender.send(ShipMessage::AddUser(user.id)).await;
|
||||
shipgate_sender.send(ShipMessage::AddUser(user.id)).await?;
|
||||
}
|
||||
clients.add(id, ClientState::new(user, settings, character, pkt.session)).await;
|
||||
vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(ship_name, num_blocks))]
|
||||
|
@ -17,7 +17,7 @@ pub async fn player_chat(id: ClientId,
|
||||
|
||||
Ok(client_location.get_all_clients_by_client(id).await.unwrap().into_iter()
|
||||
.map(move |client| {
|
||||
(client.client, SendShipPacket::PlayerChat(cmsg.clone()).clone())
|
||||
(client.client, SendShipPacket::PlayerChat(cmsg.clone()))
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use libpso::packet::messages::*;
|
||||
use crate::common::leveltable::LEVEL_TABLE;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemShops};
|
||||
use crate::ship::location::{ClientLocation, ClientLocationError};
|
||||
use crate::ship::location::ClientLocation;
|
||||
use crate::ship::drops::ItemDrop;
|
||||
use crate::ship::room::Rooms;
|
||||
use crate::ship::items::ClientItemId;
|
||||
@ -86,16 +86,16 @@ pub async fn request_item<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let room_id = client_location.get_room(id).await?;
|
||||
let monster = rooms.with(room_id, |room| Box::pin(async move {
|
||||
room.maps.enemy_by_id(request_item.enemy_id as usize)
|
||||
})).await??;
|
||||
|
||||
if monster.dropped_item {
|
||||
return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id).into())
|
||||
return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id))
|
||||
}
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await?;
|
||||
let client_and_drop = rooms.with_mut(room_id, |room| Box::pin(async move {
|
||||
clients_in_area.into_iter()
|
||||
.filter_map(move |area_client| {
|
||||
@ -138,9 +138,9 @@ pub async fn pickup_item<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
let room_id = client_location.get_room(id).await?;
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await?;
|
||||
|
||||
clients.with(id, |client| {
|
||||
let mut entity_gateway = entity_gateway.clone();
|
||||
@ -197,16 +197,16 @@ pub async fn request_box_item<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static
|
||||
{
|
||||
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let room_id = client_location.get_room(id).await?;
|
||||
let box_object = rooms.with(room_id, |room| Box::pin(async move {
|
||||
room.maps.object_by_id(box_drop_request.object_id as usize)
|
||||
})).await??;
|
||||
|
||||
if box_object.dropped_item {
|
||||
return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id).into())
|
||||
return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id))
|
||||
}
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await?;
|
||||
|
||||
let client_and_drop = rooms.with_mut(room_id, |room| Box::pin(async move {
|
||||
clients_in_area.into_iter()
|
||||
@ -266,8 +266,8 @@ pub async fn bank_interaction<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let other_clients_in_area = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
let other_clients_in_area = client_location.get_all_clients_by_client(id).await?;
|
||||
|
||||
let bank_action_pkts = clients.with(id, |client| {
|
||||
let mut entity_gateway = entity_gateway.clone();
|
||||
@ -323,7 +323,7 @@ pub async fn shop_request(id: ClientId,
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, ShipError>
|
||||
{
|
||||
//let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let room_id = client_location.get_room(id).await?;
|
||||
/*
|
||||
let room = rooms.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
@ -401,7 +401,7 @@ pub async fn buy_item<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
|
||||
let create = clients.with_mut(id, |client| {
|
||||
let mut entity_gateway = entity_gateway.clone();
|
||||
@ -422,7 +422,7 @@ where
|
||||
(item, remove)
|
||||
},
|
||||
_ => {
|
||||
return Err(ShipError::ShopError.into())
|
||||
return Err(ShipError::ShopError)
|
||||
}
|
||||
};
|
||||
|
||||
@ -442,7 +442,7 @@ where
|
||||
builder::message::create_withdrawn_inventory_item(area_client, &inventory_item)
|
||||
})}).await??;
|
||||
|
||||
let other_clients_in_area = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let other_clients_in_area = client_location.get_client_neighbors(id).await?;
|
||||
Ok(other_clients_in_area.into_iter()
|
||||
.map(move |c| {
|
||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create.clone()))))
|
||||
@ -489,11 +489,11 @@ where
|
||||
|
||||
let inventory = item_state.get_character_inventory(&client.character).await?;
|
||||
let item = inventory.get_by_client_id(&ClientItemId(tek_request.item_id))
|
||||
.ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
||||
.ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
||||
let mut weapon = *item.item.as_individual()
|
||||
.ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||
.ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||
.as_weapon()
|
||||
.ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
||||
.ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
||||
|
||||
weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked {
|
||||
special: special_mod,
|
||||
@ -519,8 +519,8 @@ pub async fn accept_tek_item<EG>(id: ClientId,
|
||||
where
|
||||
EG: EntityGateway + Clone + 'static,
|
||||
{
|
||||
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let neighbors = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
let neighbors = client_location.get_client_neighbors(id).await?;
|
||||
|
||||
clients.with(id, |client| {
|
||||
let mut entity_gateway = entity_gateway.clone();
|
||||
|
@ -146,45 +146,17 @@ pub async fn remove_from_lobby(id: ClientId,
|
||||
pub async fn get_room_tab_info(id: ClientId,
|
||||
pkt: MenuDetail,
|
||||
client_location: &mut ClientLocation,
|
||||
clients: &Clients,
|
||||
rooms: &mut Rooms)
|
||||
clients: &Clients)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
|
||||
/*
|
||||
let room_id = RoomId(pkt.item as usize);
|
||||
if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? {
|
||||
let mut room_info = String::new();
|
||||
let clients_in_room = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
for client in clients_in_room {
|
||||
let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?;
|
||||
let gc = cs.user.guildcard;
|
||||
let name = &cs.character.name;
|
||||
let cc = cs.character.char_class;
|
||||
let lv = LEVEL_TABLE.get_level_from_exp(cc, cs.character.exp);
|
||||
let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1);
|
||||
|
||||
room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str();
|
||||
}
|
||||
Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new(room_info)))])
|
||||
} else {
|
||||
Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new("Game is no longer active".into())))])
|
||||
}
|
||||
*/
|
||||
dbg!("a");
|
||||
let room_id = RoomId(pkt.item as usize);
|
||||
dbg!("b");
|
||||
let clients_in_room = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
dbg!("c");
|
||||
let room_info = if clients_in_room.len() == 0 {
|
||||
dbg!("d");
|
||||
let room_info = if clients_in_room.is_empty() {
|
||||
String::from("Game is no longer active")
|
||||
}
|
||||
else {
|
||||
dbg!("d2");
|
||||
join_all(clients_in_room.iter()
|
||||
.map(|clientl| async move {
|
||||
dbg!("e");
|
||||
clients.with(clientl.client, |client| Box::pin(async move {
|
||||
dbg!("f");
|
||||
format!("{} Lv{} {}\n{} {}",
|
||||
client.character.name,
|
||||
LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp),
|
||||
|
@ -28,7 +28,7 @@ where
|
||||
let enemy_id = request_exp.enemy_id as usize;
|
||||
let enemy_exp = rooms.with(room_id, |room| Box::pin(async move {
|
||||
let monster = room.maps.enemy_by_id(enemy_id)?;
|
||||
let monster_stats = room.monster_stats.get(&monster.monster).ok_or(ShipError::UnknownMonster(monster.monster))?;
|
||||
let monster_stats = room.monster_stats.get(&monster.monster).ok_or_else(|| ShipError::UnknownMonster(monster.monster))?;
|
||||
Ok::<_, ShipError>(monster_stats.exp)
|
||||
})).await??;
|
||||
|
||||
@ -150,7 +150,7 @@ where
|
||||
})).await?;
|
||||
if let Some(drop_location) = drop_location {
|
||||
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
||||
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id).into());
|
||||
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id));
|
||||
}
|
||||
|
||||
if no_longer_has_item.item_id == 0xFFFFFFFF {
|
||||
@ -163,7 +163,7 @@ where
|
||||
})}).await??;
|
||||
|
||||
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?;
|
||||
let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount as u32);
|
||||
let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount);
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
Ok(clients_in_area.into_iter()
|
||||
@ -218,7 +218,7 @@ where
|
||||
.collect())
|
||||
}
|
||||
else {
|
||||
Err(ShipError::InvalidItem(ClientItemId(no_longer_has_item.item_id)).into())
|
||||
Err(ShipError::InvalidItem(ClientItemId(no_longer_has_item.item_id)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ pub async fn update_player_position(id: ClientId,
|
||||
_ => {},
|
||||
}
|
||||
Ok::<_, ShipError>(())
|
||||
})}).await?;
|
||||
})}).await??;
|
||||
}
|
||||
Ok(client_location.get_client_neighbors(id).await?.into_iter()
|
||||
.map(move |client| {
|
||||
|
@ -8,7 +8,6 @@ use crate::ship::location::{ClientLocation, ClientLocationError};
|
||||
use crate::ship::packet::builder::quest;
|
||||
use libpso::util::array_to_utf8;
|
||||
|
||||
// TOOD: enum
|
||||
enum QuestFileType {
|
||||
Bin,
|
||||
Dat
|
||||
@ -44,16 +43,6 @@ pub async fn send_quest_category_list(id: ClientId,
|
||||
rooms: &Rooms)
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
|
||||
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
/*
|
||||
let mut room = rooms.get_mut(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.write()
|
||||
.await;
|
||||
let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]);
|
||||
room.set_quest_group(rql.flag as usize);
|
||||
Ok(Box::new(vec![(id, SendShipPacket::QuestCategoryList(qcl))].into_iter()))
|
||||
*/
|
||||
let rql = rql.clone();
|
||||
rooms.with_mut(room_id, |room| Box::pin(async move {
|
||||
let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]);
|
||||
@ -71,7 +60,7 @@ pub async fn select_quest_category(id: ClientId,
|
||||
rooms.with(room_id, |room| Box::pin(async move {
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(menuselect.item as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(menuselect.item))?;
|
||||
.ok_or_else(|| ShipError::InvalidQuestCategory(menuselect.item as u16))?;
|
||||
|
||||
let ql = quest::quest_list(menuselect.item, category_quests);
|
||||
Ok(vec![(id, SendShipPacket::QuestOptionList(ql))])
|
||||
@ -88,12 +77,12 @@ pub async fn quest_detail(id: ClientId,
|
||||
rooms.with(room_id, |room| Box::pin(async move {
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(questdetailrequest.category as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(questdetailrequest.category as u32))?;
|
||||
.ok_or_else(|| ShipError::InvalidQuestCategory(questdetailrequest.category))?;
|
||||
|
||||
let quest = category_quests.iter()
|
||||
.find(|q| {
|
||||
q.id == questdetailrequest.quest as u16
|
||||
}).ok_or(ShipError::InvalidQuest(questdetailrequest.quest as u32))?;
|
||||
q.id == questdetailrequest.quest
|
||||
}).ok_or_else(|| ShipError::InvalidQuest(questdetailrequest.quest))?;
|
||||
|
||||
let qd = quest::quest_detail(quest);
|
||||
|
||||
@ -116,13 +105,13 @@ pub async fn player_chose_quest(id: ClientId,
|
||||
Box::pin(async move {
|
||||
let quest = room.quests[room.quest_group.value()].iter()
|
||||
.nth(questmenuselect.category as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidQuestCategory(questmenuselect.category))?
|
||||
.1
|
||||
.iter()
|
||||
.find(|q| {
|
||||
q.id == questmenuselect.quest as u16
|
||||
q.id == questmenuselect.quest
|
||||
})
|
||||
.ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidQuest(questmenuselect.quest))?
|
||||
.clone();
|
||||
|
||||
let rare_monster_drops = room.rare_monster_table.clone();
|
||||
@ -138,11 +127,6 @@ pub async fn player_chose_quest(id: ClientId,
|
||||
client.done_loading_quest = false;
|
||||
})).await?;
|
||||
}
|
||||
//area_clients.iter().for_each(|c| {
|
||||
//if let Some(client) = clients.get_mut(&c.client) {
|
||||
// client.done_loading_quest = false;
|
||||
//}
|
||||
//});
|
||||
Ok(area_clients
|
||||
.into_iter()
|
||||
.flat_map(move |c| {
|
||||
@ -150,53 +134,6 @@ pub async fn player_chose_quest(id: ClientId,
|
||||
})
|
||||
.collect())
|
||||
})}).await?
|
||||
/*
|
||||
let mut room = rooms.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.as_ref()
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.write()
|
||||
.await;
|
||||
/*
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(questmenuselect.category as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))?;
|
||||
|
||||
let quest = category_quests.iter()
|
||||
.find(|q| {
|
||||
q.id == questmenuselect.quest as u16
|
||||
}).ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))?
|
||||
.clone();
|
||||
*/
|
||||
|
||||
let quest = room.quests[room.quest_group.value()].iter()
|
||||
.nth(questmenuselect.category as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))?
|
||||
.1
|
||||
.iter()
|
||||
.find(|q| {
|
||||
q.id == questmenuselect.quest as u16
|
||||
})
|
||||
.ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))?
|
||||
.clone();
|
||||
|
||||
let rare_monster_drops = room.rare_monster_table.clone();
|
||||
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_drops);
|
||||
room.map_areas = quest.map_areas.clone();
|
||||
|
||||
let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin");
|
||||
let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat");
|
||||
|
||||
let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
area_clients.iter().for_each(|c| {
|
||||
if let Some(client) = clients.get_mut(&c.client) {
|
||||
client.done_loading_quest = false;
|
||||
}
|
||||
});
|
||||
Ok(Box::new(area_clients.into_iter().flat_map(move |c| {
|
||||
vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))]
|
||||
})))
|
||||
*/
|
||||
}
|
||||
|
||||
pub async fn quest_file_request(id: ClientId,
|
||||
@ -212,12 +149,12 @@ pub async fn quest_file_request(id: ClientId,
|
||||
let (category_id, quest_id, datatype) = parse_filename(&quest_file_request.filename)?;
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(category_id as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(category_id as u32))?;
|
||||
.ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?;
|
||||
|
||||
let quest = category_quests.iter()
|
||||
.find(|q| {
|
||||
q.id == quest_id as u16
|
||||
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
||||
q.id == quest_id
|
||||
}).ok_or_else(|| ShipError::InvalidQuest(quest_id))?;
|
||||
|
||||
let blob = match datatype {
|
||||
QuestFileType::Bin => &quest.bin_blob,
|
||||
@ -245,12 +182,12 @@ pub async fn quest_chunk_ack(id: ClientId,
|
||||
let (category_id, quest_id, datatype) = parse_filename(&quest_chunk_ack.filename)?;
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(category_id as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(category_id as u32))?;
|
||||
.ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?;
|
||||
|
||||
let quest = category_quests.iter()
|
||||
.find(|q| {
|
||||
q.id == quest_id
|
||||
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
||||
}).ok_or_else(|| ShipError::InvalidQuest(quest_id))?;
|
||||
|
||||
let blob = match datatype {
|
||||
QuestFileType::Bin => &quest.bin_blob,
|
||||
@ -268,41 +205,6 @@ pub async fn quest_chunk_ack(id: ClientId,
|
||||
|
||||
Ok(vec![(id, SendShipPacket::QuestChunk(qc))])
|
||||
})).await?
|
||||
|
||||
/*
|
||||
let mut room = rooms.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.write()
|
||||
.await
|
||||
.as_ref()
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||
|
||||
let (category_id, quest_id, datatype) = parse_filename(&quest_chunk_ack.filename)?;
|
||||
let (_, category_quests) = room.quests[room.quest_group.value()].iter()
|
||||
.nth(category_id as usize)
|
||||
.ok_or(ShipError::InvalidQuestCategory(category_id as u32))?;
|
||||
|
||||
let quest = category_quests.iter()
|
||||
.find(|q| {
|
||||
q.id == quest_id
|
||||
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
||||
|
||||
let blob = match datatype {
|
||||
QuestFileType::Bin => &quest.bin_blob,
|
||||
QuestFileType::Dat => &quest.dat_blob,
|
||||
};
|
||||
|
||||
let mut blob_cursor = Cursor::new(&**blob);
|
||||
blob_cursor.seek(SeekFrom::Start((quest_chunk_ack.chunk_num as u64 + 1) * 0x400))?;
|
||||
let mut subblob = [0u8; 0x400];
|
||||
let blob_length = blob_cursor.read(&mut subblob)?;
|
||||
if blob_length == 0 {
|
||||
return Ok(Box::new(None.into_iter()));
|
||||
}
|
||||
let qc = quest::quest_chunk(quest_chunk_ack.chunk_num + 1, quest_chunk_ack.filename, subblob, blob_length);
|
||||
|
||||
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
||||
*/
|
||||
}
|
||||
|
||||
pub async fn done_loading_quest(id: ClientId,
|
||||
@ -315,14 +217,14 @@ pub async fn done_loading_quest(id: ClientId,
|
||||
let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
let all_loaded = area_clients.iter()
|
||||
.map(|client| async {
|
||||
clients.with(client.client, |client| Box::pin(async move {
|
||||
client.done_loading_quest
|
||||
}))
|
||||
})
|
||||
.map(|client|
|
||||
clients.with(client.client, |client| Box::pin(async move {
|
||||
client.done_loading_quest
|
||||
}))
|
||||
)
|
||||
.collect::<FuturesOrdered<_>>()
|
||||
.all(|c| async move {
|
||||
c.await.unwrap_or(false)
|
||||
c.unwrap_or(false)
|
||||
}).await;
|
||||
|
||||
if all_loaded {
|
||||
|
@ -1,16 +1,16 @@
|
||||
use std::convert::{TryFrom, Into};
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
use crate::common::serverstate::ClientId;
|
||||
use crate::common::leveltable::LEVEL_TABLE;
|
||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients};
|
||||
use crate::ship::room::Rooms;
|
||||
use crate::ship::location::{ClientLocation, RoomId, RoomLobby, ClientLocationError, GetAreaError};
|
||||
use crate::ship::location::{ClientLocation, RoomId, RoomLobby, GetAreaError};
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::room;
|
||||
use crate::ship::items::state::ItemState;
|
||||
use std::convert::{TryFrom, Into};
|
||||
use async_std::sync::{Arc, RwLock};
|
||||
use futures::stream::{FuturesOrdered, StreamExt};
|
||||
|
||||
pub async fn create_room(id: ClientId,
|
||||
create_room: CreateRoom,
|
||||
@ -39,7 +39,6 @@ pub async fn create_room(id: ClientId,
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
let lobby_neighbors = client_location.get_client_neighbors(id).await?;
|
||||
|
||||
//let room_id = client_location.create_new_room(id).await.map_err(Into::<ClientLocationError>::into)?;
|
||||
let room_id = client_location.create_new_room(id).await?;
|
||||
let room = clients.with(id, |client| {
|
||||
let mut item_state = item_state.clone();
|
||||
@ -66,7 +65,6 @@ pub async fn create_room(id: ClientId,
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// TODO: remove unwraps
|
||||
pub async fn room_name_request(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
rooms: &Rooms)
|
||||
@ -81,7 +79,6 @@ pub async fn room_name_request(id: ClientId,
|
||||
})).await
|
||||
},
|
||||
RoomLobby::Lobby(_) => Err(GetAreaError::NotInRoom.into())
|
||||
//RoomLobby::Lobby(_) => Err(ShipError::ClientLocationError(GetAreaError::NotInRoom))
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,8 +122,7 @@ pub async fn join_room(id: ClientId,
|
||||
let original_room_clients = client_location.get_clients_in_room(room_id).await?;
|
||||
client_location.add_client_to_room(id, room_id).await?;
|
||||
let area_client = client_location.get_local_client(id).await?;
|
||||
//let original_leader = client_location.get_area_leader(original_area).await.unwrap();
|
||||
let room_leader = client_location.get_room_leader(room_id).await.unwrap();
|
||||
let room_leader = client_location.get_room_leader(room_id).await?;
|
||||
|
||||
clients.with(id, |client| {
|
||||
let mut item_state = item_state.clone();
|
||||
@ -138,14 +134,13 @@ pub async fn join_room(id: ClientId,
|
||||
let clients = clients.clone();
|
||||
let client_location = client_location.clone();
|
||||
Box::pin(async move {
|
||||
builder::room::join_room(id, &clients, &client_location, room_id, &room).await
|
||||
builder::room::join_room(id, &clients, &client_location, room_id, room).await
|
||||
})}).await??;
|
||||
let add_to = clients.with(id, |client| {
|
||||
let item_state = item_state.clone();
|
||||
Box::pin(async move {
|
||||
builder::room::add_to_room(id, client, &area_client, &room_leader, &item_state, room_id).await
|
||||
})}).await??;
|
||||
//let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), original_leader.local_client.id()));
|
||||
|
||||
rooms.with_mut(room_id, |room| Box::pin(async move {
|
||||
room.bursting = true;
|
||||
@ -161,7 +156,7 @@ pub async fn join_room(id: ClientId,
|
||||
async move {
|
||||
client_location.get_area_leader(original_area).await.ok().map(|leader| {
|
||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||
(c.client, leave_lobby.clone())
|
||||
(c.client, leave_lobby)
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -169,37 +164,6 @@ pub async fn join_room(id: ClientId,
|
||||
.await
|
||||
)
|
||||
.collect())
|
||||
|
||||
/*
|
||||
if let Ok(leader) = client_location.get_area_leader(original_area).await {
|
||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||
result.extend(original_neighbors.into_iter()
|
||||
.map(move |c| (c.client, leave_lobby.clone())))
|
||||
}
|
||||
*/
|
||||
|
||||
//Ok(result)
|
||||
/*
|
||||
|
||||
if let Some(room) = &mut *rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.write().await {
|
||||
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
||||
vec![(id, SendShipPacket::JoinRoom(join_room))]
|
||||
.into_iter()
|
||||
.chain(original_room_clients.into_iter()
|
||||
.map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone())))
|
||||
));
|
||||
|
||||
if let Ok(leader) = client_location.get_area_leader(original_area).await {
|
||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||
result = Box::new(result.chain(original_neighbors.into_iter()
|
||||
.map(move |c| (c.client, leave_lobby.clone()))))
|
||||
}
|
||||
|
||||
Ok(result.collect())
|
||||
} else {
|
||||
Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Game is no longer active".into())))])
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pub async fn done_bursting(id: ClientId,
|
||||
@ -230,7 +194,6 @@ pub async fn request_room_list(id: ClientId,
|
||||
client_location: &ClientLocation,
|
||||
rooms: &Rooms)
|
||||
-> Vec<(ClientId, SendShipPacket)> {
|
||||
//let active_room_list = futures::stream::iter(rooms.iter())
|
||||
let active_room_list = rooms.stream()
|
||||
.enumerate()
|
||||
.filter_map(|(i, r)| async move {
|
||||
@ -270,17 +233,16 @@ pub async fn request_room_list(id: ClientId,
|
||||
pub async fn cool_62(id: ClientId,
|
||||
cool_62: Like62ButCooler,
|
||||
client_location: &ClientLocation)
|
||||
-> Vec<(ClientId, SendShipPacket)> {
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
|
||||
let target = cool_62.flag as u8;
|
||||
let cool_62 = cool_62.clone();
|
||||
client_location
|
||||
Ok(client_location
|
||||
.get_client_neighbors(id)
|
||||
.await
|
||||
.unwrap()
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(move |client| client.local_client.id() == target)
|
||||
.map(move |client| {
|
||||
(client.client, SendShipPacket::Like62ButCooler(cool_62.clone()))
|
||||
})
|
||||
.collect()
|
||||
.collect())
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub fn block_list(id: ClientId, shipname: &str, num_blocks: usize) -> Vec<(Clien
|
||||
|
||||
pub fn selected_ship(id: ClientId, menuselect: MenuSelect, ship_list: &[Ship])
|
||||
-> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
|
||||
let ship = ship_list.get(menuselect.item as usize).ok_or(ShipError::InvalidShip(menuselect.item as usize))?;
|
||||
let ship = ship_list.get(menuselect.item as usize).ok_or_else(|| ShipError::InvalidShip(menuselect.item as usize))?;
|
||||
let ip = u32::from_ne_bytes(ship.ip.octets());
|
||||
Ok(vec![(id, SendShipPacket::RedirectClient(RedirectClient::new(ip, ship.port)))])
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ pub async fn trade_request(id: ClientId,
|
||||
this.meseta += amount as usize;
|
||||
}
|
||||
else {
|
||||
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||
|
||||
match &item.item {
|
||||
InventoryItemDetail::Individual(_) => {
|
||||
@ -192,7 +192,7 @@ pub async fn trade_request(id: ClientId,
|
||||
this.meseta -= amount as usize;
|
||||
}
|
||||
else {
|
||||
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||
|
||||
match &item.item {
|
||||
InventoryItemDetail::Individual(_) => {
|
||||
@ -207,9 +207,9 @@ pub async fn trade_request(id: ClientId,
|
||||
})
|
||||
.ok_or(TradeError::InvalidItemId(ClientItemId(item_id)))?;
|
||||
|
||||
match this.items[trade_item_index].stacked().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1.cmp(&(amount as usize)) {
|
||||
match this.items[trade_item_index].stacked().ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1.cmp(&(amount as usize)) {
|
||||
std::cmp::Ordering::Greater => {
|
||||
*this.items[trade_item_index].stacked_mut().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1 -= amount as usize;
|
||||
*this.items[trade_item_index].stacked_mut().ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1 -= amount as usize;
|
||||
},
|
||||
std::cmp::Ordering::Equal => {
|
||||
this.items.remove(trade_item_index);
|
||||
@ -314,7 +314,7 @@ async fn inner_items_to_trade(id: ClientId,
|
||||
Ok::<_, ShipError>((this, other_inventory))
|
||||
})}).await??;
|
||||
|
||||
if items_to_trade.count as usize != (this.items.len() + (if this.meseta != 0 { 1 } else { 0 })) {
|
||||
if items_to_trade.count as usize != (this.items.len() + usize::from(this.meseta != 0)) {
|
||||
return Err(TradeError::MismatchedTradeItems.into())
|
||||
}
|
||||
|
||||
@ -342,7 +342,7 @@ async fn inner_items_to_trade(id: ClientId,
|
||||
}
|
||||
else {
|
||||
let real_item = this_inventory.get_by_client_id(&ClientItemId(item.item_id))
|
||||
.ok_or(ItemStateError::InvalidItemId(ClientItemId(item.item_id)))?;
|
||||
.ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item.item_id)))?;
|
||||
let real_trade_item = this.items
|
||||
.iter()
|
||||
.find(|i| i.item_id() == ClientItemId(item.item_id))
|
||||
|
@ -1,16 +1,13 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::{From, Into, TryFrom, TryInto};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use async_std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::future::Future;
|
||||
use futures::stream::{Stream, StreamExt, FuturesOrdered};
|
||||
use async_std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||
use futures::future::BoxFuture;
|
||||
use futures::stream::{FuturesOrdered, Stream};
|
||||
|
||||
use thiserror::Error;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use crate::ship::map::Maps;
|
||||
use crate::ship::drops::DropTable;
|
||||
use crate::entity::character::SectionID;
|
||||
@ -19,8 +16,7 @@ use crate::ship::map::area::MapAreaLookup;
|
||||
use crate::ship::map::enemy::RareMonsterAppearTable;
|
||||
use crate::ship::quests;
|
||||
use crate::ship::ship::ShipError;
|
||||
|
||||
use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError, RoomId};
|
||||
use crate::ship::location::{MAX_ROOMS, RoomId};
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -32,28 +28,11 @@ impl Default for Rooms {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#[derive(escher::Rebindable)]
|
||||
struct BorrowedRoom<'a> {
|
||||
lock: RwLockReadGuard<'a, Option<RoomState>>,
|
||||
room: &'a Option<RoomState>,
|
||||
}
|
||||
|
||||
impl<'a> std::ops::Deref for BorrowedRoom<'a> {
|
||||
type Target = RoomState;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.room
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
impl Rooms {
|
||||
pub async fn add(&self, room_id: RoomId, room: RoomState) -> Result<(), ShipError> {
|
||||
*self.0
|
||||
.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.write()
|
||||
.await = Some(room);
|
||||
Ok(())
|
||||
@ -86,7 +65,7 @@ impl Rooms {
|
||||
{
|
||||
let room = self.0
|
||||
.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.read()
|
||||
.await;
|
||||
if let Some(room) = room.as_ref() {
|
||||
@ -104,7 +83,7 @@ impl Rooms {
|
||||
{
|
||||
let mut room = self.0
|
||||
.get(room_id.0)
|
||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?
|
||||
.write()
|
||||
.await;
|
||||
|
||||
@ -116,7 +95,7 @@ impl Rooms {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get<'a>(&'a self, room_id: RoomId) -> RwLockReadGuard<'a, Option<RoomState>> {
|
||||
pub async fn get(&self, room_id: RoomId) -> RwLockReadGuard<Option<RoomState>> {
|
||||
self.0
|
||||
.get(room_id.0)
|
||||
.unwrap()
|
||||
@ -124,7 +103,7 @@ impl Rooms {
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn stream<'a>(&'a self) -> impl Stream<Item = RwLockReadGuard<'a, Option<RoomState>>> + 'a {
|
||||
pub fn stream(&self) -> impl Stream<Item = RwLockReadGuard<Option<RoomState>>> {
|
||||
self.0
|
||||
.iter()
|
||||
.map(|room| async move {
|
||||
@ -136,11 +115,6 @@ impl Rooms {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("")]
|
||||
pub enum RoomCreationError {
|
||||
|
227
src/ship/ship.rs
227
src/ship/ship.rs
@ -9,7 +9,7 @@ use rand::Rng;
|
||||
use thiserror::Error;
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::login::{RedirectClient, Login, LoginResponse, Session, ShipList};
|
||||
use libpso::packet::login::{RedirectClient, Login, LoginResponse, ShipList};
|
||||
use libpso::packet::messages::*;
|
||||
use libpso::{PacketParseError, PSOPacket};
|
||||
use libpso::crypto::bb::PSOBBCipher;
|
||||
@ -24,17 +24,15 @@ use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, Lo
|
||||
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};
|
||||
use crate::entity::item;
|
||||
use crate::entity::character::SectionID;
|
||||
|
||||
use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError, RoomId};
|
||||
use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId};
|
||||
|
||||
use crate::ship::items;
|
||||
use crate::ship::room;
|
||||
use crate::ship::map::{MapsError, MapAreaError, MapArea};
|
||||
use crate::ship::map::{MapsError, MapAreaError};
|
||||
use crate::ship::packet::handler;
|
||||
use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem};
|
||||
use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop};
|
||||
use crate::ship::trade::TradeState;
|
||||
|
||||
// TODO: remove once stuff settles down
|
||||
@ -56,16 +54,7 @@ pub enum ShipError {
|
||||
#[error("too many clients")]
|
||||
TooManyClients,
|
||||
#[error("client error location {0}")]
|
||||
//ClientLocationError(#[from] ClientLocationError),
|
||||
ClientLocationError(ClientLocationError),
|
||||
/*
|
||||
#[error("get neighbor error {0}")]
|
||||
GetNeighborError(#[from] GetNeighborError),
|
||||
#[error("get clients error {0}")]
|
||||
GetClientsError(#[from] GetClientsError),
|
||||
#[error("get area error {0}")]
|
||||
GetAreaError(#[from] GetAreaError),
|
||||
*/
|
||||
#[error("maps error {0}")]
|
||||
MapsError(#[from] MapsError),
|
||||
#[error("map area error {0}")]
|
||||
@ -89,9 +78,9 @@ pub enum ShipError {
|
||||
#[error("box already dropped item {0} {1}")]
|
||||
BoxAlreadyDroppedItem(ClientId, u16),
|
||||
#[error("invalid quest category {0}")]
|
||||
InvalidQuestCategory(u32),
|
||||
InvalidQuestCategory(u16),
|
||||
#[error("invalid quest {0}")]
|
||||
InvalidQuest(u32),
|
||||
InvalidQuest(u16),
|
||||
#[error("invalid quest filename {0}")]
|
||||
InvalidQuestFilename(String),
|
||||
#[error("io error {0}")]
|
||||
@ -118,24 +107,10 @@ pub enum ShipError {
|
||||
MessageError(#[from] crate::ship::packet::handler::direct_message::MessageError),
|
||||
#[error("room creation error {0}")]
|
||||
RoomCreationError(#[from] room::RoomCreationError),
|
||||
#[error("channel send error {0}")]
|
||||
SendError(#[from] async_std::channel::SendError<ShipMessage>),
|
||||
}
|
||||
|
||||
/*
|
||||
impl From<ClientLocationError> for ShipError {
|
||||
fn from(other: &ClientLocationError) -> ShipError {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
impl<I: Into<ClientLocationError>> Into<ShipError> for I {
|
||||
fn into(other: I) -> ShipError {
|
||||
ShipError::ClientLocationError(other.into())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl<I: Into<ClientLocationError>> From<I> for ShipError {
|
||||
fn from(other: I) -> ShipError {
|
||||
ShipError::ClientLocationError(other.into())
|
||||
@ -420,45 +395,23 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerStateBuilder<EG> {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Block {
|
||||
client_location: ClientLocation,
|
||||
pub rooms: room::Rooms,
|
||||
}
|
||||
|
||||
impl Default for Block {
|
||||
fn default() -> Block {
|
||||
Block {
|
||||
client_location: ClientLocation::default(),
|
||||
rooms: room::Rooms::default(),
|
||||
//rooms: core::array::from_fn(|_| Arc::new(RwLock::new(None))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl Block {
|
||||
fn with<F, T>(&self, func: F) -> T
|
||||
where
|
||||
T: Send,
|
||||
F: FnOnce(&Block) -> T,
|
||||
{
|
||||
func(self)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Blocks(pub Vec<Block>);
|
||||
|
||||
impl Blocks {
|
||||
async fn from_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> {
|
||||
async fn get_from_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> {
|
||||
let block = clients.with(id, |client| Box::pin(async move {
|
||||
client.block
|
||||
})).await?;
|
||||
self.0
|
||||
.get_mut(block)
|
||||
.ok_or(ShipError::InvalidBlock(block))
|
||||
.ok_or_else(|| ShipError::InvalidBlock(block))
|
||||
}
|
||||
|
||||
}
|
||||
@ -477,7 +430,6 @@ pub struct ShipServerState<EG: EntityGateway + Clone + 'static> {
|
||||
|
||||
auth_token: AuthToken,
|
||||
ship_list: Vec<Ship>,
|
||||
//shipgate_sender: Option<Box<dyn Fn(ShipMessage) + Send + Sync>>,
|
||||
shipgate_sender: Option<channel::Sender<ShipMessage>>,
|
||||
trades: TradeState,
|
||||
}
|
||||
@ -490,42 +442,42 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
||||
async fn message(&mut self, id: ClientId, msg: Message) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||
Ok(match msg.msg {
|
||||
GameMessage::RequestExp(request_exp) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms).await?
|
||||
},
|
||||
GameMessage::PlayerDropItem(player_drop_item) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
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?
|
||||
},
|
||||
GameMessage::DropCoordinates(drop_coordinates) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &self.clients, &block.rooms).await?
|
||||
},
|
||||
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
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?
|
||||
},
|
||||
GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
|
||||
GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
|
||||
GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
|
||||
GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::update_player_position(id, msg, &self.clients, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
GameMessage::ChargeAttack(charge_attack) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::PlayerUseItem(player_use_item) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
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?
|
||||
},
|
||||
GameMessage::PlayerFeedMag(player_feed_mag) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::message::player_feed_mag(id, player_feed_mag, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::PlayerEquipItem(player_equip_item) => {
|
||||
@ -538,11 +490,11 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
||||
handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::PlayerSoldItem(player_sold_item) => {
|
||||
handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await?
|
||||
handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
_ => {
|
||||
let cmsg = msg.clone();
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
block.client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||
.map(move |client| {
|
||||
(client.client, SendShipPacket::Message(cmsg.clone()))
|
||||
@ -554,7 +506,7 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
||||
|
||||
async fn direct_message(&mut self, id: ClientId, msg: DirectMessage) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||
let target = msg.flag;
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
Ok(match msg.msg {
|
||||
GameMessage::GuildcardSend(guildcard_send) => {
|
||||
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients).await?
|
||||
@ -575,7 +527,7 @@ impl<EG: EntityGateway + Clone + 'static> ShipServerState<EG> {
|
||||
handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::ShopRequest(shop_request) => {
|
||||
handler::direct_message::shop_request(id, shop_request, &block.client_location, &self.clients, &block.rooms, &mut self.shops).await?
|
||||
handler::direct_message::shop_request(id, shop_request, &block.client_location, &self.clients, &block.rooms, &self.shops).await?
|
||||
},
|
||||
GameMessage::BuyItem(buy_item) => {
|
||||
handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await?
|
||||
@ -630,11 +582,6 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
||||
})).await {
|
||||
self.entity_gateway.set_character_playtime(&char_id, char_playtime).await?;
|
||||
}
|
||||
/*
|
||||
if let Some(client) = self.clients.get_mut(&id) {
|
||||
client.update_playtime();
|
||||
self.entity_gateway.set_character_playtime(&client.character.id, client.character.playtime).await?;
|
||||
}*/
|
||||
|
||||
Ok(match pkt {
|
||||
RecvShipPacket::Login(login) => {
|
||||
@ -645,14 +592,14 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
||||
.collect()
|
||||
},
|
||||
RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
match questdetailrequest.menu {
|
||||
QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &mut block.rooms).await?,
|
||||
QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &block.rooms).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
},
|
||||
RecvShipPacket::MenuSelect(menuselect) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
match menuselect.menu {
|
||||
SHIP_MENU_ID => {
|
||||
let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().into_iter().flatten();
|
||||
@ -664,73 +611,39 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
||||
let select_block = handler::lobby::block_selected(id, menuselect, &self.clients, &self.item_state).await?.into_iter();
|
||||
leave_lobby.chain(select_block).collect()
|
||||
}
|
||||
ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &self.clients, &mut self.item_state, &mut block.rooms).await?,
|
||||
QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &mut block.rooms).await?,
|
||||
ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await?,
|
||||
QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &block.rooms).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
},
|
||||
RecvShipPacket::QuestMenuSelect(questmenuselect) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::quest::player_chose_quest(id, questmenuselect, &mut self.clients, &block.client_location, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::quest::player_chose_quest(id, questmenuselect, &self.clients, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::MenuDetail(menudetail) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients).await?
|
||||
},
|
||||
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
|
||||
/*
|
||||
let password = room_password_req.password;
|
||||
let correct_password = block.rooms.with(RoomId(room_password_req.item as usize), |room| Box::pin(async move {
|
||||
password == room.password
|
||||
})).await?;
|
||||
*/
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
|
||||
let room_password = block.rooms.with(RoomId(room_password_req.item as usize), |room| Box::pin(async move {
|
||||
room.password
|
||||
})).await?;
|
||||
|
||||
/*
|
||||
let correct_password = room_password_req.password == block.rooms
|
||||
.get(RoomId(room_password_req.item as usize))
|
||||
.await
|
||||
.map(|room| room.password)
|
||||
.unwrap_or_else(false);
|
||||
*/
|
||||
|
||||
//if correct_password {
|
||||
if room_password_req.password == room_password {
|
||||
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_state, &mut block.rooms).await?
|
||||
handler::room::join_room(id, menuselect, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await?
|
||||
}
|
||||
else {
|
||||
vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))]
|
||||
}
|
||||
|
||||
/*
|
||||
if room_password_req.password == block.rooms[room_password_req.item as usize]
|
||||
.read()
|
||||
.await
|
||||
.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 block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await?
|
||||
}
|
||||
else {
|
||||
Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter())
|
||||
}
|
||||
*/
|
||||
},
|
||||
RecvShipPacket::CharData(chardata) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state).await?
|
||||
},
|
||||
RecvShipPacket::Message(msg) => {
|
||||
@ -740,65 +653,65 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
||||
self.direct_message(id, msg).await?
|
||||
},
|
||||
RecvShipPacket::PlayerChat(msg) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::communication::player_chat(id, msg, &block.client_location, &self.clients).await?
|
||||
},
|
||||
RecvShipPacket::CreateRoom(create_room) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::create_room(id, create_room, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::RoomNameRequest(_req) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::room_name_request(id, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::UpdateConfig(pkt) => {
|
||||
handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await?
|
||||
handler::settings::update_config(id, pkt, &self.clients, &mut self.entity_gateway).await?
|
||||
},
|
||||
RecvShipPacket::ViewInfoboardRequest(_pkt) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::communication::request_infoboard(id, &block.client_location, &self.clients).await?
|
||||
},
|
||||
RecvShipPacket::WriteInfoboard(pkt) => {
|
||||
handler::communication::write_infoboard(id, pkt, &self.clients, &mut self.entity_gateway).await?
|
||||
},
|
||||
RecvShipPacket::RoomListRequest(_req) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::request_room_list(id, &block.client_location, &block.rooms).await
|
||||
},
|
||||
RecvShipPacket::Like62ButCooler(cool62) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::room::cool_62(id, cool62, &block.client_location).await
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::cool_62(id, cool62, &block.client_location).await?
|
||||
},
|
||||
RecvShipPacket::ClientCharacterData(_) => {
|
||||
// TOOD: validate this in some way?
|
||||
Vec::new()
|
||||
},
|
||||
RecvShipPacket::DoneBursting(_) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::done_bursting(id, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::DoneBursting2(_) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::room::done_bursting(id, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::LobbySelect(pkt) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &mut block.rooms, &mut self.entity_gateway).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, &mut self.entity_gateway).await?
|
||||
},
|
||||
RecvShipPacket::RequestQuestList(rql) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::quest::send_quest_category_list(id, rql, &block.client_location, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::quest::send_quest_category_list(id, rql, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::QuestFileRequest(quest_file_request) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::quest::quest_file_request(id, quest_file_request, &block.client_location, &mut block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &mut block.rooms).await?
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &block.rooms).await?
|
||||
},
|
||||
RecvShipPacket::DoneLoadingQuest(_) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::quest::done_loading_quest(id, &self.clients, &block.client_location).await?
|
||||
},
|
||||
RecvShipPacket::FullCharacterData(_full_character_data) => {
|
||||
@ -814,11 +727,11 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
||||
handler::ship::block_list(id, &self.name, self.blocks.0.len())
|
||||
},
|
||||
RecvShipPacket::ItemsToTrade(items_to_trade) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::trade::items_to_trade(id, items_to_trade, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await?
|
||||
},
|
||||
RecvShipPacket::TradeConfirmed(_) => {
|
||||
let block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await?
|
||||
},
|
||||
RecvShipPacket::KeyboardConfig(keyboard_config) => {
|
||||
@ -832,7 +745,7 @@ impl<EG: EntityGateway + Clone> 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 block = self.blocks.from_client(id, &self.clients).await?;
|
||||
let block = self.blocks.get_from_client(id, &self.clients).await?;
|
||||
let area_client = block.client_location.get_local_client(id).await?;
|
||||
let neighbors = block.client_location.get_client_neighbors(id).await?;
|
||||
|
||||
@ -886,7 +799,7 @@ impl<EG: EntityGateway + Clone> InterserverActor for ShipServerState<EG> {
|
||||
async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
vec![
|
||||
(id, ShipMessage::Authenticate(self.auth_token.clone())),
|
||||
(id, ShipMessage::NewShip(Ship {
|
||||
(id, ShipMessage::NewShip(Ship {
|
||||
name: self.name.clone(),
|
||||
ip: self.ip,
|
||||
port: self.port,
|
||||
@ -896,7 +809,7 @@ impl<EG: EntityGateway + Clone> InterserverActor for ShipServerState<EG> {
|
||||
]
|
||||
}
|
||||
|
||||
async fn on_action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
|
||||
async fn on_action(&mut self, _id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
|
||||
match msg {
|
||||
LoginMessage::SendMail{..} => {
|
||||
Ok(Vec::new())
|
||||
@ -923,7 +836,7 @@ impl<EG: EntityGateway + Clone> InterserverActor for ShipServerState<EG> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn set_sender(&mut self, _server_id: ServerId, sender: channel::Sender<Self::SendMessage>) {
|
||||
async fn set_sender(&mut self, _server_id: ServerId, sender: channel::Sender<Self::SendMessage>) {
|
||||
self.shipgate_sender = Some(sender);
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ impl ShopItem for ArmorShopItem {
|
||||
armor: frame.armor,
|
||||
dfp: 0,
|
||||
evp: 0,
|
||||
slots: frame.slots as u8,
|
||||
slots: frame.slots,
|
||||
})
|
||||
},
|
||||
ArmorShopItem::Barrier(barrier) => {
|
||||
|
@ -49,7 +49,7 @@ async fn test_character_gains_exp() {
|
||||
|
||||
ship.clients.with(ClientId(1), |client| Box::pin(async move {
|
||||
assert!(exp == client.character.exp);
|
||||
})).await;
|
||||
})).await.unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -133,9 +133,9 @@ async fn test_character_levels_up_multiple_times() {
|
||||
|
||||
assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 8, ..})})));
|
||||
|
||||
let c1 = ship.clients.with(ClientId(1), |client| Box::pin(async move {
|
||||
ship.clients.with(ClientId(1), |client| Box::pin(async move {
|
||||
assert!(exp == client.character.exp);
|
||||
})).await;
|
||||
})).await.unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user