Skip to content

Commit

Permalink
feat: modify inventories
Browse files Browse the repository at this point in the history
  • Loading branch information
mokurin000 committed Feb 17, 2024
1 parent caed2dd commit f1c973b
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 54 deletions.
67 changes: 13 additions & 54 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs, path::PathBuf};

use cavestory_save::{GameProfile, Profile, ProfileError};
use cavestory_save::{GameProfile, Profile};

use cavestory_save::items::*;
use cavestory_save::strum::IntoEnumIterator;
Expand All @@ -9,12 +9,15 @@ use std::sync::mpsc::{Receiver, Sender};

use tap::pipe::Pipe;

use self::utils::ProfileExt;

pub struct MainApp {
path: Option<PathBuf>,
path_sender: Sender<PathBuf>,
path_receiver: Receiver<PathBuf>,
profile: Option<(Profile, GameProfile)>,
weapon_num: usize,
inventory_num: usize,
equip_checked: [bool; 9],
}

Expand All @@ -28,6 +31,7 @@ impl Default for MainApp {
path_receiver,
profile: None,
weapon_num: 0,
inventory_num: 0,
equip_checked: [false; 9],
}
}
Expand All @@ -37,56 +41,6 @@ impl MainApp {
pub fn new(_cc: &eframe::CreationContext<'_>) -> Self {
Default::default()
}

fn verify_and_init(&mut self, data: Vec<u8>) -> Result<(), ProfileError> {
match Profile::try_from(data) {
Ok(profile) => {
let game_profile = GameProfile::dump(&profile);
self.profile = Some((profile, game_profile));
self.weapon_num = self.count_weapon().unwrap();
self.equip_checked = self.detect_equip().unwrap();
Ok(())
}
Err(e) => {
use rfd::{AsyncMessageDialog, MessageLevel};
tokio::task::spawn(async move {
AsyncMessageDialog::new()
.set_level(MessageLevel::Error)
.set_title("Load Error")
.set_description(&e.to_string())
.show()
.await;
});
Err(e)
}
}
}

fn detect_equip(&self) -> Option<[bool; 9]> {
self.profile
.as_ref()
.map(|(_, GameProfile { equipment, .. })| {
let mut equip_checked: [bool; 9] = Default::default();

let equip_current = equipment;
for (i, equip) in Equipment::iter().enumerate() {
equip_checked[i] = equip_current.check(equip);
}

equip_checked
})
}

fn count_weapon(&self) -> Option<usize> {
self.profile
.as_ref()
.map(|(_, GameProfile { weapon, .. })| {
weapon
.iter()
.take_while(|w| w.classification != WeaponType::None)
.count()
})
}
}

impl eframe::App for MainApp {
Expand Down Expand Up @@ -147,9 +101,7 @@ impl eframe::App for MainApp {
if let Some(profile) = &mut self.profile {
if ui.button("Undo all").clicked() {
profile.1 = GameProfile::dump(&profile.0);
let _ = profile;
self.weapon_num = self.count_weapon().unwrap();
self.equip_checked = self.detect_equip().unwrap();
self.update_state();
}
}

Expand Down Expand Up @@ -226,6 +178,10 @@ impl eframe::App for MainApp {
egui::Window::new("Weapons").show(ctx, |ui| {
weapon::draw_window(ui, &mut self.weapon_num, weapon);
});

egui::Window::new("Inventory").show(ctx, |ui| {
inventory::draw_window(ui, &mut self.inventory_num, inventory);
});
});
}

Expand All @@ -250,4 +206,7 @@ impl eframe::App for MainApp {
}

mod basic;
mod inventory;
mod weapon;

mod utils;
47 changes: 47 additions & 0 deletions src/app/inventory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use cavestory_save::{items::Inventory, strum::IntoEnumIterator};
use egui::Ui;

const MAX_INVENTORY_NUM: usize = 31;

pub fn draw_window(ui: &mut Ui, inventory_num: &mut usize, inventory: &mut [Inventory]) {
ui.horizontal(|ui| {
// do not set the 8th weapon, you may go into issue.
if (*inventory_num == 0
|| inventory
.get(*inventory_num - 1)
.is_some_and(|&i| i != Inventory::None))
&& *inventory_num < MAX_INVENTORY_NUM
&& ui.button(" + ").clicked()
{
*inventory_num += 1
}

if *inventory_num > 0 && ui.button(" - ").clicked() {
*inventory_num -= 1;
inventory[*inventory_num] = Default::default();
}
});

ui.separator();

let chunk_size = 6;
for (chunk_i, chunk) in inventory[..*inventory_num]
.chunks_mut(chunk_size)
.enumerate()
{
ui.horizontal(|ui| {
for (i, inventory) in chunk.iter_mut().enumerate() {
ui.vertical(|ui| {
egui::ComboBox::new(format!("weapontype-box-{}", chunk_i * chunk_size + i), "")
.width(150.)
.selected_text(inventory.to_string())
.show_ui(ui, |ui| {
for model in Inventory::iter() {
ui.selectable_value(inventory, model, model.to_string());
}
});
});
}
});
}
}
84 changes: 84 additions & 0 deletions src/app/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use cavestory_save::{
items::{EquipOpt, Equipment, Inventory, WeaponType},
strum::IntoEnumIterator,
GameProfile, Profile, ProfileError,
};

use crate::MainApp;

pub trait ProfileExt {
fn verify_and_init(&mut self, data: Vec<u8>) -> Result<(), ProfileError>;
fn update_state(&mut self) -> Option<()>;
fn detect_equip(&self) -> Option<[bool; 9]>;
fn count_weapon(&self) -> Option<usize>;
fn count_inventory(&self) -> Option<usize>;
}

impl ProfileExt for MainApp {
fn verify_and_init(&mut self, data: Vec<u8>) -> Result<(), ProfileError> {
match Profile::try_from(data) {
Ok(profile) => {
let game_profile = GameProfile::dump(&profile);
self.profile = Some((profile, game_profile));
self.update_state();
Ok(())
}
Err(e) => {
use rfd::{AsyncMessageDialog, MessageLevel};
tokio::task::spawn(async move {
AsyncMessageDialog::new()
.set_level(MessageLevel::Error)
.set_title("Load Error")
.set_description(&e.to_string())
.show()
.await;
});
Err(e)
}
}
}

fn update_state(&mut self) -> Option<()> {
self.weapon_num = self.count_weapon()?;
self.inventory_num = self.count_inventory()?;
self.equip_checked = self.detect_equip()?;
Some(())
}

fn detect_equip(&self) -> Option<[bool; 9]> {
self.profile
.as_ref()
.map(|(_, GameProfile { equipment, .. })| {
let mut equip_checked: [bool; 9] = Default::default();

let equip_current = equipment;
for (i, equip) in Equipment::iter().enumerate() {
equip_checked[i] = equip_current.check(equip);
}

equip_checked
})
}

fn count_weapon(&self) -> Option<usize> {
self.profile
.as_ref()
.map(|(_, GameProfile { weapon, .. })| {
weapon
.iter()
.take_while(|w| w.classification != WeaponType::None)
.count()
})
}

fn count_inventory(&self) -> Option<usize> {
self.profile
.as_ref()
.map(|(_, GameProfile { inventory, .. })| {
inventory
.iter()
.take_while(|&&i| i != Inventory::None)
.count()
})
}
}

0 comments on commit f1c973b

Please sign in to comment.