diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/net_prediction.cpp | |
| download | openparsec-main.tar.xz openparsec-main.zip | |
Diffstat (limited to 'src/parsec/net_prediction.cpp')
| -rw-r--r-- | src/parsec/net_prediction.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/parsec/net_prediction.cpp b/src/parsec/net_prediction.cpp new file mode 100644 index 0000000..bec7e4e --- /dev/null +++ b/src/parsec/net_prediction.cpp @@ -0,0 +1,194 @@ +/* + * PARSEC - + * + * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:30 $ + * + * Orginally written by: + * Copyright (c) Clemens Beer <cbx@parsec.org> 2002-2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include <stdio.h> +#include <string.h> + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "net_defs.h" + +// utility modules +#include "utl_list.h" + +// local module header +#include "net_prediction.h" + +// proprietary module headers +#include "con_aux.h" +#include "e_record.h" +#include "g_extra.h" +#include "h_supp.h" +#include "net_game.h" +#include "net_stream.h" +#include "g_sfx.h" + + +// special implementation for a extra collect prediction event ---------------- +// +G_PredEventExtraCollect::G_PredEventExtraCollect( ExtraObject* pExtra ) : + m_pExtra( pExtra ) +{ + ASSERT( pExtra != NULL ); +} + +// do the extra collection ---------------------------------------------------- +// +void G_PredEventExtraCollect::Do() +{ + char* pszMessage = TheGameExtraManager->CollectExtra( MyShip, m_pExtra ); + + // show message saying what type of extra has been collected + if ( m_nDoCount == 0 ) { + if ( pszMessage != NULL ) { +//#ifdef PARSEC_DEBUG +// WriteExtraCollectMessage( "G_PredEventExtraCollect::Do()" ); +//#else // !PARSEC_DEBUG + WriteExtraCollectMessage( pszMessage ); +//#endif // !PARSEC_DEBUG + } else { + MSGOUT( "CheckShipExtraCollision(): invalid extra type: %0x.", m_pExtra->ObjectType ); + } + } + +#ifdef PARSEC_DEBUG + MSGOUT( "G_PredEventExtraCollect::Do()" ); +#endif // PARSEC_DEBUG + NET_PredEvent::Do(); +} + + +//NOTE: stores information about events that were predicted in the game-engine +// whenever the game-engine modifies the local world, we save a prediction +// that includes a checkpoint ( = next outgoing message id ) +// whenever we receive a packet, we clear all predictions inserted before +// the ACK checkpoint and we re-apply all pending predictions not yet +// ACK ( checkpoint # is synonym for message id ) + +// standard ctor -------------------------------------------------------------- +// +NET_PredictionManager::NET_PredictionManager( NET_Stream* pStream ) +{ + ASSERT( pStream != NULL ); + + m_predictions = new UTL_List<NET_PredEvent*>; + m_pStream = pStream; +} + + +// standard dtor -------------------------------------------------------------- +// +NET_PredictionManager::~NET_PredictionManager() +{ + Reset(); + delete m_predictions; +} + + +// reset ---------------------------------------------------------------------- +// +void NET_PredictionManager::Reset() +{ + // remove all predictions + for( LE_PredEvt* entry = m_predictions->GetHead(); entry != NULL; entry = entry->m_pNext ) { + delete entry->m_data; + } + m_predictions->Clear(); +} + + +// clear all predictions up to the message# and reapply all predictions after the message# +// +void NET_PredictionManager::DoCheckpoint( dword MessageId ) +{ + for( LE_PredEvt* pEntry = m_predictions->GetHead(); pEntry != NULL; ) { + LE_PredEvt* pNext = pEntry->m_pNext; + NET_PredEvent* pPred = pEntry->m_data; + if ( pPred->GetMessageId() <= MessageId ) { +#ifdef PARSEC_DEBUG + MSGOUT( "NET_PredictionManager::DoCheckpoint(): removing ACK prediction ( pred-msgid %d <= msgid %d)", pPred->GetMessageId(), MessageId ); +#endif // PARSEC_DEBUG + delete m_predictions->RemoveEntry( pEntry ); + } else { +#ifdef PARSEC_DEBUG + int nDoCountBefore = pPred->GetDoCount(); + MSGOUT( "NET_PredictionManager::DoCheckpoint(): reapplying prediction ( pred-msgid %d > msgid %d)", pPred->GetMessageId(), MessageId ); +#endif // PARSEC_DEBUG + + pPred->Do(); + +#ifdef PARSEC_DEBUG + ASSERT( pPred->GetDoCount() == ( nDoCountBefore + 1 ) ); +#endif // PARSEC_DEBUG + } + pEntry = pNext; + } +} + + +// add a predictionevent ------------------------------------------------------ +// ensures that MAX_NUM_PREDICTIONS is not exceeded +void NET_PredictionManager::_AddPrediction( NET_PredEvent* pEvent ) +{ + // check for prediction choke ( server does not send ACKs for checkpoints fast enough ) + if ( m_predictions->GetNumEntries() >= MAX_NUM_PREDICTIONS ) { + MSGOUT( "NET_PredictionManager::_AddPrediction(): prediction list overflow" ); + return; + } else { + m_predictions->AppendTail( pEvent ); + pEvent->SetMessageId( m_pStream->GetNextOutMessageId() ); +#ifdef PARSEC_DEBUG + int nDoCountBefore = pEvent->GetDoCount(); + + MSGOUT( "NET_PredictionManager::_AddPrediction() at msgid: %d", m_pStream->GetNextOutMessageId() ); + +#endif // PARSEC_DEBUG + + pEvent->Do(); + +#ifdef PARSEC_DEBUG + ASSERT( pEvent->GetDoCount() == ( nDoCountBefore + 1 ) ); +#endif // PARSEC_DEBUG + } +} + + +// add a prediction event for collecting an extra ----------------------------- +// +void NET_PredictionManager::PredictExtraCollect( ExtraObject* pExtra ) +{ + ASSERT( pExtra != NULL ); + _AddPrediction( new G_PredEventExtraCollect( pExtra ) ); +} + |
