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.
569 lines
22 KiB
569 lines
22 KiB
4 years ago
|
/*==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 PL_SDL_inc
|
||
|
#define PL_SDL_inc
|
||
|
|
||
|
//
|
||
|
// Code for the State Description Language (SDL)
|
||
|
//
|
||
|
|
||
|
#include "plSDLDescriptor.h"
|
||
|
#include "hsUtils.h"
|
||
|
#include "hsStlUtils.h"
|
||
|
|
||
|
#include "../pnFactory/plCreatable.h"
|
||
|
#include "../pnKeyedObject/plKey.h"
|
||
|
#include "../pnKeyedObject/plUoid.h"
|
||
|
|
||
|
#include "../plUnifiedTime/plUnifiedTime.h"
|
||
|
|
||
|
namespace plSDL
|
||
|
{
|
||
|
typedef std::list<plStateDescriptor*> DescriptorList;
|
||
|
enum GeneralPurpose
|
||
|
{
|
||
|
kLatestVersion = -1, // used when requesting the latest version of a state descriptor
|
||
|
kMaxListSize = 9999 // maximum size of var lists
|
||
|
};
|
||
|
|
||
|
enum ContentsFlags // or saveFlags, 16 bits
|
||
|
{
|
||
|
kHasUoid = 0x1,
|
||
|
kHasNotificationInfo = 0x2,
|
||
|
kHasTimeStamp = 0x4,
|
||
|
kSameAsDefault = 0x8,
|
||
|
kHasDirtyFlag = 0x10,
|
||
|
kWantTimeStamp = 0x20,
|
||
|
|
||
|
kAddedVarLengthIO = 0x8000, // using to establish a new version in the header, can delete in 8/03
|
||
|
|
||
|
kHasMaximumValue= 0xffff,
|
||
|
};
|
||
|
|
||
|
enum RWOptions
|
||
|
{
|
||
|
kDirtyOnly = 1<< 0, // write option
|
||
|
kSkipNotificationInfo = 1<< 1, // read/write option
|
||
|
kBroadcast = 1<< 2, // send option
|
||
|
kWriteTimeStamps = 1<< 3, // write out time stamps
|
||
|
kTimeStampOnRead = 1<< 4, // read: timestamp each var when it gets read. write: request that the reader timestamp the dirty vars.
|
||
|
kTimeStampOnWrite = 1<< 5, // read: n/a. write: timestamp each var when it gets written.
|
||
|
kKeepDirty = 1<< 6, // don't clear dirty flag on read
|
||
|
kDontWriteDirtyFlag = 1<< 7, // write option. don't write var dirty flag.
|
||
|
kMakeDirty = 1<< 8, // read/write: set dirty flag on var read/write.
|
||
|
kDirtyNonDefaults = 1<< 9, // dirty the var if non default value.
|
||
|
kForceConvert = 1<<10, // always try to convert rec to latest on read
|
||
|
};
|
||
|
|
||
|
enum BehaviorFlags
|
||
|
{
|
||
|
kDisallowTimeStamping = 0x1,
|
||
|
};
|
||
|
|
||
|
extern const char* kAgeSDLObjectName;
|
||
|
void VariableLengthRead(hsStream* s, int size, int* val);
|
||
|
void VariableLengthWrite(hsStream* s, int size, int val);
|
||
|
};
|
||
|
|
||
|
class plStateVarNotificationInfo
|
||
|
{
|
||
|
private:
|
||
|
std::string fHintString;
|
||
|
public:
|
||
|
void SetHintString(const char* c) { fHintString=c; }
|
||
|
const char* GetHintString() const { return fHintString.c_str(); }
|
||
|
|
||
|
void Read(hsStream* s, UInt32 readOptions);
|
||
|
void Write(hsStream* s, UInt32 writeOptions) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Base class for a state variable.
|
||
|
// A state var is a var descriptor and it's value (contents)
|
||
|
//
|
||
|
class plSimpleStateVariable;
|
||
|
class plSDStateVariable;
|
||
|
class plStateVariable
|
||
|
{
|
||
|
public:
|
||
|
enum Flags
|
||
|
{
|
||
|
kDirty = 0x1, // true when someone sets the value using Set(...), can be cleared after writing
|
||
|
kUsed = 0x2 // true when it contains some value (either by Set(...) or Read() )
|
||
|
};
|
||
|
protected:
|
||
|
UInt32 fFlags;
|
||
|
plStateVarNotificationInfo fNotificationInfo;
|
||
|
public:
|
||
|
plStateVariable() : fFlags(0) {}
|
||
|
virtual ~plStateVariable() {}
|
||
|
|
||
|
const char* GetName() const { return GetVarDescriptor()->GetName(); }
|
||
|
bool IsNamed(const char* n) const { return (n && !stricmp(GetName(), n)); }
|
||
|
virtual int GetCount() const = 0;
|
||
|
|
||
|
// conversion ops
|
||
|
virtual plSimpleStateVariable* GetAsSimpleStateVar() = 0;
|
||
|
virtual plSDStateVariable* GetAsSDStateVar() = 0;
|
||
|
virtual plVarDescriptor* GetVarDescriptor() = 0;
|
||
|
virtual const plVarDescriptor* GetVarDescriptor() const = 0;
|
||
|
virtual void Alloc(int cnt=-1 /* -1 means don't change count */) = 0;
|
||
|
|
||
|
virtual bool IsDirty() const { return (fFlags & kDirty) != 0; }
|
||
|
virtual bool IsUsed() const { return (fFlags & kUsed) != 0; }
|
||
|
|
||
|
void SetDirty(bool d) { if (d) fFlags |= kDirty; else fFlags &= ~kDirty; }
|
||
|
void SetUsed(bool d) { if (d) fFlags |= kUsed; else fFlags &= ~kUsed; }
|
||
|
virtual void SetFromDefaults(bool timeStampNow) = 0;
|
||
|
virtual void TimeStamp( const plUnifiedTime & ut=plUnifiedTime::GetCurrentTime() ) = 0;
|
||
|
virtual const plUnifiedTime& GetTimeStamp() const = 0;
|
||
|
|
||
|
plStateVarNotificationInfo& GetNotificationInfo() { return fNotificationInfo; }
|
||
|
const plStateVarNotificationInfo& GetNotificationInfo() const { return fNotificationInfo; }
|
||
|
|
||
|
virtual void DumpToObjectDebugger(bool dirtyOnly, int level) const {}
|
||
|
virtual void DumpToStream(hsStream* stream, bool dirtyOnly, int level) const {}
|
||
|
|
||
|
// IO
|
||
|
virtual bool ReadData(hsStream* s, float timeConvert, UInt32 readOptions);
|
||
|
virtual bool WriteData(hsStream* s, float timeConvert, UInt32 writeOptions) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Change Notifier.
|
||
|
// When a plSimpleStateVariable changes it's value by more than the given delta value,
|
||
|
// a notification msg will be sent to the objects that registered interest.
|
||
|
//
|
||
|
class plStateChangeNotifier
|
||
|
{
|
||
|
friend class plSimpleStateVariable;
|
||
|
private:
|
||
|
float fDelta;
|
||
|
typedef std::vector<plKey> KeyList;
|
||
|
KeyList fKeys; // the objects to notify on change>delta
|
||
|
static UInt32 fCurrentPlayerID;
|
||
|
|
||
|
void IAddKey(plKey k);
|
||
|
int IRemoveKey(plKey k);
|
||
|
public:
|
||
|
plStateChangeNotifier();
|
||
|
plStateChangeNotifier(float i, plKey k);
|
||
|
|
||
|
void AddNotificationKey(plKey k) { IAddKey(k); }
|
||
|
void AddNotificationKeys(KeyList keys);
|
||
|
int RemoveNotificationKey(plKey k); // returns number of keys left after removal
|
||
|
int RemoveNotificationKeys(KeyList keys); // returns number of keys left after removal
|
||
|
|
||
|
void SendNotificationMsg(const plSimpleStateVariable* srcVar, const plSimpleStateVariable* dstVar, const char* sdlName);
|
||
|
|
||
|
bool GetValue(float* i) const;
|
||
|
bool SetValue(float i);
|
||
|
|
||
|
static UInt32 GetCurrentPlayerID() { return fCurrentPlayerID; }
|
||
|
static void SetCurrentPlayerID(UInt32 p) { fCurrentPlayerID=p; }
|
||
|
|
||
|
bool operator==(const plStateChangeNotifier &) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// A (non-nested) variable descriptor and its data contents.
|
||
|
//
|
||
|
class plUoid;
|
||
|
class plKey;
|
||
|
class plClientUnifiedTime;
|
||
|
typedef unsigned char byte;
|
||
|
class plSimpleStateVariable : public plStateVariable
|
||
|
{
|
||
|
protected:
|
||
|
union
|
||
|
{
|
||
|
int* fI; // array of int
|
||
|
short* fS; // array of short
|
||
|
byte* fBy; // array of byte
|
||
|
float* fF; // array of float
|
||
|
double* fD; // array of double
|
||
|
bool* fB; // array of bool
|
||
|
plUoid* fU; // array of uoid
|
||
|
plCreatable** fC; // array of plCreatable ptrs
|
||
|
plVarDescriptor::String32* fS32; // array of strings
|
||
|
plClientUnifiedTime* fT; // array of Times
|
||
|
};
|
||
|
mutable plUnifiedTime fTimeStamp; // the last time the var was changed
|
||
|
plSimpleVarDescriptor fVar;
|
||
|
|
||
|
typedef std::vector<plStateChangeNotifier> StateChangeNotifiers;
|
||
|
StateChangeNotifiers fChangeNotifiers;
|
||
|
|
||
|
void IDeAlloc();
|
||
|
void IInit(); // initize vars
|
||
|
void IVarSet(bool timeStampNow=false);
|
||
|
|
||
|
// converter fxns
|
||
|
bool IConvertFromBool(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromInt(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromByte(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromShort(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromFloat(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromDouble(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromString(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromRGB(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromRGBA(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromRGB8(plVarDescriptor::Type newType);
|
||
|
bool IConvertFromRGBA8(plVarDescriptor::Type newType);
|
||
|
|
||
|
bool IReadData(hsStream* s, float timeConvert, int idx, UInt32 readOptions);
|
||
|
bool IWriteData(hsStream* s, float timeConvert, int idx, UInt32 writeOptions) const;
|
||
|
|
||
|
public:
|
||
|
|
||
|
plSimpleStateVariable() { IInit(); }
|
||
|
plSimpleStateVariable(plVarDescriptor* vd) { IInit(); CopyFrom(vd); }
|
||
|
~plSimpleStateVariable() { IDeAlloc(); }
|
||
|
|
||
|
// conversion ops
|
||
|
plSimpleStateVariable* GetAsSimpleStateVar() { return this; }
|
||
|
plSDStateVariable* GetAsSDStateVar() { return nil; }
|
||
|
bool operator==(const plSimpleStateVariable &other) const; // assumes matching var descriptors
|
||
|
|
||
|
void TimeStamp( const plUnifiedTime & ut=plUnifiedTime::GetCurrentTime() );
|
||
|
void CopyFrom(plVarDescriptor* v);
|
||
|
void CopyData(const plSimpleStateVariable* other, UInt32 writeOptions=0);
|
||
|
bool SetFromString(const char* value, int idx, bool timeStampNow); // set value from string, type. return false on err
|
||
|
char* GetAsString(int idx) const;
|
||
|
bool ConvertTo(plSimpleVarDescriptor* toVar, bool force=false); // return false on err
|
||
|
void Alloc(int cnt=-1 /* -1 means don't change count */); // alloc memory after setting type
|
||
|
void Reset();
|
||
|
|
||
|
// setters
|
||
|
bool Set(float v, int idx=0);
|
||
|
bool Set(float* v, int idx=0); // floatVector
|
||
|
bool Set(double v, int idx=0);
|
||
|
bool Set(double* v, int idx=0); // doubleVector
|
||
|
bool Set(int v, int idx=0);
|
||
|
bool Set(int* v, int idx=0) { return Set(*v, idx); } // helper since there is no int vec type
|
||
|
bool Set(byte v, int idx=0);
|
||
|
bool Set(byte* v, int idx=0); // byteVector
|
||
|
bool Set(short v, int idx=0);
|
||
|
bool Set(short* v, int idx=0) { return Set(*v, idx); } // helper since there is no short vec type
|
||
|
bool Set(bool v, int idx=0);
|
||
|
bool Set(bool* v, int idx=0) { return Set(*v, idx); } // helper since there is no bool vec type
|
||
|
bool Set(const char* v, int idx=0); // string
|
||
|
bool Set(const plKey& v, int idx=0);
|
||
|
bool Set(plCreatable*, int idx=0); // only SDL generated by the server is allowed to use this type.
|
||
|
void SetFromDefaults(bool timeStampNow);
|
||
|
|
||
|
// getters
|
||
|
bool Get(int* value, int idx=0) const;
|
||
|
bool Get(short* value, int idx=0) const;
|
||
|
bool Get(byte* value, int idx=0) const; // returns byte or byteVector
|
||
|
bool Get(float* value, int idx=0) const; // returns float or floatVector
|
||
|
bool Get(double* value, int idx=0) const; // returns double or doubleVector
|
||
|
bool Get(bool* value, int idx=0) const;
|
||
|
bool Get(char value[], int idx=0) const;
|
||
|
bool Get(plKey* value, int idx=0) const;
|
||
|
bool Get(plCreatable** value, int idx=0) const;
|
||
|
const plUnifiedTime& GetTimeStamp() const { return fTimeStamp; }
|
||
|
|
||
|
// Special backdoor so the KI Manager can get the key name without having a ResMgr
|
||
|
const char* GetKeyName(int idx=0) const;
|
||
|
|
||
|
int GetCount() const { return fVar.GetCount(); } // helper
|
||
|
plVarDescriptor* GetVarDescriptor() { return &fVar; }
|
||
|
plSimpleVarDescriptor* GetSimpleVarDescriptor() { return fVar.GetAsSimpleVarDescriptor(); }
|
||
|
const plVarDescriptor* GetVarDescriptor() const { return &fVar; }
|
||
|
const plSimpleVarDescriptor* GetSimpleVarDescriptor() const { return fVar.GetAsSimpleVarDescriptor(); }
|
||
|
|
||
|
// State Change Notification
|
||
|
void AddStateChangeNotification(plStateChangeNotifier& n);
|
||
|
void RemoveStateChangeNotification(plKey notificationObj); // remove all with this key
|
||
|
void RemoveStateChangeNotification(plStateChangeNotifier n); // remove ones which match
|
||
|
void NotifyStateChange(const plSimpleStateVariable* other, const char* sdlName); // send notification msg if necessary, internal use
|
||
|
|
||
|
void DumpToObjectDebugger(bool dirtyOnly, int level) const;
|
||
|
void DumpToStream(hsStream* stream, bool dirtyOnly, int level) const;
|
||
|
|
||
|
// IO
|
||
|
bool ReadData(hsStream* s, float timeConvert, UInt32 readOptions);
|
||
|
bool WriteData(hsStream* s, float timeConvert, UInt32 writeOptions) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// A list of state data records, all of which are the same kind.
|
||
|
// Corresponds to a SD var descriptor.
|
||
|
//
|
||
|
class plStateDataRecord;
|
||
|
class plSDStateVariable : public plStateVariable
|
||
|
{
|
||
|
public:
|
||
|
typedef std::vector<const plStateDataRecord*> ConstDataRecList;
|
||
|
protected:
|
||
|
typedef std::vector<plStateDataRecord*> DataRecList;
|
||
|
DataRecList fDataRecList;
|
||
|
plSDVarDescriptor* fVarDescriptor;
|
||
|
|
||
|
void IDeInit();
|
||
|
public:
|
||
|
plSDStateVariable(plSDVarDescriptor* sdvd);
|
||
|
~plSDStateVariable(); // delete all records
|
||
|
|
||
|
// conversion ops
|
||
|
plSimpleStateVariable* GetAsSimpleStateVar() { return nil; }
|
||
|
plSDStateVariable* GetAsSDStateVar() { return this; }
|
||
|
bool operator==(const plSDStateVariable &other) const; // assumes matching var descriptors
|
||
|
|
||
|
void ConvertTo(plSDStateVariable* otherSDVar, bool force=false);
|
||
|
void CopyFrom(plSDStateVariable* other, UInt32 writeOptions=0);
|
||
|
void UpdateFrom(plSDStateVariable* other, UInt32 writeOptions=0);
|
||
|
void AddStateDataRecord(plStateDataRecord *sdr) { fDataRecList.push_back(sdr); SetDirty(true); SetUsed(true); }
|
||
|
void InsertStateDataRecord(plStateDataRecord *sdr, int i) { fDataRecList[i] = sdr; SetDirty(true); SetUsed(true);}
|
||
|
void SetFromDefaults(bool timeStampNow);
|
||
|
void TimeStamp( const plUnifiedTime & ut=plUnifiedTime::GetCurrentTime() );
|
||
|
const plUnifiedTime& GetTimeStamp() const { static plUnifiedTime foo; return foo; }
|
||
|
|
||
|
void Alloc(int cnt=-1 /* -1 means don't change count */); // wipe and re-create
|
||
|
void Alloc(plSDVarDescriptor* sdvd, int cnt=-1); // wipe and re-create
|
||
|
void Resize(int cnt);
|
||
|
|
||
|
bool IsDirty() const;
|
||
|
bool IsUsed() const;
|
||
|
|
||
|
// getters
|
||
|
plStateDataRecord* GetStateDataRecord(int i) { return fDataRecList[i]; }
|
||
|
const plStateDataRecord* GetStateDataRecord(int i) const { return fDataRecList[i]; }
|
||
|
int GetCount() const { return fDataRecList.size(); }
|
||
|
int GetUsedCount() const;
|
||
|
int GetDirtyCount() const;
|
||
|
void GetUsedDataRecords(ConstDataRecList*) const;
|
||
|
void GetDirtyDataRecords(ConstDataRecList*) const;
|
||
|
plVarDescriptor* GetVarDescriptor() { return fVarDescriptor; }
|
||
|
plSDVarDescriptor* GetSDVarDescriptor() { return fVarDescriptor->GetAsSDVarDescriptor(); }
|
||
|
const plVarDescriptor* GetVarDescriptor() const { return fVarDescriptor; }
|
||
|
const plSDVarDescriptor* GetSDVarDescriptor() const { return fVarDescriptor->GetAsSDVarDescriptor(); }
|
||
|
void FlagNewerState(const plSDStateVariable&, bool respectAlwaysNew);
|
||
|
void FlagAlwaysNewState();
|
||
|
void DumpToObjectDebugger(bool dirtyOnly, int level) const;
|
||
|
void DumpToStream(hsStream* stream, bool dirtyOnly, int level) const;
|
||
|
|
||
|
// IO
|
||
|
bool ReadData(hsStream* s, float timeConvert, UInt32 readOptions);
|
||
|
bool WriteData(hsStream* s, float timeConvert, UInt32 writeOptions) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Contains the actual data contents and points to its associated descriptor
|
||
|
//
|
||
|
class plNetMsgSDLState;
|
||
|
class plStateDataRecord : public plCreatable
|
||
|
{
|
||
|
public:
|
||
|
typedef std::vector<plSimpleStateVariable*> SimpleVarsList;
|
||
|
typedef std::vector<plSDStateVariable*> SDVarsList;
|
||
|
enum Flags
|
||
|
{
|
||
|
kVolatile = 0x1
|
||
|
};
|
||
|
protected:
|
||
|
typedef std::vector<plStateVariable*> VarsList;
|
||
|
|
||
|
const plStateDescriptor* fDescriptor;
|
||
|
plUoid fAssocObject; // optional
|
||
|
VarsList fVarsList; // list of variables
|
||
|
VarsList fSDVarsList; // list of nested data records
|
||
|
UInt32 fFlags;
|
||
|
static const UInt8 kIOVersion; // I/O Version
|
||
|
|
||
|
void IDeleteVarsList(VarsList& vars);
|
||
|
void IInitDescriptor(const char* name, int version); // or plSDL::kLatestVersion
|
||
|
void IInitDescriptor(const plStateDescriptor* sd);
|
||
|
|
||
|
void IReadHeader(hsStream* s);
|
||
|
void IWriteHeader(hsStream* s) const;
|
||
|
bool IConvertVar(plSimpleStateVariable* fromVar, plSimpleStateVariable* toVar, bool force);
|
||
|
|
||
|
plStateVariable* IFindVar(const VarsList& vars, const char* name) const;
|
||
|
int IGetNumUsedVars(const VarsList& vars) const;
|
||
|
int IGetUsedVars(const VarsList& varsOut, VarsList *varsIn) const; // build a list of vars that have data
|
||
|
bool IHasUsedVars(const VarsList& vars) const;
|
||
|
|
||
|
int IGetNumDirtyVars(const VarsList& vars) const;
|
||
|
int IGetDirtyVars(const VarsList& varsOut, VarsList *varsIn) const; // build a list of vars that are dirty
|
||
|
bool IHasDirtyVars(const VarsList& vars) const;
|
||
|
public:
|
||
|
CLASSNAME_REGISTER( plStateDataRecord );
|
||
|
GETINTERFACE_ANY( plStateDataRecord, plCreatable);
|
||
|
|
||
|
plStateDataRecord(const char* sdName, int version=plSDL::kLatestVersion);
|
||
|
plStateDataRecord(plStateDescriptor* sd);
|
||
|
plStateDataRecord(const plStateDataRecord &other, UInt32 writeOptions=0 ):fFlags(0) { CopyFrom(other, writeOptions); }
|
||
|
plStateDataRecord():fFlags(0) {}
|
||
|
~plStateDataRecord();
|
||
|
|
||
|
bool ConvertTo(plStateDescriptor* other, bool force=false );
|
||
|
bool operator==(const plStateDataRecord &other) const; // assumes matching state descriptors
|
||
|
|
||
|
UInt32 GetFlags() const { return fFlags; }
|
||
|
void SetFlags(UInt32 f) { fFlags =f; }
|
||
|
|
||
|
plSimpleStateVariable* FindVar(const char* name) const { return (plSimpleStateVariable*)IFindVar(fVarsList, name); }
|
||
|
plSDStateVariable* FindSDVar(const char* name) const { return (plSDStateVariable*)IFindVar(fSDVarsList, name); }
|
||
|
|
||
|
plStateDataRecord& operator=(const plStateDataRecord& other) { CopyFrom(other); }
|
||
|
void CopyFrom(const plStateDataRecord& other, UInt32 writeOptions=0);
|
||
|
void UpdateFrom(const plStateDataRecord& other, UInt32 writeOptions=0);
|
||
|
void SetFromDefaults(bool timeStampNow);
|
||
|
void TimeStampDirtyVars();
|
||
|
|
||
|
int GetNumVars() const { return fVarsList.size(); }
|
||
|
plSimpleStateVariable* GetVar(int i) const { return (plSimpleStateVariable*)fVarsList[i]; }
|
||
|
int GetNumSDVars() const { return fSDVarsList.size(); }
|
||
|
plSDStateVariable* GetSDVar(int i) const { return (plSDStateVariable*)fSDVarsList[i]; }
|
||
|
|
||
|
// Used vars
|
||
|
bool IsUsed() const { return (HasUsedVars() || HasUsedSDVars()); }
|
||
|
|
||
|
int GetNumUsedVars() const { return IGetNumUsedVars(fVarsList); }
|
||
|
int GetUsedVars(SimpleVarsList *vars) const { return IGetUsedVars(fVarsList, (VarsList*)vars); } // build a list of vars that have data
|
||
|
bool HasUsedVars() const { return IHasUsedVars(fVarsList); }
|
||
|
|
||
|
int GetNumUsedSDVars() const { return IGetNumUsedVars(fSDVarsList); }
|
||
|
int GetUsedSDVars(SDVarsList *vars) const { return IGetUsedVars(fSDVarsList, (VarsList*)vars); } // build a list of SD vars that have data
|
||
|
bool HasUsedSDVars() const { return IHasUsedVars(fSDVarsList); }
|
||
|
|
||
|
// Dirty Vars
|
||
|
bool IsDirty() const { return (HasDirtyVars() || HasDirtySDVars()); }
|
||
|
|
||
|
int GetNumDirtyVars() const { return IGetNumDirtyVars(fVarsList); }
|
||
|
int GetDirtyVars(SimpleVarsList *vars) const { return IGetDirtyVars(fVarsList, (VarsList*)vars); } // build a list of vars that are dirty
|
||
|
bool HasDirtyVars() const { return IHasDirtyVars(fVarsList); }
|
||
|
|
||
|
int GetNumDirtySDVars() const { return IGetNumDirtyVars(fSDVarsList); }
|
||
|
int GetDirtySDVars(SDVarsList *vars) const { return IGetDirtyVars(fSDVarsList, (VarsList*)vars); }; // build a list of Sdvars that are dirty
|
||
|
bool HasDirtySDVars() const { return IHasDirtyVars(fSDVarsList); }
|
||
|
|
||
|
const plStateDescriptor* GetDescriptor() const { return fDescriptor; }
|
||
|
void SetDescriptor(const char* sdName, int version);
|
||
|
|
||
|
plNetMsgSDLState* PrepNetMsg(float timeConvert, UInt32 writeOptions) const; // create/prep a net msg with this data
|
||
|
|
||
|
void SetAssocObject(const plUoid& u) { fAssocObject=u; } // optional
|
||
|
plUoid* GetAssocObject() { return &fAssocObject; } // optional
|
||
|
const plUoid* GetAssocObject() const { return &fAssocObject; } // optional
|
||
|
|
||
|
// utils
|
||
|
void FlagDifferentState(const plStateDataRecord& other); // mark items which differ from 'other' as dirty
|
||
|
void FlagNewerState(const plStateDataRecord& other, bool respectAlwaysNew=false); // mark items which are newer than 'other' as dirty
|
||
|
void FlagAlwaysNewState(); // mark 'alwaysNew' items as dirty
|
||
|
void DumpToObjectDebugger(const char* msg, bool dirtyOnly=false, int level=0) const;
|
||
|
void DumpToStream(hsStream* stream, const char* msg, bool dirtyOnly=false, int level=0) const;
|
||
|
|
||
|
// IO
|
||
|
bool Read(hsStream* s, float timeConvert, UInt32 readOptions=0);
|
||
|
void Write(hsStream* s, float timeConvert, UInt32 writeOptions=0) const;
|
||
|
|
||
|
static bool ReadStreamHeader(hsStream* s, char** name, int* version, plUoid* objUoid=nil);
|
||
|
void WriteStreamHeader(hsStream* s, plUoid* objUoid=nil) const;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Simple SDL parser
|
||
|
//
|
||
|
class plSDLMgr;
|
||
|
class plSDLParser
|
||
|
{
|
||
|
private:
|
||
|
bool IReadDescriptors() const;
|
||
|
bool ILoadSDLFile(const char* fileName) const;
|
||
|
bool IParseVarDesc(const char* fileName, hsStream* stream, char token[], plStateDescriptor*& curDesc,
|
||
|
plVarDescriptor*& curVar) const;
|
||
|
bool IParseStateDesc(const char* fileName, hsStream* stream, char token[], plStateDescriptor*& curDesc) const;
|
||
|
|
||
|
void DebugMsg(char* fmt, ...) const;
|
||
|
void DebugMsgV(char* fmt, va_list args) const;
|
||
|
|
||
|
public:
|
||
|
|
||
|
bool Parse() const; // reads sdl folder, creates descriptor list
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Holds, loads and unloads all state descriptors from sdl files.
|
||
|
// Singleton.
|
||
|
//
|
||
|
class plNetApp;
|
||
|
class plSDLMgr
|
||
|
{
|
||
|
friend class plSDLParser;
|
||
|
private:
|
||
|
std::string fSDLDir;
|
||
|
plSDL::DescriptorList fDescriptors;
|
||
|
plNetApp* fNetApp;
|
||
|
UInt32 fBehaviorFlags;
|
||
|
|
||
|
void IDeleteDescriptors(plSDL::DescriptorList* dl);
|
||
|
public:
|
||
|
plSDLMgr();
|
||
|
~plSDLMgr();
|
||
|
|
||
|
static plSDLMgr* GetInstance();
|
||
|
plStateDescriptor* FindDescriptor(const char* name, int version, const plSDL::DescriptorList * dl=nil) const; // version or kLatestVersion
|
||
|
|
||
|
const plSDL::DescriptorList * GetDescriptors( void ) const { return &fDescriptors;}
|
||
|
|
||
|
void SetSDLDir(const char* s) { fSDLDir=s; }
|
||
|
const char* GetSDLDir() const { return fSDLDir.c_str(); }
|
||
|
|
||
|
void SetNetApp(plNetApp* a) { fNetApp=a; }
|
||
|
plNetApp* GetNetApp() const { return fNetApp; }
|
||
|
|
||
|
bool Init( UInt32 behaviorFlags=0 ); // parse sdl folder
|
||
|
void DeInit();
|
||
|
UInt32 GetBehaviorFlags() const { return fBehaviorFlags; }
|
||
|
void SetBehaviorFlags(UInt32 v) { fBehaviorFlags=v; }
|
||
|
bool AllowTimeStamping() const { return ! ( fBehaviorFlags&plSDL::kDisallowTimeStamping ); }
|
||
|
|
||
|
// I/O - return # of bytes read/written
|
||
|
int Write(hsStream* s, const plSDL::DescriptorList* dl=nil); // write descriptors to a stream
|
||
|
int Read(hsStream* s, plSDL::DescriptorList* dl=nil); // read descriptors into provided list (use legacyList if nil)
|
||
|
};
|
||
|
|
||
|
#endif // PL_SDL_inc
|