void SV_WriteSector(Sector *sec, MapStateWriter *msw) { Writer1 *writer = msw->writer(); int i, type; float flooroffx = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_X); float flooroffy = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_Y); float ceiloffx = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_X); float ceiloffy = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_Y); byte lightlevel = (byte) (255.f * P_GetFloatp(sec, DMU_LIGHT_LEVEL)); short floorheight = (short) P_GetIntp(sec, DMU_FLOOR_HEIGHT); short ceilingheight = (short) P_GetIntp(sec, DMU_CEILING_HEIGHT); short floorFlags = (short) P_GetIntp(sec, DMU_FLOOR_FLAGS); short ceilingFlags = (short) P_GetIntp(sec, DMU_CEILING_FLAGS); world_Material *floorMaterial = (world_Material *)P_GetPtrp(sec, DMU_FLOOR_MATERIAL); world_Material *ceilingMaterial = (world_Material *)P_GetPtrp(sec, DMU_CEILING_MATERIAL); xsector_t *xsec = P_ToXSector(sec); #if !__JHEXEN__ // Determine type. if(xsec->xg) type = sc_xg1; else #endif if(NON_ZERO(flooroffx) || NON_ZERO(flooroffy) || NON_ZERO(ceiloffx) || NON_ZERO(ceiloffy)) type = sc_ploff; else type = sc_normal; // Type byte. Writer_WriteByte(writer, type); // Version. // 2: Surface colors. // 3: Surface flags. Writer_WriteByte(writer, 3); // write a version byte. Writer_WriteInt16(writer, floorheight); Writer_WriteInt16(writer, ceilingheight); Writer_WriteInt16(writer, msw->serialIdFor(floorMaterial)); Writer_WriteInt16(writer, msw->serialIdFor(ceilingMaterial)); Writer_WriteInt16(writer, floorFlags); Writer_WriteInt16(writer, ceilingFlags); #if __JHEXEN__ Writer_WriteInt16(writer, (short) lightlevel); #else Writer_WriteByte(writer, lightlevel); #endif float rgb[3]; P_GetFloatpv(sec, DMU_COLOR, rgb); for(i = 0; i < 3; ++i) Writer_WriteByte(writer, (byte)(255.f * rgb[i])); P_GetFloatpv(sec, DMU_FLOOR_COLOR, rgb); for(i = 0; i < 3; ++i) Writer_WriteByte(writer, (byte)(255.f * rgb[i])); P_GetFloatpv(sec, DMU_CEILING_COLOR, rgb); for(i = 0; i < 3; ++i) Writer_WriteByte(writer, (byte)(255.f * rgb[i])); Writer_WriteInt16(writer, xsec->special); Writer_WriteInt16(writer, xsec->tag); #if __JHEXEN__ Writer_WriteInt16(writer, xsec->seqType); #endif if(type == sc_ploff #if !__JHEXEN__ || type == sc_xg1 #endif ) { Writer_WriteFloat(writer, flooroffx); Writer_WriteFloat(writer, flooroffy); Writer_WriteFloat(writer, ceiloffx); Writer_WriteFloat(writer, ceiloffy); } #if !__JHEXEN__ if(xsec->xg) // Extended General? { SV_WriteXGSector(sec, writer); } #endif }
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 }
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); }