You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4382 lines
176 KiB
4382 lines
176 KiB
use std::convert::TryInto;
|
|
use elseware::common::serverstate::{ClientId, ServerState};
|
|
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
|
use elseware::entity::item;
|
|
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
|
use elseware::entity::item::{Meseta, ItemEntity};
|
|
use elseware::ship::items::transaction::TransactionError;
|
|
use elseware::ship::packet::handler::trade::TradeError;
|
|
|
|
use libpso::packet::ship::*;
|
|
use libpso::packet::messages::*;
|
|
|
|
#[path = "common.rs"]
|
|
mod common;
|
|
use common::*;
|
|
|
|
async fn initialize_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
|
|
ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client1.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(client2, &RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client2.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Respond, 0)
|
|
})))).await.unwrap().for_each(drop);
|
|
}
|
|
|
|
async fn confirm_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
|
|
ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client1.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Confirm
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(client2, &RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client2.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Confirm
|
|
})))).await.unwrap().for_each(drop);
|
|
}
|
|
|
|
async fn finalconfirm_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) {
|
|
ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client1.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::FinalConfirm
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(client2, &RecvShipPacket::DirectMessage(DirectMessage::new(client1.0 as u32 -1, GameMessage::TradeRequest(TradeRequest {
|
|
client: client2.0 as u8 -1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::FinalConfirm
|
|
})))).await.unwrap().for_each(drop);
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct TradeItemBuilder {
|
|
count: usize,
|
|
items: [TradeItem; 32],
|
|
}
|
|
|
|
impl TradeItemBuilder {
|
|
fn individual(mut self, item: &elseware::entity::item::InventoryItemEntity, item_id: u32) -> Self {
|
|
let idata = item.with_individual(|i| i.item.as_client_bytes()).unwrap();
|
|
self.items[self.count] = TradeItem {
|
|
item_data: idata[0..12].try_into().unwrap(),
|
|
item_id: item_id,
|
|
item_data2: idata[12..16].try_into().unwrap(),
|
|
};
|
|
|
|
self.count += 1;
|
|
self
|
|
}
|
|
|
|
fn stacked(mut self, item: &elseware::entity::item::InventoryItemEntity, item_id: u32, amount: u8) -> Self {
|
|
let idata = item
|
|
.with_stacked(|i| i[0].item.tool().unwrap().as_stacked_bytes(i.len()))
|
|
.map(|mut data| {
|
|
data[5] = amount;
|
|
data
|
|
})
|
|
.unwrap();
|
|
self.items[self.count] = TradeItem {
|
|
item_data: idata[0..12].try_into().unwrap(),
|
|
item_id: item_id,
|
|
item_data2: idata[12..16].try_into().unwrap(),
|
|
};
|
|
|
|
self.count += 1;
|
|
self
|
|
}
|
|
|
|
fn meseta(mut self, amount: usize) -> Self {
|
|
self.items[self.count] = TradeItem {
|
|
item_data: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
item_id: 0xFFFFFFFF,
|
|
item_data2: u32::to_le_bytes(amount as u32),
|
|
};
|
|
|
|
self.count += 1;
|
|
self
|
|
}
|
|
|
|
fn build(self) -> [TradeItem; 32] {
|
|
self.items
|
|
}
|
|
}
|
|
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_one_individual_item() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 0);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_player2_to_player1() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p2_inv = Vec::new();
|
|
p2_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 0);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p2_items.items[0], 0x210000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_reverse_trade_ack_order() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(2), ClientId(1)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(2), ClientId(1)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(2), ClientId(1)).await;
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 0);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_one_stacked_item() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 0);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_partial_stacked_item() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 1)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 1);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_individual_both() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap()];
|
|
let p2_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap()];
|
|
|
|
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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p2_items.items[0], 0x210000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert!(matches!(p1_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Handgun, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_stacked_both() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monofluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 3)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p2_items.items[0], 0x210000, 3)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 3);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_partial_stack_both() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monofluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 1)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p2_items.items[0], 0x210000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
amount: 2,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
amount: 1,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert_eq!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
assert!(matches!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_same_stacked_item_to_eachother() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack = futures::future::join_all((0..4).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 3)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 1)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p2_items.items[0], 0x210000, 3)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
amount: 3,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
amount: 1,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 5);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_stacked_when_already_have_partial_stack() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810001,
|
|
item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810001,
|
|
item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
amount: 2,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 5);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_individual_for_stacked() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap()];
|
|
|
|
let p2_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
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_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p2_items.items[0], 0x210000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[7], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_multiple_individual() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Buster,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
];
|
|
let p2_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Autogun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
];
|
|
|
|
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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p2_items.items[0], 0x210000)
|
|
.individual(&p2_items.items[1], 0x210001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 14);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_data: [0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // handgun
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810003,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[7], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810003,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[8], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[9], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810004,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[10], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_data: [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], // saber
|
|
item_id: 0x810004,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[12], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[13], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
assert!(matches!(p1_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Handgun, ..}), ..}));
|
|
assert!(matches!(p1_items.items[1].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Autogun, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Saber, ..}), ..}));
|
|
assert!(matches!(p2_items.items[1].with_individual(|i| i.clone()).unwrap(), item::ItemEntity{item: item::ItemDetail::Weapon(item::weapon::Weapon {weapon: item::weapon::WeaponType::Buster, ..}), ..}));
|
|
}
|
|
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_multiple_stacked() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack1 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
let p1_stack2 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Dimate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack1 = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monofluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
let p2_stack2 = futures::future::join_all((0..3).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Difluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack1, p2_stack2])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 3)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210001, 3)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.stacked(&p1_items.items[1], 0x10001, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p2_items.items[0], 0x210000, 3)
|
|
.stacked(&p2_items.items[1], 0x210001, 3)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 14);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[4], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 0,
|
|
item_id: 0x810002,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[5], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 1,
|
|
item_id: 0x210001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[6], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810003,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[7], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810003,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[8], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10000,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[9], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810004,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[10], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {
|
|
client: 1,
|
|
item_id: 0x810004,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[11], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
|
client: 0,
|
|
item_id: 0x10001,
|
|
..
|
|
}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[12], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[13], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 3);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
assert_eq!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 3);
|
|
assert!(matches!(p1_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Difluid, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Dimate, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_not_enough_inventory_space_individual() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.err().unwrap();
|
|
match ack.downcast::<TransactionError<anyhow::Error>>().unwrap() {
|
|
TransactionError::Action(a) => {
|
|
assert_eq!(a.downcast::<TradeError>().unwrap(), TradeError::NoInventorySpace);
|
|
},
|
|
_ => panic!()
|
|
}
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_not_enough_inventory_space_stacked() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.err().unwrap();
|
|
match ack.downcast::<TransactionError<anyhow::Error>>().unwrap() {
|
|
TransactionError::Action(a) => {
|
|
assert_eq!(a.downcast::<TradeError>().unwrap(), TradeError::NoInventorySpace);
|
|
},
|
|
_ => panic!()
|
|
}
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_stack_too_big() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..8).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_stack = futures::future::join_all((0..7).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(vec![p2_stack])).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 4)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 4)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.err().unwrap();
|
|
match ack.downcast::<TransactionError<anyhow::Error>>().unwrap() {
|
|
TransactionError::Action(a) => {
|
|
assert_eq!(a.downcast::<TradeError>().unwrap(), TradeError::NoStackSpace);
|
|
},
|
|
_ => panic!()
|
|
}
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.len()).unwrap(), 8);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.len()).unwrap(), 7);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_meseta() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.meseta(23)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
|
assert_eq!(c1_meseta, Meseta(2300));
|
|
let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
|
|
assert_eq!(c2_meseta, Meseta(23));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_too_much_meseta() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
|
|
entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 2000)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.meseta(2000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
|
assert_eq!(c1_meseta, Meseta(4000));
|
|
let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
|
|
assert_eq!(c2_meseta, Meseta(999000));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_invalid_amount_of_meseta() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
|
|
entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5000)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.meseta(5000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
|
assert_eq!(c1_meseta, Meseta(4000));
|
|
let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
|
|
assert_eq!(c2_meseta, Meseta(999000));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_trade_meseta_request_and_items_dont_match() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(4000)).await.unwrap();
|
|
entity_gateway.set_character_meseta(&char2.id, Meseta(999000)).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 50)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.meseta(23)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
|
assert_eq!(c1_meseta, Meseta(4000));
|
|
let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
|
|
assert_eq!(c2_meseta, Meseta(999000));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_player_declined_trade() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Cancel
|
|
})))).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_back_out_of_trade_last_minute() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Cancel
|
|
})))).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_valid_trade_when_both_inventories_are_full() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
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(), 30);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p2_items.items[0], 0x210000)
|
|
.individual(&p2_items.items[1], 0x210001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 14);
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 30);
|
|
assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 28);
|
|
assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 2);
|
|
assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 28);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_invalid_trade_when_both_inventories_are_full() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p2_inv = futures::future::join_all((0..30).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}
|
|
).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
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());
|
|
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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
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(), 30);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10002, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x210001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.individual(&p1_items.items[1], 0x10002)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 3,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p2_items.items[0], 0x210000)
|
|
.individual(&p2_items.items[1], 0x210001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.err().unwrap();
|
|
match ack.downcast::<TransactionError<anyhow::Error>>().unwrap() {
|
|
TransactionError::Action(a) => {
|
|
assert_eq!(a.downcast::<TradeError>().unwrap(), TradeError::NoInventorySpace);
|
|
},
|
|
_ => panic!()
|
|
}
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 30);
|
|
assert_eq!(p1_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Saber, ..}, ..))).count(), 30);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 30);
|
|
assert_eq!(p2_items.items.iter().filter(|i| matches!(i.individual().unwrap().item, item::ItemDetail::Weapon(item::weapon::Weapon { weapon: item::weapon::WeaponType::Handgun, ..}, ..))).count(), 30);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_client_tries_to_start_two_trades() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a").await;
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.build());
|
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
|
log_in_char(&mut ship, ClientId(3), "a3", "a").await;
|
|
|
|
join_lobby(&mut ship, ClientId(1)).await;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
join_lobby(&mut ship, ClientId(3)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
join_room(&mut ship, ClientId(3), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 0,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
|
|
})))).await.err().unwrap();
|
|
assert_eq!(ack.downcast::<TradeError>().unwrap(), TradeError::ClientAlreadyInTrade);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_client_tries_trading_with_client_already_trading() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 (_user2, _char3) = new_user_character(&mut entity_gateway, "a3", "a").await;
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.build());
|
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
|
log_in_char(&mut ship, ClientId(3), "a3", "a").await;
|
|
|
|
join_lobby(&mut ship, ClientId(1)).await;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
join_lobby(&mut ship, ClientId(3)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
join_room(&mut ship, ClientId(3), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
let ack = ship.handle(ClientId(3), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::TradeRequest(TradeRequest {
|
|
client: 2,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 0)
|
|
})))).await.err().unwrap();
|
|
assert_eq!(ack.downcast::<TradeError>().unwrap(), TradeError::OtherAlreadyInTrade);
|
|
|
|
let ack = ship.handle(ClientId(3), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 2,
|
|
target: 0,
|
|
trade: TradeRequestCommand::Initialize(TradeRequestInitializeCommand::Initialize, 1)
|
|
})))).await.err().unwrap();
|
|
assert_eq!(ack.downcast::<TradeError>().unwrap(), TradeError::OtherAlreadyInTrade);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_add_then_remove_individual_item() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
for _ in 0..2 {
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
}
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::RemoveItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_add_then_remove_stacked_item() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack1 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p1_stack2 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monofluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::RemoveItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[1], 0x10001, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 1);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_add_then_remove_partial_stack() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack1 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
let p1_stack2 = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monofluid,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack1, p1_stack2])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 2);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::RemoveItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 1)
|
|
.stacked(&p1_items.items[1], 0x10001, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 2,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 8);
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
assert_eq!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert!(matches!(p1_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 2);
|
|
assert_eq!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap().len(), 1);
|
|
assert_eq!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap().len(), 2);
|
|
assert!(matches!(p2_items.items[0].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monomate, ..}), ..}));
|
|
assert!(matches!(p2_items.items[1].with_stacked(|i| i.clone()).unwrap()[0], item::ItemEntity{item: item::ItemDetail::Tool(item::tool::Tool {tool: item::tool::ToolType::Monofluid, ..}), ..}));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_add_then_remove_meseta() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(2323)).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 23)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::RemoveItem(0xFFFFFF01, 5)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.meseta(18)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
|
assert_eq!(c1_meseta, Meseta(2305));
|
|
let c2_meseta = entity_gateway.get_character_meseta(&char2.id).await.unwrap();
|
|
assert_eq!(c2_meseta, Meseta(18));
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_items_to_trade_data_does_not_match() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let new_item = item::InventoryItemEntity::Individual(
|
|
ItemEntity {
|
|
id: p1_items.items[0].with_individual(|i| i.id).unwrap(),
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 2,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
)});
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&new_item, 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_items_to_trade_id_does_not_match() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_stack_is_same_amount_in_request_and_items_to_trade() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 2)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 1)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_stack_is_same_amount_in_request_and_items_to_trade2() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_stack = futures::future::join_all((0..2).map(|_| {
|
|
let mut entity_gateway = entity_gateway.clone();
|
|
async move {
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Tool(
|
|
item::tool::Tool {
|
|
tool: item::tool::ToolType::Monomate,
|
|
}
|
|
)
|
|
}).await
|
|
}}))
|
|
.await
|
|
.into_iter()
|
|
.collect::<Result<Vec<ItemEntity>,_>>()
|
|
.unwrap();
|
|
|
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![p1_stack])).await.unwrap();
|
|
entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(Vec::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.stacked(&p1_items.items[0], 0x10000, 2)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_items_to_trade_count_less_than() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Brand,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Buster,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
];
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_items_to_trade_count_greater_than() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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.set_character_meseta(&char1.id, Meseta(23)).await.unwrap();
|
|
|
|
let p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Brand,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Buster,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
];
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0xFFFFFF01, 5)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.meseta(5)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 4,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_items_to_trade_count_mismatch_with_meseta() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = vec![
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Saber,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Brand,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Buster,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap(),
|
|
];
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10001, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.individual(&p1_items.items[1], 0x10001)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 3,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::CancelTrade(..))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::CancelTrade(..))));
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 3);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|
|
|
|
#[async_std::test]
|
|
async fn test_dropping_item_after_trade() {
|
|
let mut entity_gateway = InMemoryGateway::default();
|
|
|
|
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 p1_inv = Vec::new();
|
|
p1_inv.push(entity_gateway.create_item(
|
|
item::NewItemEntity {
|
|
item: item::ItemDetail::Weapon(
|
|
item::weapon::Weapon {
|
|
weapon: item::weapon::WeaponType::Handgun,
|
|
grind: 0,
|
|
special: None,
|
|
attrs: [None, None, None],
|
|
tekked: true,
|
|
}
|
|
),
|
|
}).await.unwrap());
|
|
|
|
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::<item::InventoryItemEntity>::new())).await.unwrap();
|
|
|
|
let mut ship = Box::new(ShipServerState::builder()
|
|
.gateway(entity_gateway.clone())
|
|
.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;
|
|
join_lobby(&mut ship, ClientId(2)).await;
|
|
|
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
|
join_room(&mut ship, ClientId(2), 0).await;
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 1);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
|
|
initialize_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(1, GameMessage::TradeRequest(TradeRequest {
|
|
client: 1,
|
|
target: 0,
|
|
trade: TradeRequestCommand::AddItem(0x10000, 1)
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
confirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
finalconfirm_trade(&mut ship, ClientId(1), ClientId(2)).await;
|
|
|
|
let titems = TradeItemBuilder::default()
|
|
.individual(&p1_items.items[0], 0x10000)
|
|
.build();
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 1,
|
|
unknown2: 0,
|
|
count: 1,
|
|
items: titems,
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::ItemsToTrade(ItemsToTrade {
|
|
trade_target: 0,
|
|
unknown2: 0,
|
|
count: 0,
|
|
items: Default::default(),
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 2);
|
|
assert!(matches!(ack[0], (ClientId(2), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
assert!(matches!(ack[1], (ClientId(1), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {}))));
|
|
|
|
let ack = ship.handle(ClientId(1), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 0);
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
|
})).await.unwrap().collect::<Vec<_>>();
|
|
assert_eq!(ack.len(), 5);
|
|
assert!(matches!(ack[0], (ClientId(1), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[1], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::CreateItem(CreateItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[2], (ClientId(2), SendShipPacket::Message(Message {
|
|
msg: GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {..}),
|
|
..
|
|
}))));
|
|
assert!(matches!(ack[3], (ClientId(2), SendShipPacket::TradeSuccessful {..})));
|
|
assert!(matches!(ack[4], (ClientId(1), SendShipPacket::TradeSuccessful {..})));
|
|
|
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
|
client: 0,
|
|
target: 0,
|
|
unknown1: 0,
|
|
map_area: 0,
|
|
item_id: 0x810001,
|
|
x: 0.0,
|
|
y: 0.0,
|
|
z: 0.0,
|
|
})))).await.unwrap().for_each(drop);
|
|
|
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
|
assert_eq!(p1_items.items.len(), 0);
|
|
let p2_items = entity_gateway.get_character_inventory(&char2.id).await.unwrap();
|
|
assert_eq!(p2_items.items.len(), 0);
|
|
}
|