2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -1,39 +1,39 @@
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
set(plResMgr_SOURCES
plBSDiffBuffer.cpp
plDiffBuffer.cpp
plKeyFinder.cpp
plLocalization.cpp
plPageInfo.cpp
plRegistryHelpers.cpp
plRegistryKeyList.cpp
plRegistryNode.cpp
plResManager.cpp
plResManagerHelper.cpp
plVersion.cpp
)
set(plResMgr_HEADERS
plBSDiffBuffer.h
plDiffBuffer.h
plKeyFinder.h
plLocalization.h
plPageInfo.h
plRegistryHelpers.h
plRegistryKeyList.h
plRegistryNode.h
plResManager.h
plResManagerHelper.h
plResMgrCreatable.h
plResMgrSettings.h
plVersion.h
)
add_library(plResMgr STATIC ${plResMgr_SOURCES} ${plResMgr_HEADERS})
source_group("Source Files" FILES ${plResMgr_SOURCES})
source_group("Header Files" FILES ${plResMgr_HEADERS})
include_directories("../../CoreLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
set(plResMgr_SOURCES
plBSDiffBuffer.cpp
plDiffBuffer.cpp
plKeyFinder.cpp
plLocalization.cpp
plPageInfo.cpp
plRegistryHelpers.cpp
plRegistryKeyList.cpp
plRegistryNode.cpp
plResManager.cpp
plResManagerHelper.cpp
plVersion.cpp
)
set(plResMgr_HEADERS
plBSDiffBuffer.h
plDiffBuffer.h
plKeyFinder.h
plLocalization.h
plPageInfo.h
plRegistryHelpers.h
plRegistryKeyList.h
plRegistryNode.h
plResManager.h
plResManagerHelper.h
plResMgrCreatable.h
plResMgrSettings.h
plVersion.h
)
add_library(plResMgr STATIC ${plResMgr_SOURCES} ${plResMgr_HEADERS})
source_group("Source Files" FILES ${plResMgr_SOURCES})
source_group("Header Files" FILES ${plResMgr_HEADERS})

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +1,111 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plBSDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// that will modify an old data buffer to match a new one.
// It's a useful utility class when doing binary file
// patching, for example, as you can write out the changes
// to this class, get back a data buffer suitable for writing,
// then use this class again later to reconstruct the new buffer.
//
// This class is copied in structure (not substance) from
// plDiffBuffer. It is based on bsdiff-4.1 from BSD
// Linux (http://www.daemonology.org/bsdiff). It's *extremely*
// hard to read code (written by a PhD), but it works well. The
// original BSD code has been modified to have the bzip2 pipes
// it used to compress data removed. It has also been converted
// to work a C++ utility class.
//
// There isn't really an Add or Copy command in bsdiff. It just
// uses three control numbers and two diff/data buffers.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plBSDiffBuffer_h
#define _plBSDiffBuffer_h
#include "hsTypes.h"
#include "hsStream.h"
//// Class Definition ////////////////////////////////////////////////////////
class hsRAMStream;
class plBSDiffBuffer
{
protected:
hsBool fWriting;
UInt32 fNewLength, fPatchLength;
unsigned char* fPatchBuffer;
public:
plBSDiffBuffer( UInt32 newLength, UInt32 oldLength = 0 ); // Constructor for writing new buffers. oldLength isn't required but helpful for optimizations
plBSDiffBuffer( void *buffer, UInt32 length ); // Constructor for applying a given diff set
// to an old buffer
virtual ~plBSDiffBuffer();
/// Creation/write functions
// Diff() creates the diff buffer from the new and old.
UInt32 Diff( UInt32 oldLength, void *oldBuffer, UInt32 newLength, void *newBuffer );
// GetBuffer() will copy the diff stream into a new buffer and return it. You are responsible for freeing the buffer.
void GetBuffer( UInt32 &length, void *&bufferPtr );
/// Apply functions
// Apply() is another way to call Patch().
UInt32 Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer )
{ return Patch(oldLength, oldBuffer, newLength, newBuffer); };
// Patch() will take this diff buffer and apply it to the given old buffer,
// allocating and producing a new buffer. You are responsible for freeing the new buffer.
UInt32 Patch( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer );
private:
UInt32 IReadUnsignedInt8(unsigned char *buf);
void IWriteUnsignedInt8(UInt32 x,unsigned char *buf);
void ISafeMemcpy(unsigned char *dest, unsigned char *src, size_t nbytes,
unsigned char *destend, unsigned char *srcend);
void ISplit(Int32 *I,Int32 *V,UInt32 start,UInt32 len,UInt32 h);
void IQSuffixSort(Int32 *I,Int32 *V,unsigned char *old,UInt32 oldsize);
UInt32 IMatchLen( unsigned char *oldBuffer, UInt32 oldLength,
unsigned char *newBuffer, UInt32 newLength);
UInt32 ISearch( Int32 *I,
unsigned char *oldBuffer, UInt32 oldLength,
unsigned char *newBuffer, UInt32 newLength,
UInt32 st, UInt32 en, Int32 *pos);
};
#endif // _plBSDiffBuffer_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plBSDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// that will modify an old data buffer to match a new one.
// It's a useful utility class when doing binary file
// patching, for example, as you can write out the changes
// to this class, get back a data buffer suitable for writing,
// then use this class again later to reconstruct the new buffer.
//
// This class is copied in structure (not substance) from
// plDiffBuffer. It is based on bsdiff-4.1 from BSD
// Linux (http://www.daemonology.org/bsdiff). It's *extremely*
// hard to read code (written by a PhD), but it works well. The
// original BSD code has been modified to have the bzip2 pipes
// it used to compress data removed. It has also been converted
// to work a C++ utility class.
//
// There isn't really an Add or Copy command in bsdiff. It just
// uses three control numbers and two diff/data buffers.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plBSDiffBuffer_h
#define _plBSDiffBuffer_h
#include "hsTypes.h"
#include "hsStream.h"
//// Class Definition ////////////////////////////////////////////////////////
class hsRAMStream;
class plBSDiffBuffer
{
protected:
hsBool fWriting;
UInt32 fNewLength, fPatchLength;
unsigned char* fPatchBuffer;
public:
plBSDiffBuffer( UInt32 newLength, UInt32 oldLength = 0 ); // Constructor for writing new buffers. oldLength isn't required but helpful for optimizations
plBSDiffBuffer( void *buffer, UInt32 length ); // Constructor for applying a given diff set
// to an old buffer
virtual ~plBSDiffBuffer();
/// Creation/write functions
// Diff() creates the diff buffer from the new and old.
UInt32 Diff( UInt32 oldLength, void *oldBuffer, UInt32 newLength, void *newBuffer );
// GetBuffer() will copy the diff stream into a new buffer and return it. You are responsible for freeing the buffer.
void GetBuffer( UInt32 &length, void *&bufferPtr );
/// Apply functions
// Apply() is another way to call Patch().
UInt32 Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer )
{ return Patch(oldLength, oldBuffer, newLength, newBuffer); };
// Patch() will take this diff buffer and apply it to the given old buffer,
// allocating and producing a new buffer. You are responsible for freeing the new buffer.
UInt32 Patch( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer );
private:
UInt32 IReadUnsignedInt8(unsigned char *buf);
void IWriteUnsignedInt8(UInt32 x,unsigned char *buf);
void ISafeMemcpy(unsigned char *dest, unsigned char *src, size_t nbytes,
unsigned char *destend, unsigned char *srcend);
void ISplit(Int32 *I,Int32 *V,UInt32 start,UInt32 len,UInt32 h);
void IQSuffixSort(Int32 *I,Int32 *V,unsigned char *old,UInt32 oldsize);
UInt32 IMatchLen( unsigned char *oldBuffer, UInt32 oldLength,
unsigned char *newBuffer, UInt32 newLength);
UInt32 ISearch( Int32 *I,
unsigned char *oldBuffer, UInt32 oldLength,
unsigned char *newBuffer, UInt32 newLength,
UInt32 st, UInt32 en, Int32 *pos);
};
#endif // _plBSDiffBuffer_h

View File

@ -1,250 +1,250 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// (specifically, adds and copys) that will modify an old
// data buffer to match a new one. It's a useful utility
// class when doing binary file patching, for example, as you
// can write out the changes to this class, get back a data
// buffer suitable for writing, then use this class again
// later to reconstruct the new buffer.
//
//// History /////////////////////////////////////////////////////////////////
//
// 7.24.2002 mcn - Created (Happy late b-day to me!)
//
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDiffBuffer.h"
#include "plBSDiffBuffer.h"
#include "hsUtils.h"
#include "hsStream.h"
//////////////////////////////////////////////////////////////////////////////
//// Constructor/Destructors /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Creation Constructor ////////////////////////////////////////////////////
// Use this constructor when creating a new diff buffer. Pass in the length
// of the final new buffer. You don't need to pass in the length of the old
// buffer, but if you do, it'll help this class do some internal space
// optimization.
plDiffBuffer::plDiffBuffer( UInt32 newLength, UInt32 oldLength )
: fBSDiffBuffer( nil )
, fIsBSDiff( false )
{
// Basically, if the new and old lengths can both fit into 16 bits
// (not including a potential negation), then we can store all the
// segment info as 16-bit values instead of 32.
if( oldLength > 0 && oldLength < 32767 && newLength < 32767 )
f16BitMode = true;
else
f16BitMode = false;
fNewLength = newLength;
fStream = TRACKED_NEW hsRAMStream();
fStream->WriteSwap32( fNewLength );
fStream->WriteBool( f16BitMode );
fWriting = true;
}
//// Application Constructor /////////////////////////////////////////////////
// Use this constructor when taking a diff buffer and applying it to an old
// buffer. Pass in a pointer to the diff buffer and its length. The buffer
// will be copied, so you don't need to keep it around after you construct
// this object.
plDiffBuffer::plDiffBuffer( void *buffer, UInt32 length )
: fBSDiffBuffer( nil )
, fStream( nil )
, fIsBSDiff( false )
, fWriting( false )
{
// Check to see if this uses the newer BSDiff format
if ( buffer && length > 32 &&
memcmp(buffer,"BSDIFF40",8)==0 )
{
// This is a bsdiff buffer. Use plBSDiffBuffer to handle it.
fBSDiffBuffer = TRACKED_NEW plBSDiffBuffer(buffer, length);
fIsBSDiff = true;
}
else
{
fStream = TRACKED_NEW hsRAMStream();
fStream->Write( length, buffer );
fStream->Rewind();
fNewLength = fStream->ReadSwap32();
f16BitMode = fStream->ReadBool();
}
}
plDiffBuffer::~plDiffBuffer()
{
if (fStream)
delete fStream;
if (fBSDiffBuffer)
delete fBSDiffBuffer;
}
//////////////////////////////////////////////////////////////////////////////
//// Creation/Write Functions ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Add /////////////////////////////////////////////////////////////////////
// Add() appends an Add-New-Data operation to the diff buffer. The data
// supplied will be copied internally, so you can discard it after you call
// this function.
void plDiffBuffer::Add( Int32 length, void *newData )
{
hsAssert( fWriting, "Trying to Add() to a difference buffer that's reading" );
// We flag our two different op types by the sign of the length. Negative
// lengths are an add operation, positive ones are copy ops.
if( f16BitMode )
fStream->WriteSwap16( -( (Int16)length ) );
else
fStream->WriteSwap32( -length );
fStream->Write( length, newData );
}
//// Copy ////////////////////////////////////////////////////////////////////
// Copy() appends a Copy-Data-From-Old operation to the diff buffer.
void plDiffBuffer::Copy( Int32 length, UInt32 oldOffset )
{
hsAssert( fWriting, "Trying to Copy() to a difference buffer that's reading" );
// We flag our two different op types by the sign of the length. Negative
// lengths are an add operation, positive ones are copy ops.
if( f16BitMode )
{
fStream->WriteSwap16( (Int16)length );
fStream->WriteSwap16( (UInt16)oldOffset );
}
else
{
fStream->WriteSwap32( length );
fStream->WriteSwap32( oldOffset );
}
}
//// GetBuffer ///////////////////////////////////////////////////////////////
// GetBuffer() will copy the diff stream into a new buffer and return it.
// You are responsible for freeing the buffer. Call this once you're done
// adding ops and want the raw data to write out somewhere. Note: this
// function will rewind the diff stream, so once you call it, you can't do
// anything else on the object.
void plDiffBuffer::GetBuffer( UInt32 &length, void *&bufferPtr )
{
hsAssert( fWriting, "Trying to GetBuffer() on a difference buffer that's reading" );
length = fStream->GetPosition();
bufferPtr = (void *)TRACKED_NEW UInt8[ length ];
fStream->Rewind();
fStream->Read( length, bufferPtr );
}
//////////////////////////////////////////////////////////////////////////////
//// Application Functions ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Apply ///////////////////////////////////////////////////////////////////
// Apply() will take this diff buffer and apply it to the given old buffer,
// allocating and producing a new buffer. You are responsible for freeing
// the new buffer.
#define hsAssertAndBreak( cond, msg ) { if( cond ) { hsAssert( false, msg ); break; } }
void plDiffBuffer::Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer )
{
hsAssert( !fWriting, "Trying to Apply() a difference buffer that's writing" );
// Is this is a BSDiff patch, use plBSDiffBuffer and return.
if (fIsBSDiff)
{
fBSDiffBuffer->Apply(oldLength, oldBuffer, newLength, newBuffer);
return;
}
/// Step 1: Allocate the new buffer
newLength = fNewLength;
UInt8 *new8Buffer = TRACKED_NEW UInt8[ newLength ];
UInt8 *old8Buffer = (UInt8 *)oldBuffer;
newBuffer = (void *)new8Buffer;
/// Step 2: Loop through the difference stream
Int32 opLength;
UInt32 newBufferPos = 0;
while( newBufferPos < newLength )
{
// Read in the op length
if( f16BitMode )
{
Int16 opLen16 = fStream->ReadSwap16();
if( opLen16 < 0 )
opLength = -( (Int32)( -opLen16 ) );
else
opLength = (UInt32)opLen16;
}
else
opLength = fStream->ReadSwap32();
// As defined, negative ops are add ops, positive ones are copys
if( opLength < 0 )
{
hsAssertAndBreak( newBufferPos - opLength > newLength, "Destination buffer offset in plDiffBuffer() is out of range!" );
// Add op, read in the added data
fStream->Read( -opLength, &new8Buffer[ newBufferPos ] );
newBufferPos += -opLength;
}
else
{
// Copy op, so get the old offset and copy from there
UInt32 oldOffset = f16BitMode ? fStream->ReadSwap16() : fStream->ReadSwap32();
hsAssertAndBreak( newBufferPos + opLength > newLength, "Destination buffer offset in plDiffBuffer() is out of range!" );
hsAssertAndBreak( oldOffset + opLength > oldLength, "Difference buffer offset in plDiffBuffer() is out of range of the old buffer!" );
memcpy( &new8Buffer[ newBufferPos ], old8Buffer + oldOffset, opLength );
newBufferPos += opLength;
}
}
hsAssert( newBufferPos == newLength, "Invalid sequence of difference ops in plDiffBuffer::Apply()" );
}
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// (specifically, adds and copys) that will modify an old
// data buffer to match a new one. It's a useful utility
// class when doing binary file patching, for example, as you
// can write out the changes to this class, get back a data
// buffer suitable for writing, then use this class again
// later to reconstruct the new buffer.
//
//// History /////////////////////////////////////////////////////////////////
//
// 7.24.2002 mcn - Created (Happy late b-day to me!)
//
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plDiffBuffer.h"
#include "plBSDiffBuffer.h"
#include "hsUtils.h"
#include "hsStream.h"
//////////////////////////////////////////////////////////////////////////////
//// Constructor/Destructors /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Creation Constructor ////////////////////////////////////////////////////
// Use this constructor when creating a new diff buffer. Pass in the length
// of the final new buffer. You don't need to pass in the length of the old
// buffer, but if you do, it'll help this class do some internal space
// optimization.
plDiffBuffer::plDiffBuffer( UInt32 newLength, UInt32 oldLength )
: fBSDiffBuffer( nil )
, fIsBSDiff( false )
{
// Basically, if the new and old lengths can both fit into 16 bits
// (not including a potential negation), then we can store all the
// segment info as 16-bit values instead of 32.
if( oldLength > 0 && oldLength < 32767 && newLength < 32767 )
f16BitMode = true;
else
f16BitMode = false;
fNewLength = newLength;
fStream = TRACKED_NEW hsRAMStream();
fStream->WriteSwap32( fNewLength );
fStream->WriteBool( f16BitMode );
fWriting = true;
}
//// Application Constructor /////////////////////////////////////////////////
// Use this constructor when taking a diff buffer and applying it to an old
// buffer. Pass in a pointer to the diff buffer and its length. The buffer
// will be copied, so you don't need to keep it around after you construct
// this object.
plDiffBuffer::plDiffBuffer( void *buffer, UInt32 length )
: fBSDiffBuffer( nil )
, fStream( nil )
, fIsBSDiff( false )
, fWriting( false )
{
// Check to see if this uses the newer BSDiff format
if ( buffer && length > 32 &&
memcmp(buffer,"BSDIFF40",8)==0 )
{
// This is a bsdiff buffer. Use plBSDiffBuffer to handle it.
fBSDiffBuffer = TRACKED_NEW plBSDiffBuffer(buffer, length);
fIsBSDiff = true;
}
else
{
fStream = TRACKED_NEW hsRAMStream();
fStream->Write( length, buffer );
fStream->Rewind();
fNewLength = fStream->ReadSwap32();
f16BitMode = fStream->ReadBool();
}
}
plDiffBuffer::~plDiffBuffer()
{
if (fStream)
delete fStream;
if (fBSDiffBuffer)
delete fBSDiffBuffer;
}
//////////////////////////////////////////////////////////////////////////////
//// Creation/Write Functions ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Add /////////////////////////////////////////////////////////////////////
// Add() appends an Add-New-Data operation to the diff buffer. The data
// supplied will be copied internally, so you can discard it after you call
// this function.
void plDiffBuffer::Add( Int32 length, void *newData )
{
hsAssert( fWriting, "Trying to Add() to a difference buffer that's reading" );
// We flag our two different op types by the sign of the length. Negative
// lengths are an add operation, positive ones are copy ops.
if( f16BitMode )
fStream->WriteSwap16( -( (Int16)length ) );
else
fStream->WriteSwap32( -length );
fStream->Write( length, newData );
}
//// Copy ////////////////////////////////////////////////////////////////////
// Copy() appends a Copy-Data-From-Old operation to the diff buffer.
void plDiffBuffer::Copy( Int32 length, UInt32 oldOffset )
{
hsAssert( fWriting, "Trying to Copy() to a difference buffer that's reading" );
// We flag our two different op types by the sign of the length. Negative
// lengths are an add operation, positive ones are copy ops.
if( f16BitMode )
{
fStream->WriteSwap16( (Int16)length );
fStream->WriteSwap16( (UInt16)oldOffset );
}
else
{
fStream->WriteSwap32( length );
fStream->WriteSwap32( oldOffset );
}
}
//// GetBuffer ///////////////////////////////////////////////////////////////
// GetBuffer() will copy the diff stream into a new buffer and return it.
// You are responsible for freeing the buffer. Call this once you're done
// adding ops and want the raw data to write out somewhere. Note: this
// function will rewind the diff stream, so once you call it, you can't do
// anything else on the object.
void plDiffBuffer::GetBuffer( UInt32 &length, void *&bufferPtr )
{
hsAssert( fWriting, "Trying to GetBuffer() on a difference buffer that's reading" );
length = fStream->GetPosition();
bufferPtr = (void *)TRACKED_NEW UInt8[ length ];
fStream->Rewind();
fStream->Read( length, bufferPtr );
}
//////////////////////////////////////////////////////////////////////////////
//// Application Functions ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Apply ///////////////////////////////////////////////////////////////////
// Apply() will take this diff buffer and apply it to the given old buffer,
// allocating and producing a new buffer. You are responsible for freeing
// the new buffer.
#define hsAssertAndBreak( cond, msg ) { if( cond ) { hsAssert( false, msg ); break; } }
void plDiffBuffer::Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer )
{
hsAssert( !fWriting, "Trying to Apply() a difference buffer that's writing" );
// Is this is a BSDiff patch, use plBSDiffBuffer and return.
if (fIsBSDiff)
{
fBSDiffBuffer->Apply(oldLength, oldBuffer, newLength, newBuffer);
return;
}
/// Step 1: Allocate the new buffer
newLength = fNewLength;
UInt8 *new8Buffer = TRACKED_NEW UInt8[ newLength ];
UInt8 *old8Buffer = (UInt8 *)oldBuffer;
newBuffer = (void *)new8Buffer;
/// Step 2: Loop through the difference stream
Int32 opLength;
UInt32 newBufferPos = 0;
while( newBufferPos < newLength )
{
// Read in the op length
if( f16BitMode )
{
Int16 opLen16 = fStream->ReadSwap16();
if( opLen16 < 0 )
opLength = -( (Int32)( -opLen16 ) );
else
opLength = (UInt32)opLen16;
}
else
opLength = fStream->ReadSwap32();
// As defined, negative ops are add ops, positive ones are copys
if( opLength < 0 )
{
hsAssertAndBreak( newBufferPos - opLength > newLength, "Destination buffer offset in plDiffBuffer() is out of range!" );
// Add op, read in the added data
fStream->Read( -opLength, &new8Buffer[ newBufferPos ] );
newBufferPos += -opLength;
}
else
{
// Copy op, so get the old offset and copy from there
UInt32 oldOffset = f16BitMode ? fStream->ReadSwap16() : fStream->ReadSwap32();
hsAssertAndBreak( newBufferPos + opLength > newLength, "Destination buffer offset in plDiffBuffer() is out of range!" );
hsAssertAndBreak( oldOffset + opLength > oldLength, "Difference buffer offset in plDiffBuffer() is out of range of the old buffer!" );
memcpy( &new8Buffer[ newBufferPos ], old8Buffer + oldOffset, opLength );
newBufferPos += opLength;
}
}
hsAssert( newBufferPos == newLength, "Invalid sequence of difference ops in plDiffBuffer::Apply()" );
}

View File

@ -1,103 +1,103 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// (specifically, adds and copys) that will modify an old
// data buffer to match a new one. It's a useful utility
// class when doing binary file patching, for example, as you
// can write out the changes to this class, get back a data
// buffer suitable for writing, then use this class again
// later to reconstruct the new buffer.
//
// This class is meant to construct diff buffers using two
// ops: add and copy. Basically, the syntax is defined so
// that to reconstruct the new buffer, you run through the
// list of ops sequentially, each one defining the next
// chunk of data in the new buffer. Add ops will add new data
// to the buffer that didn't exist in the old buffer, and
// copy ops will copy data that existed in the old buffer
// (from an arbitrary offset, to facilitate encoding data
// shuffling). Delete ops are implicit, as they simply aren't
// defined in the stream of ops.
//
//// History /////////////////////////////////////////////////////////////////
//
// 7.24.2002 mcn - Created (Happy late b-day to me!)
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDiffBuffer_h
#define _plDiffBuffer_h
#include "hsTypes.h"
#include "hsStream.h"
//// Class Definition ////////////////////////////////////////////////////////
class hsRAMStream;
class plBSDiffBuffer;
class plDiffBuffer
{
protected:
hsBool fWriting, f16BitMode;
UInt32 fNewLength;
hsRAMStream *fStream;
// Support for BSDiff patch buffers (Patching only)
plBSDiffBuffer *fBSDiffBuffer;
hsBool fIsBSDiff;
public:
plDiffBuffer( UInt32 newLength, UInt32 oldLength = 0 ); // Constructor for writing new buffers. oldLength isn't required but helpful for optimizations
plDiffBuffer( void *buffer, UInt32 length ); // Constructor for applying a given diff set
// to an old buffer
virtual ~plDiffBuffer();
/// Creation/write functions
// Add() appends an Add-New-Data operation to the diff buffer. The data supplied will be copied internally.
void Add( Int32 length, void *newData );
// Copy() appends a Copy-Data-From-Old operation to the diff buffer
void Copy( Int32 length, UInt32 oldOffset );
// GetBuffer() will copy the diff stream into a new buffer and return it. You are responsible for freeing the buffer.
void GetBuffer( UInt32 &length, void *&bufferPtr );
/// Apply functions
// Apply() will take this diff buffer and apply it to the given old buffer, allocating and producing a new buffer. You are responsible for freeing the new buffer.
void Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer );
};
#endif // _plDiffBuffer_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plDiffBuffer - A utility class for writing and applying a difference
// buffer--i.e. a buffer containing a series of modifications
// (specifically, adds and copys) that will modify an old
// data buffer to match a new one. It's a useful utility
// class when doing binary file patching, for example, as you
// can write out the changes to this class, get back a data
// buffer suitable for writing, then use this class again
// later to reconstruct the new buffer.
//
// This class is meant to construct diff buffers using two
// ops: add and copy. Basically, the syntax is defined so
// that to reconstruct the new buffer, you run through the
// list of ops sequentially, each one defining the next
// chunk of data in the new buffer. Add ops will add new data
// to the buffer that didn't exist in the old buffer, and
// copy ops will copy data that existed in the old buffer
// (from an arbitrary offset, to facilitate encoding data
// shuffling). Delete ops are implicit, as they simply aren't
// defined in the stream of ops.
//
//// History /////////////////////////////////////////////////////////////////
//
// 7.24.2002 mcn - Created (Happy late b-day to me!)
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDiffBuffer_h
#define _plDiffBuffer_h
#include "hsTypes.h"
#include "hsStream.h"
//// Class Definition ////////////////////////////////////////////////////////
class hsRAMStream;
class plBSDiffBuffer;
class plDiffBuffer
{
protected:
hsBool fWriting, f16BitMode;
UInt32 fNewLength;
hsRAMStream *fStream;
// Support for BSDiff patch buffers (Patching only)
plBSDiffBuffer *fBSDiffBuffer;
hsBool fIsBSDiff;
public:
plDiffBuffer( UInt32 newLength, UInt32 oldLength = 0 ); // Constructor for writing new buffers. oldLength isn't required but helpful for optimizations
plDiffBuffer( void *buffer, UInt32 length ); // Constructor for applying a given diff set
// to an old buffer
virtual ~plDiffBuffer();
/// Creation/write functions
// Add() appends an Add-New-Data operation to the diff buffer. The data supplied will be copied internally.
void Add( Int32 length, void *newData );
// Copy() appends a Copy-Data-From-Old operation to the diff buffer
void Copy( Int32 length, UInt32 oldOffset );
// GetBuffer() will copy the diff stream into a new buffer and return it. You are responsible for freeing the buffer.
void GetBuffer( UInt32 &length, void *&bufferPtr );
/// Apply functions
// Apply() will take this diff buffer and apply it to the given old buffer, allocating and producing a new buffer. You are responsible for freeing the new buffer.
void Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer );
};
#endif // _plDiffBuffer_h

View File

