void NetDemo::writeSnapshotData(byte *buf, size_t &length) { G_SnapshotLevel(); FLZOMemFile memfile; memfile.Open(); // open for writing FArchive arc(memfile); // Save the server cvars byte vars[4096], *vars_p; vars_p = vars; cvar_t::C_WriteCVars(&vars_p, CVAR_SERVERINFO); arc.WriteCount(vars_p - vars); arc.Write(vars, vars_p - vars); arc << level.mapname; arc << (BYTE)(gamestate == GS_INTERMISSION); G_SerializeSnapshots(arc); P_SerializeRNGState(arc); P_SerializeACSDefereds(arc); // Save the status of the flags in CTF for (int i = 0; i < NUMFLAGS; i++) arc << CTFdata[i]; // Save team points for (int i = 0; i < NUMTEAMS; i++) arc << TEAMpoints[i]; arc << level.time; for (int i = 0; i < NUM_WORLDVARS; i++) arc << ACS_WorldVars[i]; for (int i = 0; i < NUM_GLOBALVARS; i++) arc << ACS_GlobalVars[i]; byte check = 0x1d; arc << check; // consistancy marker gameaction = ga_nothing; arc.Close(); // get the size of the snapshot data length = memfile.Length(); memfile.WriteToBuffer(buf, NetDemo::MAX_SNAPSHOT_SIZE); if (level.info->snapshot != NULL) { delete level.info->snapshot; level.info->snapshot = NULL; } }
void G_DoCompleted (void) { int i; gameaction = ga_nothing; if (gamestate == GS_TITLELEVEL) { level.MapName = nextlevel; G_DoLoadLevel (startpos, false); startpos = 0; viewactive = true; return; } // [RH] Mark this level as having been visited if (!(level.flags & LEVEL_CHANGEMAPCHEAT)) FindLevelInfo (level.MapName)->flags |= LEVEL_VISITED; if (automapactive) AM_Stop (); wminfo.finished_ep = level.cluster - 1; wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->PName, FTexture::TEX_MiscPatch)]; wminfo.current = level.MapName; if (deathmatch && (dmflags & DF_SAME_LEVEL) && !(level.flags & LEVEL_CHANGEMAPCHEAT)) { wminfo.next = level.MapName; wminfo.LName1 = wminfo.LName0; } else { level_info_t *nextinfo = FindLevelInfo (nextlevel, false); if (nextinfo == NULL || strncmp (nextlevel, "enDSeQ", 6) == 0) { wminfo.next = nextlevel; wminfo.LName1 = NULL; } else { wminfo.next = nextinfo->MapName; wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->PName, FTexture::TEX_MiscPatch)]; } } CheckWarpTransMap (wminfo.next, true); nextlevel = wminfo.next; wminfo.next_ep = FindLevelInfo (wminfo.next)->cluster - 1; wminfo.maxkills = level.total_monsters; wminfo.maxitems = level.total_items; wminfo.maxsecret = level.total_secrets; wminfo.maxfrags = 0; wminfo.partime = TICRATE * level.partime; wminfo.sucktime = level.sucktime; wminfo.pnum = consoleplayer; wminfo.totaltime = level.totaltime; for (i=0 ; i<MAXPLAYERS ; i++) { wminfo.plyr[i].in = playeringame[i]; wminfo.plyr[i].skills = players[i].killcount; wminfo.plyr[i].sitems = players[i].itemcount; wminfo.plyr[i].ssecret = players[i].secretcount; wminfo.plyr[i].stime = level.time; memcpy (wminfo.plyr[i].frags, players[i].frags , sizeof(wminfo.plyr[i].frags)); wminfo.plyr[i].fragcount = players[i].fragcount; } // [RH] If we're in a hub and staying within that hub, take a snapshot // of the level. If we're traveling to a new hub, take stuff from // the player and clear the world vars. If this is just an // ordinary cluster (not a hub), take stuff from the player, but // leave the world vars alone. cluster_info_t *thiscluster = FindClusterInfo (level.cluster); cluster_info_t *nextcluster = FindClusterInfo (wminfo.next_ep+1); // next_ep is cluster-1 EFinishLevelType mode; if (thiscluster != nextcluster || deathmatch || !(thiscluster->flags & CLUSTER_HUB)) { if (nextcluster->flags & CLUSTER_HUB) { mode = FINISH_NextHub; } else { mode = FINISH_NoHub; } } else { mode = FINISH_SameHub; } // Intermission stats for entire hubs G_LeavingHub(mode, thiscluster, &wminfo); for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { // take away appropriate inventory G_PlayerFinishLevel (i, mode, changeflags); } } if (mode == FINISH_SameHub) { // Remember the level's state for re-entry. if (!(level.flags2 & LEVEL2_FORGETSTATE)) { G_SnapshotLevel (); // Do not free any global strings this level might reference // while it's not loaded. FBehavior::StaticLockLevelVarStrings(); } else { // Make sure we don't have a snapshot lying around from before. level.info->ClearSnapshot(); } } else { // Forget the states of all existing levels. G_ClearSnapshots (); if (mode == FINISH_NextHub) { // Reset world variables for the new hub. P_ClearACSVars(false); } level.time = 0; level.maptime = 0; } if (!deathmatch && ((level.flags & LEVEL_NOINTERMISSION) || ((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB)))) { G_WorldDone (); return; } gamestate = GS_INTERMISSION; viewactive = false; automapactive = false; // [RH] If you ever get a statistics driver operational, adapt this. // if (statcopy) // memcpy (statcopy, &wminfo, sizeof(wminfo)); WI_Start (&wminfo); }