fix more tests + fix warnings
This commit is contained in:
parent
174445c175
commit
b3e0674ca5
109
src/bin/main.rs
109
src/bin/main.rs
@ -1,11 +1,9 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::time::SystemTime;
|
||||
use log::{info};
|
||||
|
||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
||||
use elseware::login::login::LoginServerState;
|
||||
use elseware::login::character::CharacterServerState;
|
||||
use elseware::ship::ship::ShipServerState;
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||
@ -64,10 +62,10 @@ fn main() {
|
||||
flags: 0,
|
||||
};
|
||||
let fake_user = entity_gateway.create_user(fake_user).await.unwrap();
|
||||
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await;
|
||||
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap();
|
||||
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||
character.name = format!("Test Char {}", i*2);
|
||||
entity_gateway.create_character(character).await;
|
||||
entity_gateway.create_character(character).await.unwrap();
|
||||
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||
character.slot = 2;
|
||||
character.name = "ItemRefactor".into();
|
||||
@ -75,6 +73,41 @@ fn main() {
|
||||
character.meseta = 999999;
|
||||
let character = entity_gateway.create_character(character).await.unwrap();
|
||||
|
||||
for _ in 0..3 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Vulcan,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
modifiers: Vec::new(),
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await.unwrap();
|
||||
}
|
||||
|
||||
for _ in 0..8 {
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await.unwrap();
|
||||
}
|
||||
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -94,7 +127,7 @@ fn main() {
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -114,7 +147,7 @@ fn main() {
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -134,7 +167,7 @@ fn main() {
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -154,7 +187,7 @@ fn main() {
|
||||
slot: 3,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -174,7 +207,59 @@ fn main() {
|
||||
slot: 4,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
|
||||
let mag = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(item::mag::Mag::baby_mag(0)),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 5,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
for _ in 0..10 {
|
||||
let fed_tool = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::FedToMag {
|
||||
mag: mag.id,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap();
|
||||
}
|
||||
//entity_gateway.bank(&mag.id).await;
|
||||
entity_gateway.change_mag_owner(&mag.id, &character).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::CellOfMag502,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 6,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
let cell = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::CellOfMag502,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Consumed,
|
||||
}).await.unwrap();
|
||||
entity_gateway.use_mag_cell(&mag.id, &cell.id).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
@ -326,7 +411,7 @@ fn main() {
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
info!("[ship] starting server");
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
.name("Sona-Nyl".into())
|
||||
.name("US/Sona-Nyl".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT)
|
||||
.gateway(thread_entity_gateway)
|
||||
@ -335,7 +420,7 @@ fn main() {
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
.name("Dylath-Leen".into())
|
||||
.name("EU/Dylath-Leen".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+2000)
|
||||
.gateway(thread_entity_gateway)
|
||||
@ -344,7 +429,7 @@ fn main() {
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
.name("Thalarion".into())
|
||||
.name("JP/Thalarion".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+3000)
|
||||
.gateway(thread_entity_gateway)
|
||||
|
@ -1,6 +1,5 @@
|
||||
use log::{info};
|
||||
use elseware::entity::gateway::postgres::PostgresGateway;
|
||||
use elseware::ship::ship::ShipServerState;
|
||||
use elseware::ship::ship::ShipServerStateBuilder;
|
||||
use elseware::common::mainloop::ship_mainloop;
|
||||
|
||||
|
@ -139,65 +139,6 @@ enum ServerStateAction<S> {
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
async fn server_state_loop<STATE, S, R, E>(mut state: STATE,
|
||||
server_state_receiver: async_std::sync::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();
|
||||
|
||||
match action {
|
||||
ClientAction::NewClient(client_id, sender) => {
|
||||
clients.insert(client_id, sender.clone());
|
||||
for action in state.on_connect(client_id) {
|
||||
match action {
|
||||
OnConnect::Cipher((inc, outc)) => {
|
||||
sender.send(ServerStateAction::Cipher(inc, outc)).await;
|
||||
},
|
||||
OnConnect::Packet(pkt) => {
|
||||
sender.send(ServerStateAction::Packet(pkt)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client {:?} state handler error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientAction::Disconnect(client_id) => {
|
||||
let pkts = state.on_disconnect(client_id);
|
||||
for (client_id, pkt) in pkts {
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Packet(pkt)).await;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.send(ServerStateAction::Disconnect).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn client_recv_loop<S, R>(client_id: ClientId,
|
||||
socket: Arc<async_std::net::TcpStream>,
|
||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
|
@ -1,6 +1,3 @@
|
||||
#![allow(dead_code)]
|
||||
use std::time::SystemTime;
|
||||
|
||||
use libpso::character::settings;
|
||||
use libpso::character::guildcard;
|
||||
|
||||
|
@ -1,18 +1,13 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::Into;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use futures::TryStreamExt;
|
||||
use libpso::character::{settings, guildcard};
|
||||
use libpso::character::settings;
|
||||
use libpso::util::vec_to_array;
|
||||
use crate::entity::account::*;
|
||||
use crate::entity::character::*;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::item::*;
|
||||
use crate::ship::map::MapArea;
|
||||
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use sqlx::Row;
|
||||
use sqlx::Execute;
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgUserAccount {
|
||||
id: i32,
|
||||
|
@ -1,12 +1,8 @@
|
||||
use std::convert::{From, TryFrom, Into, TryInto};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::convert::{From, TryFrom, Into};
|
||||
use futures::future::join_all;
|
||||
use futures::TryStreamExt;
|
||||
//use futures::StreamExt;
|
||||
use async_std::stream::StreamExt;
|
||||
//use futures::StreamExt;
|
||||
use libpso::character::{settings, guildcard};
|
||||
use libpso::util::vec_to_array;
|
||||
use libpso::character::guildcard;
|
||||
use crate::entity::account::*;
|
||||
use crate::entity::character::*;
|
||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||
|
@ -24,7 +24,7 @@ use crate::entity::item::weapon::Weapon;
|
||||
use crate::entity::item::armor::Armor;
|
||||
use crate::entity::item::tech::Technique;
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::entity::item::mag::{Mag, MagType};
|
||||
use crate::entity::item::mag::Mag;
|
||||
use crate::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel};
|
||||
|
||||
use crate::login::login::get_login_status;
|
||||
@ -184,7 +184,6 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
}
|
||||
|
||||
character.meseta = 300;
|
||||
|
||||
let character = entity_gateway.create_character(character).await.unwrap();
|
||||
|
||||
let new_weapon = match character.char_class {
|
||||
@ -209,7 +208,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
character_id: character.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}}).await;
|
||||
}}).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
@ -225,7 +224,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
character_id: character.id,
|
||||
slot: 1,
|
||||
equipped: true,
|
||||
}}).await;
|
||||
}}).await.unwrap();
|
||||
|
||||
let mut mag = Mag::baby_mag(character.appearance.skin);
|
||||
mag.change_owner(character.char_class, character.section_id);
|
||||
@ -236,7 +235,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
character_id: character.id,
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
}}).await;
|
||||
}}).await.unwrap();
|
||||
|
||||
for _ in 0..4 {
|
||||
entity_gateway.create_item(
|
||||
@ -249,7 +248,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
character_id: character.id,
|
||||
slot: 3,
|
||||
equipped: false,
|
||||
}}).await;
|
||||
}}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
@ -260,7 +259,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
character_id: character.id,
|
||||
slot: 4,
|
||||
equipped: false,
|
||||
}}).await;
|
||||
}}).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,7 +405,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||
let mut user = client.user.as_mut().unwrap();
|
||||
user.flags = setflag.flags;
|
||||
self.entity_gateway.save_user(&user).await;
|
||||
self.entity_gateway.save_user(&user).await.unwrap();
|
||||
Ok(None.into_iter())
|
||||
}
|
||||
|
||||
@ -444,7 +443,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
||||
client.session.action = SessionAction::SelectCharacter;
|
||||
client.session.character_slot = preview.slot as u8;
|
||||
user.flags = 0;
|
||||
self.entity_gateway.save_user(&user).await;
|
||||
self.entity_gateway.save_user(&user).await.unwrap();
|
||||
Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard,
|
||||
user.team_id.unwrap_or(1),
|
||||
client.session)),
|
||||
@ -543,7 +542,7 @@ impl<EG: EntityGateway> InterserverActor for CharacterServerState<EG> {
|
||||
type RecvMessage = ShipMessage;
|
||||
type Error = ();
|
||||
|
||||
async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
async fn on_connect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
@ -652,8 +651,7 @@ mod test {
|
||||
use super::*;
|
||||
use crate::entity::account::*;
|
||||
use libpso::character::{settings, character};
|
||||
use std::time::SystemTime;
|
||||
use crate::entity::gateway::{InMemoryGateway};
|
||||
use crate::entity::gateway::{InMemoryGateway, GatewayError};
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_option_send() {
|
||||
@ -663,8 +661,8 @@ mod test {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for TestData {
|
||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
||||
Some(UserSettingsEntity {
|
||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||
Ok(UserSettingsEntity {
|
||||
id: UserSettingsId(0),
|
||||
user_id: user.id,
|
||||
settings: settings::UserSettings::default()
|
||||
@ -684,6 +682,7 @@ mod test {
|
||||
created_at: chrono::Utc::now(),
|
||||
team_id: None,
|
||||
flags: 0,
|
||||
activated: true,
|
||||
});
|
||||
server.clients.insert(ClientId(5), clientstate);
|
||||
|
||||
@ -727,6 +726,7 @@ mod test {
|
||||
muted_until: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
flags: 0,
|
||||
activated: true,
|
||||
});
|
||||
|
||||
let mut server = CharacterServerState::new(test_data.clone());
|
||||
@ -762,7 +762,7 @@ mod test {
|
||||
} })).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(send.len() == 2);
|
||||
|
||||
let chars = test_data.get_characters_by_user(&fake_user.user.unwrap()).await;
|
||||
let chars = test_data.get_characters_by_user(&fake_user.user.unwrap()).await.unwrap();
|
||||
assert!(chars[1].as_ref().unwrap().name == "\tEtest name");
|
||||
assert!(chars[0].is_none());
|
||||
}
|
||||
|
@ -144,9 +144,9 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::time::SystemTime;
|
||||
use super::*;
|
||||
use crate::entity::account::{UserAccountId};
|
||||
use crate::entity::gateway::GatewayError;
|
||||
|
||||
const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login {
|
||||
tag: 65536,
|
||||
@ -180,9 +180,9 @@ mod test {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for TestData {
|
||||
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||
async fn get_user_by_name(&self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||
assert!(name == "testuser");
|
||||
Some(UserAccountEntity {
|
||||
Ok(UserAccountEntity {
|
||||
id: UserAccountId(1),
|
||||
username: "testuser".to_owned(),
|
||||
password: bcrypt::hash("mypassword", 5).unwrap(),
|
||||
@ -192,11 +192,12 @@ mod test {
|
||||
muted_until: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
flags: 0,
|
||||
activated: true,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let mut server = LoginServerState::new(TestData {});
|
||||
let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap());
|
||||
|
||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(send == vec![
|
||||
@ -230,12 +231,12 @@ mod test {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for TestData {
|
||||
async fn get_user_by_name(&self, _name: String) -> Option<UserAccountEntity> {
|
||||
None
|
||||
async fn get_user_by_name(&self, _name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||
Err(GatewayError::Error)
|
||||
}
|
||||
}
|
||||
|
||||
let mut server = LoginServerState::new(TestData {});
|
||||
let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap());
|
||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(send == vec![
|
||||
@ -264,9 +265,9 @@ mod test {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for TestData {
|
||||
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||
async fn get_user_by_name(&self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||
assert!(name == "testuser");
|
||||
Some(UserAccountEntity {
|
||||
Ok(UserAccountEntity {
|
||||
id: UserAccountId(1),
|
||||
username: "testuser".to_owned(),
|
||||
password: bcrypt::hash("notpassword", 5).unwrap(),
|
||||
@ -276,11 +277,12 @@ mod test {
|
||||
muted_until: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
flags: 0,
|
||||
activated: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let mut server = LoginServerState::new(TestData {});
|
||||
let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap());
|
||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(send == vec![
|
||||
@ -309,9 +311,9 @@ mod test {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for TestData {
|
||||
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||
async fn get_user_by_name(&self, name: String) -> Result<UserAccountEntity, GatewayError> {
|
||||
assert!(name == "testuser");
|
||||
Some(UserAccountEntity {
|
||||
Ok(UserAccountEntity {
|
||||
id: UserAccountId(1),
|
||||
username: "testuser".to_owned(),
|
||||
password: bcrypt::hash("mypassword", 5).unwrap(),
|
||||
@ -321,11 +323,12 @@ mod test {
|
||||
muted_until: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
flags: 0,
|
||||
activated: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let mut server = LoginServerState::new(TestData {});
|
||||
let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap());
|
||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(send == vec![
|
||||
|
@ -136,7 +136,7 @@ impl RareDropTable {
|
||||
tool: tool,
|
||||
})
|
||||
},
|
||||
RareDropItem::Mag(mag) => {
|
||||
RareDropItem::Mag(_mag) => {
|
||||
ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18)))
|
||||
}
|
||||
}
|
||||
|
@ -305,9 +305,9 @@ impl ItemManager {
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}
|
||||
).await;
|
||||
).await?;
|
||||
if let Some(_) = new_inventory_item.mag() {
|
||||
entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await;
|
||||
entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await?;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
@ -329,7 +329,7 @@ impl ItemManager {
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}
|
||||
).await;
|
||||
).await?;
|
||||
}
|
||||
|
||||
if stacked_floor_item.count() != new_inventory_item.count() {
|
||||
@ -349,7 +349,7 @@ impl ItemManager {
|
||||
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
|
||||
}
|
||||
character.meseta = std::cmp::min(character.meseta + meseta_floor_item.meseta.0, 999999);
|
||||
entity_gateway.save_character(&character).await;
|
||||
entity_gateway.save_character(&character).await?;
|
||||
TriggerCreateItem::No
|
||||
},
|
||||
None => {
|
||||
@ -470,7 +470,7 @@ impl ItemManager {
|
||||
y: item_drop_location.2,
|
||||
z: item_drop_location.3,
|
||||
}
|
||||
).await;
|
||||
).await?;
|
||||
},
|
||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||
let stacked_floor_item = shared_floor.drop_stacked_inventory_item(stacked_inventory_item, item_drop_location);
|
||||
@ -483,7 +483,7 @@ impl ItemManager {
|
||||
y: item_drop_location.2,
|
||||
z: item_drop_location.3,
|
||||
}
|
||||
).await;
|
||||
).await?;
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -504,7 +504,7 @@ impl ItemManager {
|
||||
return Err(ItemManagerError::CouldNotDropMeseta)
|
||||
}
|
||||
character.meseta -= amount;
|
||||
entity_gateway.save_character(&character).await;
|
||||
entity_gateway.save_character(&character).await?;
|
||||
|
||||
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
||||
let floor_item = FloorItem::Meseta(MesetaFloorItem {
|
||||
@ -547,7 +547,7 @@ impl ItemManager {
|
||||
y: 0.0,
|
||||
z: drop_location.z,
|
||||
}
|
||||
).await;
|
||||
).await?;
|
||||
}
|
||||
|
||||
Ok(stacked_floor_item)
|
||||
@ -565,10 +565,10 @@ impl ItemManager {
|
||||
|
||||
for entity_id in consumed_item.entity_ids() {
|
||||
entity_gateway.change_item_location(&entity_id,
|
||||
ItemLocation::Consumed).await;
|
||||
ItemLocation::Consumed).await?;
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
Ok(consumed_item)
|
||||
}
|
||||
|
||||
@ -592,7 +592,7 @@ impl ItemManager {
|
||||
ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: BankName("".to_string())
|
||||
}).await;
|
||||
}).await?;
|
||||
},
|
||||
BankItem::Stacked(stacked_bank_item) => {
|
||||
for entity_id in &stacked_bank_item.entity_ids {
|
||||
@ -600,12 +600,12 @@ impl ItemManager {
|
||||
ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: BankName("".to_string())
|
||||
}).await;
|
||||
}).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -631,7 +631,7 @@ impl ItemManager {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await;
|
||||
}).await?;
|
||||
},
|
||||
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
|
||||
for entity_id in &stacked_inventory_item.entity_ids {
|
||||
@ -640,7 +640,7 @@ impl ItemManager {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await;
|
||||
}).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -676,13 +676,13 @@ impl ItemManager {
|
||||
mag.feed(consumed_tool_type);
|
||||
|
||||
for entity_id in consumed_tool.entity_ids() {
|
||||
entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await;
|
||||
entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await?;
|
||||
entity_gateway.change_item_location(&entity_id, ItemLocation::FedToMag {
|
||||
mag: individual_item.entity_id,
|
||||
}).await;
|
||||
}).await?;
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -796,7 +796,7 @@ impl ItemManager {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -838,7 +838,7 @@ impl ItemManager {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
||||
}).await?;
|
||||
}
|
||||
picked_up_item.item_id
|
||||
};
|
||||
|
@ -1,14 +1,8 @@
|
||||
use thiserror::Error;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::character::CharacterEntity;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail};
|
||||
use crate::entity::item::tool::ToolType;
|
||||
use crate::entity::item::mag::MagCell;
|
||||
use crate::ship::items::{ItemManager, ClientItemId, CharacterInventory, ConsumedItem};
|
||||
|
||||
|
||||
|
||||
|
||||
use crate::ship::items::{CharacterInventory, ConsumedItem};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("")]
|
||||
@ -18,45 +12,39 @@ pub enum UseItemError {
|
||||
InvalidItem,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//pub fn use_tool()
|
||||
|
||||
pub async fn power_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.power += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn mind_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.mind += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn evade_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.evade += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn def_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.def += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn luck_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.luck += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn hp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.hp += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn tp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.tp += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
entity_gateway.save_character(character).await.unwrap();
|
||||
}
|
||||
|
||||
async fn mag_cell<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory, mag_cell_type: MagCell) -> Result<(), UseItemError> {
|
||||
@ -71,7 +59,7 @@ async fn mag_cell<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &Consum
|
||||
actual_mag.apply_mag_cell(mag_cell_type);
|
||||
for mag_entity_id in mag_item.entity_ids() {
|
||||
for cell_entity_id in used_cell.entity_ids() {
|
||||
entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await;
|
||||
entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub async fn validate_login<EG: EntityGateway>(id: ClientId,
|
||||
.clone();
|
||||
let settings = entity_gateway.get_user_settings_by_user(&user).await?;
|
||||
|
||||
item_manager.load_character(entity_gateway, &character).await;
|
||||
item_manager.load_character(entity_gateway, &character).await?;
|
||||
clients.insert(id, ClientState::new(user, settings, character, pkt.session));
|
||||
vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))]
|
||||
}
|
||||
|
@ -42,6 +42,6 @@ pub async fn write_infoboard<EG: EntityGateway>(id: ClientId,
|
||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||
client.character.info_board.update_infoboard(new_infoboard);
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await.unwrap();
|
||||
Box::new(None.into_iter())
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ where
|
||||
item: item_drop,
|
||||
};
|
||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?;
|
||||
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
||||
|
||||
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
|
||||
@ -236,7 +236,7 @@ where
|
||||
if client.character.meseta > bank_interaction.meseta_amount && (bank_interaction.meseta_amount + client.character.bank_meseta) <= 999999 {
|
||||
client.character.meseta -= bank_interaction.meseta_amount;
|
||||
client.character.bank_meseta += bank_interaction.meseta_amount;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
@ -251,7 +251,7 @@ where
|
||||
if client.character.meseta + bank_interaction.meseta_amount <= 999999 {
|
||||
client.character.meseta += bank_interaction.meseta_amount;
|
||||
client.character.bank_meseta -= bank_interaction.meseta_amount;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
@ -361,7 +361,7 @@ where
|
||||
}
|
||||
|
||||
client.character.meseta -= item.price() as u32;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
|
||||
let inventory_item = item_manager.player_buys_item(entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as usize).await?;
|
||||
let create = builder::message::create_withdrawn_inventory_item(area_client, inventory_item)?;
|
||||
|
@ -101,7 +101,7 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId,
|
||||
}
|
||||
}
|
||||
}
|
||||
item_manager.load_character(entity_gateway, &client.character).await;
|
||||
item_manager.load_character(entity_gateway, &client.character).await?;
|
||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
||||
let neighbors = client_location.get_client_neighbors(id).unwrap();
|
||||
|
@ -58,7 +58,7 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId,
|
||||
}
|
||||
|
||||
client.character.exp += exp_gain;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
|
||||
Ok(exp_pkts)
|
||||
}
|
||||
@ -243,7 +243,7 @@ where
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
if client.character.meseta >= charge.meseta {
|
||||
client.character.meseta -= charge.meseta;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
Ok(Box::new(None.into_iter()))
|
||||
} else {
|
||||
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
||||
@ -278,7 +278,7 @@ where
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
if client.character.meseta >= 10 {
|
||||
client.character.meseta -= 10;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await?;
|
||||
Ok(Box::new(None.into_iter()))
|
||||
} else {
|
||||
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
||||
@ -355,4 +355,4 @@ where
|
||||
}
|
||||
|
||||
Ok(Box::new(None.into_iter()))
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ pub async fn update_config<EG: EntityGateway>(id: ClientId,
|
||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||
client.character.config.update(update_config);
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await.unwrap();
|
||||
Box::new(None.into_iter())
|
||||
}
|
||||
|
||||
@ -22,6 +22,6 @@ pub async fn save_options<EG: EntityGateway>(id: ClientId,
|
||||
// // TODO: don't unwrap?
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||
client.character.option_flags = save_options.options;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
entity_gateway.save_character(&client.character).await.unwrap();
|
||||
Box::new(None.into_iter())
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ use crate::ship::room;
|
||||
use crate::ship::quests;
|
||||
use crate::ship::map::{MapsError, MapAreaError, MapArea};
|
||||
use crate::ship::packet::handler;
|
||||
use crate::ship::shops::{ShopType, WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem};
|
||||
use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem};
|
||||
|
||||
pub const SHIP_PORT: u16 = 23423;
|
||||
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
||||
@ -568,7 +568,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
||||
RecvShipPacket::DoneLoadingQuest(_) => {
|
||||
handler::quest::done_loading_quest(id, &mut self.clients, &self.client_location)?
|
||||
},
|
||||
RecvShipPacket::FullCharacterData(full_character_data) => {
|
||||
RecvShipPacket::FullCharacterData(_full_character_data) => {
|
||||
Box::new(None.into_iter())
|
||||
},
|
||||
RecvShipPacket::SaveOptions(save_options) => {
|
||||
@ -622,11 +622,11 @@ impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> {
|
||||
})) ]
|
||||
}
|
||||
|
||||
async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
|
||||
async fn action(&mut self, _id: ServerId, _msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
@ -6,9 +5,6 @@ use std::convert::TryInto;
|
||||
use serde::Deserialize;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand::distributions::{WeightedIndex, Distribution};
|
||||
use rand::seq::{SliceRandom, IteratorRandom};
|
||||
use crate::entity::character::SectionID;
|
||||
use crate::ship::room::Difficulty;
|
||||
use crate::entity::item::ItemDetail;
|
||||
use crate::entity::item::armor::{Armor, ArmorType};
|
||||
use crate::entity::item::shield::{Shield, ShieldType};
|
||||
|
@ -6,9 +6,6 @@ use std::convert::TryInto;
|
||||
use serde::Deserialize;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand::distributions::{WeightedIndex, Distribution};
|
||||
use rand::seq::{SliceRandom, IteratorRandom};
|
||||
use crate::entity::character::SectionID;
|
||||
use crate::ship::room::Difficulty;
|
||||
use crate::entity::item::ItemDetail;
|
||||
use crate::entity::item::tool::{Tool, ToolType};
|
||||
use crate::entity::item::tech::{Technique, TechniqueDisk};
|
||||
@ -206,34 +203,6 @@ impl<R: Rng + SeedableRng> ToolShop<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_tech(&mut self, character_level: usize) -> ToolShopItem {
|
||||
let tier = self.techs.0.iter()
|
||||
.filter(|t| t.level <= character_level)
|
||||
.last()
|
||||
.unwrap();
|
||||
|
||||
let mut tier = tier.techs.iter()
|
||||
.map(|(tech, entry)| {
|
||||
(tech, entry)
|
||||
});
|
||||
|
||||
|
||||
let tech_choice = WeightedIndex::new(tier.clone().map(|(_, e)| e.probability)).unwrap();
|
||||
let tech_detail = tier.nth(tech_choice.sample(&mut self.rng)).unwrap();
|
||||
let tech_level = match tech_detail.1.level {
|
||||
TechLevel::Set{set_level} => set_level,
|
||||
TechLevel::Level{level_divisor} => std::cmp::max(std::cmp::min(character_level, 99)/level_divisor, 1),
|
||||
TechLevel::Range{min, max} => self.rng.gen_range(min, max+1),
|
||||
};
|
||||
|
||||
ToolShopItem::Tech(
|
||||
TechniqueDisk {
|
||||
tech: *tech_detail.0,
|
||||
level: tech_level as u32,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn generate_tech_types(&mut self, character_level: usize) -> Vec<Technique> {
|
||||
let tier = self.techs.0.iter()
|
||||
.filter(|t| t.level <= character_level)
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![allow(dead_code)]
|
||||
use std::time::SystemTime;
|
||||
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use elseware::entity::gateway::EntityGateway;
|
||||
|
@ -1008,7 +1008,7 @@ async fn test_deposit_meseta_when_bank_is_maxed() {
|
||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.meseta = 300;
|
||||
char1.bank_meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
|
@ -54,7 +54,7 @@ async fn test_character_levels_up() {
|
||||
|
||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.exp = 49;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
|
@ -321,7 +321,7 @@ async fn test_other_clients_see_stacked_purchase() {
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
|
Loading…
x
Reference in New Issue
Block a user