@ -1,195 +1,195 @@
/*==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/>.
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==*/
#define plIndexFile_cpp // for version numbers in plVersion.h
#include "plIndexFile.h"
#include "hsStream.h"
#include "plVersion.h"
//--------------------
// plIndexFileHeader
//--------------------
plIndexFileHeader::plIndexFileHeader()
{
fTimeStamp[ 0 ] = fTimeStamp[ 1 ] = 0;
fStrTblStartPos = 0;
fStrTblKnt = 0;
fMajorVersion = plVersion::GetMajorVersion();
fMinorVersion = plVersion::GetMinorVersion();
fExportLocal = 0;
}
void plIndexFileHeader::Write(hsStream *s)
{
s->WriteSwap32(2,fTimeStamp);
s->WriteSwap32(fStrTblStartPos);
s->WriteSwap16(fStrTblKnt);
s->WriteSwap16(fMajorVersion);
s->WriteSwap16(fMinorVersion);
s->WriteSwap16(fExportLocal);
}
void plIndexFileHeader::Read(hsStream *s)
{
s->ReadSwap32(2,fTimeStamp);
fStrTblStartPos = s->ReadSwap32();
fStrTblKnt = s->ReadSwap16();
fMajorVersion = s->ReadSwap16();
fMinorVersion = s->ReadSwap16();
fExportLocal = s->ReadSwap16();
}
//--------------------
// plIndexFileRoom
//--------------------
void plIndexFileRoom::Write(hsStream *s)
{
fRmUoid.Write(s);
s->WriteSwap32(fTypesInRoom);
s->WriteSwap16(fFiller1_16);
s->WriteSwap32(fFiller2_32);
s->WriteSwap32(fFiller3_32);
}
void plIndexFileRoom::Read(hsStream *s)
{
fRmUoid.Read(s);
fTypesInRoom = s->ReadSwap32();
s->ReadSwap16();
s->ReadSwap32();
s->ReadSwap32();
}
//--------------------
// plIndexFileType
//--------------------
void plIndexFileType::Write(hsStream *s)
{
fTypeUoid.Write(s);
s->WriteSwap32(fNumKeys);
s->WriteSwap32(fFiller1_32);
s->WriteSwap32(fFiller2_32);
}
void plIndexFileType::Read(hsStream *s)
{
fTypeUoid.Read(s);
fNumKeys = s->ReadSwap32();
s->ReadSwap32();
s->ReadSwap32();
}
//--------------------
// plIndexFileKey
//--------------------
void plIndexFileKey::Write(hsStream *s)
{
fKeyUoid.Write(s);
s->WriteSwap32(fStartPos);
s->WriteSwap32(fDataLen);
s->WriteSwap16(fNameIx);
s->WriteSwap16(fFiller1_16);
}
void plIndexFileKey::Read(hsStream *s)
{
fKeyUoid.Read(s);
fStartPos = s->ReadSwap32();
fDataLen = s->ReadSwap32();
fNameIx = s->ReadSwap16();
s->ReadSwap16();
}
//--------------------
// plIxStrTbl
//--------------------
plIxStrTbl::~plIxStrTbl()
{
if (fpStrings) delete []fpStrings; // if strings came from elsewhere, not our responsibility
}
UInt16 plIxStrTbl::AddString(const char *p)
{ Int16 ix = FindString(p);
if (ix != -1)
return ix; // duplicate
fStringTbl.push_back(p); return fStringTbl.size() - 1;
}
Int16 plIxStrTbl::FindString(const char *p)
{
for (int i=0; i < fStringTbl.size(); i++)
{
if (!_stricmp(p,fStringTbl[i]))
return i;
}
return -1;
}
void plIxStrTbl::Write(hsStream *s)
{
for (int i=0; i < fStringTbl.size(); i++)
{ Int32 len= fStringTbl[i] ? strlen(fStringTbl[i]) : 0;
hsAssert(len < 256,"Name string too long");
UInt8 l = (UInt8) len;
s->WriteByte(l); // FUTURE, don't really need length!
if (len)
{
s->Write(len, fStringTbl[i]);
}
s->WriteByte(0); // Null terminate
}
}
void plIxStrTbl::Read(hsStream *s)
{ UInt32 pos = s->GetPosition();
s->FastFwd();
fTabSize = s->GetPosition() - pos; // Get size of table
s->SetPosition(pos);
fpStrings = new char[fTabSize];
hsAssert(fpStrings,"new failed");
s->Read(fTabSize,fpStrings); // Read all the string in
char *p = fpStrings;
while (p < fpStrings + fTabSize)
{
UInt8 len = *p;
p++;
hsAssert(p < fpStrings + fTabSize,"String Index error");
fStringTbl.push_back(p);
p += len + 1; // past len and NULL
};
}
/*==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/>.
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==*/
#define plIndexFile_cpp // for version numbers in plVersion.h
#include "plIndexFile.h"
#include "hsStream.h"
#include "plVersion.h"
//--------------------
// plIndexFileHeader
//--------------------
plIndexFileHeader::plIndexFileHeader()
{
fTimeStamp[ 0 ] = fTimeStamp[ 1 ] = 0;
fStrTblStartPos = 0;
fStrTblKnt = 0;
fMajorVersion = plVersion::GetMajorVersion();
fMinorVersion = plVersion::GetMinorVersion();
fExportLocal = 0;
}
void plIndexFileHeader::Write(hsStream *s)
{
s->WriteSwap32(2,fTimeStamp);
s->WriteSwap32(fStrTblStartPos);
s->WriteSwap16(fStrTblKnt);
s->WriteSwap16(fMajorVersion);
s->WriteSwap16(fMinorVersion);
s->WriteSwap16(fExportLocal);
}
void plIndexFileHeader::Read(hsStream *s)
{
s->ReadSwap32(2,fTimeStamp);
fStrTblStartPos = s->ReadSwap32();
fStrTblKnt = s->ReadSwap16();
fMajorVersion = s->ReadSwap16();
fMinorVersion = s->ReadSwap16();
fExportLocal = s->ReadSwap16();
}
//--------------------
// plIndexFileRoom
//--------------------
void plIndexFileRoom::Write(hsStream *s)
{
fRmUoid.Write(s);
s->WriteSwap32(fTypesInRoom);
s->WriteSwap16(fFiller1_16);
s->WriteSwap32(fFiller2_32);
s->WriteSwap32(fFiller3_32);
}
void plIndexFileRoom::Read(hsStream *s)
{
fRmUoid.Read(s);
fTypesInRoom = s->ReadSwap32();
s->ReadSwap16();
s->ReadSwap32();
s->ReadSwap32();
}
//--------------------
// plIndexFileType
//--------------------
void plIndexFileType::Write(hsStream *s)
{
fTypeUoid.Write(s);
s->WriteSwap32(fNumKeys);
s->WriteSwap32(fFiller1_32);
s->WriteSwap32(fFiller2_32);
}
void plIndexFileType::Read(hsStream *s)
{
fTypeUoid.Read(s);
fNumKeys = s->ReadSwap32();
s->ReadSwap32();
s->ReadSwap32();
}
//--------------------
// plIndexFileKey
//--------------------
void plIndexFileKey::Write(hsStream *s)
{
fKeyUoid.Write(s);
s->WriteSwap32(fStartPos);
s->WriteSwap32(fDataLen);
s->WriteSwap16(fNameIx);
s->WriteSwap16(fFiller1_16);
}
void plIndexFileKey::Read(hsStream *s)
{
fKeyUoid.Read(s);
fStartPos = s->ReadSwap32();
fDataLen = s->ReadSwap32();
fNameIx = s->ReadSwap16();
s->ReadSwap16();
}
//--------------------
// plIxStrTbl
//--------------------
plIxStrTbl::~plIxStrTbl()
{
if (fpStrings) delete []fpStrings; // if strings came from elsewhere, not our responsibility
}
UInt16 plIxStrTbl::AddString(const char *p)
{ Int16 ix = FindString(p);
if (ix != -1)
return ix; // duplicate
fStringTbl.push_back(p); return fStringTbl.size() - 1;
}
Int16 plIxStrTbl::FindString(const char *p)
{
for (int i=0; i < fStringTbl.size(); i++)
{
if (!_stricmp(p,fStringTbl[i]))
return i;
}
return -1;
}
void plIxStrTbl::Write(hsStream *s)
{
for (int i=0; i < fStringTbl.size(); i++)
{ Int32 len= fStringTbl[i] ? strlen(fStringTbl[i]) : 0;
hsAssert(len < 256,"Name string too long");
UInt8 l = (UInt8) len;
s->WriteByte(l); // FUTURE, don't really need length!
if (len)
{
s->Write(len, fStringTbl[i]);
}
s->WriteByte(0); // Null terminate
}
}
void plIxStrTbl::Read(hsStream *s)
{ UInt32 pos = s->GetPosition();
s->FastFwd();
fTabSize = s->GetPosition() - pos; // Get size of table
s->SetPosition(pos);
fpStrings = new char[fTabSize];
hsAssert(fpStrings,"new failed");
s->Read(fTabSize,fpStrings); // Read all the string in
char *p = fpStrings;
while (p < fpStrings + fTabSize)
{
UInt8 len = *p;
p++;
hsAssert(p < fpStrings + fTabSize,"String Index error");
fStringTbl.push_back(p);
p += len + 1; // past len and NULL
};
}

View File

