From ce283e50631db36287d7bc51b529105792dcaadc Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Thu, 1 Feb 2024 00:04:07 -0800 Subject: [PATCH] the work --- src/gameplay_attributes.rs | 3 +- src/gameplay_modes.rs | 168 +++++++++++++++++++++++++++++++++---- src/lib.rs | 2 + src/map.rs | 11 +++ src/model.rs | 26 +++++- src/updatable.rs | 62 ++++++++++++++ 6 files changed, 253 insertions(+), 19 deletions(-) create mode 100644 src/map.rs create mode 100644 src/updatable.rs diff --git a/src/gameplay_attributes.rs b/src/gameplay_attributes.rs index 6756e45..75e9024 100644 --- a/src/gameplay_attributes.rs +++ b/src/gameplay_attributes.rs @@ -8,8 +8,9 @@ pub struct ContactingLadder{ #[derive(Clone,Hash,Eq,PartialEq)] pub enum ContactingBehaviour{ Surf, - Cling,//usable as a zipline, or other weird and wonderful things Ladder(ContactingLadder), + NoJump, + Cling,//usable as a zipline, or other weird and wonderful things Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32 } //you have this effect while intersecting diff --git a/src/gameplay_modes.rs b/src/gameplay_modes.rs index a06fbb2..66ed787 100644 --- a/src/gameplay_modes.rs +++ b/src/gameplay_modes.rs @@ -1,12 +1,23 @@ use std::collections::{HashSet,HashMap}; use crate::model::ModelId; use crate::gameplay_style; +use crate::updatable::Updatable; +#[derive(Clone)] pub struct StageElement{ stage:StageId,//which stage spawn to send to force:bool,//allow setting to lower spawn id i.e. 7->3 behaviour:StageElementBehaviour } +impl StageElement{ + pub fn new(stage_id:u32,force:bool,behaviour:StageElementBehaviour)->Self{ + Self{ + stage:StageId(stage_id), + force, + behaviour, + } + } +} #[derive(Clone,Hash,Eq,PartialEq)] pub enum StageElementBehaviour{ @@ -20,25 +31,63 @@ pub enum StageElementBehaviour{ Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both. } +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +pub struct CheckpointId(usize); +#[derive(Clone,Hash,Eq,PartialEq)] pub struct StageId(u32); pub struct Stage{ spawn:ModelId, + //open world support lol + ordered_checkpoints_count:u32, //other behaviour models of this stage can have - ordered_checkpoints:Vec<ModelId>, + ordered_checkpoints:HashMap<CheckpointId,ModelId>, unordered_checkpoints:HashSet<ModelId>, } - -#[derive(Clone,Hash,Eq,PartialEq)] -pub enum ZoneBehaviour{ - Finish, - Anitcheat, +#[derive(Default)] +pub struct StageUpdate{ + //other behaviour models of this stage can have + ordered_checkpoints:HashMap<CheckpointId,ModelId>, + unordered_checkpoints:HashSet<ModelId>, } +impl Updatable<&StageUpdate> for Stage{ + fn insert(&mut self,update:&StageUpdate){ + for (&checkpoint,&model) in &update.ordered_checkpoints{ + self.ordered_checkpoints.insert(checkpoint,model); + } + for &checkpoint in &update.unordered_checkpoints{ + self.unordered_checkpoints.insert(checkpoint); + } + } + fn remove(&mut self,update:&StageUpdate){ + for (checkpoint,_) in &update.ordered_checkpoints{ + self.ordered_checkpoints.remove(checkpoint); + } + for model in &update.unordered_checkpoints{ + self.unordered_checkpoints.remove(model); + } + } +} + +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +pub enum Zone{ + Start, + Finish, + Anticheat, +} +#[derive(Clone,Hash,Eq,PartialEq)] pub struct ModeId(u32); +impl ModeId{ + pub const MAIN:Self=Self(0); + pub const BONUS:Self=Self(1); + pub const fn mode(mode_id:u32)->Self{ + Self(mode_id) + } +} pub struct Mode{ style:gameplay_style::StyleModifiers, - start:ModelId, - zones:HashMap<ModelId,ZoneBehaviour>, - stages:Vec<Stage>, + start:ModelId,//when you press reset you go here + zones:HashMap<ModelId,Zone>, + stages:Vec<Stage>,//when you load the map you go to stages[0].spawn //mutually exlusive stage element behaviour elements:HashMap<ModelId,StageElement>, jump_limit:HashMap<ModelId,u32>, @@ -47,23 +96,25 @@ impl Mode{ pub fn get_spawn_model_id(&self,stage:StageId)->Option<ModelId>{ self.stages.get(stage.0 as usize).map(|s|s.spawn) } + //TODO: put this in the SNF pub fn denormalize_data(&mut self){ //expand and index normalized data + self.zones.insert(self.start,Zone::Start); for (stage_id,stage) in self.stages.iter().enumerate(){ self.elements.insert(stage.spawn,StageElement{ stage:StageId(stage_id as u32), force:false, behaviour:StageElementBehaviour::SpawnAt, }); - for &model_id in &stage.ordered_checkpoints{ - self.elements.insert(model_id,StageElement{ + for (_,&model) in &stage.ordered_checkpoints{ + self.elements.insert(model,StageElement{ stage:StageId(stage_id as u32), force:false, behaviour:StageElementBehaviour::Checkpoint, }); } - for &model_id in &stage.unordered_checkpoints{ - self.elements.insert(model_id,StageElement{ + for &model in &stage.unordered_checkpoints{ + self.elements.insert(model,StageElement{ stage:StageId(stage_id as u32), force:false, behaviour:StageElementBehaviour::Checkpoint, @@ -72,19 +123,102 @@ impl Mode{ } } } +//this would be nice as a macro +#[derive(Default)] +pub struct ModeUpdate{ + zones:HashMap<ModelId,Zone>, + stages:HashMap<StageId,StageUpdate>, + //mutually exlusive stage element behaviour + elements:HashMap<ModelId,StageElement>, + jump_limit:HashMap<ModelId,u32>, +} +impl Updatable<&ModeUpdate> for Mode{ + fn insert(&mut self,update:&ModeUpdate){ + for (&model,&zone) in &update.zones{ + self.zones.insert(model,zone); + } + for (stage,stage_update) in &update.stages{ + if let Some(stage)=self.stages.get_mut(stage.0 as usize){ + stage.insert(stage_update); + } + } + for (&model,stage_element) in &update.elements{ + self.elements.insert(model,stage_element.clone()); + } + for (&model,&limit) in &update.jump_limit{ + self.jump_limit.insert(model,limit); + } + } + fn remove(&mut self,update:&ModeUpdate){ + for (model,_) in &update.zones{ + self.zones.remove(model); + } + for (stage,stage_update) in &update.stages{ + if let Some(stage)=self.stages.get_mut(stage.0 as usize){ + stage.remove(stage_update); + } + } + for (model,_) in &update.elements{ + self.elements.remove(model); + } + for (model,_) in &update.jump_limit{ + self.jump_limit.remove(model); + } + } +} +impl ModeUpdate{ + pub fn zone(model_id:ModelId,zone:Zone)->Self{ + let mut mu=Self::default(); + mu.zones.insert(model_id,zone); + mu + } + pub fn stage(stage_id:StageId,stage_update:StageUpdate)->Self{ + let mut mu=Self::default(); + mu.stages.insert(stage_id,stage_update); + mu + } + pub fn element(model_id:ModelId,element:StageElement)->Self{ + let mut mu=Self::default(); + mu.elements.insert(model_id,element); + mu + } + pub fn jump_limit(model_id:ModelId,jump_limit:u32)->Self{ + let mut mu=Self::default(); + mu.jump_limit.insert(model_id,jump_limit); + mu + } +} #[derive(Default)] pub struct Modes{ modes:Vec<Mode>, } impl Modes{ - pub fn clear(&mut self){ - self.modes.clear(); + pub fn new(modes:Vec<Mode>)->Self{ + Self{ + modes, + } } pub fn get_mode(&self,mode:ModeId)->Option<&Mode>{ self.modes.get(mode.0 as usize) } - pub fn insert(&mut self,mode:Mode){ - self.modes.push(mode); +} +pub struct ModesUpdate{ + modes:HashMap<ModeId,ModeUpdate>, +} +impl Updatable<&ModesUpdate> for Modes{ + fn insert(&mut self,update:&ModesUpdate){ + for (mode,mode_update) in &update.modes{ + if let Some(mode)=self.modes.get_mut(mode.0 as usize){ + mode.insert(mode_update); + } + } + } + fn remove(&mut self,update:&ModesUpdate){ + for (mode,mode_update) in &update.modes{ + if let Some(mode)=self.modes.get_mut(mode.0 as usize){ + mode.remove(mode_update); + } + } } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 99b060b..b567481 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ pub mod bvh; +pub mod map; pub mod aabb; pub mod model; pub mod zeroes; pub mod integer; +pub mod updatable; pub mod instruction; pub mod gameplay_modes; pub mod gameplay_style; diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..d85c28b --- /dev/null +++ b/src/map.rs @@ -0,0 +1,11 @@ +use std::collections::HashMap; + +use crate::model; +use crate::gameplay_modes; +//this is the current map data loaded in memory +pub struct Map{ + modes:gameplay_modes::Modes, + models:model::Models, + //RenderPattern + textures:HashMap<u32,Vec<u8>>, +} diff --git a/src/model.rs b/src/model.rs index cbf7370..ebbfabe 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,5 +1,7 @@ +use std::collections::HashMap; use crate::integer::{Planar64Vec3,Planar64Affine3}; use crate::gameplay_attributes; +use crate::updatable::Updatable; pub type TextureCoordinate=glam::Vec2; pub type Color4=glam::Vec4; @@ -30,6 +32,8 @@ pub struct IndexedPhysicsGroup{ pub groups:Vec<GroupId>, } //This is a superset of PhysicsModel and GraphicsModel +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +pub struct IndexedModelId(u32); pub struct IndexedModel{ pub unique_pos:Vec<Planar64Vec3>,//Unit32Vec3 pub unique_normal:Vec<Planar64Vec3>,//Unit32Vec3 @@ -47,8 +51,28 @@ pub struct IndexedModel{ #[derive(Clone,Copy,Hash,Eq,PartialEq)] pub struct ModelId(u32); pub struct Model{ - pub model:ModelId, + pub model:IndexedModelId, pub attributes:gameplay_attributes::CollisionAttributesId, pub color:Color4,//transparency is in here pub transform:Planar64Affine3, } + +pub struct Models{ + indexed_models:HashMap<IndexedModelId,IndexedModel>, + models:HashMap<ModelId,Model>, +} +impl Updatable<Models> for Models{ + fn insert(&mut self,update:Models){ + self.indexed_models.extend(update.indexed_models); + self.models.extend(update.models); + } + fn remove(&mut self,update:Models){ + for (indexed_model_id,_) in &update.indexed_models{ + self.indexed_models.remove(indexed_model_id); + } + for (model_id,_) in &update.models{ + self.models.remove(model_id); + } + todo!("stop cloning models for remove"); + } +} \ No newline at end of file diff --git a/src/updatable.rs b/src/updatable.rs new file mode 100644 index 0000000..f3d6b4d --- /dev/null +++ b/src/updatable.rs @@ -0,0 +1,62 @@ +pub trait Updatable<Updater>{ + fn insert(&mut self,update:Updater); + fn remove(&mut self,update:Updater); +} +//what if do like this +//* +pub trait Updatable2<Updater>{ + fn update(&mut self,update:Updater); +} +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +struct InnerId(u32); +#[derive(Clone)] +struct Inner{ + id:InnerId, + enabled:bool, +} +#[derive(Clone,Copy,Hash,Eq,PartialEq)] +struct OuterId(u32); +struct Outer{ + id:OuterId, + inners:std::collections::HashMap<InnerId,Inner>, +} + +enum Update<I,U>{ + Insert(I), + Update(U), + Remove +} + +struct InnerUpdate{ + //#[updatable(Update)] + enabled:Option<bool>, +} +struct OuterUpdate{ + //#[updatable(Insert,Update,Remove)] + inners:std::collections::HashMap<InnerId,Update<Inner,InnerUpdate>>, + //#[updatable(Update)] + //inners:std::collections::HashMap<InnerId,InnerUpdate>, +} +impl Updatable2<InnerUpdate> for Inner{ + fn update(&mut self,update:InnerUpdate){ + if let Some(enabled)=update.enabled{ + self.enabled=enabled; + } + } +} +impl Updatable2<OuterUpdate> for Outer{ + fn update(&mut self,update:OuterUpdate){ + for (id,up) in update.inners{ + match up{ + Update::Insert(new_inner)=>self.inners.insert(id,new_inner), + Update::Update(inner_update)=>self.inners.get_mut(&id).map(|inner|{ + let old=inner.clone(); + inner.update(inner_update); + old + }), + Update::Remove=>self.inners.remove(&id), + }; + } + } +} +//*/ \ No newline at end of file