@@ -92,31 +92,8 @@ public Level Deserialize()
9292 ArtObjects = ArtObjects ,
9393 } ;
9494
95- level . Triles = new OrderedDictionary < TrileEmplacement , TrileInstance > ( ) ;
96-
97- foreach ( var trileModel in Triles )
98- {
99- var trile = trileModel . Deserialize ( ) ;
100-
101- if ( level . Triles . TryGetValue ( trileModel . Emplacement , out var existingTrile ) )
102- {
103- if ( existingTrile . OverlappedTriles == null )
104- {
105- existingTrile . OverlappedTriles = new List < TrileInstance > ( ) ;
106- }
107-
108- level . Triles [ trileModel . Emplacement ] . OverlappedTriles . Add ( trile ) ;
109- continue ;
110- }
111-
112- level . Triles [ trileModel . Emplacement ] = trile ;
113- }
114-
115- level . Groups = new Dictionary < int , TrileGroup > ( ) ;
116- foreach ( var groupModel in Groups )
117- {
118- level . Groups [ groupModel . Key ] = groupModel . Value . Deserialize ( ) ;
119- }
95+ ArrangeTrilesIntoLevel ( level ) ;
96+ RecreateGroupsInLevel ( level ) ;
12097
12198 return level ;
12299 }
@@ -156,7 +133,18 @@ public void SerializeFrom(Level level)
156133 Volumes = level . Volumes ;
157134 ArtObjects = level . ArtObjects ;
158135
159- // sort tiles into modified structures
136+ ExtractTrileListFromLevel ( level ) ;
137+ ExtractCleanedGroupsFromLevel ( level ) ;
138+ }
139+
140+ private void ExtractTrileListFromLevel ( Level level )
141+ {
142+ // OverlappedTriles list in original Level's Trile Instance structure exists as a way to store
143+ // multiple triles under the same TrileEmplacement key in Triles dictionary.
144+ // This is wasteful for JSON format. To avoid this, custom model for TrileInstance containing Emplacement
145+ // is made, so overlapping triles can exist next to one another.
146+ // We're merging them back into OverlappedTriles array in ArrangeTrilesIntoLevel during deconversion.
147+
160148 Triles = new ( ) ;
161149 foreach ( var trileRecord in level . Triles )
162150 {
@@ -174,13 +162,54 @@ public void SerializeFrom(Level level)
174162 Triles . Add ( new TrileInstanceJsonModel ( pos , overlapping ) ) ;
175163 }
176164 }
165+ }
177166
178- // create groups of modified paths
167+ private void ArrangeTrilesIntoLevel ( Level level )
168+ {
169+ level . Triles = new OrderedDictionary < TrileEmplacement , TrileInstance > ( ) ;
170+ foreach ( var trileModel in Triles )
171+ {
172+ var trile = trileModel . Deserialize ( ) ;
173+
174+ if ( level . Triles . TryGetValue ( trileModel . Emplacement , out var existingTrile ) )
175+ {
176+ if ( existingTrile . OverlappedTriles == null )
177+ {
178+ existingTrile . OverlappedTriles = new List < TrileInstance > ( ) ;
179+ }
180+
181+ level . Triles [ trileModel . Emplacement ] . OverlappedTriles . Add ( trile ) ;
182+ continue ;
183+ }
184+
185+ level . Triles [ trileModel . Emplacement ] = trile ;
186+ }
187+ }
188+
189+ private void ExtractCleanedGroupsFromLevel ( Level level )
190+ {
191+ // Groups store exact copies of contained TrileInstances. This is very wasteful, and even the game
192+ // dumps them and looks them up again using TrileEmplacement calculated from trile's position
193+ // (see FezEngine.Structure.Level.OnDeserialization())
194+ // We're dumping all trile data using custom model for TrileGroup,
195+ // and then rebuilding it in RecreateGroupsInLevel.
196+
179197 Groups = new Dictionary < int , TrileGroupJsonModel > ( ) ;
180198 foreach ( var pair in level . Groups )
181199 {
182200 Groups [ pair . Key ] = new TrileGroupJsonModel ( pair . Value ) ;
183201 }
184202 }
203+
204+ private void RecreateGroupsInLevel ( Level level )
205+ {
206+ level . Groups = new Dictionary < int , TrileGroup > ( ) ;
207+ foreach ( var groupModel in Groups )
208+ {
209+ var group = groupModel . Value . Deserialize ( ) ;
210+ groupModel . Value . ReconstructTrilesInGroup ( group , level ) ;
211+ level . Groups [ groupModel . Key ] = group ;
212+ }
213+ }
185214 }
186215}
0 commit comments