const char* version_getFormattedVersionString() { static char versionString[MAX_STR_LENGTH] = {'\0'}; if (versionString[0] == '\0') { // Compose the working copy state string #if (SVN_WC_MODIFIED && SVN_WC_SWITCHED) const char* wc_state = _(" (modified and switched locally)"); #elif (SVN_WC_MODIFIED) const char* wc_state = _(" (modified locally)"); #elif (SVN_WC_SWITCHED) const char* wc_state = _(" (switched locally)"); #else const char* wc_state = ""; #endif // Compose the build type string #ifdef DEBUG const char* build_type = _(" - DEBUG"); #else const char* build_type = ""; #endif const char* build_date = NULL; if (strncmp(svn_uri_cstr, "tags/", strlen("tags/")) != 0) { sasprintf((char**)&build_date, _(" - Built %s"), version_getBuildDate()); } else { build_date = ""; } // Construct the version string // TRANSLATORS: This string looks as follows when expanded. // "Version <version name/number> <working copy state><BUILD DATE><BUILD TYPE>" snprintf(versionString, MAX_STR_LENGTH, _("Version %s%s%s%s"), version_getVersionString(), wc_state, build_date, build_type); } return versionString; }
static void gameStateUpdate() { syncDebug("map = \"%s\", pseudorandom 32-bit integer = 0x%08X, allocated = %d %d %d %d %d %d %d %d %d %d, position = %d %d %d %d %d %d %d %d %d %d", game.map, gameRandU32(), NetPlay.players[0].allocated, NetPlay.players[1].allocated, NetPlay.players[2].allocated, NetPlay.players[3].allocated, NetPlay.players[4].allocated, NetPlay.players[5].allocated, NetPlay.players[6].allocated, NetPlay.players[7].allocated, NetPlay.players[8].allocated, NetPlay.players[9].allocated, NetPlay.players[0].position, NetPlay.players[1].position, NetPlay.players[2].position, NetPlay.players[3].position, NetPlay.players[4].position, NetPlay.players[5].position, NetPlay.players[6].position, NetPlay.players[7].position, NetPlay.players[8].position, NetPlay.players[9].position ); for (unsigned n = 0; n < MAX_PLAYERS; ++n) { syncDebug("Player %d = \"%s\"", n, NetPlay.players[n].name); } // Add version string to desynch logs. Different version strings will not trigger a desynch dump per se, due to the syncDebug{Get, Set}Crc guard. auto crc = syncDebugGetCrc(); syncDebug("My client version = %s", version_getVersionString()); syncDebugSetCrc(crc); // Actually send pending droid orders. sendQueuedDroidInfo(); sendPlayerGameTime(); NETflush(); // Make sure the game time tick message is really sent over the network. if (!paused && !scriptPaused()) { /* 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 command droids cmdDroidUpdate(); 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); DROID *psNext; for (DROID *psCurr = apsDroidLists[i]; psCurr != nullptr; 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); } for (DROID *psCurr = mission.apsDroidLists[i]; psCurr != nullptr; 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); } // FIXME: These for-loops are code duplicationo STRUCTURE *psNBuilding; for (STRUCTURE *psCBuilding = apsStructLists[i]; psCBuilding != nullptr; 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); } for (STRUCTURE *psCBuilding = mission.apsStructLists[i]; psCBuilding != nullptr; 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 } } missionTimerUpdate(); proj_UpdateAll(); FEATURE *psNFeat; for (FEATURE *psCFeat = apsFeatureLists[0]; psCFeat; psCFeat = psNFeat) { psNFeat = psCFeat->psNext; featureUpdate(psCFeat); } // Clean up dead droid pointers in UI. hciUpdate(); // Free dead droid memory. objmemUpdate(); // 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(); // Must be at the beginning or end of each tick, since countUpdate is also called randomly (unsynchronised) between ticks. countUpdate(true); static int i = 0; if (i++ % 10 == 0) // trigger every second { jsDebugUpdate(); } }