openclonk/src/network/C4GameControlNetwork.h

288 lines
8.3 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2009-2016, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
#include "control/C4GameControl.h"
#ifndef INC_C4GameControlNetwork
#define INC_C4GameControlNetwork
#include "control/C4Control.h"
#include "network/C4Network2.h"
#include "network/C4PacketBase.h"
// constants
const int32_t C4ControlBacklog = 100, // (ctrl ticks)
C4ClientIDAll = C4ClientIDUnknown,
C4ControlOverflowLimit = 3, // (ctrl ticks)
C4MaxPreSend = 15; // (frames) - must be smaller than C4ControlBacklog!
const uint32_t C4ControlRequestInterval = 2000; // (ms)
enum C4GameControlNetworkMode
{
CNM_Decentral = 0, // 0 is the standard mode set in config
CNM_Central = 1,
CNM_Async = 2
};
// declarations
class C4GameControlPacket; class C4GameControlClient;
class C4PacketControlReq; class C4ClientList;
// main class
class C4GameControlNetwork // run by network thread
{
public:
C4GameControlNetwork(class C4GameControl *pParent);
~C4GameControlNetwork();
protected:
volatile bool fEnabled, fRunning;
// local status
int32_t iClientID;
bool fHost, fActivated;
C4GameControlNetworkMode eMode;
int32_t iTargetTick;
// options
volatile int32_t iControlPreSend;
// statistics
// time started to wait.
C4TimeMilliseconds tWaitStart;
int32_t iAvgControlSendTime;
int32_t iTargetFPS; // used for PreSend-colculation
// control send / recv status
volatile int32_t iControlSent, iControlReady;
// control list
C4GameControlPacket *pCtrlStack;
CStdCSec CtrlCSec;
// list of clients (activated only!)
C4GameControlClient *pClients;
CStdCSec ClientsCSec;
// holds control that needs to be executed synchronized (main thread only)
C4Control SyncControl;
C4GameControlPacket *pSyncCtrlQueue;
// control request timing
C4TimeMilliseconds tNextControlRequest;
// links
C4GameControl *const pParent;
C4Network2 *pNetwork;
public:
bool IsEnabled() const { return fEnabled; }
bool IsRunning() const { return fRunning; }
bool IsActivated() const { return fActivated; }
int32_t getControlPreSend() const { return iControlPreSend; }
void setControlPreSend(int32_t iToVal) { iControlPreSend = std::min(iToVal, C4MaxPreSend); }
int32_t getAvgControlSendTime() const { return iAvgControlSendTime; }
void setTargetFPS(int32_t iToVal) { iTargetFPS = iToVal; }
// main thread communication
bool Init(int32_t iClientID, bool fHost, int32_t iStartTick, bool fActivated, C4Network2 *pNetwork); // by main thread
void Clear(); // by main thread
void Execute(); // by main thread
bool CtrlReady(int32_t iTick); // by main thread
bool CtrlOverflow(int32_t iTick) const { return fRunning && iControlReady >= iTick + C4ControlOverflowLimit; } // by main thread
int32_t GetBehind(int32_t iTick) const { return iControlReady - iTick + 1; } // by main thread
bool GetControl(C4Control *pCtrl, int32_t iTick); // by main thread
bool ClientReady(int32_t iClientID, int32_t iTick); // by main thread
int32_t ClientPerfStat(int32_t iClientID); // by main thread
int32_t ClientNextControl(int32_t iClientID); // by main thread
bool CtrlNeeded(int32_t iTick) const; // by main thread
void DoInput(const C4Control &Input); // by main thread
void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, enum C4ControlDeliveryType eType); // by main thread
// sync control
C4ControlDeliveryType DecideControlDelivery() const; // by main thread
void ExecSyncControl(); // by main thread
void ExecSyncControl(int32_t iControlTick); // by main thread
// clients
void CopyClientList(const C4ClientList &rClients);
// pausing
void SetRunning(bool fnRunning, int32_t inTargetTick = -1); // by main thread
void SetActivated(bool fnActivated); // by main thread
void SetCtrlMode(C4GameControlNetworkMode enMode); // by main thread
C4GameControlNetworkMode GetCtrlMode() const { return eMode; } // by main thread
// performance
void CalcPerformance(int32_t iCtrlTick); // by main thread
// interfaces
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
void OnResComplete(C4Network2Res *pRes);
protected:
// clients
void AddClient(int32_t iClientID, const char *szName); // by main thread
void RemoveClient(int32_t iClientID); // by main thread
void ClearClients(); // by main thread
// packet handling
void HandleControl(int32_t iByClientID, const C4GameControlPacket &rPkt);
void HandleControlReq(const C4PacketControlReq &rPkt, C4Network2IOConnection *pConn);
void HandleControlPkt(C4PacketType eCtrlType, C4ControlPacket *pPkt, enum C4ControlDeliveryType eType);
// client list
C4GameControlClient *getClient(int32_t iID);
void AddClient(C4GameControlClient *pClient);
void RemoveClient(C4GameControlClient *pClient);
// control stack
C4GameControlPacket *getCtrl(int32_t iClientID, int32_t iCtrlTick); // by both
void AddCtrl(C4GameControlPacket *pCtrl);
void ClearCtrl(int32_t iBeforeTick = -1);
void CheckCompleteCtrl(bool fSetEvent); // by both
C4GameControlPacket *PackCompleteCtrl(int32_t iTick); // by main thread
// sync control
void AddSyncCtrlToQueue(const C4Control &Ctrl, int32_t iTick); // by main thread
void ExecQueuedSyncCtrl(); // by main thread
};
class C4GameControlPacket : public C4PacketBase
{
friend class C4GameControlNetwork;
public:
C4GameControlPacket();
// needed as C4Control doesn't seem to implement correct copying behavior
C4GameControlPacket(const C4GameControlPacket &Pkt2);
C4GameControlPacket &operator = (const C4GameControlPacket &Pkt2);
protected:
// header
int32_t iClientID, iCtrlTick{-1};
C4TimeMilliseconds tTime;
// data
C4Control Ctrl;
// list (C4GameControlNetwork)
C4GameControlPacket *pNext{nullptr};
public:
int32_t getClientID() const { return iClientID; }
int32_t getCtrlTick() const { return iCtrlTick; }
C4TimeMilliseconds getTime() const { return tTime; }
const C4Control &getControl() const { return Ctrl; }
void Set(int32_t iClientID, int32_t iCtrlTick);
void Set(int32_t iClientID, int32_t iCtrlTick, const C4Control &Ctrl);
void Add(const C4GameControlPacket &Ctrl);
void CompileFunc(StdCompiler *pComp) override;
};
class C4GameControlClient
{
friend class C4GameControlNetwork;
public:
C4GameControlClient();
protected:
// core data
int32_t iClientID;
char szName[C4MaxName + 1];
// next expected control for this client
int32_t iNextControl{0};
// performance data
int32_t iPerformance{0};
// list (C4GameControl)
C4GameControlClient *pNext;
public:
int32_t getClientID() const { return iClientID; }
const char *getName() const { return szName; }
int32_t getNextControl() const { return iNextControl; }
int32_t getPerfStat() const;
void Set(int32_t iClientID, const char *szName);
void SetNextControl(int32_t inNextControl) { iNextControl = inNextControl; }
void AddPerf(int32_t iTime);
};
// * Packet classes *
class C4PacketControlReq : public C4PacketBase
{
public:
C4PacketControlReq(int32_t iCtrlTick = -1);
protected:
int32_t iCtrlTick;
public:
int32_t getCtrlTick() const { return iCtrlTick; }
void CompileFunc(StdCompiler *pComp) override;
};
class C4PacketControlPkt : public C4PacketBase
{
public:
C4PacketControlPkt() = default;
C4PacketControlPkt(enum C4ControlDeliveryType eDelivery, const C4IDPacket &Ctrl)
: eDelivery(eDelivery), Ctrl(Ctrl)
{ }
protected:
enum C4ControlDeliveryType eDelivery{CDT_Queue};
C4IDPacket Ctrl;
public:
C4ControlDeliveryType getDelivery() const { return eDelivery; }
const C4IDPacket &getCtrl() const { return Ctrl; }
void CompileFunc(StdCompiler *pComp) override;
};
class C4PacketExecSyncCtrl : public C4PacketBase
{
public:
C4PacketExecSyncCtrl(int32_t iControlTick = ~0) : iControlTick(iControlTick) { }
protected:
int32_t iControlTick;
public:
int32_t getControlTick() const { return iControlTick; }
void CompileFunc(StdCompiler *pComp) override { pComp->Value(mkNamingAdapt(iControlTick, "ControlTick", -1)); }
};
#endif // INC_C4GameControlNetwork