void writeSoundTargets() { #if !__JHEXEN__ if (!IS_SERVER) return; // Not for us. // Write the total number. int count = 0; for (int i = 0; i < numsectors; ++i) { xsector_t *xsec = P_ToXSector((Sector *)P_ToPtr(DMU_SECTOR, i)); if (xsec->soundTarget) { count += 1; } } // beginSegment(); Writer_WriteInt32(writer, count); // Write the mobj references using the mobj archive. for (int i = 0; i < numsectors; ++i) { xsector_t *xsec = P_ToXSector((Sector *)P_ToPtr(DMU_SECTOR, i)); if (xsec->soundTarget) { Writer_WriteInt32(writer, i); Writer_WriteInt16(writer, thingArchive->serialIdFor(xsec->soundTarget)); } } // endSegment(); #endif }
void SaveInfo_Write(SaveInfo *info, Writer *writer) { saveheader_t *hdr; DENG_ASSERT(info != 0); hdr = &info->header; Writer_WriteInt32(writer, hdr->magic); Writer_WriteInt32(writer, hdr->version); Writer_WriteInt32(writer, hdr->gameMode); Str_Write(&info->name, writer); Writer_WriteByte(writer, hdr->skill); Writer_WriteByte(writer, hdr->episode); Writer_WriteByte(writer, hdr->map); Writer_WriteByte(writer, hdr->deathmatch); Writer_WriteByte(writer, hdr->noMonsters); #if __JHEXEN__ Writer_WriteByte(writer, hdr->randomClasses); #else Writer_WriteByte(writer, hdr->respawnMonsters); Writer_WriteInt32(writer, hdr->mapTime); { int i; for(i = 0; i < MAXPLAYERS; ++i) { Writer_WriteByte(writer, hdr->players[i]); }} #endif Writer_WriteInt32(writer, info->gameId); }
void playerheader_s::write(Writer1 *writer) { Writer_WriteByte(writer, 2); // version byte numPowers = NUM_POWER_TYPES; numKeys = NUM_KEY_TYPES; numFrags = MAXPLAYERS; numWeapons = NUM_WEAPON_TYPES; numAmmoTypes = NUM_AMMO_TYPES; numPSprites = NUMPSPRITES; #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ numInvItemTypes = NUM_INVENTORYITEM_TYPES; #endif #if __JHEXEN__ numArmorTypes = NUMARMOR; #endif Writer_WriteInt32(writer, numPowers); Writer_WriteInt32(writer, numKeys); Writer_WriteInt32(writer, numFrags); Writer_WriteInt32(writer, numWeapons); Writer_WriteInt32(writer, numAmmoTypes); Writer_WriteInt32(writer, numPSprites); #if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ Writer_WriteInt32(writer, numInvItemTypes); #endif #if __JHEXEN__ Writer_WriteInt32(writer, numArmorTypes); #endif }
void fireflicker_s::write(MapStateWriter *msw) const { Writer1 *writer = msw->writer(); Writer_WriteByte(writer, 1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. Writer_WriteInt32(writer, P_ToIndex(sector)); Writer_WriteInt32(writer, (int) (255.0f * maxLight)); Writer_WriteInt32(writer, (int) (255.0f * minLight)); }
void writePlayers() { beginSegment(ASEG_PLAYER_HEADER); playerheader_t plrHdr; plrHdr.write(writer); beginSegment(ASEG_PLAYERS); { #if __JHEXEN__ for (int i = 0; i < MAXPLAYERS; ++i) { Writer_WriteByte(writer, players[i].plr->inGame); } #endif for (int i = 0; i < MAXPLAYERS; ++i) { player_t *plr = players + i; if (!plr->plr->inGame) continue; Writer_WriteInt32(writer, Net_GetPlayerID(i)); plr->write(writer, plrHdr); } } endSegment(); }
void writeMapHeader() { #if __JHEXEN__ // Maps have their own version number. Writer_WriteByte(writer, MY_SAVE_VERSION); // Write the map timer Writer_WriteInt32(writer, mapTime); #endif }
void writeMisc() { #if __JHEXEN__ beginSegment(ASEG_MISC); for (int i = 0; i < MAXPLAYERS; ++i) { Writer_WriteInt32(writer, localQuakeHappening[i]); } #endif #if __JDOOM__ DENG2_ASSERT(theBossBrain != 0); theBossBrain->write(thisPublic); #endif }
void plat_t::write(MapStateWriter *msw) const { Writer *writer = msw->writer(); Writer_WriteByte(writer, 1); // Write a version byte. Writer_WriteByte(writer, (byte) type); Writer_WriteInt32(writer, P_ToIndex(sector)); Writer_WriteInt32(writer, FLT2FIX(speed)); Writer_WriteInt16(writer, (int)low); Writer_WriteInt16(writer, (int)high); Writer_WriteInt32(writer, wait); Writer_WriteInt32(writer, count); Writer_WriteByte(writer, (byte) state); Writer_WriteByte(writer, (byte) oldState); Writer_WriteByte(writer, (byte) crush); Writer_WriteInt32(writer, tag); }
void waggle_s::write(MapStateWriter *msw) const { Writer1 *writer = msw->writer(); Writer_WriteByte(writer, 1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. Writer_WriteInt32(writer, P_ToIndex(sector)); Writer_WriteInt32(writer, FLT2FIX(originalHeight)); Writer_WriteInt32(writer, FLT2FIX(accumulator)); Writer_WriteInt32(writer, FLT2FIX(accDelta)); Writer_WriteInt32(writer, FLT2FIX(targetScale)); Writer_WriteInt32(writer, FLT2FIX(scale)); Writer_WriteInt32(writer, FLT2FIX(scaleDelta)); Writer_WriteInt32(writer, ticker); Writer_WriteInt32(writer, state); }
void writePolyobjs() { #if __JHEXEN__ beginSegment(ASEG_POLYOBJS); Writer_WriteInt32(writer, numpolyobjs); for (int i = 0; i < numpolyobjs; ++i) { Polyobj *po = Polyobj_ById(i); DENG2_ASSERT(po != 0); po->write(thisPublic); } // endSegment(); #endif }
/** * Serializes thinkers for both client and server. * * @note Clients do not save data for all thinkers. In some cases the server will send it * anyway (so saving it would just bloat client save states). * * @note Some thinker classes are NEVER saved by clients. */ void writeThinkers() { beginSegment(ASEG_THINKERS); #if __JHEXEN__ Writer_WriteInt32(writer, thingArchive->size()); // number of mobjs. #endif // Serialize qualifying thinkers. writethinkerworker_params_t parm; de::zap(parm); parm.msw = thisPublic; parm.excludePlayers = thingArchive->excludePlayers(); Thinker_Iterate(0/*all thinkers*/, writeThinkerWorker, &parm); // Mark the end of the thinkers. // endSegment(); Writer_WriteByte(writer, TC_END); }
void pillar_s::write(MapStateWriter *msw) const { Writer1 *writer = msw->writer(); Writer_WriteByte(writer, 1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. Writer_WriteInt32(writer, P_ToIndex(sector)); Writer_WriteInt32(writer, FLT2FIX(ceilingSpeed)); Writer_WriteInt32(writer, FLT2FIX(floorSpeed)); Writer_WriteInt32(writer, FLT2FIX(floorDest)); Writer_WriteInt32(writer, FLT2FIX(ceilingDest)); Writer_WriteInt32(writer, direction); Writer_WriteInt32(writer, crush); }
void light_s::write(MapStateWriter *msw) const { Writer1 *writer = msw->writer(); Writer_WriteByte(writer, 1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. Writer_WriteByte(writer, (byte)type); Writer_WriteInt32(writer, P_ToIndex(sector)); Writer_WriteInt32(writer, (int) (255.0f * value1)); Writer_WriteInt32(writer, (int) (255.0f * value2)); Writer_WriteInt32(writer, tics1); Writer_WriteInt32(writer, tics2); Writer_WriteInt32(writer, count); }
void SV_SaveGameClient(uint /*sessionId*/) { throw de::Error("SV_SaveGameClient", "Not currently implemented"); #if 0 #if !__JHEXEN__ // unsupported in libhexen player_t *pl = &players[CONSOLEPLAYER]; mobj_t *mo = pl->plr->mo; if(!IS_CLIENT || !mo) return; // Prepare new saved game session session. de::game::GameStateFolder *session = new de::game::GameStateFolder(saveNameForClientSessionId(sessionId)); de::game::GameStateMetadata *metadata = G_CurrentSessionMetadata(); metadata->set("sessionId", sessionId); session->replaceMetadata(metadata); de::Path path = de::String("/savegame") / "client" / session->path(); if(!SV_OpenFileForWrite(path)) { App_Log(DE2_RES_WARNING, "SV_SaveGameClient: Failed opening \"%s\" for writing", path.toString().toLatin1().constData()); // Discard the useless session. delete session; return; } Writer1 *writer = SV_NewWriter(); SV_WriteSessionMetadata(*metadata, writer); // Some important information. // Our position and look angles. Writer_WriteInt32(writer, FLT2FIX(mo->origin[VX])); Writer_WriteInt32(writer, FLT2FIX(mo->origin[VY])); Writer_WriteInt32(writer, FLT2FIX(mo->origin[VZ])); Writer_WriteInt32(writer, FLT2FIX(mo->floorZ)); Writer_WriteInt32(writer, FLT2FIX(mo->ceilingZ)); Writer_WriteInt32(writer, mo->angle); /* $unifiedangles */ Writer_WriteFloat(writer, pl->plr->lookDir); /* $unifiedangles */ SV_BeginSegment(ASEG_PLAYER_HEADER); playerheader_t plrHdr; plrHdr.write(writer); players[CONSOLEPLAYER].write(writer, plrHdr); ThingArchive thingArchive; MapStateWriter(thingArchive).write(writer); /// @todo No consistency bytes in client saves? SV_CloseFile(); Writer_Delete(writer); delete session; #else DENG2_UNUSED(sessionId); #endif #endif }
void SV_WriteLine(Line *li, MapStateWriter *msw) { xline_t *xli = P_ToXLine(li); Writer1 *writer = msw->writer(); #if !__JHEXEN__ Writer_WriteByte(writer, xli->xg? 1 : 0); /// @c 1= XG data will follow. #else Writer_WriteByte(writer, 0); #endif // Version. // 2: Per surface texture offsets. // 2: Surface colors. // 3: "Mapped by player" values. // 3: Surface flags. // 4: Engine-side line flags. Writer_WriteByte(writer, 4); // Write a version byte Writer_WriteInt16(writer, P_GetIntp(li, DMU_FLAGS)); Writer_WriteInt16(writer, xli->flags); for(int i = 0; i < MAXPLAYERS; ++i) Writer_WriteByte(writer, xli->mapped[i]); #if __JHEXEN__ Writer_WriteByte(writer, xli->special); Writer_WriteByte(writer, xli->arg1); Writer_WriteByte(writer, xli->arg2); Writer_WriteByte(writer, xli->arg3); Writer_WriteByte(writer, xli->arg4); Writer_WriteByte(writer, xli->arg5); #else Writer_WriteInt16(writer, xli->special); Writer_WriteInt16(writer, xli->tag); #endif // For each side float rgba[4]; for(int i = 0; i < 2; ++i) { Side *si = (Side *)P_GetPtrp(li, (i? DMU_BACK:DMU_FRONT)); if(!si) continue; Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_X)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_Y)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_X)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_Y)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_X)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_Y)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_FLAGS)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_FLAGS)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_FLAGS)); Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_TOP_MATERIAL))); Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_BOTTOM_MATERIAL))); Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_MIDDLE_MATERIAL))); P_GetFloatpv(si, DMU_TOP_COLOR, rgba); for(int k = 0; k < 3; ++k) Writer_WriteByte(writer, (byte)(255 * rgba[k])); P_GetFloatpv(si, DMU_BOTTOM_COLOR, rgba); for(int k = 0; k < 3; ++k) Writer_WriteByte(writer, (byte)(255 * rgba[k])); P_GetFloatpv(si, DMU_MIDDLE_COLOR, rgba); for(int k = 0; k < 4; ++k) Writer_WriteByte(writer, (byte)(255 * rgba[k])); Writer_WriteInt32(writer, P_GetIntp(si, DMU_MIDDLE_BLENDMODE)); Writer_WriteInt16(writer, P_GetIntp(si, DMU_FLAGS)); } #if !__JHEXEN__ // Extended General? if(xli->xg) { SV_WriteXGLine(li, msw); } #endif }
static void Net_DoUpdate(void) { static int lastTime = 0; int nowTime, newTics; /** * This timing is only used by the client when it determines if it is * time to send ticcmds or coordinates to the server. */ // Check time. nowTime = Timer_Ticks(); // Clock reset? if(firstNetUpdate) { firstNetUpdate = false; lastTime = nowTime; } newTics = nowTime - lastTime; if(newTics <= 0) return; // Nothing new to update. lastTime = nowTime; // This is as far as dedicated servers go. #ifdef __CLIENT__ /** * Clients will periodically send their coordinates to the server so * any prediction errors can be fixed. Client movement is almost * entirely local. */ #ifdef _DEBUG if(netGame && verbose >= 2) { Con_Message("Net_DoUpdate: coordTimer=%i cl:%i shmo:%p", coordTimer, isClient, ddPlayers[consolePlayer].shared.mo); } #endif coordTimer -= newTics; if(isClient && coordTimer <= 0 && ddPlayers[consolePlayer].shared.mo) { mobj_t *mo = ddPlayers[consolePlayer].shared.mo; coordTimer = 1; //netCoordTime; // 35/2 Msg_Begin(PKT_COORDS); Writer_WriteFloat(msgWriter, gameTime); Writer_WriteFloat(msgWriter, mo->origin[VX]); Writer_WriteFloat(msgWriter, mo->origin[VY]); if(mo->origin[VZ] == mo->floorZ) { // This'll keep us on the floor even in fast moving sectors. Writer_WriteInt32(msgWriter, DDMININT); } else { Writer_WriteInt32(msgWriter, FLT2FIX(mo->origin[VZ])); } // Also include angles. Writer_WriteUInt16(msgWriter, mo->angle >> 16); Writer_WriteInt16(msgWriter, P_LookDirToShort(ddPlayers[consolePlayer].shared.lookDir)); // Control state. Writer_WriteChar(msgWriter, FLT2FIX(ddPlayers[consolePlayer].shared.forwardMove) >> 13); Writer_WriteChar(msgWriter, FLT2FIX(ddPlayers[consolePlayer].shared.sideMove) >> 13); Msg_End(); Net_SendBuffer(0, 0); }
void mobj_s::write(MapStateWriter *msw) const { Writer1 *writer = msw->writer(); mobj_t const *mo = this; // Version. // JHEXEN // 2: Added the 'translucency' byte. // 3: Added byte 'vistarget' // 4: Added long 'tracer' // 4: Added long 'lastenemy' // 5: Added flags3 // 6: Floor material removed. // // JDOOM || JHERETIC || JDOOM64 // 4: Added byte 'translucency' // 5: Added byte 'vistarget' // 5: Added tracer in jDoom // 5: Added dropoff fix in jHeretic // 5: Added long 'floorclip' // 6: Added proper respawn data // 6: Added flags 2 in jDoom // 6: Added damage // 7: Added generator in jHeretic // 7: Added flags3 // // JDOOM // 9: Revised mapspot flag interpretation // // JHERETIC // 8: Added special3 // 9: Revised mapspot flag interpretation // // JHEXEN // 7: Removed superfluous info ptr // 8: Added 'onMobj' Writer_WriteByte(writer, MOBJ_SAVEVERSION); #if !__JHEXEN__ // A version 2 features: archive number and target. Writer_WriteInt16(writer, msw->serialIdFor(mo)); Writer_WriteInt16(writer, msw->serialIdFor(mo->target)); # if __JDOOM__ || __JDOOM64__ // Ver 5 features: Save tracer (fixes Archvile, Revenant bug) Writer_WriteInt16(writer, msw->serialIdFor(mo->tracer)); # endif #endif Writer_WriteInt16(writer, msw->serialIdFor(mo->onMobj)); // Info for drawing: position. Writer_WriteInt32(writer, FLT2FIX(mo->origin[VX])); Writer_WriteInt32(writer, FLT2FIX(mo->origin[VY])); Writer_WriteInt32(writer, FLT2FIX(mo->origin[VZ])); //More drawing info: to determine current sprite. Writer_WriteInt32(writer, mo->angle); // Orientation. Writer_WriteInt32(writer, mo->sprite); // Used to find patch_t and flip value. Writer_WriteInt32(writer, mo->frame); #if !__JHEXEN__ // The closest interval over all contacted Sectors. Writer_WriteInt32(writer, FLT2FIX(mo->floorZ)); Writer_WriteInt32(writer, FLT2FIX(mo->ceilingZ)); #endif // For movement checking. Writer_WriteInt32(writer, FLT2FIX(mo->radius)); Writer_WriteInt32(writer, FLT2FIX(mo->height)); // Momentums, used to update position. Writer_WriteInt32(writer, FLT2FIX(mo->mom[MX])); Writer_WriteInt32(writer, FLT2FIX(mo->mom[MY])); Writer_WriteInt32(writer, FLT2FIX(mo->mom[MZ])); // If == VALIDCOUNT, already checked. Writer_WriteInt32(writer, mo->valid); Writer_WriteInt32(writer, mo->type); Writer_WriteInt32(writer, mo->tics); // State tic counter. Writer_WriteInt32(writer, int(mo->state - STATES) /*PTR2INT(mo->state)*/); #if __JHEXEN__ Writer_WriteInt32(writer, mo->damage); #endif Writer_WriteInt32(writer, mo->flags); #if __JHEXEN__ Writer_WriteInt32(writer, mo->flags2); Writer_WriteInt32(writer, mo->flags3); if(mo->type == MT_KORAX) Writer_WriteInt32(writer, 0); // Searching index. else Writer_WriteInt32(writer, mo->special1); switch(mo->type) { case MT_LIGHTNING_FLOOR: case MT_LIGHTNING_ZAP: case MT_HOLY_TAIL: case MT_LIGHTNING_CEILING: if(mo->flags & MF_CORPSE) Writer_WriteInt32(writer, 0); else Writer_WriteInt32(writer, msw->serialIdFor(INT2PTR(mobj_t, mo->special2))); break; default: Writer_WriteInt32(writer, mo->special2); break; } #endif Writer_WriteInt32(writer, mo->health); // Movement direction, movement generation (zig-zagging). Writer_WriteInt32(writer, mo->moveDir); // 0-7 Writer_WriteInt32(writer, mo->moveCount); // When 0, select a new dir. #if __JHEXEN__ if(mo->flags & MF_CORPSE) Writer_WriteInt32(writer, 0); else Writer_WriteInt32(writer, (int) msw->serialIdFor(mo->target)); #endif // Reaction time: if non 0, don't attack yet. // Used by player to freeze a bit after teleporting. Writer_WriteInt32(writer, mo->reactionTime); // If >0, the target will be chased no matter what (even if shot). Writer_WriteInt32(writer, mo->threshold); // Additional info record for player avatars only (only valid if type is MT_PLAYER). { int const playerNum = (mo->player? int(mo->player - players + 1) : 0); Writer_WriteInt32(writer, playerNum /*PTR2INT(mo->player)*/); } // Player number last looked for. Writer_WriteInt32(writer, mo->lastLook); #if !__JHEXEN__ // For nightmare/multiplayer respawn. Writer_WriteInt32(writer, FLT2FIX(mo->spawnSpot.origin[VX])); Writer_WriteInt32(writer, FLT2FIX(mo->spawnSpot.origin[VY])); Writer_WriteInt32(writer, FLT2FIX(mo->spawnSpot.origin[VZ])); Writer_WriteInt32(writer, mo->spawnSpot.angle); Writer_WriteInt32(writer, mo->spawnSpot.flags); Writer_WriteInt32(writer, mo->intFlags); // $dropoff_fix: internal flags. Writer_WriteInt32(writer, FLT2FIX(mo->dropOffZ)); // $dropoff_fix Writer_WriteInt32(writer, mo->gear); // Used in torque simulation. Writer_WriteInt32(writer, mo->damage); Writer_WriteInt32(writer, mo->flags2); Writer_WriteInt32(writer, mo->flags3); # ifdef __JHERETIC__ Writer_WriteInt32(writer, mo->special1); Writer_WriteInt32(writer, mo->special2); Writer_WriteInt32(writer, mo->special3); # endif Writer_WriteByte(writer, mo->translucency); Writer_WriteByte(writer, (byte)(mo->visTarget + 1)); #endif Writer_WriteInt32(writer, FLT2FIX(mo->floorClip)); #if __JHEXEN__ Writer_WriteInt32(writer, msw->serialIdFor(mo)); Writer_WriteInt32(writer, mo->tid); Writer_WriteInt32(writer, mo->special); Writer_Write(writer, mo->args, sizeof(mo->args)); Writer_WriteByte(writer, mo->translucency); Writer_WriteByte(writer, (byte)(mo->visTarget + 1)); switch(mo->type) { case MT_BISH_FX: case MT_HOLY_FX: case MT_DRAGON: case MT_THRUSTFLOOR_UP: case MT_THRUSTFLOOR_DOWN: case MT_MINOTAUR: case MT_SORCFX1: case MT_MSTAFF_FX2: case MT_HOLY_TAIL: case MT_LIGHTNING_CEILING: if(mo->flags & MF_CORPSE) Writer_WriteInt32(writer, 0); else Writer_WriteInt32(writer, msw->serialIdFor(mo->tracer)); break; default: DENG_ASSERT(mo->tracer == NULL); /// @todo Tracer won't be saved correctly? Writer_WriteInt32(writer, PTR2INT(mo->tracer)); break; } Writer_WriteInt32(writer, PTR2INT(mo->lastEnemy)); #elif __JHERETIC__ Writer_WriteInt16(writer, msw->serialIdFor(mo->generator)); #endif }