// //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// // Power Checking. Send a power level check every now and again. static BOOL sendPowerCheck() { uint8_t player; if (powerCheckLastSent > gameTime) { powerCheckLastSent = 0; } // Only send if not done recently if (gameTime - powerCheckLastSent < POWER_PERIOD) { return true; } powerCheckLastSent = gameTime; for (player = 0; player < MAX_PLAYERS; ++player) { powerCheckLastPower[player] = getPrecisePower(player); if (myResponsibility(player)) { if (!isInSync()) // Don't really send anything, unless out of synch. { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_POWER); NETuint8_t(&player); NETuint32_t(&gameTime); NETint64_t(&powerCheckLastPower[player]); NETend(); } } } return true; }
void CCovarianceFunctionCacheOld::validateCache() { if (!isInSync()) { KCacheNull = true; SVDCacheNull = true; cholKCacheNull = true; //set sync } setSync(); }
static void gameStateUpdate() { // Can't dump isHumanPlayer, since it causes spurious desynch dumps when players leave. // TODO isHumanPlayer should probably be synchronised, since the game state seems to depend on it, so there might also be a risk of real desynchs when players leave. //syncDebug("map = \"%s\", humanPlayers = %d %d %d %d %d %d %d %d", game.map, isHumanPlayer(0), isHumanPlayer(1), isHumanPlayer(2), isHumanPlayer(3), isHumanPlayer(4), isHumanPlayer(5), isHumanPlayer(6), isHumanPlayer(7)); syncDebug("map = \"%s\"", game.map); // Actually send pending droid orders. sendQueuedDroidInfo(); sendPlayerGameTime(); gameSRand(gameTime); // Brute force way of synchronising the random number generator, which can't go out of synch. if (!paused && !scriptPaused() && !editPaused()) { /* Update the event system */ if (!bInTutorial) { eventProcessTriggers(gameTime/SCR_TICKRATE); } else { eventProcessTriggers(realTime/SCR_TICKRATE); } updateScripts(); } // Update abandoned structures handleAbandonedStructures(); // Update the visibility change stuff visUpdateLevel(); // Put all droids/structures/features into the grid. gridReset(); // Check which objects are visible. processVisibility(); // Update the map. mapUpdate(); //update the findpath system fpathUpdate(); // update the cluster system clusterUpdate(); // update the command droids cmdDroidUpdate(); if(getDrivingStatus()) { driveUpdate(); } fireWaitingCallbacks(); //Now is the good time to fire waiting callbacks (since interpreter is off now) for (unsigned i = 0; i < MAX_PLAYERS; i++) { //update the current power available for a player updatePlayerPower(i); //set the flag for each player setHQExists(false, i); setSatUplinkExists(false, i); numCommandDroids[i] = 0; numConstructorDroids[i] = 0; numDroids[i]=0; numTransporterDroids[i]=0; DROID *psNext; for (DROID *psCurr = apsDroidLists[i]; psCurr != NULL; psCurr = psNext) { // Copy the next pointer - not 100% sure if the droid could get destroyed but this covers us anyway psNext = psCurr->psNext; droidUpdate(psCurr); // update the droid counts numDroids[i]++; switch (psCurr->droidType) { case DROID_COMMAND: numCommandDroids[i] += 1; break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: numConstructorDroids[i] += 1; break; case DROID_TRANSPORTER: if( (psCurr->psGroup != NULL) ) { DROID *psDroid = NULL; numTransporterDroids[i] += psCurr->psGroup->refCount-1; // and count the units inside it... for (psDroid = psCurr->psGroup->psList; psDroid != NULL && psDroid != psCurr; psDroid = psDroid->psGrpNext) { if (psDroid->droidType == DROID_CYBORG_CONSTRUCT || psDroid->droidType == DROID_CONSTRUCT) { numConstructorDroids[i] += 1; } if (psDroid->droidType == DROID_COMMAND) { numCommandDroids[i] += 1; } } } break; default: break; } } numMissionDroids[i]=0; for (DROID *psCurr = mission.apsDroidLists[i]; psCurr != NULL; psCurr = psNext) { /* Copy the next pointer - not 100% sure if the droid could get destroyed but this covers us anyway */ psNext = psCurr->psNext; missionDroidUpdate(psCurr); numMissionDroids[i]++; switch (psCurr->droidType) { case DROID_COMMAND: numCommandDroids[i] += 1; break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: numConstructorDroids[i] += 1; break; case DROID_TRANSPORTER: if( (psCurr->psGroup != NULL) ) { numTransporterDroids[i] += psCurr->psGroup->refCount-1; } break; default: break; } } for (DROID *psCurr = apsLimboDroids[i]; psCurr != NULL; psCurr = psNext) { /* Copy the next pointer - not 100% sure if the droid could get destroyed but this covers us anyway */ psNext = psCurr->psNext; // count the type of units switch (psCurr->droidType) { case DROID_COMMAND: numCommandDroids[i] += 1; break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: numConstructorDroids[i] += 1; break; default: break; } } // FIXME: These for-loops are code duplicationo /*set this up AFTER droidUpdate so that if trying to building a new one, we know whether one exists already*/ setLasSatExists(false, i); STRUCTURE *psNBuilding; for (STRUCTURE *psCBuilding = apsStructLists[i]; psCBuilding != NULL; psCBuilding = psNBuilding) { /* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway */ psNBuilding = psCBuilding->psNext; structureUpdate(psCBuilding, false); //set animation flag if (psCBuilding->pStructureType->type == REF_HQ && psCBuilding->status == SS_BUILT) { setHQExists(true, i); } if (psCBuilding->pStructureType->type == REF_SAT_UPLINK && psCBuilding->status == SS_BUILT) { setSatUplinkExists(true, i); } //don't wait for the Las Sat to be built - can't build another if one is partially built if (asWeaponStats[psCBuilding->asWeaps[0].nStat]. weaponSubClass == WSC_LAS_SAT) { setLasSatExists(true, i); } } for (STRUCTURE *psCBuilding = mission.apsStructLists[i]; psCBuilding != NULL; psCBuilding = psNBuilding) { /* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway. It shouldn't do since its not even on the map!*/ psNBuilding = psCBuilding->psNext; structureUpdate(psCBuilding, true); // update for mission if (psCBuilding->pStructureType->type == REF_HQ && psCBuilding->status == SS_BUILT) { setHQExists(true, i); } if (psCBuilding->pStructureType->type == REF_SAT_UPLINK && psCBuilding->status == SS_BUILT) { setSatUplinkExists(true, i); } //don't wait for the Las Sat to be built - can't build another if one is partially built if (asWeaponStats[psCBuilding->asWeaps[0].nStat]. weaponSubClass == WSC_LAS_SAT) { setLasSatExists(true, i); } } } missionTimerUpdate(); proj_UpdateAll(); FEATURE *psNFeat; for (FEATURE *psCFeat = apsFeatureLists[0]; psCFeat; psCFeat = psNFeat) { psNFeat = psCFeat->psNext; featureUpdate(psCFeat); } objmemUpdate(); // Do completely useless stuff. if (!isInSync()) { sendCheck(); // send some pointless checking info if we're doomed anyway } // Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update. gameTimeUpdateEnd(); }
// //////////////////////////////////////////////////////////////////////// // Send structure information. static BOOL sendStructureCheck(void) { uint8_t player; if (structureCheckLastSent > gameTime) { structureCheckLastSent = 0; } // Only send a struct send if not done recently if (gameTime - structureCheckLastSent < STRUCT_PERIOD) { return true; } structureCheckLastSent = gameTime; for (player = 0; player < MAX_PLAYERS; ++player) { STRUCTURE *pS = pickAStructure(player); bool hasCapacity = true; uint8_t capacity; // Only send info about complete buildings if (pS == NULL || pS->status != SS_BUILT) { structureCheckLastId[player] = 0; continue; } switch (pS->pStructureType->type) { case REF_RESEARCH: capacity = pS->pFunctionality->researchFacility.capacity; break; case REF_FACTORY: case REF_VTOL_FACTORY: capacity = pS->pFunctionality->factory.capacity; break; case REF_POWER_GEN: capacity = pS->pFunctionality->powerGenerator.capacity; default: hasCapacity = false; break; } structureCheckLastId[player] = pS->id; structureCheckLastBody[player] = pS->body; structureCheckLastDirection[player] = pS->rot; structureCheckLastType[player] = pS->pStructureType->type; if (myResponsibility(player)) { if (!isInSync()) // Don't really send anything, unless out of synch. { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_STRUCT); NETuint8_t(&player); NETuint32_t(&gameTime); NETuint32_t(&pS->id); NETuint32_t(&pS->body); NETuint32_t(&pS->pStructureType->type); NETRotation(&pS->rot); if (hasCapacity) { NETuint8_t(&capacity); } NETend(); } } } return true; }
// /////////////////////////////////////////////////////////////////////////// // send a droid info packet. static BOOL sendDroidCheck(void) { DROID *pD, **ppD; uint8_t i, count; static UDWORD lastSent = 0; // Last time a struct was sent. UDWORD toSend = 12; if (lastSent > gameTime) { lastSent= 0; } // Only send a struct send if not done recently if (gameTime - lastSent < DROID_PERIOD) { return true; } lastSent = gameTime; if (!isInSync()) // Don't really send anything, unless out of synch. { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_DROID); } // Allocate space for the list of droids to send ppD = alloca(sizeof(DROID *) * toSend); // Get the list of droids to sent for (i = 0, count = 0; i < toSend; i++) { pD = pickADroid(); if (pD == NULL || (pD->gameCheckDroid != NULL && ((PACKAGED_CHECK *)pD->gameCheckDroid)->gameTime > gameTime)) { continue; // Didn't find a droid, or droid was synched recently. } // If the droid is ours add it to the list if (myResponsibility(pD->player)) { ppD[count++] = pD; } free(pD->gameCheckDroid); pD->gameCheckDroid = (PACKAGED_CHECK *)malloc(sizeof(PACKAGED_CHECK)); *(PACKAGED_CHECK *)pD->gameCheckDroid = packageCheck(pD); } if (!isInSync()) // Don't really send anything, unless out of synch. { // Send the number of droids to expect NETuint8_t(&count); NETuint32_t(&gameTime); // Send game time. // Add the droids to the packet for (i = 0; i < count; i++) { NETPACKAGED_CHECK((PACKAGED_CHECK *)ppD[i]->gameCheckDroid); } } if (!isInSync()) // Don't really send anything, unless out of synch. { return NETend(); } return true; }