/* =========================================================================== 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 . 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 __SNAP_PROCESSOR_H__ #define __SNAP_PROCESSOR_H__ /* ================================================ idSnapshotProcessor ================================================ */ class idSnapshotProcessor { public: static const int INITIAL_SNAP_SEQUENCE = 42; idSnapshotProcessor(); ~idSnapshotProcessor(); void Reset( bool cstor = false ); // TrySetPendingSnapshot Sets the currently pending snap. // No new snaps will be sent until this snap has been fully sent. // Returns true of the newly supplied snapshot was accepted (there were no pending snaps) bool TrySetPendingSnapshot( idSnapShot& ss ); // Peek into delta to get deltaSequence, and deltaBaseSequence void PeekDeltaSequence( const char* deltaMem, int deltaSize, int& deltaSequence, int& deltaBaseSequence ); // Apply a delta to the supplied snapshot bool ApplyDeltaToSnapshot( idSnapShot& snap, const char* deltaMem, int deltaSize, int visIndex ); // Attempts to write the currently pending snap to the supplied buffer, which can then be sent as an unreliable msg. // SubmitPendingSnap will submit the pending snap to a job, so that it can be retrieved later for sending. void SubmitPendingSnap( int visIndex, uint8* objMemory, int objMemorySize, lzwCompressionData_t* lzwData ); // GetPendingSnapDelta int GetPendingSnapDelta( byte* outBuffer, int maxLength ); // If PendingSnapReadyToSend is true, then GetPendingSnapDelta will return something to send bool PendingSnapReadyToSend() const { return jobMemory->lzwInOutData.numlzwDeltas > 0; } // When you call WritePendingSnapshot, and then send the resulting buffer as a unreliable msg, you will eventually // receive this on the client. Call this function to receive and apply it to the base state, and possibly return a fully received snap // to then apply to the client game state bool ReceiveSnapshotDelta( const byte* deltaData, int deltaLength, int visIndex, int& outSeq, int& outBaseSeq, idSnapShot& outSnap, bool& fullSnap ); // Function to apply a received (or ack'd) delta to the base state bool ApplySnapshotDelta( int visIndex, int snapshotNumber ); // Remove deltas for basestate we no longer have. // We know we can remove them, because we will never be able to apply them, since // the basestate needed to generate a full snap from these deltas is gone. void RemoveDeltasForOldBaseSequence(); // Make sure delta sequence and basesequence values are valid, and in order, etc void SanityCheckDeltas(); // HasPendingSnap will return true if there is more of the last TrySetPendingSnapshot to be sent bool HasPendingSnap() const { return hasPendingSnap; } idSnapShot* GetBaseState() { return &baseState; } idSnapShot* GetPendingSnap() { return &pendingSnap; } int GetSnapSequence() { return snapSequence; } int GetBaseSequence() { return baseSequence; } int GetFullSnapBaseSequence() { return lastFullSnapBaseSequence; } // This is used to ack the latest delta we have. If we have no deltas, we sent -1 to make sure // Server knows we don't want to ack, since we are as up to date as we can be int GetLastAppendedSequence() { return deltas.Num() == 0 ? -1 : deltas.ItemSequence( deltas.Num() - 1 ); } int GetSnapQueueSize() { return deltas.Num(); } bool IsBusyConfirmingPartialSnap(); void AddSnapObjTemplate( int objID, idBitMsg& msg ); static const int MAX_SNAPSHOT_QUEUE = 64; private: // Internal commands to set up, and flush the compressors static const int MAX_SNAP_SIZE = idPacketProcessor::MAX_MSG_SIZE; static const int MAX_SNAPSHOT_QUEUE_MEM = 64 * 1024; // 64k // sequence number of the last snapshot we sent/received // on the server, the sequencing is different for each network peer (net_verboseSnapshot 1) // on the jobbed snapshot compression path, the sequence is incremented in NewLZWStream and pulled into this in idSnapshotProcessor::GetPendingSnapDelta int snapSequence; int baseSequence; int lastFullSnapBaseSequence; // Latest base sequence number that is a full snap idSnapShot baseState; // known snapshot base on the client idDataQueue< MAX_SNAPSHOT_QUEUE, MAX_SNAPSHOT_QUEUE_MEM > deltas; // list of unacknowledged snapshot deltas idSnapShot pendingSnap; // Current snap waiting to be fully sent bool hasPendingSnap; // true if pendingSnap is still waiting to be sent struct jobMemory_t { static const int MAX_LZW_DELTAS = 1; // FIXME: cleanup the old multiple delta support completely // @TODO this is a hack fix to allow online to load into coop (where there are lots of entities). // The real solution should be coming soon. // Doom MP: we encountered the same problem, going from 1024 to 4096 as well until a better solution is in place // (initial, useless, exchange of func_statics is killing us) static const int MAX_OBJ_PARMS = 4096; static const int MAX_LZW_PARMS = 32; static const int MAX_OBJ_HEADERS = 256; static const int MAX_LZW_MEM = 1024 * 8; // 8k in the byte * lzwMem buffers, must be <= PS3_DMA_MAX // Parm memory to jobs idArray objParms; idArray headers; idArray lzwParms; // Output memory from jobs idArray lzwDeltas; // Info about each pending delta output from jobs idArray lzwMem; // Memory for output from lzw jobs lzwInOutData_t lzwInOutData; // In/Out data used so lzw data can persist across lzw jobs }; jobMemory_t* jobMemory; idSnapShot submittedState; idSnapShot templateStates; // holds default snapshot states for some newly spawned object idSnapShot submittedTemplateStates; int partialBaseSequence; }; #endif /* !__SNAP_PROCESSOR_H__ */