Merge pull request 'split_bins' (#243) from split_bins into master
This commit is contained in:
commit
1b9eafeaa9
@ -30,7 +30,8 @@ ages-prs = "0.1"
|
|||||||
async-trait = "0.1.31"
|
async-trait = "0.1.31"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
barrel = { version = "0.6.5", features = ["pg"] }
|
barrel = { version = "0.6.5", features = ["pg"] }
|
||||||
postgres = "0.17.5"
|
|
||||||
refinery = { version = "0.3.0", features = ["postgres"] }
|
refinery = { version = "0.3.0", features = ["postgres"] }
|
||||||
sqlx = { version = "0.4.0-beta.1", features = ["postgres", "json", "chrono"] }
|
sqlx = { version = "0.4.0-beta.1", features = ["postgres", "json", "chrono"] }
|
||||||
|
strum = "0.19.5"
|
||||||
|
strum_macros = "0.19"
|
||||||
|
|
||||||
|
|||||||
49
src/bin/login.rs
Normal file
49
src/bin/login.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use log::{info};
|
||||||
|
use elseware::entity::gateway::postgres::PostgresGateway;
|
||||||
|
use elseware::login::login::LoginServerState;
|
||||||
|
use elseware::login::character::CharacterServerState;
|
||||||
|
use elseware::common::mainloop::{login_mainloop, character_mainloop};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let colors = fern::colors::ColoredLevelConfig::new()
|
||||||
|
.error(fern::colors::Color::Red)
|
||||||
|
.warn(fern::colors::Color::Yellow)
|
||||||
|
.info(fern::colors::Color::Green)
|
||||||
|
.debug(fern::colors::Color::White)
|
||||||
|
.trace(fern::colors::Color::BrightBlack);
|
||||||
|
let stdio = fern::Dispatch::new()
|
||||||
|
.level(log::LevelFilter::Debug)
|
||||||
|
.format(move |out, message, record| {
|
||||||
|
out.finish(format_args!(
|
||||||
|
"\x1B[{}m[{}][{}][{}] {}\x1B[0m",
|
||||||
|
colors.get_color(&record.level()).to_fg_str(),
|
||||||
|
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
||||||
|
record.target(),
|
||||||
|
record.level(),
|
||||||
|
message,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.chain(std::io::stdout());
|
||||||
|
fern::Dispatch::new()
|
||||||
|
.chain(stdio)
|
||||||
|
.apply().unwrap();
|
||||||
|
|
||||||
|
let db_host = std::env::var("DB_HOST").unwrap();
|
||||||
|
let db_username = std::env::var("DB_USERNAME").unwrap();
|
||||||
|
let db_password = std::env::var("DB_PASSWORD").unwrap();
|
||||||
|
let db_dbname = std::env::var("DB_DBNAME").unwrap();
|
||||||
|
let charserv_ip = std::env::var("CHARSERV_IP").unwrap().parse().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 char_state = CharacterServerState::new(entity_gateway);
|
||||||
|
let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT);
|
||||||
|
|
||||||
|
info!("[auth/character] starting server");
|
||||||
|
async_std::task::block_on(async move {
|
||||||
|
futures::future::join_all(vec![login_loop, character_loop]).await
|
||||||
|
});
|
||||||
|
}
|
||||||
113
src/bin/main.rs
113
src/bin/main.rs
@ -1,11 +1,9 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::time::SystemTime;
|
|
||||||
use log::{info};
|
use log::{info};
|
||||||
|
|
||||||
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd};
|
||||||
use elseware::login::login::LoginServerState;
|
use elseware::login::login::LoginServerState;
|
||||||
use elseware::login::character::CharacterServerState;
|
use elseware::login::character::CharacterServerState;
|
||||||
use elseware::ship::ship::ShipServerState;
|
|
||||||
use elseware::ship::ship::ShipServerStateBuilder;
|
use elseware::ship::ship::ShipServerStateBuilder;
|
||||||
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity};
|
||||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway};
|
||||||
@ -60,14 +58,14 @@ fn main() {
|
|||||||
team_id: None,
|
team_id: None,
|
||||||
banned_until: None,
|
banned_until: None,
|
||||||
muted_until: None,
|
muted_until: None,
|
||||||
created_at: chrono::Utc::now(),
|
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
};
|
};
|
||||||
let fake_user = entity_gateway.create_user(fake_user).await.unwrap();
|
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);
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
character.name = format!("Test Char {}", i*2);
|
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);
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
character.slot = 2;
|
character.slot = 2;
|
||||||
character.name = "ItemRefactor".into();
|
character.name = "ItemRefactor".into();
|
||||||
@ -75,6 +73,41 @@ fn main() {
|
|||||||
character.meseta = 999999;
|
character.meseta = 999999;
|
||||||
let character = entity_gateway.create_character(character).await.unwrap();
|
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(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -94,7 +127,7 @@ fn main() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -114,7 +147,7 @@ fn main() {
|
|||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -134,7 +167,7 @@ fn main() {
|
|||||||
slot: 2,
|
slot: 2,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -154,7 +187,7 @@ fn main() {
|
|||||||
slot: 3,
|
slot: 3,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -174,7 +207,59 @@ fn main() {
|
|||||||
slot: 4,
|
slot: 4,
|
||||||
equipped: true,
|
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(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Weapon(
|
item: ItemDetail::Weapon(
|
||||||
@ -315,7 +400,7 @@ fn main() {
|
|||||||
|
|
||||||
let thread_entity_gateway = entity_gateway.clone();
|
let thread_entity_gateway = entity_gateway.clone();
|
||||||
info!("[auth] starting server");
|
info!("[auth] starting server");
|
||||||
let login_state = LoginServerState::new(thread_entity_gateway);
|
let login_state = LoginServerState::new(thread_entity_gateway, "127.0.0.1".parse().unwrap());
|
||||||
let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT);
|
let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT);
|
||||||
|
|
||||||
let thread_entity_gateway = entity_gateway.clone();
|
let thread_entity_gateway = entity_gateway.clone();
|
||||||
@ -326,7 +411,7 @@ fn main() {
|
|||||||
let thread_entity_gateway = entity_gateway.clone();
|
let thread_entity_gateway = entity_gateway.clone();
|
||||||
info!("[ship] starting server");
|
info!("[ship] starting server");
|
||||||
let ship_state = ShipServerStateBuilder::new()
|
let ship_state = ShipServerStateBuilder::new()
|
||||||
.name("Sona-Nyl".into())
|
.name("US/Sona-Nyl".into())
|
||||||
.ip(Ipv4Addr::new(127,0,0,1))
|
.ip(Ipv4Addr::new(127,0,0,1))
|
||||||
.port(elseware::ship::ship::SHIP_PORT)
|
.port(elseware::ship::ship::SHIP_PORT)
|
||||||
.gateway(thread_entity_gateway)
|
.gateway(thread_entity_gateway)
|
||||||
@ -335,7 +420,7 @@ fn main() {
|
|||||||
|
|
||||||
let thread_entity_gateway = entity_gateway.clone();
|
let thread_entity_gateway = entity_gateway.clone();
|
||||||
let ship_state = ShipServerStateBuilder::new()
|
let ship_state = ShipServerStateBuilder::new()
|
||||||
.name("Dylath-Leen".into())
|
.name("EU/Dylath-Leen".into())
|
||||||
.ip(Ipv4Addr::new(127,0,0,1))
|
.ip(Ipv4Addr::new(127,0,0,1))
|
||||||
.port(elseware::ship::ship::SHIP_PORT+2000)
|
.port(elseware::ship::ship::SHIP_PORT+2000)
|
||||||
.gateway(thread_entity_gateway)
|
.gateway(thread_entity_gateway)
|
||||||
@ -344,7 +429,7 @@ fn main() {
|
|||||||
|
|
||||||
let thread_entity_gateway = entity_gateway.clone();
|
let thread_entity_gateway = entity_gateway.clone();
|
||||||
let ship_state = ShipServerStateBuilder::new()
|
let ship_state = ShipServerStateBuilder::new()
|
||||||
.name("Thalarion".into())
|
.name("JP/Thalarion".into())
|
||||||
.ip(Ipv4Addr::new(127,0,0,1))
|
.ip(Ipv4Addr::new(127,0,0,1))
|
||||||
.port(elseware::ship::ship::SHIP_PORT+3000)
|
.port(elseware::ship::ship::SHIP_PORT+3000)
|
||||||
.gateway(thread_entity_gateway)
|
.gateway(thread_entity_gateway)
|
||||||
|
|||||||
16
src/bin/patch.rs
Normal file
16
src/bin/patch.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
async_std::task::block_on(async move {
|
||||||
|
patch_loop.await
|
||||||
|
});
|
||||||
|
}
|
||||||
52
src/bin/ship.rs
Normal file
52
src/bin/ship.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use log::{info};
|
||||||
|
use elseware::entity::gateway::postgres::PostgresGateway;
|
||||||
|
use elseware::ship::ship::ShipServerStateBuilder;
|
||||||
|
use elseware::common::mainloop::ship_mainloop;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let colors = fern::colors::ColoredLevelConfig::new()
|
||||||
|
.error(fern::colors::Color::Red)
|
||||||
|
.warn(fern::colors::Color::Yellow)
|
||||||
|
.info(fern::colors::Color::Green)
|
||||||
|
.debug(fern::colors::Color::White)
|
||||||
|
.trace(fern::colors::Color::BrightBlack);
|
||||||
|
let stdio = fern::Dispatch::new()
|
||||||
|
.level(log::LevelFilter::Debug)
|
||||||
|
.format(move |out, message, record| {
|
||||||
|
out.finish(format_args!(
|
||||||
|
"\x1B[{}m[{}][{}][{}] {}\x1B[0m",
|
||||||
|
colors.get_color(&record.level()).to_fg_str(),
|
||||||
|
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
||||||
|
record.target(),
|
||||||
|
record.level(),
|
||||||
|
message,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.chain(std::io::stdout());
|
||||||
|
fern::Dispatch::new()
|
||||||
|
.chain(stdio)
|
||||||
|
.apply().unwrap();
|
||||||
|
|
||||||
|
let db_host = std::env::var("DB_HOST").unwrap();
|
||||||
|
let db_username = std::env::var("DB_USERNAME").unwrap();
|
||||||
|
let db_password = std::env::var("DB_PASSWORD").unwrap();
|
||||||
|
let db_dbname = std::env::var("DB_DBNAME").unwrap();
|
||||||
|
let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password);
|
||||||
|
|
||||||
|
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::new()
|
||||||
|
.name(ship_name)
|
||||||
|
.ip(ip)
|
||||||
|
.port(elseware::ship::ship::SHIP_PORT)
|
||||||
|
.gateway(entity_gateway)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
info!("[auth/character] starting server");
|
||||||
|
async_std::task::block_on(async move {
|
||||||
|
ship_loop.await
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -139,65 +139,6 @@ enum ServerStateAction<S> {
|
|||||||
Disconnect,
|
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,
|
async fn client_recv_loop<S, R>(client_id: ClientId,
|
||||||
socket: Arc<async_std::net::TcpStream>,
|
socket: Arc<async_std::net::TcpStream>,
|
||||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||||
@ -283,7 +224,10 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
|||||||
match action {
|
match action {
|
||||||
ClientAction::NewClient(client_id, sender) => {
|
ClientAction::NewClient(client_id, sender) => {
|
||||||
clients.insert(client_id, sender.clone());
|
clients.insert(client_id, sender.clone());
|
||||||
for action in state.on_connect(client_id) {
|
let actions = state.on_connect(client_id).await;
|
||||||
|
match actions {
|
||||||
|
Ok(actions) => {
|
||||||
|
for action in actions {
|
||||||
match action {
|
match action {
|
||||||
OnConnect::Cipher((inc, outc)) => {
|
OnConnect::Cipher((inc, outc)) => {
|
||||||
sender.send(ServerStateAction::Cipher(inc, outc)).await;
|
sender.send(ServerStateAction::Cipher(inc, outc)).await;
|
||||||
@ -293,6 +237,11 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("[client {:?} state on_connect error] {:?}", client_id, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ClientAction::Packet(client_id, pkt) => {
|
ClientAction::Packet(client_id, pkt) => {
|
||||||
let pkts = state.handle(client_id, &pkt).await;
|
let pkts = state.handle(client_id, &pkt).await;
|
||||||
@ -310,7 +259,9 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientAction::Disconnect(client_id) => {
|
ClientAction::Disconnect(client_id) => {
|
||||||
let pkts = state.on_disconnect(client_id);
|
let pkts = state.on_disconnect(client_id).await;
|
||||||
|
match pkts {
|
||||||
|
Ok(pkts) => {
|
||||||
for (client_id, pkt) in pkts {
|
for (client_id, pkt) in pkts {
|
||||||
if let Some(client) = clients.get_mut(&client_id) {
|
if let Some(client) = clients.get_mut(&client_id) {
|
||||||
client.send(ServerStateAction::Packet(pkt)).await;
|
client.send(ServerStateAction::Packet(pkt)).await;
|
||||||
@ -321,6 +272,11 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
|||||||
client.send(ServerStateAction::Disconnect).await;
|
client.send(ServerStateAction::Disconnect).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("[client {:?} state on_disconnect error] {:?}", client_id, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl MessageReceiver {
|
|||||||
let size = u32::from_le_bytes(size_buf) as usize;
|
let size = u32::from_le_bytes(size_buf) as usize;
|
||||||
|
|
||||||
let mut payload = vec![0u8; size];
|
let mut payload = vec![0u8; size];
|
||||||
self.socket.read_exact(&mut payload).await.map_err(|err| MessageReceiverError::Disconnected)?;
|
self.socket.read_exact(&mut payload).await.map_err(|_| MessageReceiverError::Disconnected)?;
|
||||||
let payload = String::from_utf8(payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
let payload = String::from_utf8(payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
||||||
|
|
||||||
let msg = serde_json::from_str(&payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
let msg = serde_json::from_str(&payload).map_err(|_| MessageReceiverError::InvalidPayload)?;
|
||||||
@ -65,7 +65,13 @@ where
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("interserver loop");
|
info!("interserver loop");
|
||||||
let action = action_receiver.recv().await.unwrap();
|
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;
|
let mut state = state.lock().await;
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
@ -94,12 +100,12 @@ where
|
|||||||
},
|
},
|
||||||
InterserverInputAction::Disconnect(server_id) => {
|
InterserverInputAction::Disconnect(server_id) => {
|
||||||
let actions = state.on_disconnect(server_id).await;
|
let actions = state.on_disconnect(server_id).await;
|
||||||
|
ships.remove(&server_id);
|
||||||
for (server, action) in actions {
|
for (server, action) in actions {
|
||||||
if let Some(sender) = ships.get_mut(&server) {
|
if let Some(sender) = ships.get_mut(&server) {
|
||||||
sender.send(action).await;
|
sender.send(action).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +170,8 @@ where
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("error in send_loop: {:?}, {:?}", server_id, err)
|
warn!("error in send_loop: {:?}, {:?}", server_id, err);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,20 +211,33 @@ pub fn ship_connect_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<ShipS
|
|||||||
interserver_state_loop(state, server_state_receiver).await;
|
interserver_state_loop(state, server_state_receiver).await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let socket = async_std::net::TcpStream::connect((ip, port)).await.unwrap();
|
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;
|
id += 1;
|
||||||
let server_id = crate::common::interserver::ServerId(id);
|
let server_id = crate::common::interserver::ServerId(id);
|
||||||
|
info!("found loginserv: {:?} {:?}", server_id, socket);
|
||||||
let (client_sender, client_receiver) = async_std::sync::channel(64);
|
let (client_sender, client_receiver) = async_std::sync::channel(64);
|
||||||
|
|
||||||
info!("ship connected to login: {:?}", socket);
|
|
||||||
login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await;
|
login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await;
|
||||||
interserver_send_loop(server_id, socket.clone(), client_receiver).await;
|
interserver_send_loop(server_id, socket.clone(), client_receiver).await;
|
||||||
|
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
loop {
|
loop {
|
||||||
if let Err(_) = socket.peer_addr() {
|
let peek = socket.peek(&mut buf).await;
|
||||||
info!("ship connected to login: {:?}", socket);
|
match peek {
|
||||||
break;
|
Ok(len) if len == 0 => {
|
||||||
|
break
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async_std::task::sleep(Duration::from_secs(10)).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@ -24,9 +24,9 @@ pub trait ServerState {
|
|||||||
type RecvPacket: RecvServerPacket;
|
type RecvPacket: RecvServerPacket;
|
||||||
type PacketError;
|
type PacketError;
|
||||||
|
|
||||||
fn on_connect(&mut self, id: ClientId) -> Vec<OnConnect<Self::SendPacket>>;
|
async fn on_connect(&mut self, id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, Self::PacketError>;
|
||||||
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, Self::PacketError>;
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, Self::PacketError>;
|
||||||
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>;
|
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, Self::SendPacket)>, Self::PacketError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
use libpso::character::settings;
|
use libpso::character::settings;
|
||||||
use libpso::character::guildcard;
|
use libpso::character::guildcard;
|
||||||
|
|
||||||
@ -24,8 +21,24 @@ pub struct NewUserAccountEntity {
|
|||||||
pub team_id: Option<u32>,
|
pub team_id: Option<u32>,
|
||||||
pub banned_until: Option<chrono::DateTime<chrono::Utc>>,
|
pub banned_until: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
pub muted_until: Option<chrono::DateTime<chrono::Utc>>,
|
pub muted_until: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
pub flags: u32,
|
pub flags: u32,
|
||||||
|
pub activated: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NewUserAccountEntity {
|
||||||
|
fn default() -> NewUserAccountEntity {
|
||||||
|
NewUserAccountEntity {
|
||||||
|
email: "".into(),
|
||||||
|
username: "".into(),
|
||||||
|
password: "".into(),
|
||||||
|
guildcard: 0xFFFFFFFF,
|
||||||
|
team_id: None,
|
||||||
|
banned_until: None,
|
||||||
|
muted_until: None,
|
||||||
|
flags: 0,
|
||||||
|
activated: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -39,8 +52,19 @@ pub struct UserAccountEntity {
|
|||||||
pub muted_until: Option<chrono::DateTime<chrono::Utc>>,
|
pub muted_until: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||||
pub flags: u32, // TODO: is this used for anything other than character creation?
|
pub flags: u32, // TODO: is this used for anything other than character creation?
|
||||||
|
pub activated: bool,
|
||||||
|
pub at_login: bool,
|
||||||
|
pub at_character: bool,
|
||||||
|
pub at_ship: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UserAccountEntity {
|
||||||
|
pub fn is_currently_online(&self) -> bool {
|
||||||
|
self.at_login | self.at_character | self.at_ship
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NewUserSettingsEntity {
|
pub struct NewUserSettingsEntity {
|
||||||
pub user_id: UserAccountId,
|
pub user_id: UserAccountId,
|
||||||
|
|||||||
@ -1,80 +1,91 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
|
|
||||||
// TODO: all these Options should be Results
|
|
||||||
|
// TODO: better granularity?
|
||||||
|
//#[derive(Error, Debug)]
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
#[error("")]
|
||||||
|
pub enum GatewayError {
|
||||||
|
Error,
|
||||||
|
PgError(#[from] sqlx::Error)
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait EntityGateway: Send + Sync + Clone {
|
pub trait EntityGateway: Send + Sync + Clone {
|
||||||
async fn create_user(&mut self, _user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, _user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, _id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, _id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, _username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, _username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, _user: &UserAccountEntity) {
|
async fn save_user(&mut self, _user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) {
|
async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, _char: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, _char: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: just make this a vec sorted by slot order?
|
// TODO: just make this a vec sorted by slot order?
|
||||||
async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, _char: &CharacterEntity) {
|
async fn save_character(&mut self, _char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, _item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, _item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_item(&mut self, _item: &ItemEntity) {
|
async fn save_item(&mut self, _item: &ItemEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) {
|
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use std::convert::TryInto;
|
|||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -31,7 +31,7 @@ impl InMemoryGateway {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for InMemoryGateway {
|
impl EntityGateway for InMemoryGateway {
|
||||||
async fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
let id = users
|
let id = users
|
||||||
.iter()
|
.iter()
|
||||||
@ -45,32 +45,38 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
team_id: user.team_id,
|
team_id: user.team_id,
|
||||||
banned_until: user.banned_until,
|
banned_until: user.banned_until,
|
||||||
muted_until: user.muted_until,
|
muted_until: user.muted_until,
|
||||||
created_at: user.created_at,
|
created_at: chrono::Utc::now(),
|
||||||
flags: user.flags,
|
flags: user.flags,
|
||||||
|
activated: user.activated,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
};
|
};
|
||||||
users.insert(user.id, user.clone());
|
users.insert(user.id, user.clone());
|
||||||
Some(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let users = self.users.lock().unwrap();
|
let users = self.users.lock().unwrap();
|
||||||
users.get(&id).map(|k| k.clone())
|
users.get(&id).map(|k| k.clone()).ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let users = self.users.lock().unwrap();
|
let users = self.users.lock().unwrap();
|
||||||
users
|
users
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_, k)| k.username == username)
|
.find(|(_, k)| k.username == username)
|
||||||
.map(|(_, k)| k.clone())
|
.map(|(_, k)| k.clone())
|
||||||
|
.ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, user: &UserAccountEntity) {
|
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
users.insert(user.id, user.clone());
|
users.insert(user.id, user.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let mut user_settings = self.user_settings.lock().unwrap();
|
let mut user_settings = self.user_settings.lock().unwrap();
|
||||||
let id = user_settings
|
let id = user_settings
|
||||||
.iter()
|
.iter()
|
||||||
@ -82,28 +88,29 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
settings: settings.settings,
|
settings: settings.settings,
|
||||||
};
|
};
|
||||||
user_settings.insert(new_settings.id, new_settings.clone());
|
user_settings.insert(new_settings.id, new_settings.clone());
|
||||||
Some(new_settings)
|
Ok(new_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let user_settings = self.user_settings.lock().unwrap();
|
let user_settings = self.user_settings.lock().unwrap();
|
||||||
user_settings
|
user_settings
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_, k)| k.user_id == user.id)
|
.find(|(_, k)| k.user_id == user.id)
|
||||||
.map(|(_, k)| k.clone())
|
.map(|(_, k)| k.clone())
|
||||||
|
.ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
let characters = self.characters.lock().unwrap();
|
let characters = self.characters.lock().unwrap();
|
||||||
let mut chars = [None; 4];
|
let mut chars = [None; 4];
|
||||||
characters
|
characters
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.user_id == user.id)
|
.filter(|(_, c)| c.user_id == user.id)
|
||||||
.for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone()));
|
.for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone()));
|
||||||
chars
|
Ok(chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, character: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, character: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
let id = characters
|
let id = characters
|
||||||
.iter()
|
.iter()
|
||||||
@ -130,19 +137,20 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
option_flags: character.option_flags,
|
option_flags: character.option_flags,
|
||||||
};
|
};
|
||||||
characters.insert(new_character.id, new_character.clone());
|
characters.insert(new_character.id, new_character.clone());
|
||||||
Some(new_character)
|
Ok(new_character)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, char: &CharacterEntity) {
|
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
characters.insert(char.id, char.clone());
|
characters.insert(char.id, char.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
GuildCardDataEntity::new(user.id)
|
Ok(GuildCardDataEntity::new(user.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
let id = items
|
let id = items
|
||||||
.iter()
|
.iter()
|
||||||
@ -154,52 +162,57 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
item: item.item,
|
item: item.item,
|
||||||
};
|
};
|
||||||
items.insert(ItemEntityId(id), new_item.clone());
|
items.insert(ItemEntityId(id), new_item.clone());
|
||||||
Some(new_item)
|
Ok(new_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_item(&mut self, item: &ItemEntity) {
|
async fn save_item(&mut self, item: &ItemEntity) -> Result<(), GatewayError> {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
items.insert(item.id, item.clone());
|
items.insert(item.id, item.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
self.items.lock().unwrap().get_mut(&item_id)
|
self.items.lock().unwrap().get_mut(&item_id)
|
||||||
.map(|item_entity| {
|
.map(|item_entity| {
|
||||||
item_entity.location = item_location
|
item_entity.location = item_location
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::FeedMag {
|
.push(mag::MagModifier::FeedMag {
|
||||||
food: *tool_item_id
|
food: *tool_item_id
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
|
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
|
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
let items = self.items.lock().unwrap();
|
let items = self.items.lock().unwrap();
|
||||||
items
|
Ok(items
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, k)| {
|
.filter(|(_, k)| {
|
||||||
match k.location {
|
match k.location {
|
||||||
ItemLocation::Inventory{character_id, ..} => character_id == character.id,
|
ItemLocation::Inventory{character_id, ..} => character_id == *char_id,
|
||||||
ItemLocation::Bank{character_id, ..} => character_id == character.id,
|
ItemLocation::Bank{character_id, ..} => character_id == *char_id,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -241,6 +254,6 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
};
|
};
|
||||||
item
|
item
|
||||||
})
|
})
|
||||||
.collect()
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,6 @@ pub mod entitygateway;
|
|||||||
pub mod inmemory;
|
pub mod inmemory;
|
||||||
pub mod postgres;
|
pub mod postgres;
|
||||||
|
|
||||||
pub use entitygateway::EntityGateway;
|
pub use entitygateway::{EntityGateway, GatewayError};
|
||||||
pub use inmemory::InMemoryGateway;
|
pub use inmemory::InMemoryGateway;
|
||||||
pub use self::postgres::PostgresGateway;
|
pub use self::postgres::PostgresGateway;
|
||||||
|
|||||||
@ -9,7 +9,10 @@ create table user_accounts (
|
|||||||
flags integer default 0 not null,
|
flags integer default 0 not null,
|
||||||
activated boolean default false not null,
|
activated boolean default false not null,
|
||||||
game_session integer,
|
game_session integer,
|
||||||
interserver_session integer
|
interserver_session integer,
|
||||||
|
at_login boolean default false not null,
|
||||||
|
at_character boolean default false not null,
|
||||||
|
at_ship boolean default false not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table user_settings (
|
create table user_settings (
|
||||||
@ -79,9 +82,9 @@ create table item_location (
|
|||||||
created_at timestamptz default current_timestamp not null
|
created_at timestamptz default current_timestamp not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table inventory_slots (
|
create table inventory_slot (
|
||||||
pchar integer references player_character not null,
|
item integer references item not null unique,
|
||||||
items integer[30] /* references item (id) */
|
slot integer not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table weapon_modifier (
|
create table weapon_modifier (
|
||||||
|
|||||||
@ -1,21 +1,13 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use futures::TryStreamExt;
|
use libpso::character::settings;
|
||||||
use libpso::character::{settings, guildcard};
|
|
||||||
use libpso::util::vec_to_array;
|
use libpso::util::vec_to_array;
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
use crate::ship::map::MapArea;
|
use crate::ship::map::MapArea;
|
||||||
|
|
||||||
use sqlx::postgres::PgPoolOptions;
|
|
||||||
use sqlx::Row;
|
|
||||||
use sqlx::Execute;
|
|
||||||
use postgres::{Client, NoTls};
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
pub struct PgUserAccount {
|
pub struct PgUserAccount {
|
||||||
id: i32,
|
id: i32,
|
||||||
@ -25,6 +17,10 @@ pub struct PgUserAccount {
|
|||||||
muted: Option<chrono::DateTime<chrono::Utc>>,
|
muted: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
created_at: chrono::DateTime<chrono::Utc>,
|
created_at: chrono::DateTime<chrono::Utc>,
|
||||||
flags: i32,
|
flags: i32,
|
||||||
|
activated: bool,
|
||||||
|
at_login: bool,
|
||||||
|
at_character: bool,
|
||||||
|
at_ship: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<UserAccountEntity> for PgUserAccount {
|
impl Into<UserAccountEntity> for PgUserAccount {
|
||||||
@ -37,9 +33,12 @@ impl Into<UserAccountEntity> for PgUserAccount {
|
|||||||
muted_until: self.muted,
|
muted_until: self.muted,
|
||||||
created_at: self.created_at,
|
created_at: self.created_at,
|
||||||
flags: self.flags as u32,
|
flags: self.flags as u32,
|
||||||
// TOOD
|
|
||||||
guildcard: self.id as u32 + 1,
|
guildcard: self.id as u32 + 1,
|
||||||
team_id: None,
|
team_id: None,
|
||||||
|
activated: self.activated,
|
||||||
|
at_login: self.at_login,
|
||||||
|
at_character: self.at_character,
|
||||||
|
at_ship: self.at_ship,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,7 +243,7 @@ impl Into<CharacterEntity> for PgCharacter {
|
|||||||
prop_y: self.prop_y,
|
prop_y: self.prop_y,
|
||||||
},
|
},
|
||||||
techs: CharacterTechniques {
|
techs: CharacterTechniques {
|
||||||
techs: self.techs.iter().enumerate().take(19).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t)) ).collect()
|
techs: self.techs.iter().enumerate().take(19).filter(|(_, t)| **t != 0xFF).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t)) ).collect()
|
||||||
},
|
},
|
||||||
config: CharacterConfig {
|
config: CharacterConfig {
|
||||||
raw_data: vec_to_array(self.config)
|
raw_data: vec_to_array(self.config)
|
||||||
|
|||||||
@ -1,22 +1,15 @@
|
|||||||
use std::convert::{From, TryFrom, Into, TryInto};
|
use std::convert::{From, TryFrom, Into};
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
//use futures::StreamExt;
|
|
||||||
use async_std::stream::StreamExt;
|
use async_std::stream::StreamExt;
|
||||||
//use futures::StreamExt;
|
use libpso::character::guildcard;
|
||||||
use libpso::character::{settings, guildcard};
|
|
||||||
use libpso::util::vec_to_array;
|
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
use super::models::*;
|
use super::models::*;
|
||||||
|
|
||||||
use sqlx::postgres::PgPoolOptions;
|
use sqlx::postgres::PgPoolOptions;
|
||||||
use sqlx::Row;
|
|
||||||
use sqlx::Execute;
|
|
||||||
use postgres::{Client, NoTls};
|
|
||||||
|
|
||||||
mod embedded {
|
mod embedded {
|
||||||
use refinery::embed_migrations;
|
use refinery::embed_migrations;
|
||||||
@ -31,8 +24,11 @@ pub struct PostgresGateway {
|
|||||||
|
|
||||||
impl PostgresGateway {
|
impl PostgresGateway {
|
||||||
pub fn new(host: &str, dbname: &str, username: &str, password: &str) -> PostgresGateway {
|
pub fn new(host: &str, dbname: &str, username: &str, password: &str) -> PostgresGateway {
|
||||||
// the postgres dep can be removed once refinery supports sqlx
|
let mut conn = refinery::config::Config::new(refinery::config::ConfigDbType::Postgres)
|
||||||
let mut conn = Client::connect(&format!("host='{}' dbname='{}' user='{}' password='{}'", host, dbname, username, password), NoTls).unwrap();
|
.set_db_host(&host)
|
||||||
|
.set_db_user(&username)
|
||||||
|
.set_db_pass(&password)
|
||||||
|
.set_db_name(&dbname);
|
||||||
embedded::migrations::runner().run(&mut conn).unwrap();
|
embedded::migrations::runner().run(&mut conn).unwrap();
|
||||||
|
|
||||||
let pool = async_std::task::block_on(async move {
|
let pool = async_std::task::block_on(async move {
|
||||||
@ -96,41 +92,43 @@ impl PostgresGateway {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for PostgresGateway {
|
impl EntityGateway for PostgresGateway {
|
||||||
async fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password) values ($1, $2, $3) returning *;")
|
let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password, activated) values ($1, $2, $3, $4) returning *;")
|
||||||
.bind(user.email)
|
.bind(user.email)
|
||||||
.bind(user.username)
|
.bind(user.username)
|
||||||
.bind(user.password)
|
.bind(user.password)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.bind(user.activated)
|
||||||
Some(new_user.into())
|
.fetch_one(&self.pool).await?;
|
||||||
|
Ok(new_user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1")
|
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1")
|
||||||
.bind(id.0)
|
.bind(id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(user.into())
|
Ok(user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where username = $1")
|
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where username = $1")
|
||||||
.bind(username)
|
.bind(username)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(user.into())
|
Ok(user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, user: &UserAccountEntity) {
|
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("UPDATE user_accounts set name=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6")
|
sqlx::query("UPDATE user_accounts set username=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6")
|
||||||
.bind(&user.username)
|
.bind(&user.username)
|
||||||
.bind(&user.password)
|
.bind(&user.password)
|
||||||
.bind(&user.banned_until)
|
.bind(&user.banned_until)
|
||||||
.bind(&user.muted_until)
|
.bind(&user.muted_until)
|
||||||
.bind(&user.flags)
|
.bind(&user.flags)
|
||||||
.bind(&user.id.0)
|
.bind(&user.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name)
|
let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name)
|
||||||
values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;")
|
values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;")
|
||||||
.bind(settings.user_id.0)
|
.bind(settings.user_id.0)
|
||||||
@ -141,18 +139,18 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(settings.settings.shortcuts.to_vec())
|
.bind(settings.settings.shortcuts.to_vec())
|
||||||
.bind(settings.settings.symbol_chats.to_vec())
|
.bind(settings.settings.symbol_chats.to_vec())
|
||||||
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(new_settings.into())
|
Ok(new_settings.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where id = $1")
|
let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where user_account = $1")
|
||||||
.bind(user.id.0)
|
.bind(user.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(settings.into())
|
Ok(settings.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) {
|
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8")
|
sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8")
|
||||||
.bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.bind(&settings.settings.key_config.to_vec())
|
.bind(&settings.settings.key_config.to_vec())
|
||||||
@ -162,10 +160,11 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(&settings.settings.symbol_chats.to_vec())
|
.bind(&settings.settings.symbol_chats.to_vec())
|
||||||
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.bind(&settings.id.0)
|
.bind(&settings.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, char: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, char: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
let q = r#"insert into player_character
|
let q = r#"insert into player_character
|
||||||
(user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs,
|
(user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs,
|
||||||
config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags)
|
config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags)
|
||||||
@ -173,7 +172,6 @@ impl EntityGateway for PostgresGateway {
|
|||||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31)
|
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31)
|
||||||
returning *;"#;
|
returning *;"#;
|
||||||
let character = sqlx::query_as::<_, PgCharacter>(q)
|
let character = sqlx::query_as::<_, PgCharacter>(q)
|
||||||
//sqlx::query(q)
|
|
||||||
.bind(char.user_id.0)
|
.bind(char.user_id.0)
|
||||||
.bind(char.slot as i16)
|
.bind(char.slot as i16)
|
||||||
.bind(char.name)
|
.bind(char.name)
|
||||||
@ -205,28 +203,25 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(char.meseta as i32)
|
.bind(char.meseta as i32)
|
||||||
.bind(char.bank_meseta as i32)
|
.bind(char.bank_meseta as i32)
|
||||||
.bind(char.option_flags as i32)
|
.bind(char.option_flags as i32)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
|
|
||||||
sqlx::query("insert into inventory_slots (pchar) values ($1)")
|
Ok(character.into())
|
||||||
.bind(character.id)
|
|
||||||
.execute(&self.pool).await.unwrap();
|
|
||||||
Some(character.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
let mut stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by slot")
|
let mut stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by slot")
|
||||||
.bind(user.id.0)
|
.bind(user.id.0)
|
||||||
.fetch(&self.pool);
|
.fetch(&self.pool);
|
||||||
let mut result = [None; 4];
|
let mut result = [None; 4];
|
||||||
while let Some(character) = stream.try_next().await.unwrap() {
|
while let Some(character) = stream.try_next().await? {
|
||||||
let index = character.slot as usize;
|
let index = character.slot as usize;
|
||||||
result[index] = Some(character.into())
|
result[index] = Some(character.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, char: &CharacterEntity) {
|
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
let q = r#"update player_character set
|
let q = r#"update player_character set
|
||||||
user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12,
|
user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12,
|
||||||
hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23,
|
hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23,
|
||||||
@ -264,128 +259,134 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(char.meseta as i32)
|
.bind(char.meseta as i32)
|
||||||
.bind(char.bank_meseta as i32)
|
.bind(char.bank_meseta as i32)
|
||||||
.bind(char.id.0 as i32)
|
.bind(char.id.0 as i32)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
GuildCardDataEntity {
|
Ok(GuildCardDataEntity {
|
||||||
id: GuildCardDataId(0),
|
id: GuildCardDataId(0),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
guildcard: guildcard::GuildCardData::default(),
|
guildcard: guildcard::GuildCardData::default(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
|
let mut tx = self.pool.begin().await?;
|
||||||
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
||||||
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&mut tx).await?;
|
||||||
let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location {
|
let location = if let ItemLocation::Inventory{slot, ..} = &item.location {
|
||||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone())))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone())))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
sqlx::query("insert into inventory_slot (item, slot) values ($1, $2)")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(*slot as i32)
|
.bind(*slot as i32)
|
||||||
.bind(character_id.0 as i32)
|
.execute(&mut tx).await?;
|
||||||
.execute(&self.pool).await.unwrap();
|
|
||||||
sqlx::query_as::<_, PgItemLocation>(r#"select
|
sqlx::query_as::<_, PgItemLocation>(r#"select
|
||||||
item_location.item,
|
item_location.item,
|
||||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location,
|
jsonb_set(item_location.location, '{Inventory,slot}', inventory_slot.slot::text::jsonb) as location,
|
||||||
item_location.created_at
|
item_location.created_at
|
||||||
from item_location
|
from item_location
|
||||||
join item on item.id = item_location.item
|
join item on item.id = item_location.item
|
||||||
join inventory_slots on inventory_slots.pchar = cast (item_location.location -> 'Inventory' ->> 'character_id' as integer)
|
join inventory_slot on inventory_slot.item = item.id
|
||||||
where item.id = $1
|
where item.id = $1
|
||||||
order by item_location.created_at
|
order by item_location.created_at
|
||||||
limit 1"#)
|
limit 1"#)
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.fetch_one(&self.pool).await.unwrap()
|
.fetch_one(&mut tx).await?
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
||||||
.fetch_one(&self.pool).await.unwrap()
|
.fetch_one(&mut tx).await?
|
||||||
};
|
};
|
||||||
Some(ItemEntity {
|
tx.commit().await?;
|
||||||
|
Ok(ItemEntity {
|
||||||
id: ItemEntityId(new_item.id as u32),
|
id: ItemEntityId(new_item.id as u32),
|
||||||
item: new_item.item.0.into(),
|
item: new_item.item.0.into(),
|
||||||
location: location.location.0.into(),
|
location: location.location.0.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
if let ItemLocation::Inventory{character_id, slot, ..} = &item_location {
|
let mut tx = self.pool.begin().await?;
|
||||||
sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null")
|
if let ItemLocation::Inventory{slot, ..} = &item_location {
|
||||||
.bind(item_id.0 as i32)
|
sqlx::query("delete from inventory_slot where item = $1")
|
||||||
.bind(character_id.0 as i32)
|
|
||||||
.execute(&self.pool).await.unwrap();
|
|
||||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
|
||||||
.bind(item_id.0 as i32)
|
.bind(item_id.0 as i32)
|
||||||
|
.execute(&mut tx).await?;
|
||||||
|
sqlx::query("insert into inventory_slot (item, slot) values ($1, $2)")
|
||||||
|
.bind(item_id.0)
|
||||||
.bind(*slot as i32)
|
.bind(*slot as i32)
|
||||||
.bind(character_id.0 as i32)
|
.execute(&mut tx).await?;
|
||||||
.execute(&self.pool).await.unwrap();
|
|
||||||
sqlx::query(r#"insert into item_location (item, location)
|
sqlx::query(r#"insert into item_location (item, location)
|
||||||
select $1, $2
|
select $1, $2
|
||||||
where (select jsonb_object_keys(location) from item_location where item=$1
|
where (select jsonb_object_keys(location) from item_location where item=$1
|
||||||
order by created_at desc limit 1) != 'Inventory'"#)
|
order by created_at desc limit 1) != 'Inventory'"#)
|
||||||
.bind(item_id.0)
|
.bind(item_id.0)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||||
.bind(item_id.0)
|
.bind(item_id.0)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
}
|
}
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id})))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id})))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id))))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id))))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id))))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id))))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, char: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
let q = r#"select * from (
|
let q = r#"select * from (
|
||||||
select distinct on (item_location.item)
|
select distinct on (item_location.item)
|
||||||
item.id,
|
item.id,
|
||||||
case
|
case
|
||||||
when item_location.location -> 'Inventory' is not null then
|
when item_location.location -> 'Inventory' is not null then
|
||||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb)
|
jsonb_set(item_location.location, '{Inventory,slot}', inventory_slot.slot::text::jsonb)
|
||||||
else
|
else
|
||||||
item_location.location
|
item_location.location
|
||||||
end,
|
end,
|
||||||
item.item
|
item.item
|
||||||
from item_location
|
from item_location
|
||||||
join item on item.id = item_location.item
|
join item on item.id = item_location.item
|
||||||
join inventory_slots on inventory_slots.pchar = $1
|
join inventory_slot on inventory_slot.item = item.id
|
||||||
order by item_location.item, item_location.created_at desc
|
order by item_location.item, item_location.created_at desc
|
||||||
) as i
|
) as i
|
||||||
where cast (location -> 'Inventory' ->> 'character_id' as integer) = $1
|
where cast (location -> 'Inventory' ->> 'character_id' as integer) = $1
|
||||||
or cast (location -> 'Bank' ->> 'character_id' as integer) = $1
|
or cast (location -> 'Bank' ->> 'character_id' as integer) = $1
|
||||||
"#;
|
"#;
|
||||||
let items = sqlx::query_as::<_, PgItemWithLocation>(q)
|
let items = sqlx::query_as::<_, PgItemWithLocation>(q)
|
||||||
.bind(char.id.0)
|
.bind(char_id.0)
|
||||||
.fetch(&self.pool);
|
.fetch(&self.pool);
|
||||||
join_all(items
|
Ok(join_all(items
|
||||||
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
||||||
let item = item.ok()?;
|
let item = item.ok()?;
|
||||||
Some(ItemEntity {
|
Some(ItemEntity {
|
||||||
@ -399,6 +400,6 @@ impl EntityGateway for PostgresGateway {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.await
|
.await
|
||||||
).await
|
).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ pub enum ItemParseError {
|
|||||||
InvalidArmorType,
|
InvalidArmorType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum ArmorType {
|
pub enum ArmorType {
|
||||||
Frame,
|
Frame,
|
||||||
Armor,
|
Armor,
|
||||||
@ -289,7 +289,7 @@ impl ArmorType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ArmorModifier {
|
pub enum ArmorModifier {
|
||||||
AddSlot {
|
AddSlot {
|
||||||
addslot: ItemEntityId,
|
addslot: ItemEntityId,
|
||||||
@ -297,7 +297,7 @@ pub enum ArmorModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Armor {
|
pub struct Armor {
|
||||||
pub armor: ArmorType,
|
pub armor: ArmorType,
|
||||||
pub dfp: u8,
|
pub dfp: u8,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ pub enum ItemParseError {
|
|||||||
InvalidESWeaponName,
|
InvalidESWeaponName,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, strum_macros::EnumIter)]
|
||||||
pub enum ESWeaponType {
|
pub enum ESWeaponType {
|
||||||
Saber = 0,
|
Saber = 0,
|
||||||
Sword,
|
Sword,
|
||||||
@ -121,7 +121,7 @@ impl ESWeaponType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, strum_macros::EnumIter)]
|
||||||
pub enum ESWeaponSpecial {
|
pub enum ESWeaponSpecial {
|
||||||
Jellen = 1,
|
Jellen = 1,
|
||||||
Zalure,
|
Zalure,
|
||||||
@ -169,7 +169,7 @@ impl ESWeaponSpecial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ESWeapon {
|
pub struct ESWeapon {
|
||||||
pub esweapon: ESWeaponType,
|
pub esweapon: ESWeaponType,
|
||||||
pub special: Option<ESWeaponSpecial>,
|
pub special: Option<ESWeaponSpecial>,
|
||||||
|
|||||||
@ -64,7 +64,7 @@ pub enum ItemParseError {
|
|||||||
InvalidMagBytes,
|
InvalidMagBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum MagType {
|
pub enum MagType {
|
||||||
Mag,
|
Mag,
|
||||||
Varuna,
|
Varuna,
|
||||||
@ -519,7 +519,7 @@ pub enum MagModifier {
|
|||||||
OwnerChange(CharacterClass, SectionID)
|
OwnerChange(CharacterClass, SectionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, enum_utils::FromStr)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr)]
|
||||||
pub enum PhotonBlast {
|
pub enum PhotonBlast {
|
||||||
Farlla,
|
Farlla,
|
||||||
Estlla,
|
Estlla,
|
||||||
@ -529,7 +529,7 @@ pub enum PhotonBlast {
|
|||||||
MyllaYoulla,
|
MyllaYoulla,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Mag {
|
pub struct Mag {
|
||||||
pub mag: MagType,
|
pub mag: MagType,
|
||||||
def: u16,
|
def: u16,
|
||||||
|
|||||||
@ -8,11 +8,12 @@ pub mod unit;
|
|||||||
pub mod mag;
|
pub mod mag;
|
||||||
pub mod esweapon;
|
pub mod esweapon;
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
use crate::entity::character::CharacterEntityId;
|
use crate::entity::character::CharacterEntityId;
|
||||||
use crate::ship::map::MapArea;
|
use crate::ship::map::MapArea;
|
||||||
use crate::ship::drops::ItemDropType;
|
use crate::ship::drops::ItemDropType;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct ItemEntityId(pub u32);
|
pub struct ItemEntityId(pub u32);
|
||||||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||||
pub struct ItemId(u32);
|
pub struct ItemId(u32);
|
||||||
@ -88,7 +89,7 @@ pub enum ItemParseError {
|
|||||||
InvalidBytes
|
InvalidBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ItemDetail {
|
pub enum ItemDetail {
|
||||||
Weapon(weapon::Weapon),
|
Weapon(weapon::Weapon),
|
||||||
Armor(armor::Armor),
|
Armor(armor::Armor),
|
||||||
|
|||||||
@ -6,7 +6,7 @@ pub enum ItemParseError {
|
|||||||
InvalidShieldType,
|
InvalidShieldType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum ShieldType {
|
pub enum ShieldType {
|
||||||
Barrier,
|
Barrier,
|
||||||
Shield,
|
Shield,
|
||||||
@ -519,7 +519,7 @@ impl ShieldType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Shield {
|
pub struct Shield {
|
||||||
pub shield: ShieldType,
|
pub shield: ShieldType,
|
||||||
pub dfp: u8,
|
pub dfp: u8,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum Technique {
|
pub enum Technique {
|
||||||
Foie,
|
Foie,
|
||||||
Gifoie,
|
Gifoie,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ pub enum ItemParseError {
|
|||||||
InvalidToolType,
|
InvalidToolType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum ToolType {
|
pub enum ToolType {
|
||||||
Monomate,
|
Monomate,
|
||||||
Dimate,
|
Dimate,
|
||||||
@ -648,7 +648,7 @@ impl ToolType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Tool {
|
pub struct Tool {
|
||||||
pub tool: ToolType,
|
pub tool: ToolType,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ pub enum ItemParseError {
|
|||||||
InvalidUnitType,
|
InvalidUnitType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum UnitType {
|
pub enum UnitType {
|
||||||
KnightPower,
|
KnightPower,
|
||||||
GeneralPower,
|
GeneralPower,
|
||||||
@ -331,7 +331,7 @@ pub enum UnitModifier {
|
|||||||
MinusMinus,
|
MinusMinus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Unit {
|
pub struct Unit {
|
||||||
pub unit: UnitType,
|
pub unit: UnitType,
|
||||||
pub modifier: Option<UnitModifier>,
|
pub modifier: Option<UnitModifier>,
|
||||||
|
|||||||
@ -32,7 +32,7 @@ impl Attribute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct WeaponAttribute {
|
pub struct WeaponAttribute {
|
||||||
pub attr: Attribute,
|
pub attr: Attribute,
|
||||||
pub value: i8,
|
pub value: i8,
|
||||||
@ -45,7 +45,7 @@ impl WeaponAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, strum_macros::EnumIter)]
|
||||||
pub enum WeaponSpecial {
|
pub enum WeaponSpecial {
|
||||||
Draw = 1,
|
Draw = 1,
|
||||||
Drain,
|
Drain,
|
||||||
@ -141,7 +141,7 @@ impl WeaponSpecial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
|
||||||
pub enum WeaponType {
|
pub enum WeaponType {
|
||||||
Saber,
|
Saber,
|
||||||
Brand,
|
Brand,
|
||||||
@ -1332,14 +1332,14 @@ impl WeaponType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum TekSpecialModifier {
|
pub enum TekSpecialModifier {
|
||||||
Plus,
|
Plus,
|
||||||
Neutral,
|
Neutral,
|
||||||
Minus,
|
Minus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum TekPercentModifier {
|
pub enum TekPercentModifier {
|
||||||
PlusPlus,
|
PlusPlus,
|
||||||
Plus,
|
Plus,
|
||||||
@ -1348,7 +1348,7 @@ pub enum TekPercentModifier {
|
|||||||
MinusMinus,
|
MinusMinus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum WeaponModifier {
|
pub enum WeaponModifier {
|
||||||
AddPercents {
|
AddPercents {
|
||||||
attr: WeaponAttribute,
|
attr: WeaponAttribute,
|
||||||
@ -1364,7 +1364,7 @@ pub enum WeaponModifier {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Weapon {
|
pub struct Weapon {
|
||||||
pub weapon: WeaponType,
|
pub weapon: WeaponType,
|
||||||
pub special: Option<WeaponSpecial>,
|
pub special: Option<WeaponSpecial>,
|
||||||
|
|||||||
@ -24,10 +24,10 @@ use crate::entity::item::weapon::Weapon;
|
|||||||
use crate::entity::item::armor::Armor;
|
use crate::entity::item::armor::Armor;
|
||||||
use crate::entity::item::tech::Technique;
|
use crate::entity::item::tech::Technique;
|
||||||
use crate::entity::item::tool::Tool;
|
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::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel};
|
||||||
|
|
||||||
use crate::login::login::get_login_status;
|
use crate::login::login::{get_login_status, check_if_already_online};
|
||||||
|
|
||||||
pub const CHARACTER_PORT: u16 = 12001;
|
pub const CHARACTER_PORT: u16 = 12001;
|
||||||
const SHIP_MENU_ID: u32 = 1;
|
const SHIP_MENU_ID: u32 = 1;
|
||||||
@ -36,6 +36,10 @@ const SHIP_MENU_ID: u32 = 1;
|
|||||||
pub enum CharacterError {
|
pub enum CharacterError {
|
||||||
InvalidMenuSelection(u32, u32),
|
InvalidMenuSelection(u32, u32),
|
||||||
ClientNotFound(ClientId),
|
ClientNotFound(ClientId),
|
||||||
|
CouldNotLoadSettings,
|
||||||
|
CouldNotLoadCharacters,
|
||||||
|
CouldNotLoadGuildcard,
|
||||||
|
DbError,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -181,7 +185,6 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
character.meseta = 300;
|
character.meseta = 300;
|
||||||
|
|
||||||
let character = entity_gateway.create_character(character).await.unwrap();
|
let character = entity_gateway.create_character(character).await.unwrap();
|
||||||
|
|
||||||
let new_weapon = match character.char_class {
|
let new_weapon = match character.char_class {
|
||||||
@ -206,7 +209,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}}).await;
|
}}).await.unwrap();
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
@ -222,7 +225,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}}).await;
|
}}).await.unwrap();
|
||||||
|
|
||||||
let mut mag = Mag::baby_mag(character.appearance.skin);
|
let mut mag = Mag::baby_mag(character.appearance.skin);
|
||||||
mag.change_owner(character.char_class, character.section_id);
|
mag.change_owner(character.char_class, character.section_id);
|
||||||
@ -233,7 +236,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 2,
|
slot: 2,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}}).await;
|
}}).await.unwrap();
|
||||||
|
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -246,7 +249,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 3,
|
slot: 3,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}}).await;
|
}}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Tool (
|
item: ItemDetail::Tool (
|
||||||
@ -257,7 +260,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 4,
|
slot: 4,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}}).await;
|
}}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,8 +281,11 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
|
|
||||||
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
Ok(match get_login_status(&self.entity_gateway, pkt).await {
|
Ok(match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) {
|
||||||
Ok(user) => {
|
Ok(mut user) => {
|
||||||
|
user.at_character = true;
|
||||||
|
self.entity_gateway.save_user(&user).await.map_err(|_| CharacterError::DbError)?;
|
||||||
|
|
||||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||||
response.guildcard = user.guildcard;
|
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) as u32;
|
||||||
@ -310,12 +316,11 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
let user = client.user.as_ref().unwrap();
|
let user = client.user.as_ref().unwrap();
|
||||||
|
|
||||||
// TODO: this should error (data should be added on account creation, why did I copy this silly sylv logic?)
|
|
||||||
let settings = match self.entity_gateway.get_user_settings_by_user(&user).await {
|
let settings = match self.entity_gateway.get_user_settings_by_user(&user).await {
|
||||||
Some(settings) => settings,
|
Ok(settings) => settings,
|
||||||
None => {
|
Err(_) => {
|
||||||
let user_settings = NewUserSettingsEntity::new(user.id);
|
let user_settings = NewUserSettingsEntity::new(user.id);
|
||||||
self.entity_gateway.create_user_settings(user_settings).await.unwrap()
|
self.entity_gateway.create_user_settings(user_settings).await.map_err(|_| CharacterError::CouldNotLoadSettings)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -329,7 +334,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
if client.characters.is_none() {
|
if client.characters.is_none() {
|
||||||
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await);
|
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadCharacters)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if select.reason == 0 {
|
if select.reason == 0 {
|
||||||
@ -374,7 +379,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
|
|
||||||
async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await;
|
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();
|
let bytes = guildcard_data.guildcard.as_bytes();
|
||||||
let mut crc = crc32::Digest::new(crc32::IEEE);
|
let mut crc = crc32::Digest::new(crc32::IEEE);
|
||||||
@ -404,7 +409,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
let mut user = client.user.as_mut().unwrap();
|
let mut user = client.user.as_mut().unwrap();
|
||||||
user.flags = setflag.flags;
|
user.flags = setflag.flags;
|
||||||
self.entity_gateway.save_user(&user).await;
|
self.entity_gateway.save_user(&user).await.unwrap();
|
||||||
Ok(None.into_iter())
|
Ok(None.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +447,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
client.session.action = SessionAction::SelectCharacter;
|
client.session.action = SessionAction::SelectCharacter;
|
||||||
client.session.character_slot = preview.slot as u8;
|
client.session.character_slot = preview.slot as u8;
|
||||||
user.flags = 0;
|
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,
|
Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard,
|
||||||
user.team_id.unwrap_or(1),
|
user.team_id.unwrap_or(1),
|
||||||
client.session)),
|
client.session)),
|
||||||
@ -470,7 +475,7 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
type RecvPacket = RecvCharacterPacket;
|
type RecvPacket = RecvCharacterPacket;
|
||||||
type PacketError = CharacterError;
|
type PacketError = CharacterError;
|
||||||
|
|
||||||
fn on_connect(&mut self, id: ClientId) -> Vec<OnConnect<Self::SendPacket>> {
|
async fn on_connect(&mut self, id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, CharacterError> {
|
||||||
self.clients.insert(id, ClientState::new());
|
self.clients.insert(id, ClientState::new());
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
@ -480,10 +485,10 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
rng.fill(&mut server_key[..]);
|
rng.fill(&mut server_key[..]);
|
||||||
rng.fill(&mut client_key[..]);
|
rng.fill(&mut client_key[..]);
|
||||||
|
|
||||||
vec![OnConnect::Packet(SendCharacterPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))),
|
Ok(vec![OnConnect::Packet(SendCharacterPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))),
|
||||||
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
||||||
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket)
|
||||||
@ -530,8 +535,14 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendCharacterPacket)> {
|
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendCharacterPacket)>, CharacterError> {
|
||||||
Vec::new()
|
if let Some(client) = self.clients.remove(&id) {
|
||||||
|
if let Some(mut user) = client.user {
|
||||||
|
user.at_character= false;
|
||||||
|
self.entity_gateway.save_user(&user).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +552,7 @@ impl<EG: EntityGateway> InterserverActor for CharacterServerState<EG> {
|
|||||||
type RecvMessage = ShipMessage;
|
type RecvMessage = ShipMessage;
|
||||||
type Error = ();
|
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()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,6 +568,7 @@ impl<EG: EntityGateway> InterserverActor for CharacterServerState<EG> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> {
|
||||||
|
self.ships.remove(&id);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -650,8 +662,7 @@ mod test {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use libpso::character::{settings, character};
|
use libpso::character::{settings, character};
|
||||||
use std::time::SystemTime;
|
use crate::entity::gateway::{InMemoryGateway, GatewayError};
|
||||||
use crate::entity::gateway::{InMemoryGateway};
|
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_option_send() {
|
async fn test_option_send() {
|
||||||
@ -661,8 +672,8 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
Some(UserSettingsEntity {
|
Ok(UserSettingsEntity {
|
||||||
id: UserSettingsId(0),
|
id: UserSettingsId(0),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
settings: settings::UserSettings::default()
|
settings: settings::UserSettings::default()
|
||||||
@ -682,6 +693,10 @@ mod test {
|
|||||||
created_at: chrono::Utc::now(),
|
created_at: chrono::Utc::now(),
|
||||||
team_id: None,
|
team_id: None,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
});
|
});
|
||||||
server.clients.insert(ClientId(5), clientstate);
|
server.clients.insert(ClientId(5), clientstate);
|
||||||
|
|
||||||
@ -725,6 +740,10 @@ mod test {
|
|||||||
muted_until: None,
|
muted_until: None,
|
||||||
created_at: chrono::Utc::now(),
|
created_at: chrono::Utc::now(),
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut server = CharacterServerState::new(test_data.clone());
|
let mut server = CharacterServerState::new(test_data.clone());
|
||||||
@ -760,7 +779,7 @@ mod test {
|
|||||||
} })).await.unwrap().collect::<Vec<_>>();
|
} })).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(send.len() == 2);
|
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[1].as_ref().unwrap().name == "\tEtest name");
|
||||||
assert!(chars[0].is_none());
|
assert!(chars[0].is_none());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
// TODO: rename this module to auth
|
// TODO: rename this module to auth
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::net;
|
use std::net;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
@ -21,6 +22,7 @@ pub const COMMUNICATION_PORT: u16 = 12123;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoginError {
|
pub enum LoginError {
|
||||||
|
DbError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -56,11 +58,19 @@ impl SendServerPacket for SendLoginPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result<UserAccountEntity, AccountStatus> {
|
pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result<UserAccountEntity, AccountStatus> {
|
||||||
let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?;
|
let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?;
|
||||||
let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?;
|
let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?;
|
||||||
let user = entity_gateway.get_user_by_name(username).await.ok_or(AccountStatus::InvalidUser)?;
|
let user = entity_gateway.get_user_by_name(username).await.map_err(|_| AccountStatus::InvalidUser)?;
|
||||||
|
/*if user.is_currently_online() {
|
||||||
|
return Err(AccountStatus::AlreadyOnline)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
log::info!("user: {}, activated {}", user.username, user.activated);
|
||||||
|
if !user.activated {
|
||||||
|
return Err(AccountStatus::PayUp)
|
||||||
|
}
|
||||||
|
|
||||||
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
||||||
match verified {
|
match verified {
|
||||||
true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) {
|
true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) {
|
||||||
@ -73,29 +83,47 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_if_already_online(user: UserAccountEntity) -> Result<UserAccountEntity, AccountStatus> {
|
||||||
|
Ok(user)
|
||||||
|
/*
|
||||||
|
if user.is_currently_online() {
|
||||||
|
Err(AccountStatus::PayUp)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LoginServerState<EG: EntityGateway> {
|
pub struct LoginServerState<EG: EntityGateway> {
|
||||||
|
character_server_ip: net::Ipv4Addr,
|
||||||
entity_gateway: EG,
|
entity_gateway: EG,
|
||||||
|
clients: HashMap<ClientId, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EG: EntityGateway> LoginServerState<EG> {
|
impl<EG: EntityGateway> LoginServerState<EG> {
|
||||||
pub fn new(entity_gateway: EG) -> LoginServerState<EG> {
|
pub fn new(entity_gateway: EG, character_server_ip: net::Ipv4Addr) -> LoginServerState<EG> {
|
||||||
LoginServerState {
|
LoginServerState {
|
||||||
entity_gateway: entity_gateway,
|
entity_gateway: entity_gateway,
|
||||||
|
character_server_ip: character_server_ip.into(),
|
||||||
|
clients: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn validate_login(&mut self, pkt: &Login) -> Vec<SendLoginPacket> {
|
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendLoginPacket>, LoginError> {
|
||||||
match get_login_status(&self.entity_gateway, pkt).await {
|
match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) {
|
||||||
Ok(_user) => {
|
Ok(mut user) => {
|
||||||
|
user.at_login = true;
|
||||||
|
self.entity_gateway.save_user(&user).await.map_err(|_| LoginError::DbError)?;
|
||||||
|
self.clients.insert(id, user.username.clone());
|
||||||
|
|
||||||
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
||||||
let ip = net::Ipv4Addr::new(127,0,0,1);
|
let ip = u32::from_ne_bytes(self.character_server_ip.octets());
|
||||||
let ip = u32::from_ne_bytes(ip.octets());
|
Ok(vec![response,
|
||||||
vec![response,
|
SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))])
|
||||||
SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))]
|
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))]
|
Ok(vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +135,7 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
|||||||
type RecvPacket = RecvLoginPacket;
|
type RecvPacket = RecvLoginPacket;
|
||||||
type PacketError = LoginError;
|
type PacketError = LoginError;
|
||||||
|
|
||||||
fn on_connect(&mut self, _id: ClientId) -> Vec<OnConnect<Self::SendPacket>> {
|
async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, LoginError> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let mut server_key = [0u8; 48];
|
let mut server_key = [0u8; 48];
|
||||||
@ -115,17 +143,17 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
|||||||
rng.fill(&mut server_key[..]);
|
rng.fill(&mut server_key[..]);
|
||||||
rng.fill(&mut client_key[..]);
|
rng.fill(&mut client_key[..]);
|
||||||
|
|
||||||
vec![OnConnect::Packet(SendLoginPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))),
|
Ok(vec![OnConnect::Packet(SendLoginPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))),
|
||||||
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
||||||
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
||||||
Ok(match pkt {
|
Ok(match pkt {
|
||||||
RecvLoginPacket::Login(login) => {
|
RecvLoginPacket::Login(login) => {
|
||||||
Box::new(self.validate_login(login).await
|
Box::new(self.validate_login(id, login).await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |pkt| {
|
.map(move |pkt| {
|
||||||
(id, pkt)
|
(id, pkt)
|
||||||
@ -134,17 +162,23 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendLoginPacket)> {
|
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendLoginPacket)>, LoginError> {
|
||||||
Vec::new()
|
if let Some(username) = self.clients.remove(&id) {
|
||||||
|
if let Ok(mut user) = self.entity_gateway.get_user_by_name(username).await {
|
||||||
|
user.at_login = false;
|
||||||
|
self.entity_gateway.save_user(&user).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::time::SystemTime;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::entity::account::{UserAccountId};
|
use crate::entity::account::{UserAccountId};
|
||||||
|
use crate::entity::gateway::GatewayError;
|
||||||
|
|
||||||
const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login {
|
const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login {
|
||||||
tag: 65536,
|
tag: 65536,
|
||||||
@ -178,9 +212,9 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
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");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
username: "testuser".to_owned(),
|
username: "testuser".to_owned(),
|
||||||
password: bcrypt::hash("mypassword", 5).unwrap(),
|
password: bcrypt::hash("mypassword", 5).unwrap(),
|
||||||
@ -190,11 +224,19 @@ mod test {
|
|||||||
muted_until: None,
|
muted_until: None,
|
||||||
created_at: chrono::Utc::now(),
|
created_at: chrono::Utc::now(),
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
@ -228,12 +270,12 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
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> {
|
||||||
None
|
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<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
@ -262,9 +304,9 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
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");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
username: "testuser".to_owned(),
|
username: "testuser".to_owned(),
|
||||||
password: bcrypt::hash("notpassword", 5).unwrap(),
|
password: bcrypt::hash("notpassword", 5).unwrap(),
|
||||||
@ -274,11 +316,15 @@ mod test {
|
|||||||
muted_until: None,
|
muted_until: None,
|
||||||
created_at: chrono::Utc::now(),
|
created_at: chrono::Utc::now(),
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
@ -307,9 +353,9 @@ mod test {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
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");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Ok(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
username: "testuser".to_owned(),
|
username: "testuser".to_owned(),
|
||||||
password: bcrypt::hash("mypassword", 5).unwrap(),
|
password: bcrypt::hash("mypassword", 5).unwrap(),
|
||||||
@ -319,11 +365,15 @@ mod test {
|
|||||||
muted_until: None,
|
muted_until: None,
|
||||||
created_at: chrono::Utc::now(),
|
created_at: chrono::Utc::now(),
|
||||||
flags: 0,
|
flags: 0,
|
||||||
|
activated: true,
|
||||||
|
at_login: false,
|
||||||
|
at_character: false,
|
||||||
|
at_ship: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
|
|||||||
@ -160,14 +160,14 @@ impl ServerState for PatchServerState {
|
|||||||
type RecvPacket = RecvPatchPacket;
|
type RecvPacket = RecvPatchPacket;
|
||||||
type PacketError = PatchError;
|
type PacketError = PatchError;
|
||||||
|
|
||||||
fn on_connect(&mut self, _id: ClientId) -> Vec<OnConnect<Self::SendPacket>> {
|
async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, PatchError> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let key_in: u32 = rng.gen();
|
let key_in: u32 = rng.gen();
|
||||||
let key_out: u32 = rng.gen();
|
let key_out: u32 = rng.gen();
|
||||||
|
|
||||||
vec![OnConnect::Packet(SendPatchPacket::PatchWelcome(PatchWelcome::new(key_out, key_in))),
|
Ok(vec![OnConnect::Packet(SendPatchPacket::PatchWelcome(PatchWelcome::new(key_out, key_in))),
|
||||||
OnConnect::Cipher((Box::new(PSOPCCipher::new(key_in)), Box::new(PSOPCCipher::new(key_out))))
|
OnConnect::Cipher((Box::new(PSOPCCipher::new(key_in)), Box::new(PSOPCCipher::new(key_out))))
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket)
|
||||||
@ -202,8 +202,8 @@ impl ServerState for PatchServerState {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendPatchPacket)> {
|
async fn on_disconnect(&mut self, _id: ClientId) -> Result<Vec<(ClientId, SendPatchPacket)>, PatchError> {
|
||||||
Vec::new()
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ impl Iterator for SendFileIterator {
|
|||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct PatchConfig {
|
pub struct PatchConfig {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub ip: String,
|
pub ip: String, // TODO: this does nothing
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,11 +403,22 @@ pub fn load_config() -> PatchConfig {
|
|||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_motd() -> String {
|
pub fn load_config_env() -> PatchConfig {
|
||||||
let mut motd: String = "Welcome to Elseware!".to_string();
|
let patch_path = std::env::var("PATCHFILE_DIR").unwrap();
|
||||||
|
let patch_port = std::env::var("PATCH_PORT").unwrap().parse().unwrap();
|
||||||
|
|
||||||
|
PatchConfig {
|
||||||
|
path: patch_path,
|
||||||
|
ip: "127.0.0.1".into(),
|
||||||
|
port: patch_port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_motd() -> String {
|
||||||
if let Ok(m) = fs::read_to_string("patch.motd") {
|
if let Ok(m) = fs::read_to_string("patch.motd") {
|
||||||
motd = m.clone();
|
m
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"Welcome to Elseware!".to_string()
|
||||||
}
|
}
|
||||||
motd
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,7 +136,7 @@ impl RareDropTable {
|
|||||||
tool: tool,
|
tool: tool,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
RareDropItem::Mag(mag) => {
|
RareDropItem::Mag(_mag) => {
|
||||||
ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18)))
|
ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,10 +48,11 @@ pub enum ItemManagerError {
|
|||||||
CannotGetIndividualItem,
|
CannotGetIndividualItem,
|
||||||
InvalidSlot(u8, u8), // slots available, slot attempted
|
InvalidSlot(u8, u8), // slots available, slot attempted
|
||||||
NoArmorEquipped,
|
NoArmorEquipped,
|
||||||
|
GatewayError(#[from] crate::entity::gateway::GatewayError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) {
|
async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) -> Result<(), ItemManagerError> {
|
||||||
for (slot, item) in inventory.iter().enumerate() {
|
for (slot, item) in inventory.iter().enumerate() {
|
||||||
match item {
|
match item {
|
||||||
InventoryItem::Individual(individual_inventory_item) => {
|
InventoryItem::Individual(individual_inventory_item) => {
|
||||||
@ -62,7 +63,7 @@ async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, char
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: individual_inventory_item.equipped,
|
equipped: individual_inventory_item.equipped,
|
||||||
}
|
}
|
||||||
).await
|
).await?
|
||||||
},
|
},
|
||||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||||
for entity_id in stacked_inventory_item.entity_ids.iter() {
|
for entity_id in stacked_inventory_item.entity_ids.iter() {
|
||||||
@ -72,11 +73,13 @@ async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, char
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;
|
}).await?
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ItemManager {
|
pub struct ItemManager {
|
||||||
@ -111,8 +114,8 @@ impl ItemManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Result
|
// TODO: Result
|
||||||
pub async fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) {
|
pub async fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) -> Result<(), ItemManagerError> {
|
||||||
let items = entity_gateway.get_items_by_character(&character).await;
|
let items = entity_gateway.get_items_by_character(&character.id).await?;
|
||||||
let inventory_items = items.clone().into_iter()
|
let inventory_items = items.clone().into_iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
match item.location {
|
match item.location {
|
||||||
@ -204,6 +207,7 @@ impl ItemManager {
|
|||||||
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
||||||
self.character_inventory.insert(character.id, inventory);
|
self.character_inventory.insert(character.id, inventory);
|
||||||
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
|
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
||||||
@ -300,9 +304,9 @@ impl ItemManager {
|
|||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
).await;
|
).await?;
|
||||||
if let Some(_) = new_inventory_item.mag() {
|
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 => {
|
None => {
|
||||||
@ -324,7 +328,7 @@ impl ItemManager {
|
|||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
).await;
|
).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if stacked_floor_item.count() != new_inventory_item.count() {
|
if stacked_floor_item.count() != new_inventory_item.count() {
|
||||||
@ -344,7 +348,7 @@ impl ItemManager {
|
|||||||
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
|
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
|
||||||
}
|
}
|
||||||
character.meseta = std::cmp::min(character.meseta + meseta_floor_item.meseta.0, 999999);
|
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
|
TriggerCreateItem::No
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
@ -392,7 +396,7 @@ impl ItemManager {
|
|||||||
y: item_drop.y,
|
y: item_drop.y,
|
||||||
z: item_drop.z,
|
z: item_drop.z,
|
||||||
}
|
}
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
FloorItem::Individual(IndividualFloorItem {
|
FloorItem::Individual(IndividualFloorItem {
|
||||||
entity_id: entity.id,
|
entity_id: entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -413,7 +417,7 @@ impl ItemManager {
|
|||||||
y: item_drop.y,
|
y: item_drop.y,
|
||||||
z: item_drop.z,
|
z: item_drop.z,
|
||||||
}
|
}
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
FloorItem::Stacked(StackedFloorItem {
|
FloorItem::Stacked(StackedFloorItem {
|
||||||
entity_ids: vec![entity.id],
|
entity_ids: vec![entity.id],
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -465,7 +469,7 @@ impl ItemManager {
|
|||||||
y: item_drop_location.2,
|
y: item_drop_location.2,
|
||||||
z: item_drop_location.3,
|
z: item_drop_location.3,
|
||||||
}
|
}
|
||||||
).await;
|
).await?;
|
||||||
},
|
},
|
||||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||||
let stacked_floor_item = shared_floor.drop_stacked_inventory_item(stacked_inventory_item, item_drop_location);
|
let stacked_floor_item = shared_floor.drop_stacked_inventory_item(stacked_inventory_item, item_drop_location);
|
||||||
@ -478,12 +482,12 @@ impl ItemManager {
|
|||||||
y: item_drop_location.2,
|
y: item_drop_location.2,
|
||||||
z: item_drop_location.3,
|
z: item_drop_location.3,
|
||||||
}
|
}
|
||||||
).await;
|
).await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +503,7 @@ impl ItemManager {
|
|||||||
return Err(ItemManagerError::CouldNotDropMeseta)
|
return Err(ItemManagerError::CouldNotDropMeseta)
|
||||||
}
|
}
|
||||||
character.meseta -= amount;
|
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 item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
||||||
let floor_item = FloorItem::Meseta(MesetaFloorItem {
|
let floor_item = FloorItem::Meseta(MesetaFloorItem {
|
||||||
@ -542,7 +546,7 @@ impl ItemManager {
|
|||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: drop_location.z,
|
z: drop_location.z,
|
||||||
}
|
}
|
||||||
).await;
|
).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(stacked_floor_item)
|
Ok(stacked_floor_item)
|
||||||
@ -560,10 +564,10 @@ impl ItemManager {
|
|||||||
|
|
||||||
for entity_id in consumed_item.entity_ids() {
|
for entity_id in consumed_item.entity_ids() {
|
||||||
entity_gateway.change_item_location(&entity_id,
|
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)
|
Ok(consumed_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +591,7 @@ impl ItemManager {
|
|||||||
ItemLocation::Bank {
|
ItemLocation::Bank {
|
||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
name: BankName("".to_string())
|
name: BankName("".to_string())
|
||||||
}).await;
|
}).await?;
|
||||||
},
|
},
|
||||||
BankItem::Stacked(stacked_bank_item) => {
|
BankItem::Stacked(stacked_bank_item) => {
|
||||||
for entity_id in &stacked_bank_item.entity_ids {
|
for entity_id in &stacked_bank_item.entity_ids {
|
||||||
@ -595,12 +599,12 @@ impl ItemManager {
|
|||||||
ItemLocation::Bank {
|
ItemLocation::Bank {
|
||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
name: BankName("".to_string())
|
name: BankName("".to_string())
|
||||||
}).await;
|
}).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +630,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;
|
}).await?;
|
||||||
},
|
},
|
||||||
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
|
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
|
||||||
for entity_id in &stacked_inventory_item.entity_ids {
|
for entity_id in &stacked_inventory_item.entity_ids {
|
||||||
@ -635,7 +639,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;
|
}).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -671,13 +675,13 @@ impl ItemManager {
|
|||||||
mag.feed(consumed_tool_type);
|
mag.feed(consumed_tool_type);
|
||||||
|
|
||||||
for entity_id in consumed_tool.entity_ids() {
|
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 {
|
entity_gateway.change_item_location(&entity_id, ItemLocation::FedToMag {
|
||||||
mag: individual_item.entity_id,
|
mag: individual_item.entity_id,
|
||||||
}).await;
|
}).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +795,7 @@ impl ItemManager {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +817,7 @@ impl ItemManager {
|
|||||||
item_entities.push(entity_gateway.create_item(NewItemEntity {
|
item_entities.push(entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: ItemDetail::Tool(tool),
|
item: ItemDetail::Tool(tool),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?);
|
}).await?);
|
||||||
}
|
}
|
||||||
let floor_item = StackedFloorItem {
|
let floor_item = StackedFloorItem {
|
||||||
entity_ids: item_entities.into_iter().map(|i| i.id).collect(),
|
entity_ids: item_entities.into_iter().map(|i| i.id).collect(),
|
||||||
@ -833,7 +837,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
}
|
}
|
||||||
picked_up_item.item_id
|
picked_up_item.item_id
|
||||||
};
|
};
|
||||||
@ -843,7 +847,7 @@ impl ItemManager {
|
|||||||
let item_entity = entity_gateway.create_item(NewItemEntity {
|
let item_entity = entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: ItemDetail::Tool(tool),
|
item: ItemDetail::Tool(tool),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
let floor_item = IndividualFloorItem {
|
let floor_item = IndividualFloorItem {
|
||||||
entity_id: item_entity.id,
|
entity_id: item_entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -861,7 +865,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
picked_up_item.item_id
|
picked_up_item.item_id
|
||||||
};
|
};
|
||||||
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
||||||
@ -871,7 +875,7 @@ impl ItemManager {
|
|||||||
let item_entity = entity_gateway.create_item(NewItemEntity {
|
let item_entity = entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: item_detail.clone(),
|
item: item_detail.clone(),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
let floor_item = IndividualFloorItem {
|
let floor_item = IndividualFloorItem {
|
||||||
entity_id: item_entity.id,
|
entity_id: item_entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -889,7 +893,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
picked_up_item.item_id
|
picked_up_item.item_id
|
||||||
};
|
};
|
||||||
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
use crate::entity::character::CharacterEntity;
|
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::entity::item::mag::MagCell;
|
||||||
use crate::ship::items::{ItemManager, ClientItemId, CharacterInventory, ConsumedItem};
|
use crate::ship::items::{CharacterInventory, ConsumedItem};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[error("")]
|
#[error("")]
|
||||||
@ -18,45 +12,39 @@ pub enum UseItemError {
|
|||||||
InvalidItem,
|
InvalidItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//pub fn use_tool()
|
|
||||||
|
|
||||||
pub async fn power_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
pub async fn power_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.power += 1;
|
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) {
|
pub async fn mind_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.mind += 1;
|
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) {
|
pub async fn evade_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.evade += 1;
|
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) {
|
pub async fn def_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.def += 1;
|
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) {
|
pub async fn luck_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.luck += 1;
|
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) {
|
pub async fn hp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.hp += 1;
|
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) {
|
pub async fn tp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||||
character.materials.tp += 1;
|
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> {
|
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);
|
actual_mag.apply_mag_cell(mag_cell_type);
|
||||||
for mag_entity_id in mag_item.entity_ids() {
|
for mag_entity_id in mag_item.entity_ids() {
|
||||||
for cell_entity_id in used_cell.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session};
|
|||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients};
|
use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients};
|
||||||
use crate::login::login::get_login_status;
|
use crate::login::login::{get_login_status, check_if_already_online};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
use crate::ship::items::ItemManager;
|
use crate::ship::items::ItemManager;
|
||||||
|
|
||||||
@ -13,21 +13,23 @@ pub async fn validate_login<EG: EntityGateway>(id: ClientId,
|
|||||||
item_manager: &mut ItemManager,
|
item_manager: &mut ItemManager,
|
||||||
ship_name: &String)
|
ship_name: &String)
|
||||||
-> Result<Vec<SendShipPacket>, ShipError> {
|
-> Result<Vec<SendShipPacket>, ShipError> {
|
||||||
Ok(match get_login_status(entity_gateway, pkt).await {
|
Ok(match get_login_status(entity_gateway, pkt).await.and_then(check_if_already_online) {
|
||||||
Ok(user) => {
|
Ok(mut user) => {
|
||||||
|
user.at_ship= true;
|
||||||
|
entity_gateway.save_user(&user).await?;
|
||||||
|
|
||||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||||
response.guildcard = user.id.0 as u32;
|
response.guildcard = user.id.0 as u32;
|
||||||
response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
|
response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
|
||||||
let characters = entity_gateway.get_characters_by_user(&user).await;
|
let characters = entity_gateway.get_characters_by_user(&user).await?;
|
||||||
let character = characters
|
let character = characters
|
||||||
.get(pkt.session.character_slot as usize)
|
.get(pkt.session.character_slot as usize)
|
||||||
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref()
|
.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(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
|
||||||
.clone();
|
.clone();
|
||||||
let settings = entity_gateway.get_user_settings_by_user(&user).await
|
let settings = entity_gateway.get_user_settings_by_user(&user).await?;
|
||||||
.ok_or(ShipError::ClientNotFound(id))?;
|
|
||||||
|
|
||||||
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));
|
clients.insert(id, ClientState::new(user, settings, character, pkt.session));
|
||||||
vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))]
|
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> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
client.character.info_board.update_infoboard(new_infoboard);
|
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())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,7 +97,7 @@ where
|
|||||||
item: item_drop,
|
item: item_drop,
|
||||||
};
|
};
|
||||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
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)?;
|
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)))));
|
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 {
|
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.meseta -= bank_interaction.meseta_amount;
|
||||||
client.character.bank_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()
|
Vec::new()
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ where
|
|||||||
if client.character.meseta + bank_interaction.meseta_amount <= 999999 {
|
if client.character.meseta + bank_interaction.meseta_amount <= 999999 {
|
||||||
client.character.meseta += bank_interaction.meseta_amount;
|
client.character.meseta += bank_interaction.meseta_amount;
|
||||||
client.character.bank_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()
|
Vec::new()
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
client.character.meseta -= item.price() as u32;
|
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 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)?;
|
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 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 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();
|
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;
|
client.character.exp += exp_gain;
|
||||||
entity_gateway.save_character(&client.character).await;
|
entity_gateway.save_character(&client.character).await?;
|
||||||
|
|
||||||
Ok(exp_pkts)
|
Ok(exp_pkts)
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ where
|
|||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
if client.character.meseta >= charge.meseta {
|
if client.character.meseta >= charge.meseta {
|
||||||
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()))
|
Ok(Box::new(None.into_iter()))
|
||||||
} else {
|
} else {
|
||||||
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
||||||
@ -278,7 +278,7 @@ where
|
|||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
if client.character.meseta >= 10 {
|
if client.character.meseta >= 10 {
|
||||||
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()))
|
Ok(Box::new(None.into_iter()))
|
||||||
} else {
|
} else {
|
||||||
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
||||||
|
|||||||
@ -10,7 +10,7 @@ pub async fn update_config<EG: EntityGateway>(id: ClientId,
|
|||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
client.character.config.update(update_config);
|
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())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,6 +22,6 @@ pub async fn save_options<EG: EntityGateway>(id: ClientId,
|
|||||||
// // TODO: don't unwrap?
|
// // TODO: don't unwrap?
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
client.character.option_flags = save_options.options;
|
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())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState
|
|||||||
use crate::common::leveltable::CharacterLevelTable;
|
use crate::common::leveltable::CharacterLevelTable;
|
||||||
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
||||||
|
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
||||||
use crate::entity::character::{CharacterEntity, SectionID};
|
use crate::entity::character::{CharacterEntity, SectionID};
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ use crate::ship::room;
|
|||||||
use crate::ship::quests;
|
use crate::ship::quests;
|
||||||
use crate::ship::map::{MapsError, MapAreaError, MapArea};
|
use crate::ship::map::{MapsError, MapAreaError, MapArea};
|
||||||
use crate::ship::packet::handler;
|
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 SHIP_PORT: u16 = 23423;
|
||||||
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2;
|
||||||
@ -62,6 +62,7 @@ pub enum ShipError {
|
|||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
NotEnoughMeseta(ClientId, u32),
|
NotEnoughMeseta(ClientId, u32),
|
||||||
ShopError,
|
ShopError,
|
||||||
|
GatewayError(#[from] GatewayError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -455,7 +456,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
type RecvPacket = RecvShipPacket;
|
type RecvPacket = RecvShipPacket;
|
||||||
type PacketError = ShipError;
|
type PacketError = ShipError;
|
||||||
|
|
||||||
fn on_connect(&mut self, _id: ClientId) -> Vec<OnConnect<Self::SendPacket>> {
|
async fn on_connect(&mut self, _id: ClientId) -> Result<Vec<OnConnect<Self::SendPacket>>, ShipError> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let mut server_key = [0u8; 48];
|
let mut server_key = [0u8; 48];
|
||||||
@ -463,10 +464,10 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
rng.fill(&mut server_key[..]);
|
rng.fill(&mut server_key[..]);
|
||||||
rng.fill(&mut client_key[..]);
|
rng.fill(&mut client_key[..]);
|
||||||
|
|
||||||
vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))),
|
Ok(vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))),
|
||||||
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)),
|
||||||
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key))))
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
|
||||||
@ -493,7 +494,8 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &self.client_location, &mut self.rooms)?
|
handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &self.client_location, &mut self.rooms)?
|
||||||
},
|
},
|
||||||
RecvShipPacket::MenuDetail(_menudetail) => {
|
RecvShipPacket::MenuDetail(_menudetail) => {
|
||||||
unreachable!();
|
//unreachable!();
|
||||||
|
Box::new(Vec::new().into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
||||||
if room_password_req.password == self.rooms[room_password_req.item as usize].as_ref()
|
if room_password_req.password == self.rooms[room_password_req.item as usize].as_ref()
|
||||||
@ -567,7 +569,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
RecvShipPacket::DoneLoadingQuest(_) => {
|
RecvShipPacket::DoneLoadingQuest(_) => {
|
||||||
handler::quest::done_loading_quest(id, &mut self.clients, &self.client_location)?
|
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())
|
Box::new(None.into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::SaveOptions(save_options) => {
|
RecvShipPacket::SaveOptions(save_options) => {
|
||||||
@ -576,7 +578,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> {
|
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
|
||||||
// TODO: don't unwrap!
|
// TODO: don't unwrap!
|
||||||
let client = self.clients.get(&id).unwrap();
|
let client = self.clients.get(&id).unwrap();
|
||||||
let area_client = self.client_location.get_local_client(id).unwrap();
|
let area_client = self.client_location.get_local_client(id).unwrap();
|
||||||
@ -599,9 +601,14 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
self.client_location.remove_client_from_area(id);
|
self.client_location.remove_client_from_area(id);
|
||||||
self.item_manager.remove_character_from_room(&client.character);
|
self.item_manager.remove_character_from_room(&client.character);
|
||||||
|
|
||||||
neighbors.into_iter().map(|n| {
|
if let Some(mut client) = self.clients.remove(&id) {
|
||||||
|
client.user.at_ship = false;
|
||||||
|
self.entity_gateway.save_user(&client.user).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(neighbors.into_iter().map(|n| {
|
||||||
(n.client, pkt.clone())
|
(n.client, pkt.clone())
|
||||||
}).collect()
|
}).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,11 +628,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())
|
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()
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -6,9 +5,6 @@ use std::convert::TryInto;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
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::ItemDetail;
|
||||||
use crate::entity::item::armor::{Armor, ArmorType};
|
use crate::entity::item::armor::{Armor, ArmorType};
|
||||||
use crate::entity::item::shield::{Shield, ShieldType};
|
use crate::entity::item::shield::{Shield, ShieldType};
|
||||||
|
|||||||
@ -6,9 +6,6 @@ use std::convert::TryInto;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
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::ItemDetail;
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use crate::entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::tech::{Technique, TechniqueDisk};
|
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> {
|
fn generate_tech_types(&mut self, character_level: usize) -> Vec<Technique> {
|
||||||
let tier = self.techs.0.iter()
|
let tier = self.techs.0.iter()
|
||||||
.filter(|t| t.level <= character_level)
|
.filter(|t| t.level <= character_level)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
use elseware::common::serverstate::{ClientId, ServerState};
|
use elseware::common::serverstate::{ClientId, ServerState};
|
||||||
use elseware::entity::gateway::EntityGateway;
|
use elseware::entity::gateway::EntityGateway;
|
||||||
@ -19,11 +18,8 @@ pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, user
|
|||||||
username: username.into(),
|
username: username.into(),
|
||||||
password: bcrypt::hash(password, 5).unwrap(),
|
password: bcrypt::hash(password, 5).unwrap(),
|
||||||
guildcard: 1,
|
guildcard: 1,
|
||||||
team_id: None,
|
activated: true,
|
||||||
banned_until: None,
|
..NewUserAccountEntity::default()
|
||||||
muted_until: None,
|
|
||||||
created_at: chrono::Utc::now(),
|
|
||||||
flags: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = entity_gateway.create_user(new_user).await.unwrap();
|
let user = entity_gateway.create_user(new_user).await.unwrap();
|
||||||
|
|||||||
@ -33,7 +33,7 @@ async fn test_bank_items_sent_in_character_login() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -72,7 +72,7 @@ async fn test_request_bank_items() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -117,7 +117,7 @@ async fn test_request_stacked_bank_items() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -165,7 +165,7 @@ async fn test_request_bank_items_sorted() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Tool (
|
item: item::ItemDetail::Tool (
|
||||||
@ -177,7 +177,7 @@ async fn test_request_bank_items_sorted() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Weapon(
|
item: item::ItemDetail::Weapon(
|
||||||
@ -194,7 +194,7 @@ async fn test_request_bank_items_sorted() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -243,7 +243,7 @@ async fn test_deposit_individual_item() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Weapon(
|
item: item::ItemDetail::Weapon(
|
||||||
@ -261,7 +261,7 @@ async fn test_deposit_individual_item() {
|
|||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -295,7 +295,7 @@ async fn test_deposit_individual_item() {
|
|||||||
&& player_no_longer_has_item.amount == 0
|
&& player_no_longer_has_item.amount == 0
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -329,7 +329,7 @@ async fn test_deposit_stacked_item() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -364,7 +364,7 @@ async fn test_deposit_stacked_item() {
|
|||||||
&& player_no_longer_has_item.amount == 3
|
&& player_no_longer_has_item.amount == 3
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -398,7 +398,7 @@ async fn test_deposit_partial_stacked_item() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -433,7 +433,7 @@ async fn test_deposit_partial_stacked_item() {
|
|||||||
&& player_no_longer_has_item.amount == 2
|
&& player_no_longer_has_item.amount == 2
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -480,7 +480,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -493,7 +493,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".into()),
|
name: item::BankName("".into()),
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -528,7 +528,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() {
|
|||||||
&& player_no_longer_has_item.amount == 2
|
&& player_no_longer_has_item.amount == 2
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -561,7 +561,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
@ -576,7 +576,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".into()),
|
name: item::BankName("".into()),
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -604,7 +604,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -653,7 +653,7 @@ async fn test_deposit_individual_item_in_full_bank() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
for _ in 0..200 {
|
for _ in 0..200 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -672,7 +672,7 @@ async fn test_deposit_individual_item_in_full_bank() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -700,7 +700,7 @@ async fn test_deposit_individual_item_in_full_bank() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -745,7 +745,7 @@ async fn test_deposit_stacked_item_in_full_bank() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..200 {
|
for _ in 0..200 {
|
||||||
@ -765,7 +765,7 @@ async fn test_deposit_stacked_item_in_full_bank() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -793,7 +793,7 @@ async fn test_deposit_stacked_item_in_full_bank() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -838,7 +838,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..199 {
|
for _ in 0..199 {
|
||||||
@ -858,7 +858,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
@ -873,7 +873,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -899,7 +899,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -931,7 +931,7 @@ async fn test_deposit_meseta() {
|
|||||||
|
|
||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.meseta = 300;
|
char1.meseta = 300;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -956,7 +956,7 @@ async fn test_deposit_meseta() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 277);
|
assert!(char.meseta == 277);
|
||||||
assert!(char.bank_meseta == 23);
|
assert!(char.bank_meseta == 23);
|
||||||
@ -969,7 +969,7 @@ async fn test_deposit_too_much_meseta() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.meseta = 300;
|
char1.meseta = 300;
|
||||||
char1.bank_meseta = 999980;
|
char1.bank_meseta = 999980;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -994,7 +994,7 @@ async fn test_deposit_too_much_meseta() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 300);
|
assert!(char.meseta == 300);
|
||||||
assert!(char.bank_meseta == 999980);
|
assert!(char.bank_meseta == 999980);
|
||||||
@ -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;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.meseta = 300;
|
char1.meseta = 300;
|
||||||
char1.bank_meseta = 999999;
|
char1.bank_meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -1033,7 +1033,7 @@ async fn test_deposit_meseta_when_bank_is_maxed() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 300);
|
assert!(char.meseta == 300);
|
||||||
assert!(char.bank_meseta == 999999);
|
assert!(char.bank_meseta == 999999);
|
||||||
@ -1063,7 +1063,7 @@ async fn test_withdraw_individual_item() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -1096,7 +1096,7 @@ async fn test_withdraw_individual_item() {
|
|||||||
if create_item.item_id == 0x20000
|
if create_item.item_id == 0x20000
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let inventory_item_ids = items.iter()
|
let inventory_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Inventory{..} = item.location {
|
if let item::ItemLocation::Inventory{..} = item.location {
|
||||||
@ -1129,7 +1129,7 @@ async fn test_withdraw_stacked_item() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1163,7 +1163,7 @@ async fn test_withdraw_stacked_item() {
|
|||||||
if create_item.item_id == 0x10002
|
if create_item.item_id == 0x10002
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let inventory_item_ids = items.iter()
|
let inventory_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Inventory {..} = item.location {
|
if let item::ItemLocation::Inventory {..} = item.location {
|
||||||
@ -1196,7 +1196,7 @@ async fn test_withdraw_partial_stacked_item() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".into())
|
name: item::BankName("".into())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1230,7 +1230,7 @@ async fn test_withdraw_partial_stacked_item() {
|
|||||||
if create_item.item_id == 0x10002
|
if create_item.item_id == 0x10002
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -1276,7 +1276,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -1289,7 +1289,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".into()),
|
name: item::BankName("".into()),
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1323,7 +1323,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() {
|
|||||||
if create_item.item_id == 0x10000
|
if create_item.item_id == 0x10000
|
||||||
));
|
));
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let inventory_item_ids = items.iter()
|
let inventory_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Inventory {..} = item.location {
|
if let item::ItemLocation::Inventory {..} = item.location {
|
||||||
@ -1355,7 +1355,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".into()),
|
name: item::BankName("".into()),
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
@ -1371,7 +1371,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1399,7 +1399,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -1447,7 +1447,7 @@ async fn test_withdraw_individual_item_in_full_inventory() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -1467,7 +1467,7 @@ async fn test_withdraw_individual_item_in_full_inventory() {
|
|||||||
slot: i,
|
slot: i,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1495,7 +1495,7 @@ async fn test_withdraw_individual_item_in_full_inventory() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -1539,7 +1539,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
@ -1560,7 +1560,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() {
|
|||||||
slot: i,
|
slot: i,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1588,7 +1588,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() {
|
|||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -1632,7 +1632,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
|
|||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
name: item::BankName("".to_string())
|
name: item::BankName("".to_string())
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..29 {
|
for i in 0..29 {
|
||||||
@ -1653,7 +1653,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
|
|||||||
slot: i,
|
slot: i,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
@ -1669,7 +1669,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
|
|||||||
slot: 29,
|
slot: 29,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -1695,7 +1695,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let bank_item_ids = items.iter()
|
let bank_item_ids = items.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let item::ItemLocation::Bank {..} = item.location {
|
if let item::ItemLocation::Bank {..} = item.location {
|
||||||
@ -1727,7 +1727,7 @@ async fn test_withdraw_meseta() {
|
|||||||
|
|
||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.bank_meseta = 300;
|
char1.bank_meseta = 300;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -1752,7 +1752,7 @@ async fn test_withdraw_meseta() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 23);
|
assert!(char.meseta == 23);
|
||||||
assert!(char.bank_meseta == 277);
|
assert!(char.bank_meseta == 277);
|
||||||
@ -1765,7 +1765,7 @@ async fn test_withdraw_too_much_meseta() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.meseta = 999980;
|
char1.meseta = 999980;
|
||||||
char1.bank_meseta = 300;
|
char1.bank_meseta = 300;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -1790,7 +1790,7 @@ async fn test_withdraw_too_much_meseta() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 999980);
|
assert!(char.meseta == 999980);
|
||||||
assert!(char.bank_meseta == 300);
|
assert!(char.bank_meseta == 300);
|
||||||
@ -1803,7 +1803,7 @@ async fn test_withdraw_meseta_inventory_is_maxed() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
char1.bank_meseta = 300;
|
char1.bank_meseta = 300;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -1828,7 +1828,7 @@ async fn test_withdraw_meseta_inventory_is_maxed() {
|
|||||||
unknown: 0,
|
unknown: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
assert!(char.meseta == 999999);
|
assert!(char.meseta == 999999);
|
||||||
assert!(char.bank_meseta == 300);
|
assert!(char.bank_meseta == 300);
|
||||||
|
|||||||
@ -24,7 +24,7 @@ async fn test_save_options() {
|
|||||||
options: 12345,
|
options: 12345,
|
||||||
})).await.unwrap().for_each(drop);
|
})).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
|
|
||||||
assert!(char.option_flags == 12345);
|
assert!(char.option_flags == 12345);
|
||||||
|
|||||||
@ -54,7 +54,7 @@ async fn test_character_levels_up() {
|
|||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 49;
|
char1.exp = 49;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
|
|||||||
@ -31,7 +31,7 @@ async fn test_equip_unit_from_equip_menu() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -87,7 +87,7 @@ async fn test_equip_unit_from_equip_menu() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let (unit1, unit2) = (&items[1], &items[2]);
|
let (unit1, unit2) = (&items[1], &items[2]);
|
||||||
|
|
||||||
let unit1_equipped = match unit1.location {
|
let unit1_equipped = match unit1.location {
|
||||||
@ -194,7 +194,7 @@ async fn test_unequip_armor_with_units() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let (armor, unit1, unit2) = (&items[0], &items[1], &items[2]);
|
let (armor, unit1, unit2) = (&items[0], &items[1], &items[2]);
|
||||||
|
|
||||||
let armor_equipped = match armor.location {
|
let armor_equipped = match armor.location {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
@ -45,7 +45,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 6);
|
assert!(p1_items.len() == 6);
|
||||||
|
|
||||||
let p1_item_ids = p1_items.iter().map(|item| {
|
let p1_item_ids = p1_items.iter().map(|item| {
|
||||||
@ -116,7 +116,7 @@ async fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -149,7 +149,7 @@ async fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 1);
|
assert!(p1_items.len() == 1);
|
||||||
|
|
||||||
let first_item = p1_items.get(0).unwrap();
|
let first_item = p1_items.get(0).unwrap();
|
||||||
@ -184,11 +184,11 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2).await;
|
entity_gateway.save_character(&char2).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -227,12 +227,12 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 30);
|
assert!(p1_items.len() == 30);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
let characters2 = entity_gateway.get_characters_by_user(&user2).await;
|
let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap();
|
||||||
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta == 23);
|
assert!(c1.meseta == 23);
|
||||||
assert!(c2.meseta == 277);
|
assert!(c2.meseta == 277);
|
||||||
@ -263,7 +263,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -278,7 +278,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: 29,
|
slot: 29,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Tool(
|
item: item::ItemDetail::Tool(
|
||||||
@ -291,7 +291,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -324,7 +324,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 31);
|
assert!(p1_items.len() == 31);
|
||||||
|
|
||||||
let monomate1 = p1_items.get(29).unwrap();
|
let monomate1 = p1_items.get(29).unwrap();
|
||||||
@ -362,7 +362,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -382,7 +382,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -415,10 +415,10 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 30);
|
assert!(p1_items.len() == 30);
|
||||||
|
|
||||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||||
assert!(p2_items.len() == 0);
|
assert!(p2_items.len() == 0);
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
@ -429,7 +429,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||||
assert!(p2_items.len() == 1);
|
assert!(p2_items.len() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +440,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
|
|
||||||
char1.meseta = 300;
|
char1.meseta = 300;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -469,7 +469,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() {
|
|||||||
})))).await;
|
})))).await;
|
||||||
assert!(split_attempt.is_err());
|
assert!(split_attempt.is_err());
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta == 300);
|
assert!(c1.meseta == 300);
|
||||||
}
|
}
|
||||||
@ -494,7 +494,7 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
for _ in 0..6 {
|
for _ in 0..6 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -509,7 +509,7 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -544,10 +544,10 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
})))).await.unwrap().collect::<Vec<_>>();
|
})))).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(packets.len() == 0);
|
assert!(packets.len() == 0);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 6);
|
assert!(p1_items.len() == 6);
|
||||||
|
|
||||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||||
assert!(p2_items.len() == 0);
|
assert!(p2_items.len() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,9 +559,9 @@ async fn test_can_not_pick_up_meseta_when_full() {
|
|||||||
let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2).await;
|
entity_gateway.save_character(&char2).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -601,9 +601,9 @@ async fn test_can_not_pick_up_meseta_when_full() {
|
|||||||
})))).await.unwrap().collect::<Vec<_>>();
|
})))).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(packets.len() == 0);
|
assert!(packets.len() == 0);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
let characters2 = entity_gateway.get_characters_by_user(&user2).await;
|
let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap();
|
||||||
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta == 999999);
|
assert!(c1.meseta == 999999);
|
||||||
assert!(c2.meseta == 277);
|
assert!(c2.meseta == 277);
|
||||||
@ -617,9 +617,9 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
|||||||
let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
char1.meseta = 999998;
|
char1.meseta = 999998;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2).await;
|
entity_gateway.save_character(&char2).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -658,9 +658,9 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
let characters2 = entity_gateway.get_characters_by_user(&user2).await;
|
let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap();
|
||||||
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta == 999999);
|
assert!(c1.meseta == 999999);
|
||||||
assert!(c2.meseta == 277);
|
assert!(c2.meseta == 277);
|
||||||
@ -686,7 +686,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -726,7 +726,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items.len() == 3);
|
assert!(p1_items.len() == 3);
|
||||||
|
|
||||||
let p1_item_ids = p1_items.iter().map(|item| {
|
let p1_item_ids = p1_items.iter().map(|item| {
|
||||||
@ -742,7 +742,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
|||||||
});
|
});
|
||||||
assert!(all_items_are_monomates);
|
assert!(all_items_are_monomates);
|
||||||
|
|
||||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||||
assert!(p2_items.len() == 2);
|
assert!(p2_items.len() == 2);
|
||||||
|
|
||||||
let p2_item_ids = p2_items.iter().map(|item| {
|
let p2_item_ids = p2_items.iter().map(|item| {
|
||||||
|
|||||||
@ -32,7 +32,7 @@ async fn test_use_monomate() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ async fn test_use_monomate() {
|
|||||||
item_id: 0x10000,
|
item_id: 0x10000,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(items.iter().filter(|item| {
|
assert!(items.iter().filter(|item| {
|
||||||
if let item::ItemDetail::Tool(t) = item.item {
|
if let item::ItemDetail::Tool(t) = item.item {
|
||||||
t.tool == item::tool::ToolType::Monomate
|
t.tool == item::tool::ToolType::Monomate
|
||||||
@ -88,7 +88,7 @@ async fn test_use_monomate_twice() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ async fn test_use_monomate_twice() {
|
|||||||
item_id: 0x10000,
|
item_id: 0x10000,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(items.iter().filter(|item| {
|
assert!(items.iter().filter(|item| {
|
||||||
if let item::ItemDetail::Tool(t) = item.item {
|
if let item::ItemDetail::Tool(t) = item.item {
|
||||||
t.tool == item::tool::ToolType::Monomate
|
t.tool == item::tool::ToolType::Monomate
|
||||||
@ -149,7 +149,7 @@ async fn test_use_last_monomate() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ async fn test_use_last_monomate() {
|
|||||||
item_id: 0x10000,
|
item_id: 0x10000,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(items.iter().filter(|item| {
|
assert!(items.iter().filter(|item| {
|
||||||
if let item::ItemDetail::Tool(t) = item.item {
|
if let item::ItemDetail::Tool(t) = item.item {
|
||||||
t.tool == item::tool::ToolType::Monomate
|
t.tool == item::tool::ToolType::Monomate
|
||||||
@ -203,7 +203,7 @@ async fn test_use_nonstackable_tool() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -218,7 +218,7 @@ async fn test_use_nonstackable_tool() {
|
|||||||
item_id: 0x10000,
|
item_id: 0x10000,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(items.len() == 0);
|
assert!(items.len() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ async fn test_use_materials() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ async fn test_use_materials() {
|
|||||||
item_id: 0x10001,
|
item_id: 0x10001,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(items.iter().filter(|item| {
|
assert!(items.iter().filter(|item| {
|
||||||
if let item::ItemDetail::Tool(t) = item.item {
|
if let item::ItemDetail::Tool(t) = item.item {
|
||||||
t.tool == item::tool::ToolType::PowerMaterial
|
t.tool == item::tool::ToolType::PowerMaterial
|
||||||
@ -287,7 +287,7 @@ async fn test_use_materials() {
|
|||||||
}
|
}
|
||||||
}).count() == 3);
|
}).count() == 3);
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
let char = characters[0].as_ref().unwrap();
|
||||||
|
|
||||||
assert!(char.materials.power == 1);
|
assert!(char.materials.power == 1);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ async fn test_mag_feed() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
for _ in 0..7 {
|
for _ in 0..7 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -41,7 +41,7 @@ async fn test_mag_feed() {
|
|||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
@ -60,7 +60,7 @@ async fn test_mag_feed() {
|
|||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let mag = p1_items.get(0).unwrap();
|
let mag = p1_items.get(0).unwrap();
|
||||||
match &mag.item {
|
match &mag.item {
|
||||||
item::ItemDetail::Mag(mag) => {
|
item::ItemDetail::Mag(mag) => {
|
||||||
@ -82,10 +82,10 @@ async fn test_mag_change_owner() {
|
|||||||
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
char1.char_class = CharacterClass::RAmarl;
|
char1.char_class = CharacterClass::RAmarl;
|
||||||
char1.section_id = SectionID::Redria;
|
char1.section_id = SectionID::Redria;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
char2.char_class = CharacterClass::FOmarl;
|
char2.char_class = CharacterClass::FOmarl;
|
||||||
char2.section_id = SectionID::Whitill;
|
char2.section_id = SectionID::Whitill;
|
||||||
entity_gateway.save_character(&char2).await;
|
entity_gateway.save_character(&char2).await.unwrap();
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -97,7 +97,7 @@ async fn test_mag_change_owner() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -128,7 +128,7 @@ async fn test_mag_change_owner() {
|
|||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||||
let mag = p2_items.get(0).unwrap();
|
let mag = p2_items.get(0).unwrap();
|
||||||
match &mag.item {
|
match &mag.item {
|
||||||
item::ItemDetail::Mag(mag) => {
|
item::ItemDetail::Mag(mag) => {
|
||||||
@ -170,7 +170,7 @@ async fn test_mag_cell() {
|
|||||||
mag: mag.id,
|
mag: mag.id,
|
||||||
}
|
}
|
||||||
}).await.unwrap();
|
}).await.unwrap();
|
||||||
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await;
|
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap();
|
||||||
}
|
}
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -184,7 +184,7 @@ async fn test_mag_cell() {
|
|||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -199,7 +199,7 @@ async fn test_mag_cell() {
|
|||||||
item_id: 0x10001,
|
item_id: 0x10001,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
let mag = p1_items.get(0).unwrap();
|
let mag = p1_items.get(0).unwrap();
|
||||||
match &mag.item {
|
match &mag.item {
|
||||||
item::ItemDetail::Mag(mag) => {
|
item::ItemDetail::Mag(mag) => {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ async fn test_player_opens_weapon_shop() {
|
|||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -47,7 +47,7 @@ async fn test_player_opens_tool_shop() {
|
|||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -77,7 +77,7 @@ async fn test_player_opens_armor_shop() {
|
|||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -108,7 +108,7 @@ async fn test_player_buys_from_weapon_shop() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -132,10 +132,10 @@ async fn test_player_buys_from_weapon_shop() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta < 999999);
|
assert!(c1.meseta < 999999);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 1);
|
assert_eq!(p1_items.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ async fn test_player_buys_from_tool_shop() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -170,10 +170,10 @@ async fn test_player_buys_from_tool_shop() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta < 999999);
|
assert!(c1.meseta < 999999);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 1);
|
assert_eq!(p1_items.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ async fn test_player_buys_multiple_from_tool_shop() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -208,10 +208,10 @@ async fn test_player_buys_multiple_from_tool_shop() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta < 999999);
|
assert!(c1.meseta < 999999);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 5);
|
assert_eq!(p1_items.len(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ async fn test_player_buys_from_armor_shop() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -246,10 +246,10 @@ async fn test_player_buys_from_armor_shop() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta < 999999);
|
assert!(c1.meseta < 999999);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 1);
|
assert_eq!(p1_items.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ async fn test_other_clients_see_purchase() {
|
|||||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -308,7 +308,7 @@ async fn test_other_clients_see_stacked_purchase() {
|
|||||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Tool(
|
item: item::ItemDetail::Tool(
|
||||||
@ -321,7 +321,7 @@ async fn test_other_clients_see_stacked_purchase() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}).await;
|
}).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -385,10 +385,10 @@ async fn test_buying_item_without_enough_mseseta() {
|
|||||||
})))).await;
|
})))).await;
|
||||||
|
|
||||||
assert!(packets.is_err());
|
assert!(packets.is_err());
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert_eq!(c1.meseta, 0);
|
assert_eq!(c1.meseta, 0);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 0);
|
assert_eq!(p1_items.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +399,7 @@ async fn test_player_double_buys_from_tool_shop() {
|
|||||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -441,10 +441,10 @@ async fn test_player_double_buys_from_tool_shop() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||||
assert!(c1.meseta < 999999);
|
assert!(c1.meseta < 999999);
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.len(), 9);
|
assert_eq!(p1_items.len(), 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ async fn test_techs_disappear_from_shop_when_bought() {
|
|||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -502,7 +502,7 @@ async fn test_techs_disappear_from_shop_when_bought() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items[0].item != p1_items[1].item);
|
assert!(p1_items[0].item != p1_items[1].item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,7 +514,7 @@ async fn test_units_disappear_from_shop_when_bought() {
|
|||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
char1.exp = 80000000;
|
char1.exp = 80000000;
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1).await;
|
entity_gateway.save_character(&char1).await.unwrap();
|
||||||
|
|
||||||
let mut ship = ShipServerState::builder()
|
let mut ship = ShipServerState::builder()
|
||||||
.gateway(entity_gateway.clone())
|
.gateway(entity_gateway.clone())
|
||||||
@ -560,6 +560,6 @@ async fn test_units_disappear_from_shop_when_bought() {
|
|||||||
unknown1: 0,
|
unknown1: 0,
|
||||||
})))).await.unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||||
assert!(p1_items[0].item != p1_items[1].item);
|
assert!(p1_items[0].item != p1_items[1].item);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user