Browse Source

e q u i p r e f a c t o r

pbs
jake 4 years ago
parent
commit
6e2fab31f0
  1. 5
      src/bin/main.rs
  2. 24
      src/entity/gateway/postgres/migrations/V0001__initial.sql
  3. 89
      src/entity/gateway/postgres/models.rs
  4. 158
      src/entity/gateway/postgres/postgres.rs
  5. 3
      src/entity/item/unit.rs
  6. 2
      src/ship/drops/generic_unit.rs
  7. 1
      src/ship/drops/rare_drop_table.rs
  8. 116
      src/ship/items/inventory.rs
  9. 109
      src/ship/items/manager.rs
  10. 26
      src/ship/packet/handler/message.rs
  11. 1
      src/ship/shops/armor.rs
  12. 6
      tests/test_item_actions.rs

5
src/bin/main.rs

@ -301,7 +301,6 @@ fn main() {
item::unit::Unit {
unit: item::unit::UnitType::PriestMind,
modifier: Some(item::unit::UnitModifier::Minus),
armor_slot: 0, // TODO: get rid of this
}
),
location: ItemLocation::Inventory {
@ -315,7 +314,6 @@ fn main() {
item::unit::Unit {
unit: item::unit::UnitType::PriestMind,
modifier: Some(item::unit::UnitModifier::Minus),
armor_slot: 1,
}
),
location: ItemLocation::Inventory {
@ -329,7 +327,6 @@ fn main() {
item::unit::Unit {
unit: item::unit::UnitType::PriestMind,
modifier: Some(item::unit::UnitModifier::Minus),
armor_slot: 2,
}
),
location: ItemLocation::Inventory {
@ -343,7 +340,6 @@ fn main() {
item::unit::Unit {
unit: item::unit::UnitType::PriestMind,
modifier: Some(item::unit::UnitModifier::Minus),
armor_slot: 3,
}
),
location: ItemLocation::Inventory {
@ -373,6 +369,7 @@ fn main() {
let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13]);
entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap();
entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap();
}
info!("[patch] starting server");

24
src/entity/gateway/postgres/migrations/V0001__initial.sql

@ -122,3 +122,27 @@ create table mag_modifier (
modifier jsonb not null,
created_at timestamptz default current_timestamp not null
);
create table equipped (
pchar integer references player_character (id) unique not null,
weapon integer references item (id),
armor integer references item (id),
shield integer references item (id),
unit0 integer references item (id),
unit1 integer references item (id),
unit2 integer references item (id),
unit3 integer references item (id),
mag integer references item (id)
);
create table inventory (
pchar integer references player_character (id) unique not null,
items jsonb not null
);
create table bank (
pchar integer references player_character (id) not null,
items jsonb not null,
name varchar(128) not null,
unique (pchar, name)
);

89
src/entity/gateway/postgres/models.rs

@ -383,7 +383,6 @@ impl Into<shield::Shield> for PgShield {
pub struct PgUnit {
unit: unit::UnitType,
modifier: Option<unit::UnitModifier>,
//armor_slot: u8,
}
impl From<unit::Unit> for PgUnit {
@ -391,7 +390,6 @@ impl From<unit::Unit> for PgUnit {
PgUnit {
unit: other.unit,
modifier: other.modifier,
//armor_slot: other.armor_slot,
}
}
}
@ -401,7 +399,6 @@ impl Into<unit::Unit> for PgUnit {
unit::Unit {
unit: self.unit,
modifier: self.modifier,
armor_slot: 0,
}
}
}
@ -573,9 +570,6 @@ pub struct PgItem {
pub enum PgItemLocationDetail {
Inventory {
character_id: u32,
//#[serde(skip_serializing)]
//slot: usize,
//equipped: bool,
},
Bank {
character_id: u32,
@ -676,6 +670,12 @@ pub struct PgMagModifier {
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgItemEntity {
pub id: i32,
pub item: sqlx::types::Json<PgItemDetail>,
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgItemWithLocation {
pub id: i32,
@ -683,6 +683,16 @@ pub struct PgItemWithLocation {
pub location: sqlx::types::Json<PgItemLocationDetail>,
}
impl Into<ItemEntity> for PgItemWithLocation {
fn into(self) -> ItemEntity {
ItemEntity {
id: ItemEntityId(self.id as u32),
item: self.item.0.into(),
location: self.location.0.into(),
}
}
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgMagModifierWithParameters {
@ -691,3 +701,70 @@ pub struct PgMagModifierWithParameters {
pub feed: Option<sqlx::types::Json<PgTool>>,
pub cell: Option<sqlx::types::Json<PgTool>>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PgInventoryItemEntity {
Individual(i32),
Stacked(Vec<i32>),
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgInventoryEntity {
pub pchar: i32,
pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgBankEntity {
pub pchar: i32,
pub items: sqlx::types::Json<Vec<PgInventoryItemEntity>>,
pub name: String,
}
#[derive(Debug, sqlx::FromRow)]
pub struct PgEquipped {
pchar: i32,
weapon: Option<i32>,
armor: Option<i32>,
shield: Option<i32>,
unit0: Option<i32>,
unit1: Option<i32>,
unit2: Option<i32>,
unit3: Option<i32>,
mag: Option<i32>,
}
impl Into<EquippedEntity> for PgEquipped {
fn into(self) -> EquippedEntity {
EquippedEntity {
weapon: self.weapon.map(|i| ItemEntityId(i as u32)),
armor: self.armor.map(|i| ItemEntityId(i as u32)),
shield: self.shield.map(|i| ItemEntityId(i as u32)),
unit: [self.unit0.map(|i| ItemEntityId(i as u32)),
self.unit1.map(|i| ItemEntityId(i as u32)),
self.unit2.map(|i| ItemEntityId(i as u32)),
self.unit3.map(|i| ItemEntityId(i as u32)),
],
mag: self.mag.map(|i| ItemEntityId(i as u32)),
}
}
}
impl From<(CharacterEntityId, EquippedEntity)> for PgEquipped {
fn from(char_equips: (CharacterEntityId, EquippedEntity)) -> PgEquipped {
PgEquipped {
pchar: char_equips.0.0 as i32,
weapon: char_equips.1.weapon.map(|i| i.0 as i32),
armor: char_equips.1.armor.map(|i| i.0 as i32),
shield: char_equips.1.shield.map(|i| i.0 as i32),
unit0: char_equips.1.unit[0].map(|i| i.0 as i32),
unit1: char_equips.1.unit[1].map(|i| i.0 as i32),
unit2: char_equips.1.unit[2].map(|i| i.0 as i32),
unit3: char_equips.1.unit[3].map(|i| i.0 as i32),
mag: char_equips.1.mag.map(|i| i.0 as i32),
}
}
}

158
src/entity/gateway/postgres/postgres.rs

@ -272,7 +272,22 @@ impl EntityGateway for PostgresGateway {
}
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
unimplemented!();
let mut tx = self.pool.begin().await?;
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
.fetch_one(&mut tx).await?;
let location = sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
.bind(new_item.id)
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
.fetch_one(&mut tx).await?;
tx.commit().await?;
Ok(ItemEntity {
id: ItemEntityId(new_item.id as u32),
item: new_item.item.0.into(),
location: location.location.0.into(),
})
/*
let mut tx = self.pool.begin().await?;
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
@ -324,7 +339,12 @@ impl EntityGateway for PostgresGateway {
}
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
unimplemented!();
sqlx::query("insert into item_location (item, location) values ($1, $2)")
.bind(item_id.0)
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
.execute(&self.pool).await?;
Ok(())
/*
let mut tx = self.pool.begin().await?;
if let ItemLocation::Inventory{slot, ..} = &item_location {
@ -417,27 +437,137 @@ impl EntityGateway for PostgresGateway {
).await)
}
*/
async fn get_character_inventory(&mut self, _char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
unimplemented!();
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
let inventory = sqlx::query_as::<_, PgInventoryEntity>("select * from inventory where pchar = $1")
.bind(char_id.0)
.fetch_one(&self.pool).await?;
// TODO: inefficient
let mut real_inventory = Vec::new();
for inv_item in inventory.items.0.into_iter() {
match inv_item {
PgInventoryItemEntity::Individual(item) => {
let entity = sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
.bind(item)
.fetch_one(&self.pool).await
.map(|item| item.into())?;
real_inventory.push(InventoryItemEntity::Individual(entity));
},
PgInventoryItemEntity::Stacked(items) => {
let mut stacked_item = Vec::new();
for s_item in items {
stacked_item.push(sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
.bind(s_item)
.fetch_one(&self.pool).await
.map(|item| item.into())?)
}
real_inventory.push(InventoryItemEntity::Stacked(stacked_item));
}
}
}
async fn get_character_bank(&mut self, _char_id: &CharacterEntityId, _bank_name: BankName) -> Result<BankEntity, GatewayError> {
unimplemented!();
Ok(InventoryEntity::new(real_inventory))
}
async fn set_character_inventory(&mut self, _char_id: &CharacterEntityId, _inventory: &InventoryEntity) -> Result<(), GatewayError> {
unimplemented!();
async fn get_character_bank(&mut self, char_id: &CharacterEntityId, bank_name: BankName) -> Result<BankEntity, GatewayError> {
let bank = sqlx::query_as::<_, PgInventoryEntity>("select * from bank where pchar = $1 and name = $2")
.bind(char_id.0)
.bind(bank_name.0)
.fetch_one(&self.pool).await?;
// TODO: inefficient
let mut real_bank = Vec::new();
for bank_item in bank.items.0.into_iter() {
match bank_item {
PgInventoryItemEntity::Individual(item) => {
let entity = sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
.bind(item)
.fetch_one(&self.pool).await
.map(|item| item.into())?;
real_bank.push(BankItemEntity::Individual(entity));
},
PgInventoryItemEntity::Stacked(items) => {
let mut stacked_item = Vec::new();
for s_item in items {
stacked_item.push(sqlx::query_as::<_, PgItemWithLocation>("select item.id, item.item, item_location.location from item join item_location on item.id = item_location.item where id = $1")
.bind(s_item)
.fetch_one(&self.pool).await
.map(|item| item.into())?)
}
real_bank.push(BankItemEntity::Stacked(stacked_item));
}
}
}
Ok(BankEntity::new(real_bank))
}
async fn set_character_bank(&mut self, _char_id: &CharacterEntityId, _inventory: &BankEntity, _bank_name: BankName) -> Result<(), GatewayError> {
unimplemented!();
async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> {
let inventory = inventory.items.iter()
.map(|item| {
match item {
InventoryItemEntity::Individual(item) => {
PgInventoryItemEntity::Individual(item.id.0 as i32)
},
InventoryItemEntity::Stacked(items) => {
PgInventoryItemEntity::Stacked(items.iter().map(|i| i.id.0 as i32).collect())
},
}
})
.collect::<Vec<_>>();
async fn get_character_equips(&mut self, _char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> {
unimplemented!();
sqlx::query("insert into inventory (pchar, items) values ($1, $2) on conflict (pchar) do update set items = $2")
.bind(char_id.0)
.bind(sqlx::types::Json(inventory))
.execute(&self.pool)
.await?;
Ok(())
}
async fn set_character_equips(&mut self, _char_id: &CharacterEntityId, _equips: &EquippedEntity) -> Result<(), GatewayError> {
unimplemented!();
async fn set_character_bank(&mut self, char_id: &CharacterEntityId, bank: &BankEntity, bank_name: BankName) -> Result<(), GatewayError> {
let bank = bank.items.iter()
.map(|item| {
match item {
BankItemEntity::Individual(item) => {
PgInventoryItemEntity::Individual(item.id.0 as i32)
},
BankItemEntity::Stacked(items) => {
PgInventoryItemEntity::Stacked(items.iter().map(|i| i.id.0 as i32).collect())
},
}
})
.collect::<Vec<_>>();
sqlx::query("insert into bank (pchar, items, name) values ($1, $2, $3) on conflict (pchar, name) do update set items = $2")
.bind(char_id.0)
.bind(sqlx::types::Json(bank))
.bind(bank_name.0)
.execute(&self.pool)
.await?;
Ok(())
}
async fn get_character_equips(&mut self, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> {
let equips = sqlx::query_as::<_, PgEquipped>("select * from equipped where pchar = $1")
.bind(char_id.0)
.fetch_one(&self.pool)
.await?;
Ok(equips.into())
}
async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equips: &EquippedEntity) -> Result<(), GatewayError> {
sqlx::query(r#"insert into equipped (pchar, weapon, armor, shield, unit0, unit1, unit2, unit3, mag) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
on conflict (pchar) do update set weapon=$2, armor=$3, shield=$4, unit0=$5, unit1=$6, unit2=$7, unit3=$8, mag=$9"#)
.bind(char_id.0)
.bind(equips.weapon.map(|i| i.0 as i32))
.bind(equips.armor.map(|i| i.0 as i32))
.bind(equips.shield.map(|i| i.0 as i32))
.bind(equips.unit[0].map(|i| i.0 as i32))
.bind(equips.unit[1].map(|i| i.0 as i32))
.bind(equips.unit[2].map(|i| i.0 as i32))
.bind(equips.unit[3].map(|i| i.0 as i32))
.bind(equips.mag.map(|i| i.0 as i32))
.execute(&self.pool)
.await?;
Ok(())
}
}

3
src/entity/item/unit.rs

@ -335,7 +335,6 @@ pub enum UnitModifier {
pub struct Unit {
pub unit: UnitType,
pub modifier: Option<UnitModifier>,
pub armor_slot: u8,
}
@ -362,7 +361,6 @@ impl Unit {
},
}
}
result[4] = self.armor_slot;
result
}
@ -380,7 +378,6 @@ impl Unit {
Ok(Unit{
unit: u.unwrap(),
modifier: m,
armor_slot: data[4],
})
}
else {

2
src/ship/drops/generic_unit.rs

@ -89,7 +89,6 @@ impl GenericUnitTable {
ItemDropType::Unit(Unit {
unit: unit_type,
modifier: unit_modifier,
armor_slot: 0,
})
})
}
@ -117,7 +116,6 @@ mod test {
assert!(gut.get_drop(&area, &mut rng) == Some(ItemDropType::Unit(Unit {
unit: unit,
modifier: umod,
armor_slot: 0,
})));
}
}

1
src/ship/drops/rare_drop_table.rs

@ -128,7 +128,6 @@ impl RareDropTable {
ItemDropType::Unit(Unit {
unit: unit,
modifier: None,
armor_slot: 0,
})
},
RareDropItem::Tool(tool) => {

116
src/ship/items/inventory.rs

@ -14,12 +14,12 @@ const INVENTORY_CAPACITY: usize = 30;
#[derive(Debug, Clone)]
pub struct InventorySlot(pub usize);
#[derive(Debug, Clone)]
pub struct IndividualInventoryItem {
pub entity_id: ItemEntityId,
pub item_id: ClientItemId,
pub item: ItemDetail,
pub equipped: bool,
}
impl IndividualInventoryItem {
@ -154,17 +154,6 @@ impl InventoryItem {
}
}
pub fn equipped(&self) -> bool {
match self {
InventoryItem::Individual(individual_inventory_item) => {
individual_inventory_item.equipped
},
InventoryItem::Stacked(_) => {
false
}
}
}
pub fn as_client_bytes(&self) -> [u8; 16] {
match self {
InventoryItem::Individual(item) => {
@ -353,13 +342,15 @@ impl<'a> InventoryItemHandle<'a> {
pub struct CharacterInventory {
item_id_counter: u32,
items: Vec<InventoryItem>,
equipped: EquippedEntity,
}
impl CharacterInventory {
pub fn new(items: Vec<InventoryItem>) -> CharacterInventory {
pub fn new(items: Vec<InventoryItem>, equipped: &EquippedEntity) -> CharacterInventory {
CharacterInventory{
item_id_counter: 0,
items: items,
equipped: equipped.clone(),
}
}
@ -378,10 +369,22 @@ impl CharacterInventory {
inventory[slot].data1.copy_from_slice(&bytes[0..12]);
inventory[slot].data2.copy_from_slice(&bytes[12..16]);
inventory[slot].item_id = item.item_id().0;
// does this do anything?
inventory[slot].equipped = if item.equipped() { 1 } else { 0 };
// because this actually equips the item
inventory[slot].flags |= if item.equipped() { 8 } else { 0 };
inventory[slot].equipped = 0;
inventory[slot].flags = 0;
if let InventoryItem::Individual(individual_item) = item {
if self.equipped.is_equipped(&individual_item.entity_id) {
if let ItemDetail::Unit(_) = individual_item.item {
inventory[slot].data1[4] = self.equipped.unit.iter()
.enumerate()
.find(|(_, u_id)| **u_id == Some(individual_item.entity_id))
.map(|(a, b)| a)
.unwrap_or(0) as u8
}
inventory[slot].equipped = 1;
inventory[slot].flags |= 8;
}
}
inventory
})
}
@ -413,7 +416,7 @@ impl CharacterInventory {
.filter(|(_, item)| {
if let InventoryItem::Individual(individual_inventory_item) = item {
if let ItemDetail::Mag(_) = &individual_inventory_item.item {
return individual_inventory_item.equipped
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
}
}
false
@ -431,7 +434,7 @@ impl CharacterInventory {
.filter(|(_, item)| {
if let InventoryItem::Individual(individual_inventory_item) = item {
if let ItemDetail::Armor(_) = &individual_inventory_item.item {
return individual_inventory_item.equipped
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
}
}
false
@ -449,7 +452,7 @@ impl CharacterInventory {
.filter(|(_, item)| {
if let InventoryItem::Individual(individual_inventory_item) = item {
if let ItemDetail::Shield(_) = &individual_inventory_item.item {
return individual_inventory_item.equipped
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
}
}
false
@ -467,7 +470,7 @@ impl CharacterInventory {
.filter(|(_, item)| {
if let InventoryItem::Individual(individual_inventory_item) = item {
if let ItemDetail::Weapon(_) = &individual_inventory_item.item {
return individual_inventory_item.equipped
return self.equipped.is_equipped(&individual_inventory_item.entity_id)
}
}
false
@ -509,7 +512,6 @@ impl CharacterInventory {
entity_id: floor_item.entity_id,
item_id: floor_item.item_id,
item: floor_item.item.clone(),
equipped: false,
}));
if let Some(InventoryItem::Individual(new_item)) = self.items.last() {
@ -573,7 +575,6 @@ impl CharacterInventory {
entity_id: individual_bank_item.entity_id,
item_id: individual_bank_item.item_id,
item: individual_bank_item.item.clone(),
equipped: false,
}));
(true, self.count()-1)
},
@ -582,7 +583,7 @@ impl CharacterInventory {
.enumerate()
.find_map(|(index, item)| {
if let InventoryItem::Stacked(stacked_inventory_item) = item {
if stacked_inventory_item.tool == stacked_inventory_item.tool {
if stacked_bank_item.tool == stacked_inventory_item.tool {
return Some((index, stacked_inventory_item))
}
}
@ -639,6 +640,53 @@ impl CharacterInventory {
self.items = sorted_items;
}
pub fn equip(&mut self, id: &ClientItemId, equip_slot: u8) {
for item in &self.items {
if let InventoryItem::Individual(inventory_item) = item {
if inventory_item.item_id == *id {
match inventory_item.item {
ItemDetail::Weapon(_) => self.equipped.weapon = Some(inventory_item.entity_id),
ItemDetail::Armor(_) => self.equipped.armor = Some(inventory_item.entity_id),
ItemDetail::Shield(_) => self.equipped.shield = Some(inventory_item.entity_id),
ItemDetail::Unit(_) => {
if let Some(unit) = self.equipped.unit.get_mut(equip_slot as usize) {
*unit = Some(inventory_item.entity_id)
}
}
ItemDetail::Mag(_) => self.equipped.mag = Some(inventory_item.entity_id),
_ => {}
}
}
}
}
}
pub fn unequip(&mut self, id: &ClientItemId) {
for item in &self.items {
if let InventoryItem::Individual(inventory_item) = item {
if inventory_item.item_id == *id {
match inventory_item.item {
ItemDetail::Weapon(_) => self.equipped.weapon = None,
ItemDetail::Armor(_) => {
self.equipped.armor = None;
self.equipped.unit = [None; 4];
}
ItemDetail::Shield(_) => self.equipped.shield = None,
ItemDetail::Unit(_) => {
for unit in self.equipped.unit.iter_mut() {
if *unit == Some(inventory_item.entity_id) {
*unit = None
}
}
}
ItemDetail::Mag(_) => self.equipped.mag = Some(inventory_item.entity_id),
_ => {}
}
}
}
}
}
pub fn as_inventory_entity(&self, character_id: &CharacterEntityId) -> InventoryEntity {
InventoryEntity {
items: self.items.iter()
@ -673,25 +721,7 @@ impl CharacterInventory {
}
pub fn as_equipped_entity(&self) -> EquippedEntity {
self.items.iter()
.fold((EquippedEntity::default(), 0), |(mut equipped, mut unit_slot), item| {
if let InventoryItem::Individual(individual_item) = item {
if individual_item.equipped {
match individual_item.item {
ItemDetail::Weapon(_) => equipped.weapon = Some(individual_item.entity_id),
ItemDetail::Armor(_) => equipped.armor = Some(individual_item.entity_id),
ItemDetail::Shield(_) => equipped.shield = Some(individual_item.entity_id),
ItemDetail::Unit(_) => {
equipped.unit[unit_slot] = Some(individual_item.entity_id);
unit_slot += 1;
}
ItemDetail::Mag(_) => equipped.mag = Some(individual_item.entity_id),
_ => {},
}
}
}
(equipped, unit_slot)
}).0
self.equipped.clone()
}
}

109
src/ship/items/manager.rs

@ -97,7 +97,6 @@ impl ItemManager {
entity_id: item.id,
item_id: self.next_global_item_id(),
item: item.item,
equipped: equipped.is_equipped(&item.id),
})
},
InventoryItemEntity::Stacked(items) => {
@ -115,7 +114,7 @@ impl ItemManager {
})
})
.collect::<Result<Vec<_>, _>>()?;
let character_inventory = CharacterInventory::new(inventory_items);
let character_inventory = CharacterInventory::new(inventory_items, &equipped);
let bank_items = bank.items.into_iter()
.map(|item| -> Result<BankItem, ItemManagerError> {
@ -147,102 +146,6 @@ impl ItemManager {
self.character_inventory.insert(character.id, character_inventory);
self.character_bank.insert(character.id, character_bank);
Ok(())
/*
let items = entity_gateway.get_items_by_character(&character.id).await?;
let inventory_items = items.clone().into_iter()
.filter_map(|item| {
match item.location {
ItemLocation::Inventory{slot, equipped, ..} => Some((item.id, item.item, slot, equipped)),
_ => None,
}
})
.fold(BTreeMap::new(), |mut acc, (id, item, slot, equipped)| {
if item.is_stackable() {
if let ItemDetail::Tool(tool) = item {
let inventory_item = acc.entry(slot).or_insert(InventoryItem::Stacked(StackedInventoryItem {
entity_ids: Vec::new(),
item_id: self.next_global_item_id(),
tool: tool,
}));
if let InventoryItem::Stacked(ref mut stacked_inventory_item) = inventory_item {
stacked_inventory_item.entity_ids.push(id);
}
}
}
else {
acc.insert(slot, InventoryItem::Individual(IndividualInventoryItem {
entity_id: id,
item_id: self.next_global_item_id(),
item: item,
equipped: equipped,
}));
}
acc
});
// TODO: not using BankName anymore, clean this up
let mut bank_items = items.into_iter()
.filter_map(|item| {
match item.location {
ItemLocation::Bank{name, ..} => Some((item.id, item.item, name)),
_ => None,
}
})
.fold(BTreeMap::new(), |mut acc, (id, item, name)| {
acc.entry(name).or_insert(Vec::new()).push((id, item));
acc
})
.into_iter()
.map(|(bank_name, bank_items)| {
let stacked_bank_items = bank_items.into_iter()
.fold(Vec::new(), |mut acc, (id, bank_item)| {
if bank_item.is_stackable() {
let existing_item = acc.iter_mut()
.find(|item| {
if let (BankItem::Stacked(stacked_bank_item), &ItemDetail::Tool(ref tool)) = (item, &bank_item) {
stacked_bank_item.tool == *tool
}
else {
false
}
});
match existing_item {
Some(item) => {
if let BankItem::Stacked(ref mut stacked_bank_item) = item {
stacked_bank_item.entity_ids.push(id);
}
}
None => {
if let ItemDetail::Tool(tool) = bank_item {
acc.push(BankItem::Stacked(StackedBankItem {
entity_ids: vec![id],
item_id: self.next_global_item_id(),
tool: tool,
}));
}
},
}
}
else {
acc.push(BankItem::Individual(IndividualBankItem {
entity_id: id,
item_id: self.next_global_item_id(),
item: bank_item,
}));
}
acc
});
(bank_name, CharacterBank::new(stacked_bank_items))
})
.collect::<BTreeMap<_, _>>();
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
self.character_inventory.insert(character.id, inventory);
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
Ok(())
*/
}
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
@ -941,10 +844,7 @@ impl ItemManager {
equip_slot: u8)
-> Result<(), ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let mut inventory_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let slot = inventory_item_handle.get_slot();
let inventory_item = inventory_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?.individual().ok_or(ItemManagerError::CannotGetIndividualItem)?;
inventory_item.equipped = true;
inventory.equip(&item_id, equip_slot);
entity_gateway.set_character_equips(&character.id, &inventory.as_equipped_entity()).await?;
Ok(())
}
@ -955,10 +855,7 @@ impl ItemManager {
item_id: ClientItemId)
-> Result<(), ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let mut inventory_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let slot = inventory_item_handle.get_slot();
let inventory_item = inventory_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?.individual().ok_or(ItemManagerError::CannotGetIndividualItem)?;
inventory_item.equipped = false;
inventory.unequip(&item_id);
entity_gateway.set_character_equips(&character.id, &inventory.as_equipped_entity()).await?;
Ok(())
}

26
src/ship/packet/handler/message.rs

@ -316,7 +316,8 @@ where
EG: EntityGateway
{
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
item_manager.player_equips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id), pkt.sub_menu).await?;
let equip_slot = ((pkt.sub_menu & 0x7) - 1) % 4;
item_manager.player_equips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id), equip_slot).await?;
Ok(Box::new(None.into_iter()))
}
@ -330,30 +331,7 @@ where
EG: EntityGateway
{
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
let equipped_unit_ids: Vec<ClientItemId> = {
item_manager.player_unequips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id)).await?;
let inventory = item_manager.get_character_inventory(&client.character).unwrap();
let ue_item = inventory.get_item_by_id(ClientItemId(pkt.item_id)).ok_or(ShipError::ItemError)?;
if let ItemType::Armor(_) = ue_item.item_type() {
inventory.items()
.iter()
.filter(|inv_item| {
if let ItemType::Unit(_) = inv_item.item_type() {
return inv_item.equipped()
}
false
})
.map(|u| u.item_id())
.collect()
} else {
Vec::new()
}
};
for unit_id in equipped_unit_ids {
item_manager.player_unequips_item(entity_gateway, &client.character, unit_id).await?;
}
Ok(Box::new(None.into_iter()))
}

1
src/ship/shops/armor.rs

@ -85,7 +85,6 @@ impl ShopItem for ArmorShopItem {
ItemDetail::Unit(Unit {
unit: *unit,
modifier: None,
armor_slot: 0,
})
},
}

6
tests/test_item_actions.rs

@ -38,7 +38,6 @@ async fn test_equip_unit_from_equip_menu() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: None,
armor_slot: 0,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,
@ -51,7 +50,6 @@ async fn test_equip_unit_from_equip_menu() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: Some(item::unit::UnitModifier::Plus),
armor_slot: 0,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,
@ -127,7 +125,6 @@ async fn test_unequip_armor_with_units() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: None,
armor_slot: 0,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,
@ -140,7 +137,6 @@ async fn test_unequip_armor_with_units() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: Some(item::unit::UnitModifier::Plus),
armor_slot: 1,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,
@ -207,7 +203,6 @@ async fn test_sort_items() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: None,
armor_slot: 0,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,
@ -220,7 +215,6 @@ async fn test_sort_items() {
item::unit::Unit{
unit: item::unit::UnitType::KnightPower,
modifier: Some(item::unit::UnitModifier::Plus),
armor_slot: 0,
}),
location: item::ItemLocation::Inventory {
character_id: char1.id,

Loading…
Cancel
Save