Merge pull request 'item_refactor' (#250) from item_refactor into master
This commit is contained in:
commit
9de04ad87b
Cargo.toml
src
tests
@ -6,15 +6,12 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||
async-std = { version = "1.5.0", features = ["unstable", "attributes"] }
|
||||
async-std = { version = "1.7.0", features = ["unstable", "attributes"] }
|
||||
futures = "0.3.5"
|
||||
rand = "0.7.3"
|
||||
rand_chacha = "0.2.2"
|
||||
mio = "0.6"
|
||||
mio-extras = "2.0.5"
|
||||
crc = "^1.0.0"
|
||||
bcrypt = "0.4"
|
||||
threadpool = "1.0"
|
||||
chrono = "0.4.11"
|
||||
serde = "*"
|
||||
serde_json = "*"
|
||||
@ -27,7 +24,7 @@ enum-utils = "0.1.2"
|
||||
derive_more = { version = "0.99.3", features = ["display"]}
|
||||
thiserror = "1.0.15"
|
||||
ages-prs = "0.1"
|
||||
async-trait = "0.1.31"
|
||||
async-trait = "0.1.41"
|
||||
lazy_static = "1.4.0"
|
||||
barrel = { version = "0.6.5", features = ["pg"] }
|
||||
refinery = { version = "0.3.0", features = ["postgres"] }
|
||||
|
130
src/bin/main.rs
130
src/bin/main.rs
@ -109,7 +109,7 @@ fn main() {
|
||||
}).await.unwrap();
|
||||
}
|
||||
|
||||
entity_gateway.create_item(
|
||||
let item0 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -125,11 +125,9 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
let item1 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -145,11 +143,9 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
let item2_w = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -165,11 +161,9 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
let item3 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -185,11 +179,9 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 3,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
let item4 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -205,22 +197,18 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 4,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
let mag = entity_gateway.create_item(
|
||||
let item5_m = 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 {
|
||||
for _ in 0..10usize {
|
||||
let fed_tool = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
@ -229,15 +217,14 @@ fn main() {
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::FedToMag {
|
||||
mag: mag.id,
|
||||
mag: item5_m.id,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap();
|
||||
entity_gateway.feed_mag(&item5_m.id, &fed_tool.id).await.unwrap();
|
||||
}
|
||||
//entity_gateway.bank(&mag.id).await;
|
||||
entity_gateway.change_mag_owner(&mag.id, &character).await.unwrap();
|
||||
entity_gateway.change_mag_owner(&item5_m.id, &character).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
let item6 = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
@ -246,8 +233,6 @@ fn main() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 6,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
let cell = entity_gateway.create_item(
|
||||
@ -259,7 +244,7 @@ fn main() {
|
||||
),
|
||||
location: item::ItemLocation::Consumed,
|
||||
}).await.unwrap();
|
||||
entity_gateway.use_mag_cell(&mag.id, &cell.id).await.unwrap();
|
||||
entity_gateway.use_mag_cell(&item5_m.id, &cell.id).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
@ -279,8 +264,8 @@ fn main() {
|
||||
character_id: character.id,
|
||||
name: item::BankName("".to_string()),
|
||||
}
|
||||
}).await;
|
||||
entity_gateway.create_item(
|
||||
}).await.unwrap();
|
||||
let item7_a = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Armor(
|
||||
item::armor::Armor {
|
||||
@ -293,12 +278,10 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 5,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item8_s = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Shield(
|
||||
item::shield::Shield {
|
||||
@ -309,133 +292,130 @@ fn main() {
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 6,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item9_u0 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Unit(
|
||||
item::unit::Unit {
|
||||
unit: item::unit::UnitType::PriestMind,
|
||||
modifier: Some(item::unit::UnitModifier::Minus),
|
||||
armor_slot: 0,
|
||||
}
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 7,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item10_u1 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Unit(
|
||||
item::unit::Unit {
|
||||
unit: item::unit::UnitType::PriestMind,
|
||||
modifier: Some(item::unit::UnitModifier::Minus),
|
||||
armor_slot: 1,
|
||||
}
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 8,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item11_u2 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Unit(
|
||||
item::unit::Unit {
|
||||
unit: item::unit::UnitType::PriestMind,
|
||||
modifier: Some(item::unit::UnitModifier::Minus),
|
||||
armor_slot: 2,
|
||||
}
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 9,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item12_u3 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Unit(
|
||||
item::unit::Unit {
|
||||
unit: item::unit::UnitType::PriestMind,
|
||||
modifier: Some(item::unit::UnitModifier::Minus),
|
||||
armor_slot: 3,
|
||||
}
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 10,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
entity_gateway.create_item(
|
||||
).await.unwrap();
|
||||
let item13 = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(5)
|
||||
),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 11,
|
||||
equipped: true,
|
||||
}
|
||||
}
|
||||
).await;
|
||||
).await.unwrap();
|
||||
|
||||
let equipped = item::EquippedEntity {
|
||||
weapon: Some(item2_w.id),
|
||||
armor: Some(item7_a.id),
|
||||
shield: Some(item8_s.id),
|
||||
unit: [Some(item9_u0.id), Some(item10_u1.id), Some(item11_u2.id), Some(item12_u3.id)],
|
||||
mag: Some(item5_m.id),
|
||||
};
|
||||
entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap();
|
||||
|
||||
let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13]);
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap();
|
||||
entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap();
|
||||
}
|
||||
|
||||
info!("[patch] starting server");
|
||||
let patch_config = load_config();
|
||||
let patch_motd = load_motd();
|
||||
let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str());
|
||||
let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd);
|
||||
let patch_loop = patch_mainloop(patch_state, patch_config.port);
|
||||
let patch_state = Box::new(PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd));
|
||||
let patch_loop = patch_mainloop(*patch_state, patch_config.port);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
info!("[auth] starting server");
|
||||
let login_state = 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_state = Box::new(LoginServerState::new(thread_entity_gateway, "127.0.0.1".parse().unwrap()));
|
||||
let login_loop = login_mainloop(*login_state, elseware::login::login::LOGIN_PORT);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
info!("[character] starting server");
|
||||
let char_state = CharacterServerState::new(thread_entity_gateway, AuthToken("".into()));
|
||||
let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT);
|
||||
let char_state = Box::new(CharacterServerState::new(thread_entity_gateway, AuthToken("".into())));
|
||||
let character_loop = character_mainloop(*char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
info!("[ship] starting server");
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
let ship_state = Box::new(ShipServerStateBuilder::new()
|
||||
.name("US/Sona-Nyl".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT)
|
||||
.gateway(thread_entity_gateway)
|
||||
.build();
|
||||
let ship_loop = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
.build());
|
||||
let ship_loop = ship_mainloop(*ship_state, elseware::ship::ship::SHIP_PORT, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
let ship_state = Box::new(ShipServerStateBuilder::new()
|
||||
.name("EU/Dylath-Leen".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+2000)
|
||||
.gateway(thread_entity_gateway)
|
||||
.build();
|
||||
let ship_loop2 = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT+2000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
.build());
|
||||
let ship_loop2 = ship_mainloop(*ship_state, elseware::ship::ship::SHIP_PORT+2000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
|
||||
let thread_entity_gateway = entity_gateway.clone();
|
||||
let ship_state = ShipServerStateBuilder::new()
|
||||
let ship_state = Box::new(ShipServerStateBuilder::new()
|
||||
.name("JP/Thalarion".into())
|
||||
.ip(Ipv4Addr::new(127,0,0,1))
|
||||
.port(elseware::ship::ship::SHIP_PORT+3000)
|
||||
.gateway(thread_entity_gateway)
|
||||
.build();
|
||||
let ship_loop3 = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT+3000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
.build());
|
||||
let ship_loop3 = ship_mainloop(*ship_state, elseware::ship::ship::SHIP_PORT+3000, std::net::Ipv4Addr::new(127, 0, 0, 1), elseware::login::login::COMMUNICATION_PORT);
|
||||
|
||||
futures::future::join_all(vec![patch_loop, login_loop, character_loop, ship_loop, ship_loop2, ship_loop3]).await;
|
||||
});
|
||||
|
@ -139,7 +139,7 @@ enum ServerStateAction<S> {
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
async fn client_recv_loop<S, R>(client_id: ClientId,
|
||||
fn client_recv_loop<S, R>(client_id: ClientId,
|
||||
socket: Arc<async_std::net::TcpStream>,
|
||||
cipher: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
server_sender: async_std::sync::Sender<ClientAction<ServerStateAction<S>, R>>,
|
||||
@ -177,7 +177,7 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
async fn client_send_loop<S>(client_id: ClientId,
|
||||
fn client_send_loop<S>(client_id: ClientId,
|
||||
socket: Arc<async_std::net::TcpStream>,
|
||||
cipher_in: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
cipher_out: Arc<Mutex<Box<dyn PSOCipher + Send>>>,
|
||||
@ -207,7 +207,7 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
||||
fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<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,
|
||||
@ -223,7 +223,6 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
||||
|
||||
match action {
|
||||
ClientAction::NewClient(client_id, sender) => {
|
||||
clients.insert(client_id, sender.clone());
|
||||
let actions = state.on_connect(client_id).await;
|
||||
match actions {
|
||||
Ok(actions) => {
|
||||
@ -237,11 +236,12 @@ async fn state_client_loop<STATE, S, R, E>(state: Arc<Mutex<STATE>>,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("[client {:?} state on_connect error] {:?}", client_id, err);
|
||||
}
|
||||
}
|
||||
clients.insert(client_id, sender);
|
||||
},
|
||||
ClientAction::Packet(client_id, pkt) => {
|
||||
let pkts = state.handle(client_id, &pkt).await;
|
||||
@ -295,7 +295,7 @@ where
|
||||
let mut id = 0;
|
||||
|
||||
let (server_state_sender, server_state_receiver) = async_std::sync::channel(1024);
|
||||
state_client_loop(state, server_state_receiver).await;
|
||||
state_client_loop(state, server_state_receiver);
|
||||
|
||||
loop {
|
||||
let (sock, addr) = listener.accept().await.unwrap();
|
||||
@ -309,8 +309,8 @@ where
|
||||
let cipher_in: Arc<Mutex<Box<dyn PSOCipher + Send>>> = Arc::new(Mutex::new(Box::new(NullCipher {})));
|
||||
let cipher_out: Arc<Mutex<Box<dyn PSOCipher + Send>>> = Arc::new(Mutex::new(Box::new(NullCipher {})));
|
||||
|
||||
client_recv_loop(client_id, socket.clone(), cipher_in.clone(), server_state_sender.clone(), client_sender).await;
|
||||
client_send_loop(client_id, socket.clone(), cipher_in.clone(), cipher_out.clone(), client_receiver).await;
|
||||
client_recv_loop(client_id, socket.clone(), cipher_in.clone(), server_state_sender.clone(), client_sender);
|
||||
client_send_loop(client_id, socket.clone(), cipher_in.clone(), cipher_out.clone(), client_receiver);
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub fn login_mainloop<EG: EntityGateway + 'static>(login_state: LoginServerState
|
||||
pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: CharacterServerState<EG>, character_port: u16, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
let character_state = Arc::new(Mutex::new(character_state));
|
||||
let client_mainloop = client_accept_mainloop(character_state.clone(), character_port);
|
||||
let ship_communication_mainloop = login_listen_mainloop(character_state.clone(), comm_port);
|
||||
let ship_communication_mainloop = login_listen_mainloop(character_state, comm_port);
|
||||
Box::pin(join_all(vec![client_mainloop, ship_communication_mainloop]).map(|_| ()))
|
||||
}
|
||||
|
||||
@ -40,6 +40,6 @@ pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: Characte
|
||||
pub fn ship_mainloop<EG: EntityGateway + 'static>(ship_state: ShipServerState<EG>, ship_port: u16, comm_ip: std::net::Ipv4Addr, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
let ship_state = Arc::new(Mutex::new(ship_state));
|
||||
let client_mainloop = client_accept_mainloop(ship_state.clone(), ship_port);
|
||||
let login_communication_mainloop = ship_connect_mainloop(ship_state.clone(), comm_ip, comm_port);
|
||||
let login_communication_mainloop = ship_connect_mainloop(ship_state, comm_ip, comm_port);
|
||||
Box::pin(join_all(vec![client_mainloop, login_communication_mainloop]).map(|_| ()))
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ pub trait EntityGateway: Send + Sync + Clone {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
async fn change_item(&mut self, _id: &ItemEntityId, _item: &ItemDetail) -> Result<(), GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
@ -85,7 +86,33 @@ pub trait EntityGateway: Send + Sync + Clone {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/*
|
||||
async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
*/
|
||||
|
||||
async fn get_character_inventory(&mut self, _char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn get_character_bank(&mut self, _char_id: &CharacterEntityId, _bank_name: BankName) -> Result<BankEntity, GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn set_character_inventory(&mut self, _char_id: &CharacterEntityId, _inventory: &InventoryEntity) -> Result<(), GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn set_character_bank(&mut self, _char_id: &CharacterEntityId, _inventory: &BankEntity, _bank_name: BankName) -> Result<(), GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn get_character_equips(&mut self, _char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn set_character_equips(&mut self, _char_id: &CharacterEntityId, _equips: &EquippedEntity) -> Result<(), GatewayError> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ pub struct InMemoryGateway {
|
||||
user_settings: Arc<Mutex<BTreeMap<UserSettingsId, UserSettingsEntity>>>,
|
||||
characters: Arc<Mutex<BTreeMap<CharacterEntityId, CharacterEntity>>>,
|
||||
items: Arc<Mutex<BTreeMap<ItemEntityId, ItemEntity>>>,
|
||||
inventories: Arc<Mutex<BTreeMap<CharacterEntityId, InventoryEntity>>>,
|
||||
banks: Arc<Mutex<BTreeMap<CharacterEntityId, BankEntity>>>,
|
||||
equips: Arc<Mutex<BTreeMap<CharacterEntityId, EquippedEntity>>>,
|
||||
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
|
||||
}
|
||||
|
||||
@ -24,11 +27,66 @@ impl InMemoryGateway {
|
||||
user_settings: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
characters: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
items: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
inventories: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
banks: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
equips: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InMemoryGateway {
|
||||
fn apply_modifiers(&self, inventory: InventoryEntity ) -> InventoryEntity {
|
||||
let items = self.items.lock().unwrap();
|
||||
let inventory_items = inventory.items.into_iter()
|
||||
.map(|item| {
|
||||
item.map_individual(|mut item| {
|
||||
item.item = match item.item {
|
||||
ItemDetail::Mag(mag) => {
|
||||
let mut mag = mag::Mag::baby_mag(mag.color as u16);
|
||||
println!("mag! {:?}", mag);
|
||||
if let Some(mag_modifiers) = self.mag_modifiers.lock().unwrap().get(&item.id) {
|
||||
for mag_modifier in mag_modifiers.iter() {
|
||||
match mag_modifier {
|
||||
mag::MagModifier::FeedMag {food} => {
|
||||
items.get(&food).map(|mag_feed| {
|
||||
match mag_feed.item {
|
||||
ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
mag::MagModifier::OwnerChange(class, section_id) => {
|
||||
mag.change_owner(*class, *section_id)
|
||||
},
|
||||
mag::MagModifier::MagCell(mag_cell_id) => {
|
||||
items.get(&mag_cell_id).map(|mag_cell| {
|
||||
match mag_cell.item {
|
||||
ItemDetail::Tool(mag_cell) => mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
println!("{:?} -> {:?}", mag_modifier, mag);
|
||||
}
|
||||
}
|
||||
ItemDetail::Mag(mag)
|
||||
}
|
||||
_ => {
|
||||
item.item
|
||||
}
|
||||
};
|
||||
|
||||
item
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
InventoryEntity::new(inventory_items)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl EntityGateway for InMemoryGateway {
|
||||
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||
@ -208,55 +266,51 @@ impl EntityGateway for InMemoryGateway {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||
let items = self.items.lock().unwrap();
|
||||
Ok(items
|
||||
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
|
||||
println!("getting inv");
|
||||
let inventories = self.inventories.lock().unwrap();
|
||||
Ok(inventories
|
||||
.iter()
|
||||
.find(|(id, _)| **id == *char_id)
|
||||
.map(|(_, inv)| inv.clone())
|
||||
.map(|inv| self.apply_modifiers(inv))
|
||||
.unwrap_or(InventoryEntity::default()))
|
||||
}
|
||||
|
||||
async fn get_character_bank(&mut self, char_id: &CharacterEntityId, _bank_name: BankName) -> Result<BankEntity, GatewayError> {
|
||||
let banks = self.banks.lock().unwrap();
|
||||
Ok(banks
|
||||
.iter()
|
||||
.find(|(id, _)| **id == *char_id)
|
||||
.map(|(_, b)| b.clone())
|
||||
.unwrap_or(BankEntity::default()))
|
||||
}
|
||||
|
||||
async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> {
|
||||
let mut inventories = self.inventories.lock().unwrap();
|
||||
inventories.insert(*char_id, inventory.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TOOD: impl bank name
|
||||
async fn set_character_bank(&mut self, char_id: &CharacterEntityId, bank: &BankEntity, _bank_name: BankName) -> Result<(), GatewayError> {
|
||||
let mut banks = self.banks.lock().unwrap();
|
||||
banks.insert(*char_id, bank.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_character_equips(&mut self, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> {
|
||||
let equips = self.equips.lock().unwrap();
|
||||
Ok(equips
|
||||
.iter()
|
||||
.filter(|(_, k)| {
|
||||
match k.location {
|
||||
ItemLocation::Inventory{character_id, ..} => character_id == *char_id,
|
||||
ItemLocation::Bank{character_id, ..} => character_id == *char_id,
|
||||
_ => false
|
||||
}
|
||||
})
|
||||
.map(|(_, k)| {
|
||||
k.clone()
|
||||
})
|
||||
.map(|mut item| {
|
||||
item.item = match item.item {
|
||||
ItemDetail::Mag(mut mag) => {
|
||||
self.mag_modifiers.lock().unwrap().get(&item.id).map(|mag_modifiers| {
|
||||
for mag_modifier in mag_modifiers.iter() {
|
||||
match mag_modifier {
|
||||
mag::MagModifier::FeedMag {food} => {
|
||||
items.get(&food).map(|mag_feed| {
|
||||
match mag_feed.item {
|
||||
ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
mag::MagModifier::OwnerChange(class, section_id) => {
|
||||
mag.change_owner(*class, *section_id)
|
||||
},
|
||||
mag::MagModifier::MagCell(mag_cell_id) => {
|
||||
items.get(&mag_cell_id).map(|mag_cell| {
|
||||
match mag_cell.item {
|
||||
ItemDetail::Tool(mag_cell) => mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
ItemDetail::Mag(mag)
|
||||
}
|
||||
_ => item.item
|
||||
};
|
||||
item
|
||||
})
|
||||
.collect())
|
||||
.find(|(id, _)| **id == *char_id)
|
||||
.map(|(_, inv)| inv.clone())
|
||||
.unwrap_or(EquippedEntity::default()))
|
||||
}
|
||||
|
||||
async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equipped: &EquippedEntity) -> Result<(), GatewayError> {
|
||||
let mut equips = self.equips.lock().unwrap();
|
||||
equips.insert(*char_id, equipped.clone());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -122,3 +122,27 @@ create table mag_modifier (
|
||||
modifier jsonb not null,
|
||||
created_at timestamptz default current_timestamp not null
|
||||
);
|
||||
|
||||
create table equipped (
|
||||
pchar integer references player_character (id) unique not null,
|
||||
weapon integer references item (id),
|
||||
armor integer references item (id),
|
||||
shield integer references item (id),
|
||||
unit0 integer references item (id),
|
||||
unit1 integer references item (id),
|
||||
unit2 integer references item (id),
|
||||
unit3 integer references item (id),
|
||||
mag integer references item (id)
|
||||
);
|
||||
|
||||
create table inventory (
|
||||
pchar integer references player_character (id) unique not null,
|
||||
items jsonb not null
|
||||
);
|
||||
|
||||
create table bank (
|
||||
pchar integer references player_character (id) not null,
|
||||
items jsonb not null,
|
||||
name varchar(128) not null,
|
||||
unique (pchar, name)
|
||||
);
|
||||
|
@ -383,7 +383,6 @@ impl Into<shield::Shield> for PgShield {
|
||||
pub struct PgUnit {
|
||||
unit: unit::UnitType,
|
||||
modifier: Option<unit::UnitModifier>,
|
||||
armor_slot: u8,
|
||||
}
|
||||
|
||||
impl From<unit::Unit> for PgUnit {
|
||||
@ -391,7 +390,6 @@ impl From<unit::Unit> for PgUnit {
|
||||
PgUnit {
|
||||
unit: other.unit,
|
||||
modifier: other.modifier,
|
||||
armor_slot: other.armor_slot,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,7 +399,6 @@ impl Into<unit::Unit> for PgUnit {
|
||||
unit::Unit {
|
||||
unit: self.unit,
|
||||
modifier: self.modifier,
|
||||
armor_slot: self.armor_slot,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -573,9 +570,6 @@ pub struct PgItem {
|
||||
pub enum PgItemLocationDetail {
|
||||
Inventory {
|
||||
character_id: u32,
|
||||
#[serde(skip_serializing)]
|
||||
slot: usize,
|
||||
equipped: bool,
|
||||
},
|
||||
Bank {
|
||||
character_id: u32,
|
||||
@ -604,7 +598,7 @@ pub enum PgItemLocationDetail {
|
||||
impl From<ItemLocation> for PgItemLocationDetail {
|
||||
fn from(other: ItemLocation) -> PgItemLocationDetail {
|
||||
match other {
|
||||
ItemLocation::Inventory{character_id, slot, equipped} => PgItemLocationDetail::Inventory{character_id: character_id.0, slot, equipped},
|
||||
ItemLocation::Inventory{character_id} => PgItemLocationDetail::Inventory{character_id: character_id.0},
|
||||
ItemLocation::Bank{character_id, name} => PgItemLocationDetail::Bank{character_id: character_id.0, name: name.0},
|
||||
ItemLocation::LocalFloor{character_id, map_area, x,y,z} => PgItemLocationDetail::LocalFloor{character_id: character_id.0, map_area, x,y,z},
|
||||
ItemLocation::SharedFloor{map_area, x,y,z} => PgItemLocationDetail::SharedFloor{map_area, x,y,z},
|
||||
@ -618,7 +612,7 @@ impl From<ItemLocation> for PgItemLocationDetail {
|
||||
impl Into<ItemLocation> for PgItemLocationDetail {
|
||||
fn into(self) -> ItemLocation {
|
||||
match self {
|
||||
PgItemLocationDetail::Inventory{character_id, slot, equipped} => ItemLocation::Inventory{character_id: CharacterEntityId(character_id), slot, equipped},
|
||||
PgItemLocationDetail::Inventory{character_id} => ItemLocation::Inventory{character_id: CharacterEntityId(character_id)},
|
||||
PgItemLocationDetail::Bank{character_id, name} => ItemLocation::Bank{character_id: CharacterEntityId(character_id), name: BankName(name)},
|
||||
PgItemLocationDetail::LocalFloor{character_id, map_area, x,y,z} => ItemLocation::LocalFloor{character_id: CharacterEntityId(character_id), map_area, x,y,z},
|
||||
PgItemLocationDetail::SharedFloor{map_area, x,y,z} => ItemLocation::SharedFloor{map_area, x,y,z},
|
||||
@ -676,6 +670,12 @@ pub struct PgMagModifier {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgItemEntity {
|
||||
pub id: i32,
|
||||
pub item: sqlx::types::Json<PgItemDetail>,
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgItemWithLocation {
|
||||
pub id: i32,
|
||||
@ -683,6 +683,16 @@ pub struct PgItemWithLocation {
|
||||
pub location: sqlx::types::Json<PgItemLocationDetail>,
|
||||
}
|
||||
|
||||
impl Into<ItemEntity> for PgItemWithLocation {
|
||||
fn into(self) -> ItemEntity {
|
||||
ItemEntity {
|
||||
id: ItemEntityId(self.id as u32),
|
||||
item: self.item.0.into(),
|
||||
location: self.location.0.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgMagModifierWithParameters {
|
||||
@ -691,3 +701,70 @@ pub struct PgMagModifierWithParameters {
|
||||
pub feed: Option<sqlx::types::Json<PgTool>>,
|
||||
pub cell: Option<sqlx::types::Json<PgTool>>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum PgInventoryItemEntity {
|
||||
Individual(i32),
|
||||
Stacked(Vec<i32>),
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgInventoryEntity {
|
||||
pub pchar: i32,
|
||||
pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgBankEntity {
|
||||
pub pchar: i32,
|
||||
pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct PgEquipped {
|
||||
pchar: i32,
|
||||
weapon: Option<i32>,
|
||||
armor: Option<i32>,
|
||||
shield: Option<i32>,
|
||||
unit0: Option<i32>,
|
||||
unit1: Option<i32>,
|
||||
unit2: Option<i32>,
|
||||
unit3: Option<i32>,
|
||||
mag: Option<i32>,
|
||||
}
|
||||
|
||||
impl Into<EquippedEntity> for PgEquipped {
|
||||
fn into(self) -> EquippedEntity {
|
||||
EquippedEntity {
|
||||
weapon: self.weapon.map(|i| ItemEntityId(i as u32)),
|
||||
armor: self.armor.map(|i| ItemEntityId(i as u32)),
|
||||
shield: self.shield.map(|i| ItemEntityId(i as u32)),
|
||||
unit: [self.unit0.map(|i| ItemEntityId(i as u32)),
|
||||
self.unit1.map(|i| ItemEntityId(i as u32)),
|
||||
self.unit2.map(|i| ItemEntityId(i as u32)),
|
||||
self.unit3.map(|i| ItemEntityId(i as u32)),
|
||||
],
|
||||
mag: self.mag.map(|i| ItemEntityId(i as u32)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(CharacterEntityId, EquippedEntity)> for PgEquipped {
|
||||
fn from(char_equips: (CharacterEntityId, EquippedEntity)) -> PgEquipped {
|
||||
PgEquipped {
|
||||
pchar: char_equips.0.0 as i32,
|
||||
weapon: char_equips.1.weapon.map(|i| i.0 as i32),
|
||||
armor: char_equips.1.armor.map(|i| i.0 as i32),
|
||||
shield: char_equips.1.shield.map(|i| i.0 as i32),
|
||||
unit0: char_equips.1.unit[0].map(|i| i.0 as i32),
|
||||
unit1: char_equips.1.unit[1].map(|i| i.0 as i32),
|
||||
unit2: char_equips.1.unit[2].map(|i| i.0 as i32),
|
||||
unit3: char_equips.1.unit[3].map(|i| i.0 as i32),
|
||||
mag: char_equips.1.mag.map(|i| i.0 as i32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,23 @@ impl EntityGateway for PostgresGateway {
|
||||
}
|
||||
|
||||
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 *;")
|
||||
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
||||
.fetch_one(&mut tx).await?;
|
||||
let location = sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
||||
.bind(new_item.id)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
||||
.fetch_one(&mut tx).await?;
|
||||
|
||||
tx.commit().await?;
|
||||
Ok(ItemEntity {
|
||||
id: ItemEntityId(new_item.id as u32),
|
||||
item: new_item.item.0.into(),
|
||||
location: location.location.0.into(),
|
||||
})
|
||||
|
||||
/*
|
||||
let mut tx = self.pool.begin().await?;
|
||||
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
||||
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
||||
@ -310,6 +327,7 @@ impl EntityGateway for PostgresGateway {
|
||||
item: new_item.item.0.into(),
|
||||
location: location.location.0.into(),
|
||||
})
|
||||
*/
|
||||
}
|
||||
|
||||
async fn change_item(&mut self, id: &ItemEntityId, item: &ItemDetail) -> Result<(), GatewayError> {
|
||||
@ -321,6 +339,13 @@ impl EntityGateway for PostgresGateway {
|
||||
}
|
||||
|
||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||
.bind(item_id.0)
|
||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||
.execute(&self.pool).await?;
|
||||
Ok(())
|
||||
|
||||
/*
|
||||
let mut tx = self.pool.begin().await?;
|
||||
if let ItemLocation::Inventory{slot, ..} = &item_location {
|
||||
sqlx::query("delete from inventory_slot where item = $1")
|
||||
@ -346,6 +371,7 @@ impl EntityGateway for PostgresGateway {
|
||||
}
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
*/
|
||||
}
|
||||
|
||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||
@ -371,7 +397,7 @@ impl EntityGateway for PostgresGateway {
|
||||
.execute(&self.pool).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*
|
||||
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||
let q = r#"select * from (
|
||||
select distinct on (item_location.item)
|
||||
@ -410,4 +436,138 @@ impl EntityGateway for PostgresGateway {
|
||||
.await
|
||||
).await)
|
||||
}
|
||||
*/
|
||||
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
|
||||
let inventory = sqlx::query_as::<_, PgInventoryEntity>("select * from inventory where pchar = $1")
|
||||
.bind(char_id.0)
|
||||
.fetch_one(&self.pool).await?;
|
||||
// TODO: inefficient
|
||||
let mut real_inventory = Vec::new();
|
||||
for inv_item in inventory.items.0.into_iter() {
|
||||
match inv_item {
|
||||
PgInventoryItemEntity::Individual(item) => {
|
||||
let entity = sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
|
||||
.bind(item)
|
||||
.fetch_one(&self.pool).await
|
||||
.map(|item| item.into())?;
|
||||
real_inventory.push(InventoryItemEntity::Individual(entity));
|
||||
},
|
||||
PgInventoryItemEntity::Stacked(items) => {
|
||||
let mut stacked_item = Vec::new();
|
||||
for s_item in items {
|
||||
stacked_item.push(sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
|
||||
.bind(s_item)
|
||||
.fetch_one(&self.pool).await
|
||||
.map(|item| item.into())?)
|
||||
}
|
||||
real_inventory.push(InventoryItemEntity::Stacked(stacked_item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(InventoryEntity::new(real_inventory))
|
||||
}
|
||||
|
||||
async fn get_character_bank(&mut self, char_id: &CharacterEntityId, bank_name: BankName) -> Result<BankEntity, GatewayError> {
|
||||
let bank = sqlx::query_as::<_, PgInventoryEntity>("select * from bank where pchar = $1 and name = $2")
|
||||
.bind(char_id.0)
|
||||
.bind(bank_name.0)
|
||||
.fetch_one(&self.pool).await?;
|
||||
// TODO: inefficient
|
||||
let mut real_bank = Vec::new();
|
||||
for bank_item in bank.items.0.into_iter() {
|
||||
match bank_item {
|
||||
PgInventoryItemEntity::Individual(item) => {
|
||||
let entity = sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
|
||||
.bind(item)
|
||||
.fetch_one(&self.pool).await
|
||||
.map(|item| item.into())?;
|
||||
real_bank.push(BankItemEntity::Individual(entity));
|
||||
},
|
||||
PgInventoryItemEntity::Stacked(items) => {
|
||||
let mut stacked_item = Vec::new();
|
||||
for s_item in items {
|
||||
stacked_item.push(sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
|
||||
.bind(s_item)
|
||||
.fetch_one(&self.pool).await
|
||||
.map(|item| item.into())?)
|
||||
}
|
||||
real_bank.push(BankItemEntity::Stacked(stacked_item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(BankEntity::new(real_bank))
|
||||
}
|
||||
|
||||
async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> {
|
||||
let inventory = inventory.items.iter()
|
||||
.map(|item| {
|
||||
match item {
|
||||
InventoryItemEntity::Individual(item) => {
|
||||
PgInventoryItemEntity::Individual(item.id.0 as i32)
|
||||
},
|
||||
InventoryItemEntity::Stacked(items) => {
|
||||
PgInventoryItemEntity::Stacked(items.iter().map(|i| i.id.0 as i32).collect())
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
sqlx::query("insert into inventory (pchar, items) values ($1, $2) on conflict (pchar) do update set items = $2")
|
||||
.bind(char_id.0)
|
||||
.bind(sqlx::types::Json(inventory))
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_character_bank(&mut self, char_id: &CharacterEntityId, bank: &BankEntity, bank_name: BankName) -> Result<(), GatewayError> {
|
||||
let bank = bank.items.iter()
|
||||
.map(|item| {
|
||||
match item {
|
||||
BankItemEntity::Individual(item) => {
|
||||
PgInventoryItemEntity::Individual(item.id.0 as i32)
|
||||
},
|
||||
BankItemEntity::Stacked(items) => {
|
||||
PgInventoryItemEntity::Stacked(items.iter().map(|i| i.id.0 as i32).collect())
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
sqlx::query("insert into bank (pchar, items, name) values ($1, $2, $3) on conflict (pchar, name) do update set items = $2")
|
||||
.bind(char_id.0)
|
||||
.bind(sqlx::types::Json(bank))
|
||||
.bind(bank_name.0)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_character_equips(&mut self, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> {
|
||||
let equips = sqlx::query_as::<_, PgEquipped>("select * from equipped where pchar = $1")
|
||||
.bind(char_id.0)
|
||||
.fetch_one(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(equips.into())
|
||||
}
|
||||
|
||||
async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equips: &EquippedEntity) -> Result<(), GatewayError> {
|
||||
sqlx::query(r#"insert into equipped (pchar, weapon, armor, shield, unit0, unit1, unit2, unit3, mag) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
on conflict (pchar) do update set weapon=$2, armor=$3, shield=$4, unit0=$5, unit1=$6, unit2=$7, unit3=$8, mag=$9"#)
|
||||
.bind(char_id.0)
|
||||
.bind(equips.weapon.map(|i| i.0 as i32))
|
||||
.bind(equips.armor.map(|i| i.0 as i32))
|
||||
.bind(equips.shield.map(|i| i.0 as i32))
|
||||
.bind(equips.unit[0].map(|i| i.0 as i32))
|
||||
.bind(equips.unit[1].map(|i| i.0 as i32))
|
||||
.bind(equips.unit[2].map(|i| i.0 as i32))
|
||||
.bind(equips.unit[3].map(|i| i.0 as i32))
|
||||
.bind(equips.mag.map(|i| i.0 as i32))
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ pub struct BankName(pub String);
|
||||
pub enum ItemLocation {
|
||||
Inventory {
|
||||
character_id: CharacterEntityId,
|
||||
slot: usize,
|
||||
equipped: bool,
|
||||
},
|
||||
Bank {
|
||||
character_id: CharacterEntityId,
|
||||
@ -154,6 +152,13 @@ impl ItemDetail {
|
||||
ItemDetail::ESWeapon(e) => e.as_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_tool(self) -> Option<tool::Tool> {
|
||||
match self {
|
||||
ItemDetail::Tool(tool) => Some(tool),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -168,3 +173,131 @@ pub struct ItemEntity {
|
||||
pub location: ItemLocation,
|
||||
pub item: ItemDetail,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InventoryItemEntity {
|
||||
Individual(ItemEntity),
|
||||
Stacked(Vec<ItemEntity>),
|
||||
}
|
||||
|
||||
impl std::convert::From<ItemEntity> for InventoryItemEntity {
|
||||
fn from(item: ItemEntity) -> InventoryItemEntity {
|
||||
InventoryItemEntity::Individual(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<ItemEntity>> for InventoryItemEntity {
|
||||
fn from(items: Vec<ItemEntity>) -> InventoryItemEntity {
|
||||
InventoryItemEntity::Stacked(items)
|
||||
}
|
||||
}
|
||||
|
||||
impl InventoryItemEntity {
|
||||
pub fn map_individual<F: Fn(ItemEntity) -> ItemEntity>(self, func: F) -> InventoryItemEntity {
|
||||
match self {
|
||||
InventoryItemEntity::Individual(item) => InventoryItemEntity::Individual(func(item)),
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
//pub fn with_individual<T>(&self, func: fn(&ItemEntity) -> T) -> Option<T> {
|
||||
pub fn with_individual<F: Fn(&ItemEntity) -> T, T>(&self, func: F) -> Option<T> {
|
||||
match self {
|
||||
InventoryItemEntity::Individual(item) => Some(func(item)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn with_stacked<T>(&self, func: fn(&Vec<ItemEntity>) -> T) -> Option<T> {
|
||||
pub fn with_stacked<F: Fn(&Vec<ItemEntity>) -> T, T>(&self, func: F) -> Option<T> {
|
||||
match self {
|
||||
InventoryItemEntity::Stacked(items) => Some(func(items)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct EquippedEntity {
|
||||
pub weapon: Option<ItemEntityId>,
|
||||
pub armor: Option<ItemEntityId>,
|
||||
pub shield: Option<ItemEntityId>,
|
||||
pub unit: [Option<ItemEntityId>; 4],
|
||||
pub mag: Option<ItemEntityId>,
|
||||
}
|
||||
|
||||
impl EquippedEntity {
|
||||
pub fn is_equipped(&self, item: &ItemEntityId) -> bool {
|
||||
self.weapon == Some(*item)
|
||||
|| self.armor == Some(*item)
|
||||
|| self.shield == Some(*item)
|
||||
|| self.unit[0] == Some(*item)
|
||||
|| self.unit[1] == Some(*item)
|
||||
|| self.unit[2] == Some(*item)
|
||||
|| self.unit[3] == Some(*item)
|
||||
|| self.mag == Some(*item)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct InventoryEntity {
|
||||
pub items: Vec<InventoryItemEntity>,
|
||||
}
|
||||
|
||||
impl InventoryEntity {
|
||||
pub fn new<T: Into<InventoryItemEntity>>(items: Vec<T>) -> InventoryEntity {
|
||||
InventoryEntity {
|
||||
items: items.into_iter().map(|i| i.into()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BankItemEntity {
|
||||
Individual(ItemEntity),
|
||||
Stacked(Vec<ItemEntity>),
|
||||
}
|
||||
|
||||
impl std::convert::From<ItemEntity> for BankItemEntity {
|
||||
fn from(item: ItemEntity) -> BankItemEntity {
|
||||
BankItemEntity::Individual(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<ItemEntity>> for BankItemEntity {
|
||||
fn from(items: Vec<ItemEntity>) -> BankItemEntity {
|
||||
BankItemEntity::Stacked(items)
|
||||
}
|
||||
}
|
||||
|
||||
impl BankItemEntity {
|
||||
pub fn with_individual<T>(&self, func: fn(&ItemEntity) -> T) -> Option<T> {
|
||||
match self {
|
||||
BankItemEntity::Individual(item) => Some(func(item)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_stacked<T>(&self, func: fn(&Vec<ItemEntity>) -> T) -> Option<T> {
|
||||
match self {
|
||||
BankItemEntity::Stacked(items) => Some(func(items)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct BankEntity {
|
||||
//pub items: [Option<CharacterBankItem>; 30],
|
||||
pub items: Vec<BankItemEntity>,
|
||||
}
|
||||
|
||||
impl BankEntity {
|
||||
pub fn new<T: Into<BankItemEntity>>(items: Vec<T>) -> BankEntity {
|
||||
BankEntity {
|
||||
items: items.into_iter().map(|i| i.into()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,7 +335,6 @@ pub enum UnitModifier {
|
||||
pub struct Unit {
|
||||
pub unit: UnitType,
|
||||
pub modifier: Option<UnitModifier>,
|
||||
pub armor_slot: u8,
|
||||
}
|
||||
|
||||
|
||||
@ -362,7 +361,6 @@ impl Unit {
|
||||
},
|
||||
}
|
||||
}
|
||||
result[4] = self.armor_slot;
|
||||
result
|
||||
}
|
||||
|
||||
@ -380,7 +378,6 @@ impl Unit {
|
||||
Ok(Unit{
|
||||
unit: u.unwrap(),
|
||||
modifier: m,
|
||||
armor_slot: data[4],
|
||||
})
|
||||
}
|
||||
else {
|
||||
|
@ -19,7 +19,7 @@ use libpso::{utf8_to_array, utf8_to_utf16_array};
|
||||
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::account::{UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
|
||||
use crate::entity::item::{NewItemEntity, ItemDetail, ItemLocation};
|
||||
use crate::entity::item::{NewItemEntity, ItemDetail, ItemLocation, InventoryItemEntity, InventoryEntity, BankEntity, BankName, EquippedEntity};
|
||||
use crate::entity::item::weapon::Weapon;
|
||||
use crate::entity::item::armor::Armor;
|
||||
use crate::entity::item::tech::Technique;
|
||||
@ -88,7 +88,7 @@ pub enum SendCharacterPacket {
|
||||
ChecksumAck(ChecksumAck),
|
||||
CharacterPreview(CharacterPreview),
|
||||
GuildcardDataHeader(GuildcardDataHeader),
|
||||
GuildcardDataChunk(GuildcardDataChunk),
|
||||
GuildcardDataChunk(Box<GuildcardDataChunk>),
|
||||
ParamDataHeader(ParamDataHeader),
|
||||
ParamDataChunk(ParamDataChunk),
|
||||
Timestamp(Timestamp),
|
||||
@ -198,7 +198,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
};
|
||||
|
||||
|
||||
entity_gateway.create_item(
|
||||
let weapon = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item : ItemDetail::Weapon(
|
||||
Weapon {
|
||||
@ -211,11 +211,9 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
}),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}}).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
let armor = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Armor (
|
||||
Armor {
|
||||
@ -227,23 +225,20 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
}),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 1,
|
||||
equipped: true,
|
||||
}}).await.unwrap();
|
||||
|
||||
let mut mag = Mag::baby_mag(character.appearance.skin);
|
||||
mag.change_owner(character.char_class, character.section_id);
|
||||
entity_gateway.create_item(
|
||||
let mag = entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Mag(mag),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
}}).await.unwrap();
|
||||
|
||||
for _ in 0..4 {
|
||||
entity_gateway.create_item(
|
||||
let mut monomates = Vec::new();
|
||||
for _ in 0..4usize {
|
||||
monomates.push(entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
Tool {
|
||||
@ -251,10 +246,12 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
}),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 3,
|
||||
equipped: false,
|
||||
}}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
}}).await.unwrap())
|
||||
}
|
||||
|
||||
let mut monofluids = Vec::new();
|
||||
for _ in 0..4usize {
|
||||
monofluids.push(entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Tool (
|
||||
Tool {
|
||||
@ -262,10 +259,20 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
}),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 4,
|
||||
equipped: false,
|
||||
}}).await.unwrap();
|
||||
}}).await.unwrap())
|
||||
}
|
||||
|
||||
let inventory = InventoryEntity {
|
||||
items: vec![InventoryItemEntity::Individual(weapon.clone()), InventoryItemEntity::Individual(armor.clone()), InventoryItemEntity::Individual(mag.clone()),
|
||||
InventoryItemEntity::Stacked(monomates), InventoryItemEntity::Stacked(monofluids)],
|
||||
};
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory);
|
||||
entity_gateway.set_character_bank(&character.id, &BankEntity::default(), BankName("".into()));
|
||||
let mut equipped = EquippedEntity::default();
|
||||
equipped.weapon = Some(weapon.id);
|
||||
equipped.armor = Some(armor.id);
|
||||
equipped.mag = Some(mag.id);
|
||||
entity_gateway.set_character_equips(&character.id, &equipped);
|
||||
}
|
||||
|
||||
|
||||
@ -405,7 +412,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
||||
let mut buf = [0u8; GUILD_CARD_CHUNK_SIZE as usize];
|
||||
buf[..len as usize].copy_from_slice(&client.guildcard_data_buffer.as_ref().unwrap()[start..end]);
|
||||
|
||||
vec![SendCharacterPacket::GuildcardDataChunk(GuildcardDataChunk::new(chunk, buf, len))]
|
||||
vec![SendCharacterPacket::GuildcardDataChunk(Box::new(GuildcardDataChunk::new(chunk, buf, len)))]
|
||||
} else {
|
||||
Vec::new()
|
||||
})
|
||||
|
@ -103,7 +103,7 @@ pub enum SendPatchPacket {
|
||||
ChangeDirectory(ChangeDirectory),
|
||||
EndFileSend(EndFileSend),
|
||||
FileInfo(FileInfo),
|
||||
FileSend(FileSend),
|
||||
FileSend(Box<FileSend>),
|
||||
FilesToPatchMetadata(FilesToPatchMetadata),
|
||||
FinalizePatching(FinalizePatching),
|
||||
Message(Message),
|
||||
@ -338,12 +338,12 @@ impl Iterator for SendFileIterator {
|
||||
else {
|
||||
let mut crc = crc32::Digest::new(crc32::IEEE);
|
||||
crc.write(&buf[0..len]);
|
||||
let pkt = SendPatchPacket::FileSend(FileSend {
|
||||
let pkt = SendPatchPacket::FileSend(Box::new(FileSend {
|
||||
chunk_num: self.chunk_num,
|
||||
checksum: crc.sum32(),
|
||||
chunk_size: len as u32,
|
||||
buffer: buf,
|
||||
});
|
||||
}));
|
||||
self.chunk_num += 1;
|
||||
Some(pkt)
|
||||
}
|
||||
|
@ -89,7 +89,6 @@ impl GenericUnitTable {
|
||||
ItemDropType::Unit(Unit {
|
||||
unit: unit_type,
|
||||
modifier: unit_modifier,
|
||||
armor_slot: 0,
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -117,7 +116,6 @@ mod test {
|
||||
assert!(gut.get_drop(&area, &mut rng) == Some(ItemDropType::Unit(Unit {
|
||||
unit: unit,
|
||||
modifier: umod,
|
||||
armor_slot: 0,
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,6 @@ impl RareDropTable {
|
||||
ItemDropType::Unit(Unit {
|
||||
unit: unit,
|
||||
modifier: None,
|
||||
armor_slot: 0,
|
||||
})
|
||||
},
|
||||
RareDropItem::Tool(tool) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::ship::items::ClientItemId;
|
||||
use libpso::character::character;//::InventoryItem;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail};
|
||||
use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation, BankEntity, BankItemEntity, BankName};
|
||||
use crate::entity::character::CharacterEntityId;
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::ship::items::inventory::{InventoryItemHandle, InventoryItem};
|
||||
|
||||
@ -292,6 +293,41 @@ impl CharacterBank {
|
||||
|
||||
self.items.last()
|
||||
}
|
||||
|
||||
pub fn as_bank_entity(&self, character_id: &CharacterEntityId, bank_name: &BankName) -> BankEntity {
|
||||
BankEntity {
|
||||
items: self.items.iter()
|
||||
.map(|item| {
|
||||
match item {
|
||||
BankItem::Individual(item) => {
|
||||
BankItemEntity::Individual(ItemEntity {
|
||||
id: item.entity_id,
|
||||
location: ItemLocation::Bank {
|
||||
character_id: *character_id,
|
||||
name: bank_name.clone(),
|
||||
},
|
||||
item: item.item.clone(),
|
||||
})
|
||||
},
|
||||
BankItem::Stacked(items) => {
|
||||
BankItemEntity::Stacked(items.entity_ids.iter()
|
||||
.map(|id| {
|
||||
ItemEntity {
|
||||
id: *id,
|
||||
location: ItemLocation::Bank {
|
||||
character_id: *character_id,
|
||||
name: bank_name.clone(),
|
||||
},
|
||||
item: ItemDetail::Tool(items.tool)
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use std::cmp::Ordering;
|
||||
use thiserror::Error;
|
||||
use libpso::character::character;//::InventoryItem;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemType};
|
||||
use crate::entity::character::CharacterEntityId;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::entity::item::mag::Mag;
|
||||
use crate::ship::items::{ClientItemId, BankItem, BankItemHandle};
|
||||
@ -13,12 +14,12 @@ const INVENTORY_CAPACITY: usize = 30;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InventorySlot(pub usize);
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IndividualInventoryItem {
|
||||
pub entity_id: ItemEntityId,
|
||||
pub item_id: ClientItemId,
|
||||
pub item: ItemDetail,
|
||||
pub equipped: bool,
|
||||
}
|
||||
|
||||
impl IndividualInventoryItem {
|
||||
@ -153,17 +154,6 @@ impl InventoryItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equipped(&self) -> bool {
|
||||
match self {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
individual_inventory_item.equipped
|
||||
},
|
||||
InventoryItem::Stacked(_) => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_client_bytes(&self) -> [u8; 16] {
|
||||
match self {
|
||||
InventoryItem::Individual(item) => {
|
||||
@ -217,6 +207,8 @@ impl InventoryItem {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
#[error("")]
|
||||
pub enum InventoryItemConsumeError {
|
||||
@ -287,7 +279,7 @@ impl<'a> InventoryItemHandle<'a> {
|
||||
EntireThing(ConsumedItem),
|
||||
Partial(Tool),
|
||||
}
|
||||
|
||||
|
||||
let inventory_item = self.inventory.items.get(self.slot).ok_or(InventoryItemConsumeError::InconsistentState)?;
|
||||
let remove_method = match inventory_item {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
@ -350,13 +342,15 @@ impl<'a> InventoryItemHandle<'a> {
|
||||
pub struct CharacterInventory {
|
||||
item_id_counter: u32,
|
||||
items: Vec<InventoryItem>,
|
||||
equipped: EquippedEntity,
|
||||
}
|
||||
|
||||
impl CharacterInventory {
|
||||
pub fn new(items: Vec<InventoryItem>) -> CharacterInventory {
|
||||
pub fn new(items: Vec<InventoryItem>, equipped: &EquippedEntity) -> CharacterInventory {
|
||||
CharacterInventory{
|
||||
item_id_counter: 0,
|
||||
items: items,
|
||||
equipped: equipped.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,10 +369,22 @@ impl CharacterInventory {
|
||||
inventory[slot].data1.copy_from_slice(&bytes[0..12]);
|
||||
inventory[slot].data2.copy_from_slice(&bytes[12..16]);
|
||||
inventory[slot].item_id = item.item_id().0;
|
||||
// does this do anything?
|
||||
inventory[slot].equipped = if item.equipped() { 1 } else { 0 };
|
||||
// because this actually equips the item
|
||||
inventory[slot].flags |= if item.equipped() { 8 } else { 0 };
|
||||
inventory[slot].equipped = 0;
|
||||
inventory[slot].flags = 0;
|
||||
|
||||
if let InventoryItem::Individual(individual_item) = item {
|
||||
if self.equipped.is_equipped(&individual_item.entity_id) {
|
||||
if let ItemDetail::Unit(_) = individual_item.item {
|
||||
inventory[slot].data1[4] = self.equipped.unit.iter()
|
||||
.enumerate()
|
||||
.find(|(_, u_id)| **u_id == Some(individual_item.entity_id))
|
||||
.map(|(a, b)| a)
|
||||
.unwrap_or(0) as u8
|
||||
}
|
||||
inventory[slot].equipped = 1;
|
||||
inventory[slot].flags |= 8;
|
||||
}
|
||||
}
|
||||
inventory
|
||||
})
|
||||
}
|
||||
@ -390,7 +396,7 @@ impl CharacterInventory {
|
||||
pub fn count(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
|
||||
pub fn get_item_handle_by_id<'a>(&'a mut self, item_id: ClientItemId) -> Option<InventoryItemHandle<'a>> {
|
||||
let (slot, _) = self.items.iter()
|
||||
.enumerate()
|
||||
@ -410,7 +416,7 @@ impl CharacterInventory {
|
||||
.filter(|(_, item)| {
|
||||
if let InventoryItem::Individual(individual_inventory_item) = item {
|
||||
if let ItemDetail::Mag(_) = &individual_inventory_item.item {
|
||||
return individual_inventory_item.equipped
|
||||
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
|
||||
}
|
||||
}
|
||||
false
|
||||
@ -428,7 +434,7 @@ impl CharacterInventory {
|
||||
.filter(|(_, item)| {
|
||||
if let InventoryItem::Individual(individual_inventory_item) = item {
|
||||
if let ItemDetail::Armor(_) = &individual_inventory_item.item {
|
||||
return individual_inventory_item.equipped
|
||||
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
|
||||
}
|
||||
}
|
||||
false
|
||||
@ -446,7 +452,7 @@ impl CharacterInventory {
|
||||
.filter(|(_, item)| {
|
||||
if let InventoryItem::Individual(individual_inventory_item) = item {
|
||||
if let ItemDetail::Shield(_) = &individual_inventory_item.item {
|
||||
return individual_inventory_item.equipped
|
||||
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
|
||||
}
|
||||
}
|
||||
false
|
||||
@ -464,7 +470,7 @@ impl CharacterInventory {
|
||||
.filter(|(_, item)| {
|
||||
if let InventoryItem::Individual(individual_inventory_item) = item {
|
||||
if let ItemDetail::Weapon(_) = &individual_inventory_item.item {
|
||||
return individual_inventory_item.equipped
|
||||
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
|
||||
}
|
||||
}
|
||||
false
|
||||
@ -506,7 +512,6 @@ impl CharacterInventory {
|
||||
entity_id: floor_item.entity_id,
|
||||
item_id: floor_item.item_id,
|
||||
item: floor_item.item.clone(),
|
||||
equipped: false,
|
||||
}));
|
||||
|
||||
if let Some(InventoryItem::Individual(new_item)) = self.items.last() {
|
||||
@ -549,7 +554,7 @@ impl CharacterInventory {
|
||||
item_id: floor_item.item_id,
|
||||
tool: floor_item.tool,
|
||||
});
|
||||
|
||||
|
||||
self.items.push(new_stacked_item);
|
||||
if let Some(InventoryItem::Stacked(new_item)) = self.items.last() {
|
||||
Some((new_item, InventorySlot(self.count()-1)))
|
||||
@ -570,16 +575,15 @@ impl CharacterInventory {
|
||||
entity_id: individual_bank_item.entity_id,
|
||||
item_id: individual_bank_item.item_id,
|
||||
item: individual_bank_item.item.clone(),
|
||||
equipped: false,
|
||||
}));
|
||||
(true, self.count())
|
||||
(true, self.count()-1)
|
||||
},
|
||||
BankItem::Stacked(stacked_bank_item) => {
|
||||
let existing_inventory_item = self.items.iter_mut()
|
||||
.enumerate()
|
||||
.find_map(|(index, item)| {
|
||||
if let InventoryItem::Stacked(stacked_inventory_item) = item {
|
||||
if stacked_inventory_item.tool == stacked_inventory_item.tool {
|
||||
if stacked_bank_item.tool == stacked_inventory_item.tool {
|
||||
return Some((index, stacked_inventory_item))
|
||||
}
|
||||
}
|
||||
@ -608,7 +612,7 @@ impl CharacterInventory {
|
||||
item_id: ClientItemId(self.item_id_counter),
|
||||
tool: stacked_bank_item.tool,
|
||||
}));
|
||||
self.count()
|
||||
self.count()-1
|
||||
}
|
||||
};
|
||||
(stacked_bank_item.count() == 0, slot)
|
||||
@ -635,5 +639,89 @@ impl CharacterInventory {
|
||||
pub fn set_items(&mut self, sorted_items: Vec<InventoryItem>) {
|
||||
self.items = sorted_items;
|
||||
}
|
||||
|
||||
pub fn equip(&mut self, id: &ClientItemId, equip_slot: u8) {
|
||||
for item in &self.items {
|
||||
if let InventoryItem::Individual(inventory_item) = item {
|
||||
if inventory_item.item_id == *id {
|
||||
match inventory_item.item {
|
||||
ItemDetail::Weapon(_) => self.equipped.weapon = Some(inventory_item.entity_id),
|
||||
ItemDetail::Armor(_) => self.equipped.armor = Some(inventory_item.entity_id),
|
||||
ItemDetail::Shield(_) => self.equipped.shield = Some(inventory_item.entity_id),
|
||||
ItemDetail::Unit(_) => {
|
||||
if let Some(unit) = self.equipped.unit.get_mut(equip_slot as usize) {
|
||||
*unit = Some(inventory_item.entity_id)
|
||||
}
|
||||
}
|
||||
ItemDetail::Mag(_) => self.equipped.mag = Some(inventory_item.entity_id),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unequip(&mut self, id: &ClientItemId) {
|
||||
for item in &self.items {
|
||||
if let InventoryItem::Individual(inventory_item) = item {
|
||||
if inventory_item.item_id == *id {
|
||||
match inventory_item.item {
|
||||
ItemDetail::Weapon(_) => self.equipped.weapon = None,
|
||||
ItemDetail::Armor(_) => {
|
||||
self.equipped.armor = None;
|
||||
self.equipped.unit = [None; 4];
|
||||
}
|
||||
ItemDetail::Shield(_) => self.equipped.shield = None,
|
||||
ItemDetail::Unit(_) => {
|
||||
for unit in self.equipped.unit.iter_mut() {
|
||||
if *unit == Some(inventory_item.entity_id) {
|
||||
*unit = None
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemDetail::Mag(_) => self.equipped.mag = Some(inventory_item.entity_id),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_inventory_entity(&self, character_id: &CharacterEntityId) -> InventoryEntity {
|
||||
InventoryEntity {
|
||||
items: self.items.iter()
|
||||
.map(|item| {
|
||||
match item {
|
||||
InventoryItem::Individual(item) => {
|
||||
InventoryItemEntity::Individual(ItemEntity {
|
||||
id: item.entity_id,
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: *character_id,
|
||||
},
|
||||
item: item.item.clone(),
|
||||
})
|
||||
},
|
||||
InventoryItem::Stacked(items) => {
|
||||
InventoryItemEntity::Stacked(items.entity_ids.iter()
|
||||
.map(|id| {
|
||||
ItemEntity {
|
||||
id: *id,
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: *character_id,
|
||||
},
|
||||
item: ItemDetail::Tool(items.tool)
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_equipped_entity(&self) -> EquippedEntity {
|
||||
self.equipped.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ use thiserror::Error;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||
use crate::entity::item::{ItemDetail, ItemLocation, BankName};
|
||||
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity};
|
||||
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity, EquippedEntity, InventoryEntity, BankItemEntity, BankEntity};
|
||||
use crate::entity::item::tool::{Tool, ToolType};
|
||||
use crate::entity::item::unit;
|
||||
use crate::ship::map::MapArea;
|
||||
@ -48,40 +48,10 @@ pub enum ItemManagerError {
|
||||
CannotGetIndividualItem,
|
||||
InvalidSlot(u8, u8), // slots available, slot attempted
|
||||
NoArmorEquipped,
|
||||
GatewayError(#[from] crate::entity::gateway::GatewayError)
|
||||
GatewayError(#[from] crate::entity::gateway::GatewayError),
|
||||
StackedItemError(Vec<ItemEntity>),
|
||||
}
|
||||
|
||||
|
||||
async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) -> Result<(), ItemManagerError> {
|
||||
for (slot, item) in inventory.iter().enumerate() {
|
||||
match item {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
entity_gateway.change_item_location(
|
||||
&individual_inventory_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: individual_inventory_item.equipped,
|
||||
}
|
||||
).await?
|
||||
},
|
||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||
for entity_id in stacked_inventory_item.entity_ids.iter() {
|
||||
entity_gateway.change_item_location(
|
||||
entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub struct ItemManager {
|
||||
id_counter: u32,
|
||||
|
||||
@ -115,98 +85,66 @@ impl ItemManager {
|
||||
|
||||
// TODO: Result
|
||||
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.id).await?;
|
||||
let inventory_items = items.clone().into_iter()
|
||||
.filter_map(|item| {
|
||||
match item.location {
|
||||
ItemLocation::Inventory{slot, equipped, ..} => Some((item.id, item.item, slot, equipped)),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.fold(BTreeMap::new(), |mut acc, (id, item, slot, equipped)| {
|
||||
if item.is_stackable() {
|
||||
if let ItemDetail::Tool(tool) = item {
|
||||
let inventory_item = acc.entry(slot).or_insert(InventoryItem::Stacked(StackedInventoryItem {
|
||||
entity_ids: Vec::new(),
|
||||
let inventory = entity_gateway.get_character_inventory(&character.id).await?;
|
||||
let bank = entity_gateway.get_character_bank(&character.id, BankName("".into())).await?;
|
||||
let equipped = entity_gateway.get_character_equips(&character.id).await?;
|
||||
|
||||
let inventory_items = inventory.items.into_iter()
|
||||
.map(|item| -> Result<InventoryItem, ItemManagerError> {
|
||||
Ok(match item {
|
||||
InventoryItemEntity::Individual(item) => {
|
||||
InventoryItem::Individual(IndividualInventoryItem {
|
||||
entity_id: item.id,
|
||||
item_id: self.next_global_item_id(),
|
||||
tool: tool,
|
||||
}));
|
||||
if let InventoryItem::Stacked(ref mut stacked_inventory_item) = inventory_item {
|
||||
stacked_inventory_item.entity_ids.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
acc.insert(slot, InventoryItem::Individual(IndividualInventoryItem {
|
||||
entity_id: id,
|
||||
item_id: self.next_global_item_id(),
|
||||
item: item,
|
||||
equipped: equipped,
|
||||
}));
|
||||
}
|
||||
|
||||
acc
|
||||
});
|
||||
|
||||
// TODO: not using BankName anymore, clean this up
|
||||
let mut bank_items = items.into_iter()
|
||||
.filter_map(|item| {
|
||||
match item.location {
|
||||
ItemLocation::Bank{name, ..} => Some((item.id, item.item, name)),
|
||||
_ => None,
|
||||
}
|
||||
item: item.item,
|
||||
})
|
||||
},
|
||||
InventoryItemEntity::Stacked(items) => {
|
||||
InventoryItem::Stacked(StackedInventoryItem {
|
||||
entity_ids: items.iter().map(|i| i.id).collect(),
|
||||
item_id: self.next_global_item_id(),
|
||||
tool: items.get(0)
|
||||
.ok_or(ItemManagerError::StackedItemError(items.clone()))?
|
||||
.item
|
||||
.clone()
|
||||
.as_tool()
|
||||
.ok_or(ItemManagerError::StackedItemError(items.clone()))?
|
||||
})
|
||||
},
|
||||
})
|
||||
})
|
||||
.fold(BTreeMap::new(), |mut acc, (id, item, name)| {
|
||||
acc.entry(name).or_insert(Vec::new()).push((id, item));
|
||||
acc
|
||||
})
|
||||
.into_iter()
|
||||
.map(|(bank_name, bank_items)| {
|
||||
let stacked_bank_items = bank_items.into_iter()
|
||||
.fold(Vec::new(), |mut acc, (id, bank_item)| {
|
||||
if bank_item.is_stackable() {
|
||||
let existing_item = acc.iter_mut()
|
||||
.find(|item| {
|
||||
if let (BankItem::Stacked(stacked_bank_item), &ItemDetail::Tool(ref tool)) = (item, &bank_item) {
|
||||
stacked_bank_item.tool == *tool
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
});
|
||||
match existing_item {
|
||||
Some(item) => {
|
||||
if let BankItem::Stacked(ref mut stacked_bank_item) = item {
|
||||
stacked_bank_item.entity_ids.push(id);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if let ItemDetail::Tool(tool) = bank_item {
|
||||
acc.push(BankItem::Stacked(StackedBankItem {
|
||||
entity_ids: vec![id],
|
||||
item_id: self.next_global_item_id(),
|
||||
tool: tool,
|
||||
}));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
else {
|
||||
acc.push(BankItem::Individual(IndividualBankItem {
|
||||
entity_id: id,
|
||||
item_id: self.next_global_item_id(),
|
||||
item: bank_item,
|
||||
}));
|
||||
}
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let character_inventory = CharacterInventory::new(inventory_items, &equipped);
|
||||
|
||||
acc
|
||||
});
|
||||
(bank_name, CharacterBank::new(stacked_bank_items))
|
||||
let bank_items = bank.items.into_iter()
|
||||
.map(|item| -> Result<BankItem, ItemManagerError> {
|
||||
Ok(match item {
|
||||
BankItemEntity::Individual(item) => {
|
||||
BankItem::Individual(IndividualBankItem {
|
||||
entity_id: item.id,
|
||||
item_id: self.next_global_item_id(),
|
||||
item: item.item,
|
||||
})
|
||||
},
|
||||
BankItemEntity::Stacked(items) => {
|
||||
BankItem::Stacked(StackedBankItem {
|
||||
entity_ids: items.iter().map(|i| i.id).collect(),
|
||||
item_id: self.next_global_item_id(),
|
||||
tool: items.get(0)
|
||||
.ok_or(ItemManagerError::StackedItemError(items.clone()))?
|
||||
.item
|
||||
.clone()
|
||||
.as_tool()
|
||||
.ok_or(ItemManagerError::StackedItemError(items.clone()))?
|
||||
})
|
||||
},
|
||||
})
|
||||
})
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
||||
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())));
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let character_bank = CharacterBank::new(bank_items);
|
||||
|
||||
self.character_inventory.insert(character.id, character_inventory);
|
||||
self.character_bank.insert(character.id, character_bank);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -301,8 +239,6 @@ impl ItemManager {
|
||||
&new_inventory_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}
|
||||
).await?;
|
||||
if let Some(_) = new_inventory_item.mag() {
|
||||
@ -325,8 +261,6 @@ impl ItemManager {
|
||||
&entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}
|
||||
).await?;
|
||||
}
|
||||
@ -356,6 +290,7 @@ impl ItemManager {
|
||||
}
|
||||
};
|
||||
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
floor_item.remove_from_floor();
|
||||
Ok(trigger_create_item)
|
||||
}
|
||||
@ -487,7 +422,7 @@ impl ItemManager {
|
||||
},
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -549,6 +484,7 @@ impl ItemManager {
|
||||
).await?;
|
||||
}
|
||||
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(stacked_floor_item)
|
||||
}
|
||||
|
||||
@ -567,7 +503,7 @@ impl ItemManager {
|
||||
ItemLocation::Consumed).await?;
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(consumed_item)
|
||||
}
|
||||
|
||||
@ -604,7 +540,8 @@ impl ItemManager {
|
||||
}
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
entity_gateway.set_character_bank(&character.id, &bank.as_bank_entity(&character.id, &BankName("".into())), BankName("".into())).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -621,30 +558,31 @@ impl ItemManager {
|
||||
.ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
|
||||
let item_to_withdraw = bank.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||
let inventory_item = inventory.withdraw_item(item_to_withdraw, amount).ok_or(ItemManagerError::Idunnoman)?;
|
||||
let inventory_item_slot = {
|
||||
let inventory_item = inventory.withdraw_item(item_to_withdraw, amount).ok_or(ItemManagerError::Idunnoman)?;
|
||||
|
||||
match inventory_item {
|
||||
(InventoryItem::Individual(individual_inventory_item), slot) => {
|
||||
entity_gateway.change_item_location(&individual_inventory_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await?;
|
||||
},
|
||||
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
|
||||
for entity_id in &stacked_inventory_item.entity_ids {
|
||||
entity_gateway.change_item_location(entity_id,
|
||||
match inventory_item {
|
||||
(InventoryItem::Individual(individual_inventory_item), slot) => {
|
||||
entity_gateway.change_item_location(&individual_inventory_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await?;
|
||||
},
|
||||
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
|
||||
for entity_id in &stacked_inventory_item.entity_ids {
|
||||
entity_gateway.change_item_location(entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
}).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
inventory_item.1
|
||||
};
|
||||
|
||||
Ok(inventory_item.0)
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
entity_gateway.set_character_bank(&character.id, &bank.as_bank_entity(&character.id, &BankName("".into())), BankName("".into())).await?;
|
||||
inventory.slot(inventory_item_slot).ok_or(ItemManagerError::Idunnoman)
|
||||
}
|
||||
|
||||
pub async fn player_feeds_mag_item<EG: EntityGateway>(&mut self,
|
||||
@ -681,7 +619,7 @@ impl ItemManager {
|
||||
}).await?;
|
||||
}
|
||||
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -795,7 +733,7 @@ impl ItemManager {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -835,8 +773,6 @@ impl ItemManager {
|
||||
entity_gateway.change_item_location(entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}).await?;
|
||||
}
|
||||
picked_up_item.item_id
|
||||
@ -863,8 +799,6 @@ impl ItemManager {
|
||||
entity_gateway.change_item_location(&picked_up_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}).await?;
|
||||
picked_up_item.item_id
|
||||
};
|
||||
@ -891,14 +825,14 @@ impl ItemManager {
|
||||
entity_gateway.change_item_location(&picked_up_item.entity_id,
|
||||
ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: slot.0,
|
||||
equipped: false,
|
||||
}).await?;
|
||||
picked_up_item.item_id
|
||||
};
|
||||
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
||||
},
|
||||
};
|
||||
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(inventory_item)
|
||||
}
|
||||
|
||||
@ -910,31 +844,8 @@ impl ItemManager {
|
||||
equip_slot: u8)
|
||||
-> Result<(), ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
let mut inventory_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||
let slot = inventory_item_handle.get_slot();
|
||||
let inventory_item = inventory_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?.individual().ok_or(ItemManagerError::CannotGetIndividualItem)?;
|
||||
inventory_item.equipped = true;
|
||||
if let ItemDetail::Unit(u) = inventory_item.item {
|
||||
if equip_slot > 0 {
|
||||
inventory_item.item = ItemDetail::Unit(unit::Unit {
|
||||
unit: u.unit,
|
||||
modifier: u.modifier,
|
||||
armor_slot: ((equip_slot & 0x7) - 1) % 4, // or just be lazy and do equip_slot - 9
|
||||
});
|
||||
} else {
|
||||
inventory_item.item = ItemDetail::Unit(unit::Unit {
|
||||
unit: u.unit,
|
||||
modifier: u.modifier,
|
||||
armor_slot: 0,
|
||||
});
|
||||
}
|
||||
};
|
||||
entity_gateway.change_item_location(&inventory_item.entity_id, ItemLocation::Inventory{
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: true,
|
||||
}).await?;
|
||||
entity_gateway.change_item(&inventory_item.entity_id, &inventory_item.item).await?;
|
||||
inventory.equip(&item_id, equip_slot);
|
||||
entity_gateway.set_character_equips(&character.id, &inventory.as_equipped_entity()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -944,23 +855,8 @@ impl ItemManager {
|
||||
item_id: ClientItemId)
|
||||
-> Result<(), ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
let mut inventory_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||
let slot = inventory_item_handle.get_slot();
|
||||
let inventory_item = inventory_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?.individual().ok_or(ItemManagerError::CannotGetIndividualItem)?;
|
||||
inventory_item.equipped = false;
|
||||
if let ItemDetail::Unit(u) = inventory_item.item {
|
||||
inventory_item.item = ItemDetail::Unit(unit::Unit {
|
||||
unit: u.unit,
|
||||
modifier: u.modifier,
|
||||
armor_slot: 0,
|
||||
});
|
||||
};
|
||||
entity_gateway.change_item_location(&inventory_item.entity_id, ItemLocation::Inventory{
|
||||
character_id: character.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}).await;
|
||||
entity_gateway.change_item(&inventory_item.entity_id, &inventory_item.item).await?;
|
||||
inventory.unequip(&item_id);
|
||||
entity_gateway.set_character_equips(&character.id, &inventory.as_equipped_entity()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -978,7 +874,7 @@ impl ItemManager {
|
||||
.collect();
|
||||
|
||||
inventory.set_items(sorted_inventory_items);
|
||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ pub fn block_selected(id: ClientId,
|
||||
.build();
|
||||
|
||||
Ok(vec![
|
||||
SendShipPacket::FullCharacter(FullCharacter {
|
||||
SendShipPacket::FullCharacter(Box::new(FullCharacter {
|
||||
character: fc,
|
||||
}),
|
||||
})),
|
||||
SendShipPacket::CharDataRequest(CharDataRequest {}),
|
||||
SendShipPacket::LobbyList(LobbyList::new()),
|
||||
])
|
||||
|
@ -316,7 +316,13 @@ where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
item_manager.player_equips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id), pkt.sub_menu).await?;
|
||||
let equip_slot = if pkt.sub_menu > 0 {
|
||||
((pkt.sub_menu & 0x7) - 1) % 4
|
||||
}
|
||||
else {
|
||||
0
|
||||
};
|
||||
item_manager.player_equips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id), equip_slot).await?;
|
||||
Ok(Box::new(None.into_iter()))
|
||||
}
|
||||
|
||||
@ -330,30 +336,7 @@ where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let equipped_unit_ids: Vec<ClientItemId> = {
|
||||
item_manager.player_unequips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id)).await?;
|
||||
let inventory = item_manager.get_character_inventory(&client.character).unwrap();
|
||||
let ue_item = inventory.get_item_by_id(ClientItemId(pkt.item_id)).ok_or(ShipError::ItemError)?;
|
||||
if let ItemType::Armor(_) = ue_item.item_type() {
|
||||
inventory.items()
|
||||
.iter()
|
||||
.filter(|inv_item| {
|
||||
if let ItemType::Unit(_) = inv_item.item_type() {
|
||||
return inv_item.equipped()
|
||||
}
|
||||
false
|
||||
})
|
||||
.map(|u| u.item_id())
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
for unit_id in equipped_unit_ids {
|
||||
item_manager.player_unequips_item(entity_gateway, &client.character, unit_id).await;
|
||||
}
|
||||
|
||||
item_manager.player_unequips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id)).await?;
|
||||
Ok(Box::new(None.into_iter()))
|
||||
}
|
||||
|
||||
@ -369,4 +352,4 @@ where
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
item_manager.player_sorts_items(entity_gateway, &client.character, pkt.item_ids).await?;
|
||||
Ok(Box::new(None.into_iter())) // Do clients care about the order of other clients items?
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ pub enum SendShipPacket {
|
||||
ShipWelcome(ShipWelcome),
|
||||
LoginResponse(LoginResponse),
|
||||
ShipBlockList(ShipBlockList),
|
||||
FullCharacter(FullCharacter),
|
||||
FullCharacter(Box<FullCharacter>),
|
||||
CharDataRequest(CharDataRequest),
|
||||
JoinLobby(JoinLobby),
|
||||
AddToLobby(AddToLobby),
|
||||
@ -341,10 +341,10 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
|
||||
ShipServerState {
|
||||
entity_gateway: self.entity_gateway.unwrap(),
|
||||
clients: HashMap::new(),
|
||||
client_location: ClientLocation::new(),
|
||||
client_location: Box::new(ClientLocation::new()),
|
||||
level_table: CharacterLevelTable::new(),
|
||||
name: self.name.unwrap_or("NAMENOTSET".into()),
|
||||
rooms: [None; MAX_ROOMS],
|
||||
rooms: Box::new([None; MAX_ROOMS]),
|
||||
item_manager: items::ItemManager::new(),
|
||||
quests: quests::load_quests("data/quests.toml".into()).unwrap(),
|
||||
ip: self.ip.unwrap_or(Ipv4Addr::new(127,0,0,1)),
|
||||
@ -358,10 +358,10 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> {
|
||||
pub struct ShipServerState<EG: EntityGateway> {
|
||||
entity_gateway: EG,
|
||||
pub clients: Clients,
|
||||
client_location: ClientLocation,
|
||||
client_location: Box<ClientLocation>,
|
||||
level_table: CharacterLevelTable,
|
||||
name: String,
|
||||
pub rooms: Rooms,
|
||||
pub rooms: Box<Rooms>,
|
||||
item_manager: items::ItemManager,
|
||||
quests: quests::QuestList,
|
||||
ip: Ipv4Addr,
|
||||
|
@ -85,7 +85,6 @@ impl ShopItem for ArmorShopItem {
|
||||
ItemDetail::Unit(Unit {
|
||||
unit: *unit,
|
||||
modifier: None,
|
||||
armor_slot: 0,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,9 @@ async fn test_save_options() {
|
||||
|
||||
let (user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
|
||||
|
@ -17,9 +17,9 @@ async fn test_character_gains_exp() {
|
||||
|
||||
let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -56,9 +56,9 @@ async fn test_character_levels_up() {
|
||||
char1.exp = 49;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -94,9 +94,9 @@ async fn test_character_levels_up_multiple_times() {
|
||||
|
||||
let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -139,9 +139,9 @@ async fn test_one_character_gets_full_exp_and_other_attacker_gets_partial() {
|
||||
let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
|
@ -16,7 +16,8 @@ async fn test_equip_unit_from_equip_menu() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Armor(
|
||||
item::armor::Armor{
|
||||
@ -28,44 +29,46 @@ async fn test_equip_unit_from_equip_menu() {
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: None,
|
||||
armor_slot: 0,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: Some(item::unit::UnitModifier::Plus),
|
||||
armor_slot: 0,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 2,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let equipped = item::EquippedEntity {
|
||||
weapon: Some(p1_inv[0].id),
|
||||
armor: None,
|
||||
shield: None,
|
||||
unit: [None; 4],
|
||||
mag: None,
|
||||
};
|
||||
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -87,44 +90,11 @@ async fn test_equip_unit_from_equip_menu() {
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
let (unit1, unit2) = (&items[1], &items[2]);
|
||||
|
||||
let unit1_equipped = match unit1.location {
|
||||
item::ItemLocation::Inventory{equipped, ..} => equipped,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let unit2_equipped = match unit2.location {
|
||||
item::ItemLocation::Inventory{equipped, ..} => equipped,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
assert!({
|
||||
match unit1.item {
|
||||
item::ItemDetail::Unit(u) => {
|
||||
if u.armor_slot == 0 && unit1_equipped {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
assert!({
|
||||
match unit2.item {
|
||||
item::ItemDetail::Unit(u) => {
|
||||
if u.armor_slot == 1 && unit2_equipped {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
let equips = entity_gateway.get_character_equips(&char1.id).await.unwrap();
|
||||
assert_eq!(equips.unit[0].unwrap(), item::ItemEntityId(2));
|
||||
assert_eq!(equips.unit[1].unwrap(), item::ItemEntityId(3));
|
||||
assert!(equips.unit[2].is_none());
|
||||
assert!(equips.unit[3].is_none());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -133,7 +103,8 @@ async fn test_unequip_armor_with_units() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Armor(
|
||||
item::armor::Armor{
|
||||
@ -145,44 +116,46 @@ async fn test_unequip_armor_with_units() {
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: None,
|
||||
armor_slot: 0,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: Some(item::unit::UnitModifier::Plus),
|
||||
armor_slot: 1,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let equipped = item::EquippedEntity {
|
||||
weapon: None,
|
||||
armor: Some(p1_inv[0].id),
|
||||
shield: None,
|
||||
unit: [Some(p1_inv[1].id), Some(p1_inv[2].id), None, None],
|
||||
mag: None,
|
||||
};
|
||||
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -194,27 +167,12 @@ async fn test_unequip_armor_with_units() {
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
let (armor, unit1, unit2) = (&items[0], &items[1], &items[2]);
|
||||
|
||||
let armor_equipped = match armor.location {
|
||||
item::ItemLocation::Inventory{equipped, ..} => equipped,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
let unit1_equipped = match unit1.location {
|
||||
item::ItemLocation::Inventory{equipped, ..} => equipped,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
let unit2_equipped = match unit2.location {
|
||||
item::ItemLocation::Inventory{equipped, ..} => equipped,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
assert!(armor_equipped == false);
|
||||
assert!(unit1_equipped == false);
|
||||
assert!(unit2_equipped == false);
|
||||
let equips = entity_gateway.get_character_equips(&char1.id).await.unwrap();
|
||||
assert!(equips.armor.is_none());
|
||||
assert!(equips.unit[0].is_none());
|
||||
assert!(equips.unit[1].is_none());
|
||||
assert!(equips.unit[2].is_none());
|
||||
assert!(equips.unit[3].is_none());
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -223,7 +181,8 @@ async fn test_sort_items() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Armor(
|
||||
item::armor::Armor{
|
||||
@ -235,55 +194,54 @@ async fn test_sort_items() {
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: None,
|
||||
armor_slot: 0,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Unit(
|
||||
item::unit::Unit{
|
||||
unit: item::unit::UnitType::KnightPower,
|
||||
modifier: Some(item::unit::UnitModifier::Plus),
|
||||
armor_slot: 0,
|
||||
}),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 2,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
}).await.unwrap());
|
||||
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
|
||||
let old_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(old_items[0].item.item_type() == item::ItemType::Armor(item::armor::ArmorType::Frame));
|
||||
assert!(old_items[0].location == item::ItemLocation::Inventory{
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
});
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 3);
|
||||
inventory_items.items[0].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(1));
|
||||
}).unwrap();
|
||||
inventory_items.items[1].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(2));
|
||||
}).unwrap();
|
||||
inventory_items.items[2].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(3));
|
||||
}).unwrap();
|
||||
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::SortItems(SortItems {
|
||||
client: 255,
|
||||
@ -293,11 +251,15 @@ async fn test_sort_items() {
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF],
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items[0].item.item_type() == item::ItemType::Armor(item::armor::ArmorType::Frame));
|
||||
assert!(items[0].location == item::ItemLocation::Inventory{
|
||||
character_id: char1.id,
|
||||
slot: 2,
|
||||
equipped: true,
|
||||
});
|
||||
}
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 3);
|
||||
inventory_items.items[0].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(2));
|
||||
}).unwrap();
|
||||
inventory_items.items[1].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(3));
|
||||
}).unwrap();
|
||||
inventory_items.items[2].with_individual(|item| {
|
||||
assert_eq!(item.id, item::ItemEntityId(1));
|
||||
}).unwrap();
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p1_monomate = Vec::new();
|
||||
p1_monomate.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -26,14 +27,14 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut p2_items = Vec::new();
|
||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||
for _ in 0..5 {
|
||||
entity_gateway.create_item(
|
||||
let mut item = Vec::new();
|
||||
for _ in 0..5usize {
|
||||
item.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -42,16 +43,18 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
p2_items.push(item);
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_monomate])).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_items)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -80,21 +83,13 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 6);
|
||||
|
||||
let p1_item_ids = p1_items.iter().map(|item| {
|
||||
item.id
|
||||
}).collect::<Vec<_>>();
|
||||
assert!(p1_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4), item::ItemEntityId(5), item::ItemEntityId(6)]);
|
||||
|
||||
let all_items_are_monomates = p1_items.iter().all(|item| {
|
||||
match item.item {
|
||||
item::ItemDetail::Tool(tool) => tool.tool == item::tool::ToolType::Monomate,
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
assert!(all_items_are_monomates);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
|
||||
vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4), item::ItemEntityId(5), item::ItemEntityId(6)]);
|
||||
assert!(items.iter().all(|item| item.item.item_type() == item::ItemType::Tool(item::tool::ToolType::Monomate)));
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -104,7 +99,8 @@ async fn test_pick_up_item_stack_of_items_not_already_held() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p2_monomate = Vec::new();
|
||||
p2_monomate.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -113,14 +109,14 @@ async fn test_pick_up_item_stack_of_items_not_already_held() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_monomate])).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -149,14 +145,13 @@ async fn test_pick_up_item_stack_of_items_not_already_held() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 1);
|
||||
|
||||
let first_item = p1_items.get(0).unwrap();
|
||||
assert!(first_item.id == item::ItemEntityId(1));
|
||||
assert!(first_item.item == item::ItemDetail::Tool(item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}));
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 1);
|
||||
assert_eq!(items[0].id, item::ItemEntityId(1));
|
||||
assert_eq!(items[0].item.item_type(), item::ItemType::Tool(item::tool::ToolType::Monomate));
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -166,8 +161,9 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
||||
let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for slot in 0..30 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_items = Vec::new();
|
||||
for _ in 0..30usize {
|
||||
p1_items.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -181,18 +177,18 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_items)).await.unwrap();
|
||||
|
||||
char2.meseta = 300;
|
||||
entity_gateway.save_character(&char2).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -227,8 +223,8 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 30);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 30);
|
||||
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
@ -245,8 +241,9 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for slot in 0..29 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
for slot in 0..29usize {
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -260,13 +257,11 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap().into());
|
||||
}
|
||||
|
||||
entity_gateway.create_item(
|
||||
p1_inv.push(item::InventoryItemEntity::Stacked(vec![entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -275,11 +270,11 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 29,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.create_item(
|
||||
}).await.unwrap()]));
|
||||
|
||||
let mut p2_monomates = Vec::new();
|
||||
p2_monomates.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -288,14 +283,15 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_monomates])).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -324,17 +320,11 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 31);
|
||||
|
||||
let monomate1 = p1_items.get(29).unwrap();
|
||||
assert!(monomate1.item == item::ItemDetail::Tool(item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}));
|
||||
let monomate2 = p1_items.get(30).unwrap();
|
||||
assert!(monomate2.item == item::ItemDetail::Tool(item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}));
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 30);
|
||||
inventory_items.items[29].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 2);
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -344,8 +334,9 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for slot in 0..30 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
for slot in 0..30usize {
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -359,13 +350,12 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p2_inv = Vec::new();
|
||||
p2_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -379,14 +369,15 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -415,11 +406,10 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 30);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||
assert!(p2_items.len() == 0);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 30);
|
||||
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
||||
assert_eq!(p2_items.items.len(), 0);
|
||||
|
||||
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||
client: 0,
|
||||
@ -429,8 +419,10 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||
assert!(p2_items.len() == 1);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 30);
|
||||
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
||||
assert_eq!(p2_items.items.len(), 1);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -442,9 +434,9 @@ async fn test_can_not_drop_more_meseta_than_is_held() {
|
||||
char1.meseta = 300;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
@ -481,8 +473,9 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for _ in 0..6 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_monomates = Vec::new();
|
||||
for _ in 0..6usize {
|
||||
p1_monomates.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -491,13 +484,13 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
for _ in 0..6 {
|
||||
entity_gateway.create_item(
|
||||
|
||||
let mut p2_monomates = Vec::new();
|
||||
for _ in 0..6usize {
|
||||
p2_monomates.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -506,15 +499,15 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_monomates])).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_monomates])).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -544,11 +537,13 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
assert!(packets.len() == 0);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 6);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||
assert!(p2_items.len() == 0);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 1);
|
||||
p1_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 6);
|
||||
}).unwrap();
|
||||
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
||||
assert_eq!(p2_items.items.len(), 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -563,9 +558,9 @@ async fn test_can_not_pick_up_meseta_when_full() {
|
||||
char2.meseta = 300;
|
||||
entity_gateway.save_character(&char2).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -621,9 +616,9 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
||||
char2.meseta = 300;
|
||||
entity_gateway.save_character(&char2).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -673,8 +668,9 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for _ in 0..5 {
|
||||
entity_gateway.create_item(
|
||||
let mut monomates = Vec::new();
|
||||
for _ in 0..5usize {
|
||||
monomates.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -683,15 +679,15 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![monomates])).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
@ -726,35 +722,17 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items.len() == 3);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
|
||||
vec![item::ItemEntityId(3), item::ItemEntityId(4), item::ItemEntityId(5)]);
|
||||
}).unwrap();
|
||||
|
||||
let p1_item_ids = p1_items.iter().map(|item| {
|
||||
item.id
|
||||
}).collect::<Vec<_>>();
|
||||
assert!(p1_item_ids == vec![item::ItemEntityId(3), item::ItemEntityId(4), item::ItemEntityId(5)]);
|
||||
|
||||
let all_items_are_monomates = p1_items.iter().all(|item| {
|
||||
match item.item {
|
||||
item::ItemDetail::Tool(tool) => tool.tool == item::tool::ToolType::Monomate,
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
assert!(all_items_are_monomates);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||
assert!(p2_items.len() == 2);
|
||||
|
||||
let p2_item_ids = p2_items.iter().map(|item| {
|
||||
item.id
|
||||
}).collect::<Vec<_>>();
|
||||
assert!(p2_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
|
||||
|
||||
let all_items_are_monomates = p1_items.iter().all(|item| {
|
||||
match item.item {
|
||||
item::ItemDetail::Tool(tool) => tool.tool == item::tool::ToolType::Monomate,
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
assert!(all_items_are_monomates);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.iter().map(|i| i.id).collect::<Vec<_>>(),
|
||||
vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
|
||||
}).unwrap();
|
||||
}
|
||||
|
@ -18,9 +18,11 @@ async fn test_use_monomate() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_items = Vec::new();
|
||||
for tool in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter() {
|
||||
let mut item = Vec::new();
|
||||
for _ in 0..2usize {
|
||||
item.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -29,16 +31,17 @@ async fn test_use_monomate() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
p1_items.push(item::InventoryItemEntity::Stacked(item));
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_items)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -49,23 +52,14 @@ async fn test_use_monomate() {
|
||||
item_id: 0x10000,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monomate
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 1);
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monofluid
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 2);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 2);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 1)
|
||||
}).unwrap();
|
||||
inventory_items.items[1].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 2)
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -74,9 +68,11 @@ async fn test_use_monomate_twice() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||
for _ in 0..3 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_items = Vec::new();
|
||||
for tool in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter() {
|
||||
let mut item = Vec::new();
|
||||
for _ in 0..3usize {
|
||||
item.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -85,16 +81,17 @@ async fn test_use_monomate_twice() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
p1_items.push(item::InventoryItemEntity::Stacked(item));
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_items)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -110,23 +107,14 @@ async fn test_use_monomate_twice() {
|
||||
item_id: 0x10000,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monomate
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 1);
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monofluid
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 3);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 2);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 1)
|
||||
}).unwrap();
|
||||
inventory_items.items[1].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 3)
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -135,27 +123,26 @@ async fn test_use_last_monomate() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||
for _ in 0..1 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: tool
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
let mut p1_inv = Vec::new();
|
||||
for tool in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter() {
|
||||
p1_inv.push(item::InventoryItemEntity::Stacked(vec![entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: tool
|
||||
}
|
||||
}).await.unwrap();
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
}
|
||||
}).await.unwrap()]));
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -166,23 +153,13 @@ async fn test_use_last_monomate() {
|
||||
item_id: 0x10000,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monomate
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 0);
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::Monofluid
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 1);
|
||||
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 1);
|
||||
assert_eq!(items[0].item.item_type(), item::ItemType::Tool(item::tool::ToolType::Monofluid));
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -191,7 +168,8 @@ async fn test_use_nonstackable_tool() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mut p1_items = Vec::new();
|
||||
p1_items.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -200,14 +178,14 @@ async fn test_use_nonstackable_tool() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_items)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -218,8 +196,8 @@ async fn test_use_nonstackable_tool() {
|
||||
item_id: 0x10000,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items.len() == 0);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -228,9 +206,11 @@ async fn test_use_materials() {
|
||||
|
||||
let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for (slot, tool) in vec![item::tool::ToolType::PowerMaterial, item::tool::ToolType::LuckMaterial].into_iter().enumerate() {
|
||||
for _ in 0..5 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
for tool in vec![item::tool::ToolType::PowerMaterial, item::tool::ToolType::LuckMaterial].into_iter() {
|
||||
let mut item = Vec::new();
|
||||
for _ in 0..5usize {
|
||||
item.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -239,16 +219,17 @@ async fn test_use_materials() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
p1_inv.push(item::InventoryItemEntity::Stacked(item));
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -269,23 +250,14 @@ async fn test_use_materials() {
|
||||
item_id: 0x10001,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::PowerMaterial
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 4);
|
||||
assert!(items.iter().filter(|item| {
|
||||
if let item::ItemDetail::Tool(t) = item.item {
|
||||
t.tool == item::tool::ToolType::LuckMaterial
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).count() == 3);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 2);
|
||||
inventory_items.items[0].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 4)
|
||||
}).unwrap();
|
||||
inventory_items.items[1].with_stacked(|items| {
|
||||
assert_eq!(items.len(), 3)
|
||||
}).unwrap();
|
||||
|
||||
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let char = characters[0].as_ref().unwrap();
|
||||
|
@ -17,19 +17,20 @@ async fn test_mag_feed() {
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mag = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(0)
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
//equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
for _ in 0..7 {
|
||||
entity_gateway.create_item(
|
||||
|
||||
let mut monomates = Vec::new();
|
||||
for _ in 0..7usize {
|
||||
monomates.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -38,20 +39,32 @@ async fn test_mag_feed() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let equipped = item::EquippedEntity {
|
||||
weapon: None,
|
||||
armor: None,
|
||||
shield: None,
|
||||
unit: [None; 4],
|
||||
mag: Some(mag.id),
|
||||
};
|
||||
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
|
||||
|
||||
let mut inventory = Vec::new();
|
||||
inventory.push(mag.into());
|
||||
inventory.push(item::InventoryItemEntity::Stacked(monomates));
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inventory)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
|
||||
for _ in 0..7 {
|
||||
for _ in 0..7usize {
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerFeedMag(PlayerFeedMag {
|
||||
client: 0,
|
||||
target: 0,
|
||||
@ -60,18 +73,21 @@ async fn test_mag_feed() {
|
||||
})))).await.unwrap().for_each(drop);
|
||||
}
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
let mag = p1_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.level() == 7);
|
||||
assert!(mag.def() == 5);
|
||||
assert!(mag.pow() == 2);
|
||||
assert!(mag.dex() == 0);
|
||||
assert!(mag.mind() == 0);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_individual(|item| {
|
||||
match &item.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
println!("mag! {:?}", mag);
|
||||
assert!(mag.level() == 7);
|
||||
assert!(mag.def() == 5);
|
||||
assert!(mag.pow() == 2);
|
||||
assert!(mag.dex() == 0);
|
||||
assert!(mag.mind() == 0);
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -87,21 +103,21 @@ async fn test_mag_change_owner() {
|
||||
char2.section_id = SectionID::Whitill;
|
||||
entity_gateway.save_character(&char2).await.unwrap();
|
||||
|
||||
entity_gateway.create_item(
|
||||
let mag = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(0)
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![mag])).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
@ -128,15 +144,17 @@ async fn test_mag_change_owner() {
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap();
|
||||
let mag = p2_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.class == CharacterClass::FOmarl);
|
||||
assert!(mag.id == SectionID::Whitill);
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
||||
assert_eq!(inventory_items.items.len(), 1);
|
||||
inventory_items.items[0].with_individual(|item| {
|
||||
match &item.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.class == CharacterClass::FOmarl);
|
||||
assert!(mag.id == SectionID::Whitill);
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
|
||||
@ -153,12 +171,10 @@ async fn test_mag_cell() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
for _ in 0..1000 {
|
||||
for _ in 0..1000usize {
|
||||
let fed_tool = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool (
|
||||
@ -172,7 +188,7 @@ async fn test_mag_cell() {
|
||||
}).await.unwrap();
|
||||
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap();
|
||||
}
|
||||
entity_gateway.create_item(
|
||||
let mag_cell = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
@ -181,14 +197,22 @@ async fn test_mag_cell() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let equipped = item::EquippedEntity {
|
||||
weapon: None,
|
||||
armor: None,
|
||||
shield: None,
|
||||
unit: [None; 4],
|
||||
mag: Some(mag.id),
|
||||
};
|
||||
entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![mag, mag_cell])).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
@ -199,12 +223,13 @@ async fn test_mag_cell() {
|
||||
item_id: 0x10001,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
let mag = p1_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.mag == item::mag::MagType::Soniti);
|
||||
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
inventory_items.items[0].with_individual(|item| {
|
||||
match &item.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert_eq!(mag.mag, item::mag::MagType::Soniti);
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}).unwrap();
|
||||
}
|
||||
|
@ -18,8 +18,9 @@ async fn test_item_ids_reset_when_rejoining_rooms() {
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
|
||||
for slot in 0..3 {
|
||||
entity_gateway.create_item(
|
||||
let mut p1_inv = Vec::new();
|
||||
for _ in 0..3usize {
|
||||
p1_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -33,14 +34,13 @@ async fn test_item_ids_reset_when_rejoining_rooms() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
for slot in 0..10 {
|
||||
entity_gateway.create_item(
|
||||
let mut p2_inv = Vec::new();
|
||||
for _ in 0..10usize {
|
||||
p2_inv.push(entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
@ -54,15 +54,16 @@ async fn test_item_ids_reset_when_rejoining_rooms() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char2.id,
|
||||
slot: slot,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
}).await.unwrap());
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
|
||||
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
|
||||
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
|
||||
|
@ -19,9 +19,9 @@ async fn test_player_opens_weapon_shop() {
|
||||
char1.exp = 80000000;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -49,9 +49,9 @@ async fn test_player_opens_tool_shop() {
|
||||
char1.exp = 80000000;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -79,9 +79,9 @@ async fn test_player_opens_armor_shop() {
|
||||
char1.exp = 80000000;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -110,9 +110,9 @@ async fn test_player_buys_from_weapon_shop() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -135,8 +135,9 @@ async fn test_player_buys_from_weapon_shop() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 1);
|
||||
//let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 1);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -148,9 +149,9 @@ async fn test_player_buys_from_tool_shop() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -173,8 +174,8 @@ async fn test_player_buys_from_tool_shop() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 1);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 1);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -186,9 +187,9 @@ async fn test_player_buys_multiple_from_tool_shop() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -211,8 +212,12 @@ async fn test_player_buys_multiple_from_tool_shop() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 5);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 1);
|
||||
p1_items.items[0].with_stacked(|item| {
|
||||
assert_eq!(item.len(), 5);
|
||||
assert_eq!(item[0].item.item_type(), item::ItemType::Tool(item::tool::ToolType::Monomate));
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -224,9 +229,9 @@ async fn test_player_buys_from_armor_shop() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -249,8 +254,8 @@ async fn test_player_buys_from_armor_shop() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 1);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 1);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -267,9 +272,9 @@ async fn test_other_clients_see_purchase() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
@ -318,14 +323,12 @@ async fn test_other_clients_see_stacked_purchase() {
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
@ -362,9 +365,9 @@ async fn test_buying_item_without_enough_mseseta() {
|
||||
|
||||
let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -388,8 +391,8 @@ async fn test_buying_item_without_enough_mseseta() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert_eq!(c1.meseta, 0);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 0);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
@ -401,9 +404,9 @@ async fn test_player_double_buys_from_tool_shop() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -444,11 +447,20 @@ async fn test_player_double_buys_from_tool_shop() {
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.len(), 9);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
assert_eq!(p1_items.items.len(), 2);
|
||||
p1_items.items[0].with_stacked(|item| {
|
||||
assert_eq!(item.len(), 7);
|
||||
assert_eq!(item[0].item.item_type(), item::ItemType::Tool(item::tool::ToolType::Monomate));
|
||||
}).unwrap();
|
||||
p1_items.items[1].with_stacked(|item| {
|
||||
assert_eq!(item.len(), 2);
|
||||
assert_eq!(item[0].item.item_type(), item::ItemType::Tool(item::tool::ToolType::Dimate));
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_techs_disappear_from_shop_when_bought() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
@ -458,9 +470,9 @@ async fn test_techs_disappear_from_shop_when_bought() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -502,8 +514,12 @@ async fn test_techs_disappear_from_shop_when_bought() {
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items[0].item != p1_items[1].item);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
p1_items.items[0].with_individual(|item1| {
|
||||
p1_items.items[1].with_individual(|item2| {
|
||||
assert_ne!(item1, item2);
|
||||
}).unwrap();
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
// TOOD: this is not deterministic and can randomly fail
|
||||
@ -516,9 +532,9 @@ async fn test_units_disappear_from_shop_when_bought() {
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await.unwrap();
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
let mut ship = Box::new(ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
.build());
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
@ -560,6 +576,10 @@ async fn test_units_disappear_from_shop_when_bought() {
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap();
|
||||
assert!(p1_items[0].item != p1_items[1].item);
|
||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||
p1_items.items[0].with_individual(|item1| {
|
||||
p1_items.items[1].with_individual(|item2| {
|
||||
assert_ne!(item1, item2);
|
||||
}).unwrap();
|
||||
}).unwrap();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user