inventory refactor - huge improvement

This commit is contained in:
Llywelwyn 2023-08-23 22:07:09 +01:00
parent 3c5f52faba
commit 0b251c991c
3 changed files with 96 additions and 69 deletions

View file

@ -6,6 +6,7 @@ use super::{
renderable_colour, renderable_colour,
ItemMenuResult, ItemMenuResult,
UniqueInventoryItem, UniqueInventoryItem,
BUC,
}; };
use crate::{ use crate::{
gamelog, gamelog,
@ -89,23 +90,32 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
.log(); .log();
return (ItemMenuResult::Selected, Some(build_identify_iterator().nth(0).unwrap().0)); return (ItemMenuResult::Selected, Some(build_identify_iterator().nth(0).unwrap().0));
} }
let mut player_inventory: BTreeMap<UniqueInventoryItem, i32> = BTreeMap::new(); let mut player_inventory: super::PlayerInventory = BTreeMap::new();
let mut inventory_ids: BTreeMap<String, Entity> = BTreeMap::new();
for (entity, _i, renderable, name) in build_identify_iterator() { for (entity, _i, renderable, name) in build_identify_iterator() {
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity); let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
let beatitude_status = if let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity) {
match beatitude.buc {
BUC::Blessed => 1,
BUC::Uncursed => 2,
BUC::Cursed => 3,
}
} else {
0
};
let unique_item = UniqueInventoryItem {
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() },
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
beatitude_status: beatitude_status,
name: name.name.clone(),
};
player_inventory player_inventory
.entry(UniqueInventoryItem { .entry(unique_item)
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() }, .and_modify(|(e, count)| {
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
name: name.name.clone(),
})
.and_modify(|count| {
*count += 1; *count += 1;
}) })
.or_insert(1); .or_insert((entity, 1));
inventory_ids.entry(singular).or_insert(entity);
} }
// Get display args // Get display args
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
@ -120,7 +130,7 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
"Identify which item? [aA-zZ][Esc.]" "Identify which item? [aA-zZ][Esc.]"
); );
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK)); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
print_options(player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
// Input // Input
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -130,19 +140,19 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
_ => { _ => {
let selection = rltk::letter_to_option(key); let selection = rltk::letter_to_option(key);
if selection > -1 && selection < (count as i32) { if selection > -1 && selection < (count as i32) {
let item = inventory_ids let item = player_inventory
.iter() .iter()
.nth(selection as usize) .nth(selection as usize)
.unwrap().1; .unwrap().1.0;
gamelog::Logger gamelog::Logger
::new() ::new()
.append("You identify the") .append("You identify the")
.colour(item_colour_ecs(&gs.ecs, *item)) .colour(item_colour_ecs(&gs.ecs, item))
.append_n(obfuscate_name_ecs(&gs.ecs, *item).0) .append_n(obfuscate_name_ecs(&gs.ecs, item).0)
.colour(WHITE) .colour(WHITE)
.append("!") .append("!")
.log(); .log();
return (ItemMenuResult::Selected, Some(*item)); return (ItemMenuResult::Selected, Some(item));
} }
(ItemMenuResult::NoResponse, None) (ItemMenuResult::NoResponse, None)
} }

View file

@ -236,8 +236,8 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
) )
); );
y += 1; y += 1;
let (player_inventory, _inventory_ids) = get_player_inventory(&ecs); let player_inventory = get_player_inventory(&ecs);
y = print_options(player_inventory, 72, y, ctx).0; y = print_options(&player_inventory, 72, y, ctx).0;
// Draw spells - if we have any -- NYI! // Draw spells - if we have any -- NYI!
if let Some(known_spells) = ecs.read_storage::<KnownSpells>().get(*player_entity) { if let Some(known_spells) = ecs.read_storage::<KnownSpells>().get(*player_entity) {
@ -403,16 +403,11 @@ pub enum ItemMenuResult {
Selected, Selected,
} }
pub fn print_options( pub fn print_options(inventory: &PlayerInventory, mut x: i32, mut y: i32, ctx: &mut Rltk) -> (i32, i32) {
inventory: BTreeMap<UniqueInventoryItem, i32>,
mut x: i32,
mut y: i32,
ctx: &mut Rltk
) -> (i32, i32) {
let mut j = 0; let mut j = 0;
let initial_x: i32 = x; let initial_x: i32 = x;
let mut width: i32 = -1; let mut width: i32 = -1;
for (item, item_count) in &inventory { for (item, (_e, item_count)) in inventory {
x = initial_x; x = initial_x;
// Print the character required to access this item. i.e. (a) // Print the character required to access this item. i.e. (a)
if j < 26 { if j < 26 {
@ -465,9 +460,9 @@ pub fn print_options(
return (y, width); return (y, width);
} }
pub fn get_max_inventory_width(inventory: &BTreeMap<UniqueInventoryItem, i32>) -> i32 { pub fn get_max_inventory_width(inventory: &PlayerInventory) -> i32 {
let mut width: i32 = 0; let mut width: i32 = 0;
for (item, count) in inventory { for (item, (e, count)) in inventory {
let mut this_width = item.display_name.singular.len() as i32; let mut this_width = item.display_name.singular.len() as i32;
// Clean this up. It should use consts. // Clean this up. It should use consts.
this_width += 4; // The spaces before and after the character to select this item, etc. this_width += 4; // The spaces before and after the character to select this item, etc.
@ -692,18 +687,21 @@ pub struct UniqueInventoryItem {
rgb: (u8, u8, u8), rgb: (u8, u8, u8),
renderables: (u8, u8, u8), renderables: (u8, u8, u8),
glyph: u16, glyph: u16,
beatitude_status: i32,
name: String, name: String,
} }
pub fn get_player_inventory(ecs: &World) -> (BTreeMap<UniqueInventoryItem, i32>, BTreeMap<String, Entity>) { pub type PlayerInventory = BTreeMap<UniqueInventoryItem, (Entity, i32)>;
pub fn get_player_inventory(ecs: &World) -> PlayerInventory {
let player_entity = ecs.fetch::<Entity>(); let player_entity = ecs.fetch::<Entity>();
let names = ecs.read_storage::<Name>(); let names = ecs.read_storage::<Name>();
let backpack = ecs.read_storage::<InBackpack>(); let backpack = ecs.read_storage::<InBackpack>();
let entities = ecs.entities(); let entities = ecs.entities();
let renderables = ecs.read_storage::<Renderable>(); let renderables = ecs.read_storage::<Renderable>();
let mut inventory_ids: BTreeMap<String, Entity> = BTreeMap::new(); let mut inventory_ids: BTreeMap<Entity, Entity> = BTreeMap::new();
let mut player_inventory: BTreeMap<UniqueInventoryItem, i32> = BTreeMap::new(); let mut player_inventory: BTreeMap<UniqueInventoryItem, (Entity, i32)> = BTreeMap::new();
for (entity, _pack, name, renderable) in (&entities, &backpack, &names, &renderables) for (entity, _pack, name, renderable) in (&entities, &backpack, &names, &renderables)
.join() .join()
.filter(|item| item.1.owner == *player_entity) { .filter(|item| item.1.owner == *player_entity) {
@ -715,26 +713,36 @@ pub fn get_player_inventory(ecs: &World) -> (BTreeMap<UniqueInventoryItem, i32>,
(renderable.fg.b * 255.0) as u8, (renderable.fg.b * 255.0) as u8,
); );
let (singular, plural) = obfuscate_name_ecs(ecs, entity); let (singular, plural) = obfuscate_name_ecs(ecs, entity);
let beatitude_status = if let Some(beatitude) = ecs.read_storage::<Beatitude>().get(entity) {
match beatitude.buc {
BUC::Blessed => 1,
BUC::Uncursed => 2,
BUC::Cursed => 3,
}
} else {
0
};
let unique_item = UniqueInventoryItem {
display_name: DisplayName { singular: singular.clone(), plural: plural },
rgb: item_colour,
renderables: renderables,
glyph: renderable.glyph,
beatitude_status: beatitude_status,
name: name.name.clone(),
};
player_inventory player_inventory
.entry(UniqueInventoryItem { .entry(unique_item)
display_name: DisplayName { singular: singular.clone(), plural: plural }, .and_modify(|(e, count)| {
rgb: item_colour,
renderables: renderables,
glyph: renderable.glyph,
name: name.name.clone(),
})
.and_modify(|count| {
*count += 1; *count += 1;
}) })
.or_insert(1); .or_insert((entity, 1));
inventory_ids.entry(singular).or_insert(entity);
} }
return (player_inventory, inventory_ids); return player_inventory;
} }
pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) { pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
let (player_inventory, inventory_ids) = get_player_inventory(&gs.ecs); let player_inventory = get_player_inventory(&gs.ecs);
let count = player_inventory.len(); let count = player_inventory.len();
let (x_offset, y_offset) = (1, 10); let (x_offset, y_offset) = (1, 10);
@ -751,7 +759,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
let y = 3 + y_offset; let y = 3 + y_offset;
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
print_options(player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -764,10 +772,10 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
return ( return (
ItemMenuResult::Selected, ItemMenuResult::Selected,
Some( Some(
*inventory_ids player_inventory
.iter() .iter()
.nth(selection as usize) .nth(selection as usize)
.unwrap().1 .unwrap().1.0
), ),
); );
} }
@ -778,7 +786,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
} }
pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) { pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
let (player_inventory, inventory_ids) = get_player_inventory(&gs.ecs); let player_inventory = get_player_inventory(&gs.ecs);
let count = player_inventory.len(); let count = player_inventory.len();
let (x_offset, y_offset) = (1, 10); let (x_offset, y_offset) = (1, 10);
@ -795,7 +803,7 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
let y = 3 + y_offset; let y = 3 + y_offset;
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK));
print_options(player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -808,10 +816,10 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
return ( return (
ItemMenuResult::Selected, ItemMenuResult::Selected,
Some( Some(
*inventory_ids player_inventory
.iter() .iter()
.nth(selection as usize) .nth(selection as usize)
.unwrap().1 .unwrap().1.0
), ),
); );
} }

View file

@ -73,23 +73,32 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
.log(); .log();
return (ItemMenuResult::Selected, Some(item)); return (ItemMenuResult::Selected, Some(item));
} }
let mut player_inventory: BTreeMap<UniqueInventoryItem, i32> = BTreeMap::new(); let mut player_inventory: super::PlayerInventory = BTreeMap::new();
let mut inventory_ids: BTreeMap<String, Entity> = BTreeMap::new();
for (entity, _i, _b, renderable, name) in build_cursed_iterator() { for (entity, _i, _b, renderable, name) in build_cursed_iterator() {
let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity); let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
let beatitude_status = if let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity) {
match beatitude.buc {
BUC::Blessed => 1,
BUC::Uncursed => 2,
BUC::Cursed => 3,
}
} else {
0
};
let unique_item = UniqueInventoryItem {
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() },
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
beatitude_status: beatitude_status,
name: name.name.clone(),
};
player_inventory player_inventory
.entry(UniqueInventoryItem { .entry(unique_item)
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() }, .and_modify(|(e, count)| {
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
name: name.name.clone(),
})
.and_modify(|count| {
*count += 1; *count += 1;
}) })
.or_insert(1); .or_insert((entity, 1));
inventory_ids.entry(singular).or_insert(entity);
} }
// Get display args // Get display args
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
@ -104,7 +113,7 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
"Decurse which item? [aA-zZ][Esc.]" "Decurse which item? [aA-zZ][Esc.]"
); );
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK)); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
print_options(player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
// Input // Input
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -114,19 +123,19 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
_ => { _ => {
let selection = rltk::letter_to_option(key); let selection = rltk::letter_to_option(key);
if selection > -1 && selection < (count as i32) { if selection > -1 && selection < (count as i32) {
let item = inventory_ids let item = player_inventory
.iter() .iter()
.nth(selection as usize) .nth(selection as usize)
.unwrap().1; .unwrap().1.0;
gamelog::Logger gamelog::Logger
::new() ::new()
.append("You decurse the") .append("You decurse the")
.colour(item_colour_ecs(&gs.ecs, *item)) .colour(item_colour_ecs(&gs.ecs, item))
.append_n(obfuscate_name_ecs(&gs.ecs, *item).0) .append_n(obfuscate_name_ecs(&gs.ecs, item).0)
.colour(WHITE) .colour(WHITE)
.append("!") .append("!")
.log(); .log();
return (ItemMenuResult::Selected, Some(*item)); return (ItemMenuResult::Selected, Some(item));
} }
(ItemMenuResult::NoResponse, None) (ItemMenuResult::NoResponse, None)
} }