mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-13 05:50:51 +00:00
249 lines
8.8 KiB
C++
249 lines
8.8 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
#ifndef __SNAPSHOT_H__
|
|
#define __SNAPSHOT_H__
|
|
|
|
#include "Snapshot_Jobs.h"
|
|
|
|
extern idCVar net_verboseSnapshot;
|
|
#define NET_VERBOSESNAPSHOT_PRINT if ( net_verboseSnapshot.GetInteger() > 0 ) idLib::Printf
|
|
#define NET_VERBOSESNAPSHOT_PRINT_LEVEL( X, Y ) if ( net_verboseSnapshot.GetInteger() >= ( X ) ) idLib::Printf( "%s", Y )
|
|
|
|
/*
|
|
A snapshot contains a list of objects and their states
|
|
*/
|
|
class idSnapShot
|
|
{
|
|
public:
|
|
idSnapShot();
|
|
idSnapShot( const idSnapShot& other );
|
|
~idSnapShot();
|
|
|
|
void operator=( const idSnapShot& other );
|
|
|
|
// clears the snapshot
|
|
void Clear();
|
|
|
|
int GetTime() const
|
|
{
|
|
return time;
|
|
}
|
|
void SetTime( int t )
|
|
{
|
|
time = t;
|
|
}
|
|
|
|
int GetRecvTime() const
|
|
{
|
|
return recvTime;
|
|
}
|
|
void SetRecvTime( int t )
|
|
{
|
|
recvTime = t;
|
|
}
|
|
|
|
// Loads only sequence and baseSequence values from the compressed stream
|
|
static void PeekDeltaSequence( const char* deltaMem, int deltaSize, int& sequence, int& baseSequence );
|
|
|
|
// Reads a new object state packet, which is assumed to be delta compressed against this snapshot
|
|
bool ReadDeltaForJob( const char* deltaMem, int deltaSize, int visIndex, idSnapShot* templateStates );
|
|
bool ReadDelta( idFile* file, int visIndex );
|
|
|
|
// Writes an object state packet which is delta compressed against the old snapshot
|
|
struct objectBuffer_t
|
|
{
|
|
objectBuffer_t() : data( NULL ), size( 0 ) { }
|
|
objectBuffer_t( int s ) : data( NULL ), size( s )
|
|
{
|
|
Alloc( s );
|
|
}
|
|
objectBuffer_t( const objectBuffer_t& o ) : data( NULL ), size( 0 )
|
|
{
|
|
*this = o;
|
|
}
|
|
~objectBuffer_t()
|
|
{
|
|
_Release();
|
|
}
|
|
void Alloc( int size );
|
|
int NumRefs()
|
|
{
|
|
return data == NULL ? 0 : data[size];
|
|
}
|
|
objectSize_t Size() const
|
|
{
|
|
return size;
|
|
}
|
|
byte* Ptr()
|
|
{
|
|
return data == NULL ? NULL : data ;
|
|
}
|
|
byte& operator[]( int i )
|
|
{
|
|
return data[i];
|
|
}
|
|
void operator=( const objectBuffer_t& other );
|
|
|
|
// (not making private because of idSnapshot)
|
|
void _AddRef();
|
|
void _Release();
|
|
private:
|
|
byte* data;
|
|
objectSize_t size;
|
|
};
|
|
|
|
struct objectState_t
|
|
{
|
|
objectState_t() :
|
|
objectNum( 0 ),
|
|
visMask( MAX_UNSIGNED_TYPE( uint32 ) ),
|
|
stale( false ),
|
|
deleted( false ),
|
|
changedCount( 0 ),
|
|
expectedSequence( 0 ),
|
|
createdFromTemplate( false )
|
|
{ }
|
|
void Print( const char* name );
|
|
|
|
uint16 objectNum;
|
|
objectBuffer_t buffer;
|
|
uint32 visMask;
|
|
bool stale; // easy way for clients to check if ss obj is stale. Probably temp till client side of vismask system is more fleshed out
|
|
bool deleted;
|
|
int changedCount; // Incremented each time the state changed
|
|
int expectedSequence;
|
|
bool createdFromTemplate;
|
|
};
|
|
|
|
struct submitDeltaJobsInfo_t
|
|
{
|
|
objParms_t* objParms; // Start of object parms
|
|
int maxObjParms; // Max parms (which will dictate how many objects can be processed)
|
|
uint8* objMemory; // Memory that objects were written out to
|
|
objHeader_t* headers; // Memory for headers
|
|
int maxHeaders;
|
|
int maxObjMemory; // Max memory (which will dictate when syncs need to occur)
|
|
lzwParm_t* lzwParms; // Start of lzw parms
|
|
int maxDeltaParms; // Max lzw parms (which will dictate how many syncs we can have)
|
|
|
|
idSnapShot* oldSnap; // snap we are comparing this snap to (to produce a delta)
|
|
int visIndex;
|
|
int baseSequence;
|
|
|
|
idSnapShot* templateStates; // states for new snapObj that arent in old states
|
|
|
|
lzwInOutData_t* lzwInOutData;
|
|
};
|
|
|
|
void SubmitWriteDeltaToJobs( const submitDeltaJobsInfo_t& submitDeltaJobInfo );
|
|
|
|
bool WriteDelta( idSnapShot& old, int visIndex, idFile* file, int maxLength, int optimalLength = 0 );
|
|
|
|
// Adds an object to the state, overwrites any existing object with the same number
|
|
objectState_t* S_AddObject( int objectNum, uint32 visMask, const idBitMsg& msg, const char* tag = NULL )
|
|
{
|
|
return S_AddObject( objectNum, visMask, msg.GetReadData(), msg.GetSize(), tag );
|
|
}
|
|
objectState_t* S_AddObject( int objectNum, uint32 visMask, const byte* buffer, int size, const char* tag = NULL )
|
|
{
|
|
return S_AddObject( objectNum, visMask, ( const char* )buffer, size, tag );
|
|
}
|
|
objectState_t* S_AddObject( int objectNum, uint32 visMask, const char* buffer, int size, const char* tag = NULL );
|
|
bool CopyObject( const idSnapShot& oldss, int objectNum, bool forceStale = false );
|
|
int CompareObject( const idSnapShot* oldss, int objectNum, int start = 0, int end = 0, int oldStart = 0 );
|
|
|
|
// returns the number of objects in this snapshot
|
|
int NumObjects() const
|
|
{
|
|
return objectStates.Num();
|
|
}
|
|
|
|
// Returns the object number of the specified object, also fills the bitmsg
|
|
int GetObjectMsgByIndex( int i, idBitMsg& msg, bool ignoreIfStale = false ) const;
|
|
|
|
// returns true if the object was found in the snapshot
|
|
bool GetObjectMsgByID( int objectNum, idBitMsg& msg, bool ignoreIfStale = false )
|
|
{
|
|
return GetObjectMsgByIndex( FindObjectIndexByID( objectNum ), msg, ignoreIfStale ) == objectNum;
|
|
}
|
|
|
|
// returns the object index or -1 if it's not found
|
|
int FindObjectIndexByID( int objectNum ) const;
|
|
|
|
// returns the object by id, or NULL if not found
|
|
objectState_t* FindObjectByID( int objectNum ) const;
|
|
|
|
// Returns whether or not an object is stale
|
|
bool ObjectIsStaleByIndex( int i ) const;
|
|
|
|
int ObjectChangedCountByIndex( int i ) const;
|
|
|
|
// clears the empty states from the snapshot snapshot
|
|
void CleanupEmptyStates();
|
|
|
|
void PrintReport();
|
|
|
|
void UpdateExpectedSeq( int newSeq );
|
|
|
|
void ApplyToExistingState( int objId, idBitMsg& msg );
|
|
objectState_t* GetTemplateState( int objNum, idSnapShot* templateStates, objectState_t* newState = NULL );
|
|
|
|
void RemoveObject( int objId );
|
|
|
|
private:
|
|
|
|
idList< objectState_t*, TAG_IDLIB_LIST_SNAPSHOT> objectStates;
|
|
idBlockAlloc< objectState_t, 16, TAG_NETWORKING > allocatedObjs;
|
|
|
|
int time;
|
|
int recvTime;
|
|
|
|
int BinarySearch( int objectNum ) const;
|
|
objectState_t& FindOrCreateObjectByID( int objectNum ); // objIndex is optional parm for returning the index of the obj
|
|
|
|
void SubmitObjectJob( const submitDeltaJobsInfo_t& submitDeltaJobsInfo, // Struct containing parameters originally passed in to SubmitWriteDeltaToJobs
|
|
objectState_t* newState, // New obj state (can be NULL, which means deleted)
|
|
objectState_t* oldState, // Old obj state (can be NULL, which means new)
|
|
objParms_t*& baseObjParm, // Starting obj parm of current stream
|
|
objParms_t*& curObjParm, // Current obj parm of current stream
|
|
objHeader_t*& curHeader, // Current header dest
|
|
uint8*& curObjDest, // Current write pos of current obj
|
|
lzwParm_t*& curlzwParm ); // Current delta parm for next lzw job
|
|
void SubmitLZWJob(
|
|
const submitDeltaJobsInfo_t& writeDeltaInfo, // Struct containing parameters originally passed in to SubmitWriteDeltaToJobs
|
|
objParms_t*& baseObjParm, // Pointer to the first obj parm for the current stream
|
|
objParms_t*& curObjParm, // Current obj parm
|
|
lzwParm_t*& curlzwParm, // Current delta parm
|
|
bool saveDictionary // If true, this is the first of several calls which will be appended
|
|
);
|
|
|
|
void WriteObject( idFile* file, int visIndex, objectState_t* newState, objectState_t* oldState, int& lastobjectNum );
|
|
void FreeObjectState( int index );
|
|
};
|
|
|
|
#endif // __SNAPSHOT_H__
|