1
1
// - Add support for IConfigNode serialization
2
2
// - Add support for Guid serialization
3
3
// - Rewrite Object reading and writing for perf, clarity, and reuse
4
- //#define DEBUG_PERSISTENTICONFIGNODE
5
- using HarmonyLib ;
4
+ // #define DEBUG_PERSISTENTICONFIGNODE
5
+
6
6
using System ;
7
7
using System . Collections ;
8
8
using System . Collections . Generic ;
9
9
using System . Reflection ;
10
10
using UnityEngine ;
11
11
using static ConfigNode ;
12
- using Random = System . Random ;
13
12
14
13
namespace KSPCommunityFixes . Modding
15
14
{
@@ -30,9 +29,9 @@ public LoadState(bool r, ReadLinkList l)
30
29
31
30
protected override void ApplyPatches ( )
32
31
{
33
- AddPatch ( PatchType . Prefix , typeof ( ConfigNode ) , nameof ( ConfigNode . ReadObject ) , new Type [ ] { typeof ( object ) , typeof ( ConfigNode ) } ) ;
32
+ AddPatch ( PatchType . Override , typeof ( ConfigNode ) , nameof ( ReadObject ) , new Type [ ] { typeof ( object ) , typeof ( ConfigNode ) } ) ;
34
33
35
- AddPatch ( PatchType . Prefix , typeof ( ConfigNode ) , nameof ( ConfigNode . WriteObject ) , new Type [ ] { typeof ( object ) , typeof ( ConfigNode ) , typeof ( int ) } ) ;
34
+ AddPatch ( PatchType . Override , typeof ( ConfigNode ) , nameof ( WriteObject ) , new Type [ ] { typeof ( object ) , typeof ( ConfigNode ) , typeof ( int ) } ) ;
36
35
37
36
AddPatch ( PatchType . Prefix , typeof ( ConfigNode ) , nameof ( CreateConfigFromObject ) , new Type [ ] { typeof ( object ) , typeof ( int ) , typeof ( ConfigNode ) } ) ;
38
37
@@ -68,52 +67,21 @@ private static void ConfigNode_LoadObjectFromConfig_Postfix(LoadState __state)
68
67
readLinks = __state . links ;
69
68
}
70
69
71
- // used by TypeCache since we can't make the below method return a value.
72
- public static bool WriteSuccess ;
73
-
74
- public static bool ConfigNode_WriteObject_Prefix ( object obj , ConfigNode node , int pass )
70
+ private static void ConfigNode_WriteObject_Override ( object obj , ConfigNode node , int pass )
75
71
{
76
- if ( obj is IPersistenceSave persistenceSave )
77
- persistenceSave . PersistenceSave ( ) ;
78
-
79
- Type type = obj . GetType ( ) ;
80
- var typeCache = TypeCache . GetOrCreate ( type ) ;
81
- if ( typeCache == null )
82
- {
83
- WriteSuccess = false ;
84
- return false ;
85
- }
86
-
87
- WriteSuccess = typeCache . Write ( obj , node , pass ) ;
88
-
89
- return false ;
72
+ TypeCache . TryWriteObject ( obj , node , pass ) ;
90
73
}
91
74
92
75
93
- public static bool ConfigNode_ReadObject_Prefix ( object obj , ConfigNode node , out bool __result )
76
+ private static bool ConfigNode_ReadObject_Override ( object obj , ConfigNode node )
94
77
{
95
- Type type = obj . GetType ( ) ;
96
- var typeCache = TypeCache . GetOrCreate ( type ) ;
97
- if ( typeCache == null )
98
- {
99
- __result = false ;
100
- return false ;
101
- }
102
-
103
- bool readResult = typeCache . Read ( obj , node ) ;
104
-
105
- if ( obj is IPersistenceLoad persistenceLoad )
106
- {
107
- iPersistentLoaders . Add ( persistenceLoad ) ;
108
- }
109
-
110
- __result = readResult ;
111
- return false ;
78
+ TypeCache . TryReadObject ( obj , node ) ;
79
+ return true ;
112
80
}
113
81
}
114
82
115
83
// This is an expanded version of System.TypeCode
116
- public enum DataType : uint
84
+ internal enum DataType : uint
117
85
{
118
86
INVALID = 0 ,
119
87
IConfigNode ,
@@ -151,7 +119,7 @@ public enum DataType : uint
151
119
LastValueType = ValueEnum ,
152
120
}
153
121
154
- public class FieldData
122
+ internal class FieldData
155
123
{
156
124
private static readonly System . Globalization . CultureInfo _Invariant = System . Globalization . CultureInfo . InvariantCulture ;
157
125
@@ -272,7 +240,7 @@ public bool Read(ConfigNode node, object host, int attribIndex)
272
240
}
273
241
else
274
242
{
275
- PersistentIConfigNode . ConfigNode_ReadObject_Prefix ( existing , node , out bool success ) ;
243
+ bool success = TypeCache . TryReadObject ( existing , node ) ;
276
244
if ( removeAfterUse )
277
245
node . name = string . Empty ;
278
246
return success ;
@@ -413,10 +381,10 @@ public bool Write(object value, ConfigNode node, int attribIndex, int pass)
413
381
414
382
case DataType . Object :
415
383
case DataType . Component :
416
- PersistentIConfigNode . ConfigNode_WriteObject_Prefix ( value , subNode , pass ) ;
384
+ bool success = TypeCache . TryWriteObject ( value , subNode , pass ) ;
417
385
if ( subNode . HasData )
418
386
node . _nodes . nodes . Add ( subNode ) ;
419
- return PersistentIConfigNode . WriteSuccess ;
387
+ return success ;
420
388
}
421
389
return false ;
422
390
}
@@ -446,7 +414,7 @@ public static object ReadObject(ConfigNode node, object existing, DataType dataT
446
414
existing = TypeCache . GetNewInstance ( fieldType ) ;
447
415
if ( existing == null )
448
416
return null ;
449
- PersistentIConfigNode . ConfigNode_ReadObject_Prefix ( existing , node , out success ) ;
417
+ success = TypeCache . TryReadObject ( existing , node ) ;
450
418
return existing ;
451
419
}
452
420
return null ;
@@ -491,7 +459,7 @@ public static MonoBehaviour CreateComponent(object host, Type fieldType, Persist
491
459
492
460
// We're not reading directly here because the class might have
493
461
// other interfaces/links/etc.
494
- PersistentIConfigNode . ConfigNode_ReadObject_Prefix ( child , node , out success ) ;
462
+ success = TypeCache . TryReadObject ( child , node ) ;
495
463
return child ;
496
464
}
497
465
@@ -825,7 +793,7 @@ private bool FindSetArrayType(Type seqType)
825
793
}
826
794
}
827
795
828
- public class TypeCache
796
+ internal class TypeCache
829
797
{
830
798
private static readonly Dictionary < Type , TypeCache > cache = new Dictionary < Type , TypeCache > ( ) ;
831
799
//private static readonly Dictionary<Type, ConstructorInfo> _typeToConstrutor = new Dictionary<Type, ConstructorInfo>();
@@ -868,6 +836,34 @@ private int SeenFieldIndex(string fieldName)
868
836
return numSeen ;
869
837
}
870
838
839
+ public static bool TryWriteObject ( object obj , ConfigNode node , int pass )
840
+ {
841
+ if ( obj is IPersistenceSave persistenceSave )
842
+ persistenceSave . PersistenceSave ( ) ;
843
+
844
+ Type type = obj . GetType ( ) ;
845
+ TypeCache typeCache = GetOrCreate ( type ) ;
846
+ if ( typeCache == null )
847
+ return false ;
848
+
849
+ return typeCache . Write ( obj , node , pass ) ;
850
+ }
851
+
852
+ public static bool TryReadObject ( object obj , ConfigNode node )
853
+ {
854
+ Type type = obj . GetType ( ) ;
855
+ TypeCache typeCache = GetOrCreate ( type ) ;
856
+ if ( typeCache == null )
857
+ return false ;
858
+
859
+ bool readResult = typeCache . Read ( obj , node ) ;
860
+
861
+ if ( obj is IPersistenceLoad persistenceLoad )
862
+ iPersistentLoaders . Add ( persistenceLoad ) ;
863
+
864
+ return readResult ;
865
+ }
866
+
871
867
public bool Read ( object host , ConfigNode node )
872
868
{
873
869
if ( _isPersistentLinkable )
@@ -952,7 +948,7 @@ public static TypeCache CreateAndAdd(Type t)
952
948
var tc = new TypeCache ( t ) ;
953
949
if ( tc . _fields . Count == 0 )
954
950
{
955
- Debug . LogError ( $ "[KSPCommunityFixes]: No Persistent fields on object of type { t . Name } that is referenced in persistent field , adding as null to TypeCache.") ;
951
+ Debug . LogWarning ( $ "[KSPCommunityFixes]: No Persistent fields on object of type { t . AssemblyQualifiedName ( ) } , adding as null to TypeCache. That object likely shouldn't implement the IConfigNode interface .") ;
956
952
tc = null ;
957
953
}
958
954
0 commit comments