@ -1,152 +1,152 @@
/*==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/>.
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 PLINDEXFILE_H
#define PLINDEXFILE_H
#include "../pnKeyedObject/plUoid.h"
#include <vector>
//---------------------------------------------------------------
// These Classes are used to Read and Write the Index file for the Database
// Records are kept the same size Currently 20 Bytes
// At the End of the file, the Strings are stored
// plIxStrTbl is used to Read and Write the String section of the Index
//---------------------------------------------------------------
//---------------------------------------------------------------
// Main header Entry, One per Index file
//---------------------------------------------------------------
class plIndexFileHeader
{
public:
plIndexFileHeader(); // I buried Paul
~plIndexFileHeader(){}
UInt32 fTimeStamp[2];
UInt32 fStrTblStartPos; // where the String table starts in the Index file
UInt16 fStrTblKnt; // how many strings in the string table
UInt16 fMajorVersion;
UInt16 fMinorVersion;
UInt16 fExportLocal; // was this file exported locally or downloaded from server?
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Room Entry One Entry per Room
//---------------------------------------------------------------
class plIndexFileRoom
{
public:
plIndexFileRoom() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileRoom(){}
plUoid fRmUoid;
UInt16 fTypesInRoom;
UInt16 fFiller1_16;
UInt32 fFiller2_32;
UInt32 fFiller3_32;
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Type Entry One Entry per Type in each Room
//---------------------------------------------------------------
class plIndexFileType
{
public:
plIndexFileType() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileType(){}
plUoid fTypeUoid;
UInt16 fNumKeys;
UInt32 fFiller1_32;
UInt32 fFiller2_32;
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Key Entry One Entry per Type in each Room
//---------------------------------------------------------------
class plIndexFileKey
{
public:
plIndexFileKey() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileKey(){}
plUoid fKeyUoid;
UInt32 fStartPos;
UInt32 fDataLen;
UInt16 fNameIx; // Index into string table of name
UInt16 fFiller1_16;
void Write(hsStream *s) ;
void Read(hsStream *s);
};
//---------------------------------------------------------------
// String Table, Lives at the end of the Index File
//---------------------------------------------------------------
class plIxStrTbl
{
std::vector<const char *>fStringTbl;
char *fpStrings;
UInt32 fTabSize; // buffer size for strings
public:
plIxStrTbl() :fpStrings(nil), fTabSize(0){}
~plIxStrTbl();
Int16 FindString(const char *p); // returns -1 if not found, otherwise the index from zero
UInt16 AddString(const char *p);
UInt16 NumStrings() { return fStringTbl.size(); }
const char * GetString(UInt16 x) { return fStringTbl[x]; }
void Write(hsStream *s);
void Read(hsStream *s);
};
class plLinkRecord
{
public:
plLinkRecord(UInt16 a, UInt16 d, UInt16 r) : fAgeIx(a), fDistIx(d), fRoomIx(r){}
~plLinkRecord(){}
UInt16 fAgeIx; // Index into string table
UInt16 fDistIx;
UInt16 fRoomIx;
UInt32 fTimeStamp[2];
};
#endif
/*==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/>.
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 PLINDEXFILE_H
#define PLINDEXFILE_H
#include "../pnKeyedObject/plUoid.h"
#include <vector>
//---------------------------------------------------------------
// These Classes are used to Read and Write the Index file for the Database
// Records are kept the same size Currently 20 Bytes
// At the End of the file, the Strings are stored
// plIxStrTbl is used to Read and Write the String section of the Index
//---------------------------------------------------------------
//---------------------------------------------------------------
// Main header Entry, One per Index file
//---------------------------------------------------------------
class plIndexFileHeader
{
public:
plIndexFileHeader(); // I buried Paul
~plIndexFileHeader(){}
UInt32 fTimeStamp[2];
UInt32 fStrTblStartPos; // where the String table starts in the Index file
UInt16 fStrTblKnt; // how many strings in the string table
UInt16 fMajorVersion;
UInt16 fMinorVersion;
UInt16 fExportLocal; // was this file exported locally or downloaded from server?
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Room Entry One Entry per Room
//---------------------------------------------------------------
class plIndexFileRoom
{
public:
plIndexFileRoom() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileRoom(){}
plUoid fRmUoid;
UInt16 fTypesInRoom;
UInt16 fFiller1_16;
UInt32 fFiller2_32;
UInt32 fFiller3_32;
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Type Entry One Entry per Type in each Room
//---------------------------------------------------------------
class plIndexFileType
{
public:
plIndexFileType() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileType(){}
plUoid fTypeUoid;
UInt16 fNumKeys;
UInt32 fFiller1_32;
UInt32 fFiller2_32;
void Write(hsStream *s);
void Read(hsStream *s);
};
//---------------------------------------------------------------
// Key Entry One Entry per Type in each Room
//---------------------------------------------------------------
class plIndexFileKey
{
public:
plIndexFileKey() { memset(this,1,sizeof(this)); } // no virtuals...relax
~plIndexFileKey(){}
plUoid fKeyUoid;
UInt32 fStartPos;
UInt32 fDataLen;
UInt16 fNameIx; // Index into string table of name
UInt16 fFiller1_16;
void Write(hsStream *s) ;
void Read(hsStream *s);
};
//---------------------------------------------------------------
// String Table, Lives at the end of the Index File
//---------------------------------------------------------------
class plIxStrTbl
{
std::vector<const char *>fStringTbl;
char *fpStrings;
UInt32 fTabSize; // buffer size for strings
public:
plIxStrTbl() :fpStrings(nil), fTabSize(0){}
~plIxStrTbl();
Int16 FindString(const char *p); // returns -1 if not found, otherwise the index from zero
UInt16 AddString(const char *p);
UInt16 NumStrings() { return fStringTbl.size(); }
const char * GetString(UInt16 x) { return fStringTbl[x]; }
void Write(hsStream *s);
void Read(hsStream *s);
};
class plLinkRecord
{
public:
plLinkRecord(UInt16 a, UInt16 d, UInt16 r) : fAgeIx(a), fDistIx(d), fRoomIx(r){}
~plLinkRecord(){}
UInt16 fAgeIx; // Index into string table
UInt16 fDistIx;
UInt16 fRoomIx;
UInt32 fTimeStamp[2];
};
#endif

View File

@ -1,498 +1,498 @@
/*==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/>.
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==*/
#include "plKeyFinder.h"
#include "hsTemplates.h"
#include "hsStlUtils.h"
#include "hsResMgr.h"
#include "plResManager.h"
#include "plRegistryHelpers.h"
#include "plRegistryNode.h"
#include "plRegistryKeyList.h"
#include "plPageInfo.h"
#include "pnFactory/plFactory.h"
#include "hsUtils.h"
#include "plCreatableIndex.h"
plResManager* IGetResMgr() { return (plResManager*)hsgResMgr::ResMgr(); }
plKeyFinder& plKeyFinder::Instance()
{
static plKeyFinder theInstance;
return theInstance;
}
const char* plKeyFinder::GetLastErrorString() // For Console display
{
// For Console display
static const char* KeyFinderErrors[] =
{
"Ok",
"Age not found",
"Page not found",
"Invalid class",
"None of those classes in this page",
"Object not found"
};
return KeyFinderErrors[fLastError];
}
//
// Does name string compare with potentially mangled (ie. [1 0 0]foo) names
//
hsBool NameMatches(const char* obName, const char* pKName, hsBool subString)
{
if (!obName || !pKName)
return false;
const char *o = obName;
const char *p = pKName;
// If names are mangled, unmangle
if (*o != '[' || *p != '[')
{
// skip past ']' in both names in case mangled
while (*o && *o != ']')
o++;
o = (*o==']') ? o+1 : obName;
while (*p && *p != ']')
p++;
p = (*p==']') ? p+1 : pKName;
}
if (!subString)
{
if (!_stricmp(o, p))
return true; // FOUND IT!!!!!!!!!!!!!!!!!!!
}
else
{
char oCopy[256], pCopy[256];
strcpy(oCopy, o);
strcpy(pCopy, p);
hsStrLower(oCopy);
hsStrLower(pCopy);
if (strstr(pCopy, oCopy))
return true;
}
return false;
}
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
const char *className, const char *obName, hsBool subString)
{
UInt16 ty = plFactory::FindClassIndex(className);
return StupidSearch(age, rm, ty, obName, subString);
}
class plKeyFinderIter : public plRegistryKeyIterator, public plRegistryPageIterator
{
protected:
UInt16 fClassType;
const char *fObjName;
hsBool fSubstr;
plKey fFoundKey;
const char *fAgeName;
public:
plKey GetFoundKey( void ) const { return fFoundKey; }
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr )
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ) { }
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr, const char *ageName )
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ),
fAgeName( ageName ) {}
virtual hsBool EatKey( const plKey& key )
{
if( key->GetUoid().GetClassType() == fClassType &&
NameMatches( fObjName, key->GetUoid().GetObjectName(), fSubstr ) )
{
fFoundKey = key;
return false;
}
return true;
}
virtual hsBool EatPage( plRegistryPageNode *pageNode )
{
#ifndef _DEBUG
try
{
#endif
if( stricmp( pageNode->GetPageInfo().GetAge(), fAgeName ) == 0 )
{
// Try loading and searching thru this page
hsTArray<plKey> keyRefs;
IGetResMgr()->LoadPageKeys( pageNode );
plKeyCollector coll( keyRefs );
pageNode->IterateKeys( &coll );
if( !pageNode->IterateKeys( this ) )
return false;
}
#ifndef _DEBUG
} catch (...)
{
}
#endif
return true;
}
};
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
UInt16 classType, const char *obName, hsBool subString)
{
if (!obName)
return nil;
plUoid newOid;
fLastError = kOk;
UInt16 maxClasses = plFactory::GetNumClasses();
UInt16 ty = classType;
if (ty == maxClasses) // error
{ fLastError = kInvalidClass;
return nil;
}
if( age != nil && rm != nil )
{
const plLocation &loc = IGetResMgr()->FindLocation( age, rm );
if( !loc.IsValid() )
{
fLastError = kPageNotFound;
return nil;
}
plKeyFinderIter keyFinder( classType, obName, subString );
if( !IGetResMgr()->IterateKeys( &keyFinder, loc ) )
// Return value of false means it stopped somewhere, i.e. found something
return keyFinder.GetFoundKey();
}
else if( age != nil )
{
plKeyFinderIter keyFinder(classType, obName, subString, age);
if( !IGetResMgr()->IterateAllPages( &keyFinder ) )
return keyFinder.GetFoundKey();
}
else
{
plKeyFinderIter keyFinder( classType, obName, subString );
if( !IGetResMgr()->IterateKeys( &keyFinder ) )
// Return value of false means it stopped somewhere, i.e. found something
return keyFinder.GetFoundKey();
}
fLastError = kObjectNotFound;
return nil;
}
void plKeyFinder::ReallyStupidResponderSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
{
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plResponderModifier), foundKeys, hintLocation);
}
void plKeyFinder::ReallyStupidActivatorSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation)
{
// use the createable macro so we don't have to pull in all of Python
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plLogicModifier), foundKeys, hintLocation);
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plPythonFileMod), foundKeys, hintLocation);
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plSittingModifier), foundKeys, hintLocation);
}
void plKeyFinder::IGetNames(std::vector<std::string>& names, const char* searchName, int index)
{
// Not really searching for any particular key, just need all the logic mods
std::vector<plKey> keys;
ReallyStupidSubstringSearch(searchName, index, keys);
for (int i = 0; i < keys.size(); i++)
{
// Only allow loaded ones to cut down on the crap
plKey key = keys[i];
if (key->ObjectIsLoaded())
names.push_back(key->GetName());
}
}
void plKeyFinder::GetResponderNames(std::vector<std::string>& names)
{
IGetNames(names, "", CLASS_INDEX_SCOPED(plResponderModifier));
}
void plKeyFinder::GetActivatorNames(std::vector<std::string>& names)
{
IGetNames(names, "", CLASS_INDEX_SCOPED(plLogicModifier));
}
class plKeyFinderIterator : public plRegistryKeyIterator, public plRegistryPageIterator
{
protected:
UInt16 fClassType;
const char *fObjName;
std::vector<plKey> &fFoundKeys;
public:
plKeyFinderIterator( UInt16 classType, const char *obName, std::vector<plKey>& foundKeys )
: fClassType( classType ), fObjName( obName ), fFoundKeys( foundKeys ) { }
virtual hsBool EatKey( const plKey& key )
{
if( key->GetUoid().IsValid() && key->GetUoid().GetClassType() == fClassType &&
strstr( key->GetUoid().GetObjectName(), fObjName ) )
{
fFoundKeys.push_back( key );
}
return true;
}
virtual hsBool EatPage( plRegistryPageNode *page )
{
hsBool ret = page->IterateKeys( this );
return ret;
}
};
void plKeyFinder::ReallyStupidSubstringSearch(const char *name, UInt16 objType, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
{
if (!name)
return;
plKeyFinderIterator collector( objType, name, foundKeys );
if( hintLocation.IsValid() )
{
plRegistryPageNode *hintPage = IGetResMgr()->FindPage( hintLocation );
if( hintPage != nil )
{
// Try all pages in the same age as that page
IGetResMgr()->IteratePages( &collector, hintPage->GetPageInfo().GetAge() );
}
if (foundKeys.size() > 0)
{
return;
}
}
//fpReg->IterateKeys( &collector );
IGetResMgr()->IterateAllPages( &collector );
}
//// Helper Class for FindSceneNodeKey ///////////////////////////////////////
class plPageFinder : public plRegistryPageIterator
{
protected:
plRegistryPageNode **fPagePtr;
const char *fFindString, *fAgeString;
public:
plPageFinder( plRegistryPageNode **page, const char *find ) : fPagePtr( page ), fFindString( find ), fAgeString( nil )
{ *fPagePtr = nil; }
plPageFinder( plRegistryPageNode **page, const char *ageS, const char *pageS ) : fPagePtr( page ), fFindString( pageS ), fAgeString( ageS )
{ *fPagePtr = nil; }
virtual hsBool EatPage( plRegistryPageNode *node )
{
static char str[ 512 ];
const plPageInfo &info = node->GetPageInfo();
// Are we searching by age/page?
if( fAgeString != nil )
{
if( stricmp( info.GetAge(), fAgeString ) == 0 &&
stricmp( info.GetPage(), fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
return true;
}
// Try for page only
if( stricmp( info.GetPage(), fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
// Try for full location
sprintf( str, "%s_%s_%s", info.GetAge(), info.GetPage() );
if( stricmp( str, fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
return true; // Keep searching
}
};
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// Given a string for either a page name or a fully qualified location name,
// finds the page and then returns the key for the sceneNode in that page.
// Note: in our case, we want to force the page's keys to load if necessary,
// since the only time we call this function will be to actually load
// the darned thing.
plKey plKeyFinder::FindSceneNodeKey( const char *pageOrFullLocName ) const
{
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, pageOrFullLocName );
// Use our own page finder, since we want to do nifty things like partial
// matches, etc.
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
return nil;
return IFindSceneNodeKey( pageNode );
}
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// Age/page pair version
plKey plKeyFinder::FindSceneNodeKey( const char *ageName, const char *pageName ) const
{
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, ageName, pageName );
// Use our own page finder, since we want to do nifty things like partial
// matches, etc.
if (IGetResMgr()->IterateAllPages(&pageFinder) || pageNode == nil)
return nil;
return IFindSceneNodeKey( pageNode );
}
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// plLocation version
plKey plKeyFinder::FindSceneNodeKey(const plLocation& location) const
{
plRegistryPageNode* pageNode = IGetResMgr()->FindPage(location);
if (pageNode == nil)
return nil;
return IFindSceneNodeKey(pageNode);
}
//// IFindSceneNodeKey ///////////////////////////////////////////////////////
plKey plKeyFinder::IFindSceneNodeKey(plRegistryPageNode* page) const
{
// Got the pageNode, try a find before loading
plRegistryKeyList* keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
if (keyList)
{
if (keyList->fStaticKeys.size() == 1)
{
return plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
}
else if (keyList->fDynamicKeys.size() == 1) // happens during export
{
plRegistryKeyList::DynSet::const_iterator it = keyList->fDynamicKeys.begin();
plKeyImp* keyImp = *it;
return plKey::Make(keyImp);
}
}
// Try loading and see if that helps
if (page->IsFullyLoaded())
return nil;
IGetResMgr()->LoadPageKeys(page);
// Get the list of all sceneNodes
plKey retVal(nil);
keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
if (keyList && keyList->fStaticKeys.size() == 1)
{
retVal = plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
}
// If we just loaded up all the keys for this page, then we
// may have a bunch of keys with a refcount of 0. For any of
// these keys that nothing else refs (yes, we have unused objects
// in the data), they don't get deleted because the refcount never
// rises above zero or falls back to zero. So we'll go ahead and
// ref and unref all of them. The ones in use stay put, the ones
// not being used go away. This is less than ideal.
IGetResMgr()->DumpUnusedKeys(page);
return retVal;
}
//// FindLocation ////////////////////////////////////////////////////////////
const plLocation &plKeyFinder::FindLocation( const char *age, const char *page ) const
{
if (age == nil)
{
static plLocation invalidLoc;
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, page );
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
return invalidLoc;
return pageNode->GetPageInfo().GetLocation();
}
return IGetResMgr()->FindLocation( age, page );
}
//// GetLocationInfo /////////////////////////////////////////////////////////
const plPageInfo* plKeyFinder::GetLocationInfo( const plLocation &loc ) const
{
plRegistryPageNode *node = IGetResMgr()->FindPage( loc );
if (node)
return &node->GetPageInfo();
else
return nil;
}
/*==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/>.
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==*/
#include "plKeyFinder.h"
#include "hsTemplates.h"
#include "hsStlUtils.h"
#include "hsResMgr.h"
#include "plResManager.h"
#include "plRegistryHelpers.h"
#include "plRegistryNode.h"
#include "plRegistryKeyList.h"
#include "plPageInfo.h"
#include "pnFactory/plFactory.h"
#include "hsUtils.h"
#include "plCreatableIndex.h"
plResManager* IGetResMgr() { return (plResManager*)hsgResMgr::ResMgr(); }
plKeyFinder& plKeyFinder::Instance()
{
static plKeyFinder theInstance;
return theInstance;
}
const char* plKeyFinder::GetLastErrorString() // For Console display
{
// For Console display
static const char* KeyFinderErrors[] =
{
"Ok",
"Age not found",
"Page not found",
"Invalid class",
"None of those classes in this page",
"Object not found"
};
return KeyFinderErrors[fLastError];
}
//
// Does name string compare with potentially mangled (ie. [1 0 0]foo) names
//
hsBool NameMatches(const char* obName, const char* pKName, hsBool subString)
{
if (!obName || !pKName)
return false;
const char *o = obName;
const char *p = pKName;
// If names are mangled, unmangle
if (*o != '[' || *p != '[')
{
// skip past ']' in both names in case mangled
while (*o && *o != ']')
o++;
o = (*o==']') ? o+1 : obName;
while (*p && *p != ']')
p++;
p = (*p==']') ? p+1 : pKName;
}
if (!subString)
{
if (!_stricmp(o, p))
return true; // FOUND IT!!!!!!!!!!!!!!!!!!!
}
else
{
char oCopy[256], pCopy[256];
strcpy(oCopy, o);
strcpy(pCopy, p);
hsStrLower(oCopy);
hsStrLower(pCopy);
if (strstr(pCopy, oCopy))
return true;
}
return false;
}
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
const char *className, const char *obName, hsBool subString)
{
UInt16 ty = plFactory::FindClassIndex(className);
return StupidSearch(age, rm, ty, obName, subString);
}
class plKeyFinderIter : public plRegistryKeyIterator, public plRegistryPageIterator
{
protected:
UInt16 fClassType;
const char *fObjName;
hsBool fSubstr;
plKey fFoundKey;
const char *fAgeName;
public:
plKey GetFoundKey( void ) const { return fFoundKey; }
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr )
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ) { }
plKeyFinderIter( UInt16 classType, const char *obName, hsBool substr, const char *ageName )
: fFoundKey( nil ), fClassType( classType ), fObjName( obName ), fSubstr( substr ),
fAgeName( ageName ) {}
virtual hsBool EatKey( const plKey& key )
{
if( key->GetUoid().GetClassType() == fClassType &&
NameMatches( fObjName, key->GetUoid().GetObjectName(), fSubstr ) )
{
fFoundKey = key;
return false;
}
return true;
}
virtual hsBool EatPage( plRegistryPageNode *pageNode )
{
#ifndef _DEBUG
try
{
#endif
if( stricmp( pageNode->GetPageInfo().GetAge(), fAgeName ) == 0 )
{
// Try loading and searching thru this page
hsTArray<plKey> keyRefs;
IGetResMgr()->LoadPageKeys( pageNode );
plKeyCollector coll( keyRefs );
pageNode->IterateKeys( &coll );
if( !pageNode->IterateKeys( this ) )
return false;
}
#ifndef _DEBUG
} catch (...)
{
}
#endif
return true;
}
};
plKey plKeyFinder::StupidSearch(const char * age, const char * rm,
UInt16 classType, const char *obName, hsBool subString)
{
if (!obName)
return nil;
plUoid newOid;
fLastError = kOk;
UInt16 maxClasses = plFactory::GetNumClasses();
UInt16 ty = classType;
if (ty == maxClasses) // error
{ fLastError = kInvalidClass;
return nil;
}
if( age != nil && rm != nil )
{
const plLocation &loc = IGetResMgr()->FindLocation( age, rm );
if( !loc.IsValid() )
{
fLastError = kPageNotFound;
return nil;
}
plKeyFinderIter keyFinder( classType, obName, subString );
if( !IGetResMgr()->IterateKeys( &keyFinder, loc ) )
// Return value of false means it stopped somewhere, i.e. found something
return keyFinder.GetFoundKey();
}
else if( age != nil )
{
plKeyFinderIter keyFinder(classType, obName, subString, age);
if( !IGetResMgr()->IterateAllPages( &keyFinder ) )
return keyFinder.GetFoundKey();
}
else
{
plKeyFinderIter keyFinder( classType, obName, subString );
if( !IGetResMgr()->IterateKeys( &keyFinder ) )
// Return value of false means it stopped somewhere, i.e. found something
return keyFinder.GetFoundKey();
}
fLastError = kObjectNotFound;
return nil;
}
void plKeyFinder::ReallyStupidResponderSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
{
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plResponderModifier), foundKeys, hintLocation);
}
void plKeyFinder::ReallyStupidActivatorSearch(const char *name, std::vector<plKey>& foundKeys, const plLocation &hintLocation)
{
// use the createable macro so we don't have to pull in all of Python
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plLogicModifier), foundKeys, hintLocation);
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plPythonFileMod), foundKeys, hintLocation);
ReallyStupidSubstringSearch(name, CLASS_INDEX_SCOPED(plSittingModifier), foundKeys, hintLocation);
}
void plKeyFinder::IGetNames(std::vector<std::string>& names, const char* searchName, int index)
{
// Not really searching for any particular key, just need all the logic mods
std::vector<plKey> keys;
ReallyStupidSubstringSearch(searchName, index, keys);
for (int i = 0; i < keys.size(); i++)
{
// Only allow loaded ones to cut down on the crap
plKey key = keys[i];
if (key->ObjectIsLoaded())
names.push_back(key->GetName());
}
}
void plKeyFinder::GetResponderNames(std::vector<std::string>& names)
{
IGetNames(names, "", CLASS_INDEX_SCOPED(plResponderModifier));
}
void plKeyFinder::GetActivatorNames(std::vector<std::string>& names)
{
IGetNames(names, "", CLASS_INDEX_SCOPED(plLogicModifier));
}
class plKeyFinderIterator : public plRegistryKeyIterator, public plRegistryPageIterator
{
protected:
UInt16 fClassType;
const char *fObjName;
std::vector<plKey> &fFoundKeys;
public:
plKeyFinderIterator( UInt16 classType, const char *obName, std::vector<plKey>& foundKeys )
: fClassType( classType ), fObjName( obName ), fFoundKeys( foundKeys ) { }
virtual hsBool EatKey( const plKey& key )
{
if( key->GetUoid().IsValid() && key->GetUoid().GetClassType() == fClassType &&
strstr( key->GetUoid().GetObjectName(), fObjName ) )
{
fFoundKeys.push_back( key );
}
return true;
}
virtual hsBool EatPage( plRegistryPageNode *page )
{
hsBool ret = page->IterateKeys( this );
return ret;
}
};
void plKeyFinder::ReallyStupidSubstringSearch(const char *name, UInt16 objType, std::vector<plKey>& foundKeys, const plLocation &hintLocation )
{
if (!name)
return;
plKeyFinderIterator collector( objType, name, foundKeys );
if( hintLocation.IsValid() )
{
plRegistryPageNode *hintPage = IGetResMgr()->FindPage( hintLocation );
if( hintPage != nil )
{
// Try all pages in the same age as that page
IGetResMgr()->IteratePages( &collector, hintPage->GetPageInfo().GetAge() );
}
if (foundKeys.size() > 0)
{
return;
}
}
//fpReg->IterateKeys( &collector );
IGetResMgr()->IterateAllPages( &collector );
}
//// Helper Class for FindSceneNodeKey ///////////////////////////////////////
class plPageFinder : public plRegistryPageIterator
{
protected:
plRegistryPageNode **fPagePtr;
const char *fFindString, *fAgeString;
public:
plPageFinder( plRegistryPageNode **page, const char *find ) : fPagePtr( page ), fFindString( find ), fAgeString( nil )
{ *fPagePtr = nil; }
plPageFinder( plRegistryPageNode **page, const char *ageS, const char *pageS ) : fPagePtr( page ), fFindString( pageS ), fAgeString( ageS )
{ *fPagePtr = nil; }
virtual hsBool EatPage( plRegistryPageNode *node )
{
static char str[ 512 ];
const plPageInfo &info = node->GetPageInfo();
// Are we searching by age/page?
if( fAgeString != nil )
{
if( stricmp( info.GetAge(), fAgeString ) == 0 &&
stricmp( info.GetPage(), fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
return true;
}
// Try for page only
if( stricmp( info.GetPage(), fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
// Try for full location
sprintf( str, "%s_%s_%s", info.GetAge(), info.GetPage() );
if( stricmp( str, fFindString ) == 0 )
{
*fPagePtr = node;
return false;
}
return true; // Keep searching
}
};
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// Given a string for either a page name or a fully qualified location name,
// finds the page and then returns the key for the sceneNode in that page.
// Note: in our case, we want to force the page's keys to load if necessary,
// since the only time we call this function will be to actually load
// the darned thing.
plKey plKeyFinder::FindSceneNodeKey( const char *pageOrFullLocName ) const
{
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, pageOrFullLocName );
// Use our own page finder, since we want to do nifty things like partial
// matches, etc.
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
return nil;
return IFindSceneNodeKey( pageNode );
}
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// Age/page pair version
plKey plKeyFinder::FindSceneNodeKey( const char *ageName, const char *pageName ) const
{
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, ageName, pageName );
// Use our own page finder, since we want to do nifty things like partial
// matches, etc.
if (IGetResMgr()->IterateAllPages(&pageFinder) || pageNode == nil)
return nil;
return IFindSceneNodeKey( pageNode );
}
//// FindSceneNodeKey ////////////////////////////////////////////////////////
// plLocation version
plKey plKeyFinder::FindSceneNodeKey(const plLocation& location) const
{
plRegistryPageNode* pageNode = IGetResMgr()->FindPage(location);
if (pageNode == nil)
return nil;
return IFindSceneNodeKey(pageNode);
}
//// IFindSceneNodeKey ///////////////////////////////////////////////////////
plKey plKeyFinder::IFindSceneNodeKey(plRegistryPageNode* page) const
{
// Got the pageNode, try a find before loading
plRegistryKeyList* keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
if (keyList)
{
if (keyList->fStaticKeys.size() == 1)
{
return plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
}
else if (keyList->fDynamicKeys.size() == 1) // happens during export
{
plRegistryKeyList::DynSet::const_iterator it = keyList->fDynamicKeys.begin();
plKeyImp* keyImp = *it;
return plKey::Make(keyImp);
}
}
// Try loading and see if that helps
if (page->IsFullyLoaded())
return nil;
IGetResMgr()->LoadPageKeys(page);
// Get the list of all sceneNodes
plKey retVal(nil);
keyList = page->IGetKeyList(CLASS_INDEX_SCOPED(plSceneNode));
if (keyList && keyList->fStaticKeys.size() == 1)
{
retVal = plKey::Make((plKeyData*)keyList->fStaticKeys[0]);
}
// If we just loaded up all the keys for this page, then we
// may have a bunch of keys with a refcount of 0. For any of
// these keys that nothing else refs (yes, we have unused objects
// in the data), they don't get deleted because the refcount never
// rises above zero or falls back to zero. So we'll go ahead and
// ref and unref all of them. The ones in use stay put, the ones
// not being used go away. This is less than ideal.
IGetResMgr()->DumpUnusedKeys(page);
return retVal;
}
//// FindLocation ////////////////////////////////////////////////////////////
const plLocation &plKeyFinder::FindLocation( const char *age, const char *page ) const
{
if (age == nil)
{
static plLocation invalidLoc;
plRegistryPageNode *pageNode;
plPageFinder pageFinder( &pageNode, page );
if( IGetResMgr()->IterateAllPages( &pageFinder ) || pageNode == nil )
return invalidLoc;
return pageNode->GetPageInfo().GetLocation();
}
return IGetResMgr()->FindLocation( age, page );
}
//// GetLocationInfo /////////////////////////////////////////////////////////
const plPageInfo* plKeyFinder::GetLocationInfo( const plLocation &loc ) const
{
plRegistryPageNode *node = IGetResMgr()->FindPage( loc );
if (node)
return &node->GetPageInfo();
else
return nil;
}

View File

@ -1,106 +1,106 @@
/*==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/>.
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 plKeyFinder_h_inc
#define plKeyFinder_h_inc
//----------------------------
// plKeyFinder
//----------------------------
// provides a way to look up an object (via its plKey)
// Using strings. The should only be used at Program Init time or console use (cause its not fast)
// The error codes are remembered, and used for subsequent calls to GetLastErrorString(); which can
// be display to tell the user where he screwed up the input.
// If a key is not found it returns nil
//----------------------------
// EXAMPLE OF USE:
//----------------------------
//
// plKeyFinder *pFind = hsgResMgr::ResMgr()->GetKeyFinder();
// plKey pKey = pFind->StupidSearch("Global", "Globalx", "1", "plSceneNode", "1");
// if (!pKey)
// hsStatusMessage(pFind->GetLastErrorString());
// delete pFind;
//
//----------------------------
#include "hsTypes.h"
#include "pnKeyedObject/plKey.h"
#include "pnKeyedObject/plUoid.h"
#include "hsStlUtils.h"
#include <string>
class plLocation;
class plRegistryPageNode;
class plPageInfo;
class plKeyFinder
{
public:
enum eErrCodes
{
kOk,
kAgeNotFound,
kPageNotFound,
kInvalidClass,
kNoClassesInPage,
kObjectNotFound
};
static plKeyFinder& Instance();
// These are Stupid search because they just do string searchs on the objects.
plKey StupidSearch(const char * age, const char * rm, const char *className, const char *obName, hsBool subString=false);
plKey StupidSearch(const char * age, const char * rm, UInt16 objType, const char *obName, hsBool subString=false);
eErrCodes GetLastErrorCode() { return fLastError; }
const char* GetLastErrorString(); // For Console display
void ReallyStupidResponderSearch(const char* name, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void ReallyStupidActivatorSearch(const char* name, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void ReallyStupidSubstringSearch(const char* name, UInt16 objType, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void GetActivatorNames(std::vector<std::string>& names);
void GetResponderNames(std::vector<std::string>& names);
plKey FindSceneNodeKey(const char* pageOrFullLocName) const;
plKey FindSceneNodeKey(const char* ageName, const char* pageName) const;
plKey FindSceneNodeKey(const plLocation& location) const;
const plLocation& FindLocation(const char* age, const char* page) const;
const plPageInfo* GetLocationInfo(const plLocation& loc) const;
protected:
plKeyFinder() {}
void IGetNames(std::vector<std::string>& names, const char* name, int index);
plKey IFindSceneNodeKey(plRegistryPageNode* page) const;
eErrCodes fLastError;
};
#endif // plKeyFinder_h_inc
/*==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/>.
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 plKeyFinder_h_inc
#define plKeyFinder_h_inc
//----------------------------
// plKeyFinder
//----------------------------
// provides a way to look up an object (via its plKey)
// Using strings. The should only be used at Program Init time or console use (cause its not fast)
// The error codes are remembered, and used for subsequent calls to GetLastErrorString(); which can
// be display to tell the user where he screwed up the input.
// If a key is not found it returns nil
//----------------------------
// EXAMPLE OF USE:
//----------------------------
//
// plKeyFinder *pFind = hsgResMgr::ResMgr()->GetKeyFinder();
// plKey pKey = pFind->StupidSearch("Global", "Globalx", "1", "plSceneNode", "1");
// if (!pKey)
// hsStatusMessage(pFind->GetLastErrorString());
// delete pFind;
//
//----------------------------
#include "hsTypes.h"
#include "pnKeyedObject/plKey.h"
#include "pnKeyedObject/plUoid.h"
#include "hsStlUtils.h"
#include <string>
class plLocation;
class plRegistryPageNode;
class plPageInfo;
class plKeyFinder
{
public:
enum eErrCodes
{
kOk,
kAgeNotFound,
kPageNotFound,
kInvalidClass,
kNoClassesInPage,
kObjectNotFound
};
static plKeyFinder& Instance();
// These are Stupid search because they just do string searchs on the objects.
plKey StupidSearch(const char * age, const char * rm, const char *className, const char *obName, hsBool subString=false);
plKey StupidSearch(const char * age, const char * rm, UInt16 objType, const char *obName, hsBool subString=false);
eErrCodes GetLastErrorCode() { return fLastError; }
const char* GetLastErrorString(); // For Console display
void ReallyStupidResponderSearch(const char* name, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void ReallyStupidActivatorSearch(const char* name, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void ReallyStupidSubstringSearch(const char* name, UInt16 objType, std::vector<plKey>& foundKeys, const plLocation& hintLocation = plLocation::kInvalidLoc);
void GetActivatorNames(std::vector<std::string>& names);
void GetResponderNames(std::vector<std::string>& names);
plKey FindSceneNodeKey(const char* pageOrFullLocName) const;
plKey FindSceneNodeKey(const char* ageName, const char* pageName) const;
plKey FindSceneNodeKey(const plLocation& location) const;
const plLocation& FindLocation(const char* age, const char* page) const;
const plPageInfo* GetLocationInfo(const plLocation& loc) const;
protected:
plKeyFinder() {}
void IGetNames(std::vector<std::string>& names, const char* name, int index);
plKey IFindSceneNodeKey(plRegistryPageNode* page) const;
eErrCodes fLastError;
};
#endif // plKeyFinder_h_inc

View File

@ -1,75 +1,75 @@
/*==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/>.
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==*/
#include "plLoc.h"
#include "../pnKeyedObject/hsKeyedObject.h"
plLocFileParser::plLocFileParser(): fThrowBack(nil), fThrowBackLevel(0)
{ fpFile = fopen(LOCTXTFILE,"rt"); // NEED to figure out where to put this
}
int plLocFileParser::NextLine(char **pP)
{
int levelKnt=0;
*pP = 0;
// If someone previously threwback a line...use it...
if (ThrowBackAvailable())
{ *pP = fThrowBack;
int rtnLevel = fThrowBackLevel;
ClearThrowBack();
return rtnLevel;
}
// Get a New Line from the file
char str[512];
while(fgets(str,512 - 1,fpFile))
{
if (*str == '#') // indicates a missing file message, ignore
continue;
int len = strlen(str);
str[len - 1] = 0; // clobber new line
//----------------------------------------------
// If its the database file, remember the name, and skip it.
//----------------------------------------------
int i=0;
while (str[i] == '\t')
{ levelKnt++;
i++;
}
*pP = hsStrcpy(str + levelKnt); // Allocate a string copy, advance past TABS
return levelKnt;
}
return LOC_EOF;
}
/*==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/>.
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==*/
#include "plLoc.h"
#include "../pnKeyedObject/hsKeyedObject.h"
plLocFileParser::plLocFileParser(): fThrowBack(nil), fThrowBackLevel(0)
{ fpFile = fopen(LOCTXTFILE,"rt"); // NEED to figure out where to put this
}
int plLocFileParser::NextLine(char **pP)
{
int levelKnt=0;
*pP = 0;
// If someone previously threwback a line...use it...
if (ThrowBackAvailable())
{ *pP = fThrowBack;
int rtnLevel = fThrowBackLevel;
ClearThrowBack();
return rtnLevel;
}
// Get a New Line from the file
char str[512];
while(fgets(str,512 - 1,fpFile))
{
if (*str == '#') // indicates a missing file message, ignore
continue;
int len = strlen(str);
str[len - 1] = 0; // clobber new line
//----------------------------------------------
// If its the database file, remember the name, and skip it.
//----------------------------------------------
int i=0;
while (str[i] == '\t')
{ levelKnt++;
i++;
}
*pP = hsStrcpy(str + levelKnt); // Allocate a string copy, advance past TABS
return levelKnt;
}
return LOC_EOF;
}

View File

@ -1,64 +1,64 @@
/*==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/>.
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 PLLOC_H
#define PLLOC_H
#include "HeadSpin.h"
#include "hsUtils.h"
// Values for UOID, such as AGE, District Room
// Are kept in configuration file(s)
// Levels are defined by the number of TABS in front of a string.
const int LOC_EOF = -1;
// plLocFileParser Is a utility class used by plRegistry to Parse the Location.txt
// configuration file.
#if HS_BUILD_FOR_WIN32
#define LOCTXTFILE "c:\\Location.txt"
#else
#define LOCTXTFILE "./Location.txt"
#endif
class plLocFileParser
{
public:
plLocFileParser();
~plLocFileParser() { if (fpFile) fclose(fpFile); fpFile = 0; }
void ThrowBack(char *p,UInt8 lev) { fThrowBack = p; fThrowBackLevel = lev; }
void ClearThrowBack() { fThrowBack = NULL; fThrowBackLevel = 0; }
bool ThrowBackAvailable() { return (fThrowBack == NULL) ? false: true; }
int NextLine(char **pP); // returns an Allocated string in pP of next valid line, and Level #, or LOC_EOF
hsBool8 Ready() { return fpFile ? true: false; }
private:
FILE * fpFile;
char * fThrowBack; // If a line is not used, it can be thrown back...unget()
int fThrowBackLevel;
};
#endif
/*==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/>.
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 PLLOC_H
#define PLLOC_H
#include "HeadSpin.h"
#include "hsUtils.h"
// Values for UOID, such as AGE, District Room
// Are kept in configuration file(s)
// Levels are defined by the number of TABS in front of a string.
const int LOC_EOF = -1;
// plLocFileParser Is a utility class used by plRegistry to Parse the Location.txt
// configuration file.
#if HS_BUILD_FOR_WIN32
#define LOCTXTFILE "c:\\Location.txt"
#else
#define LOCTXTFILE "./Location.txt"
#endif
class plLocFileParser
{
public:
plLocFileParser();
~plLocFileParser() { if (fpFile) fclose(fpFile); fpFile = 0; }
void ThrowBack(char *p,UInt8 lev) { fThrowBack = p; fThrowBackLevel = lev; }
void ClearThrowBack() { fThrowBack = NULL; fThrowBackLevel = 0; }
bool ThrowBackAvailable() { return (fThrowBack == NULL) ? false: true; }
int NextLine(char **pP); // returns an Allocated string in pP of next valid line, and Level #, or LOC_EOF
hsBool8 Ready() { return fpFile ? true: false; }
private:
FILE * fpFile;
char * fThrowBack; // If a line is not used, it can be thrown back...unget()
int fThrowBackLevel;
};
#endif

View File

@ -1,244 +1,244 @@
/*==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/>.
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==*/
#include "hsTypes.h"
#include "plLocalization.h"
#include "plFile/plFileUtils.h"
#include "hsUtils.h"
plLocalization::Language plLocalization::fLanguage = plLocalization::kEnglish;
char* plLocalization::fLangTags[] =
{
"_eng", // kEnglish
"_fre", // kFrench
"_ger", // kGerman
"_spa", // kSpanish
"_ita", // kItalian
"_jpn" // kJapanese
};
const int kLangTagLen = 4;
char* plLocalization::fLangNames[] =
{
"English", // kEnglish
"French", // kFrench
"German", // kGerman
"Spanish", // kSpanish
"Italian", // kItalian
"Japanese" // kJapanese
};
bool plLocalization::fUsesUnicode[] =
{
false, // kEnglish
false, // kFrench
false, // kGerman
false, // kSpanish
false, // kItalian
true // kJapanese
};
plLocalization::encodingTypes plLocalization::fUnicodeEncoding[] =
{
Enc_Unencoded, // kEnglish
Enc_Unencoded, // kFrench
Enc_Unencoded, // kGerman
Enc_Unencoded, // kSpanish
Enc_Unencoded, // kItalian
Enc_UTF8, // kJapanese
};
hsBool plLocalization::IGetLocalized(const char* name, Language lang, char* localizedName)
{
const char* underscore = strrchr(name, '_');
if (underscore)
{
char langTag[kLangTagLen+1];
strncpy(langTag,underscore,kLangTagLen);
langTag[kLangTagLen] = '\0';
if (strncmp(langTag, fLangTags[kEnglish], kLangTagLen) == 0)
{
if (localizedName)
{
strcpy(localizedName, name);
int underscorePos = underscore - name;
memcpy(localizedName + underscorePos, fLangTags[lang], kLangTagLen);
}
return true;
}
}
return false;
}
hsBool plLocalization::ExportGetLocalized(const char* name, int lang, char* localizedName)
{
return IGetLocalized(name, Language(lang+1), localizedName) &&
plFileUtils::FileExists(localizedName);
}
std::string plLocalization::LocalToString(const std::vector<std::string> & localizedText)
{
std::string retVal = "";
for (int i=0; i<localizedText.size(); i++)
{
if (i > kNumLanguages-1)
break;
std::string langHeader = "$";
std::string langName = GetLanguageName((Language)i);
langHeader += langName.substr(0,2) + "$";
retVal += langHeader + localizedText[i];
}
return retVal;
}
std::vector<std::string> plLocalization::StringToLocal(const std::string & localizedText)
{
std::vector<std::string> retVal;
wchar_t *temp = hsStringToWString(localizedText.c_str());
std::wstring wLocalizedText = temp;
delete [] temp;
std::vector<std::wstring> wStringVector = StringToLocal(wLocalizedText);
int i;
for (i=0; i<wStringVector.size(); i++)
{
char *local = hsWStringToString(wStringVector[i].c_str());
std::string val = local;
delete [] local;
retVal.push_back(val);
}
return retVal;
}
std::vector<std::wstring> plLocalization::StringToLocal(const std::wstring & localizedText)
{
std::vector<std::wstring> tags;
std::vector<int> tagLocs;
std::vector<int> sortedTagLocs;
std::vector<std::wstring> retVal;
int i;
for (i=0; i<kNumLanguages; i++)
{
std::wstring tag = L"$";
std::string temp = GetLanguageName((Language)i);
wchar_t *wTemp = hsStringToWString(temp.c_str());
std::wstring langName = wTemp;
delete [] wTemp;
tag += langName.substr(0,2) + L"$";
tags.push_back(tag);
tagLocs.push_back(localizedText.find(tag));
sortedTagLocs.push_back(i);
retVal.push_back(L"");
}
for (i=0; i<kNumLanguages-1; i++)
{
for (int j=i; j<kNumLanguages; j++)
{
if (tagLocs[sortedTagLocs[i]] > tagLocs[sortedTagLocs[j]])
sortedTagLocs[i]^=sortedTagLocs[j]^=sortedTagLocs[i]^=sortedTagLocs[j]; // swap the contents (yes, it works)
}
}
// now sortedTagLocs has the indexes of tagLocs sorted from smallest loc to highest loc
hsBool noTags = true;
for (i=0; i<kNumLanguages; i++)
{
int lang = sortedTagLocs[i]; // the language we are extracting
if (tagLocs[lang] != -1)
{
noTags = false; // at least one tag was found in the text
int startLoc = tagLocs[lang] + tags[lang].length();
int endLoc;
if (i+1 == kNumLanguages)
endLoc = localizedText.length();
else
endLoc = tagLocs[sortedTagLocs[i+1]];
retVal[lang] = localizedText.substr(startLoc,endLoc-startLoc);
}
}
if (noTags)
retVal[0] = localizedText; // if no tags were in the text, we assume it to be English
return retVal;
}
#include "hsWindows.h"
void plLocalization::SetDefaultLanguage()
{
fLanguage = kEnglish;
#if 0 // disable all languages
#ifdef HS_BUILD_FOR_WIN32
HKEY hLocalKey = NULL;
HKEY hMSKey = NULL;
HKEY hWindowsKey = NULL;
HKEY hCurVerKey = NULL;
HKEY hUninstKey = NULL;
HKEY hUruKey = NULL;
#define RegOpen(key, retKey, subKeyName) RegOpenKeyEx(key, subKeyName, 0, KEY_READ, &retKey) == ERROR_SUCCESS
if (RegOpen(HKEY_LOCAL_MACHINE, hLocalKey, "software") &&
RegOpen(hLocalKey, hMSKey, "microsoft") &&
RegOpen(hMSKey, hWindowsKey, "windows") &&
RegOpen(hWindowsKey, hCurVerKey, "currentversion") &&
RegOpen(hCurVerKey, hUninstKey, "uninstall") &&
RegOpen(hUninstKey, hUruKey, "Uru - Ages Beyond Myst"))
{
char value[20];
DWORD bufsize = sizeof(value);
if (RegQueryValueEx(hUruKey, "Lang", NULL, NULL, (LPBYTE)value, &bufsize) == ERROR_SUCCESS)
{
if (hsStrEQ(value, "en"))
fLanguage = kEnglish;
else if (hsStrEQ(value, "fr"))
fLanguage = kFrench;
else if (hsStrEQ(value, "de"))
fLanguage = kGerman;
else if (hsStrEQ(value, "es"))
fLanguage = kSpanish;
else if (hsStrEQ(value, "it"))
fLanguage = kItalian;
else if (hsStrEQ(value, "jp"))
fLanguage = kJapanese;
else
fLanguage = kEnglish;
}
}
RegCloseKey(hLocalKey);
RegCloseKey(hMSKey);
RegCloseKey(hWindowsKey);
RegCloseKey(hCurVerKey);
RegCloseKey(hUninstKey);
RegCloseKey(hUruKey);
#endif // HS_BUILD_FOR_WIN32
#endif // 0
}
/*==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/>.
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==*/
#include "hsTypes.h"
#include "plLocalization.h"
#include "plFile/plFileUtils.h"
#include "hsUtils.h"
plLocalization::Language plLocalization::fLanguage = plLocalization::kEnglish;
char* plLocalization::fLangTags[] =
{
"_eng", // kEnglish
"_fre", // kFrench
"_ger", // kGerman
"_spa", // kSpanish
"_ita", // kItalian
"_jpn" // kJapanese
};
const int kLangTagLen = 4;
char* plLocalization::fLangNames[] =
{
"English", // kEnglish
"French", // kFrench
"German", // kGerman
"Spanish", // kSpanish
"Italian", // kItalian
"Japanese" // kJapanese
};
bool plLocalization::fUsesUnicode[] =
{
false, // kEnglish
false, // kFrench
false, // kGerman
false, // kSpanish
false, // kItalian
true // kJapanese
};
plLocalization::encodingTypes plLocalization::fUnicodeEncoding[] =
{
Enc_Unencoded, // kEnglish
Enc_Unencoded, // kFrench
Enc_Unencoded, // kGerman
Enc_Unencoded, // kSpanish
Enc_Unencoded, // kItalian
Enc_UTF8, // kJapanese
};
hsBool plLocalization::IGetLocalized(const char* name, Language lang, char* localizedName)
{
const char* underscore = strrchr(name, '_');
if (underscore)
{
char langTag[kLangTagLen+1];
strncpy(langTag,underscore,kLangTagLen);
langTag[kLangTagLen] = '\0';
if (strncmp(langTag, fLangTags[kEnglish], kLangTagLen) == 0)
{
if (localizedName)
{
strcpy(localizedName, name);
int underscorePos = underscore - name;
memcpy(localizedName + underscorePos, fLangTags[lang], kLangTagLen);
}
return true;
}
}
return false;
}
hsBool plLocalization::ExportGetLocalized(const char* name, int lang, char* localizedName)
{
return IGetLocalized(name, Language(lang+1), localizedName) &&
plFileUtils::FileExists(localizedName);
}
std::string plLocalization::LocalToString(const std::vector<std::string> & localizedText)
{
std::string retVal = "";
for (int i=0; i<localizedText.size(); i++)
{
if (i > kNumLanguages-1)
break;
std::string langHeader = "$";
std::string langName = GetLanguageName((Language)i);
langHeader += langName.substr(0,2) + "$";
retVal += langHeader + localizedText[i];
}
return retVal;
}
std::vector<std::string> plLocalization::StringToLocal(const std::string & localizedText)
{
std::vector<std::string> retVal;
wchar_t *temp = hsStringToWString(localizedText.c_str());
std::wstring wLocalizedText = temp;
delete [] temp;
std::vector<std::wstring> wStringVector = StringToLocal(wLocalizedText);
int i;
for (i=0; i<wStringVector.size(); i++)
{
char *local = hsWStringToString(wStringVector[i].c_str());
std::string val = local;
delete [] local;
retVal.push_back(val);
}
return retVal;
}
std::vector<std::wstring> plLocalization::StringToLocal(const std::wstring & localizedText)
{
std::vector<std::wstring> tags;
std::vector<int> tagLocs;
std::vector<int> sortedTagLocs;
std::vector<std::wstring> retVal;
int i;
for (i=0; i<kNumLanguages; i++)
{
std::wstring tag = L"$";
std::string temp = GetLanguageName((Language)i);
wchar_t *wTemp = hsStringToWString(temp.c_str());
std::wstring langName = wTemp;
delete [] wTemp;
tag += langName.substr(0,2) + L"$";
tags.push_back(tag);
tagLocs.push_back(localizedText.find(tag));
sortedTagLocs.push_back(i);
retVal.push_back(L"");
}
for (i=0; i<kNumLanguages-1; i++)
{
for (int j=i; j<kNumLanguages; j++)
{
if (tagLocs[sortedTagLocs[i]] > tagLocs[sortedTagLocs[j]])
sortedTagLocs[i]^=sortedTagLocs[j]^=sortedTagLocs[i]^=sortedTagLocs[j]; // swap the contents (yes, it works)
}
}
// now sortedTagLocs has the indexes of tagLocs sorted from smallest loc to highest loc
hsBool noTags = true;
for (i=0; i<kNumLanguages; i++)
{
int lang = sortedTagLocs[i]; // the language we are extracting
if (tagLocs[lang] != -1)
{
noTags = false; // at least one tag was found in the text
int startLoc = tagLocs[lang] + tags[lang].length();
int endLoc;
if (i+1 == kNumLanguages)
endLoc = localizedText.length();
else
endLoc = tagLocs[sortedTagLocs[i+1]];
retVal[lang] = localizedText.substr(startLoc,endLoc-startLoc);
}
}
if (noTags)
retVal[0] = localizedText; // if no tags were in the text, we assume it to be English
return retVal;
}
#include "hsWindows.h"
void plLocalization::SetDefaultLanguage()
{
fLanguage = kEnglish;
#if 0 // disable all languages
#ifdef HS_BUILD_FOR_WIN32
HKEY hLocalKey = NULL;
HKEY hMSKey = NULL;
HKEY hWindowsKey = NULL;
HKEY hCurVerKey = NULL;
HKEY hUninstKey = NULL;
HKEY hUruKey = NULL;
#define RegOpen(key, retKey, subKeyName) RegOpenKeyEx(key, subKeyName, 0, KEY_READ, &retKey) == ERROR_SUCCESS
if (RegOpen(HKEY_LOCAL_MACHINE, hLocalKey, "software") &&
RegOpen(hLocalKey, hMSKey, "microsoft") &&
RegOpen(hMSKey, hWindowsKey, "windows") &&
RegOpen(hWindowsKey, hCurVerKey, "currentversion") &&
RegOpen(hCurVerKey, hUninstKey, "uninstall") &&
RegOpen(hUninstKey, hUruKey, "Uru - Ages Beyond Myst"))
{
char value[20];
DWORD bufsize = sizeof(value);
if (RegQueryValueEx(hUruKey, "Lang", NULL, NULL, (LPBYTE)value, &bufsize) == ERROR_SUCCESS)
{
if (hsStrEQ(value, "en"))
fLanguage = kEnglish;
else if (hsStrEQ(value, "fr"))
fLanguage = kFrench;
else if (hsStrEQ(value, "de"))
fLanguage = kGerman;
else if (hsStrEQ(value, "es"))
fLanguage = kSpanish;
else if (hsStrEQ(value, "it"))
fLanguage = kItalian;
else if (hsStrEQ(value, "jp"))
fLanguage = kJapanese;
else
fLanguage = kEnglish;
}
}
RegCloseKey(hLocalKey);
RegCloseKey(hMSKey);
RegCloseKey(hWindowsKey);
RegCloseKey(hCurVerKey);
RegCloseKey(hUninstKey);
RegCloseKey(hUruKey);
#endif // HS_BUILD_FOR_WIN32
#endif // 0
}

View File

@ -1,117 +1,117 @@
/*==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/>.
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 plLocalization_h_inc
#define plLocalization_h_inc
#include "hsStlUtils.h"
class plLocalization
{
public:
enum Language
{
kEnglish,
kFrench,
kGerman,
kSpanish,
kItalian,
kJapanese,
kNumLanguages,
};
typedef enum encodingTypes
{
Enc_Unencoded, // This can also mean that python did the decoding for us and we don't need to tweak it on our end
Enc_Split_String,
Enc_Hybrid_Split_String,
Enc_UTF8,
Enc_UTF16,
Enc_Unicode_Escape,
Enc_Raw_Unicode_Escape,
Enc_Latin_1,
Enc_ASCII,
Enc_MBCS
};
protected:
static Language fLanguage;
static char* fLangTags[kNumLanguages];
static char* fLangNames[kNumLanguages];
static bool fUsesUnicode[kNumLanguages];
static encodingTypes fUnicodeEncoding[kNumLanguages];
static hsBool IGetLocalized(const char* name, Language lang, char* localizedName);
public:
// Sets the default language, as determined by the installer
static void SetDefaultLanguage();
static void SetLanguage(Language lang) { fLanguage = lang; }
static Language GetLanguage() { return fLanguage; }
static char* GetLanguageName(Language lang) { return fLangNames[lang]; }
static hsBool UsingUnicode() { return fUsesUnicode[fLanguage]; }
static encodingTypes UnicodeEncoding() { return fUnicodeEncoding[fLanguage]; }
// Returns true if we're using localized assets. If it returns false, you
// don't need to bother calling GetLocalized
static hsBool IsLocalized() { return fLanguage != kEnglish; }
// Pass in a key name and this will give you the localized name
// Returns false if the original keyname is not for a localized asset
static hsBool GetLocalized(const char* name, char* localizedName) { return IGetLocalized(name, fLanguage, localizedName); }
//
// Export only
//
// When you're exporting an asset that could be localized, you'll want to do
// a loop something like this to try and find any localized versions.
//
// for (int i = 0; i < plLocalization::GetNumLocales(); i++)
// {
// char localName[MAX_PATH];
// if (plLocalization::ExportGetLocalized(fileName, i, localName))
// {
// ...
// }
// }
//
static int GetNumLocales() { return kNumLanguages - 1; }
static hsBool ExportGetLocalized(const char* name, int lang, char* localizedName);
// Just tells us if this is localized, doesn't actually convert it for us
static hsBool IsLocalizedName(const char* name) { return IGetLocalized(name, kEnglish, nil); }
// Converts a vector of translated strings to a encoded string that can be decoded by StringToLocal()
// The index in the vector of a string is it's language
static std::string LocalToString(const std::vector<std::string> & localizedText);
// Converts a string encoded by LocalToString to a vector of translated strings
static std::vector<std::string> StringToLocal(const std::string & localizedText);
static std::vector<std::wstring> StringToLocal(const std::wstring & localizedText);
};
/*==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/>.
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 plLocalization_h_inc
#define plLocalization_h_inc
#include "hsStlUtils.h"
class plLocalization
{
public:
enum Language
{
kEnglish,
kFrench,
kGerman,
kSpanish,
kItalian,
kJapanese,
kNumLanguages,
};
typedef enum encodingTypes
{
Enc_Unencoded, // This can also mean that python did the decoding for us and we don't need to tweak it on our end
Enc_Split_String,
Enc_Hybrid_Split_String,
Enc_UTF8,
Enc_UTF16,
Enc_Unicode_Escape,
Enc_Raw_Unicode_Escape,
Enc_Latin_1,
Enc_ASCII,
Enc_MBCS
};
protected:
static Language fLanguage;
static char* fLangTags[kNumLanguages];
static char* fLangNames[kNumLanguages];
static bool fUsesUnicode[kNumLanguages];
static encodingTypes fUnicodeEncoding[kNumLanguages];
static hsBool IGetLocalized(const char* name, Language lang, char* localizedName);
public:
// Sets the default language, as determined by the installer
static void SetDefaultLanguage();
static void SetLanguage(Language lang) { fLanguage = lang; }
static Language GetLanguage() { return fLanguage; }
static char* GetLanguageName(Language lang) { return fLangNames[lang]; }
static hsBool UsingUnicode() { return fUsesUnicode[fLanguage]; }
static encodingTypes UnicodeEncoding() { return fUnicodeEncoding[fLanguage]; }
// Returns true if we're using localized assets. If it returns false, you
// don't need to bother calling GetLocalized
static hsBool IsLocalized() { return fLanguage != kEnglish; }
// Pass in a key name and this will give you the localized name
// Returns false if the original keyname is not for a localized asset
static hsBool GetLocalized(const char* name, char* localizedName) { return IGetLocalized(name, fLanguage, localizedName); }
//
// Export only
//
// When you're exporting an asset that could be localized, you'll want to do
// a loop something like this to try and find any localized versions.
//
// for (int i = 0; i < plLocalization::GetNumLocales(); i++)
// {
// char localName[MAX_PATH];
// if (plLocalization::ExportGetLocalized(fileName, i, localName))
// {
// ...
// }
// }
//
static int GetNumLocales() { return kNumLanguages - 1; }
static hsBool ExportGetLocalized(const char* name, int lang, char* localizedName);
// Just tells us if this is localized, doesn't actually convert it for us
static hsBool IsLocalizedName(const char* name) { return IGetLocalized(name, kEnglish, nil); }
// Converts a vector of translated strings to a encoded string that can be decoded by StringToLocal()
// The index in the vector of a string is it's language
static std::string LocalToString(const std::vector<std::string> & localizedText);
// Converts a string encoded by LocalToString to a vector of translated strings
static std::vector<std::string> StringToLocal(const std::string & localizedText);
static std::vector<std::wstring> StringToLocal(const std::wstring & localizedText);
};
#endif // plLocalization_h_inc

View File

@ -1,193 +1,193 @@
/*==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/>.
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==*/
#include "plPageInfo.h"
#include "hsUtils.h"
#include "hsStream.h"
#include "pnKeyedObject/plUoid.h"
#include "plVersion.h"
static UInt32 sCurrPageInfoVersion = 6;
//// Constructor/Destructor //////////////////////////////////////////////////
plPageInfo::plPageInfo()
{
IInit();
}
plPageInfo::plPageInfo( const plLocation &loc )
{
IInit();
fLocation = loc;
}
void plPageInfo::IInit()
{
fAge = fPage = nil;
fLocation.Invalidate();
SetMajorVersion(plVersion::GetMajorVersion());
fClassVersions.clear();
fChecksum = 0;
fDataStart = fIndexStart = 0;
}
plPageInfo::~plPageInfo()
{
SetStrings( nil, nil );
}
plPageInfo::plPageInfo( const plPageInfo &src )
{
IInit();
ISetFrom( src );
}
plPageInfo &plPageInfo::operator=( const plPageInfo &src )
{
ISetFrom( src );
return *this;
}
void plPageInfo::ISetFrom( const plPageInfo &src )
{
fLocation = src.fLocation;
SetStrings( src.fAge, src.fPage );
fMajorVersion = src.fMajorVersion;
fClassVersions = src.fClassVersions;
fChecksum = src.fChecksum;
fDataStart = src.fDataStart;
fIndexStart = src.fIndexStart;
}
void plPageInfo::SetStrings( const char *age, const char *page )
{
delete [] fAge;
delete [] fPage;
fAge = ( age == nil ) ? nil : hsStrcpy( age );
fPage = ( page == nil ) ? nil : hsStrcpy( page );
}
void plPageInfo::SetLocation( const plLocation &loc )
{
fLocation = loc;
}
void plPageInfo::AddClassVersion(UInt16 classIdx, UInt16 version)
{
ClassVersion cv;
cv.Class = classIdx;
cv.Version = version;
fClassVersions.push_back(cv);
}
const plLocation& plPageInfo::GetLocation() const
{
return fLocation;
}
void plPageInfo::Read( hsStream *s )
{
delete [] fAge;
delete [] fPage;
IInit();
// 5 is the earliest version since we began working again on the P20 codebase in Sep 2005,
// after Uru's online component was cancelled in Feb 2004, so I've removed support for
// anything prior to that to clean things up a bit.
UInt32 version = s->ReadSwap32();
if (version > sCurrPageInfoVersion || version < 5)
{
hsAssert( false, "Invalid header version in plPageInfo::Read()" );
return;
}
if (version >= 5)
{
fLocation.Read( s );
fAge = s->ReadSafeString();
if (version < 6)
delete s->ReadSafeString(); // fChapter was never used, and always "District".
fPage = s->ReadSafeString();
s->ReadSwap( &fMajorVersion );
if (version < 6)
{
UInt16 unusedMinorVersion;
s->ReadSwap(&unusedMinorVersion);
Int32 unusedReleaseVersion;
s->ReadSwap(&unusedReleaseVersion); // This was always zero... yanked.
UInt32 unusedFlags;
s->ReadSwap(&unusedFlags);
}
s->ReadSwap( &fChecksum );
s->ReadSwap( &fDataStart );
s->ReadSwap( &fIndexStart );
}
if (version >= 6)
{
UInt16 numClassVersions = s->ReadSwap16();
fClassVersions.reserve(numClassVersions);
for (UInt16 i = 0; i < numClassVersions; i++)
{
ClassVersion cv;
cv.Class = s->ReadSwap16();
cv.Version = s->ReadSwap16();
fClassVersions.push_back(cv);
}
}
}
void plPageInfo::Write( hsStream *s )
{
s->WriteSwap32( sCurrPageInfoVersion );
fLocation.Write( s );
s->WriteSafeString( fAge );
s->WriteSafeString( fPage );
s->WriteSwap( fMajorVersion );
s->WriteSwap( fChecksum );
s->WriteSwap( fDataStart );
s->WriteSwap( fIndexStart );
UInt16 numClassVersions = UInt16(fClassVersions.size());
s->WriteSwap16(numClassVersions);
for (UInt16 i = 0; i < numClassVersions; i++)
{
ClassVersion& cv = fClassVersions[i];
s->WriteSwap16(cv.Class);
s->WriteSwap16(cv.Version);
}
}
//// IsValid /////////////////////////////////////////////////////////////////
// Just a simple test for now.
hsBool plPageInfo::IsValid( void ) const
{
return fLocation.IsValid();
}
/*==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/>.
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==*/
#include "plPageInfo.h"
#include "hsUtils.h"
#include "hsStream.h"
#include "pnKeyedObject/plUoid.h"
#include "plVersion.h"
static UInt32 sCurrPageInfoVersion = 6;
//// Constructor/Destructor //////////////////////////////////////////////////
plPageInfo::plPageInfo()
{
IInit();
}
plPageInfo::plPageInfo( const plLocation &loc )
{
IInit();
fLocation = loc;
}
void plPageInfo::IInit()
{
fAge = fPage = nil;
fLocation.Invalidate();
SetMajorVersion(plVersion::GetMajorVersion());
fClassVersions.clear();
fChecksum = 0;
fDataStart = fIndexStart = 0;
}
plPageInfo::~plPageInfo()
{
SetStrings( nil, nil );
}
plPageInfo::plPageInfo( const plPageInfo &src )
{
IInit();
ISetFrom( src );
}
plPageInfo &plPageInfo::operator=( const plPageInfo &src )
{
ISetFrom( src );
return *this;
}
void plPageInfo::ISetFrom( const plPageInfo &src )
{
fLocation = src.fLocation;
SetStrings( src.fAge, src.fPage );
fMajorVersion = src.fMajorVersion;
fClassVersions = src.fClassVersions;
fChecksum = src.fChecksum;
fDataStart = src.fDataStart;
fIndexStart = src.fIndexStart;
}
void plPageInfo::SetStrings( const char *age, const char *page )
{
delete [] fAge;
delete [] fPage;
fAge = ( age == nil ) ? nil : hsStrcpy( age );
fPage = ( page == nil ) ? nil : hsStrcpy( page );
}
void plPageInfo::SetLocation( const plLocation &loc )
{
fLocation = loc;
}
void plPageInfo::AddClassVersion(UInt16 classIdx, UInt16 version)
{
ClassVersion cv;
cv.Class = classIdx;
cv.Version = version;
fClassVersions.push_back(cv);
}
const plLocation& plPageInfo::GetLocation() const
{
return fLocation;
}
void plPageInfo::Read( hsStream *s )
{
delete [] fAge;
delete [] fPage;
IInit();
// 5 is the earliest version since we began working again on the P20 codebase in Sep 2005,
// after Uru's online component was cancelled in Feb 2004, so I've removed support for
// anything prior to that to clean things up a bit.
UInt32 version = s->ReadSwap32();
if (version > sCurrPageInfoVersion || version < 5)
{
hsAssert( false, "Invalid header version in plPageInfo::Read()" );
return;
}
if (version >= 5)
{
fLocation.Read( s );
fAge = s->ReadSafeString();
if (version < 6)
delete s->ReadSafeString(); // fChapter was never used, and always "District".
fPage = s->ReadSafeString();
s->ReadSwap( &fMajorVersion );
if (version < 6)
{
UInt16 unusedMinorVersion;
s->ReadSwap(&unusedMinorVersion);
Int32 unusedReleaseVersion;
s->ReadSwap(&unusedReleaseVersion); // This was always zero... yanked.
UInt32 unusedFlags;
s->ReadSwap(&unusedFlags);
}
s->ReadSwap( &fChecksum );
s->ReadSwap( &fDataStart );
s->ReadSwap( &fIndexStart );
}
if (version >= 6)
{
UInt16 numClassVersions = s->ReadSwap16();
fClassVersions.reserve(numClassVersions);
for (UInt16 i = 0; i < numClassVersions; i++)
{
ClassVersion cv;
cv.Class = s->ReadSwap16();
cv.Version = s->ReadSwap16();
fClassVersions.push_back(cv);
}
}
}
void plPageInfo::Write( hsStream *s )
{
s->WriteSwap32( sCurrPageInfoVersion );
fLocation.Write( s );
s->WriteSafeString( fAge );
s->WriteSafeString( fPage );
s->WriteSwap( fMajorVersion );
s->WriteSwap( fChecksum );
s->WriteSwap( fDataStart );
s->WriteSwap( fIndexStart );
UInt16 numClassVersions = UInt16(fClassVersions.size());
s->WriteSwap16(numClassVersions);
for (UInt16 i = 0; i < numClassVersions; i++)
{
ClassVersion& cv = fClassVersions[i];
s->WriteSwap16(cv.Class);
s->WriteSwap16(cv.Version);
}
}
//// IsValid /////////////////////////////////////////////////////////////////
// Just a simple test for now.
hsBool plPageInfo::IsValid( void ) const
{
return fLocation.IsValid();
}

View File

@ -1,96 +1,96 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plPageInfo - Pack of info about an individual page
//
#ifndef _plPageInfo_h
#define _plPageInfo_h
#include "hsTypes.h"
#include "pnKeyedObject/plUoid.h"
#include <vector>
class hsStream;
class plLocation;
class plPageInfo
{
public:
struct ClassVersion { UInt16 Class; UInt16 Version; };
typedef std::vector<ClassVersion> ClassVerVec;
protected:
plLocation fLocation;
char* fAge;
char* fPage;
UInt16 fMajorVersion;
ClassVerVec fClassVersions;
UInt32 fChecksum;
UInt32 fDataStart, fIndexStart;
void IInit( void );
void ISetFrom( const plPageInfo &src );
public:
plPageInfo();
plPageInfo( const plLocation &loc );
plPageInfo( const plPageInfo &src );
virtual ~plPageInfo();
const char* GetAge() const { return fAge; }
const char* GetPage() const { return fPage; }
plPageInfo &operator=( const plPageInfo &src );
void ClearClassVersions() { fClassVersions.clear(); }
void AddClassVersion(UInt16 classIdx, UInt16 version);
const ClassVerVec& GetClassVersions() const { return fClassVersions; }
void SetStrings( const char *age, const char *page );
void SetLocation(const plLocation& loc);
const plLocation& GetLocation() const;
UInt16 GetMajorVersion() const { return fMajorVersion; }
void SetMajorVersion(UInt16 major) { fMajorVersion = major; }
void SetChecksum( UInt32 c ) { fChecksum = c; }
UInt32 GetChecksum( void ) const { return fChecksum; }
void Read( hsStream *s );
void Write( hsStream *s );
hsBool IsValid( void ) const;
UInt32 GetDataStart( void ) const { return fDataStart; }
void SetDataStart( UInt32 s ) { fDataStart = s; }
UInt32 GetIndexStart( void ) const { return fIndexStart; }
void SetIndexStart( UInt32 s ) { fIndexStart = s; }
};
#endif // _plPageInfo_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plPageInfo - Pack of info about an individual page
//
#ifndef _plPageInfo_h
#define _plPageInfo_h
#include "hsTypes.h"
#include "pnKeyedObject/plUoid.h"
#include <vector>
class hsStream;
class plLocation;
class plPageInfo
{
public:
struct ClassVersion { UInt16 Class; UInt16 Version; };
typedef std::vector<ClassVersion> ClassVerVec;
protected:
plLocation fLocation;
char* fAge;
char* fPage;
UInt16 fMajorVersion;
ClassVerVec fClassVersions;
UInt32 fChecksum;
UInt32 fDataStart, fIndexStart;
void IInit( void );
void ISetFrom( const plPageInfo &src );
public:
plPageInfo();
plPageInfo( const plLocation &loc );
plPageInfo( const plPageInfo &src );
virtual ~plPageInfo();
const char* GetAge() const { return fAge; }
const char* GetPage() const { return fPage; }
plPageInfo &operator=( const plPageInfo &src );
void ClearClassVersions() { fClassVersions.clear(); }
void AddClassVersion(UInt16 classIdx, UInt16 version);
const ClassVerVec& GetClassVersions() const { return fClassVersions; }
void SetStrings( const char *age, const char *page );
void SetLocation(const plLocation& loc);
const plLocation& GetLocation() const;
UInt16 GetMajorVersion() const { return fMajorVersion; }
void SetMajorVersion(UInt16 major) { fMajorVersion = major; }
void SetChecksum( UInt32 c ) { fChecksum = c; }
UInt32 GetChecksum( void ) const { return fChecksum; }
void Read( hsStream *s );
void Write( hsStream *s );
hsBool IsValid( void ) const;
UInt32 GetDataStart( void ) const { return fDataStart; }
void SetDataStart( UInt32 s ) { fDataStart = s; }
UInt32 GetIndexStart( void ) const { return fIndexStart; }
void SetIndexStart( UInt32 s ) { fIndexStart = s; }
};
#endif // _plPageInfo_h

View File

@ -1,43 +1,43 @@
/*==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/>.
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==*/
#include "plRegistryHelpers.h"
#include "plRegistryNode.h"
plKeyCollector::plKeyCollector( hsTArray<plKey> &keys ) : fKeys( keys )
{
}
hsBool plKeyCollector::EatKey(const plKey& key)
{
fKeys.Append(key);
return true;
}
hsBool plIndirectUnloadIterator::EatPage(plRegistryPageNode* page)
{
page->IterateKeys(this);
return true;
/*==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/>.
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==*/
#include "plRegistryHelpers.h"
#include "plRegistryNode.h"
plKeyCollector::plKeyCollector( hsTArray<plKey> &keys ) : fKeys( keys )
{
}
hsBool plKeyCollector::EatKey(const plKey& key)
{
fKeys.Append(key);
return true;
}
hsBool plIndirectUnloadIterator::EatPage(plRegistryPageNode* page)
{
page->IterateKeys(this);
return true;
}

View File

@ -1,86 +1,86 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plRegistryHelpers - Little helper classes for the registry and resManager
//
//// History /////////////////////////////////////////////////////////////////
//
// 3.25.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plRegistryHelpers_h
#define _plRegistryHelpers_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plKey;
class plRegistryPageNode;
//// Little Iterator Class Defs //////////////////////////////////////////////
class plRegistryKeyIterator
{
public:
virtual ~plRegistryKeyIterator() {}
virtual hsBool EatKey(const plKey& key) = 0;
};
class plRegistryPageIterator
{
public:
virtual ~plRegistryPageIterator() {}
virtual hsBool EatPage(plRegistryPageNode* keyNode) = 0;
};
//// plKeyCollector //////////////////////////////////////////////////////////
// Helper key iterator that collects the given keys into the given hsTArray
class plKeyCollector : public plRegistryKeyIterator
{
protected:
hsTArray<plKey> &fKeys;
public:
plKeyCollector(hsTArray<plKey>& keys);
virtual hsBool EatKey(const plKey& key);
};
// If you loaded keys with another iterator, this will ensure that they're unloaded
class plIndirectUnloadIterator : public plRegistryPageIterator, public plRegistryKeyIterator
{
public:
plIndirectUnloadIterator() {}
hsBool EatKey(const plKey& key) { return true; }
hsBool EatPage(plRegistryPageNode* page);
};
#endif // _plRegistryHelpers_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plRegistryHelpers - Little helper classes for the registry and resManager
//
//// History /////////////////////////////////////////////////////////////////
//
// 3.25.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plRegistryHelpers_h
#define _plRegistryHelpers_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plKey;
class plRegistryPageNode;
//// Little Iterator Class Defs //////////////////////////////////////////////
class plRegistryKeyIterator
{
public:
virtual ~plRegistryKeyIterator() {}
virtual hsBool EatKey(const plKey& key) = 0;
};
class plRegistryPageIterator
{
public:
virtual ~plRegistryPageIterator() {}
virtual hsBool EatPage(plRegistryPageNode* keyNode) = 0;
};
//// plKeyCollector //////////////////////////////////////////////////////////
// Helper key iterator that collects the given keys into the given hsTArray
class plKeyCollector : public plRegistryKeyIterator
{
protected:
hsTArray<plKey> &fKeys;
public:
plKeyCollector(hsTArray<plKey>& keys);
virtual hsBool EatKey(const plKey& key);
};
// If you loaded keys with another iterator, this will ensure that they're unloaded
class plIndirectUnloadIterator : public plRegistryPageIterator, public plRegistryKeyIterator
{
public:
plIndirectUnloadIterator() {}
hsBool EatKey(const plKey& key) { return true; }
hsBool EatPage(plRegistryPageNode* page);
};
#endif // _plRegistryHelpers_h

View File

@ -1,347 +1,347 @@
/*==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/>.
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==*/
#include "plRegistryKeyList.h"
#include "plRegistryHelpers.h"
#include "hsStream.h"
#include <algorithm>
plRegistryKeyList::plRegistryKeyList(UInt16 classType)
{
fClassType = classType;
fReffedStaticKeys = 0;
fLocked = 0;
fFlags = 0;
}
plRegistryKeyList::~plRegistryKeyList()
{
hsAssert(fLocked == 0, "Key list still locked on delete");
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* keyImp = fStaticKeys[i];
if (!keyImp->ObjectIsLoaded())
delete keyImp;
}
}
// Special dummy key that lets us set the return value of the GetName call.
// Makes it easier to do STL searches.
class plSearchKeyImp : public plKeyImp
{
public:
const char* fSearchKeyName;
const char* GetName() const { return fSearchKeyName; }
};
plKeyImp* plRegistryKeyList::FindKey(const char* keyName)
{
static plSearchKeyImp searchKey;
searchKey.fSearchKeyName = keyName;
// Search the static key list
if (fFlags & kStaticUnsorted)
{
// We're unsorted, brute force it. May do a separate search table in the
// future if this is a bottlneck
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* curKey = fStaticKeys[i];
if (curKey && hsStrCaseEQ(keyName, curKey->GetName()))
return curKey;
}
}
else
{
// We're sorted, do a fast lookup
StaticVec::const_iterator it = std::lower_bound(fStaticKeys.begin(), fStaticKeys.end(), &searchKey, KeySorter());
if (it != fStaticKeys.end() && hsStrCaseEQ(keyName, (*it)->GetName()))
return *it;
}
// Search the dynamic key list
DynSet::const_iterator dynIt = fDynamicKeys.find(&searchKey);
if (dynIt != fDynamicKeys.end())
return *dynIt;
return nil;
}
plKeyImp* plRegistryKeyList::FindKey(const plUoid& uoid)
{
UInt32 objectID = uoid.GetObjectID();
// Key is dynamic or doesn't know it's index. Do a find by name.
if (objectID == 0)
return FindKey(uoid.GetObjectName());
// Direct lookup
if (objectID <= fStaticKeys.size())
{
#ifdef PLASMA_EXTERNAL_RELEASE
return fStaticKeys[objectID-1];
#else
// If this is an internal release, our objectIDs might not match
// because of local data. Verify that we have the right key by
// name, and if it's wrong, do the slower find-by-name.
plKeyImp *keyImp = fStaticKeys[objectID-1];
if (!hsStrCaseEQ(keyImp->GetName(), uoid.GetObjectName()))
return FindKey(uoid.GetObjectName());
else
return keyImp;
#endif // PLASMA_EXTERNAL_RELEASE
}
// If we got here it probably means we just deleted all our keys of the matching type
// because no one was using them. No worries. The resManager will catch this and
// reload our keys, then try again.
return nil;
}
void plRegistryKeyList::ILock()
{
fLocked++;
}
void plRegistryKeyList::IUnlock()
{
fLocked--;
if (fLocked == 0)
IRepack();
}
bool plRegistryKeyList::IterateKeys(plRegistryKeyIterator* iterator)
{
ILock();
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* keyImp = fStaticKeys[i];
if (keyImp != nil)
{
if (!iterator->EatKey(plKey::Make(keyImp)))
{
IUnlock();
return false;
}
}
}
DynSet::const_iterator it;
for (it = fDynamicKeys.begin(); it != fDynamicKeys.end(); it++)
{
plKeyImp* keyImp = *it;
hsAssert(keyImp, "Shouldn't ever have a nil dynamic key");
if (!iterator->EatKey(plKey::Make(keyImp)))
{
IUnlock();
return false;
}
}
IUnlock();
return true;
}
void plRegistryKeyList::AddKey(plKeyImp* key, LoadStatus& loadStatusChange)
{
loadStatusChange = kNoChange;
hsAssert(fLocked == 0, "Don't currently support adding keys while locked");
if (fLocked == 0 && key != nil)
{
// If this is the first key added, we just became loaded
if (fDynamicKeys.empty())
loadStatusChange = kDynLoaded;
hsAssert(fDynamicKeys.find(key) == fDynamicKeys.end(), "Key already added");
fDynamicKeys.insert(key);
}
}
void plRegistryKeyList::SetKeyUsed(plKeyImp* key)
{
// If this is a static key, mark that we used it. Otherwise, just ignore it.
UInt32 id = key->GetUoid().GetObjectID();
if (id > 0)
fReffedStaticKeys++;
}
bool plRegistryKeyList::SetKeyUnused(plKeyImp* key, LoadStatus& loadStatusChange)
{
loadStatusChange = kNoChange;
// Clones never officially get added to the key list (they're maintained by
// the original key), so just ignore them
if (key->GetUoid().IsClone())
{
delete key;
return true;
}
// Check if it's a static key
UInt32 id = key->GetUoid().GetObjectID();
hsAssert(id <= fStaticKeys.size(), "Bad static key id");
if (id != 0 && id <= fStaticKeys.size())
{
fReffedStaticKeys--;
if (fLocked == 0)
IRepack();
// That was our last used static key, we're static unloaded
if (fReffedStaticKeys == 0)
loadStatusChange = kStaticUnloaded;
return true;
}
// Try to find it in the dynamic key list
DynSet::iterator dynIt = fDynamicKeys.find(key);
if (dynIt != fDynamicKeys.end())
{
hsAssert(fLocked == 0, "Don't currently support removing dynamic keys while locked");
if (fLocked == 0)
{
fDynamicKeys.erase(dynIt);
delete key;
// That was our last dynamic key, notify of dynamic unloaded
if (fDynamicKeys.empty())
loadStatusChange = kDynUnloaded;
return true;
}
return false;
}
hsAssert(0, "Couldn't find this key, what is it?");
return false;
}
//// IRepack /////////////////////////////////////////////////////////////////
// Frees the memory for our static key array if none of them are loaded
void plRegistryKeyList::IRepack()
{
if (fReffedStaticKeys == 0 && !fStaticKeys.empty())
{
for (int i = 0; i < fStaticKeys.size(); i++)
delete fStaticKeys[i];
fStaticKeys.clear();
}
}
void plRegistryKeyList::PrepForWrite()
{
// If we have any static keys already, we were read in. To keep from
// invalidating old key indexes any new keys have to go on the end, hence we're
// unsorted now.
if (!fStaticKeys.empty())
fFlags |= kStaticUnsorted;
// If a dynamic keys doesn't have an object assigned to it, we're not writing
// it out. Figure out how many valid keys we have.
int numDynKeys = 0;
DynSet::const_iterator cIt;
for (cIt = fDynamicKeys.begin(); cIt != fDynamicKeys.end(); cIt++)
{
plKeyImp* key = *cIt;
// We're only going to write out keys that have objects
if (key->ObjectIsLoaded())
numDynKeys++;
}
// Start our new object id's after any already created ones
UInt32 objectID = fStaticKeys.size()+1;
// Make room for our new keys
fStaticKeys.resize(fStaticKeys.size()+numDynKeys);
DynSet::iterator it = fDynamicKeys.begin();
while (it != fDynamicKeys.end())
{
plKeyImp* key = *it;
it++;
// If we're gonna use this key, tag it with it's object id and move it to the static array.
if (key->ObjectIsLoaded())
{
key->SetObjectID(objectID);
fStaticKeys[objectID-1] = key;
objectID++;
fReffedStaticKeys++;
fDynamicKeys.erase(key);
}
}
}
void plRegistryKeyList::Read(hsStream* s)
{
UInt32 keyListLen = s->ReadSwap32();
if (!fStaticKeys.empty())
{
s->Skip(keyListLen);
return;
}
fFlags = s->ReadByte();
UInt32 numKeys = s->ReadSwap32();
fStaticKeys.resize(numKeys);
for (int i = 0; i < numKeys; i++)
{
plKeyImp* newKey = TRACKED_NEW plKeyImp;
newKey->Read(s);
fStaticKeys[i] = newKey;
}
}
void plRegistryKeyList::Write(hsStream* s)
{
// Save space for the length of our data
UInt32 beginPos = s->GetPosition();
s->WriteSwap32(0);
s->WriteByte(fFlags);
int numKeys = fStaticKeys.size();
s->WriteSwap32(numKeys);
// Write out all our keys (anything in dynamic is unused, so just ignore those)
for (int i = 0; i < numKeys; i++)
{
plKeyImp* key = fStaticKeys[i];
key->Write(s);
}
// Go back to the start and write the length of our data
UInt32 endPos = s->GetPosition();
s->SetPosition(beginPos);
s->WriteSwap32(endPos-beginPos-sizeof(UInt32));
s->SetPosition(endPos);
}
/*==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/>.
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==*/
#include "plRegistryKeyList.h"
#include "plRegistryHelpers.h"
#include "hsStream.h"
#include <algorithm>
plRegistryKeyList::plRegistryKeyList(UInt16 classType)
{
fClassType = classType;
fReffedStaticKeys = 0;
fLocked = 0;
fFlags = 0;
}
plRegistryKeyList::~plRegistryKeyList()
{
hsAssert(fLocked == 0, "Key list still locked on delete");
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* keyImp = fStaticKeys[i];
if (!keyImp->ObjectIsLoaded())
delete keyImp;
}
}
// Special dummy key that lets us set the return value of the GetName call.
// Makes it easier to do STL searches.
class plSearchKeyImp : public plKeyImp
{
public:
const char* fSearchKeyName;
const char* GetName() const { return fSearchKeyName; }
};
plKeyImp* plRegistryKeyList::FindKey(const char* keyName)
{
static plSearchKeyImp searchKey;
searchKey.fSearchKeyName = keyName;
// Search the static key list
if (fFlags & kStaticUnsorted)
{
// We're unsorted, brute force it. May do a separate search table in the
// future if this is a bottlneck
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* curKey = fStaticKeys[i];
if (curKey && hsStrCaseEQ(keyName, curKey->GetName()))
return curKey;
}
}
else
{
// We're sorted, do a fast lookup
StaticVec::const_iterator it = std::lower_bound(fStaticKeys.begin(), fStaticKeys.end(), &searchKey, KeySorter());
if (it != fStaticKeys.end() && hsStrCaseEQ(keyName, (*it)->GetName()))
return *it;
}
// Search the dynamic key list
DynSet::const_iterator dynIt = fDynamicKeys.find(&searchKey);
if (dynIt != fDynamicKeys.end())
return *dynIt;
return nil;
}
plKeyImp* plRegistryKeyList::FindKey(const plUoid& uoid)
{
UInt32 objectID = uoid.GetObjectID();
// Key is dynamic or doesn't know it's index. Do a find by name.
if (objectID == 0)
return FindKey(uoid.GetObjectName());
// Direct lookup
if (objectID <= fStaticKeys.size())
{
#ifdef PLASMA_EXTERNAL_RELEASE
return fStaticKeys[objectID-1];
#else
// If this is an internal release, our objectIDs might not match
// because of local data. Verify that we have the right key by
// name, and if it's wrong, do the slower find-by-name.
plKeyImp *keyImp = fStaticKeys[objectID-1];
if (!hsStrCaseEQ(keyImp->GetName(), uoid.GetObjectName()))
return FindKey(uoid.GetObjectName());
else
return keyImp;
#endif // PLASMA_EXTERNAL_RELEASE
}
// If we got here it probably means we just deleted all our keys of the matching type
// because no one was using them. No worries. The resManager will catch this and
// reload our keys, then try again.
return nil;
}
void plRegistryKeyList::ILock()
{
fLocked++;
}
void plRegistryKeyList::IUnlock()
{
fLocked--;
if (fLocked == 0)
IRepack();
}
bool plRegistryKeyList::IterateKeys(plRegistryKeyIterator* iterator)
{
ILock();
for (int i = 0; i < fStaticKeys.size(); i++)
{
plKeyImp* keyImp = fStaticKeys[i];
if (keyImp != nil)
{
if (!iterator->EatKey(plKey::Make(keyImp)))
{
IUnlock();
return false;
}
}
}
DynSet::const_iterator it;
for (it = fDynamicKeys.begin(); it != fDynamicKeys.end(); it++)
{
plKeyImp* keyImp = *it;
hsAssert(keyImp, "Shouldn't ever have a nil dynamic key");
if (!iterator->EatKey(plKey::Make(keyImp)))
{
IUnlock();
return false;
}
}
IUnlock();
return true;
}
void plRegistryKeyList::AddKey(plKeyImp* key, LoadStatus& loadStatusChange)
{
loadStatusChange = kNoChange;
hsAssert(fLocked == 0, "Don't currently support adding keys while locked");
if (fLocked == 0 && key != nil)
{
// If this is the first key added, we just became loaded
if (fDynamicKeys.empty())
loadStatusChange = kDynLoaded;
hsAssert(fDynamicKeys.find(key) == fDynamicKeys.end(), "Key already added");
fDynamicKeys.insert(key);
}
}
void plRegistryKeyList::SetKeyUsed(plKeyImp* key)
{
// If this is a static key, mark that we used it. Otherwise, just ignore it.
UInt32 id = key->GetUoid().GetObjectID();
if (id > 0)
fReffedStaticKeys++;
}
bool plRegistryKeyList::SetKeyUnused(plKeyImp* key, LoadStatus& loadStatusChange)
{
loadStatusChange = kNoChange;
// Clones never officially get added to the key list (they're maintained by
// the original key), so just ignore them
if (key->GetUoid().IsClone())
{
delete key;
return true;
}
// Check if it's a static key
UInt32 id = key->GetUoid().GetObjectID();
hsAssert(id <= fStaticKeys.size(), "Bad static key id");
if (id != 0 && id <= fStaticKeys.size())
{
fReffedStaticKeys--;
if (fLocked == 0)
IRepack();
// That was our last used static key, we're static unloaded
if (fReffedStaticKeys == 0)
loadStatusChange = kStaticUnloaded;
return true;
}
// Try to find it in the dynamic key list
DynSet::iterator dynIt = fDynamicKeys.find(key);
if (dynIt != fDynamicKeys.end())
{
hsAssert(fLocked == 0, "Don't currently support removing dynamic keys while locked");
if (fLocked == 0)
{
fDynamicKeys.erase(dynIt);
delete key;
// That was our last dynamic key, notify of dynamic unloaded
if (fDynamicKeys.empty())
loadStatusChange = kDynUnloaded;
return true;
}
return false;
}
hsAssert(0, "Couldn't find this key, what is it?");
return false;
}
//// IRepack /////////////////////////////////////////////////////////////////
// Frees the memory for our static key array if none of them are loaded
void plRegistryKeyList::IRepack()
{
if (fReffedStaticKeys == 0 && !fStaticKeys.empty())
{
for (int i = 0; i < fStaticKeys.size(); i++)
delete fStaticKeys[i];
fStaticKeys.clear();
}
}
void plRegistryKeyList::PrepForWrite()
{
// If we have any static keys already, we were read in. To keep from
// invalidating old key indexes any new keys have to go on the end, hence we're
// unsorted now.
if (!fStaticKeys.empty())
fFlags |= kStaticUnsorted;
// If a dynamic keys doesn't have an object assigned to it, we're not writing
// it out. Figure out how many valid keys we have.
int numDynKeys = 0;
DynSet::const_iterator cIt;
for (cIt = fDynamicKeys.begin(); cIt != fDynamicKeys.end(); cIt++)
{
plKeyImp* key = *cIt;
// We're only going to write out keys that have objects
if (key->ObjectIsLoaded())
numDynKeys++;
}
// Start our new object id's after any already created ones
UInt32 objectID = fStaticKeys.size()+1;
// Make room for our new keys
fStaticKeys.resize(fStaticKeys.size()+numDynKeys);
DynSet::iterator it = fDynamicKeys.begin();
while (it != fDynamicKeys.end())
{
plKeyImp* key = *it;
it++;
// If we're gonna use this key, tag it with it's object id and move it to the static array.
if (key->ObjectIsLoaded())
{
key->SetObjectID(objectID);
fStaticKeys[objectID-1] = key;
objectID++;
fReffedStaticKeys++;
fDynamicKeys.erase(key);
}
}
}
void plRegistryKeyList::Read(hsStream* s)
{
UInt32 keyListLen = s->ReadSwap32();
if (!fStaticKeys.empty())
{
s->Skip(keyListLen);
return;
}
fFlags = s->ReadByte();
UInt32 numKeys = s->ReadSwap32();
fStaticKeys.resize(numKeys);
for (int i = 0; i < numKeys; i++)
{
plKeyImp* newKey = TRACKED_NEW plKeyImp;
newKey->Read(s);
fStaticKeys[i] = newKey;
}
}
void plRegistryKeyList::Write(hsStream* s)
{
// Save space for the length of our data
UInt32 beginPos = s->GetPosition();
s->WriteSwap32(0);
s->WriteByte(fFlags);
int numKeys = fStaticKeys.size();
s->WriteSwap32(numKeys);
// Write out all our keys (anything in dynamic is unused, so just ignore those)
for (int i = 0; i < numKeys; i++)
{
plKeyImp* key = fStaticKeys[i];
key->Write(s);
}
// Go back to the start and write the length of our data
UInt32 endPos = s->GetPosition();
s->SetPosition(beginPos);
s->WriteSwap32(endPos-beginPos-sizeof(UInt32));
s->SetPosition(endPos);
}

