void process_action_flags( short player_identifier, const uint32 *action_flags, short count) { if (replay.game_is_being_recorded) { record_action_flags(player_identifier, action_flags, count); } GetRealActionQueues()->enqueueActionFlags(player_identifier, action_flags, count); }
/********************************************************************************************* * * Function: pull_flags_from_recording * Purpose: remove one flag from each queue from the recording buffer. * Returns: true if it pulled the flags, false if it didn't * *********************************************************************************************/ static bool pull_flags_from_recording( short count) { short player_index; bool success= true; // first check that we can pull something from each playerÕs queue // (at the beginning of the game, we wonÕt be able to) // i'm not sure that i really need to do this check. oh well. for (player_index = 0; success && player_index<dynamic_world->player_count; player_index++) { if(get_recording_queue_size(player_index)==0) success= false; } if(success) { for (player_index = 0; player_index < dynamic_world->player_count; player_index++) { short index; ActionQueue *queue; queue= get_player_recording_queue(player_index); for (index= 0; index<count; index++) { if (queue->read_index != queue->write_index) { #ifdef DEBUG_REPLAY debug_stream_of_flags(*(queue->buffer+queue->read_index), player_index); #endif GetRealActionQueues()->enqueueActionFlags(player_index, queue->buffer + queue->read_index, 1); INCREMENT_QUEUE_COUNTER(queue->read_index); } else { dprintf("Dropping flag?"); } } } } return success; }
std::pair<bool, int16> update_world() { short theElapsedTime = 0; bool canUpdate = true; int theUpdateResult = kUpdateNormalCompletion; #ifndef DISABLE_NETWORKING if (game_is_networked) NetProcessMessagesInGame(); #endif while(canUpdate) { // If we have flags in the GameQueue, or can put a tick's-worth there, we're ok. // Note that GameQueue should be stocked evenly (i.e. every player has the same # of flags) if(GameQueue->countActionFlags(0) == 0) { canUpdate = overlay_queue_with_queue_into_queue(GetRealActionQueues(), GetLuaActionQueues(), GameQueue); } if(!sPredictionWanted) { // See if the speed-limiter (net time or heartbeat count) will let us advance a tick #if !defined(DISABLE_NETWORKING) int theMostRecentAllowedTick = game_is_networked ? NetGetNetTime() : get_heartbeat_count(); #else int theMostRecentAllowedTick = get_heartbeat_count(); #endif if(dynamic_world->tick_count >= theMostRecentAllowedTick) { canUpdate = false; } } // If we can't update, we can't update. We're done for now. if(!canUpdate) { break; } // Transition from predictive -> real update mode, if necessary. exit_predictive_mode(); // Capture the flags for each player for use in prediction for(short i = 0; i < dynamic_world->player_count; i++) sMostRecentFlagsForPlayer[i] = GameQueue->peekActionFlags(i, 0); theUpdateResult = update_world_elements_one_tick(); theElapsedTime++; L_Call_PostIdle(); if(theUpdateResult != kUpdateNormalCompletion || Movie::instance()->IsRecording()) { canUpdate = false; } } // This and the following voodoo comes, effectively, from Bungie's code. if(theUpdateResult == kUpdateChangeLevel) { theElapsedTime = 0; } /* Game is over. */ if(theUpdateResult == kUpdateGameOver) { game_timed_out(); theElapsedTime = 0; } else if (theElapsedTime) { update_interface(theElapsedTime); update_fades(); } check_recording_replaying(); // ZZZ: Prediction! bool didPredict = false; if(theUpdateResult == kUpdateNormalCompletion && sPredictionWanted) { NetUpdateUnconfirmedActionFlags(); // We use "2" to make sure there's always room for our one set of elements. // (thePredictiveQueues should always hold only 0 or 1 element for each player.) ActionQueues thePredictiveQueues(dynamic_world->player_count, 2, true); // Observe, since we don't use a speed-limiter in predictive mode, that there cannot be flags // stranded in the GameQueue. Unfortunately this approach will mispredict if a script is // controlling the local player. We could be smarter about it if that eventually becomes an issue. for ( ; sPredictedTicks < NetGetUnconfirmedActionFlagsCount(); sPredictedTicks++) { // Real -> predictive transition, if necessary enter_predictive_mode(); // Enqueue stuff into thePredictiveQueues for(short thePlayerIndex = 0; thePlayerIndex < dynamic_world->player_count; thePlayerIndex++) { uint32 theFlags = (thePlayerIndex == local_player_index) ? NetGetUnconfirmedActionFlag(sPredictedTicks) : sMostRecentFlagsForPlayer[thePlayerIndex]; thePredictiveQueues.enqueueActionFlags(thePlayerIndex, &theFlags, 1); } // update_players() will dequeue the elements we just put in there update_players(&thePredictiveQueues, true); didPredict = true; } // loop while local player has flags we haven't used for prediction } // if we should predict // we return separately 1. "whether to redraw" and 2. "how many game-ticks elapsed" return std::pair<bool, int16>(didPredict || theElapsedTime != 0, theElapsedTime); }
int32 availableCapacity() const { return GetRealActionQueues()->availableCapacity(mPlayerIndex); }
void reset(int32 inTick) { mWriteTick = inTick; GetRealActionQueues()->resetQueue(mPlayerIndex); }