/*==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 . 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 "hsTypes.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 fSendFlags; std::string fSDLName; plSynchedObject* GetObject() const { return plSynchedObject::ConvertNoRef(fObjKey->ObjectIsLoaded()); } StateDefn() : fObjKey(nil),fSendFlags(0) {} StateDefn(plKey k, UInt32 f, const char* sdlName) : fObjKey(k),fSendFlags(f) { fSDLName=sdlName; } }; private: typedef std::vector SDLStateList; SDLStateList fSDLExcludeList; SDLStateList fSDLVolatileList; UInt32 fSynchFlags; plNetGroupId fNetGroup; static std::vector fSynchStateStack; static plSynchedObject* fStaticSynchedObj; // static which temporarily holds address of each object's synchMgr static std::vector fDirtyStates; static void IRemoveDirtyState(plKey o, const char* sdlName); static void IAddDirtyState(plKey o, const char* sdlName, UInt32 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* 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 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 sendFlags); void SendSDLStateMsg(const char* SDLStateName, UInt32 synchFlags); // don't use, only for net code void ClearSynchFlagsBit(UInt32 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 GetNumDirtyStates() { return fDirtyStates.size(); } static plSynchedObject::StateDefn* GetDirtyState(Int32 i) { return &fDirtyStates[i]; } static void ClearDirtyState(std::vector& 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 AddrOffsetType; typedef UInt8 NumSynchedValuesType; typedef UInt16 FlagsType; friend class plSynchedValueBase; private: AddrOffsetType* fSynchedValueAddrOffsets; // represent dwords offsets NumSynchedValuesType fNumSynchedValues; // array of friends plSynchedValueBase** fSynchedValueFriends; NumSynchedValuesType fNumSynchedValueFriends; // dirty callback notifiers std::vector fDirtyNotifiers; void IAppendSynchedValueAddrOffset(AddrOffsetType synchedValueAddrOffset); void IAppendSynchedValueFriend(plSynchedValueBase* v); plSynchedValueBase* IGetSynchedValue(NumSynchedValuesType i) const { return (plSynchedValueBase*)((Int32)this + (fSynchedValueAddrOffsets[i]<<2)); } plSynchedValueBase* IGetSynchedValueFriend(NumSynchedValuesType i) const { return fSynchedValueFriends[i]; } public: Int32 GetNumSynchedValues() const { return fNumSynchedValues+fNumSynchedValueFriends; } plSynchedValueBase* GetSynchedValue(int i) const; UInt8 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 #define SYNCHED_TARRAY(type) plSynchedTArray #define SYNCHED_VALUE_FRIEND(type) plSynchedValueFriend #define SYNCHED_TARRAY_FRIEND(type) plSynchedTArrayFriend #else #define SYNCHED_VALUE(type) type #define SYNCHED_TARRAY(type) hsTArray #define SYNCHED_VALUE_FRIEND(type) type #define SYNCHED_TARRAY_FRIEND(type) hsTArray #endif #endif // PLSYNCHOBJ_inc