validation: check for unanchored parts #230
@@ -223,6 +223,7 @@ pub struct ModelInfo<'a>{
|
||||
model_name:&'a str,
|
||||
map_info:MapInfo<'a>,
|
||||
counts:Counts<'a>,
|
||||
unanchored_parts:Vec<&'a Instance>,
|
||||
}
|
||||
|
||||
pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_dom_weak::Instance)->ModelInfo<'a>{
|
||||
@@ -232,6 +233,10 @@ pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_d
|
||||
// count objects (default count is 0)
|
||||
let mut counts=Counts::default();
|
||||
|
||||
// locate unanchored parts
|
||||
let mut unanchored_parts=Vec::new();
|
||||
let anchored_ustr=rbx_dom_weak::ustr("Anchored");
|
||||
|
||||
let db=rbx_reflection_database::get();
|
||||
let base_part=&db.classes["BasePart"];
|
||||
let base_parts=dom.descendants_of(model_instance.referent()).filter(|&instance|
|
||||
@@ -259,6 +264,10 @@ pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_d
|
||||
Ok(WormholeElement{behaviour:WormholeBehaviour::Out,wormhole_id})=>*counts.wormhole_out_counts.entry(wormhole_id).or_insert(0)+=1,
|
||||
Err(_)=>(),
|
||||
}
|
||||
// Unanchored parts
|
||||
if let Some(rbx_dom_weak::types::Variant::Bool(false))=instance.properties.get(&anchored_ustr){
|
||||
unanchored_parts.push(instance);
|
||||
}
|
||||
}
|
||||
|
||||
ModelInfo{
|
||||
@@ -266,6 +275,7 @@ pub fn get_model_info<'a>(dom:&'a rbx_dom_weak::WeakDom,model_instance:&'a rbx_d
|
||||
model_name:model_instance.name.as_str(),
|
||||
map_info,
|
||||
counts,
|
||||
unanchored_parts,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,6 +457,9 @@ struct MapCheck<'a>{
|
||||
// No duplicate WormholeOut# (duplicate WormholeIn# ok)
|
||||
// No dangling WormholeOut#
|
||||
wormhole_out_counts:DuplicateCheck<WormholeID,u64>,
|
||||
|
||||
// === GENERAL CHECKS ===
|
||||
unanchored_parts:Result<(),Vec<&'a Instance>>,
|
||||
}
|
||||
|
||||
impl<'a> ModelInfo<'a>{
|
||||
@@ -520,6 +533,13 @@ impl<'a> ModelInfo<'a>{
|
||||
// There must be exactly one of any perticular wormhole out id in the map.
|
||||
let wormhole_out_counts=DuplicateCheckContext(self.counts.wormhole_out_counts).check(|&c|1<c);
|
||||
|
||||
// There must not be any unanchored parts
|
||||
let unanchored_parts=if self.unanchored_parts.is_empty(){
|
||||
Ok(())
|
||||
}else{
|
||||
Err(self.unanchored_parts)
|
||||
};
|
||||
|
||||
MapCheck{
|
||||
model_class,
|
||||
model_name,
|
||||
@@ -535,6 +555,7 @@ impl<'a> ModelInfo<'a>{
|
||||
spawn_counts,
|
||||
wormhole_in_counts,
|
||||
wormhole_out_counts,
|
||||
unanchored_parts,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -557,6 +578,7 @@ impl MapCheck<'_>{
|
||||
spawn_counts:DuplicateCheck(Ok(())),
|
||||
wormhole_in_counts:SetDifferenceCheck(Ok(())),
|
||||
wormhole_out_counts:DuplicateCheck(Ok(())),
|
||||
unanchored_parts:Ok(()),
|
||||
}=>{
|
||||
Ok(MapInfoOwned{
|
||||
display_name:display_name.to_owned(),
|
||||
@@ -780,6 +802,17 @@ impl MapCheck<'_>{
|
||||
summary_format!("DuplicateWormholeOut","Duplicate WormholeOut: {context}")
|
||||
}
|
||||
};
|
||||
let unanchored_parts=match &self.unanchored_parts{
|
||||
Ok(())=>passed!("UnanchoredParts"),
|
||||
Err(unanchored_parts)=>{
|
||||
let count=unanchored_parts.len();
|
||||
let plural=if count==1{"part"}else{"parts"};
|
||||
let context=Separated::new(", ",||unanchored_parts.iter().map(|&instance|
|
||||
instance.name.as_str()
|
||||
).take(20));
|
||||
summary_format!("UnanchoredParts","{count} unanchored {plural}: {context}")
|
||||
}
|
||||
};
|
||||
Ok(MapCheckList{checks:Box::new([
|
||||
model_class,
|
||||
model_name,
|
||||
@@ -797,13 +830,14 @@ impl MapCheck<'_>{
|
||||
extra_wormhole_in,
|
||||
missing_wormhole_in,
|
||||
duplicate_wormhole_out,
|
||||
unanchored_parts,
|
||||
])})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct MapCheckList{
|
||||
pub checks:Box<[Check;16]>,
|
||||
pub checks:Box<[Check;17]>,
|
||||
}
|
||||
|
||||
pub struct CheckListAndVersion{
|
||||
|
||||
Reference in New Issue
Block a user