/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts 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 .
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando / G *
* *
* $Archive:: /Commando/Code/Combat/reflist.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 2/06/01 2:33p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef REFLIST_H
#define REFLIST_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef WWDEBUG_H
#include "wwdebug.h"
#endif
#ifndef CHUNKIO_H
#include "chunkio.h"
#endif
#ifndef SAVELOAD_H
#include "saveload.h"
#endif
#ifndef PERSIST_H
#include "persist.h"
#endif
/*
** Forward declarations
*/
class ScriptableGameObj;
class ReferencerClass;
/*
** Advance notice of referencer
*/
//template class ReferencerClass;
/*
** A object class that can be referenced
*/
template
class ReferenceableClass {
public:
friend class ReferencerClass;
ReferenceableClass( T *reference_data ) : ReferenceData( reference_data ), ReferencerListHead( NULL ) {}
~ReferenceableClass( void );
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
protected:
ReferencerClass *ReferencerListHead;
T * Get_Data( void ) const { return ReferenceData; }
private:
T *ReferenceData;
};
/*
** An object class that can reference an ReferencableClass
*/
class ReferencerClass : public PostLoadableClass {
public:
friend class ReferenceableClass;
ReferencerClass( void ) : ReferenceTarget( NULL ), TargetReferencerListNext( NULL ) {}
ReferencerClass( const ScriptableGameObj * target ) : ReferenceTarget( NULL ), TargetReferencerListNext( NULL ) { *this = target; }
virtual ~ReferencerClass( void ) { operator = ((const ScriptableGameObj*)NULL); }
virtual void On_Post_Load(void);
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
const ReferencerClass & operator = ( const ReferencerClass & src ) { operator = (src.Get_Ptr()); return *this; }
const ReferencerClass & operator = ( const ScriptableGameObj * reference_target );
void Set_Ptr (const ScriptableGameObj * reference_target) { *this = reference_target; }
ScriptableGameObj * Get_Ptr (void) const { return ReferenceTarget ? ReferenceTarget->Get_Data() : NULL; }
operator ScriptableGameObj * (void) const { return Get_Ptr(); }
protected:
ReferenceableClass *ReferenceTarget;
ReferencerClass *TargetReferencerListNext;
};
/*
** Clears all references in objects referencing me
*/
template
ReferenceableClass::~ReferenceableClass( void )
{
while ( ReferencerListHead != NULL ) { // clear each reference to me
ReferencerClass *referencer = ReferencerListHead;
WWASSERT( referencer->ReferenceTarget == this );
ReferencerListHead = referencer->TargetReferencerListNext;
referencer->ReferenceTarget = NULL;
referencer->TargetReferencerListNext = NULL;
}
}
/*
** Save & Load
*/
enum {
CHUNKID_REF_VARIABLES = 913991844,
XXXX_MICROCHUNKID_LIST_HEAD = 1,
MICROCHUNKID_XXXXXXXXX,
MICROCHUNKID_PTR,
MICROCHUNKID_TARGET,
XXXX_MICROCHUNKID_NEXT,
};
template
bool ReferenceableClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_REF_VARIABLES );
void * ptr = this;
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PTR, ptr );
csave.End_Chunk();
return true;
}
template
bool ReferenceableClass::Load( ChunkLoadClass & cload )
{
void * old_ptr;
cload.Open_Chunk();
WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_REF_VARIABLES );
WWASSERT( ReferencerListHead == NULL );
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
case MICROCHUNKID_PTR:
cload.Read(&old_ptr,sizeof(void*));
SaveLoadSystemClass::Register_Pointer(old_ptr, this);
break;
default:
// Debug_Say(( "Unrecognized REFLIST Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
cload.Close_Chunk();
return true;
}
/*
** A refcounted version of the ReferencerClass
*/
class RefCountedReferencerClass : public ReferencerClass, public RefCountClass {
public:
friend class ReferenceableClass;
RefCountedReferencerClass( void ) :
ReferencerClass ()
{
}
RefCountedReferencerClass( const ReferencerClass &src ) :
ReferencerClass ()
{
ReferencerClass::operator=( src );
}
};
#endif