From 4a8b791acb258fd8ed630bb101b3f9556b31fed4 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 10 Feb 2022 11:54:57 -0500 Subject: [PATCH] Separate binary from game engine --- Cargo.toml | 2 +- Makefile | 2 +- README.md | 4 +- src/effects.rs | 1 + src/gamelog/events.rs | 2 + src/gamelog/logstore.rs | 1 + src/lib.rs | 185 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 186 +--------------------------------------- src/raws.rs | 1 + src/raws/rawmaster.rs | 1 + src/rng.rs | 4 + src/spatial.rs | 1 + 12 files changed, 202 insertions(+), 188 deletions(-) create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index b13462f..469eb0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "roguelike_tutorial" +name = "tim_rogue" version = "0.1.0" rust-version = "1.56" edition = "2021" diff --git a/Makefile b/Makefile index c3373ac..e573d8a 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,6 @@ fix: $(call print-help, fix, Fixes some warnings, then runs the formatter) make fmt docs: $(call print-help, docs, Generates code docs) - cargo doc --features $(FEATURES) + cargo doc --features $(FEATURES) --document-private-items .phony: run-pi clean check run fmt fix lint docs build build-wasm check-wasm build-wasm-dev \ No newline at end of file diff --git a/README.md b/README.md index 6921b03..54b584a 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,6 @@ If you want to see what else you can run with Makefile, run `make help`. This wi * Added a macro to register components for `specs`, like was in the tutorial for saving/loading. * Game state machine is moved to `src/state.rs` * Colors (Bracket-lib `RGB` struct) have been converted to static values in `src/colors.rs`, to cut down on boilerplate and numbers of ways of generating color values. -* All references to `rltk` have been converted to `bracket_lib`, as `rltk` was a facade in `bracket_lib` \ No newline at end of file +* All references to `rltk` have been converted to `bracket_lib`, as `rltk` was a facade in `bracket_lib` +* Made the crate a library and binary, with the binary just starting and running the game engine +* Submodules use named files as the module base, rather than `mod.rs` \ No newline at end of file diff --git a/src/effects.rs b/src/effects.rs index b3a7e99..10eea2f 100644 --- a/src/effects.rs +++ b/src/effects.rs @@ -10,6 +10,7 @@ use std::collections::{HashSet, VecDeque}; use std::sync::Mutex; use ::bracket_lib::prelude::*; +use ::lazy_static::lazy_static; use ::specs::prelude::*; pub use targeting::*; diff --git a/src/gamelog/events.rs b/src/gamelog/events.rs index 3b3e0db..fe14dce 100644 --- a/src/gamelog/events.rs +++ b/src/gamelog/events.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; use std::sync::Mutex; +use ::lazy_static::lazy_static; + lazy_static! { static ref EVENTS: Mutex> = Mutex::new(HashMap::new()); } diff --git a/src/gamelog/logstore.rs b/src/gamelog/logstore.rs index 4309cf4..ed71953 100644 --- a/src/gamelog/logstore.rs +++ b/src/gamelog/logstore.rs @@ -1,6 +1,7 @@ use std::sync::Mutex; use ::bracket_lib::prelude::*; +use ::lazy_static::lazy_static; use super::LogFragment; use crate::colors; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..fc4d7bb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,185 @@ +//! Roguelike +//! +//! An implementation of a rogue-like dungeon-crawler game. + +mod colors; +mod components; +mod damage_system; +mod effects; +mod gamelog; +mod gamesystem; +mod gui; +mod map; +mod map_builders; +mod player; +mod random_table; +pub mod raws; +mod rect; +mod rex_assets; +mod rng; +mod saveload_system; +mod spatial; +mod spawner; +mod state; +mod systems; + +use ::bracket_lib::prelude::*; +use ::specs::prelude::*; +use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator}; +use components::*; +use map::*; +use rect::Rect; +use state::*; + +/// Cut down on the amount of syntax to register components +/// +/// Compare: +/// ```ignore +/// let mut game_state = State::new(); +/// +/// register!(state <- ComponentA, ComponentB, ...); +/// ``` +/// +/// Without macro: +/// ```ignore +/// let mut game_state = State::new(); +/// +/// state.ecs.register::(); +/// state.ecs.register::(); +/// ``` +macro_rules! register { + // $state is needed to get the scope at the usage point + // $Type is the Component type that is being registered + ($state: ident <- $( $Type: ty ),*,) => { + $( + $state.ecs.register::<$Type>(); + )* + } +} + +/// Register the Component Structs with Specs +fn register_components() -> State { + let mut state = State::new(); + + register!( + state <- + AlwaysTargetsSelf, + ApplyMove, + ApplyTeleport, + AreaOfEffect, + AttributeBonus, + Attributes, + BlocksTile, + BlocksVisibility, + Chasing, + Confusion, + Consumable, + CursedItem, + DamageOverTime, + DMSerializationHelper, + Door, + Duration, + EntityMoved, + EntryTrigger, + EquipmentChanged, + Equippable, + Equipped, + Faction, + Hidden, + HungerClock, + IdentifiedItem, + InBackpack, + InflictsDamage, + Initiative, + Item, + KnownSpells, + LightSource, + LootTable, + MagicItem, + MagicMapper, + MoveMode, + MyTurn, + Name, + NaturalAttackDefense, + ObfuscatedName, + OnDeath, + OtherLevelPosition, + ParticleLifetime, + Player, + Pools, + Position, + ProvidesFood, + ProvidesHealing, + ProvidesIdentification, + ProvidesMana, + ProvidesRemoveCurse, + Quips, + Ranged, + Renderable, + SerializationHelper, + SimpleMarker, + SingleActivation, + Skills, + Slow, + SpawnParticleBurst, + SpawnParticleLine, + SpecialAbilities, + SpellTemplate, + StatusEffect, + Target, + TeachesSpell, + TeleportTo, + TileSize, + TownPortal, + Vendor, + Viewshed, + WantsToApproach, + WantsToCastSpell, + WantsToDropItem, + WantsToFlee, + WantsToMelee, + WantsToPickupItem, + WantsToRemoveItem, + WantsToShoot, + WantsToUseItem, + Weapon, + Wearable, + ); + + state +} + +/// Sets up the game. +/// +/// * Creates the [`State`] object +/// * Registers [`components`](register!) +/// * Loads the dynamic game entities using the [`raws`](crate::raws::load_raws) module +/// * Generates the map builder environment +/// * Creates the [`Player`](crate::spawner::player) +/// * Generates the first [`map`](crate::state::State::generate_world_map) +pub fn init_state() -> State { + use systems::particle_system::ParticleBuilder; + + let mut state = register_components(); + + state + .ecs + .insert(SimpleMarkerAllocator::::new()); + + raws::load_raws(); + + state.ecs.insert(MasterDungeonMap::new()); + state.ecs.insert(Map::new(1, 64, 64, "New Map")); + state.ecs.insert(Point::zero()); + + let player_entity = spawner::player(&mut state.ecs, 0, 0); + state.ecs.insert(player_entity); + + state.ecs.insert(RunState::MapGeneration {}); + state.ecs.insert(ParticleBuilder::new()); + state.ecs.insert(rex_assets::RexAssets::new()); + + state.generate_world_map(1, 0); + + state +} diff --git a/src/main.rs b/src/main.rs index ed55bb9..76ed5c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,188 +1,4 @@ -//! Roguelike -//! -//! An implementation of a rogue-like dungeon-crawler game. -#[macro_use] -extern crate lazy_static; - -mod colors; -mod components; -mod damage_system; -mod effects; -mod gamelog; -mod gamesystem; -mod gui; -mod map; -pub mod map_builders; -mod player; -mod random_table; -mod raws; -mod rect; -mod rex_assets; -mod rng; -mod saveload_system; -mod spatial; -mod spawner; -mod state; -mod systems; - use ::bracket_lib::prelude::*; -use ::specs::prelude::*; -use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator}; -use components::*; -pub use map::*; -pub use rect::Rect; -pub use state::*; - -/// Cut down on the amount of syntax to register components -/// -/// Compare: -/// ```ignore -/// let mut game_state = State::new(); -/// -/// register!(state <- ComponentA, ComponentB, ...); -/// ``` -/// -/// Without macro: -/// ```ignore -/// let mut game_state = State::new(); -/// -/// state.ecs.register::(); -/// state.ecs.register::(); -/// ``` -macro_rules! register { - // $state is needed to get the scope at the usage point - // $Type is the Component type that is being registered - ($state: ident <- $( $Type: ty ),*,) => { - $( - $state.ecs.register::<$Type>(); - )* - } -} - -/// Register the Component Structs with Specs -fn register_components(state: &mut State) { - register!( - state <- - AlwaysTargetsSelf, - ApplyMove, - ApplyTeleport, - AreaOfEffect, - AttributeBonus, - Attributes, - BlocksTile, - BlocksVisibility, - Chasing, - Confusion, - Consumable, - CursedItem, - DamageOverTime, - DMSerializationHelper, - Door, - Duration, - EntityMoved, - EntryTrigger, - EquipmentChanged, - Equippable, - Equipped, - Faction, - Hidden, - HungerClock, - IdentifiedItem, - InBackpack, - InflictsDamage, - Initiative, - Item, - KnownSpells, - LightSource, - LootTable, - MagicItem, - MagicMapper, - MoveMode, - MyTurn, - Name, - NaturalAttackDefense, - ObfuscatedName, - OnDeath, - OtherLevelPosition, - ParticleLifetime, - Player, - Pools, - Position, - ProvidesFood, - ProvidesHealing, - ProvidesIdentification, - ProvidesMana, - ProvidesRemoveCurse, - Quips, - Ranged, - Renderable, - SerializationHelper, - SimpleMarker, - SingleActivation, - Skills, - Slow, - SpawnParticleBurst, - SpawnParticleLine, - SpecialAbilities, - SpellTemplate, - StatusEffect, - Target, - TeachesSpell, - TeleportTo, - TileSize, - TownPortal, - Vendor, - Viewshed, - WantsToApproach, - WantsToCastSpell, - WantsToDropItem, - WantsToFlee, - WantsToMelee, - WantsToPickupItem, - WantsToRemoveItem, - WantsToShoot, - WantsToUseItem, - Weapon, - Wearable, - ); -} - -/// Sets up the game. -/// -/// * Creates the [`State`] object -/// * Registers [`components`](register!) -/// * Loads the dynamic game entities using the [`raws`](crate::raws::load_raws) module -/// * Generates the map builder environment -/// * Creates the [`Player`](crate::spawner::player) -/// * Generates the first [`map`](crate::state::State::generate_world_map) -fn init_state() -> State { - use systems::particle_system::ParticleBuilder; - - let mut state = State::new(); - - register_components(&mut state); - - state - .ecs - .insert(SimpleMarkerAllocator::::new()); - - raws::load_raws(); - - state.ecs.insert(MasterDungeonMap::new()); - state.ecs.insert(Map::new(1, 64, 64, "New Map")); - state.ecs.insert(Point::zero()); - - let player_entity = spawner::player(&mut state.ecs, 0, 0); - state.ecs.insert(player_entity); - - state.ecs.insert(RunState::MapGeneration {}); - state.ecs.insert(ParticleBuilder::new()); - state.ecs.insert(rex_assets::RexAssets::new()); - - state.generate_world_map(1, 0); - - state -} /// The entry point fn main() -> BError { @@ -194,5 +10,5 @@ fn main() -> BError { .with_vsync(false) .build()?; - main_loop(context, init_state()) + main_loop(context, ::tim_rogue::init_state()) } diff --git a/src/raws.rs b/src/raws.rs index b55610a..e929a96 100644 --- a/src/raws.rs +++ b/src/raws.rs @@ -12,6 +12,7 @@ mod weapon_traits; use std::sync::Mutex; use ::bracket_lib::prelude::*; +use ::lazy_static::lazy_static; use ::serde::Deserialize; pub use faction_structs::*; use item_structs::*; diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index ce64e1b..694a22a 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use ::bracket_lib::prelude::*; +use ::lazy_static::lazy_static; use ::regex::Regex; use ::specs::prelude::*; use ::specs::saveload::{MarkedBuilder, SimpleMarker}; diff --git a/src/rng.rs b/src/rng.rs index feb31a4..5223b76 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -1,6 +1,8 @@ +//! The random number generator, using a mutex to share the instance use std::sync::Mutex; use ::bracket_lib::prelude::*; +use ::lazy_static::lazy_static; lazy_static! { static ref RNG: Mutex = Mutex::new(RandomNumberGenerator::new()); @@ -11,10 +13,12 @@ pub fn reseed(seed: u64) { *RNG.lock().unwrap() = RandomNumberGenerator::seeded(seed); } +/// Rolls `n` dice, with `die_type` sides pub fn roll_dice(n: i32, die_type: i32) -> i32 { RNG.lock().unwrap().roll_dice(n, die_type) } +/// Returns a number in the range given pub fn range(min: i32, max: i32) -> i32 { RNG.lock().unwrap().range(min, max) } diff --git a/src/spatial.rs b/src/spatial.rs index 1cf82e2..a2674b9 100644 --- a/src/spatial.rs +++ b/src/spatial.rs @@ -1,5 +1,6 @@ use std::sync::Mutex; +use ::lazy_static::lazy_static; use ::specs::prelude::*; use crate::{tile_walkable, Map, RunState};