1616
1717import entralinked .Configuration ;
1818import entralinked .Entralinked ;
19+ import entralinked .GameVersion ;
1920import entralinked .model .avenue .AvenueVisitor ;
2021import entralinked .model .dlc .Dlc ;
2122import entralinked .model .dlc .DlcList ;
@@ -202,63 +203,24 @@ private void handleDownloadSaveData(PglRequest request, Context ctx) throws IOEx
202203 return ;
203204 }
204205
205- logger .info ("Player {} is downloading save data as user {} " , player .getGameSyncId (), user . getRedactedId ());
206+ logger .info ("Player {} is downloading save data" , player .getGameSyncId ());
206207
207208 // Write status code
208209 writeStatusCode (outputStream , 0 );
209210
210- // Allow it to wake up anyway, maybe the poor sap is stuck..
211- // Just don't send any other data.
211+ // Allow waking up but don't send any data
212212 if (player .getStatus () == PlayerStatus .AWAKE ) {
213213 return ;
214214 }
215215
216+ GameVersion version = player .getGameVersion ();
216217 List <DreamEncounter > encounters = player .getEncounters ();
217218 List <DreamItem > items = player .getItems ();
218219
219- // Prepare DLC information
220- String cgearType = player .getGameVersion ().isVersion2 () ? "CGEAR2" : "CGEAR" ;
221- String cgearSkin = player .getCGearSkin ();
222- String dexSkin = player .getDexSkin ();
223- String musical = player .getMusical ();
224- int cgearSkinIndex = 0 ;
225- int dexSkinIndex = 0 ;
226- int musicalIndex = 0 ;
227-
228- // Create or remove custom C-Gear skin DLC override
229- if ("custom" .equals (cgearSkin )) {
230- cgearSkinIndex = 1 ;
231- user .setDlcOverride (cgearType , new Dlc (player .getCGearSkinFile ().getAbsolutePath (),
232- "custom" , "IRAO" , cgearType , cgearSkinIndex , 9730 , 0 , true ));
233- } else {
234- cgearSkinIndex = dlcList .getDlcIndex ("IRAO" , cgearType , cgearSkin );
235- user .removeDlcOverride (cgearType );
236- }
237-
238- // Create or remove custom Pokédex skin DLC override
239- if ("custom" .equals (dexSkin )) {
240- dexSkinIndex = 1 ;
241- user .setDlcOverride ("ZUKAN" , new Dlc (player .getDexSkinFile ().getAbsolutePath (),
242- "custom" , "IRAO" , "ZUKAN" , dexSkinIndex , 25090 , 0 , true ));
243- } else {
244- dexSkinIndex = dlcList .getDlcIndex ("IRAO" , "ZUKAN" , dexSkin );
245- user .removeDlcOverride ("ZUKAN" );
246- }
247-
248- // Create or remove custom musical DLC override
249- if ("custom" .equals (musical )) {
250- musicalIndex = 1 ;
251- File file = player .getMusicalFile ();
252- user .setDlcOverride ("MUSICAL" , new Dlc (file .getAbsolutePath (),
253- "custom" , "IRAO" , "MUSICAL" , musicalIndex , (int )file .length (), 0 , true ));
254- } else {
255- musicalIndex = dlcList .getDlcIndex ("IRAO" , "MUSICAL" , musical );
256- user .removeDlcOverride ("MUSICAL" );
257- }
258-
259- // When waking up a Pokémon, these 4 bytes are written to 0x1D304 in the save file.
260- // If the bytes in the game's save file match the new bytes, they will be set to 0x00000000
261- // and no content will be downloaded.
220+ // When waking up a Pokémon, these 4 bytes are written to 0x1D304 in the save file.
221+ // If the bytes in the game's save file match the new bytes, they will be set to 0x00000000
222+ // and no content will be downloaded.
223+ // Looking at some old save files, this was very likely just a total tuck-in/wake-up counter.
262224 outputStream .writeInt ((int )(Math .random () * Integer .MAX_VALUE ));
263225
264226 // Write encounter data (max 10)
@@ -277,9 +239,9 @@ private void handleDownloadSaveData(PglRequest request, Context ctx) throws IOEx
277239 // Write misc stuff and DLC information
278240 outputStream .writeShort (player .getLevelsGained ());
279241 outputStream .write (0 ); // Unknown
280- outputStream .write (musicalIndex );
281- outputStream .write (cgearSkinIndex );
282- outputStream .write (dexSkinIndex );
242+ outputStream .write (getDlcIndex ( user , player . getMusical (), "MUSICAL" , player . getMusicalFile ()) );
243+ outputStream .write (getDlcIndex ( user , player . getCGearSkin (), version . isVersion2 () ? "CGEAR2" : "CGEAR" , player . getCGearSkinFile ()) );
244+ outputStream .write (getDlcIndex ( user , player . getDexSkin (), "ZUKAN" , player . getDexSkinFile ()) );
283245 outputStream .write (decorList .isEmpty () ? 0 : 1 ); // Seems to be a flag for indicating whether or not decor data is present
284246 outputStream .write (0 ); // Must be zero?
285247
@@ -319,14 +281,14 @@ private void handleDownloadSaveData(PglRequest request, Context ctx) throws IOEx
319281
320282 // Join Avenue visitor data -- copied in parts to 0x2422C in the save file.
321283 // Black Version 2 and White Version 2 only.
322- if (player . getGameVersion () .isVersion2 ()) {
284+ if (version .isVersion2 ()) {
323285 List <AvenueVisitor > avenueVisitors = player .getAvenueVisitors ();
324286
325287 for (AvenueVisitor visitor : avenueVisitors ) {
326288 // Write visitor name + padding. Names cannot be duplicate.
327289 byte [] nameBytes = visitor .name ().getBytes (StandardCharsets .UTF_16LE );
328290 outputStream .write (nameBytes , 0 , Math .min (14 , nameBytes .length ));
329- outputStream .writeBytes (-1 , 14 - nameBytes .length );
291+ outputStream .writeBytes (-1 , 16 - nameBytes .length );
330292
331293 // Full visitor type consists of a trainer class and what I call a 'personality' index
332294 // that, along with the trainer class, determines which phrases the visitor uses.
@@ -335,7 +297,6 @@ private void handleDownloadSaveData(PglRequest request, Context ctx) throws IOEx
335297 // For example, if the visitor type is '0', then shop type '0' would be a raffle.
336298 // However, if the visitor type is '2', then shop type '0' results in a dojo instead.
337299 int visitorType = visitor .type ().getClientId () + visitor .personality () * 8 ;
338- outputStream .writeShort (-1 ); // Does nothing, seems to be read as part of the name.
339300 outputStream .write (visitorType );
340301 outputStream .write (visitor .shopType ().ordinal () + (7 - visitorType * 2 % 7 ));
341302 outputStream .writeShort (0 ); // Does nothing
@@ -575,4 +536,17 @@ private void writeStatusCode(LEOutputStream outputStream, int status) throws IOE
575536 outputStream .writeInt (status );
576537 outputStream .writeBytes (0 , 124 );
577538 }
539+
540+ /**
541+ * Gets the index of the player's chosen DLC for the specified type and prepares DLC overriding if necessary.
542+ */
543+ private int getDlcIndex (User user , String name , String type , File customFile ) {
544+ if ("custom" .equals (name )) {
545+ user .setDlcOverride (type , new Dlc (customFile .getAbsolutePath (), name , "IRAO" , type , 1 , (int )customFile .length (), 0 , true ));
546+ return 1 ;
547+ } else {
548+ user .removeDlcOverride (type );
549+ return dlcList .getDlcIndex ("IRAO" , type , name );
550+ }
551+ }
578552}
0 commit comments