View File

@ -1,113 +1,113 @@
/*==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/>.
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 plRegistryKeyList_h_inc
#define plRegistryKeyList_h_inc
#include "hsTypes.h"
#include "pnKeyedObject/plKeyImp.h"
#include <vector>
#include <set>
class plRegistryKeyIterator;
class KeySorter
{
public:
bool operator() (plKeyImp* k1, plKeyImp* k2) const
{
hsAssert(k1 && k2, "Should have valid keys here");
return stricmp(k1->GetName(), k2->GetName()) < 0;
}
};
//
// List of keys for a single class type.
//
class plRegistryKeyList
{
protected:
friend class plKeyFinder;
UInt16 fClassType;
// Lock counter for iterating. If this is >0, don't do any ops that
// can change key positions in the array (instead, just leave holes)
UInt16 fLocked;
enum Flags { kStaticUnsorted = 0x1 };
UInt8 fFlags;
// Static keys are one's we read off disk. These don't change and are
// assumed to be already sorted when they're read in.
typedef std::vector<plKeyImp*> StaticVec;
StaticVec fStaticKeys;
UInt32 fReffedStaticKeys; // Number of static keys that are loaded
// Dynamic keys are anything created at runtime. They are put in the
// correct sorted position when they are added
typedef std::set<plKeyImp*, KeySorter> DynSet;
DynSet fDynamicKeys;
plRegistryKeyList() {}
void ILock();
void IUnlock();
void IRepack();
public:
plRegistryKeyList(UInt16 classType);
~plRegistryKeyList();
UInt16 GetClassType() const { return fClassType; }
// Find a key by name (case-insensitive)
plKeyImp* FindKey(const char* keyName);
// Find a key by uoid index.
plKeyImp* FindKey(const plUoid& uoid);
bool IterateKeys(plRegistryKeyIterator* iterator);
// Changes in our load status that can be caused by loading or unloading a key
enum LoadStatus
{
kNoChange,
kDynLoaded,
kDynUnloaded,
kStaticUnloaded,
};
void AddKey(plKeyImp* key, LoadStatus& loadStatusChange);
void SetKeyUsed(plKeyImp* key);
bool SetKeyUnused(plKeyImp* key, LoadStatus& loadStatusChange);
// Export time only. Before we write to disk, assign all the static keys
// object ID's that they can use to do fast lookups at load time.
void PrepForWrite();
void Read(hsStream* s);
void Write(hsStream* s);
};
#endif // plRegistryKeyList_h_inc
/*==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/>.
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 plRegistryKeyList_h_inc
#define plRegistryKeyList_h_inc
#include "hsTypes.h"
#include "pnKeyedObject/plKeyImp.h"
#include <vector>
#include <set>
class plRegistryKeyIterator;
class KeySorter
{
public:
bool operator() (plKeyImp* k1, plKeyImp* k2) const
{
hsAssert(k1 && k2, "Should have valid keys here");
return stricmp(k1->GetName(), k2->GetName()) < 0;
}
};
//
// List of keys for a single class type.
//
class plRegistryKeyList
{
protected:
friend class plKeyFinder;
UInt16 fClassType;
// Lock counter for iterating. If this is >0, don't do any ops that
// can change key positions in the array (instead, just leave holes)
UInt16 fLocked;
enum Flags { kStaticUnsorted = 0x1 };
UInt8 fFlags;
// Static keys are one's we read off disk. These don't change and are
// assumed to be already sorted when they're read in.
typedef std::vector<plKeyImp*> StaticVec;
StaticVec fStaticKeys;
UInt32 fReffedStaticKeys; // Number of static keys that are loaded
// Dynamic keys are anything created at runtime. They are put in the
// correct sorted position when they are added
typedef std::set<plKeyImp*, KeySorter> DynSet;
DynSet fDynamicKeys;
plRegistryKeyList() {}
void ILock();
void IUnlock();
void IRepack();
public:
plRegistryKeyList(UInt16 classType);
~plRegistryKeyList();
UInt16 GetClassType() const { return fClassType; }
// Find a key by name (case-insensitive)
plKeyImp* FindKey(const char* keyName);
// Find a key by uoid index.
plKeyImp* FindKey(const plUoid& uoid);
bool IterateKeys(plRegistryKeyIterator* iterator);
// Changes in our load status that can be caused by loading or unloading a key
enum LoadStatus
{
kNoChange,
kDynLoaded,
kDynUnloaded,
kStaticUnloaded,
};
void AddKey(plKeyImp* key, LoadStatus& loadStatusChange);
void SetKeyUsed(plKeyImp* key);
bool SetKeyUnused(plKeyImp* key, LoadStatus& loadStatusChange);
// Export time only. Before we write to disk, assign all the static keys
// object ID's that they can use to do fast lookups at load time.
void PrepForWrite();
void Read(hsStream* s);
void Write(hsStream* s);
};
#endif // plRegistryKeyList_h_inc

View File

@ -1,403 +1,403 @@
/*==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/>.
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==*/
#include "plRegistryNode.h"
#include "plRegistryKeyList.h"
#include "plRegistryHelpers.h"
#include "pnKeyedObject/plKeyImp.h"
#include "plStatusLog/plStatusLog.h"
#include "pnFactory/plFactory.h"
#include "plFile/plFileUtils.h"
#include "hsStlUtils.h"
#include "plVersion.h"
plRegistryPageNode::plRegistryPageNode(const char* path)
: fValid(kPageCorrupt)
, fPath(nil)
, fDynLoadedTypes(0)
, fStaticLoadedTypes(0)
, fOpenRequests(0)
, fIsNewPage(false)
{
fPath = hsStrcpy(path);
hsStream* stream = OpenStream();
if (stream)
{
fPageInfo.Read(&fStream);
fValid = IVerify();
CloseStream();
}
}
plRegistryPageNode::plRegistryPageNode(const plLocation& location, const char* age, const char* page, const char* dataPath)
: fValid(kPageOk)
, fPath(nil)
, fPageInfo(location)
, fDynLoadedTypes(0)
, fStaticLoadedTypes(0)
, fOpenRequests(0)
, fIsNewPage(true)
{
fPageInfo.SetStrings(age, page);
char filePath[512];
// Copy the path over
strncpy(filePath, dataPath, sizeof(filePath));
plFileUtils::AddSlash(filePath);
// Time to construct our actual file name. For now, we'll use the same old format
// of age_page.extension
strncat(filePath, fPageInfo.GetAge(), sizeof(filePath));
strncat(filePath, "_District_", sizeof(filePath));
strncat(filePath, fPageInfo.GetPage(), sizeof(filePath));
strncat(filePath, ".prp", sizeof(filePath));
fPath = hsStrcpy(filePath);
}
plRegistryPageNode::~plRegistryPageNode()
{
delete [] fPath;
UnloadKeys();
}
PageCond plRegistryPageNode::IVerify()
{
// Check the checksum values first, to make sure the files aren't corrupt
UInt32 ourChecksum = 0;
hsStream* stream = OpenStream();
if (stream)
{
ourChecksum = stream->GetEOF() - fPageInfo.GetDataStart();
CloseStream();
}
if (ourChecksum != fPageInfo.GetChecksum())
return kPageCorrupt;
// If major version out-of-date, entire location is screwed
if (fPageInfo.GetMajorVersion() > plVersion::GetMajorVersion())
return kPageTooNew;
else if (fPageInfo.GetMajorVersion() < plVersion::GetMajorVersion())
return kPageOutOfDate;
// Check the minor versions
const plPageInfo::ClassVerVec& classVersions = fPageInfo.GetClassVersions();
for (int i = 0; i < classVersions.size(); i++)
{
const plPageInfo::ClassVersion& cv = classVersions[i];
UInt16 curVersion = plVersion::GetCreatableVersion(cv.Class);
if (curVersion > cv.Version)
return kPageOutOfDate;
else if (curVersion < cv.Version)
return kPageTooNew;
}
return kPageOk;
}
hsStream* plRegistryPageNode::OpenStream()
{
if (fOpenRequests == 0)
{
if (!fStream.Open(fPath, "rb"))
return nil;
}
fOpenRequests++;
return &fStream;
}
void plRegistryPageNode::CloseStream()
{
if (fOpenRequests > 0)
fOpenRequests--;
if (fOpenRequests == 0)
fStream.Close();
}
void plRegistryPageNode::LoadKeys()
{
hsAssert(IsValid(), "Trying to load keys for invalid page");
hsAssert(!fIsNewPage, "Trying to read a new page");
if (IsFullyLoaded())
return;
hsStream* stream = OpenStream();
if (!stream)
{
hsAssert(0, xtl::format("plRegistryPageNode::LoadKeysFromSource - bad stream %s,%s",
GetPageInfo().GetAge(), GetPageInfo().GetPage()).c_str());
return;
}
// If we're loading keys in the middle of a read because FindKey() failed, we'd better
// make note of our stream position and restore it when we're done.
UInt32 oldPos = stream->GetPosition();
stream->SetPosition(GetPageInfo().GetIndexStart());
// Read in the number of key types
UInt32 numTypes = stream->ReadSwap32();
for (UInt32 i = 0; i < numTypes; i++)
{
UInt16 classType = stream->ReadSwap16();
plRegistryKeyList* keyList = IGetKeyList(classType);
if (!keyList)
{
keyList = TRACKED_NEW plRegistryKeyList(classType);
fKeyLists[classType] = keyList;
}
keyList->Read(stream);
}
stream->SetPosition(oldPos);
CloseStream();
fStaticLoadedTypes = fKeyLists.size();
}
void plRegistryPageNode::UnloadKeys()
{
KeyMap::iterator it = fKeyLists.begin();
for (; it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
delete keyList;
}
fKeyLists.clear();
fDynLoadedTypes = 0;
fStaticLoadedTypes = 0;
}
//// plWriteIterator /////////////////////////////////////////////////////////
// Key iterator for writing objects
class plWriteIterator : public plRegistryKeyIterator
{
protected:
hsStream* fStream;
public:
plWriteIterator(hsStream* s) : fStream(s) {}
virtual hsBool EatKey(const plKey& key)
{
plKeyImp* imp = (plKeyImp*)key;
imp->WriteObject(fStream);
return true;
}
};
void plRegistryPageNode::Write()
{
hsAssert(fOpenRequests == 0, "Trying to write while the page is open for reading");
if (!fStream.Open(fPath, "wb"))
{
hsAssert(0, "Couldn't open file for writing");
return;
}
// Some prep stuff. Assign object IDs for every key in this page, and put the
// versions of all our creatable types in the pageinfo.
fPageInfo.ClearClassVersions();
KeyMap::const_iterator it;
for (it = fKeyLists.begin(); it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
keyList->PrepForWrite();
int ver = plVersion::GetCreatableVersion(keyList->GetClassType());
fPageInfo.AddClassVersion(keyList->GetClassType(), ver);
}
// First thing we write is the pageinfo. Later we'll rewind and overwrite this with the final values
fPageInfo.Write(&fStream);
fPageInfo.SetDataStart(fStream.GetPosition());
// Write all our objects
plWriteIterator writer(&fStream);
IterateKeys(&writer);
fPageInfo.SetIndexStart(fStream.GetPosition());
// Write our keys
fStream.WriteSwap32(fKeyLists.size());
for (it = fKeyLists.begin(); it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
fStream.WriteSwap16(keyList->GetClassType());
keyList->Write(&fStream);
}
// Rewind and write the pageinfo with the correct data and index offsets
fStream.Rewind();
fPageInfo.SetChecksum(fStream.GetEOF() - fPageInfo.GetDataStart());
fPageInfo.Write(&fStream);
fStream.Close();
}
//// IterateKeys /////////////////////////////////////////////////////////////
hsBool plRegistryPageNode::IterateKeys(plRegistryKeyIterator* iterator) const
{
KeyMap::const_iterator it = fKeyLists.begin();
for (; it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
if (!keyList->IterateKeys(iterator))
return false;
}
return true;
}
//// IterateKeys /////////////////////////////////////////////////////////////
// Restricted version that only iterates through the keys of a given class
// type.
hsBool plRegistryPageNode::IterateKeys(plRegistryKeyIterator* iterator, UInt16 classToRestrictTo) const
{
plRegistryKeyList* keyList = IGetKeyList(classToRestrictTo);
if (keyList != nil)
return keyList->IterateKeys(iterator);
return true;
}
plKeyImp* plRegistryPageNode::FindKey(UInt16 classType, const char* name) const
{
plRegistryKeyList* keys = IGetKeyList(classType);
if (keys == nil)
return nil;
return keys->FindKey(name);
}
plKeyImp* plRegistryPageNode::FindKey(const plUoid& uoid) const
{
plRegistryKeyList* keys = IGetKeyList(uoid.GetClassType());
if (keys == nil)
return nil;
return keys->FindKey(uoid);
}
void plRegistryPageNode::AddKey(plKeyImp* key)
{
UInt16 classType = key->GetUoid().GetClassType();
plRegistryKeyList* keys = fKeyLists[classType];
if (keys == nil)
{
keys = TRACKED_NEW plRegistryKeyList(classType);
fKeyLists[classType] = keys;
}
// Error check
if (keys->FindKey(key->GetUoid().GetObjectName()) != nil)
{
//char str[512], tempStr[128];
//sprintf(str, "Attempting to add a key with a duplicate name. Not allowed."
// "\n\n(Key name: %s, Class: %s, Loc: %s)", key->GetUoid().GetObjectName(),
// plFactory::GetNameOfClass(classType), key->GetUoid().GetLocation().StringIze(tempStr));
//hsStatusMessage(str);
hsBool recovered = false;
// Attempt recovery
for (int i = 0; i < 500; i++)
{
char tempName[512];
sprintf(tempName, "%s%d", key->GetUoid().GetObjectName(), i);
if (keys->FindKey(tempName) == nil)
{
plUoid uoid(key->GetUoid().GetLocation(), key->GetUoid().GetClassType(), tempName, key->GetUoid().GetLoadMask());
key->SetUoid(uoid);
recovered = true;
break;
}
}
if (!recovered)
{
hsAssert(0, "Couldn't allocate a unique key");
return;
}
}
plRegistryKeyList::LoadStatus loadStatusChange;
keys->AddKey(key, loadStatusChange);
if (loadStatusChange == plRegistryKeyList::kDynLoaded)
fDynLoadedTypes++;
}
void plRegistryPageNode::SetKeyUsed(plKeyImp* key)
{
plRegistryKeyList* keys = IGetKeyList(key->GetUoid().GetClassType());
if (keys == nil)
return;
keys->SetKeyUsed(key);
}
hsBool plRegistryPageNode::SetKeyUnused(plKeyImp* key)
{
plRegistryKeyList* keys = IGetKeyList(key->GetUoid().GetClassType());
if (keys == nil)
return false;
plRegistryKeyList::LoadStatus loadStatusChange;
hsBool removed = keys->SetKeyUnused(key, loadStatusChange);
// If the key type just changed load status, update our load counts
if (loadStatusChange == plRegistryKeyList::kDynUnloaded)
fDynLoadedTypes--;
else if (loadStatusChange == plRegistryKeyList::kStaticUnloaded)
fStaticLoadedTypes--;
return removed;
}
plRegistryKeyList* plRegistryPageNode::IGetKeyList(UInt16 classType) const
{
KeyMap::const_iterator it = fKeyLists.find(classType);
if (it != fKeyLists.end())
return it->second;
return nil;
}
void plRegistryPageNode::DeleteSource()
{
hsAssert(fOpenRequests == 0, "Deleting a stream that's open for reading");
plFileUtils::RemoveFile(fPath);
}
/*==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/>.
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==*/
#include "plRegistryNode.h"
#include "plRegistryKeyList.h"
#include "plRegistryHelpers.h"
#include "pnKeyedObject/plKeyImp.h"
#include "plStatusLog/plStatusLog.h"
#include "pnFactory/plFactory.h"
#include "plFile/plFileUtils.h"
#include "hsStlUtils.h"
#include "plVersion.h"
plRegistryPageNode::plRegistryPageNode(const char* path)
: fValid(kPageCorrupt)
, fPath(nil)
, fDynLoadedTypes(0)
, fStaticLoadedTypes(0)
, fOpenRequests(0)
, fIsNewPage(false)
{
fPath = hsStrcpy(path);
hsStream* stream = OpenStream();
if (stream)
{
fPageInfo.Read(&fStream);
fValid = IVerify();
CloseStream();
}
}
plRegistryPageNode::plRegistryPageNode(const plLocation& location, const char* age, const char* page, const char* dataPath)
: fValid(kPageOk)
, fPath(nil)
, fPageInfo(location)
, fDynLoadedTypes(0)
, fStaticLoadedTypes(0)
, fOpenRequests(0)
, fIsNewPage(true)
{
fPageInfo.SetStrings(age, page);
char filePath[512];
// Copy the path over
strncpy(filePath, dataPath, sizeof(filePath));
plFileUtils::AddSlash(filePath);
// Time to construct our actual file name. For now, we'll use the same old format
// of age_page.extension
strncat(filePath, fPageInfo.GetAge(), sizeof(filePath));
strncat(filePath, "_District_", sizeof(filePath));
strncat(filePath, fPageInfo.GetPage(), sizeof(filePath));
strncat(filePath, ".prp", sizeof(filePath));
fPath = hsStrcpy(filePath);
}
plRegistryPageNode::~plRegistryPageNode()
{
delete [] fPath;
UnloadKeys();
}
PageCond plRegistryPageNode::IVerify()
{
// Check the checksum values first, to make sure the files aren't corrupt
UInt32 ourChecksum = 0;
hsStream* stream = OpenStream();
if (stream)
{
ourChecksum = stream->GetEOF() - fPageInfo.GetDataStart();
CloseStream();
}
if (ourChecksum != fPageInfo.GetChecksum())
return kPageCorrupt;
// If major version out-of-date, entire location is screwed
if (fPageInfo.GetMajorVersion() > plVersion::GetMajorVersion())
return kPageTooNew;
else if (fPageInfo.GetMajorVersion() < plVersion::GetMajorVersion())
return kPageOutOfDate;
// Check the minor versions
const plPageInfo::ClassVerVec& classVersions = fPageInfo.GetClassVersions();
for (int i = 0; i < classVersions.size(); i++)
{
const plPageInfo::ClassVersion& cv = classVersions[i];
UInt16 curVersion = plVersion::GetCreatableVersion(cv.Class);
if (curVersion > cv.Version)
return kPageOutOfDate;
else if (curVersion < cv.Version)
return kPageTooNew;
}
return kPageOk;
}
hsStream* plRegistryPageNode::OpenStream()
{
if (fOpenRequests == 0)
{
if (!fStream.Open(fPath, "rb"))
return nil;
}
fOpenRequests++;
return &fStream;
}
void plRegistryPageNode::CloseStream()
{
if (fOpenRequests > 0)
fOpenRequests--;
if (fOpenRequests == 0)
fStream.Close();
}
void plRegistryPageNode::LoadKeys()
{
hsAssert(IsValid(), "Trying to load keys for invalid page");
hsAssert(!fIsNewPage, "Trying to read a new page");
if (IsFullyLoaded())
return;
hsStream* stream = OpenStream();
if (!stream)
{
hsAssert(0, xtl::format("plRegistryPageNode::LoadKeysFromSource - bad stream %s,%s",
GetPageInfo().GetAge(), GetPageInfo().GetPage()).c_str());
return;
}
// If we're loading keys in the middle of a read because FindKey() failed, we'd better
// make note of our stream position and restore it when we're done.
UInt32 oldPos = stream->GetPosition();
stream->SetPosition(GetPageInfo().GetIndexStart());
// Read in the number of key types
UInt32 numTypes = stream->ReadSwap32();
for (UInt32 i = 0; i < numTypes; i++)
{
UInt16 classType = stream->ReadSwap16();
plRegistryKeyList* keyList = IGetKeyList(classType);
if (!keyList)
{
keyList = TRACKED_NEW plRegistryKeyList(classType);
fKeyLists[classType] = keyList;
}
keyList->Read(stream);
}
stream->SetPosition(oldPos);
CloseStream();
fStaticLoadedTypes = fKeyLists.size();
}
void plRegistryPageNode::UnloadKeys()
{
KeyMap::iterator it = fKeyLists.begin();
for (; it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
delete keyList;
}
fKeyLists.clear();
fDynLoadedTypes = 0;
fStaticLoadedTypes = 0;
}
//// plWriteIterator /////////////////////////////////////////////////////////
// Key iterator for writing objects
class plWriteIterator : public plRegistryKeyIterator
{
protected:
hsStream* fStream;
public:
plWriteIterator(hsStream* s) : fStream(s) {}
virtual hsBool EatKey(const plKey& key)
{
plKeyImp* imp = (plKeyImp*)key;
imp->WriteObject(fStream);
return true;
}
};
void plRegistryPageNode::Write()
{
hsAssert(fOpenRequests == 0, "Trying to write while the page is open for reading");
if (!fStream.Open(fPath, "wb"))
{
hsAssert(0, "Couldn't open file for writing");
return;
}
// Some prep stuff. Assign object IDs for every key in this page, and put the
// versions of all our creatable types in the pageinfo.
fPageInfo.ClearClassVersions();
KeyMap::const_iterator it;
for (it = fKeyLists.begin(); it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
keyList->PrepForWrite();
int ver = plVersion::GetCreatableVersion(keyList->GetClassType());
fPageInfo.AddClassVersion(keyList->GetClassType(), ver);
}
// First thing we write is the pageinfo. Later we'll rewind and overwrite this with the final values
fPageInfo.Write(&fStream);
fPageInfo.SetDataStart(fStream.GetPosition());
// Write all our objects
plWriteIterator writer(&fStream);
IterateKeys(&writer);
fPageInfo.SetIndexStart(fStream.GetPosition());
// Write our keys
fStream.WriteSwap32(fKeyLists.size());
for (it = fKeyLists.begin(); it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
fStream.WriteSwap16(keyList->GetClassType());
keyList->Write(&fStream);
}
// Rewind and write the pageinfo with the correct data and index offsets
fStream.Rewind();
fPageInfo.SetChecksum(fStream.GetEOF() - fPageInfo.GetDataStart());
fPageInfo.Write(&fStream);
fStream.Close();
}
//// IterateKeys /////////////////////////////////////////////////////////////
hsBool plRegistryPageNode::IterateKeys(plRegistryKeyIterator* iterator) const
{
KeyMap::const_iterator it = fKeyLists.begin();
for (; it != fKeyLists.end(); it++)
{
plRegistryKeyList* keyList = it->second;
if (!keyList->IterateKeys(iterator))
return false;
}
return true;
}
//// IterateKeys /////////////////////////////////////////////////////////////
// Restricted version that only iterates through the keys of a given class
// type.
hsBool plRegistryPageNode::IterateKeys(plRegistryKeyIterator* iterator, UInt16 classToRestrictTo) const
{
plRegistryKeyList* keyList = IGetKeyList(classToRestrictTo);
if (keyList != nil)
return keyList->IterateKeys(iterator);
return true;
}
plKeyImp* plRegistryPageNode::FindKey(UInt16 classType, const char* name) const
{
plRegistryKeyList* keys = IGetKeyList(classType);
if (keys == nil)
return nil;
return keys->FindKey(name);
}
plKeyImp* plRegistryPageNode::FindKey(const plUoid& uoid) const
{
plRegistryKeyList* keys = IGetKeyList(uoid.GetClassType());
if (keys == nil)
return nil;
return keys->FindKey(uoid);
}
void plRegistryPageNode::AddKey(plKeyImp* key)
{
UInt16 classType = key->GetUoid().GetClassType();
plRegistryKeyList* keys = fKeyLists[classType];
if (keys == nil)
{
keys = TRACKED_NEW plRegistryKeyList(classType);
fKeyLists[classType] = keys;
}
// Error check
if (keys->FindKey(key->GetUoid().GetObjectName()) != nil)
{
//char str[512], tempStr[128];
//sprintf(str, "Attempting to add a key with a duplicate name. Not allowed."
// "\n\n(Key name: %s, Class: %s, Loc: %s)", key->GetUoid().GetObjectName(),
// plFactory::GetNameOfClass(classType), key->GetUoid().GetLocation().StringIze(tempStr));
//hsStatusMessage(str);
hsBool recovered = false;
// Attempt recovery
for (int i = 0; i < 500; i++)
{
char tempName[512];
sprintf(tempName, "%s%d", key->GetUoid().GetObjectName(), i);
if (keys->FindKey(tempName) == nil)
{
plUoid uoid(key->GetUoid().GetLocation(), key->GetUoid().GetClassType(), tempName, key->GetUoid().GetLoadMask());
key->SetUoid(uoid);
recovered = true;
break;
}
}
if (!recovered)
{
hsAssert(0, "Couldn't allocate a unique key");
return;
}
}
plRegistryKeyList::LoadStatus loadStatusChange;
keys->AddKey(key, loadStatusChange);
if (loadStatusChange == plRegistryKeyList::kDynLoaded)
fDynLoadedTypes++;
}
void plRegistryPageNode::SetKeyUsed(plKeyImp* key)
{
plRegistryKeyList* keys = IGetKeyList(key->GetUoid().GetClassType());
if (keys == nil)
return;
keys->SetKeyUsed(key);
}
hsBool plRegistryPageNode::SetKeyUnused(plKeyImp* key)
{
plRegistryKeyList* keys = IGetKeyList(key->GetUoid().GetClassType());
if (keys == nil)
return false;
plRegistryKeyList::LoadStatus loadStatusChange;
hsBool removed = keys->SetKeyUnused(key, loadStatusChange);
// If the key type just changed load status, update our load counts
if (loadStatusChange == plRegistryKeyList::kDynUnloaded)
fDynLoadedTypes--;
else if (loadStatusChange == plRegistryKeyList::kStaticUnloaded)
fStaticLoadedTypes--;
return removed;
}
plRegistryKeyList* plRegistryPageNode::IGetKeyList(UInt16 classType) const
{
KeyMap::const_iterator it = fKeyLists.find(classType);
if (it != fKeyLists.end())
return it->second;
return nil;
}
void plRegistryPageNode::DeleteSource()
{
hsAssert(fOpenRequests == 0, "Deleting a stream that's open for reading");
plFileUtils::RemoveFile(fPath);
}

