@@ -45,6 +45,38 @@ public int GetHashCode(UndertaleSprite x)
4545 }
4646}
4747class UndertaleGameObjectComparer : IEqualityComparer < UndertaleGameObject >
48+ {
49+ public bool Equals ( UndertaleGameObject ? x , UndertaleGameObject ? y )
50+ {
51+ if ( x == null || y == null ) return false ;
52+ return x . Name . Content == y . Name . Content &&
53+ ( x . Sprite ? . Name . Content ?? "" ) == ( y . Sprite ? . Name . Content ?? "" ) &&
54+ ( x . ParentId ? . Name . Content ?? "" ) == ( y . ParentId ? . Name . Content ?? "" ) &&
55+ x . Visible == y . Visible &&
56+ x . Persistent == y . Persistent &&
57+ x . Awake == y . Awake &&
58+ x . CollisionShape == y . CollisionShape &&
59+ x . Events . Count == y . Events . Count ;
60+ }
61+
62+ // If Equals() returns true for a pair of objects
63+ // then GetHashCode() must return the same value for these objects.
64+
65+ public int GetHashCode ( UndertaleGameObject x )
66+ {
67+ //Check whether the object is null
68+ if ( x == null ) return 0 ;
69+ return x . Name . Content . GetHashCode ( ) ^
70+ ( x . Sprite ? . Name . Content ?? "" ) . GetHashCode ( ) ^
71+ ( x . ParentId ? . Name . Content ?? "" ) . GetHashCode ( ) ^
72+ x . Visible . GetHashCode ( ) ^
73+ x . Persistent . GetHashCode ( ) ^
74+ x . Awake . GetHashCode ( ) ^
75+ x . CollisionShape . GetHashCode ( ) ^
76+ x . Events . Count . GetHashCode ( ) ;
77+ }
78+ }
79+ class UndertaleGameObjectNameComparer : IEqualityComparer < UndertaleGameObject >
4880{
4981 public bool Equals ( UndertaleGameObject ? x , UndertaleGameObject ? y )
5082 {
@@ -64,17 +96,25 @@ public int GetHashCode(UndertaleGameObject x)
6496}
6597public class GameObjectSummary
6698{
67- public string name = "" ;
68- public string spriteName = "" ;
69- public string parentName = "" ;
70- public bool isVisible ;
71- public bool isPersistent ;
72- public bool isAwake ;
73- public string collisionShapeFlags = "" ;
99+ public string name { get ; set ; } = "" ;
100+ public string spriteName { get ; set ; } = "" ;
101+ public string parentName { get ; set ; } = "" ;
102+ public bool isVisible { get ; set ; }
103+ public bool isPersistent { get ; set ; }
104+ public bool isAwake { get ; set ; }
105+ public string collisionShapeFlags { get ; set ; } = "" ;
106+ public List < ( string , int ) > Events { get ; set ; } = new List < ( string , int ) > ( ) ;
74107}
75108
76109static public class DiffUtils
77110{
111+ public static IEnumerable < ( int , T ) > Enumerate < T > ( this IEnumerable < T > ienumerable )
112+ {
113+ int ind = 0 ;
114+ foreach ( T element in ienumerable ) {
115+ yield return ( ind ++ , element ) ;
116+ }
117+ }
78118 // thanks to Pong to acknowledge me that possibility
79119 private static unsafe bool UnsafeCompare ( byte [ ] a1 , byte [ ] a2 )
80120 {
@@ -150,8 +190,7 @@ private static void AddedRemovedCodes(UndertaleData name, UndertaleData referenc
150190 private static void ModifiedCodes( UndertaleData name, UndertaleData reference , DirectoryInfo outputFolder )
151191 {
152192 using MemoryStream ms = new ( ) ;
153- SharpSerializerBinarySettings settings = new ( BinarySerializationMode . Burst ) ;
154- SharpSerializer burstSerializer = new ( settings) ;
193+ SharpSerializer burstSerializer = new ( new SharpSerializerBinarySettings ( BinarySerializationMode . Burst ) ) ;
155194
156195 GlobalDecompileContext contextName = new ( name , false ) ;
157196 GlobalDecompileContext contextRef = new ( reference , false ) ;
@@ -206,34 +245,89 @@ private static void AddedRemovedObjects(UndertaleData name, UndertaleData refere
206245 DirectoryInfo dirAddedObject = new ( Path . Join ( outputFolder . FullName , Path . DirectorySeparatorChar . ToString ( ) , "AddedGameObjects" ) ) ;
207246 dirAddedObject. Create ( ) ;
208247
209- IEnumerable< UndertaleGameObject > added = name . GameObjects . Except ( reference . GameObjects , new UndertaleGameObjectComparer ( ) ) ;
210- IEnumerable< UndertaleGameObject > removed = reference . GameObjects . Except ( name . GameObjects , new UndertaleGameObjectComparer ( ) ) ;
248+ IEnumerable< UndertaleGameObject > added = name . GameObjects . Except ( reference . GameObjects , new UndertaleGameObjectNameComparer ( ) ) ;
249+ IEnumerable< UndertaleGameObject > removed = reference . GameObjects . Except ( name . GameObjects , new UndertaleGameObjectNameComparer ( ) ) ;
211250 using ( StreamWriter sw = new ( Path . Join ( outputFolder . FullName , Path . DirectorySeparatorChar . ToString ( ) , $ "addedGameObjects.txt") ) )
212251 {
213252 foreach ( UndertaleGameObject ob in added)
214253 {
215254 sw. WriteLine ( ob . Name . Content ) ;
255+ GameObjectSummary gameObjectSummary = new ( )
256+ {
257+ name = ob . Name . Content ,
258+ spriteName = ob . Sprite ? . Name . Content ?? "" ,
259+ parentName = ob . ParentId ? . Name . Content ?? "" ,
260+ isVisible = ob . Visible ,
261+ isPersistent = ob . Persistent ,
262+ isAwake = ob . Awake ,
263+ collisionShapeFlags = ob . CollisionShape . ToString ( ) ,
264+ Events = ob . Events . Enumerate ( ) . SelectMany ( x => x . Item2 . Select ( y => ( ( ( EventType ) x . Item1 ) . ToString ( ) , ( int ) y . EventSubtype ) ) ) . ToList ( ) ,
265+ } ;
266+
216267 File. WriteAllText ( Path . Join ( dirAddedObject . FullName , Path . DirectorySeparatorChar . ToString ( ) , $ "{ ob . Name . Content } .json") ,
217- JsonConvert . SerializeObject (
218- new GameObjectSummary ( )
219- {
220- name = ob . Name . Content ,
221- spriteName = ob . Sprite ? . Name . Content ?? "" ,
222- parentName = ob . ParentId ? . Name . Content ?? "" ,
223- isVisible = ob . Visible ,
224- isPersistent = ob . Persistent ,
225- isAwake = ob . Awake ,
226- collisionShapeFlags = ob . CollisionShape . ToString ( ) ,
227- }
228- )
268+ JsonConvert . SerializeObject ( gameObjectSummary )
229269 ) ;
230270 }
231271 }
232272 File. WriteAllLines ( Path . Join ( outputFolder . FullName , Path . DirectorySeparatorChar . ToString ( ) , $ "removedGameObjects.txt") , removed . Select ( x => x . Name . Content ) ) ;
233273 }
274+ private static void ModifiedObjects( UndertaleData name , UndertaleData reference , DirectoryInfo outputFolder )
275+ {
276+ diff_match_patch dmp = new ( ) ;
277+ UndertaleGameObjectComparer comparer = new ( ) ;
278+
279+ DirectoryInfo dirModifiedObject = new ( Path . Join ( outputFolder . FullName , Path . DirectorySeparatorChar . ToString ( ) , "ModifiedObjects" ) ) ;
280+ dirModifiedObject . Create ( ) ;
281+
282+ UndertaleGameObject obRef;
283+ string strName = "" ;
284+ string strRef = "" ;
285+
286+ IEnumerable < UndertaleGameObject > common = name . GameObjects . Intersect ( reference . GameObjects , new UndertaleGameObjectNameComparer ( ) ) ;
287+
288+ foreach ( UndertaleGameObject ob in common)
289+ {
290+ obRef = reference. GameObjects . First ( t => t . Name . Content == ob . Name . Content ) ;
291+ if ( comparer . Equals ( ob , obRef ) ) continue;
292+
293+ strName = JsonConvert. SerializeObject (
294+ new GameObjectSummary ( )
295+ {
296+ name = ob . Name . Content ,
297+ spriteName = ob . Sprite ? . Name . Content ?? "" ,
298+ parentName = ob . ParentId ? . Name . Content ?? "" ,
299+ isVisible = ob . Visible ,
300+ isPersistent = ob . Persistent ,
301+ isAwake = ob . Awake ,
302+ collisionShapeFlags = ob . CollisionShape . ToString ( ) ,
303+ Events = ob . Events . Enumerate ( ) . SelectMany ( x => x . Item2 . Select ( y => ( ( ( EventType ) x . Item1 ) . ToString ( ) , ( int ) y . EventSubtype ) ) ) . ToList ( ) ,
304+ }
305+ ) ;
306+ strRef = JsonConvert. SerializeObject (
307+ new GameObjectSummary ( )
308+ {
309+ name = obRef . Name . Content ,
310+ spriteName = obRef . Sprite ? . Name . Content ?? "" ,
311+ parentName = obRef . ParentId ? . Name . Content ?? "" ,
312+ isVisible = obRef . Visible ,
313+ isPersistent = obRef . Persistent ,
314+ isAwake = obRef . Awake ,
315+ collisionShapeFlags = obRef . CollisionShape . ToString ( ) ,
316+ Events = ob . Events . Enumerate ( ) . SelectMany ( x => x . Item2 . Select ( y => ( ( ( EventType ) x . Item1 ) . ToString ( ) , ( int ) y . EventSubtype ) ) ) . ToList ( ) ,
317+ }
318+ ) ;
319+
320+ List< Diff > diff = dmp . diff_main ( strRef , strName ) ;
321+ if ( diff . Count == 0 || ( diff . Count == 1 && diff [ 0 ] . operation == Operation . EQUAL ) ) continue;
322+
323+ string report = dmp. diff_prettyHtml ( diff ) ;
324+ File. WriteAllText ( Path . Join ( dirModifiedObject . FullName , Path . DirectorySeparatorChar . ToString ( ) , $ "{ ob . Name . Content } .html") , report ) ;
325+ }
326+ }
234327 public static void DiffObjects( UndertaleData name , UndertaleData reference , DirectoryInfo outputFolder )
235328 {
236329 AddedRemovedObjects( name , reference , outputFolder ) ;
330+ ModifiedObjects( name , reference , outputFolder ) ;
237331 }
238332 public static void DiffRooms( UndertaleData name , UndertaleData reference , DirectoryInfo outputFolder )
239333 {
0 commit comments