Merge branch '65-add-code-comments' into 'dev'

Add code documentation

See merge request softwaregrundprojekt/2025-2026/einzelprojekt/tutorium-moritz/bernroider-dominik/bernroider-dominik!40
This commit is contained in:
Dominik Bernroider
2025-12-10 17:17:37 +00:00
55 changed files with 190 additions and 5 deletions

View File

@@ -2,6 +2,7 @@ use crate::prelude::*;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
/// Global configuration loaded from file, containing balancing numbers and paths.
#[derive(Resource, Deserialize, Debug)] #[derive(Resource, Deserialize, Debug)]
pub struct GameConfig { pub struct GameConfig {
pub grid_width: u32, pub grid_width: u32,
@@ -14,6 +15,7 @@ pub struct GameConfig {
pub berries_per_focus_minute: u32, pub berries_per_focus_minute: u32,
} }
/// Configuration for a specific type of seed.
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct BerrySeedConfig { pub struct BerrySeedConfig {
pub name: String, pub name: String,
@@ -61,10 +63,12 @@ impl Default for GameConfig {
} }
impl GameConfig { impl GameConfig {
/// Reads `config.json` from assets.
pub fn read_config() -> Option<Self> { pub fn read_config() -> Option<Self> {
Self::read_from_path(std::path::Path::new("assets/config.json")) Self::read_from_path(std::path::Path::new("assets/config.json"))
} }
/// Reads configuration from a specific path.
pub fn read_from_path(path: &std::path::Path) -> Option<Self> { pub fn read_from_path(path: &std::path::Path) -> Option<Self> {
let file = File::open(path).ok()?; let file = File::open(path).ok()?;
let reader = BufReader::new(file); let reader = BufReader::new(file);

View File

@@ -2,6 +2,7 @@ use crate::prelude::*;
pub mod states; pub mod states;
/// Handles core engine setup like camera and initial state.
pub struct CorePlugin; pub struct CorePlugin;
impl Plugin for CorePlugin { impl Plugin for CorePlugin {
@@ -11,6 +12,7 @@ impl Plugin for CorePlugin {
} }
} }
/// Spawns the main 2D camera.
fn setup_camera(mut commands: Commands) { fn setup_camera(mut commands: Commands) {
commands.spawn(Camera2d::default()); commands.spawn(Camera2d::default());
} }

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Global states of the application.
#[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default)] #[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default)]
pub enum AppState { pub enum AppState {
#[default] #[default]

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Plugin for the main game screen, managing the game loop and environment.
pub struct GameScreenPlugin; pub struct GameScreenPlugin;
impl Plugin for GameScreenPlugin { impl Plugin for GameScreenPlugin {
@@ -9,10 +10,12 @@ impl Plugin for GameScreenPlugin {
} }
} }
/// Sets up the game screen environment (e.g., background color).
fn setup(mut clear_color: ResMut<ClearColor>) { fn setup(mut clear_color: ResMut<ClearColor>) {
*clear_color = ClearColor(Color::srgb(0.294, 0.412, 0.184)); *clear_color = ClearColor(Color::srgb(0.294, 0.412, 0.184));
} }
/// Cleans up resources when exiting the game screen.
fn cleanup(mut clear_color: ResMut<ClearColor>) { fn cleanup(mut clear_color: ResMut<ClearColor>) {
*clear_color = ClearColor(Color::srgb(0.2, 0.2, 0.2)); *clear_color = ClearColor(Color::srgb(0.2, 0.2, 0.2));
} }

View File

@@ -1,18 +1,22 @@
use super::errors::GridError; use super::errors::GridError;
use crate::prelude::*; use crate::prelude::*;
/// Component representing a single tile on the grid.
#[derive(Component)] #[derive(Component)]
pub struct Tile { pub struct Tile {
pub x: u32, pub x: u32,
pub y: u32, pub y: u32,
} }
/// Visual marker component for the crop on a tile.
#[derive(Component)] #[derive(Component)]
pub struct CropVisual; pub struct CropVisual;
/// Visual marker component for the water on a tile.
#[derive(Component)] #[derive(Component)]
pub struct WaterVisual; pub struct WaterVisual;
/// The logical state of a tile.
#[derive(Component, Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[derive(Component, Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum TileState { pub enum TileState {
#[default] #[default]
@@ -38,6 +42,7 @@ impl TileState {
} }
} }
/// Resource containing grid dimensions and tile entities.
#[derive(Resource)] #[derive(Resource)]
pub struct Grid { pub struct Grid {
pub width: u32, pub width: u32,
@@ -46,6 +51,7 @@ pub struct Grid {
} }
impl Grid { impl Grid {
/// Returns the entity of the tile at the given position.
pub fn get_tile(&self, pos: (u32, u32)) -> Result<Entity, GridError> { pub fn get_tile(&self, pos: (u32, u32)) -> Result<Entity, GridError> {
if pos.0 >= self.width || pos.1 >= self.height { if pos.0 >= self.width || pos.1 >= self.height {
return Err(GridError::OutOfBounds { return Err(GridError::OutOfBounds {
@@ -56,6 +62,7 @@ impl Grid {
Ok(self.tiles[pos.0 as usize][pos.1 as usize]) Ok(self.tiles[pos.0 as usize][pos.1 as usize])
} }
/// Modifies the state of a tile using a mapping function.
pub fn map_tile_state<F>( pub fn map_tile_state<F>(
&self, &self,
pos: (u32, u32), pos: (u32, u32),
@@ -75,6 +82,7 @@ impl Grid {
Ok(()) Ok(())
} }
/// Counts the number of tiles that are not unclaimed.
pub fn count_claimed_tiles(&self, tile_query: &Query<&TileState>) -> u32 { pub fn count_claimed_tiles(&self, tile_query: &Query<&TileState>) -> u32 {
self.tiles self.tiles
.iter() .iter()

View File

@@ -1 +1,2 @@
/// The pixel size of a tile (width and height).
pub const TILE_SIZE: f32 = 32.0; pub const TILE_SIZE: f32 = 32.0;

View File

@@ -1,5 +1,6 @@
use std::{error::Error, fmt}; use std::{error::Error, fmt};
/// Errors related to grid operations.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum GridError { pub enum GridError {
OutOfBounds { x: i32, y: i32 }, OutOfBounds { x: i32, y: i32 },

View File

@@ -7,6 +7,7 @@ pub mod consts;
pub mod errors; pub mod errors;
pub mod utils; pub mod utils;
/// Manages the game grid, including tiles, visuals, and updates.
pub struct GridPlugin; pub struct GridPlugin;
impl Plugin for GridPlugin { impl Plugin for GridPlugin {
@@ -18,6 +19,7 @@ impl Plugin for GridPlugin {
} }
} }
/// Initializes the grid and spawns tile entities.
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) { fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) {
let grid_width = config.grid_width; let grid_width = config.grid_width;
let grid_height = config.grid_height; let grid_height = config.grid_height;
@@ -96,6 +98,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<Gam
}); });
} }
/// Despawns all grid entities and removes resources.
fn cleanup(mut commands: Commands, tile_query: Query<Entity, With<Tile>>) { fn cleanup(mut commands: Commands, tile_query: Query<Entity, With<Tile>>) {
for tile_entity in tile_query.iter() { for tile_entity in tile_query.iter() {
commands.entity(tile_entity).despawn(); commands.entity(tile_entity).despawn();
@@ -103,6 +106,7 @@ fn cleanup(mut commands: Commands, tile_query: Query<Entity, With<Tile>>) {
commands.remove_resource::<Grid>(); commands.remove_resource::<Grid>();
} }
/// Updates tile visuals based on their state (e.g., crop growth, highlighting).
fn update_tiles( fn update_tiles(
mut query: Query< mut query: Query<
(&TileState, &mut AseSlice, &Children, &Tile), (&TileState, &mut AseSlice, &Children, &Tile),

View File

@@ -1,14 +1,17 @@
use super::errors::GridError; use super::errors::GridError;
use crate::prelude::*; use crate::prelude::*;
/// Calculates the starting X coordinate for centering the grid.
pub fn grid_start_x(grid_width: u32) -> f32 { pub fn grid_start_x(grid_width: u32) -> f32 {
-(grid_width as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0 -(grid_width as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
} }
/// Calculates the starting Y coordinate for centering the grid.
pub fn grid_start_y(grid_height: u32) -> f32 { pub fn grid_start_y(grid_height: u32) -> f32 {
-(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0 -(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
} }
/// Converts world coordinates to grid coordinates.
pub fn world_to_grid_coords( pub fn world_to_grid_coords(
world_pos: Vec3, world_pos: Vec3,
grid_width: u32, grid_width: u32,
@@ -30,6 +33,7 @@ pub fn world_to_grid_coords(
Ok((x as u32, y as u32)) Ok((x as u32, y as u32))
} }
/// Converts grid coordinates to world coordinates.
pub fn grid_to_world_coords( pub fn grid_to_world_coords(
grid_x: u32, grid_x: u32,
grid_y: u32, grid_y: u32,

View File

@@ -1,5 +1,6 @@
use crate::{features::phase::components::TimerSettings, prelude::*}; use crate::{features::phase::components::TimerSettings, prelude::*};
/// Markers for root UI nodes.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
Status, Status,
@@ -7,12 +8,14 @@ pub enum RootMarker {
ShovelOverlay, ShovelOverlay,
} }
/// Markers for text components in the HUD.
#[derive(Component)] #[derive(Component)]
pub enum TextType { pub enum TextType {
Phase, Phase,
Timer, Timer,
} }
/// Markers for buttons in the HUD and settings.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
SettingsOpen, SettingsOpen,
@@ -24,6 +27,7 @@ pub enum ButtonType {
}, },
} }
/// Types of timers available in the game.
#[derive(Clone)] #[derive(Clone)]
pub enum TimerType { pub enum TimerType {
Focus, Focus,
@@ -32,6 +36,7 @@ pub enum TimerType {
} }
impl TimerSettings { impl TimerSettings {
/// Changes the duration of a specific timer.
pub fn change(&mut self, timer_type: &TimerType, amount: i32) { pub fn change(&mut self, timer_type: &TimerType, amount: i32) {
match timer_type { match timer_type {
TimerType::Focus => { TimerType::Focus => {
@@ -59,6 +64,7 @@ impl TimerSettings {
} }
} }
/// Input types for adjusting timer settings.
#[derive(Component, Clone)] #[derive(Component, Clone)]
pub enum SettingsTimerInput { pub enum SettingsTimerInput {
Minutes(TimerType), Minutes(TimerType),

View File

@@ -8,6 +8,7 @@ use ui::*;
pub mod components; pub mod components;
pub mod ui; pub mod ui;
/// Plugin for the Head-Up Display (HUD) containing status bars and buttons.
pub struct HudPlugin; pub struct HudPlugin;
impl Plugin for HudPlugin { impl Plugin for HudPlugin {
@@ -27,6 +28,7 @@ impl Plugin for HudPlugin {
} }
} }
/// Initializes the HUD UI.
fn setup(mut commands: Commands, game_config: Res<GameConfig>, asset_server: Res<AssetServer>) { fn setup(mut commands: Commands, game_config: Res<GameConfig>, asset_server: Res<AssetServer>) {
commands.spawn(( commands.spawn((
RootMarker::Status, RootMarker::Status,
@@ -126,6 +128,7 @@ fn setup(mut commands: Commands, game_config: Res<GameConfig>, asset_server: Res
)); ));
} }
/// Updates the status text (phase and timer).
fn update_status(phase_res: Res<CurrentPhase>, mut text_query: Query<(&mut Text, &TextType)>) { fn update_status(phase_res: Res<CurrentPhase>, mut text_query: Query<(&mut Text, &TextType)>) {
if !phase_res.is_changed() { if !phase_res.is_changed() {
return; return;
@@ -140,6 +143,7 @@ fn update_status(phase_res: Res<CurrentPhase>, mut text_query: Query<(&mut Text,
} }
} }
/// Handles HUD button interactions.
fn buttons( fn buttons(
mut commands: Commands, mut commands: Commands,
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>, mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
@@ -181,12 +185,14 @@ fn buttons(
} }
} }
/// Cleans up HUD resources.
fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) { fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) {
for entity in query.iter() { for entity in query.iter() {
commands.entity(entity).despawn(); commands.entity(entity).despawn();
} }
} }
/// Updates the timer settings display in the settings menu.
fn update_timer_settings( fn update_timer_settings(
timer_settings: ResMut<TimerSettings>, timer_settings: ResMut<TimerSettings>,
mut query: Query<(&SettingsTimerInput, &mut Text)>, mut query: Query<(&SettingsTimerInput, &mut Text)>,
@@ -215,6 +221,7 @@ fn update_timer_settings(
} }
} }
/// Updates the visibility of the shovel overlay based on inventory.
fn update_shovel_overlay_visibility( fn update_shovel_overlay_visibility(
inventory: Res<inventory::components::Inventory>, inventory: Res<inventory::components::Inventory>,
item_stacks: Query<&inventory::components::ItemStack>, item_stacks: Query<&inventory::components::ItemStack>,

View File

@@ -2,6 +2,7 @@ use super::super::components::*;
use super::timer_settings::timer_settings; use super::timer_settings::timer_settings;
use crate::prelude::*; use crate::prelude::*;
/// Spawns the settings popup.
pub fn open_settings(commands: &mut Commands) { pub fn open_settings(commands: &mut Commands) {
spawn_popup( spawn_popup(
commands, commands,

View File

@@ -1,6 +1,7 @@
use super::super::components::*; use super::super::components::*;
use crate::prelude::*; use crate::prelude::*;
/// Creates a UI bundle for a specific timer setting.
pub fn timer_settings(timer_type: TimerType) -> impl Bundle { pub fn timer_settings(timer_type: TimerType) -> impl Bundle {
( (
Node { Node {

View File

@@ -11,6 +11,7 @@ use bevy::window::PrimaryWindow;
pub mod utils; pub mod utils;
/// Handles user input for the game.
pub struct InputPlugin; pub struct InputPlugin;
impl Plugin for InputPlugin { impl Plugin for InputPlugin {
@@ -45,6 +46,7 @@ impl Plugin for InputPlugin {
} }
} }
/// Handles right-click movement input.
fn move_click( fn move_click(
mut move_messages: MessageWriter<MoveMessage>, mut move_messages: MessageWriter<MoveMessage>,
mouse_btn: Res<ButtonInput<MouseButton>>, mouse_btn: Res<ButtonInput<MouseButton>>,
@@ -75,6 +77,7 @@ fn move_click(
} }
} }
/// Handles left-click interactions (tile selection, shovel).
fn interact_click( fn interact_click(
mut tile_click_messages: MessageWriter<TileClickMessage>, mut tile_click_messages: MessageWriter<TileClickMessage>,
mouse_btn: Res<ButtonInput<MouseButton>>, mouse_btn: Res<ButtonInput<MouseButton>>,
@@ -174,6 +177,7 @@ fn interact_click(
} }
} }
} }
/// Handles debug interactions (shift + left click).
fn debug_click( fn debug_click(
mouse_btn: Res<ButtonInput<MouseButton>>, mouse_btn: Res<ButtonInput<MouseButton>>,
keys: Res<ButtonInput<KeyCode>>, keys: Res<ButtonInput<KeyCode>>,
@@ -220,6 +224,7 @@ fn debug_click(
} }
} }
/// Pauses/resumes the phase timer on Space press.
fn phase_timer_pause( fn phase_timer_pause(
mut pause_messages: MessageWriter<PhaseTimerPauseMessage>, mut pause_messages: MessageWriter<PhaseTimerPauseMessage>,
keys: Res<ButtonInput<KeyCode>>, keys: Res<ButtonInput<KeyCode>>,
@@ -229,12 +234,14 @@ fn phase_timer_pause(
} }
} }
/// Skips to the next phase on Enter press.
fn next_phase(mut messages: MessageWriter<NextPhaseMessage>, keys: Res<ButtonInput<KeyCode>>) { fn next_phase(mut messages: MessageWriter<NextPhaseMessage>, keys: Res<ButtonInput<KeyCode>>) {
if keys.just_pressed(KeyCode::Enter) { if keys.just_pressed(KeyCode::Enter) {
messages.write(NextPhaseMessage); messages.write(NextPhaseMessage);
} }
} }
/// Opens the shop on 'P' press.
fn shop_keybind( fn shop_keybind(
keys: Res<ButtonInput<KeyCode>>, keys: Res<ButtonInput<KeyCode>>,
mut commands: Commands, mut commands: Commands,
@@ -254,6 +261,7 @@ fn shop_keybind(
} }
} }
/// Closes popups on Escape press.
fn popup_keybind( fn popup_keybind(
mut close_popup_messages: MessageWriter<ClosePopupMessage>, mut close_popup_messages: MessageWriter<ClosePopupMessage>,
keys: Res<ButtonInput<KeyCode>>, keys: Res<ButtonInput<KeyCode>>,

View File

@@ -1,6 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use bevy::window::PrimaryWindow; use bevy::window::PrimaryWindow;
/// Converts mouse position to grid coordinates, respecting UI blocks.
pub fn mouse_to_grid( pub fn mouse_to_grid(
window: Single<&Window, With<PrimaryWindow>>, window: Single<&Window, With<PrimaryWindow>>,
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>, camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,

View File

@@ -1,6 +1,7 @@
use crate::features::config::components::BerrySeedConfig; use crate::features::config::components::BerrySeedConfig;
use crate::prelude::*; use crate::prelude::*;
/// Types of items available in the game.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ItemType { pub enum ItemType {
Berry, Berry,
@@ -102,18 +103,21 @@ impl ItemType {
} }
} }
/// A stack of items of a specific type.
#[derive(Component, Serialize, Deserialize, Clone, Debug)] #[derive(Component, Serialize, Deserialize, Clone, Debug)]
pub struct ItemStack { pub struct ItemStack {
pub item_type: ItemType, pub item_type: ItemType,
pub amount: u32, pub amount: u32,
} }
/// Resource containing all items owned by the player.
#[derive(Resource, Default, Serialize, Deserialize)] #[derive(Resource, Default, Serialize, Deserialize)]
pub struct Inventory { pub struct Inventory {
pub items: Vec<Entity>, pub items: Vec<Entity>,
} }
impl Inventory { impl Inventory {
/// Checks if the inventory contains a specific item type.
pub fn has_item_type(&self, items_query: &Query<&ItemStack>, item_type: ItemType) -> bool { pub fn has_item_type(&self, items_query: &Query<&ItemStack>, item_type: ItemType) -> bool {
self.items.iter().any(|&entity| { self.items.iter().any(|&entity| {
if let Ok(stack) = items_query.get(entity) { if let Ok(stack) = items_query.get(entity) {
@@ -124,6 +128,7 @@ impl Inventory {
}) })
} }
/// Adds or removes items from the inventory.
pub fn update_item_stack( pub fn update_item_stack(
&mut self, &mut self,
commands: &mut Commands, commands: &mut Commands,
@@ -193,11 +198,13 @@ impl Inventory {
} }
} }
/// Markers for inventory UI root nodes.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
Inventory, Inventory,
} }
/// Markers for inventory-related buttons.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
InventoryOpen, InventoryOpen,

View File

@@ -5,6 +5,7 @@ use components::*;
pub mod components; pub mod components;
pub mod ui; pub mod ui;
/// Plugin for the inventory system, including storage and UI.
pub struct InventoryPlugin; pub struct InventoryPlugin;
impl Plugin for InventoryPlugin { impl Plugin for InventoryPlugin {
@@ -18,6 +19,7 @@ impl Plugin for InventoryPlugin {
} }
} }
/// Handles inventory button interactions.
fn buttons( fn buttons(
mut commands: Commands, mut commands: Commands,
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>, mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
@@ -37,6 +39,7 @@ fn buttons(
} }
} }
/// Debug system to add/remove berries with arrow keys.
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn debug_modify_berries( fn debug_modify_berries(
mut commands: Commands, mut commands: Commands,

View File

@@ -2,6 +2,7 @@ use super::super::components::RootMarker;
use crate::prelude::GameConfig; use crate::prelude::GameConfig;
use crate::{features::inventory::ui::list_itemstack, prelude::*}; use crate::{features::inventory::ui::list_itemstack, prelude::*};
/// Spawns the inventory popup.
pub fn open_inventory( pub fn open_inventory(
commands: &mut Commands, commands: &mut Commands,
items: Query<&ItemStack>, items: Query<&ItemStack>,

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Creates a UI bundle for a single item stack in the inventory list.
pub fn list_itemstack( pub fn list_itemstack(
itemstack: &ItemStack, itemstack: &ItemStack,
game_config: &GameConfig, game_config: &GameConfig,

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Resource managing active notifications.
#[derive(Resource)] #[derive(Resource)]
pub struct Notifications { pub struct Notifications {
items: Vec<(Notification, NotificationLevel)>, items: Vec<(Notification, NotificationLevel)>,
@@ -44,18 +45,22 @@ impl Notifications {
} }
} }
/// Marker for the UI node containing notifications.
#[derive(Component)] #[derive(Component)]
pub struct NotificationContainer; pub struct NotificationContainer;
/// Component tracking the lifetime of a displayed notification.
#[derive(Component)] #[derive(Component)]
pub struct NotificationLifetime(pub Timer); pub struct NotificationLifetime(pub Timer);
/// Data for a single notification.
#[derive(Component)] #[derive(Component)]
pub struct Notification { pub struct Notification {
pub title: Option<String>, pub title: Option<String>,
pub message: String, pub message: String,
} }
/// Severity level of a notification.
#[derive(Component)] #[derive(Component)]
pub enum NotificationLevel { pub enum NotificationLevel {
Info, Info,

View File

@@ -7,6 +7,7 @@ use components::{NotificationContainer, NotificationLifetime, Notifications};
pub mod components; pub mod components;
pub mod ui; pub mod ui;
/// Plugin for the notification system.
pub struct NotificationPlugin; pub struct NotificationPlugin;
impl Plugin for NotificationPlugin { impl Plugin for NotificationPlugin {
@@ -17,12 +18,12 @@ impl Plugin for NotificationPlugin {
} }
} }
/// Spawns the notification container up /// Spawns the notification container up.
fn setup(mut commands: Commands) { fn setup(mut commands: Commands) {
commands.spawn(notification_container()); commands.spawn(notification_container());
} }
/// Spawns/Despawns UI elements for each item in the `Notifications` Resource /// Spawns/Despawns UI elements for each item in the `Notifications` Resource.
fn handle_notification( fn handle_notification(
mut commands: Commands, mut commands: Commands,
mut notifications: ResMut<Notifications>, mut notifications: ResMut<Notifications>,

View File

@@ -1,6 +1,7 @@
use super::components::*; use super::components::*;
use crate::prelude::*; use crate::prelude::*;
/// Creates the notification container UI bundle.
pub fn notification_container() -> impl Bundle { pub fn notification_container() -> impl Bundle {
( (
NotificationContainer, NotificationContainer,
@@ -16,6 +17,7 @@ pub fn notification_container() -> impl Bundle {
) )
} }
/// Spawns a single notification UI element.
pub fn spawn_notification( pub fn spawn_notification(
commands: &mut Commands, commands: &mut Commands,
content: Notification, content: Notification,

View File

@@ -1,6 +1,7 @@
use super::utils::format_time; use super::utils::format_time;
use crate::prelude::*; use crate::prelude::*;
/// Represents the different states of the Pomodoro timer.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Phase { pub enum Phase {
Break { duration: f32 }, Break { duration: f32 },
@@ -37,9 +38,11 @@ impl Phase {
} }
} }
/// Resource holding the current phase state.
#[derive(Resource, Debug, Serialize, Deserialize, Clone)] #[derive(Resource, Debug, Serialize, Deserialize, Clone)]
pub struct CurrentPhase(pub Phase); pub struct CurrentPhase(pub Phase);
/// Configuration for phase durations.
#[derive(Resource, Debug, Serialize, Deserialize, Clone)] #[derive(Resource, Debug, Serialize, Deserialize, Clone)]
pub struct TimerSettings { pub struct TimerSettings {
pub focus_duration: u32, pub focus_duration: u32,
@@ -59,6 +62,7 @@ impl Default for TimerSettings {
} }
} }
/// Tracks statistics for the current session.
#[derive(Resource, Debug, Default, Serialize, Deserialize, Clone)] #[derive(Resource, Debug, Default, Serialize, Deserialize, Clone)]
pub struct SessionTracker { pub struct SessionTracker {
pub completed_focus_phases: u32, pub completed_focus_phases: u32,

View File

@@ -1,12 +1,15 @@
use crate::prelude::*; use crate::prelude::*;
/// Message sent when a phase timer reaches zero.
#[derive(Message)] #[derive(Message)]
pub struct PhaseTimerFinishedMessage { pub struct PhaseTimerFinishedMessage {
pub phase: Phase, pub phase: Phase,
} }
/// Message to toggle pause state.
#[derive(Message)] #[derive(Message)]
pub struct PhaseTimerPauseMessage; pub struct PhaseTimerPauseMessage;
/// Message to proceed to the next phase.
#[derive(Message)] #[derive(Message)]
pub struct NextPhaseMessage; pub struct NextPhaseMessage;

View File

@@ -7,6 +7,7 @@ pub mod components;
pub mod messages; pub mod messages;
pub mod utils; pub mod utils;
/// Plugin managing the Pomodoro phase timer and state.
pub struct PhasePlugin; pub struct PhasePlugin;
impl Plugin for PhasePlugin { impl Plugin for PhasePlugin {
@@ -36,6 +37,7 @@ impl Plugin for PhasePlugin {
} }
} }
/// Debug system to shorten phase duration for testing.
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn debug_short_phase_duration( fn debug_short_phase_duration(
mut phase_res: ResMut<CurrentPhase>, mut phase_res: ResMut<CurrentPhase>,
@@ -55,6 +57,7 @@ fn debug_short_phase_duration(
} }
} }
/// Updates the current phase duration from settings.
fn load_rules(mut phase_res: ResMut<CurrentPhase>, settings: Res<TimerSettings>) { fn load_rules(mut phase_res: ResMut<CurrentPhase>, settings: Res<TimerSettings>) {
let phase = &mut phase_res.0; let phase = &mut phase_res.0;
@@ -71,6 +74,7 @@ fn load_rules(mut phase_res: ResMut<CurrentPhase>, settings: Res<TimerSettings>)
} }
} }
/// Ticks the phase timer and handles completion.
fn tick_timer( fn tick_timer(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
@@ -107,7 +111,7 @@ fn tick_timer(
} }
} }
/// Rewards the player at the end of a focus phase with `berries_per_focus_minute` * `focus_duration` /// Rewards the player at the end of a focus phase with `berries_per_focus_minute` * `focus_duration`.
fn grant_focus_rewards( fn grant_focus_rewards(
mut messages: MessageReader<PhaseTimerFinishedMessage>, mut messages: MessageReader<PhaseTimerFinishedMessage>,
config: Res<GameConfig>, config: Res<GameConfig>,
@@ -147,6 +151,7 @@ fn grant_focus_rewards(
} }
} }
/// Toggles pause state of the timer.
fn handle_pause( fn handle_pause(
mut messages: MessageReader<PhaseTimerPauseMessage>, mut messages: MessageReader<PhaseTimerPauseMessage>,
mut phase_res: ResMut<CurrentPhase>, mut phase_res: ResMut<CurrentPhase>,
@@ -171,6 +176,7 @@ fn handle_pause(
} }
} }
/// Transitions to the next phase based on current state.
pub fn next_phase( pub fn next_phase(
current_phase: &mut CurrentPhase, current_phase: &mut CurrentPhase,
session_tracker: &mut SessionTracker, session_tracker: &mut SessionTracker,
@@ -204,6 +210,7 @@ pub fn next_phase(
} }
} }
/// Handles transition to the next phase after user confirmation.
pub fn handle_continue( pub fn handle_continue(
mut messages: MessageReader<NextPhaseMessage>, mut messages: MessageReader<NextPhaseMessage>,
mut phase_res: ResMut<CurrentPhase>, mut phase_res: ResMut<CurrentPhase>,

View File

@@ -1,3 +1,4 @@
/// Formats seconds into MM:SS or HH:MM:SS string.
pub fn format_time(seconds: f32) -> String { pub fn format_time(seconds: f32) -> String {
let seconds = seconds.max(0.0) as u32; let seconds = seconds.max(0.0) as u32;

View File

@@ -1,5 +1,6 @@
use crate::{features::phase::components::SessionTracker, prelude::*}; use crate::{features::phase::components::SessionTracker, prelude::*};
/// Actions Pom can perform on tiles.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum InteractionAction { pub enum InteractionAction {
Plant(ItemType), Plant(ItemType),

View File

@@ -2,20 +2,24 @@ use crate::features::pom::actions::InteractionAction;
use crate::prelude::*; use crate::prelude::*;
use std::collections::VecDeque; use std::collections::VecDeque;
/// Marker component for the main character.
#[derive(Component)] #[derive(Component)]
pub struct Pom; pub struct Pom;
/// Current logical position on the grid.
#[derive(Component, Serialize, Deserialize, Clone, Copy, Default)] #[derive(Component, Serialize, Deserialize, Clone, Copy, Default)]
pub struct GridPosition { pub struct GridPosition {
pub x: u32, pub x: u32,
pub y: u32, pub y: u32,
} }
/// Queue of grid positions to visit.
#[derive(Component, Default)] #[derive(Component, Default)]
pub struct PathQueue { pub struct PathQueue {
pub steps: VecDeque<(u32, u32)>, pub steps: VecDeque<(u32, u32)>,
} }
/// Movement direction state for animation.
#[derive(Component, Default)] #[derive(Component, Default)]
pub enum MovingState { pub enum MovingState {
#[default] #[default]
@@ -38,6 +42,7 @@ impl MovingState {
} }
} }
/// Target tile and action for pending interaction.
#[derive(Component, Default)] #[derive(Component, Default)]
pub struct InteractionTarget { pub struct InteractionTarget {
pub target: Option<(u32, u32)>, pub target: Option<(u32, u32)>,

View File

@@ -1,17 +1,20 @@
use crate::features::pom::actions::InteractionAction; use crate::features::pom::actions::InteractionAction;
use crate::prelude::*; use crate::prelude::*;
/// Request to move Pom to a specific tile.
#[derive(Message)] #[derive(Message)]
pub struct MoveMessage { pub struct MoveMessage {
pub x: u32, pub x: u32,
pub y: u32, pub y: u32,
} }
/// Notification that a move request was invalid.
#[derive(Message)] #[derive(Message)]
pub struct InvalidMoveMessage { pub struct InvalidMoveMessage {
pub message: String, pub message: String,
} }
/// Request to start an interaction sequence.
#[derive(Message)] #[derive(Message)]
pub struct InteractStartMessage { pub struct InteractStartMessage {
pub x: u32, pub x: u32,
@@ -19,6 +22,7 @@ pub struct InteractStartMessage {
pub action: InteractionAction, pub action: InteractionAction,
} }
/// Notification that a tile was clicked (requesting context menu).
#[derive(Message)] #[derive(Message)]
pub struct TileClickMessage { pub struct TileClickMessage {
pub x: u32, pub x: u32,

View File

@@ -11,6 +11,7 @@ pub mod messages;
pub mod ui; pub mod ui;
pub mod utils; pub mod utils;
/// Plugin controlling the main character (Pom) behavior.
pub struct PomPlugin; pub struct PomPlugin;
impl Plugin for PomPlugin { impl Plugin for PomPlugin {
@@ -34,6 +35,7 @@ impl Plugin for PomPlugin {
} }
} }
/// Draws the path Pom will follow using gizmos.
fn draw_path( fn draw_path(
mut gizmos: Gizmos, mut gizmos: Gizmos,
query: Query<(&Transform, &PathQueue), With<Pom>>, query: Query<(&Transform, &PathQueue), With<Pom>>,
@@ -65,6 +67,7 @@ fn draw_path(
} }
} }
/// Spawns the Pom character.
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) { fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) {
commands.spawn(( commands.spawn((
Pom, Pom,
@@ -87,12 +90,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<Gam
)); ));
} }
/// Despawns the Pom character.
fn cleanup(mut commands: Commands, pom_query: Query<Entity, With<Pom>>) { fn cleanup(mut commands: Commands, pom_query: Query<Entity, With<Pom>>) {
for pom_entity in pom_query.iter() { for pom_entity in pom_query.iter() {
commands.entity(pom_entity).despawn(); commands.entity(pom_entity).despawn();
} }
} }
/// Calculates path for manual movement requests.
fn handle_move( fn handle_move(
mut move_messages: MessageReader<MoveMessage>, mut move_messages: MessageReader<MoveMessage>,
mut invalid_move_messages: MessageWriter<InvalidMoveMessage>, mut invalid_move_messages: MessageWriter<InvalidMoveMessage>,
@@ -127,6 +132,7 @@ fn handle_move(
} }
} }
/// Calculates path to interaction target.
fn handle_interact( fn handle_interact(
mut interact_messages: MessageReader<InteractStartMessage>, mut interact_messages: MessageReader<InteractStartMessage>,
mut pom_query: Query<(&GridPosition, &mut PathQueue, &mut InteractionTarget)>, mut pom_query: Query<(&GridPosition, &mut PathQueue, &mut InteractionTarget)>,
@@ -184,6 +190,7 @@ fn handle_interact(
} }
} }
/// Executes the pending interaction when target is reached.
pub fn perform_interaction( pub fn perform_interaction(
mut pom_query: Query<(&GridPosition, &mut InteractionTarget, &PathQueue)>, mut pom_query: Query<(&GridPosition, &mut InteractionTarget, &PathQueue)>,
grid: Res<Grid>, grid: Res<Grid>,
@@ -239,6 +246,7 @@ pub fn perform_interaction(
} }
} }
/// Moves the Pom character along the path.
fn move_pom( fn move_pom(
time: Res<Time>, time: Res<Time>,
mut query: Query<( mut query: Query<(
@@ -288,6 +296,7 @@ fn move_pom(
} }
} }
/// Updates Pom animation based on movement state.
fn update_pom(asset_server: Res<AssetServer>, mut query: Query<(&MovingState, &mut AseAnimation)>) { fn update_pom(asset_server: Res<AssetServer>, mut query: Query<(&MovingState, &mut AseAnimation)>) {
for (moving_state, mut animation) in query.iter_mut() { for (moving_state, mut animation) in query.iter_mut() {
match moving_state { match moving_state {

View File

@@ -4,11 +4,13 @@ use crate::features::ui::utils::ui_blocks;
use crate::prelude::*; use crate::prelude::*;
use bevy::window::PrimaryWindow; use bevy::window::PrimaryWindow;
/// Marker for context menu UI root.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
ContextMenu, ContextMenu,
} }
/// Buttons available in the context menu.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
Interact { Interact {
@@ -19,6 +21,7 @@ pub enum ButtonType {
Cancel, Cancel,
} }
/// Spawns the context menu at the clicked tile position.
pub fn open_context_menu( pub fn open_context_menu(
mut commands: Commands, mut commands: Commands,
mut tile_click_messages: MessageReader<TileClickMessage>, mut tile_click_messages: MessageReader<TileClickMessage>,
@@ -87,6 +90,7 @@ pub fn open_context_menu(
} }
} }
/// Closes context menu when clicking elsewhere.
pub fn click_outside_context_menu( pub fn click_outside_context_menu(
mut commands: Commands, mut commands: Commands,
mouse_btn: Res<ButtonInput<MouseButton>>, mouse_btn: Res<ButtonInput<MouseButton>>,
@@ -107,6 +111,7 @@ pub fn click_outside_context_menu(
} }
} }
/// Handles context menu button clicks.
pub fn buttons( pub fn buttons(
mut commands: Commands, mut commands: Commands,
mut button_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>, mut button_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,
@@ -133,6 +138,7 @@ pub fn buttons(
} }
} }
/// Closes context menu on ClosePopupMessage.
pub fn close_context_menu( pub fn close_context_menu(
mut commands: Commands, mut commands: Commands,
mut close_popup_reader: MessageReader<ClosePopupMessage>, mut close_popup_reader: MessageReader<ClosePopupMessage>,

View File

@@ -2,6 +2,7 @@ use crate::prelude::*;
pub mod context_menu; pub mod context_menu;
/// Plugin for Pom-related UI (context menu).
pub struct PomUiPlugin; pub struct PomUiPlugin;
impl Plugin for PomUiPlugin { impl Plugin for PomUiPlugin {

View File

@@ -2,6 +2,7 @@ use crate::prelude::*;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
/// A star pathfinding node.
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
pub struct Node { pub struct Node {
x: u32, x: u32,
@@ -25,11 +26,12 @@ impl PartialOrd for Node {
} }
} }
/// Calculates Manhattan distance between two points.
pub fn manhattan_distance(x1: u32, y1: u32, x2: u32, y2: u32) -> u32 { pub fn manhattan_distance(x1: u32, y1: u32, x2: u32, y2: u32) -> u32 {
x1.abs_diff(x2) + y1.abs_diff(y2) x1.abs_diff(x2) + y1.abs_diff(y2)
} }
/// Checks if Pom would be trapped in a small, isolated area if a specific tile is blocked /// Checks if Pom would be trapped in a small, isolated area if a specific tile is blocked.
pub fn is_trapped<F>( pub fn is_trapped<F>(
start: (u32, u32), start: (u32, u32),
blocked_pos: (u32, u32), blocked_pos: (u32, u32),
@@ -98,6 +100,7 @@ where
visited.len() < min_safe_area visited.len() < min_safe_area
} }
/// Finds a path from start to end using A* algorithm.
pub fn find_path( pub fn find_path(
start: (u32, u32), start: (u32, u32),
end: (u32, u32), end: (u32, u32),

View File

@@ -2,9 +2,11 @@ use crate::prelude::*;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
/// Resource containing the path to the current save file.
#[derive(Resource, Clone, Debug)] #[derive(Resource, Clone, Debug)]
pub struct SavegamePath(pub PathBuf); pub struct SavegamePath(pub PathBuf);
/// Metadata about a savegame.
#[derive(Debug)] #[derive(Debug)]
pub struct SavegameInfo { pub struct SavegameInfo {
pub path: SavegamePath, pub path: SavegamePath,
@@ -13,11 +15,13 @@ pub struct SavegameInfo {
pub completed_focus: u32, pub completed_focus: u32,
} }
/// Helper for partial JSON deserialization.
#[derive(Deserialize)] #[derive(Deserialize)]
struct PartialSaveData { struct PartialSaveData {
session_tracker: PartialSessionTracker, session_tracker: PartialSessionTracker,
} }
/// Helper for partial JSON deserialization of session stats.
#[derive(Deserialize)] #[derive(Deserialize)]
struct PartialSessionTracker { struct PartialSessionTracker {
completed_focus_phases: u32, completed_focus_phases: u32,
@@ -26,6 +30,7 @@ struct PartialSessionTracker {
} }
impl SavegamePath { impl SavegamePath {
/// Constructs a new path for a specific save index.
pub fn new(index: u32) -> Self { pub fn new(index: u32) -> Self {
let base_path = get_internal_path().unwrap_or_else(|| { let base_path = get_internal_path().unwrap_or_else(|| {
println!( println!(
@@ -41,6 +46,7 @@ impl SavegamePath {
Self(base_path.join(format!("savegame-{}.json", index))) Self(base_path.join(format!("savegame-{}.json", index)))
} }
/// Lists all available savegames.
pub fn list() -> Vec<SavegameInfo> { pub fn list() -> Vec<SavegameInfo> {
let mut savegames = Vec::new(); let mut savegames = Vec::new();
@@ -88,6 +94,7 @@ impl SavegamePath {
savegames savegames
} }
/// Returns a path for a new savegame (incremented index).
pub fn next() -> Self { pub fn next() -> Self {
let savegames = Self::list(); let savegames = Self::list();
let next_index = savegames.last().map(|s| s.index + 1).unwrap_or(0); let next_index = savegames.last().map(|s| s.index + 1).unwrap_or(0);
@@ -95,11 +102,13 @@ impl SavegamePath {
} }
} }
/// Markers for savegame UI.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
PopupSavegameLoad, PopupSavegameLoad,
} }
/// Buttons for savegame management.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
SavegameLoad { savegame_path: SavegamePath }, SavegameLoad { savegame_path: SavegamePath },

View File

@@ -1,7 +1,9 @@
use crate::prelude::*; use crate::prelude::*;
/// Trigger to save the current game.
#[derive(Message)] #[derive(Message)]
pub struct SavegameDumpMessage; pub struct SavegameDumpMessage;
/// Trigger to load a game from disk.
#[derive(Message)] #[derive(Message)]
pub struct SavegameLoadMessage; pub struct SavegameLoadMessage;

View File

@@ -10,6 +10,7 @@ pub mod components;
pub mod messages; pub mod messages;
pub mod ui; pub mod ui;
/// Plugin dealing with savegame loading and saving.
pub struct SavegamePlugin; pub struct SavegamePlugin;
impl Plugin for SavegamePlugin { impl Plugin for SavegamePlugin {
@@ -25,6 +26,7 @@ impl Plugin for SavegamePlugin {
} }
} }
/// The structure of a save file.
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct SaveData { struct SaveData {
grid_width: u32, grid_width: u32,
@@ -37,6 +39,7 @@ struct SaveData {
inventory: Vec<ItemStack>, inventory: Vec<ItemStack>,
} }
/// Serializes game state and writes it to a file.
fn dump_savegame( fn dump_savegame(
mut messages: MessageReader<SavegameDumpMessage>, mut messages: MessageReader<SavegameDumpMessage>,
save_path: Res<SavegamePath>, save_path: Res<SavegamePath>,
@@ -106,6 +109,7 @@ fn dump_savegame(
} }
} }
/// Reads a save file and restores game state.
fn load_savegame( fn load_savegame(
mut commands: Commands, mut commands: Commands,
mut messages: MessageReader<SavegameLoadMessage>, mut messages: MessageReader<SavegameLoadMessage>,
@@ -174,7 +178,7 @@ fn load_savegame(
} }
} }
/// Resets all components/resources loaded by `load_savegame` /// Resets all components/resources loaded by `load_savegame`.
fn reset_savegame( fn reset_savegame(
mut commands: Commands, mut commands: Commands,
grid: Res<Grid>, grid: Res<Grid>,

View File

@@ -1,6 +1,7 @@
use super::super::components::{ButtonType, RootMarker}; use super::super::components::{ButtonType, RootMarker};
use crate::{features::savegame::messages::SavegameLoadMessage, prelude::*}; use crate::{features::savegame::messages::SavegameLoadMessage, prelude::*};
/// Spawns the "Load Game" popup.
pub fn spawn_load_popup(commands: &mut Commands) { pub fn spawn_load_popup(commands: &mut Commands) {
spawn_popup( spawn_popup(
commands, commands,
@@ -88,6 +89,7 @@ pub fn spawn_load_popup(commands: &mut Commands) {
); );
} }
/// Handles interactions in the load popup.
pub fn load_popup_handler( pub fn load_popup_handler(
mut commands: Commands, mut commands: Commands,
mut next_state: ResMut<NextState<AppState>>, mut next_state: ResMut<NextState<AppState>>,

View File

@@ -1,16 +1,19 @@
use crate::prelude::*; use crate::prelude::*;
/// Markers for shop UI.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
Shop, Shop,
} }
/// Buttons in the shop.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
ShopOpen, ShopOpen,
ShopBuyItem(ShopOffer), ShopBuyItem(ShopOffer),
} }
/// An item available for purchase.
#[derive(Clone)] #[derive(Clone)]
pub struct ShopOffer { pub struct ShopOffer {
pub item: ItemStack, pub item: ItemStack,
@@ -18,6 +21,7 @@ pub struct ShopOffer {
} }
impl ShopOffer { impl ShopOffer {
/// Generates a list of all current offers.
pub fn list_all(game_config: &GameConfig, tile_count: u32) -> Vec<ShopOffer> { pub fn list_all(game_config: &GameConfig, tile_count: u32) -> Vec<ShopOffer> {
let mut offers = Vec::new(); let mut offers = Vec::new();
@@ -50,6 +54,7 @@ impl ShopOffer {
offers offers
} }
/// Attempts to purchase the offer.
pub fn buy( pub fn buy(
&self, &self,
inventory: &mut Inventory, inventory: &mut Inventory,

View File

@@ -5,6 +5,7 @@ use ui::open_shop;
pub mod components; pub mod components;
pub mod ui; pub mod ui;
/// Plugin for the in-game shop.
pub struct ShopPlugin; pub struct ShopPlugin;
impl Plugin for ShopPlugin { impl Plugin for ShopPlugin {
@@ -13,6 +14,7 @@ impl Plugin for ShopPlugin {
} }
} }
/// Handles shop button interactions.
fn buttons( fn buttons(
mut commands: Commands, mut commands: Commands,
mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>, mut interaction_query: Query<(&Interaction, &ButtonType), (Changed<Interaction>, With<Button>)>,

View File

@@ -1,6 +1,7 @@
use super::super::components::*; use super::super::components::*;
use crate::{features::inventory::ui::item::list_itemstack, prelude::*}; use crate::{features::inventory::ui::item::list_itemstack, prelude::*};
/// Creates the UI bundle for a shop offer.
pub fn shop_offer( pub fn shop_offer(
offer: &ShopOffer, offer: &ShopOffer,
game_config: &GameConfig, game_config: &GameConfig,
@@ -26,6 +27,7 @@ pub fn shop_offer(
) )
} }
/// Creates the UI bundle for displaying a price.
pub fn shop_price( pub fn shop_price(
price: u32, price: u32,
asset_server: &Res<AssetServer>, asset_server: &Res<AssetServer>,

View File

@@ -1,6 +1,7 @@
use super::super::components::*; use super::super::components::*;
use crate::{features::shop::ui::shop_offer, prelude::*}; use crate::{features::shop::ui::shop_offer, prelude::*};
/// Spawns the shop popup.
pub fn open_shop( pub fn open_shop(
commands: &mut Commands, commands: &mut Commands,
game_config: &GameConfig, game_config: &GameConfig,

View File

@@ -1,10 +1,12 @@
use crate::prelude::*; use crate::prelude::*;
/// Markers for main menu UI.
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
MainMenu, MainMenu,
} }
/// Buttons in the main menu.
#[derive(Component)] #[derive(Component)]
pub enum ButtonType { pub enum ButtonType {
LoadGame, LoadGame,

View File

@@ -4,6 +4,7 @@ use components::*;
pub mod components; pub mod components;
/// Plugin for the main menu screen.
pub struct StartScreenPlugin; pub struct StartScreenPlugin;
impl Plugin for StartScreenPlugin { impl Plugin for StartScreenPlugin {
@@ -14,6 +15,7 @@ impl Plugin for StartScreenPlugin {
} }
} }
/// Spawns the main menu UI.
fn setup(mut commands: Commands) { fn setup(mut commands: Commands) {
commands.spawn(( commands.spawn((
RootMarker::MainMenu, RootMarker::MainMenu,
@@ -60,6 +62,7 @@ fn setup(mut commands: Commands) {
)); ));
} }
/// Handles main menu button interactions.
fn menu( fn menu(
mut commands: Commands, mut commands: Commands,
mut next_state: ResMut<NextState<AppState>>, mut next_state: ResMut<NextState<AppState>>,
@@ -84,6 +87,7 @@ fn menu(
} }
} }
/// Cleans up main menu resources.
fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) { fn cleanup(mut commands: Commands, query: Query<Entity, With<RootMarker>>) {
for entity in query.iter() { for entity in query.iter() {
commands.entity(entity).despawn(); commands.entity(entity).despawn();

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Event triggering a scroll action on an entity.
#[derive(EntityEvent, Debug)] #[derive(EntityEvent, Debug)]
#[entity_event(propagate, auto_propagate)] #[entity_event(propagate, auto_propagate)]
pub struct Scroll { pub struct Scroll {
@@ -7,6 +8,7 @@ pub struct Scroll {
pub delta: Vec2, pub delta: Vec2,
} }
/// Visual styles for buttons.
#[derive(Component, Clone)] #[derive(Component, Clone)]
pub enum ButtonVariant { pub enum ButtonVariant {
Primary, Primary,

View File

@@ -1,6 +1,10 @@
use crate::prelude::*; use crate::prelude::*;
/// Pixel height of a single scroll line.
pub const LINE_HEIGHT: f32 = 21.0; pub const LINE_HEIGHT: f32 = 21.0;
/// Default background color for buttons.
pub const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15); pub const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
/// Background color when hovering a button.
pub const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25); pub const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
/// Background color when pressing a button.
pub const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35); pub const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

View File

@@ -1,4 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
/// Message to close any open popup.
#[derive(Message)] #[derive(Message)]
pub struct ClosePopupMessage; pub struct ClosePopupMessage;

View File

@@ -7,6 +7,7 @@ pub mod messages;
pub mod ui; pub mod ui;
pub mod utils; pub mod utils;
/// Plugin for general UI behavior like scrolling and button states.
pub struct UiPlugin; pub struct UiPlugin;
impl Plugin for UiPlugin { impl Plugin for UiPlugin {
@@ -20,6 +21,7 @@ impl Plugin for UiPlugin {
} }
} }
/// Reads mouse wheel events and triggers scroll actions.
fn scroll_events( fn scroll_events(
mut mouse_wheel_reader: MessageReader<MouseWheel>, mut mouse_wheel_reader: MessageReader<MouseWheel>,
hover_map: Res<HoverMap>, hover_map: Res<HoverMap>,
@@ -45,6 +47,7 @@ fn scroll_events(
} }
} }
/// Updates scroll position based on scroll events.
fn on_scroll_handler( fn on_scroll_handler(
mut scroll: On<components::Scroll>, mut scroll: On<components::Scroll>,
mut query: Query<(&mut ScrollPosition, &Node, &ComputedNode)>, mut query: Query<(&mut ScrollPosition, &Node, &ComputedNode)>,

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Creates a standard button UI bundle.
pub fn button<C, R>( pub fn button<C, R>(
button_type: impl Component, button_type: impl Component,
variant: ButtonVariant, variant: ButtonVariant,
@@ -24,6 +25,7 @@ where
) )
} }
/// Creates a rounded pill-shaped button UI bundle.
pub fn pill_button<C, R>( pub fn pill_button<C, R>(
button_type: impl Component, button_type: impl Component,
variant: ButtonVariant, variant: ButtonVariant,
@@ -48,6 +50,7 @@ where
) )
} }
/// Updates button colors based on interaction state.
pub fn update_buttons( pub fn update_buttons(
mut interaction_query: Query< mut interaction_query: Query<
(&Interaction, &ButtonVariant, &mut BackgroundColor), (&Interaction, &ButtonVariant, &mut BackgroundColor),

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Trait for easy flexbox layout construction.
pub trait Flexbox { pub trait Flexbox {
fn hstack(spacing: Val) -> Self; fn hstack(spacing: Val) -> Self;
fn vstack(spacing: Val) -> Self; fn vstack(spacing: Val) -> Self;

View File

@@ -3,12 +3,15 @@ use bevy::ecs::relationship::RelatedSpawnerCommands;
use super::super::messages::ClosePopupMessage; use super::super::messages::ClosePopupMessage;
use crate::prelude::*; use crate::prelude::*;
/// Marker for popup root nodes.
#[derive(Component)] #[derive(Component)]
pub struct PopupRoot; pub struct PopupRoot;
/// Marker for the close button in a popup.
#[derive(Component)] #[derive(Component)]
pub struct PopupCloseButton; pub struct PopupCloseButton;
/// Spawns a generic popup window.
pub fn spawn_popup( pub fn spawn_popup(
commands: &mut Commands, commands: &mut Commands,
root: impl Component, root: impl Component,
@@ -68,6 +71,7 @@ pub fn spawn_popup(
}); });
} }
/// Spawns a context menu at a specific position.
pub fn spawn_context_menu( pub fn spawn_context_menu(
commands: &mut Commands, commands: &mut Commands,
root: impl Component, root: impl Component,
@@ -93,6 +97,7 @@ pub fn spawn_context_menu(
.with_children(child); .with_children(child);
} }
/// Handles closing popups via message or close button.
pub fn handle_popup_close( pub fn handle_popup_close(
mut commands: Commands, mut commands: Commands,
root_query: Query<Entity, With<PopupRoot>>, root_query: Query<Entity, With<PopupRoot>>,

View File

@@ -1,5 +1,6 @@
pub use crate::prelude::*; pub use crate::prelude::*;
/// Creates a basic text bundle.
pub fn text(content: impl Into<String>, size: f32, color: Color) -> (Text, TextFont, TextColor) { pub fn text(content: impl Into<String>, size: f32, color: Color) -> (Text, TextFont, TextColor) {
( (
Text::new(content), Text::new(content),
@@ -8,6 +9,7 @@ pub fn text(content: impl Into<String>, size: f32, color: Color) -> (Text, TextF
) )
} }
/// Creates a text bundle with an additional component attached.
pub fn text_with_component( pub fn text_with_component(
component: impl Component, component: impl Component,
content: impl Into<String>, content: impl Into<String>,

View File

@@ -1,6 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use bevy::window::PrimaryWindow; use bevy::window::PrimaryWindow;
/// Checks if the cursor is hovering over any UI element.
pub fn ui_blocks( pub fn ui_blocks(
window: Single<&Window, With<PrimaryWindow>>, window: Single<&Window, With<PrimaryWindow>>,
cursor_pos: Vec2, cursor_pos: Vec2,

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
/// Defines the bounds of the grid for the server.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct MaxFieldSize { pub struct MaxFieldSize {
#[serde(rename = "minX")] #[serde(rename = "minX")]
@@ -12,12 +13,14 @@ pub struct MaxFieldSize {
pub max_y: u32, pub max_y: u32,
} }
/// Coordinates for a wonder event target.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Position { pub struct Position {
pub x: u32, pub x: u32,
pub y: u32, pub y: u32,
} }
/// WebSocket messages exchanged with the wonder event server.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(tag = "messageType")] #[serde(tag = "messageType")]
pub enum WonderEventMessage { pub enum WonderEventMessage {

View File

@@ -9,20 +9,25 @@ use url::Url;
pub mod components; pub mod components;
/// Plugin managing random wonder events via WebSocket.
pub struct WonderEventPlugin; pub struct WonderEventPlugin;
/// Message to initiate a wonder event request.
#[derive(Message)] #[derive(Message)]
pub struct RequestWonderEvent { pub struct RequestWonderEvent {
pub url_str: String, pub url_str: String,
pub max_field_size: MaxFieldSize, pub max_field_size: MaxFieldSize,
} }
/// Resource holding the channel sender for wonder events.
#[derive(Resource)] #[derive(Resource)]
pub struct WonderEventSender(pub Sender<WonderEventMessage>); pub struct WonderEventSender(pub Sender<WonderEventMessage>);
/// Resource holding the channel receiver for wonder events.
#[derive(Resource)] #[derive(Resource)]
pub struct WonderEventReceiver(pub Mutex<Receiver<WonderEventMessage>>); pub struct WonderEventReceiver(pub Mutex<Receiver<WonderEventMessage>>);
/// Component for animated floating text effects.
#[derive(Component)] #[derive(Component)]
struct FloatingText { struct FloatingText {
timer: Timer, timer: Timer,
@@ -49,11 +54,13 @@ impl Plugin for WonderEventPlugin {
} }
} }
/// Tracks if an event has already triggered this phase.
#[derive(Resource, Default)] #[derive(Resource, Default)]
struct WonderEventState { struct WonderEventState {
triggered_for_current_phase: bool, triggered_for_current_phase: bool,
} }
/// Checks if the focus phase is halfway through to trigger an event.
fn check_halfway_focus( fn check_halfway_focus(
mut state: ResMut<WonderEventState>, mut state: ResMut<WonderEventState>,
phase_res: Res<CurrentPhase>, phase_res: Res<CurrentPhase>,
@@ -95,6 +102,7 @@ fn check_halfway_focus(
} }
} }
/// Spawns a thread to request a wonder event from the server.
fn handle_wonder_event_trigger( fn handle_wonder_event_trigger(
mut events: MessageReader<RequestWonderEvent>, mut events: MessageReader<RequestWonderEvent>,
sender: Res<WonderEventSender>, sender: Res<WonderEventSender>,
@@ -159,6 +167,7 @@ fn handle_wonder_event_trigger(
} }
} }
/// Processes responses from the wonder event server.
fn handle_wonder_event_response( fn handle_wonder_event_response(
receiver: Res<WonderEventReceiver>, receiver: Res<WonderEventReceiver>,
grid: Res<Grid>, grid: Res<Grid>,
@@ -241,6 +250,7 @@ fn handle_wonder_event_response(
} }
} }
/// Updates floating text positions and lifetimes.
fn animate_floating_text( fn animate_floating_text(
mut commands: Commands, mut commands: Commands,
time: Res<Time>, time: Res<Time>,

View File

@@ -1,6 +1,7 @@
use directories::ProjectDirs; use directories::ProjectDirs;
use std::path::PathBuf; use std::path::PathBuf;
/// Returns the platform-specific data directory for the application.
pub fn get_internal_path() -> Option<PathBuf> { pub fn get_internal_path() -> Option<PathBuf> {
let project_dirs = ProjectDirs::from("de", "demenik", "pomomon-garden"); let project_dirs = ProjectDirs::from("de", "demenik", "pomomon-garden");