View File

@ -1,132 +1,132 @@
/*==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/>.
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 plRegistryNode_h_inc
#define plRegistryNode_h_inc
#include "hsTypes.h"
#include "hsStream.h"
#include "plPageInfo.h"
#include <map>
class plRegistryKeyList;
class hsStream;
class plKeyImp;
class plRegistryKeyIterator;
enum PageCond
{
kPageOk,
kPageOutOfDate,
kPageTooNew,
kPageCorrupt,
};
//
// Represents one entire (age,page) location and contains all keys in that
// location. Note: just because the node exists does not mean that the keys are loaded.
//
class plRegistryPageNode
{
protected:
friend class plKeyFinder;
// Map from class type to a list of keys of that type
typedef std::map<UInt16, plRegistryKeyList*> KeyMap;
KeyMap fKeyLists;
int fDynLoadedTypes; // The number of key types that have dynamic keys loaded
int fStaticLoadedTypes; // The number of key types that have all their keys loaded
PageCond fValid; // Condition of the page
char* fPath; // Path to the page file
plPageInfo fPageInfo; // Info about this page
hsBufferedStream fStream; // Stream for reading/writing our page
UInt8 fOpenRequests; // How many handles there are to fStream (or
// zero if it's closed)
hsBool fIsNewPage; // True if this page is new (not read off disk)
plRegistryPageNode() {}
inline plRegistryKeyList* IGetKeyList(UInt16 classType) const;
PageCond IVerify();
public:
// For reading a page off disk
plRegistryPageNode(const char* path);
// For creating a new page.
plRegistryPageNode(const plLocation& location, const char* age, const char* page, const char* dataPath);
~plRegistryPageNode();
hsBool IsValid() const { return fValid == kPageOk; }
PageCond GetPageCondition() { return fValid; }
// True if we have any static or dynamic keys loaded
hsBool IsLoaded() const { return fDynLoadedTypes > 0 || fStaticLoadedTypes > 0; }
// True if all of our static keys are loaded
hsBool IsFullyLoaded() const { return (fStaticLoadedTypes == fKeyLists.size() && !fKeyLists.empty()) || fIsNewPage; }
// Export time only. If we want to reuse a page, load the keys we want then
// call SetNewPage, so it will be considered a new page from now on. That
// way we won't try to load it's keys again.
hsBool IsNewPage() const { return fIsNewPage; }
void SetNewPage() { fIsNewPage = true; }
const plPageInfo& GetPageInfo() const { return fPageInfo; }
void LoadKeys(); // Loads the keys off disk
void UnloadKeys(); // Frees all our keys
// Find a key by type and name
plKeyImp* FindKey(UInt16 classType, const char* name) const;
// Find a key by direct uoid lookup (or fallback to name lookup if that doesn't work)
plKeyImp* FindKey(const plUoid& uoid) const;
void AddKey(plKeyImp* key);
// Sets a key as used or unused, ie there aren't any refs to it anymore.
// When all the static keys are unused we can free the memory associated with
// them. When a dynamic key is unused we just delete it right away.
void SetKeyUsed(plKeyImp* key);
hsBool SetKeyUnused(plKeyImp* key);
hsBool IterateKeys(plRegistryKeyIterator* iterator) const;
hsBool IterateKeys(plRegistryKeyIterator* iterator, UInt16 classToRestrictTo) const;
// Call this to get a read stream for the page. If a valid pointer is
// returned, make sure to call CloseStream when you're done using it.
hsStream* OpenStream();
void CloseStream();
// Takes care of everything involved in writing this page to disk
void Write();
void DeleteSource();
const char* GetPagePath() const { return fPath; }
};
#endif // plRegistryNode_h_inc
/*==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/>.
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 plRegistryNode_h_inc
#define plRegistryNode_h_inc
#include "hsTypes.h"
#include "hsStream.h"
#include "plPageInfo.h"
#include <map>
class plRegistryKeyList;
class hsStream;
class plKeyImp;
class plRegistryKeyIterator;
enum PageCond
{
kPageOk,
kPageOutOfDate,
kPageTooNew,
kPageCorrupt,
};
//
// Represents one entire (age,page) location and contains all keys in that
// location. Note: just because the node exists does not mean that the keys are loaded.
//
class plRegistryPageNode
{
protected:
friend class plKeyFinder;
// Map from class type to a list of keys of that type
typedef std::map<UInt16, plRegistryKeyList*> KeyMap;
KeyMap fKeyLists;
int fDynLoadedTypes; // The number of key types that have dynamic keys loaded
int fStaticLoadedTypes; // The number of key types that have all their keys loaded
PageCond fValid; // Condition of the page
char* fPath; // Path to the page file
plPageInfo fPageInfo; // Info about this page
hsBufferedStream fStream; // Stream for reading/writing our page
UInt8 fOpenRequests; // How many handles there are to fStream (or
// zero if it's closed)
hsBool fIsNewPage; // True if this page is new (not read off disk)
plRegistryPageNode() {}
inline plRegistryKeyList* IGetKeyList(UInt16 classType) const;
PageCond IVerify();
public:
// For reading a page off disk
plRegistryPageNode(const char* path);
// For creating a new page.
plRegistryPageNode(const plLocation& location, const char* age, const char* page, const char* dataPath);
~plRegistryPageNode();
hsBool IsValid() const { return fValid == kPageOk; }
PageCond GetPageCondition() { return fValid; }
// True if we have any static or dynamic keys loaded
hsBool IsLoaded() const { return fDynLoadedTypes > 0 || fStaticLoadedTypes > 0; }
// True if all of our static keys are loaded
hsBool IsFullyLoaded() const { return (fStaticLoadedTypes == fKeyLists.size() && !fKeyLists.empty()) || fIsNewPage; }
// Export time only. If we want to reuse a page, load the keys we want then
// call SetNewPage, so it will be considered a new page from now on. That
// way we won't try to load it's keys again.
hsBool IsNewPage() const { return fIsNewPage; }
void SetNewPage() { fIsNewPage = true; }
const plPageInfo& GetPageInfo() const { return fPageInfo; }
void LoadKeys(); // Loads the keys off disk
void UnloadKeys(); // Frees all our keys
// Find a key by type and name
plKeyImp* FindKey(UInt16 classType, const char* name) const;
// Find a key by direct uoid lookup (or fallback to name lookup if that doesn't work)
plKeyImp* FindKey(const plUoid& uoid) const;
void AddKey(plKeyImp* key);
// Sets a key as used or unused, ie there aren't any refs to it anymore.
// When all the static keys are unused we can free the memory associated with
// them. When a dynamic key is unused we just delete it right away.
void SetKeyUsed(plKeyImp* key);
hsBool SetKeyUnused(plKeyImp* key);
hsBool IterateKeys(plRegistryKeyIterator* iterator) const;
hsBool IterateKeys(plRegistryKeyIterator* iterator, UInt16 classToRestrictTo) const;
// Call this to get a read stream for the page. If a valid pointer is
// returned, make sure to call CloseStream when you're done using it.
hsStream* OpenStream();
void CloseStream();
// Takes care of everything involved in writing this page to disk
void Write();
void DeleteSource();
const char* GetPagePath() const { return fPath; }
};
#endif // plRegistryNode_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,227 +1,227 @@
/*==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/>.
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 plResManager_h_inc
#define plResManager_h_inc
#include "hsResMgr.h"
#include <set>
#include <map>
#include <vector>
class plRegistryPageNode;
class plRegistryKeyIterator;
class plRegistryPageIterator;
class plRegistryDataStream;
class plResAgeHolder;
class plResManagerHelper;
class plDispatch;
// plProgressProc is a proc called every time an object loads, to keep a progress bar for
// loading ages up-to-date.
typedef void(*plProgressProc)(plKey key);
class plResManager : public hsResMgr
{
public:
plResManager();
virtual ~plResManager();
// If the ResManager has already been initialized, you should call Reset after setting this
void SetDataPath(const char* path) { fDataPath = path; }
// Mainly for external tools.
void AddSinglePage(const char* path);
plRegistryPageNode* FindSinglePage(const char* path) const;
void RemoveSinglePage(const char* path);
//---------------------------
// Load and Unload
//---------------------------
virtual void Load (const plKey& objKey); // places on list to be loaded
virtual hsBool Unload(const plKey& objKey); // Unregisters (deletes) an object, Return true if successful
virtual plKey CloneKey(const plKey& objKey);
//---------------------------
// Finding Functions
//---------------------------
plKey FindOriginalKey(const plUoid&);
virtual plKey FindKey(const plUoid&); // Same as above, but will check the uoid for clones
const plLocation& FindLocation(const char* age, const char* page) const;
// Use nil for any strings you don't need
const void GetLocationStrings(const plLocation& loc, char* ageBuffer, char* pageBuffer) const;
//---------------------------
// Establish reference linkage
//---------------------------
virtual hsBool AddViaNotify(const plKey& key, plRefMsg* msg, plRefFlags::Type flags);
virtual hsBool AddViaNotify(plRefMsg* msg, plRefFlags::Type flags); // msg->fRef->GetKey() == sentKey
virtual hsBool SendRef(const plKey& key, plRefMsg* refMsg, plRefFlags::Type flags);
virtual hsBool SendRef(hsKeyedObject* ko, plRefMsg* refMsg, plRefFlags::Type flags);
//---------------------------
// Reding and Writing keys
//---------------------------
// Read a Key in, and Notify me when the Object is loaded
virtual plKey ReadKeyNotifyMe(hsStream* stream, plRefMsg* retMsg, plRefFlags::Type flags);
// Just read the Key data in and find a match in the registry and return it.
virtual plKey ReadKey(hsStream* stream);
// For convenience you can write a key using the KeyedObject or the Key...same result
virtual void WriteKey(hsStream* s, hsKeyedObject* obj);
virtual void WriteKey(hsStream* s, const plKey& key);
//---------------------------
// Reding and Writing Objects directly
//---------------------------
virtual plCreatable* ReadCreatable(hsStream* s);
virtual void WriteCreatable(hsStream* s, plCreatable* cre);
virtual plCreatable* ReadCreatableVersion(hsStream* s);
virtual void WriteCreatableVersion(hsStream* s, plCreatable* cre);
//---------------------------
// Registry Modification Functions
//---------------------------
virtual plKey NewKey(const char* name, hsKeyedObject* object, const plLocation& loc, const plLoadMask& m = plLoadMask::kAlways);
virtual plKey NewKey(plUoid& newUoid, hsKeyedObject* object);
virtual plDispatchBase* Dispatch();
virtual void SetProgressBarProc(plProgressProc proc);
//---------------------------
// Load optimizations
//---------------------------
void LoadAgeKeys(const char* age);
void DropAgeKeys(const char* age);
void PageInRoom(const plLocation& page, UInt16 objClassToRef, plRefMsg* refMsg);
void PageInAge(const char* age);
// Usually, a page file is kept open during load because the first keyed object
// read causes all the other objects to be read before it returns. In some
// cases though (mostly just the texture file), this doesn't work. In that
// case, we just want to force it to stay open until we're done reading the age.
void KeepPageOpen(const plLocation& page, hsBool keepOpen);
// We're on the way down, act accordingly.
virtual void BeginShutdown();
// Determines whether the time to read each object is dumped to a log
void LogReadTimes(hsBool logReadTimes);
// All keys version
hsBool IterateKeys(plRegistryKeyIterator* iterator);
// Single page version
hsBool IterateKeys(plRegistryKeyIterator* iterator, const plLocation& pageToRestrictTo);
// Iterate through loaded pages
hsBool IteratePages(plRegistryPageIterator* iterator, const char* ageToRestrictTo = nil);
// Iterate through ALL pages, loaded or not
hsBool IterateAllPages(plRegistryPageIterator* iterator);
// Helpers for key iterators
void LoadPageKeys(plRegistryPageNode* pageNode);
void UnloadPageObjects(plRegistryPageNode* pageNode, UInt16 classIndexHint);
void DumpUnusedKeys(plRegistryPageNode* page) const;
plRegistryPageNode* FindPage(const plLocation& location) const;
plRegistryPageNode* FindPage(const char* age, const char* page) const;
// Runs through all the pages and verifies that the data versions are good
hsBool VerifyPages();
protected:
friend class hsKeyedObject;
friend class plKeyImp;
friend class plResManagerHelper;
virtual plKey ReRegister(const char* nm, const plUoid& uoid);
virtual hsBool ReadObject(plKeyImp* key); // plKeys call this when needed
virtual hsBool IReadObject(plKeyImp* pKey, hsStream *stream);
plCreatable* IReadCreatable(hsStream* s) const;
plKey ICloneKey(const plUoid& objUoid, UInt32 playerID, UInt32 cloneID);
virtual void IKeyReffed(plKeyImp* key);
virtual void IKeyUnreffed(plKeyImp* key);
virtual hsBool IReset();
virtual hsBool IInit();
virtual void IShutdown();
void IPageOutSceneNodes(hsBool forceAll);
void IDropAllAgeKeys();
hsKeyedObject* IGetSharedObject(plKeyImp* pKey);
void IUnloadPageKeys(plRegistryPageNode* pageNode, hsBool dontClear = false);
hsBool IDeleteBadPages(hsTArray<plRegistryPageNode*>& invalidPages, hsBool conflictingSeqNums);
hsBool IWarnNewerPages(hsTArray<plRegistryPageNode*>& newerPages);
void ILockPages();
void IUnlockPages();
void AddPage(plRegistryPageNode* page);
// Adds a key to the registry. Assumes uoid already set
void AddKey(plKeyImp* key);
plRegistryPageNode* CreatePage(const plLocation& location, const char* age, const char* page);
hsBool fInited;
UInt16 fPageOutHint;
// True if we're reading in an object. We only read one object at a time
hsBool fReadingObject;
std::vector<plKey> fQueuedReads;
std::string fDataPath;
plDispatch* fDispatch;
UInt32 fCurCloneID; // Current clone ID. If it isn't zero, we're cloning
UInt32 fCurClonePlayerID;
UInt32 fCloningCounter; // Next clone ID to use.
typedef std::map<std::string,plResAgeHolder*> HeldAgeKeyMap;
HeldAgeKeyMap fHeldAgeKeys;
plProgressProc fProgressProc;
plResManagerHelper *fMyHelper;
hsBool fLogReadTimes;
UInt8 fPageListLock; // Number of locks on the page lists. If it's greater than zero, they can't be modified
hsBool fPagesNeedCleanup; // True if something modified the page lists while they were locked.
typedef std::set<plRegistryPageNode*> PageSet;
PageSet fAllPages; // All the pages, loaded or not
PageSet fLoadedPages; // Just the loaded pages
mutable plRegistryPageNode* fLastFoundPage;
};
#endif // plResManager_h_inc
/*==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/>.
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 plResManager_h_inc
#define plResManager_h_inc
#include "hsResMgr.h"
#include <set>
#include <map>
#include <vector>
class plRegistryPageNode;
class plRegistryKeyIterator;
class plRegistryPageIterator;
class plRegistryDataStream;
class plResAgeHolder;
class plResManagerHelper;
class plDispatch;
// plProgressProc is a proc called every time an object loads, to keep a progress bar for
// loading ages up-to-date.
typedef void(*plProgressProc)(plKey key);
class plResManager : public hsResMgr
{
public:
plResManager();
virtual ~plResManager();
// If the ResManager has already been initialized, you should call Reset after setting this
void SetDataPath(const char* path) { fDataPath = path; }
// Mainly for external tools.
void AddSinglePage(const char* path);
plRegistryPageNode* FindSinglePage(const char* path) const;
void RemoveSinglePage(const char* path);
//---------------------------
// Load and Unload
//---------------------------
virtual void Load (const plKey& objKey); // places on list to be loaded
virtual hsBool Unload(const plKey& objKey); // Unregisters (deletes) an object, Return true if successful
virtual plKey CloneKey(const plKey& objKey);
//---------------------------
// Finding Functions
//---------------------------
plKey FindOriginalKey(const plUoid&);
virtual plKey FindKey(const plUoid&); // Same as above, but will check the uoid for clones
const plLocation& FindLocation(const char* age, const char* page) const;
// Use nil for any strings you don't need
const void GetLocationStrings(const plLocation& loc, char* ageBuffer, char* pageBuffer) const;
//---------------------------
// Establish reference linkage
//---------------------------
virtual hsBool AddViaNotify(const plKey& key, plRefMsg* msg, plRefFlags::Type flags);
virtual hsBool AddViaNotify(plRefMsg* msg, plRefFlags::Type flags); // msg->fRef->GetKey() == sentKey
virtual hsBool SendRef(const plKey& key, plRefMsg* refMsg, plRefFlags::Type flags);
virtual hsBool SendRef(hsKeyedObject* ko, plRefMsg* refMsg, plRefFlags::Type flags);
//---------------------------
// Reding and Writing keys
//---------------------------
// Read a Key in, and Notify me when the Object is loaded
virtual plKey ReadKeyNotifyMe(hsStream* stream, plRefMsg* retMsg, plRefFlags::Type flags);
// Just read the Key data in and find a match in the registry and return it.
virtual plKey ReadKey(hsStream* stream);
// For convenience you can write a key using the KeyedObject or the Key...same result
virtual void WriteKey(hsStream* s, hsKeyedObject* obj);
virtual void WriteKey(hsStream* s, const plKey& key);
//---------------------------
// Reding and Writing Objects directly
//---------------------------
virtual plCreatable* ReadCreatable(hsStream* s);
virtual void WriteCreatable(hsStream* s, plCreatable* cre);
virtual plCreatable* ReadCreatableVersion(hsStream* s);
virtual void WriteCreatableVersion(hsStream* s, plCreatable* cre);
//---------------------------
// Registry Modification Functions
//---------------------------
virtual plKey NewKey(const char* name, hsKeyedObject* object, const plLocation& loc, const plLoadMask& m = plLoadMask::kAlways);
virtual plKey NewKey(plUoid& newUoid, hsKeyedObject* object);
virtual plDispatchBase* Dispatch();
virtual void SetProgressBarProc(plProgressProc proc);
//---------------------------
// Load optimizations
//---------------------------
void LoadAgeKeys(const char* age);
void DropAgeKeys(const char* age);
void PageInRoom(const plLocation& page, UInt16 objClassToRef, plRefMsg* refMsg);
void PageInAge(const char* age);
// Usually, a page file is kept open during load because the first keyed object
// read causes all the other objects to be read before it returns. In some
// cases though (mostly just the texture file), this doesn't work. In that
// case, we just want to force it to stay open until we're done reading the age.
void KeepPageOpen(const plLocation& page, hsBool keepOpen);
// We're on the way down, act accordingly.
virtual void BeginShutdown();
// Determines whether the time to read each object is dumped to a log
void LogReadTimes(hsBool logReadTimes);
// All keys version
hsBool IterateKeys(plRegistryKeyIterator* iterator);
// Single page version
hsBool IterateKeys(plRegistryKeyIterator* iterator, const plLocation& pageToRestrictTo);
// Iterate through loaded pages
hsBool IteratePages(plRegistryPageIterator* iterator, const char* ageToRestrictTo = nil);
// Iterate through ALL pages, loaded or not
hsBool IterateAllPages(plRegistryPageIterator* iterator);
// Helpers for key iterators
void LoadPageKeys(plRegistryPageNode* pageNode);
void UnloadPageObjects(plRegistryPageNode* pageNode, UInt16 classIndexHint);
void DumpUnusedKeys(plRegistryPageNode* page) const;
plRegistryPageNode* FindPage(const plLocation& location) const;
plRegistryPageNode* FindPage(const char* age, const char* page) const;
// Runs through all the pages and verifies that the data versions are good
hsBool VerifyPages();
protected:
friend class hsKeyedObject;
friend class plKeyImp;
friend class plResManagerHelper;
virtual plKey ReRegister(const char* nm, const plUoid& uoid);
virtual hsBool ReadObject(plKeyImp* key); // plKeys call this when needed
virtual hsBool IReadObject(plKeyImp* pKey, hsStream *stream);
plCreatable* IReadCreatable(hsStream* s) const;
plKey ICloneKey(const plUoid& objUoid, UInt32 playerID, UInt32 cloneID);
virtual void IKeyReffed(plKeyImp* key);
virtual void IKeyUnreffed(plKeyImp* key);
virtual hsBool IReset();
virtual hsBool IInit();
virtual void IShutdown();
void IPageOutSceneNodes(hsBool forceAll);
void IDropAllAgeKeys();
hsKeyedObject* IGetSharedObject(plKeyImp* pKey);
void IUnloadPageKeys(plRegistryPageNode* pageNode, hsBool dontClear = false);
hsBool IDeleteBadPages(hsTArray<plRegistryPageNode*>& invalidPages, hsBool conflictingSeqNums);
hsBool IWarnNewerPages(hsTArray<plRegistryPageNode*>& newerPages);
void ILockPages();
void IUnlockPages();
void AddPage(plRegistryPageNode* page);
// Adds a key to the registry. Assumes uoid already set
void AddKey(plKeyImp* key);
plRegistryPageNode* CreatePage(const plLocation& location, const char* age, const char* page);
hsBool fInited;
UInt16 fPageOutHint;
// True if we're reading in an object. We only read one object at a time
hsBool fReadingObject;
std::vector<plKey> fQueuedReads;
std::string fDataPath;
plDispatch* fDispatch;
UInt32 fCurCloneID; // Current clone ID. If it isn't zero, we're cloning
UInt32 fCurClonePlayerID;
UInt32 fCloningCounter; // Next clone ID to use.
typedef std::map<std::string,plResAgeHolder*> HeldAgeKeyMap;
HeldAgeKeyMap fHeldAgeKeys;
plProgressProc fProgressProc;
plResManagerHelper *fMyHelper;
hsBool fLogReadTimes;
UInt8 fPageListLock; // Number of locks on the page lists. If it's greater than zero, they can't be modified
hsBool fPagesNeedCleanup; // True if something modified the page lists while they were locked.
typedef std::set<plRegistryPageNode*> PageSet;
PageSet fAllPages; // All the pages, loaded or not
PageSet fLoadedPages; // Just the loaded pages
mutable plRegistryPageNode* fLastFoundPage;
};
#endif // plResManager_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,130 +1,130 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plResManagerHelper - The wonderful helper class that can receive messages
// for the resManager.
//
//// History /////////////////////////////////////////////////////////////////
//
// 6.7.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plResManagerHelper_h
#define _plResManagerHelper_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "plRegistryHelpers.h"
#include "pnKeyedObject/hsKeyedObject.h"
// Defined as a project setting so we can do this right
//#define MCN_RESMGR_DEBUGGING
//// Class Definition ////////////////////////////////////////////////////////
#ifdef MCN_RESMGR_DEBUGGING
class plStatusLog;
class plDebugPrintIterator;
class plResMgrDebugInterface;
#endif
class plResManager;
class plRegistryPageNode;
class plResManagerHelper : public hsKeyedObject
{
protected:
plResManager *fResManager;
static plResManagerHelper *fInstance;
hsBool fInShutdown;
#ifdef MCN_RESMGR_DEBUGGING
friend class plDebugPrintIterator;
friend class plResMgrDebugInterface;
plStatusLog *fDebugScreen;
hsBool fRefreshing, fCurrAgeExpanded;
int fCurrAge;
int fDebugDisplayType;
enum DebugDisplayTypes
{
kSizes = 0,
kPercents,
kBars,
kMaxDisplayType
};
plResMgrDebugInterface *fDebugInput;
#endif
void IUpdateDebugScreen( hsBool force = false );
public:
plResManagerHelper( plResManager *resMgr );
virtual ~plResManagerHelper();
CLASSNAME_REGISTER( plResManagerHelper );
GETINTERFACE_ANY( plResManagerHelper, hsKeyedObject );
virtual hsBool MsgReceive( plMessage *msg );
virtual void Read( hsStream *s, hsResMgr *mgr );
virtual void Write( hsStream *s, hsResMgr *mgr );
void Init( void );
void Shutdown( void );
void LoadAndHoldPageKeys( plRegistryPageNode *page );
void EnableDebugScreen( hsBool enable );
// Please let the res manager handle telling this.
void SetInShutdown(hsBool b) { fInShutdown = b; }
hsBool GetInShutdown() const { return fInShutdown; }
static plResManagerHelper *GetInstance( void ) { return fInstance; }
};
//// Reffer Class ////////////////////////////////////////////////////////////
class plResPageKeyRefList : public plKeyCollector
{
protected:
hsTArray<plKey> fKeyList;
public:
plResPageKeyRefList() : plKeyCollector( fKeyList ) {}
virtual ~plResPageKeyRefList() { fKeyList.Reset(); }
};
#endif // _plResManagerHelper_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plResManagerHelper - The wonderful helper class that can receive messages
// for the resManager.
//
//// History /////////////////////////////////////////////////////////////////
//
// 6.7.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plResManagerHelper_h
#define _plResManagerHelper_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "plRegistryHelpers.h"
#include "pnKeyedObject/hsKeyedObject.h"
// Defined as a project setting so we can do this right
//#define MCN_RESMGR_DEBUGGING
//// Class Definition ////////////////////////////////////////////////////////
#ifdef MCN_RESMGR_DEBUGGING
class plStatusLog;
class plDebugPrintIterator;
class plResMgrDebugInterface;
#endif
class plResManager;
class plRegistryPageNode;
class plResManagerHelper : public hsKeyedObject
{
protected:
plResManager *fResManager;
static plResManagerHelper *fInstance;
hsBool fInShutdown;
#ifdef MCN_RESMGR_DEBUGGING
friend class plDebugPrintIterator;
friend class plResMgrDebugInterface;
plStatusLog *fDebugScreen;
hsBool fRefreshing, fCurrAgeExpanded;
int fCurrAge;
int fDebugDisplayType;
enum DebugDisplayTypes
{
kSizes = 0,
kPercents,
kBars,
kMaxDisplayType
};
plResMgrDebugInterface *fDebugInput;
#endif
void IUpdateDebugScreen( hsBool force = false );
public:
plResManagerHelper( plResManager *resMgr );
virtual ~plResManagerHelper();
CLASSNAME_REGISTER( plResManagerHelper );
GETINTERFACE_ANY( plResManagerHelper, hsKeyedObject );
virtual hsBool MsgReceive( plMessage *msg );
virtual void Read( hsStream *s, hsResMgr *mgr );
virtual void Write( hsStream *s, hsResMgr *mgr );
void Init( void );
void Shutdown( void );
void LoadAndHoldPageKeys( plRegistryPageNode *page );
void EnableDebugScreen( hsBool enable );
// Please let the res manager handle telling this.
void SetInShutdown(hsBool b) { fInShutdown = b; }
hsBool GetInShutdown() const { return fInShutdown; }
static plResManagerHelper *GetInstance( void ) { return fInstance; }
};
//// Reffer Class ////////////////////////////////////////////////////////////
class plResPageKeyRefList : public plKeyCollector
{
protected:
hsTArray<plKey> fKeyList;
public:
plResPageKeyRefList() : plKeyCollector( fKeyList ) {}
virtual ~plResPageKeyRefList() { fKeyList.Reset(); }
};
#endif // _plResManagerHelper_h

View File

@ -1,29 +1,29 @@
/*==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/>.
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==*/
// Future home of plResMgr
/*==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/>.
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==*/
// Future home of plResMgr

