generated from GarandPLG/rust-flake-template
Replace settings module with skirmish mode
Removed the settings UI and its keybinding logic, added a skirmish view and corresponding keybindings, simplified the SettingsState to hold skirmish configuration, updated module exports, and changed the CLI default map height from 25 to 21. Also fixed the main menu selection limit.
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
use crate::app::{
|
||||
App,
|
||||
keybindings::{default_keybindings, main_menu_keybindings, settings_keybindings},
|
||||
keybindings::{default_keybindings, main_menu_keybindings, skirmish_keybindings},
|
||||
view::View,
|
||||
};
|
||||
use ratatui::crossterm::event::KeyEvent;
|
||||
@@ -8,7 +8,7 @@ use ratatui::crossterm::event::KeyEvent;
|
||||
pub fn handle_keybindings(app: &mut App, key_event: KeyEvent) {
|
||||
match app.view {
|
||||
View::MainMenu => main_menu_keybindings(app, &key_event),
|
||||
View::Settings => settings_keybindings(app, &key_event),
|
||||
View::Skirmish => skirmish_keybindings(app, &key_event),
|
||||
_ => default_keybindings(app, &key_event),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
||||
}
|
||||
Action::Down => {
|
||||
app.states.main_menu.selected_view =
|
||||
app.states.main_menu.selected_view.saturating_add(1).min(4);
|
||||
app.states.main_menu.selected_view.saturating_add(1).min(3);
|
||||
}
|
||||
Action::Space => {
|
||||
let selected_view: usize = app.states.main_menu.selected_view;
|
||||
@@ -26,8 +26,6 @@ pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
||||
app.view = View::PerkDecks;
|
||||
} else if selected_view == 3 {
|
||||
app.view = View::SkillsConfig;
|
||||
} else if selected_view == 4 {
|
||||
app.view = View::Settings;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
pub mod default;
|
||||
pub mod keybindings;
|
||||
pub mod main_menu;
|
||||
pub mod settings;
|
||||
pub mod skirmish;
|
||||
|
||||
pub use default::default_keybindings;
|
||||
pub use keybindings::{Action, Group, KEYBINDINGS, KeyBinding, binding_for, event_to_action};
|
||||
pub use main_menu::main_menu_keybindings;
|
||||
pub use settings::settings_keybindings;
|
||||
pub use skirmish::skirmish_keybindings;
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
use crate::app::{
|
||||
App, View,
|
||||
keybindings::{Action, event_to_action},
|
||||
states::SettingsValue,
|
||||
};
|
||||
use ratatui::crossterm::event::KeyEvent;
|
||||
use std::any::type_name_of_val;
|
||||
|
||||
pub fn settings_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||
if let Some(action) = event_to_action(&key_event) {
|
||||
match action {
|
||||
Action::Up => {
|
||||
app.states.settings.selected_setting = app
|
||||
.states
|
||||
.settings
|
||||
.selected_setting
|
||||
.saturating_sub(1)
|
||||
.max(0)
|
||||
}
|
||||
Action::Down => {
|
||||
app.states.settings.selected_setting = app
|
||||
.states
|
||||
.settings
|
||||
.selected_setting
|
||||
.saturating_add(1)
|
||||
.min(9)
|
||||
}
|
||||
Action::Esc => app.view = View::MainMenu,
|
||||
Action::Space => app.states.settings.show_popup = !app.states.settings.show_popup,
|
||||
Action::Enter => {
|
||||
// FIXME: No feedback
|
||||
// FIXME: Extract match block into a function
|
||||
if app.states.settings.show_popup {
|
||||
let option =
|
||||
&app.states.settings.options[app.states.settings.selected_setting].value;
|
||||
|
||||
let option_type: &'static str = type_name_of_val(option);
|
||||
|
||||
let new_value: String = app.states.settings.selected_setting_new_value.clone();
|
||||
|
||||
match option_type {
|
||||
"u8" => {
|
||||
if let Ok(value) = new_value.parse::<u8>() {
|
||||
app.states.settings.options[app.states.settings.selected_setting]
|
||||
.value = SettingsValue::U8(value);
|
||||
|
||||
app.states.settings.selected_setting_new_value = "".to_string();
|
||||
app.states.settings.error_message = "".to_string();
|
||||
app.states.settings.show_popup = false;
|
||||
} else {
|
||||
app.states.settings.error_message = "Invalid value".to_string();
|
||||
}
|
||||
}
|
||||
"f32" => {
|
||||
if let Ok(value) = new_value.parse::<f32>() {
|
||||
app.states.settings.options[app.states.settings.selected_setting]
|
||||
.value = SettingsValue::F32(value);
|
||||
|
||||
app.states.settings.selected_setting_new_value = "".to_string();
|
||||
app.states.settings.error_message = "".to_string();
|
||||
app.states.settings.show_popup = false;
|
||||
} else {
|
||||
app.states.settings.error_message = "Invalid value".to_string();
|
||||
}
|
||||
}
|
||||
"u16" => {
|
||||
if let Ok(value) = new_value.parse::<u16>() {
|
||||
app.states.settings.options[app.states.settings.selected_setting]
|
||||
.value = SettingsValue::U16(value);
|
||||
|
||||
app.states.settings.selected_setting_new_value = "".to_string();
|
||||
app.states.settings.error_message = "".to_string();
|
||||
app.states.settings.show_popup = false;
|
||||
} else {
|
||||
app.states.settings.error_message = "Invalid value".to_string();
|
||||
}
|
||||
}
|
||||
"std::string::String" => {
|
||||
app.states.settings.options[app.states.settings.selected_setting]
|
||||
.value = SettingsValue::Text(new_value);
|
||||
|
||||
app.states.settings.selected_setting_new_value = "".to_string();
|
||||
app.states.settings.error_message = "".to_string();
|
||||
app.states.settings.show_popup = false;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::Backspace => {
|
||||
if app.states.settings.show_popup {
|
||||
app.states.settings.selected_setting_new_value.pop();
|
||||
}
|
||||
}
|
||||
Action::WildCard(c) => {
|
||||
if app.states.settings.show_popup {
|
||||
app.states.settings.selected_setting_new_value.push(c);
|
||||
}
|
||||
}
|
||||
Action::Quit => app.exit = true,
|
||||
Action::Quit2 => app.exit = true,
|
||||
// _ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
use crate::app::{
|
||||
App, View,
|
||||
keybindings::{Action, event_to_action},
|
||||
};
|
||||
use ratatui::crossterm::event::KeyEvent;
|
||||
|
||||
pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||
if let Some(action) = event_to_action(&key_event) {
|
||||
match action {
|
||||
Action::Quit => app.exit = true,
|
||||
Action::Quit2 => app.exit = true,
|
||||
Action::Esc => app.view = View::MainMenu,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-52
@@ -1,8 +1,5 @@
|
||||
use crate::{
|
||||
app::states::{
|
||||
MainMenuState, PerkDecksState, SettingsOption, SettingsState, SettingsValue,
|
||||
SkillsConfigState, SkirmishState,
|
||||
},
|
||||
app::states::{MainMenuState, PerkDecksState, SettingsState, SkillsConfigState, SkirmishState},
|
||||
cli::Cli,
|
||||
};
|
||||
|
||||
@@ -38,54 +35,16 @@ impl GameStates {
|
||||
selected_skill: 0,
|
||||
},
|
||||
settings: SettingsState {
|
||||
id: 4,
|
||||
name: "Settings",
|
||||
selected_setting: 0,
|
||||
show_popup: false,
|
||||
selected_setting_new_value: String::new(),
|
||||
error_message: String::new(),
|
||||
options: vec![
|
||||
SettingsOption {
|
||||
name: "Username",
|
||||
value: SettingsValue::Text(args.username),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Game Mode",
|
||||
value: SettingsValue::GameMode(args.game_mode),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Map Width",
|
||||
value: SettingsValue::U8(args.map_width),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Map Height",
|
||||
value: SettingsValue::U8(args.map_height),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Perk Deck",
|
||||
value: SettingsValue::PerkDeck(args.perk_deck),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Starting Wood",
|
||||
value: SettingsValue::U8(args.starting_wood),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Starting Iron",
|
||||
value: SettingsValue::U8(args.starting_iron),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Supply Limit",
|
||||
value: SettingsValue::U8(args.supply_limit),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "XP Modifier",
|
||||
value: SettingsValue::F32(args.xp_modifier),
|
||||
},
|
||||
SettingsOption {
|
||||
name: "Skill Points Limit",
|
||||
value: SettingsValue::U16(args.skill_points_limit),
|
||||
},
|
||||
],
|
||||
username: args.username,
|
||||
game_mode: args.game_mode,
|
||||
map_width: args.map_width,
|
||||
map_height: args.map_height,
|
||||
perk_deck: args.perk_deck,
|
||||
starting_wood: args.starting_wood,
|
||||
starting_iron: args.starting_iron,
|
||||
supply_limit: args.supply_limit,
|
||||
xp_modifier: args.xp_modifier,
|
||||
skill_points_limit: args.skill_points_limit,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ pub mod skirmish;
|
||||
|
||||
pub use main_menu::MainMenuState;
|
||||
pub use perk_decks::{PerkDecks, PerkDecksState};
|
||||
pub use settings::{GameMode, SettingsOption, SettingsState, SettingsValue};
|
||||
pub use settings::SettingsState;
|
||||
pub use skills_config::SkillsConfigState;
|
||||
pub use skirmish::SkirmishState;
|
||||
pub use skirmish::{GameMode, SkirmishState};
|
||||
|
||||
+11
-54
@@ -1,58 +1,15 @@
|
||||
use crate::app::states::PerkDecks;
|
||||
use clap::ValueEnum;
|
||||
use std::fmt::Display;
|
||||
use crate::app::states::{GameMode, PerkDecks};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SettingsState {
|
||||
pub id: usize,
|
||||
pub name: &'static str,
|
||||
pub selected_setting: usize,
|
||||
pub show_popup: bool,
|
||||
pub selected_setting_new_value: String,
|
||||
pub error_message: String,
|
||||
pub options: Vec<SettingsOption>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SettingsOption {
|
||||
pub name: &'static str,
|
||||
pub value: SettingsValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SettingsValue {
|
||||
U8(u8),
|
||||
F32(f32),
|
||||
U16(u16),
|
||||
Text(String),
|
||||
GameMode(GameMode),
|
||||
PerkDeck(PerkDecks),
|
||||
}
|
||||
|
||||
impl Display for SettingsValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
SettingsValue::U8(v) => write!(f, "{}", v),
|
||||
SettingsValue::F32(v) => write!(f, "{}", v),
|
||||
SettingsValue::U16(v) => write!(f, "{}", v),
|
||||
SettingsValue::Text(v) => write!(f, "{}", v),
|
||||
SettingsValue::GameMode(v) => write!(f, "{}", v),
|
||||
SettingsValue::PerkDeck(v) => write!(f, "{}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||
pub enum GameMode {
|
||||
LastManStanding,
|
||||
FrontLines,
|
||||
}
|
||||
|
||||
impl Display for GameMode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GameMode::FrontLines => write!(f, "Front Lines"),
|
||||
GameMode::LastManStanding => write!(f, "Last Man Standing"),
|
||||
}
|
||||
}
|
||||
pub username: String,
|
||||
pub game_mode: GameMode,
|
||||
pub map_width: u8,
|
||||
pub map_height: u8,
|
||||
pub perk_deck: PerkDecks,
|
||||
pub starting_wood: u16,
|
||||
pub starting_iron: u16,
|
||||
pub supply_limit: u8,
|
||||
pub xp_modifier: f32,
|
||||
pub skill_points_limit: u16,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
use clap::ValueEnum;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct SkirmishState {
|
||||
pub id: usize,
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||
pub enum GameMode {
|
||||
LastManStanding,
|
||||
FrontLines,
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,6 +1,6 @@
|
||||
use crate::app::{
|
||||
App,
|
||||
views::{default_view, main_menu_view, settings_view},
|
||||
views::{default_view, main_menu_view, skirmish_view},
|
||||
};
|
||||
use clap::ValueEnum;
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
@@ -11,7 +11,6 @@ pub enum View {
|
||||
Skirmish,
|
||||
PerkDecks,
|
||||
SkillsConfig,
|
||||
Settings,
|
||||
}
|
||||
|
||||
impl Widget for &App {
|
||||
@@ -21,7 +20,7 @@ impl Widget for &App {
|
||||
{
|
||||
match self.view {
|
||||
View::MainMenu => main_menu_view(self, area, buf),
|
||||
View::Settings => settings_view(self, area, buf),
|
||||
View::Skirmish => skirmish_view(self, area, buf),
|
||||
_ => default_view(area, buf),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pub mod default;
|
||||
pub mod main_menu;
|
||||
pub mod settings;
|
||||
pub mod skirmish;
|
||||
|
||||
pub use default::default_view;
|
||||
pub use main_menu::main_menu_view;
|
||||
pub use settings::settings_view;
|
||||
pub use skirmish::skirmish_view;
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
use crate::app::{App, keybindings::Action, widgets::KeybindingsWidget};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Constraint, Layout, Rect},
|
||||
style::{Style, Stylize},
|
||||
text::Line,
|
||||
widgets::{Block, Borders, Padding, Paragraph, Widget, Wrap},
|
||||
};
|
||||
|
||||
pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||
let vertical_layout: Layout = Layout::vertical([
|
||||
Constraint::Length(4),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(5),
|
||||
]);
|
||||
|
||||
let [title_area, main_area, keybindings_area] = vertical_layout.areas(area);
|
||||
|
||||
{
|
||||
Paragraph::new("War in tunnels")
|
||||
.alignment(Alignment::Left)
|
||||
.yellow()
|
||||
.block(
|
||||
Block::new()
|
||||
.gray()
|
||||
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
|
||||
.padding(Padding::new(5, 1, 1, 1)),
|
||||
)
|
||||
.render(title_area, buf);
|
||||
|
||||
let lines: Vec<Line<'_>> = app
|
||||
.states
|
||||
.settings
|
||||
.options
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, o)| {
|
||||
if i == app.states.settings.selected_setting {
|
||||
Line::from_iter([
|
||||
"> ".cyan(),
|
||||
o.name.yellow(),
|
||||
": ".gray(),
|
||||
o.value.to_string().light_green(),
|
||||
])
|
||||
} else {
|
||||
Line::from(format!(" {}: {}", o.name, o.value)).white()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let settings_block: Block<'_> = Block::new()
|
||||
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
|
||||
.padding(Padding::new(1, 1, 1, 1))
|
||||
.title(Line::from_iter([
|
||||
"[ ".gray(),
|
||||
"Settings".magenta(),
|
||||
" ]".gray(),
|
||||
]))
|
||||
.gray();
|
||||
|
||||
let settings_area: Rect = settings_block.inner(main_area);
|
||||
|
||||
settings_block.render(main_area, buf);
|
||||
|
||||
Paragraph::new(lines).alignment(Alignment::Center).render(
|
||||
settings_area.centered_vertically(Constraint::Ratio(1, 2)),
|
||||
buf,
|
||||
);
|
||||
|
||||
let popup_text: Vec<Line<'_>> = Vec::from_iter([
|
||||
app.states
|
||||
.settings
|
||||
.selected_setting_new_value
|
||||
.clone()
|
||||
.into(),
|
||||
app.states.settings.error_message.clone().into(),
|
||||
]);
|
||||
|
||||
if app.states.settings.show_popup {
|
||||
Paragraph::new(popup_text)
|
||||
.wrap(Wrap { trim: true })
|
||||
.style(Style::default())
|
||||
.block(
|
||||
Block::new()
|
||||
.title("Insert new value")
|
||||
.title_style(Style::default().yellow())
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().gray())
|
||||
.padding(Padding {
|
||||
left: 1,
|
||||
right: 1,
|
||||
top: 1,
|
||||
bottom: 1,
|
||||
}),
|
||||
)
|
||||
.render(
|
||||
Rect {
|
||||
x: 2,
|
||||
y: main_area.height - 1,
|
||||
width: main_area.width - 3,
|
||||
height: if app.states.settings.error_message.is_empty() {
|
||||
5
|
||||
} else {
|
||||
6
|
||||
},
|
||||
},
|
||||
buf,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let actions: Vec<Action> = vec![
|
||||
Action::Up,
|
||||
Action::Down,
|
||||
Action::Quit,
|
||||
Action::Quit2,
|
||||
Action::Esc,
|
||||
Action::Space,
|
||||
Action::Enter,
|
||||
Action::Backspace,
|
||||
Action::WildCard('_'),
|
||||
];
|
||||
|
||||
KeybindingsWidget::new(actions).render(keybindings_area, buf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
use crate::app::{App, keybindings::Action, widgets::KeybindingsWidget};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Constraint, Layout, Margin, Rect},
|
||||
style::Stylize,
|
||||
text::Line,
|
||||
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
||||
};
|
||||
|
||||
pub fn skirmish_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||
let vertical_layout: Layout = Layout::vertical([
|
||||
Constraint::Length(4),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(4),
|
||||
]);
|
||||
|
||||
let [title_area, main_area, keybindings_area] = vertical_layout.areas(area);
|
||||
|
||||
{
|
||||
let lines: Vec<Line<'_>> = Vec::from_iter([
|
||||
Line::raw("War in Tunnels").yellow(),
|
||||
Line::from_iter([
|
||||
format!("Wood: {} (+{}) | ", app.states.settings.starting_wood, 5),
|
||||
format!("Iron: {} (+{}) | ", app.states.settings.starting_iron, 1),
|
||||
format!(
|
||||
"Supply Limit: {}/{} | ",
|
||||
10, app.states.settings.supply_limit
|
||||
),
|
||||
format!(
|
||||
"Skills points: {} ({}/{}) | ",
|
||||
1, 20, app.states.settings.skill_points_limit
|
||||
),
|
||||
format!("Perk Deck: {}/9", 5),
|
||||
]),
|
||||
]);
|
||||
|
||||
Paragraph::new(lines)
|
||||
.alignment(Alignment::Left)
|
||||
.block(
|
||||
Block::new()
|
||||
.gray()
|
||||
.padding(Padding {
|
||||
left: 1,
|
||||
right: 1,
|
||||
top: 0,
|
||||
bottom: 1,
|
||||
})
|
||||
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT),
|
||||
)
|
||||
.render(title_area, buf);
|
||||
}
|
||||
|
||||
{
|
||||
let board_block: Block = Block::new()
|
||||
.gray()
|
||||
.title(Line::from_iter([
|
||||
"[ ".gray(),
|
||||
"Skirmish".magenta(),
|
||||
" - ".gray(),
|
||||
"Map".green(),
|
||||
" ]".gray(),
|
||||
]))
|
||||
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT);
|
||||
|
||||
let board_area: Rect = board_block.inner(main_area);
|
||||
board_block.render(main_area, buf);
|
||||
|
||||
let inner_board_area: Rect = board_area.inner(Margin {
|
||||
horizontal: 1,
|
||||
vertical: 1,
|
||||
});
|
||||
|
||||
let map_width: u16 = inner_board_area.width / (app.states.settings.map_width as u16);
|
||||
let map_height: u16 = inner_board_area.height / (app.states.settings.map_height as u16);
|
||||
|
||||
Paragraph::new(format!(
|
||||
"x = {}, y = {}, mw = {}, mh = {}",
|
||||
inner_board_area.width, inner_board_area.height, map_width, map_height
|
||||
))
|
||||
.block(Block::default())
|
||||
.render(inner_board_area, buf);
|
||||
}
|
||||
|
||||
{
|
||||
let actions: Vec<Action> = vec![Action::Quit, Action::Quit2, Action::Esc];
|
||||
|
||||
KeybindingsWidget::new(actions).render(keybindings_area, buf);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -45,7 +45,7 @@ pub struct Cli {
|
||||
long,
|
||||
help = "Map height",
|
||||
value_name = "Positive integer [11; 50]",
|
||||
default_value = "25"
|
||||
default_value = "21"
|
||||
)]
|
||||
pub map_height: u8,
|
||||
|
||||
@@ -64,7 +64,7 @@ pub struct Cli {
|
||||
value_name = "Positive integer",
|
||||
default_value = "50"
|
||||
)]
|
||||
pub starting_wood: u8,
|
||||
pub starting_wood: u16,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
@@ -72,7 +72,7 @@ pub struct Cli {
|
||||
value_name = "Positive integer",
|
||||
default_value = "25"
|
||||
)]
|
||||
pub starting_iron: u8,
|
||||
pub starting_iron: u16,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
|
||||
Reference in New Issue
Block a user