void FRemapTable::StaticSerializeTranslations(FSerializer &arc) { if (arc.BeginArray("translations")) { // Does this level have custom translations? FRemapTable *trans; int w; if (arc.isWriting()) { for (unsigned int i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i) { trans = translationtables[TRANSLATION_LevelScripted][i]; if (trans != NULL && !trans->IsIdentity()) { if (arc.BeginObject(nullptr)) { arc("index", i); trans->Serialize(arc); arc.EndObject(); } } } } else { while (arc.BeginObject(nullptr)) { arc("index", w); trans = translationtables[TRANSLATION_LevelScripted].GetVal(w); if (trans == NULL) { trans = new FRemapTable; translationtables[TRANSLATION_LevelScripted].SetVal(w, trans); } trans->Serialize(arc); arc.EndObject(); } } arc.EndArray(); } }
void P_SerializeSounds(FSerializer &arc) { S_SerializeSounds(arc); DSeqNode::SerializeSequences (arc); const char *name = NULL; BYTE order; if (arc.isWriting()) { order = S_GetMusic(&name); } arc.StringPtr("musicname", name) ("musicorder", order); if (arc.isReading()) { if (!S_ChangeMusic(name, order)) if (level.cdtrack == 0 || !S_ChangeCDMusic(level.cdtrack, level.cdid)) S_ChangeMusic(level.Music, level.musicorder); } }
void G_SerializeLevel(FSerializer &arc, bool hubload) { int i = level.totaltime; if (arc.isWriting()) { arc.Array("checksum", level.md5, 16); } else { // prevent bad things from happening by doing a check on the size of level arrays and the map's entire checksum. // The old code happily tried to load savegames with any mismatch here, often causing meaningless errors // deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered. BYTE chk[16] = { 0 }; arc.Array("checksum", chk, 16); if (arc.GetSize("linedefs") != (unsigned)numlines || arc.GetSize("sidedefs") != (unsigned)numsides || arc.GetSize("sectors") != (unsigned)numsectors || arc.GetSize("polyobjs") != (unsigned)po_NumPolyobjs || memcmp(chk, level.md5, 16)) { I_Error("Savegame is from a different level"); } } arc("saveversion", SaveVersion); Renderer->StartSerialize(arc); if (arc.isReading()) { DThinker::DestroyAllThinkers(); interpolator.ClearInterpolations(); arc.ReadObjects(hubload); } arc("level.flags", level.flags) ("level.flags2", level.flags2) ("level.fadeto", level.fadeto) ("level.found_secrets", level.found_secrets) ("level.found_items", level.found_items) ("level.killed_monsters", level.killed_monsters) ("level.total_secrets", level.total_secrets) ("level.total_items", level.total_items) ("level.total_monsters", level.total_monsters) ("level.gravity", level.gravity) ("level.aircontrol", level.aircontrol) ("level.teamdamage", level.teamdamage) ("level.maptime", level.maptime) ("level.totaltime", i) ("level.skytexture1", level.skytexture1) ("level.skytexture2", level.skytexture2); // Hub transitions must keep the current total time if (!hubload) level.totaltime = i; if (arc.isReading()) { sky1texture = level.skytexture1; sky2texture = level.skytexture2; R_InitSkyMap(); G_AirControlChanged(); } // fixme: This needs to ensure it reads from the correct place. Should be one once there's enough of this code converted to JSON FBehavior::StaticSerializeModuleStates(arc); // The order here is important: First world state, then portal state, then thinkers, and last polyobjects. arc.Array("linedefs", lines, &loadlines[0], numlines); arc.Array("sidedefs", sides, &loadsides[0], numsides); arc.Array("sectors", sectors, &loadsectors[0], numsectors); arc("zones", Zones); arc("lineportals", linePortals); arc("sectorportals", sectorPortals); if (arc.isReading()) P_CollectLinkedPortals(); DThinker::SerializeThinkers(arc, !hubload); arc.Array("polyobjs", polyobjs, po_NumPolyobjs); arc("subsectors", subsectors); StatusBar->SerializeMessages(arc); AM_SerializeMarkers(arc); FRemapTable::StaticSerializeTranslations(arc); FCanvasTextureInfo::Serialize(arc); P_SerializePlayers(arc, hubload); P_SerializeSounds(arc); if (arc.isReading()) { for (int i = 0; i < numsectors; i++) { P_Recalculate3DFloors(§ors[i]); } for (int i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL) { players[i].mo->SetupWeaponSlots(); } } } Renderer->EndSerialize(arc); }
void P_SerializePlayers(FSerializer &arc, bool skipload) { int numPlayers, numPlayersNow; int i; // Count the number of players present right now. for (numPlayersNow = 0, i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i]) { ++numPlayersNow; } } if (arc.isWriting()) { // Record the number of players in this save. arc("numplayers", numPlayersNow); if (arc.BeginArray("players")) { // Record each player's name, followed by their data. for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i]) { if (arc.BeginObject(nullptr)) { const char *n = players[i].userinfo.GetName(); arc.StringPtr("playername", n); players[i].Serialize(arc); arc.EndObject(); } } } arc.EndArray(); } } else { arc("numplayers", numPlayers); if (arc.BeginArray("players")) { // If there is only one player in the game, they go to the // first player present, no matter what their name. if (numPlayers == 1) { ReadOnePlayer(arc, skipload); } else { ReadMultiplePlayers(arc, numPlayers, numPlayersNow, skipload); } arc.EndArray(); } if (!skipload && numPlayersNow > numPlayers) { SpawnExtraPlayers(); } // Redo pitch limits, since the spawned player has them at 0. players[consoleplayer].SendPitchLimits(); } }