int vsnprintf(char* inBuffer, size_t inBufferSize, const char* inFormat, va_list inArgs) { int theResult = vsprintf(inBuffer, inFormat, inArgs); // In case logging vsnprintf's a long string, don't warn while warning. static bool issuingWarning = false; if(theResult + 1 > inBufferSize && !issuingWarning) { issuingWarning = true; logWarning2("vsnprintf emulation wrote too many bytes (%d/%d)", theResult + 1, inBufferSize); issuingWarning = false; } return theResult; }
// ZZZ: if in predictive mode, restore the saved partial game-state (it'd better take us back // to _exactly_ the same full game-state we saved earlier, else problems.) static void exit_predictive_mode() { if(sPredictedTicks > 0) { for(short i = 0; i < dynamic_world->player_count; i++) { player_data* player = get_player_data(i); assert(player->monster_index == sSavedPlayerData[i].monster_index); { // We *don't* restore this tiny part of the game-state back because // otherwise the player can't use [] to scroll the inventory panel. // [] scrolling happens outside the normal input/update system, so that's // enough to persuade me that not restoring this won't OOS any more often // than []-scrolling did before prediction. :) int16 saved_interface_flags = player->interface_flags; int16 saved_interface_decay = player->interface_decay; *player = sSavedPlayerData[i]; player->interface_flags = saved_interface_flags; player->interface_decay = saved_interface_decay; } if(sSavedPlayerData[i].monster_index != NONE) { assert(get_monster_data(sSavedPlayerData[i].monster_index)->object_index == sSavedPlayerMonsterData[i].object_index); *get_monster_data(sSavedPlayerData[i].monster_index) = sSavedPlayerMonsterData[i]; if(sSavedPlayerMonsterData[i].object_index != NONE) { assert(get_object_data(sSavedPlayerMonsterData[i].object_index)->parasitic_object == sSavedPlayerObjectData[i].parasitic_object); remove_object_from_polygon_object_list(sSavedPlayerMonsterData[i].object_index); *get_object_data(sSavedPlayerMonsterData[i].object_index) = sSavedPlayerObjectData[i]; // We have to defer this insertion since the object lists could still have other players // in their predictive locations etc. - we need to reconstruct everything exactly as it // was when we entered predictive mode. deferred_add_object_to_polygon_object_list(sSavedPlayerMonsterData[i].object_index, sSavedPlayerObjectNextObject[i]); if(sSavedPlayerObjectData[i].parasitic_object != NONE) *get_object_data(sSavedPlayerObjectData[i].parasitic_object) = sSavedPlayerParasiticObjectData[i]; } } } perform_deferred_polygon_object_list_manipulations(); sPredictedTicks = 0; // Sanity checking if(sSavedTickCount != dynamic_world->tick_count) logWarning2("saved tick count %d != dynamic_world->tick_count %d", sSavedTickCount, dynamic_world->tick_count); if(sSavedRandomSeed != get_random_seed()) logWarning2("saved random seed %d != get_random_seed() %d", sSavedRandomSeed, get_random_seed()); } }