11//#define DO_PRETTY_COMPOSITES
22
33using CATHODE . Scripting ;
4+ using CATHODE . Scripting . Internal ;
45using CathodeLib ;
56using System ;
67using System . Collections . Generic ;
78using System . IO ;
89using System . Linq ;
910using System . Runtime . InteropServices ;
11+ using System . Runtime . InteropServices . ComTypes ;
1012
1113namespace CATHODE
1214{
@@ -19,26 +21,64 @@ public class Commands : CathodeFile
1921 // - Root Instance (the map's entry composite, usually containing entities that call mission/environment composites)
2022 // - Global Instance (the main data handler for keeping track of mission number, etc - kinda like a big singleton)
2123 // - Pause Menu Instance
22- private ShortGuid [ ] _entryPoints ;
24+ private ShortGuid [ ] _entryPoints = null ;
2325 private Composite [ ] _entryPointObjects = null ;
2426
25- private List < Composite > _composites = null ;
27+ public List < Composite > Composites { get { return _composites ; } }
28+ private List < Composite > _composites = new List < Composite > ( ) ;
2629
2730 public Commands ( string path ) : base ( path ) { }
2831
2932 #region FILE_IO
3033 /* Save all changes back out */
3134 override public bool Save ( )
3235 {
33- if ( _entryPoints == null || _entryPoints . Length != 3 || _entryPoints [ 0 ] == null )
34- return false ;
36+ //Validate entry points and composite count
37+ if ( _composites . Count == 0 ) return false ;
38+ if ( _entryPoints == null ) _entryPoints = new ShortGuid [ 3 ] ;
39+ if ( _entryPoints [ 0 ] . val == null && _entryPoints [ 1 ] . val == null && _entryPoints [ 2 ] . val == null && _composites . Count == 0 ) return false ;
40+
41+ //If we have composites but the entry points are broken, correct them first!
42+ if ( GetComposite ( _entryPoints [ 2 ] ) == null )
43+ {
44+ Composite pausemenu = GetComposite ( "PAUSEMENU" ) ;
45+ if ( pausemenu == null )
46+ {
47+ Console . WriteLine ( "WARNING: PAUSEMENU composite does not exist! Creating blank placeholder." ) ;
48+ pausemenu = AddComposite ( "PAUSEMENU" ) ;
49+ pausemenu . shortGUID = new ShortGuid ( "FE-7B-FE-B3" ) ;
50+ }
51+ _entryPoints [ 2 ] = pausemenu . shortGUID ;
52+ }
53+ if ( GetComposite ( _entryPoints [ 1 ] ) == null )
54+ {
55+ Composite global = GetComposite ( "GLOBAL" ) ;
56+ if ( global == null )
57+ {
58+ Console . WriteLine ( "WARNING: GLOBAL composite does not exist! Creating blank placeholder. This may cause issues with GLOBAL references." ) ;
59+ global = AddComposite ( "GLOBAL" ) ;
60+ global . shortGUID = new ShortGuid ( "1D-2E-CE-E5" ) ;
61+ }
62+ _entryPoints [ 1 ] = global . shortGUID ;
63+ }
64+ if ( GetComposite ( _entryPoints [ 0 ] ) == null )
65+ {
66+ Console . WriteLine ( "WARNING: Entry point was not set! Defaulting to composite at index zero." ) ;
67+ _entryPoints [ 0 ] = _composites [ 0 ] . shortGUID ;
68+ }
69+ RefreshEntryPointObjects ( ) ;
3570
3671 BinaryWriter writer = new BinaryWriter ( File . OpenWrite ( _filepath ) ) ;
3772 writer . BaseStream . SetLength ( 0 ) ;
3873
3974 //Write entry points
4075 for ( int i = 0 ; i < 3 ; i ++ )
41- Utilities . Write < ShortGuid > ( writer , _entryPoints [ i ] ) ;
76+ {
77+ if ( _entryPoints [ i ] . val == null || GetComposite ( _entryPoints [ i ] ) == null )
78+ writer . Write ( new byte [ ] { 0x00 , 0x00 , 0x00 , 0x00 } ) ;
79+ else
80+ Utilities . Write < ShortGuid > ( writer , _entryPoints [ i ] ) ;
81+ }
4282
4383 //Write placeholder info for parameter/composite offsets
4484 int offsetToRewrite = ( int ) writer . BaseStream . Position ;
@@ -420,7 +460,7 @@ override public bool Save()
420460 break ;
421461 case ResourceType . COLLISION_MAPPING :
422462 writer . Write ( resourceReferences [ p ] . startIndex ) ;
423- writer . Write ( resourceReferences [ p ] . entityID . val ) ;
463+ writer . Write ( resourceReferences [ p ] . collisionID . val ) ;
424464 break ;
425465 case ResourceType . ANIMATED_MODEL :
426466 case ResourceType . DYNAMIC_PHYSICS_SYSTEM :
@@ -859,7 +899,7 @@ override protected bool Load()
859899 break ;
860900 case ResourceType . COLLISION_MAPPING :
861901 resource . startIndex = reader . ReadInt32 ( ) ; //COLLISION.MAP entry index?
862- resource . entityID = new ShortGuid ( reader ) ; //ID which maps to the entity using the resource (?) - check GetFriendlyName
902+ resource . collisionID = new ShortGuid ( reader ) ; //ID which maps to *something*
863903 break ;
864904 case ResourceType . ANIMATED_MODEL :
865905 case ResourceType . DYNAMIC_PHYSICS_SYSTEM :
@@ -1074,6 +1114,15 @@ override protected bool Load()
10741114 #endregion
10751115
10761116 #region ACCESSORS
1117+ /* Add a new composite */
1118+ public Composite AddComposite ( string name , bool isRoot = false )
1119+ {
1120+ Composite comp = new Composite ( name ) ;
1121+ _composites . Add ( comp ) ;
1122+ if ( isRoot ) SetRootComposite ( comp ) ;
1123+ return comp ;
1124+ }
1125+
10771126 /* Return a list of filenames for composites in the CommandsPAK archive */
10781127 public string [ ] GetCompositeNames ( )
10791128 {
@@ -1082,26 +1131,16 @@ public string[] GetCompositeNames()
10821131 return toReturn ;
10831132 }
10841133
1085- /* Find the a script entry object by name */
1086- public int GetFileIndex ( string FileName )
1134+ /* Get an individual composite */
1135+ public Composite GetComposite ( string name )
10871136 {
1088- for ( int i = 0 ; i < _composites . Count ; i ++ ) if ( _composites [ i ] . name == FileName || _composites [ i ] . name == FileName . Replace ( '/' , '\\ ' ) ) return i ;
1089- return - 1 ;
1137+ return _composites . FirstOrDefault ( o => o . name == name || o . name == name . Replace ( '/' , '\\ ' ) ) ;
10901138 }
1091-
1092- /* Get an individual composite */
10931139 public Composite GetComposite ( ShortGuid id )
10941140 {
10951141 if ( id . val == null ) return null ;
10961142 return _composites . FirstOrDefault ( o => o . shortGUID == id ) ;
10971143 }
1098- public Composite GetCompositeByIndex ( int index )
1099- {
1100- return ( index >= _composites . Count || index < 0 ) ? null : _composites [ index ] ;
1101- }
1102-
1103- /* Get all composites */
1104- public List < Composite > Composites { get { return _composites ; } }
11051144
11061145 /* Get entry point composite objects */
11071146 public Composite [ ] EntryPoints
@@ -1110,16 +1149,22 @@ public Composite[] EntryPoints
11101149 {
11111150 if ( _entryPoints == null ) return null ;
11121151 if ( _entryPointObjects != null ) return _entryPointObjects ;
1113- _entryPointObjects = new Composite [ _entryPoints . Length ] ;
1114- for ( int i = 0 ; i < _entryPoints . Length ; i ++ ) _entryPointObjects [ i ] = GetComposite ( _entryPoints [ i ] ) ;
1152+ RefreshEntryPointObjects ( ) ;
11151153 return _entryPointObjects ;
11161154 }
11171155 }
11181156
11191157 /* Set the root composite for this COMMANDS.PAK (the root of the level - GLOBAL and PAUSEMENU are also instanced) */
1120- public void SetRootComposite ( ShortGuid id )
1158+ public void SetRootComposite ( Composite composite )
1159+ {
1160+ SetRootComposite ( composite . shortGUID ) ;
1161+ }
1162+ public void SetRootComposite ( ShortGuid compositeID )
11211163 {
1122- _entryPoints [ 0 ] = id ;
1164+ if ( _entryPoints == null )
1165+ _entryPoints = new ShortGuid [ 3 ] ;
1166+
1167+ _entryPoints [ 0 ] = compositeID ;
11231168 _entryPointObjects = null ;
11241169 }
11251170 #endregion
@@ -1155,6 +1200,13 @@ private List<ParameterData> PruneParameterList(List<ParameterData> parameters)
11551200 }
11561201 return prunedList ;
11571202 }
1203+
1204+ /* Refresh the composite pointers for our entry points */
1205+ private void RefreshEntryPointObjects ( )
1206+ {
1207+ _entryPointObjects = new Composite [ _entryPoints . Length ] ;
1208+ for ( int i = 0 ; i < _entryPoints . Length ; i ++ ) _entryPointObjects [ i ] = GetComposite ( _entryPoints [ i ] ) ;
1209+ }
11581210 #endregion
11591211
11601212 /* -- */
0 commit comments