From 56859d4e0c416c4973321fd6343a34794d3cf356 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 30 Jan 2024 20:25:07 -0800 Subject: [PATCH] wip make it work --- src/rbx.rs | 180 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 67 deletions(-) diff --git a/src/rbx.rs b/src/rbx.rs index 8a76a87..72e44b9 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -1,5 +1,9 @@ +use std::collections::HashMap; use crate::primitives; -use strafesnet_common::gameplay_attributes; +use strafesnet_common::map; +use strafesnet_common::model; +use strafesnet_common::gameplay_modes; +use strafesnet_common::gameplay_attributes as attr; use strafesnet_common::integer::{Planar64,Planar64Vec3,Planar64Mat3,Planar64Affine3}; fn class_is_a(class: &str, superclass: &str) -> bool { @@ -40,91 +44,133 @@ fn planar64_affine3_from_roblox(cf:&rbx_dom_weak::types::CFrame,size:&rbx_dom_we Planar64Vec3::try_from([cf.position.x,cf.position.y,cf.position.z]).unwrap() ) } -fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_intersecting:bool)->model::CollisionAttributes{ - let mut general=model::GameMechanicAttributes::default(); - let mut intersecting=model::IntersectingAttributes::default(); - let mut contacting=model::ContactingAttributes::default(); +#[derive(Default)] +struct ModesBuilder{ + modes:HashMap, + mode_updates:Vec<(gameplay_modes::ModeId,gameplay_modes::ModeUpdate)>, +} +impl ModesBuilder{ + fn insert_mode(&mut self,mode_id:gameplay_modes::ModeId,mode:gameplay_modes::Mode){ + assert!(self.modes.insert(mode_id,mode).is_none(),"Cannot replace existing mode"); + } + fn push_mode_update(&mut self,mode_id:gameplay_modes::ModeId,mode_update:gameplay_modes::ModeUpdate){ + self.mode_updates.push((mode_id,mode_update)); + } +} +fn get_attributes(modes_builder:&mut ModesBuilder,model_id:model::ModelId,name:&str,can_collide:bool,velocity:Planar64Vec3,force_intersecting:bool)->attr::CollisionAttributes{ + let mut general=attr::GeneralAttributes::default(); + let mut intersecting=attr::IntersectingAttributes::default(); + let mut contacting=attr::ContactingAttributes::default(); let mut force_can_collide=can_collide; match name{ "Water"=>{ force_can_collide=false; //TODO: read stupid CustomPhysicalProperties - intersecting.water=Some(model::IntersectingWater{density:Planar64::ONE,viscosity:Planar64::ONE/10,velocity}); + intersecting.water=Some(attr::IntersectingWater{density:Planar64::ONE,viscosity:Planar64::ONE/10,velocity}); }, "Accelerator"=>{ //although the new game supports collidable accelerators, this is a roblox compatability map loader force_can_collide=false; - general.accelerator=Some(model::GameMechanicAccelerator{acceleration:velocity}); + general.accelerator=Some(attr::Accelerator{acceleration:velocity}); }, - // "UnorderedCheckpoint"=>general.teleport_behaviour=Some(model::TeleportBehaviour::StageElement(model::GameMechanicStageElement{ + // "UnorderedCheckpoint"=>general.teleport_behaviour=Some(model::TeleportBehaviour::StageElement(attr::StageElement{ // mode_id:0, // stage_id:0, // force:false, // behaviour:model::StageElementBehaviour::Unordered // })), - "SetVelocity"=>general.trajectory=Some(model::GameMechanicSetTrajectory::Velocity(velocity)), - "MapFinish"=>{force_can_collide=false;general.zone=Some(model::GameMechanicZone{mode_id:0,behaviour:model::ZoneBehaviour::Finish})}, - "MapAnticheat"=>{force_can_collide=false;general.zone=Some(model::GameMechanicZone{mode_id:0,behaviour:model::ZoneBehaviour::Anitcheat})}, - "Platform"=>general.teleport_behaviour=Some(model::TeleportBehaviour::StageElement(model::GameMechanicStageElement{ - mode_id:0, - stage_id:0, - force:false, - behaviour:model::StageElementBehaviour::Platform, - })), + "SetVelocity"=>general.trajectory=Some(attr::SetTrajectory::Velocity(velocity)), + "MapFinish"=>{ + force_can_collide=false; + modes_builder.push_mode_update( + gameplay_modes::ModeId::MAIN, + gameplay_modes::ModeUpdate::zone( + model_id, + gameplay_modes::Zone::Finish, + ), + ); + }, + "MapAnticheat"=>{ + force_can_collide=false; + modes_builder.push_mode_update( + gameplay_modes::ModeId::MAIN, + gameplay_modes::ModeUpdate::zone( + model_id, + gameplay_modes::Zone::Anticheat, + ), + ); + }, + "Platform"=>{ + modes_builder.push_mode_update( + gameplay_modes::ModeId::MAIN, + gameplay_modes::ModeUpdate::element( + model_id, + gameplay_modes::StageElement::new(0,false,gameplay_modes::StageElementBehaviour::Platform),//roblox does not know which stage the platform belongs to + ), + ); + }, other=>{ if let Some(captures)=lazy_regex::regex!(r"^(Force)?(Spawn|SpawnAt|Trigger|Teleport|Platform)(\d+)$") .captures(other){ - general.teleport_behaviour=Some(model::TeleportBehaviour::StageElement(model::GameMechanicStageElement{ - mode_id:0, - stage_id:captures[3].parse::().unwrap(), - force:match captures.get(1){ - Some(m)=>m.as_str()=="Force", - None=>false, - }, - behaviour:match &captures[2]{ - "Spawn"|"SpawnAt"=>model::StageElementBehaviour::SpawnAt, - //cancollide false so you don't hit the side - //NOT a decoration - "Trigger"=>{force_can_collide=false;model::StageElementBehaviour::Trigger}, - "Teleport"=>{force_can_collide=false;model::StageElementBehaviour::Teleport}, - "Platform"=>model::StageElementBehaviour::Platform, - _=>panic!("regex1[2] messed up bad"), - } - })); - }else if let Some(captures)=lazy_regex::regex!(r"^(Force)?(Jump)(\d+)$") + modes_builder.push_mode_update( + gameplay_modes::ModeId::MAIN, + gameplay_modes::ModeUpdate::element( + model_id, + gameplay_modes::StageElement::new( + //stage_id: + captures[3].parse::().unwrap(), + //force: + match captures.get(1){ + Some(m)=>m.as_str()=="Force", + None=>false, + }, + //behaviour: + match &captures[2]{ + "Spawn"|"SpawnAt"=>gameplay_modes::StageElementBehaviour::SpawnAt, + //cancollide false so you don't hit the side + //NOT a decoration + "Trigger"=>{force_can_collide=false;gameplay_modes::StageElementBehaviour::Trigger}, + "Teleport"=>{force_can_collide=false;gameplay_modes::StageElementBehaviour::Teleport}, + "Platform"=>gameplay_modes::StageElementBehaviour::Platform, + _=>panic!("regex1[2] messed up bad"), + }, + ), + ), + ); + }else if let Some(captures)=lazy_regex::regex!(r"^Jump(\d+)$") .captures(other){ - general.teleport_behaviour=Some(model::TeleportBehaviour::StageElement(model::GameMechanicStageElement{ - mode_id:0, - stage_id:0, - force:match captures.get(1){ - Some(m)=>m.as_str()=="Force", - None=>false, - }, - behaviour:match &captures[2]{ - "Jump"=>model::StageElementBehaviour::JumpLimit(captures[3].parse::().unwrap()), - _=>panic!("regex4[1] messed up bad"), - } - })); + modes_builder.push_mode_update( + gameplay_modes::ModeId::MAIN, + gameplay_modes::ModeUpdate::jump_limit( + model_id, + //jump_limit: + captures[1].parse::().unwrap() + ), + ); }else if let Some(captures)=lazy_regex::regex!(r"^Bonus(Finish|Anticheat)(\d+)$") .captures(other){ force_can_collide=false; - match &captures[1]{ - "Finish"=>general.zone=Some(model::GameMechanicZone{mode_id:captures[2].parse::().unwrap(),behaviour:model::ZoneBehaviour::Finish}), - "Anticheat"=>general.zone=Some(model::GameMechanicZone{mode_id:captures[2].parse::().unwrap(),behaviour:model::ZoneBehaviour::Anitcheat}), - _=>panic!("regex2[1] messed up bad"), - } - }else if let Some(captures)=lazy_regex::regex!(r"^(WormholeIn)(\d+)$") + modes_builder.push_mode_update( + gameplay_modes::ModeId::mode(captures[2].parse::().unwrap()), + gameplay_modes::ModeUpdate::zone( + model_id, + //zone: + match &captures[1]{ + "Finish"=>gameplay_modes::Zone::Finish, + "Anticheat"=>gameplay_modes::Zone::Anticheat, + _=>panic!("regex2[1] messed up bad"), + }, + ), + ); + }else if let Some(captures)=lazy_regex::regex!(r"^WormholeIn(\d+)$") .captures(other){ force_can_collide=false; - match &captures[1]{ - "WormholeIn"=>general.teleport_behaviour=Some(model::TeleportBehaviour::Wormhole(model::GameMechanicWormhole{destination_model_id:captures[2].parse::().unwrap()})), - _=>panic!("regex3[1] messed up bad"), - } + general.wormhole=Some(attr::Wormhole{destination_model_id:captures[1].parse::().unwrap()}); } // else if let Some(captures)=lazy_regex::regex!(r"^(OrderedCheckpoint)(\d+)$") // .captures(other){ // match &captures[1]{ - // "OrderedCheckpoint"=>general.checkpoint=Some(model::GameMechanicCheckpoint::Ordered{mode_id:0,checkpoint_id:captures[2].parse::().unwrap()}), + // "OrderedCheckpoint"=>general.checkpoint=Some(attr::Checkpoint::Ordered{mode_id:0,checkpoint_id:captures[2].parse::().unwrap()}), // _=>panic!("regex3[1] messed up bad"), // } // } @@ -132,25 +178,25 @@ fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_interse } //need some way to skip this if velocity!=Planar64Vec3::ZERO{ - general.booster=Some(model::GameMechanicBooster::Velocity(velocity)); + general.booster=Some(attr::Booster::Velocity(velocity)); } match force_can_collide{ true=>{ match name{ - "Bounce"=>contacting.contact_behaviour=Some(model::ContactingBehaviour::Elastic(u32::MAX)), - "Surf"=>contacting.contact_behaviour=Some(model::ContactingBehaviour::Surf), - "Ladder"=>contacting.contact_behaviour=Some(model::ContactingBehaviour::Ladder(model::ContactingLadder{sticky:true})), + "Bounce"=>contacting.contact_behaviour=Some(attr::ContactingBehaviour::Elastic(u32::MAX)), + "Surf"=>contacting.contact_behaviour=Some(attr::ContactingBehaviour::Surf), + "Ladder"=>contacting.contact_behaviour=Some(attr::ContactingBehaviour::Ladder(attr::ContactingLadder{sticky:true})), _=>(), } - model::CollisionAttributes::Contact{contacting,general} + attr::CollisionAttributes::Contact{contacting,general} }, false=>if force_intersecting ||general.any() ||intersecting.any() { - model::CollisionAttributes::Intersect{intersecting,general} + attr::CollisionAttributes::Intersect{intersecting,general} }else{ - model::CollisionAttributes::Decoration + attr::CollisionAttributes::Decoration }, } } @@ -233,7 +279,7 @@ enum RobloxBasePartDescription{ Wedge(RobloxWedgeDescription), CornerWedge(RobloxCornerWedgeDescription), } -pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> model::IndexedModelInstances{ +pub fn convert(dom:rbx_dom_weak::WeakDom)->map::Map{ //IndexedModelInstances includes textures let mut spawn_point=Planar64Vec3::ZERO; @@ -506,7 +552,7 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> model::IndexedModel }); model_id }; - indexed_models[model_id].instances.push(model::ModelInstance { + indexed_models[model_id].instances.push(model::Model{ transform:model_transform, color:glam::vec4(color3.r as f32/255f32, color3.g as f32/255f32, color3.b as f32/255f32, 1.0-*transparency), attributes:get_attributes(&object.name,*can_collide,Planar64Vec3::try_from([velocity.x,velocity.y,velocity.z]).unwrap(),force_intersecting),