You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
10 KiB
286 lines
10 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
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 3 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, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
#ifndef PLSYNCHOBJ_inc |
|
#define PLSYNCHOBJ_inc |
|
|
|
#include "HeadSpin.h" |
|
#include "pnKeyedObject/hsKeyedObject.h" |
|
#include "pnKeyedObject/plKey.h" |
|
#include "hsStlUtils.h" |
|
#include "plNetGroup.h" |
|
|
|
///////////////////////////////////// |
|
// plSynchedObject |
|
// one per savable object |
|
///////////////////////////////////// |
|
class hsStream; |
|
class plDirtyNotifier; |
|
class plSynchedObject : public hsKeyedObject |
|
{ |
|
public: |
|
enum LocallyOwnedAnswer |
|
{ |
|
kNo=false, |
|
kYes=true |
|
}; |
|
|
|
enum Flags |
|
{ |
|
kDontDirty = 0x1, |
|
kSendReliably = 0x2, // object wants reliable send |
|
kHasConstantNetGroup = 0x4, // has a constant net group. |
|
kDontSynchGameMessages = 0x8, // don't send/recv game actions |
|
kExcludePersistentState = 0x10, // don't send SDL state msgs to server, check exclude list |
|
kExcludeAllPersistentState=0x20, // don't send ANY type of SDL state |
|
kLocalOnly = (kExcludeAllPersistentState | kDontSynchGameMessages), // localOnly in all respects |
|
kHasVolatileState = 0x40, // server won't save this state on shutdown |
|
kAllStateIsVolatile = 0x80 |
|
}; |
|
|
|
enum SDLSendFlags |
|
{ |
|
kBCastToClients = 0x1, |
|
kForceFullSend = 0x2, |
|
kSkipLocalOwnershipCheck= 0x4, |
|
kSendImmediately = 0x8, |
|
kDontPersistOnServer = 0x10, // for an SDL bcast msg which is used for synching only, not persisting |
|
kUseRelevanceRegions = 0x20, |
|
kNewState = 0x40, |
|
kIsAvatarState = 0x80, |
|
}; |
|
|
|
struct StateDefn |
|
{ |
|
plKey fObjKey; |
|
uint32_t fSendFlags; |
|
std::string fSDLName; |
|
|
|
plSynchedObject* GetObject() const { return plSynchedObject::ConvertNoRef(fObjKey->ObjectIsLoaded()); } |
|
StateDefn() : fObjKey(nil),fSendFlags(0) {} |
|
StateDefn(plKey k, uint32_t f, const char* sdlName) : fObjKey(k),fSendFlags(f) { fSDLName=sdlName; } |
|
}; |
|
|
|
private: |
|
typedef std::vector<std::string> SDLStateList; |
|
SDLStateList fSDLExcludeList; |
|
SDLStateList fSDLVolatileList; |
|
uint32_t fSynchFlags; |
|
|
|
plNetGroupId fNetGroup; |
|
|
|
static std::vector<hsBool> fSynchStateStack; |
|
static plSynchedObject* fStaticSynchedObj; // static which temporarily holds address of each object's synchMgr |
|
static std::vector<StateDefn> fDirtyStates; |
|
|
|
static void IRemoveDirtyState(plKey o, const char* sdlName); |
|
static void IAddDirtyState(plKey o, const char* sdlName, uint32_t sendFlags); |
|
bool IOKToDirty(const char* SDLStateName) const; |
|
SDLStateList::const_iterator IFindInSDLStateList(const SDLStateList& list, const char* sdlName) const; |
|
protected: |
|
bool IOKToNetwork(const char* sdlName, uint32_t* synchFlags) const; |
|
public: |
|
plSynchedObject(); |
|
virtual ~plSynchedObject(); |
|
|
|
CLASSNAME_REGISTER( plSynchedObject ); |
|
GETINTERFACE_ANY( plSynchedObject, hsKeyedObject); |
|
|
|
virtual hsBool MsgReceive(plMessage* msg); |
|
|
|
// getters |
|
int GetSynchFlags() const { return fSynchFlags; } |
|
plNetGroupId GetNetGroup() const { return fNetGroup; }; |
|
plNetGroupId GetEffectiveNetGroup() const; |
|
|
|
// setters |
|
void SetSynchFlagsBit(uint32_t f) { fSynchFlags |= f; } |
|
virtual void SetNetGroupConstant(plNetGroupId netGroup); |
|
virtual void SetNetGroup(plNetGroupId netGroup) { fNetGroup = netGroup; } |
|
plNetGroupId SelectNetGroup(plKey groupKey); |
|
|
|
virtual hsBool DirtySynchState(const char* sdlName, uint32_t sendFlags); |
|
void SendSDLStateMsg(const char* SDLStateName, uint32_t synchFlags); // don't use, only for net code |
|
|
|
void ClearSynchFlagsBit(uint32_t f) { fSynchFlags &= ~f; } |
|
|
|
// static |
|
static hsBool GetSynchDisabled() { return fSynchStateStack.size() ? fSynchStateStack.back() : true; } |
|
static void PushSynchDisabled(hsBool b) { fSynchStateStack.push_back(b); } |
|
static hsBool PopSynchDisabled(); |
|
static plSynchedObject* GetStaticSynchedObject() { return fStaticSynchedObj; } |
|
static int32_t GetNumDirtyStates() { return fDirtyStates.size(); } |
|
static plSynchedObject::StateDefn* GetDirtyState(int32_t i) { return &fDirtyStates[i]; } |
|
static void ClearDirtyState(std::vector<StateDefn>& carryOver) { fDirtyStates=carryOver; } |
|
|
|
// IO |
|
// void SendCreationMsg(double secs); |
|
// void SendDestructionMsg(double secs) ; |
|
|
|
virtual void Read(hsStream* s, hsResMgr* mgr); |
|
virtual void Write(hsStream* s, hsResMgr* mgr); |
|
|
|
int IsLocallyOwned() const; // returns yes/no/maybe |
|
|
|
// disable net synching only |
|
bool IsNetSynched() const { return (fSynchFlags & kDontSynchGameMessages)==0; } |
|
void SetNetSynched(bool b) { if (!b) fSynchFlags |= kDontSynchGameMessages; else fSynchFlags &= ~kDontSynchGameMessages; } |
|
|
|
// disable net synching AND persisting |
|
bool IsLocalOnly() const { return (fSynchFlags & kLocalOnly)==0; } |
|
void SetLocalOnly(bool b) { if (b) fSynchFlags |= kLocalOnly; else fSynchFlags &= ~kLocalOnly; } |
|
|
|
// disable particular types of persistence |
|
void AddToSDLExcludeList(const char*); |
|
void RemoveFromSDLExcludeList(const char*); |
|
bool IsInSDLExcludeList(const char*) const; |
|
|
|
// make volatile particular types of state |
|
void AddToSDLVolatileList(const char*); |
|
void RemoveFromSDLVolatileList(const char*); |
|
bool IsInSDLVolatileList(const char*) const; |
|
|
|
// |
|
// synched value stuff, currently unused |
|
// current size is 16 + numValue bytes*2 + numFriends*4 bytes |
|
// |
|
#ifdef USE_SYNCHED_VALUES |
|
public: |
|
typedef uint16_t AddrOffsetType; |
|
typedef uint8_t NumSynchedValuesType; |
|
typedef uint16_t FlagsType; |
|
friend class plSynchedValueBase; |
|
|
|
private: |
|
AddrOffsetType* fSynchedValueAddrOffsets; // represent uint32_ts offsets |
|
NumSynchedValuesType fNumSynchedValues; |
|
|
|
// array of friends |
|
plSynchedValueBase** fSynchedValueFriends; |
|
NumSynchedValuesType fNumSynchedValueFriends; |
|
|
|
// dirty callback notifiers |
|
std::vector<plDirtyNotifier*> fDirtyNotifiers; |
|
|
|
void IAppendSynchedValueAddrOffset(AddrOffsetType synchedValueAddrOffset); |
|
void IAppendSynchedValueFriend(plSynchedValueBase* v); |
|
plSynchedValueBase* IGetSynchedValue(NumSynchedValuesType i) const |
|
{ return (plSynchedValueBase*)((int32_t)this + (fSynchedValueAddrOffsets[i]<<2)); } |
|
plSynchedValueBase* IGetSynchedValueFriend(NumSynchedValuesType i) const |
|
{ return fSynchedValueFriends[i]; } |
|
|
|
public: |
|
int32_t GetNumSynchedValues() const { return fNumSynchedValues+fNumSynchedValueFriends; } |
|
plSynchedValueBase* GetSynchedValue(int i) const; |
|
|
|
uint8_t RegisterSynchedValue(plSynchedValueBase* v); |
|
hsBool RemoveSynchedValue(plSynchedValueBase* v); // handles SVFriends too |
|
void RegisterSynchedValueFriend(plSynchedValueBase* v); |
|
#endif |
|
|
|
#ifdef USE_DIRTY_NOTIFIERS |
|
// dirty CB notifiers |
|
void AddDirtyNotifier(plDirtyNotifier* dn); |
|
void RemoveDirtyNotifier(plDirtyNotifier* dn); |
|
#endif |
|
void CallDirtyNotifiers(); |
|
}; |
|
|
|
// |
|
// helper class to set dirty tracking on/off within scope |
|
// |
|
class plSynchEnabler |
|
{ |
|
public: |
|
plSynchEnabler(hsBool enable) { plSynchedObject::PushSynchDisabled(!enable); } |
|
~plSynchEnabler() { plSynchedObject::PopSynchDisabled(); } |
|
}; |
|
|
|
#ifdef USE_DIRTY_NOTIFIERS |
|
/////////////////////////////////// |
|
// plDirtyNotifier - When a synchedObj |
|
// gets dirty, this callback will be called. |
|
/////////////////////////////////// |
|
class plDirtyNotifier |
|
{ |
|
protected: |
|
plKey fSynchedObjKey; |
|
void* fUserData; |
|
public: |
|
plDirtyNotifier() : fSynchedObjKey(nil),fUserData(nil) {} |
|
virtual ~plDirtyNotifier() |
|
{ |
|
if (fSynchedObjKey) |
|
{ |
|
plSynchedObject* so = plSynchedObject::ConvertNoRef(fSynchedObjKey->ObjectIsLoaded()); |
|
if (so) |
|
so->RemoveDirtyNotifier(this); |
|
} |
|
} |
|
|
|
void SetSynchedObjKey(plKey k) { fSynchedObjKey=k; } // should be set |
|
void SetUserData(void* v) { fUserData=v;} // optional |
|
|
|
plKey GetSynchedObjKey() { return fSynchedObjKey; } |
|
void* GetUserData() { return fUserData;} |
|
|
|
// override |
|
virtual void Callback() = 0; |
|
}; |
|
#endif |
|
|
|
// |
|
// MACROS |
|
// |
|
|
|
#ifdef USE_SYNCHED_VALUES |
|
#define SYNCHED_VALUE(type) plSynchedValue<type> |
|
#define SYNCHED_TARRAY(type) plSynchedTArray<type> |
|
#define SYNCHED_VALUE_FRIEND(type) plSynchedValueFriend<type> |
|
#define SYNCHED_TARRAY_FRIEND(type) plSynchedTArrayFriend<type> |
|
#else |
|
#define SYNCHED_VALUE(type) type |
|
#define SYNCHED_TARRAY(type) hsTArray<type> |
|
#define SYNCHED_VALUE_FRIEND(type) type |
|
#define SYNCHED_TARRAY_FRIEND(type) hsTArray<type> |
|
#endif |
|
|
|
#endif // PLSYNCHOBJ_inc
|
|
|