Matei
207d1367ec
- The server will no longer send a new turn until the previous one has been "acknowledged". (TODO: this may create lag between turns in its current form; investigate and possibly allow executing two turns while the third is being negotiated). - Mutexes are now being used in NetServer and NetClient to ensure commands go into the right batches. - Commented out some orders in the GUI code that should not be there and are not 100% working anyway (they were part of the follow/formation system). - Units that spawn or are created by scripts now have net-safe position and orientation. - Added a debug flag that can be turned on to print details about when commands are received and executed (DEBUG_SYNCHRONIZATION). This is especially useful if you diff the stdouts of two running games. There should be no differences if everything is in synch. This was SVN commit r5463.
129 lines
3.4 KiB
C++
129 lines
3.4 KiB
C++
#ifndef INCLUDED_TURNMANAGER
|
|
#define INCLUDED_TURNMANAGER
|
|
|
|
//#include "Network/NetMessage.h"
|
|
//#include "Network/Network.h"
|
|
#include <vector>
|
|
|
|
class CGameRecord;
|
|
class CNetMessage;
|
|
class IMessagePipeEnd;
|
|
|
|
class CTurnManager
|
|
{
|
|
public:
|
|
// Default turn length
|
|
static const uint DEFAULT_TURN_LENGTH = 150;
|
|
|
|
// Used with IterateBatch() to iterate a command batch and set the sync mask
|
|
// for each message. If the iterating function doesn't wish to change the
|
|
// mask, it should return oldMask unchanged.
|
|
typedef uint (BatchIteratorFunc)(CNetMessage *pMsg, uint oldMask, void *userdata);
|
|
|
|
// FIXME Should be in CNetServer instead
|
|
struct SClientTimingData
|
|
{
|
|
// The maximum latency observed from this client
|
|
uint m_MaxLatency;
|
|
// Approximate current round-trip time in milliseconds
|
|
uint m_Latency;
|
|
// Frames per Second - won't be used unless 1000/m_FPS > m_Latency (i.e.
|
|
// framerate is too slow to handle [m_Latency] as the turn length)
|
|
uint m_FPS;
|
|
};
|
|
|
|
private:
|
|
struct SMessageSyncEntry
|
|
{
|
|
// A bitmask telling which clients to sync this message to
|
|
uint m_ClientMask;
|
|
// The message pointer
|
|
CNetMessage *m_pMessage;
|
|
|
|
inline SMessageSyncEntry(CNetMessage *pMsg):
|
|
m_ClientMask(0),
|
|
m_pMessage(pMsg)
|
|
{}
|
|
};
|
|
|
|
struct SBatch
|
|
{
|
|
std::vector <SMessageSyncEntry> m_Messages;
|
|
uint m_TurnLength;
|
|
|
|
void Swap(SBatch &other);
|
|
};
|
|
|
|
struct SClient
|
|
{
|
|
// FIXME Move to CNetServer
|
|
SClientTimingData m_TimingData;
|
|
IMessagePipeEnd *m_Pipe;
|
|
};
|
|
|
|
std::vector <SClient> m_Clients;
|
|
SBatch m_Batches[3];
|
|
|
|
CGameRecord *m_pRecord;
|
|
|
|
protected:
|
|
// Rotate the three batches: {0, 1, 2} => {1, 2, 0}
|
|
void RotateBatches();
|
|
|
|
// Go through each message in the specified batch and send the message to
|
|
// each of the clients whose bit in the message's mask is set
|
|
void SendBatch(uint batch);
|
|
void ClearBatch(uint batch);
|
|
|
|
void SetClientPipe(uint client, IMessagePipeEnd *pipe);
|
|
// FIXME Should be in CNetServer instead [and implemented]
|
|
// void UpdateTimingData(uint client, uint fps, uint currentLatency);
|
|
void SetTurnLength(uint batch, uint turnLength);
|
|
|
|
void SendMessage(CNetMessage *pMsg, uint clientMask);
|
|
|
|
// Add the message to the specified batch. The message is assumed to be
|
|
// validated before passed here, and will be blindly trusted.
|
|
void QueueMessage(uint batch, CNetMessage *pMsg);
|
|
|
|
// Send the specified batch to CGameRecord for recording
|
|
void RecordBatch(uint batch);
|
|
static BatchIteratorFunc RecordIterator;
|
|
|
|
public:
|
|
CTurnManager();
|
|
virtual ~CTurnManager() { }
|
|
|
|
void Initialize(size_t numClients);
|
|
|
|
// Return the millisecond delay between the last frame and the next.
|
|
// CSimulation will use this to determine when to perform the deterministic
|
|
// update and call NewTurn()
|
|
uint GetTurnLength();
|
|
|
|
// Called by CSimulation when the current turn time has passed.
|
|
virtual void NewTurn()=0;
|
|
|
|
// Used by CSimulation to ask whether it can call NewTurn.
|
|
virtual bool NewTurnReady() { return true; }
|
|
|
|
// Apply a function to all messages in a given batch.
|
|
void IterateBatch(uint batch, BatchIteratorFunc *func, void *userdata);
|
|
|
|
// Queue a command originating from the local player.
|
|
virtual void QueueLocalCommand(CNetMessage *pMsg)=0;
|
|
};
|
|
|
|
class CSinglePlayerTurnManager: public CTurnManager
|
|
{
|
|
public:
|
|
CSinglePlayerTurnManager();
|
|
|
|
virtual void NewTurn();
|
|
virtual void QueueLocalCommand(CNetMessage *pMsg);
|
|
};
|
|
|
|
extern CSinglePlayerTurnManager *g_SinglePlayerTurnManager;
|
|
|
|
#endif
|