View File

@ -1,26 +1,26 @@
/*==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/>.
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==*/
// Future home of plResMgr
/*==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/>.
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==*/
// Future home of plResMgr

View File

@ -1,37 +1,37 @@
/*==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/>.
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 plResMgrCreatable_inc
#define plResMgrCreatable_inc
#include "pnFactory/plCreator.h"
#include "plResManagerHelper.h"
REGISTER_NONCREATABLE(plResManagerHelper);
#endif // plResMgrCreatable_inc
/*==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/>.
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 plResMgrCreatable_inc
#define plResMgrCreatable_inc
#include "pnFactory/plCreator.h"
#include "plResManagerHelper.h"
REGISTER_NONCREATABLE(plResManagerHelper);
#endif // plResMgrCreatable_inc

View File

@ -1,92 +1,92 @@
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plResMgrSettings - Class that holds all the various settings for
// plResManager
//
//// History /////////////////////////////////////////////////////////////////
//
// 6.22.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plResMgrSettings_h
#define _plResMgrSettings_h
#include "hsTypes.h"
class plResMgrSettings
{
protected:
friend class plResManager;
bool fFilterOlderPageVersions;
bool fFilterNewerPageVersions;
UInt8 fLoggingLevel;
bool fPassiveKeyRead;
bool fLoadPagesOnInit;
plResMgrSettings()
{
fFilterOlderPageVersions = true;
fFilterNewerPageVersions = true;
fPassiveKeyRead = false;
fLoadPagesOnInit = true;
fLoggingLevel = 0;
}
public:
enum LogLevels
{
kNoLogging = 0,
kBasicLogging = 1,
kDetailedLogging = 2,
kObjectLogging = 3,
kObjectDetailLogging = 4
};
bool GetFilterOlderPageVersions() const { return fFilterOlderPageVersions; }
void SetFilterOlderPageVersions(bool f) { fFilterOlderPageVersions = f; }
bool GetFilterNewerPageVersions() const { return fFilterNewerPageVersions; }
void SetFilterNewerPageVersions(bool f) { fFilterNewerPageVersions = f; }
UInt8 GetLoggingLevel() const { return fLoggingLevel; }
void SetLoggingLevel(UInt8 level) { fLoggingLevel = level; }
bool GetPassiveKeyRead() const { return fPassiveKeyRead; }
void SetPassiveKeyRead(bool p) { fPassiveKeyRead = p; }
bool GetLoadPagesOnInit() const { return fLoadPagesOnInit; }
void SetLoadPagesOnInit(bool load) { fLoadPagesOnInit = load; }
static plResMgrSettings& Get();
};
#endif // _plResMgrSettings_h
/*==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/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
//
// plResMgrSettings - Class that holds all the various settings for
// plResManager
//
//// History /////////////////////////////////////////////////////////////////
//
// 6.22.2002 mcn - Created
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _plResMgrSettings_h
#define _plResMgrSettings_h
#include "hsTypes.h"
class plResMgrSettings
{
protected:
friend class plResManager;
bool fFilterOlderPageVersions;
bool fFilterNewerPageVersions;
UInt8 fLoggingLevel;
bool fPassiveKeyRead;
bool fLoadPagesOnInit;
plResMgrSettings()
{
fFilterOlderPageVersions = true;
fFilterNewerPageVersions = true;
fPassiveKeyRead = false;
fLoadPagesOnInit = true;
fLoggingLevel = 0;
}
public:
enum LogLevels
{
kNoLogging = 0,
kBasicLogging = 1,
kDetailedLogging = 2,
kObjectLogging = 3,
kObjectDetailLogging = 4
};
bool GetFilterOlderPageVersions() const { return fFilterOlderPageVersions; }
void SetFilterOlderPageVersions(bool f) { fFilterOlderPageVersions = f; }
bool GetFilterNewerPageVersions() const { return fFilterNewerPageVersions; }
void SetFilterNewerPageVersions(bool f) { fFilterNewerPageVersions = f; }
UInt8 GetLoggingLevel() const { return fLoggingLevel; }
void SetLoggingLevel(UInt8 level) { fLoggingLevel = level; }
bool GetPassiveKeyRead() const { return fPassiveKeyRead; }
void SetPassiveKeyRead(bool p) { fPassiveKeyRead = p; }
bool GetLoadPagesOnInit() const { return fLoadPagesOnInit; }
void SetLoadPagesOnInit(bool load) { fLoadPagesOnInit = load; }
static plResMgrSettings& Get();
};
#endif // _plResMgrSettings_h

View File

@ -1,91 +1,91 @@
/*==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/>.
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==*/
#include "plVersion.h"
#include "pnFactory/plFactory.h"
#include <vector>
#include "plCreatableIndex.h"
#define ChangedCreatable(ver, creatable) if (minorVersion == ver) creatables.push_back(CLASS_INDEX_SCOPED(creatable));
//
// Every time you bump the minor version number, add entries here for each
// creatable that was changed. Every time the minor version is reset (for a
// major version change), delete all the entries.
//
static void GetChangedCreatables(int minorVersion, std::vector<UInt16>& creatables)
{
ChangedCreatable(1, plLoadAvatarMsg);
ChangedCreatable(1, plArmatureMod);
ChangedCreatable(2, plAvBrainHuman);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
static int CreatableVersions[plCreatableIndex::plNumClassIndices];
static void CalcCreatableVersions()
{
memset(CreatableVersions, 0, sizeof(CreatableVersions));
for (int minorVer = 1; minorVer <= PLASMA2_MINOR_VERSION; minorVer++)
{
std::vector<UInt16> changedTypes;
changedTypes.reserve(10);
GetChangedCreatables(minorVer, changedTypes);
for (int i = 0; i < changedTypes.size(); i++)
{
UInt16 changedType = changedTypes[i];
CreatableVersions[changedType] = minorVer;
// Bump any classes that derive from this one
for (UInt16 toCheck = 0; toCheck < plFactory::GetNumClasses(); toCheck++)
{
if (plFactory::DerivesFrom(changedType, toCheck))
CreatableVersions[toCheck] = minorVer;
}
}
}
}
UInt16 plVersion::GetMajorVersion() { return PLASMA2_MAJOR_VERSION; }
UInt16 plVersion::GetMinorVersion() { return PLASMA2_MINOR_VERSION; }
int plVersion::GetCreatableVersion(UInt16 creatableIndex)
{
static bool calced = false;
if (!calced)
{
calced = true;
CalcCreatableVersions();
}
return CreatableVersions[creatableIndex];
}
/*==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/>.
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==*/
#include "plVersion.h"
#include "pnFactory/plFactory.h"
#include <vector>
#include "plCreatableIndex.h"
#define ChangedCreatable(ver, creatable) if (minorVersion == ver) creatables.push_back(CLASS_INDEX_SCOPED(creatable));
//
// Every time you bump the minor version number, add entries here for each
// creatable that was changed. Every time the minor version is reset (for a
// major version change), delete all the entries.
//
static void GetChangedCreatables(int minorVersion, std::vector<UInt16>& creatables)
{
ChangedCreatable(1, plLoadAvatarMsg);
ChangedCreatable(1, plArmatureMod);
ChangedCreatable(2, plAvBrainHuman);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
static int CreatableVersions[plCreatableIndex::plNumClassIndices];
static void CalcCreatableVersions()
{
memset(CreatableVersions, 0, sizeof(CreatableVersions));
for (int minorVer = 1; minorVer <= PLASMA2_MINOR_VERSION; minorVer++)
{
std::vector<UInt16> changedTypes;
changedTypes.reserve(10);
GetChangedCreatables(minorVer, changedTypes);
for (int i = 0; i < changedTypes.size(); i++)
{
UInt16 changedType = changedTypes[i];
CreatableVersions[changedType] = minorVer;
// Bump any classes that derive from this one
for (UInt16 toCheck = 0; toCheck < plFactory::GetNumClasses(); toCheck++)
{
if (plFactory::DerivesFrom(changedType, toCheck))
CreatableVersions[toCheck] = minorVer;
}
}
}
}
UInt16 plVersion::GetMajorVersion() { return PLASMA2_MAJOR_VERSION; }
UInt16 plVersion::GetMinorVersion() { return PLASMA2_MINOR_VERSION; }
int plVersion::GetCreatableVersion(UInt16 creatableIndex)
{
static bool calced = false;
if (!calced)
{
calced = true;
CalcCreatableVersions();
}
return CreatableVersions[creatableIndex];
}

View File

@ -1,277 +1,277 @@
/*==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/>.
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 plVersion_h_inc
#define plVersion_h_inc
#include "hsTypes.h"
// RULES:
// Log your change
// Set Minor Version to ZERO when you Bump Major Version
// If you change the minor, see GetChangedCreateables in plVersion.cpp
#define PLASMA2_MAJOR_VERSION 70 // Major Version...every file will need to be reexported
#define PLASMA2_MINOR_VERSION 2 // Minor Version...only files with the specified creatables
// will need to be reexported
// Don't modify this, it's automatically updated when branches are made
#define PLASMA2_BRANCH_NAME "Main Branch"
class plVersion
{
public:
static UInt16 GetMajorVersion();
static UInt16 GetMinorVersion();
// Pass in a creatable index to get its current version. Zero means it
// hasn't changed since the last major version change, anything else is the
// last minor version it changed at. This takes into account the version of
// parent classes.
static int GetCreatableVersion(UInt16 creatableIndex);
};
/* Major Log ---Death to those who do not log changes---
# Date Who comment
1 5/8/01 Paulg Added version Number
2 5/11/01 mf Changed sortable mesh format by 2 bytes.
3 5/14/01 Paulg Index files Location is used for ReadConfig at Client Startup, RoomLoc added to Index
4 5/21/01 matt Fixed errant bounding types for physicals (old bad codes will choke)
5 5/24/01 mf Added Occluders to the data format.
6 5/29/01 mf Purvis changed the sound data format and didn't change the version.
7 5/3/01 thamer Cleaned up some object read/write routines
8 6/12/01 mcn Obliterated hsGTexture on down. Now we use plBitmaps and plMipmaps (class IDs changed)
9 6/21/01 mcn Updated drawable disk format. Forgot a field that made particle systems break when it wasn't there
10 6/25/01 mcn Updated plMipmap format. Helps resolve the huge memory issues we were having
11 6/28/01 mf Slight changes to material and geometry formats to support projective texturing.
12 7/02/01 mcn Changed file format to fix disappearing objects in SceneViewer
13 7/09/01 bob Changed file format of plSimpleParticleGenerator to allow mesh generated systems.
14 7/13/01 thamer Changed uoid read/write to include clone number
15 7/20/01 thamer Changed uoid sequence to support up to 4 player rooms
16 7/20/01 mcn Added a second drawable + key to drawInterfaces
17 7/22/01 bob Changed file format to have particle systems support material diffuse/opacity animations
18 7/27/01 mcn Added stuff to drawableSpans for SceneViewer. Are we ever going to have another non-zero minor version? :)
19 7/31/01 mf Did a get and the format had changed but the version hadn't been updated (again). Is this version thing dead?
20 8/13/01 mcn Not that I know of. Change to various object formats to support object instancing.
21 8/20/01 mf Like you'd know. Revised inter-object dependency connections throughout the five scene graphs.
22 8/21/01 mf CoordinateInterfaces keep refs to child SceneObjects instead of child CoordinateInterfaces.
22 8/21/01 mcn You hurt my feelings. I bump major version in retaliation. (Also upped max UV count)
23 8/24/01 mf Made runtime lights respect Max's OTM.
24 8/26/01 mcn Changed plSound format to support stereo (background music) sounds
25 9/05/01 thamer Changed uoid to support 32bit clones
26 9/14/01 mcn Added all 12 parameters to the Audio Region component.
27 9/25/01 mf Added soft volumes to run-time lights. Breaks any scene with RT lights.
28 10/03/01 matt Changed physics format just enough to make everyone reexport everything.
29 10/9/01 ee Changed Uoid member types to a new format that can accomodate strings.
30 10/10/01 mcn Split diffuse layer colors to static and runtime diffuse colors. Breaks the entire universe and parts of New Jersey.
31 10/11/01 ee Activated string usage in uoids -- this version thing is sure not dead now.
32 10/11/01 mf Changed format of plSpan. Only breaks scenes with visible geometry. Should that be Minor Version?
33 10/12/01 cp changed read/write functions in plAnimTimeConvert. Breaks all previously exported animations
34 10/22/01 Colin Changed format of plBitmap
35 10/30/01 mf Change to span format, breaks anything with visible geometry.
36 11/5/01 mcn Changed structure of sound classes to be far more intuitive and bug-free.
37 11/9/01 ee Just for fun.
38 11/13/01 bob Changed file format for plAnimTimeConvert / plAnimCmdMsg / plAGAnim (sense a theme?)
39 11/25/01 mf More sorting info for drawable geometry.
40 11/29/01 mcn Fixed sound fade param read/write. Anything with sounds must be re-exported.
41 12/04/01 bob More animation file format changes.
42 12/05/01 mcn Changes to sound format. Now properties are in a general props field. Also added disable-LOD prop to sounds
43 12/18/01 cjp changes to physics system
44 12/18/01 bob anim file format.
45 12/19/01 Colin anim file format, again.
46 12/28/01 mf DrawInterface format change to purge the last of the Opaque/Blending dualism.
47 1/2/01 mf Decoupled the hardware and software skinning vertex formats.
48 1/6/01 mf Added grey area to Soft Regions (formerly Soft Volumes).
49 1/17/02 cp new camera system checked into client and plugins
50 1/21/02 Colin Physics changes
51 1/24/02 Colin Animation format change
52 2/14/02 bob plAnimTimeConvert format change
53 2/14/02 matt made all brains non-keyed. reordering all over the place
54 3/15/02 cjp new LOS query types, format change to plHKPhysical
55 4/09/02 cjp more new LOS query types, format change to plHKPhysical, camera type changes
56 4/23/02 bob nuked plSimpleModifier from plAGMasterMod. Changes file format for animation.
57 5/17/02 Colin Changed Uoid format for cloning
58 7/02/02 thamer Changed synchedOject R/W format to support more LocalOnly options
59 8/14/02 bob Anim file format
60 2/08/03 mf Changed formats for everything drawable and/or physical. That leaves behaviors, but it's about time for a major version change anyway.
61 2/18/03 mf Between my changes and Bob's, we're just not sure what hasn't changed anymore. At least drawables and avatars.
62 3/30/03 mf Added LoadMask to plUoid
63 5/30/03 thamer optimized Uoid size
64 10/28/05 jeff changed plLocation to handle more pages and plUoid for optimization reasons
65 2/22/06 bob animation key rewrite to save space
66 2/27/06 bob 64-bit quaternion anim keys
67 2/28/06 bob Anims store UInt16 frame numbers, not 32-bit float times.
68 3/03/06 bob constant anim channels (plMatrixConstant, plScalarConstant had no R/W methods)
69 5/08/06 bob changed plVertCoder and hsMatrix44::Read/Write
70 2/12/07 bob Merged in several registry/resMangaer fixes
*/
/* Minor Log ---Death to those who do not log changes---
# Date Who comment
1 5/8/01 Paulg Added version Number
2 5/9/01 mcn Changed color components of drawableSpans
0 5/11/01 mf Dropped back to zero on Major Version change
1 8/06/01 thamer Upped the version for mf's anim callback changes.
2 8/06/01 bob Changes to particle system read/write.
0 8/13/01 mcn Bumped back to 0 due to major version change.
1 8/23/01 bob Added animation controller to particle systems, changing their format.
0 8/24/01 mcn Bumped back to 0 yet again.
1 8/27/01 mcn Changed how emissive flags are handled on materials.
2 8/29/01 bob Changed plAvatarMod file format
0 9/05/01 thamer Bumped back to 0 yet again.
1 9/17/01 matt Avatar only.
2 9/24/01 bob Avatar and sound file formats changed. (For age linking effects)
0 9/25/01 mf Reset to zero for major change.
1 10/7/01 Colin Format of plResponderModifier and plEventCallbackMsg changed.
0 10/9/01 ee Reset to zero for major change.
1 10/11/01 mcn Changed sound format. Anything with sounds (including avatar b/c of linking sounds) breaks. Is this a record for # of version changes in one week?
1 10/15/01 mcn Added soft volumes to sounds. Breaks anything with sounds. Again.
2 10/17/01 Colin Changed format of plAGAnim
0 10/22/01 Colin Reset to zero for major change.
1 11/01/01 bob Changed format for plAGAnim and plAGMasterMod. Will break avatars without re-export.
0 11/02/01 mf Reset to zero for major change.
1 11/28/01 mcn Changed meaning of sound volume property. Will work if not re-exported, but will sound wrong.
0 11/29/01 mcn Reset on major version change.
1 12/10/01 bob Changes to animTimeConvert. Animated materials will need a re-export.
0 12/18/01 bob Reset to zero for major change.
1 1/07/02 bob File format change for particle systems.
0 1/21/02 Colin Reset to zero for major change.
1 1/24/02 Colin File format for responders
2 1/24/02 mcn Changed postEffectMod format. Not many people use it though, so only minor version change.
0 1/24/02 Colin Reset to zero for major change.
1 1/28/02 bob File format change to avatars for clothing customization.
2 1/30/02 Colin File format change to sit component
3 1/31/02 Colin File format change to logic modifier (all detector components)
4 2/13/02 Colin File format change to ladder modifier
0 2/14/02 bob Reset to zero for major change.
1(5) 2/14/02 mcn GUI control format changes to support dynamic text layers (the RIGHT way)
2(6) 2/19/02 mcn Added version field to dialogs, to allow synching with C++ and Python code (just in case)
7 3/01/02 mcn Moved GUI controls to pfGUIColorScheme methods of handling colors/fonts
8 3/01/02 cjp changed format of new camera brains, only affects the few using them right now
10 3/08/02 mcn Changed internal format of sounds to facilitate packing them in files later
11 3/08/02 mcn Added a shadow option to GUI color schemes. Also added mouse-over animations to buttons.
12 3/12/02 bob Change format of clothing
13 3/15/02 matt Changed base class for sit modifier
0 3/15/02 cjp Only chris forgot to log it - mf
1 3/29/02 mf Added light group support for particle systems.
2 4/02/02 Colin Format change for responder modifiers
0 4/15/02 cjp Only chris forgot to log it - mf
1 4/15/02 mf Added a parm to partycle systems just for fun.
2 4/17/02 cjp Added new modifier for interface information, changed plMaxNode.cpp.
0 4/23/02 bob Reset to zero.
1 4/25/02 mcn GUI objects no longer fog. Must reexport GUI components.
2 5/05/02 mf Particle system enhancements
3 5/06/02 matt Changes to one shot modifier and multistage modifier
4 5/06/02 bob Changes to plArmatureMod and Clothing stuff. For swappable meshes and footsteps.
5 5/07/02 bob Changed clothing item file format (again) for text descriptions and thumbnails
6 5/09/02 mcn Added sound event capabilities to GUI controls
7 5/13/02 mcn Added some new options to GUI knobs
8 5/14/02 matt Fix net propagation for animation stages (fading) and generic brains (exit flags)
0 5/17/02 Colin Reset for major version
1 5/21/02 mcn Added a channel select option for plWin32Sounds
2 5/23/02 bob Added multiple texture layers per element in plClothingItem
3 5/23/02 mcn Added some options to plSoundBuffer.
4 6/18/02 mcn Added some more options to plSound, incl. localOnly flags
6 6/21/02 mcn Updated plDynamicTextMap to include an initial image buffer
7 6/26/02 mcn Major revision to sound system to support hardware acceleration
0 7/02/02 thamer Reset for major version
1 7/08/02 matt Format change for animation stages -- added next/prevStage override
2 7/10/02 bob Format changes for avatar footstep sounds
3 7/12/02 mcn Format change to sounds for EAX effects
4 7/23/02 bob Format change to footstep sounds for more surface options
5 7/29/02 mcn More EAX format changes to sounds
6 7/29/02 mcn Added cutoff attenuation to spot/omni lights
7 8/01/02 bob Format change to clothing items
0 8/14/02 bob Reset for major version
1 8/19/02 bob plClothingItem file format
2 9/02/02 bob plArmatureLODMod file format change for bone LOD
3 9/12/02 mf Making ripples and waves play nice with each other.
4 9/18/02 bob plClothingItem file format... again
5 9/19/02 mcn New GUI control proxy stuff
6 9/23/02 mcn Removed dead sound stuff
7 9/24/02 mcn Sound priority stuff
8 9/25/02 mcn Support for new grouped random sound objects
9 10/15/02 mcn Material anim support in GUI controls
10 10/21/02 mcn Variable volume support to group sounds. No format break.
11 10/29/02 cjp proper python notification of avatar page out & last avatar out plus elevator persistance fix - breaks message format for exclude regions
12 10/29/02 mcn Fixing chris's booboo
13 10/29/02 cjp Changed camera component data format slightly.
16 11/18.02 cjp changed camera speed components & objects, don't know where v 14 & 15 went
17 12/04/20 matt New line-of-sight categories; format change for physicals.
18 12/05/02 mf Enhanced linefollowmod to play nice with stereizer, and added field to occluder's cullpoly.
19 12/17/02 matt Bumped armaturemod, based on strong circumstantial evidenced that I missed something.
20 12/31/02 matt New format for animation stages, written by the multistage mod.
21 01/03/03 matt Change to sitmodifier.
22 01/16/03 matt More simplification for animation stages and generic brains.
23 01/20/03 bob Added layer to clothing items for aged skin blending
24 01/21/03 mf plLayers now read and write out their shaders.
25 01/29/03 bob plMorphSequence read/writes the plSharedMeshes it uses
27 02/05/03 mcn Updates to pfGUIButtonMod
0 02/18/03 mf Reset for major version change.
1 02/19/03 bob Added layers to plClothingItem. Took the opp to cleanup the R/W functions
2 02/21/03 mf Added features to dynamic water. No one should notice.
3 02/24/03 cjp changed animated cameras - added new commands for controlling them
4 02/24/03 mcn Updates to GUI stuff to support, er, new GUI stuff.
5 03/11/03 bob Clothing and linkSound format change
0 03/30/03 mf Reset for major version change.
9 04/14/03 Colin Havok change. At 9 since mf forgot to bump the version (and Matt did a bunch of undocumented bumps)
10 04/15/03 bob Added a footstep surface type
11 4/18/03 mcn Added list of the layers grabbed by a GUI DynDisplay
12 4/23/03 bob File format for plMultistageBehMod, needed for a ladder fix
13 05/01/03 Colin Changed how Havok vectors and quats are written
14 03/30/03 mf Particle effect enhancement
0 05/30/03 thamer Reset for major version change.
1 06/01/03 bob Added a flags variable to plSharedMesh
2 06/06/03 markd Added NotifyType for GUIButtons
3 06/07/03 mcn Added sound groups to physicals
4 06/24/03 bob More params for Flocking particles
5 07/05/03 mf Particle and footprints working together
6 07/13/03 bob Avatar file format
7 07/31/03 bob LinkToAgeMsg (which affects responders) and panic link regions
8 08/21/03 Colin Removed some stuff from plSoundBuffer
9 08/22/03 bob Added info to plClothingItem
10 09/16/03 bob Removed stuff in plAnimCmdMsg, which affects responders.
11 09/18/03 mf Changed plLoadMask, of which plWaveSet7 is the biggest user.
12 01/03/04 jeff pfGUIDynDisplayCtrl now stores material as well as layer information
!! 11 02/10/04 mf Dropped back a version, to reduce patch size for Expansion 1.
12 03/12/04 bob New stuff in Swim Regions
0 10/28/05 jeff Reset for major version change
1 11/28/05 jeff GUI text boxes can now pull strings from the localization mgr
2 12/01/05 jeff pfKIMsg can now handle unicode strings
3 02/02/06 adam modified plDynamicEnvMap as a part of back-porting planar reflections from P21
0 02/22/06 bob Reset for major version change
1 04/12/06 Colin Changed physical format
0 05/08/06 bob Reset for major version change
1 05/16/06 markd Changed physics format to include boxes
2 06/26/06 jeff Changed coop brain format so book sharing works again
3 12/05/06 bob Avatar uses a render target instead of a plMipmap.
4 01/16/07 bob Still does, it's just not created at export.
5 01/24/07 adam Changed plAGMasterMod so one can be set as a group master in grouped anims
0 02/12/07 bob Reset for major version change
1 03/29/07 jeff Changed plLoadAvatarMsg and plArmatureMod to be more flexible
2 06/28/07 jeff Changed plAvBrainHuman format to store whether it's an actor or not
*/
#endif // plVersion_h_inc
/*==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/>.
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 plVersion_h_inc
#define plVersion_h_inc
#include "hsTypes.h"
// RULES:
// Log your change
// Set Minor Version to ZERO when you Bump Major Version
// If you change the minor, see GetChangedCreateables in plVersion.cpp
#define PLASMA2_MAJOR_VERSION 70 // Major Version...every file will need to be reexported
#define PLASMA2_MINOR_VERSION 2 // Minor Version...only files with the specified creatables
// will need to be reexported
// Don't modify this, it's automatically updated when branches are made
#define PLASMA2_BRANCH_NAME "Main Branch"
class plVersion
{
public:
static UInt16 GetMajorVersion();
static UInt16 GetMinorVersion();
// Pass in a creatable index to get its current version. Zero means it
// hasn't changed since the last major version change, anything else is the
// last minor version it changed at. This takes into account the version of
// parent classes.
static int GetCreatableVersion(UInt16 creatableIndex);
};
/* Major Log ---Death to those who do not log changes---
# Date Who comment
1 5/8/01 Paulg Added version Number
2 5/11/01 mf Changed sortable mesh format by 2 bytes.
3 5/14/01 Paulg Index files Location is used for ReadConfig at Client Startup, RoomLoc added to Index
4 5/21/01 matt Fixed errant bounding types for physicals (old bad codes will choke)
5 5/24/01 mf Added Occluders to the data format.
6 5/29/01 mf Purvis changed the sound data format and didn't change the version.
7 5/3/01 thamer Cleaned up some object read/write routines
8 6/12/01 mcn Obliterated hsGTexture on down. Now we use plBitmaps and plMipmaps (class IDs changed)
9 6/21/01 mcn Updated drawable disk format. Forgot a field that made particle systems break when it wasn't there
10 6/25/01 mcn Updated plMipmap format. Helps resolve the huge memory issues we were having
11 6/28/01 mf Slight changes to material and geometry formats to support projective texturing.
12 7/02/01 mcn Changed file format to fix disappearing objects in SceneViewer
13 7/09/01 bob Changed file format of plSimpleParticleGenerator to allow mesh generated systems.
14 7/13/01 thamer Changed uoid read/write to include clone number
15 7/20/01 thamer Changed uoid sequence to support up to 4 player rooms
16 7/20/01 mcn Added a second drawable + key to drawInterfaces
17 7/22/01 bob Changed file format to have particle systems support material diffuse/opacity animations
18 7/27/01 mcn Added stuff to drawableSpans for SceneViewer. Are we ever going to have another non-zero minor version? :)
19 7/31/01 mf Did a get and the format had changed but the version hadn't been updated (again). Is this version thing dead?
20 8/13/01 mcn Not that I know of. Change to various object formats to support object instancing.
21 8/20/01 mf Like you'd know. Revised inter-object dependency connections throughout the five scene graphs.
22 8/21/01 mf CoordinateInterfaces keep refs to child SceneObjects instead of child CoordinateInterfaces.
22 8/21/01 mcn You hurt my feelings. I bump major version in retaliation. (Also upped max UV count)
23 8/24/01 mf Made runtime lights respect Max's OTM.
24 8/26/01 mcn Changed plSound format to support stereo (background music) sounds
25 9/05/01 thamer Changed uoid to support 32bit clones
26 9/14/01 mcn Added all 12 parameters to the Audio Region component.
27 9/25/01 mf Added soft volumes to run-time lights. Breaks any scene with RT lights.
28 10/03/01 matt Changed physics format just enough to make everyone reexport everything.
29 10/9/01 ee Changed Uoid member types to a new format that can accomodate strings.
30 10/10/01 mcn Split diffuse layer colors to static and runtime diffuse colors. Breaks the entire universe and parts of New Jersey.
31 10/11/01 ee Activated string usage in uoids -- this version thing is sure not dead now.
32 10/11/01 mf Changed format of plSpan. Only breaks scenes with visible geometry. Should that be Minor Version?
33 10/12/01 cp changed read/write functions in plAnimTimeConvert. Breaks all previously exported animations
34 10/22/01 Colin Changed format of plBitmap
35 10/30/01 mf Change to span format, breaks anything with visible geometry.
36 11/5/01 mcn Changed structure of sound classes to be far more intuitive and bug-free.
37 11/9/01 ee Just for fun.
38 11/13/01 bob Changed file format for plAnimTimeConvert / plAnimCmdMsg / plAGAnim (sense a theme?)
39 11/25/01 mf More sorting info for drawable geometry.
40 11/29/01 mcn Fixed sound fade param read/write. Anything with sounds must be re-exported.
41 12/04/01 bob More animation file format changes.
42 12/05/01 mcn Changes to sound format. Now properties are in a general props field. Also added disable-LOD prop to sounds
43 12/18/01 cjp changes to physics system
44 12/18/01 bob anim file format.
45 12/19/01 Colin anim file format, again.
46 12/28/01 mf DrawInterface format change to purge the last of the Opaque/Blending dualism.
47 1/2/01 mf Decoupled the hardware and software skinning vertex formats.
48 1/6/01 mf Added grey area to Soft Regions (formerly Soft Volumes).
49 1/17/02 cp new camera system checked into client and plugins
50 1/21/02 Colin Physics changes
51 1/24/02 Colin Animation format change
52 2/14/02 bob plAnimTimeConvert format change
53 2/14/02 matt made all brains non-keyed. reordering all over the place
54 3/15/02 cjp new LOS query types, format change to plHKPhysical
55 4/09/02 cjp more new LOS query types, format change to plHKPhysical, camera type changes
56 4/23/02 bob nuked plSimpleModifier from plAGMasterMod. Changes file format for animation.
57 5/17/02 Colin Changed Uoid format for cloning
58 7/02/02 thamer Changed synchedOject R/W format to support more LocalOnly options
59 8/14/02 bob Anim file format
60 2/08/03 mf Changed formats for everything drawable and/or physical. That leaves behaviors, but it's about time for a major version change anyway.
61 2/18/03 mf Between my changes and Bob's, we're just not sure what hasn't changed anymore. At least drawables and avatars.
62 3/30/03 mf Added LoadMask to plUoid
63 5/30/03 thamer optimized Uoid size
64 10/28/05 jeff changed plLocation to handle more pages and plUoid for optimization reasons
65 2/22/06 bob animation key rewrite to save space
66 2/27/06 bob 64-bit quaternion anim keys
67 2/28/06 bob Anims store UInt16 frame numbers, not 32-bit float times.
68 3/03/06 bob constant anim channels (plMatrixConstant, plScalarConstant had no R/W methods)
69 5/08/06 bob changed plVertCoder and hsMatrix44::Read/Write
70 2/12/07 bob Merged in several registry/resMangaer fixes
*/
/* Minor Log ---Death to those who do not log changes---
# Date Who comment
1 5/8/01 Paulg Added version Number
2 5/9/01 mcn Changed color components of drawableSpans
0 5/11/01 mf Dropped back to zero on Major Version change
1 8/06/01 thamer Upped the version for mf's anim callback changes.
2 8/06/01 bob Changes to particle system read/write.
0 8/13/01 mcn Bumped back to 0 due to major version change.
1 8/23/01 bob Added animation controller to particle systems, changing their format.
0 8/24/01 mcn Bumped back to 0 yet again.
1 8/27/01 mcn Changed how emissive flags are handled on materials.
2 8/29/01 bob Changed plAvatarMod file format
0 9/05/01 thamer Bumped back to 0 yet again.
1 9/17/01 matt Avatar only.
2 9/24/01 bob Avatar and sound file formats changed. (For age linking effects)
0 9/25/01 mf Reset to zero for major change.
1 10/7/01 Colin Format of plResponderModifier and plEventCallbackMsg changed.
0 10/9/01 ee Reset to zero for major change.
1 10/11/01 mcn Changed sound format. Anything with sounds (including avatar b/c of linking sounds) breaks. Is this a record for # of version changes in one week?
1 10/15/01 mcn Added soft volumes to sounds. Breaks anything with sounds. Again.
2 10/17/01 Colin Changed format of plAGAnim
0 10/22/01 Colin Reset to zero for major change.
1 11/01/01 bob Changed format for plAGAnim and plAGMasterMod. Will break avatars without re-export.
0 11/02/01 mf Reset to zero for major change.
1 11/28/01 mcn Changed meaning of sound volume property. Will work if not re-exported, but will sound wrong.
0 11/29/01 mcn Reset on major version change.
1 12/10/01 bob Changes to animTimeConvert. Animated materials will need a re-export.
0 12/18/01 bob Reset to zero for major change.
1 1/07/02 bob File format change for particle systems.
0 1/21/02 Colin Reset to zero for major change.
1 1/24/02 Colin File format for responders
2 1/24/02 mcn Changed postEffectMod format. Not many people use it though, so only minor version change.
0 1/24/02 Colin Reset to zero for major change.
1 1/28/02 bob File format change to avatars for clothing customization.
2 1/30/02 Colin File format change to sit component
3 1/31/02 Colin File format change to logic modifier (all detector components)
4 2/13/02 Colin File format change to ladder modifier
0 2/14/02 bob Reset to zero for major change.
1(5) 2/14/02 mcn GUI control format changes to support dynamic text layers (the RIGHT way)
2(6) 2/19/02 mcn Added version field to dialogs, to allow synching with C++ and Python code (just in case)
7 3/01/02 mcn Moved GUI controls to pfGUIColorScheme methods of handling colors/fonts
8 3/01/02 cjp changed format of new camera brains, only affects the few using them right now
10 3/08/02 mcn Changed internal format of sounds to facilitate packing them in files later
11 3/08/02 mcn Added a shadow option to GUI color schemes. Also added mouse-over animations to buttons.
12 3/12/02 bob Change format of clothing
13 3/15/02 matt Changed base class for sit modifier
0 3/15/02 cjp Only chris forgot to log it - mf
1 3/29/02 mf Added light group support for particle systems.
2 4/02/02 Colin Format change for responder modifiers
0 4/15/02 cjp Only chris forgot to log it - mf
1 4/15/02 mf Added a parm to partycle systems just for fun.
2 4/17/02 cjp Added new modifier for interface information, changed plMaxNode.cpp.
0 4/23/02 bob Reset to zero.
1 4/25/02 mcn GUI objects no longer fog. Must reexport GUI components.
2 5/05/02 mf Particle system enhancements
3 5/06/02 matt Changes to one shot modifier and multistage modifier
4 5/06/02 bob Changes to plArmatureMod and Clothing stuff. For swappable meshes and footsteps.
5 5/07/02 bob Changed clothing item file format (again) for text descriptions and thumbnails
6 5/09/02 mcn Added sound event capabilities to GUI controls
7 5/13/02 mcn Added some new options to GUI knobs
8 5/14/02 matt Fix net propagation for animation stages (fading) and generic brains (exit flags)
0 5/17/02 Colin Reset for major version
1 5/21/02 mcn Added a channel select option for plWin32Sounds
2 5/23/02 bob Added multiple texture layers per element in plClothingItem
3 5/23/02 mcn Added some options to plSoundBuffer.
4 6/18/02 mcn Added some more options to plSound, incl. localOnly flags
6 6/21/02 mcn Updated plDynamicTextMap to include an initial image buffer
7 6/26/02 mcn Major revision to sound system to support hardware acceleration
0 7/02/02 thamer Reset for major version
1 7/08/02 matt Format change for animation stages -- added next/prevStage override
2 7/10/02 bob Format changes for avatar footstep sounds
3 7/12/02 mcn Format change to sounds for EAX effects
4 7/23/02 bob Format change to footstep sounds for more surface options
5 7/29/02 mcn More EAX format changes to sounds
6 7/29/02 mcn Added cutoff attenuation to spot/omni lights
7 8/01/02 bob Format change to clothing items
0 8/14/02 bob Reset for major version
1 8/19/02 bob plClothingItem file format
2 9/02/02 bob plArmatureLODMod file format change for bone LOD
3 9/12/02 mf Making ripples and waves play nice with each other.
4 9/18/02 bob plClothingItem file format... again
5 9/19/02 mcn New GUI control proxy stuff
6 9/23/02 mcn Removed dead sound stuff
7 9/24/02 mcn Sound priority stuff
8 9/25/02 mcn Support for new grouped random sound objects
9 10/15/02 mcn Material anim support in GUI controls
10 10/21/02 mcn Variable volume support to group sounds. No format break.
11 10/29/02 cjp proper python notification of avatar page out & last avatar out plus elevator persistance fix - breaks message format for exclude regions
12 10/29/02 mcn Fixing chris's booboo
13 10/29/02 cjp Changed camera component data format slightly.
16 11/18.02 cjp changed camera speed components & objects, don't know where v 14 & 15 went
17 12/04/20 matt New line-of-sight categories; format change for physicals.
18 12/05/02 mf Enhanced linefollowmod to play nice with stereizer, and added field to occluder's cullpoly.
19 12/17/02 matt Bumped armaturemod, based on strong circumstantial evidenced that I missed something.
20 12/31/02 matt New format for animation stages, written by the multistage mod.
21 01/03/03 matt Change to sitmodifier.
22 01/16/03 matt More simplification for animation stages and generic brains.
23 01/20/03 bob Added layer to clothing items for aged skin blending
24 01/21/03 mf plLayers now read and write out their shaders.
25 01/29/03 bob plMorphSequence read/writes the plSharedMeshes it uses
27 02/05/03 mcn Updates to pfGUIButtonMod
0 02/18/03 mf Reset for major version change.
1 02/19/03 bob Added layers to plClothingItem. Took the opp to cleanup the R/W functions
2 02/21/03 mf Added features to dynamic water. No one should notice.
3 02/24/03 cjp changed animated cameras - added new commands for controlling them
4 02/24/03 mcn Updates to GUI stuff to support, er, new GUI stuff.
5 03/11/03 bob Clothing and linkSound format change
0 03/30/03 mf Reset for major version change.
9 04/14/03 Colin Havok change. At 9 since mf forgot to bump the version (and Matt did a bunch of undocumented bumps)
10 04/15/03 bob Added a footstep surface type
11 4/18/03 mcn Added list of the layers grabbed by a GUI DynDisplay
12 4/23/03 bob File format for plMultistageBehMod, needed for a ladder fix
13 05/01/03 Colin Changed how Havok vectors and quats are written
14 03/30/03 mf Particle effect enhancement
0 05/30/03 thamer Reset for major version change.
1 06/01/03 bob Added a flags variable to plSharedMesh
2 06/06/03 markd Added NotifyType for GUIButtons
3 06/07/03 mcn Added sound groups to physicals
4 06/24/03 bob More params for Flocking particles
5 07/05/03 mf Particle and footprints working together
6 07/13/03 bob Avatar file format
7 07/31/03 bob LinkToAgeMsg (which affects responders) and panic link regions
8 08/21/03 Colin Removed some stuff from plSoundBuffer
9 08/22/03 bob Added info to plClothingItem
10 09/16/03 bob Removed stuff in plAnimCmdMsg, which affects responders.
11 09/18/03 mf Changed plLoadMask, of which plWaveSet7 is the biggest user.
12 01/03/04 jeff pfGUIDynDisplayCtrl now stores material as well as layer information
!! 11 02/10/04 mf Dropped back a version, to reduce patch size for Expansion 1.
12 03/12/04 bob New stuff in Swim Regions
0 10/28/05 jeff Reset for major version change
1 11/28/05 jeff GUI text boxes can now pull strings from the localization mgr
2 12/01/05 jeff pfKIMsg can now handle unicode strings
3 02/02/06 adam modified plDynamicEnvMap as a part of back-porting planar reflections from P21
0 02/22/06 bob Reset for major version change
1 04/12/06 Colin Changed physical format
0 05/08/06 bob Reset for major version change
1 05/16/06 markd Changed physics format to include boxes
2 06/26/06 jeff Changed coop brain format so book sharing works again
3 12/05/06 bob Avatar uses a render target instead of a plMipmap.
4 01/16/07 bob Still does, it's just not created at export.
5 01/24/07 adam Changed plAGMasterMod so one can be set as a group master in grouped anims
0 02/12/07 bob Reset for major version change
1 03/29/07 jeff Changed plLoadAvatarMsg and plArmatureMod to be more flexible
2 06/28/07 jeff Changed plAvBrainHuman format to store whether it's an actor or not
*/
#endif // plVersion_h_inc