33import java .text .DecimalFormat ;
44import java .text .DecimalFormatSymbols ;
55import java .util .Map ;
6+ import java .util .Map .Entry ;
7+ import java .util .Optional ;
8+ import java .util .Set ;
69import java .util .HashMap ;
10+ import java .util .List ;
711import java .util .stream .Collectors ;
812import java .util .stream .Stream ;
913
1216
1317@ Singleton
1418class Serializer {
15-
16- Map <String , String > commands , keys ;
19+ public Map <String , String > commands , keys , separators ;
1720 Map <Entity .Type , String > types ;
1821 Map <Curve , String > curves ;
1922 private static DecimalFormat decimalFormat ;
@@ -46,7 +49,7 @@ class Serializer {
4649 keys .put ("fontFamily" , "ff" );
4750 keys .put ("fontSize" , "s" );
4851 keys .put ("text" , "T" );
49- keys .put ("children" , "C " );
52+ keys .put ("children" , "ch " );
5053 keys .put ("scaleX" , "sx" );
5154 keys .put ("scaleY" , "sy" );
5255 keys .put ("anchorX" , "ax" );
@@ -65,6 +68,13 @@ class Serializer {
6568 commands .put ("CREATE" , "C" );
6669 commands .put ("UPDATE" , "U" );
6770 commands .put ("LOADSPRITESHEET" , "L" );
71+ commands .put ("WORLDUPDATE" , "W" );
72+
73+ separators = new HashMap <>();
74+ separators .put ("COMMAND" , ";" );
75+ separators .put ("COMMAND_ARGUMENT" , " " );
76+ separators .put ("ARGUMENT_DETAILS" , "," );
77+ separators .put ("COMMAND_TYPE" , "\n " );
6878
6979 curves = new HashMap <>();
7080 curves .put (Curve .NONE , "_" );
@@ -89,6 +99,9 @@ class Serializer {
8999 if (commands .values ().stream ().distinct ().count () != commands .values ().size ()) {
90100 throw new RuntimeException ("Duplicate commands" );
91101 }
102+ if (separators .values ().stream ().distinct ().count () != separators .values ().size ()) {
103+ throw new RuntimeException ("Duplicate separators" );
104+ }
92105 if (types .values ().stream ().distinct ().count () != types .values ().size ()) {
93106 throw new RuntimeException ("Duplicate types" );
94107 }
@@ -98,6 +111,14 @@ class Serializer {
98111 if (keys .values ().stream ().anyMatch (character -> curves .containsValue (character ))) {
99112 throw new RuntimeException ("Same string used for a curve and a property" );
100113 }
114+ if (separators .values ().stream ().anyMatch (
115+ character -> curves .containsValue (character ) ||
116+ keys .containsValue (character ) ||
117+ types .containsValue (character ) ||
118+ commands .containsValue (character )
119+ )) {
120+ throw new RuntimeException ("String already used as separator" );
121+ }
101122
102123 }
103124
@@ -120,11 +141,16 @@ static String escape(String text) {
120141 return escaped ;
121142 }
122143
123- public String serializeEntitiesStateDiff (Entity <?> entity , EntityState diff , String frameInstant ) {
124- return join (
125- commands .get ("UPDATE" ),
144+ private String serializeEntitiesStateDiff (Entity <?> entity , EntityState diff , String frameInstant ) {
145+ String meta = join (
126146 entity .getId (),
127- frameInstant ,
147+ frameInstant
148+ );
149+ if (diff .isEmpty ()) {
150+ return meta ;
151+ }
152+ return join (
153+ meta ,
128154 minifyDiff (diff )
129155 );
130156 }
@@ -156,22 +182,94 @@ private String minifyKey(String key) {
156182 private String minifyDiff (EntityState diff ) {
157183 return diff .entrySet ().stream ()
158184 .map ((entry ) -> join (minifyKey (entry .getKey ()), minifyParam (entry .getKey (), entry .getValue ())))
159- .collect (Collectors .joining (" " ));
185+ .collect (Collectors .joining (separators . get ( "COMMAND_ARGUMENT" ) ));
160186 }
161187
162- public String serializeCreateEntity (Entity <?> e ) {
188+ private String serializeCreateEntity (Entity <?> e ) {
163189 return join (
164- commands .get ("CREATE" ),
165190 types .get (e .getType ())
166191 );
167192 }
168193
169- public Object serializeLoadSpriteSheet (SpriteSheetLoader spriteSheet ) {
194+ public Optional <String > serializeCreateEntities (List <Entity <?>> entities ) {
195+ if (entities .isEmpty ()) {
196+ return Optional .empty ();
197+ } else {
198+ return Optional .of (
199+ commands .get ("CREATE" ) + entities .stream ()
200+ .map (e -> serializeCreateEntity (e ))
201+ .collect (Collectors .joining (separators .get ("COMMAND" )))
202+ );
203+ }
204+ }
205+
206+ private String serializeLoadSpriteSheet (SpriteSheetLoader spriteSheet ) {
170207 return join (
171- commands . get ( "LOADSPRITESHEET" ), spriteSheet .getName (), spriteSheet .getSourceImage (),
208+ spriteSheet .getName (), spriteSheet .getSourceImage (),
172209 spriteSheet .getWidth (), spriteSheet .getHeight (), spriteSheet .getOrigRow (), spriteSheet .getOrigCol (), spriteSheet .getImageCount (),
173210 spriteSheet .getImagesPerRow ()
174211 );
175212 }
176213
214+ public Optional <String > serializeLoadSpriteSheets (List <SpriteSheetLoader > spriteSheets ) {
215+ if (spriteSheets .isEmpty ()) {
216+ return Optional .empty ();
217+ } else {
218+ return Optional .of (
219+ commands .get ("LOADSPRITESHEET" ) + spriteSheets .stream ()
220+ .map (e -> serializeLoadSpriteSheet (e ))
221+ .collect (Collectors .joining (separators .get ("COMMAND" )))
222+ );
223+ }
224+ }
225+
226+ public Optional <String > serializeWorldStateUpdates (List <String > worldUpdates ) {
227+ if (worldUpdates .isEmpty ()) {
228+ return Optional .empty ();
229+ } else {
230+ return Optional .of (
231+ commands .get ("WORLDUPDATE" ) +
232+ worldUpdates .stream ()
233+ .collect (Collectors .joining (separators .get ("COMMAND_ARGUMENT" )))
234+ );
235+ }
236+ }
237+
238+ public Optional <String > serializeWorldDiff (List <WorldState > diffs ) {
239+ if (diffs .isEmpty ()) {
240+ return Optional .empty ();
241+ } else {
242+ List <String > serialized = diffs .stream ()
243+ .map (worldDiff -> {
244+ Optional <String > result ;
245+ Set <Entry <Entity <?>, EntityState >> diff = worldDiff .getEntityStateMap ().entrySet ();
246+ if (diff .isEmpty ()) {
247+ result = Optional .empty ();
248+ } else {
249+ result = Optional .of (
250+ diff
251+ .stream ()
252+ .map (e -> {
253+ return serializeEntitiesStateDiff (e .getKey (), e .getValue (), worldDiff .getFrameTime ());
254+ })
255+ .collect (Collectors .joining (separators .get ("COMMAND" )))
256+ );
257+ }
258+ return result ;
259+ })
260+ .filter (Optional ::isPresent )
261+ .map (Optional ::get )
262+ .collect (Collectors .toList ());
263+ if (serialized .isEmpty ()) {
264+ return Optional .empty ();
265+ } else {
266+ return Optional .of (
267+ commands .get ("UPDATE" ) + serialized
268+ .stream ()
269+ .collect (Collectors .joining (separators .get ("COMMAND" )))
270+ );
271+ }
272+ }
273+ }
274+
177275}
0 commit comments