mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-13 07:57:51 +00:00
- Standardized use of PClassActor::AllActorClasses for iterating over all classes of actors
instead of PClass::m_Types (now PClass::AllClasses). - Removed ClassIndex from PClass. It was only needed by FArchive, and maps take care of the problem just as well. - Moved PClass into a larger type system (which is likely to change some/lots once I try and actually use it and have a better feel for what I need from it). SVN r2281 (scripting)
This commit is contained in:
parent
900324c205
commit
ee55e0319f
24 changed files with 1204 additions and 350 deletions
|
@ -1453,9 +1453,9 @@ static int PatchAmmo (int ammoNum)
|
|||
// Fix per-ammo/max-ammo amounts for descendants of the base ammo class
|
||||
if (oldclip != *per)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClassActor *type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type == ammoType)
|
||||
continue;
|
||||
|
|
|
@ -1754,14 +1754,16 @@ void D_DoomMain (void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
PClass::StaticInit();
|
||||
PType::StaticInit();
|
||||
|
||||
// Combine different file parameters with their pre-switch bits.
|
||||
Args->CollectFiles("-deh", ".deh");
|
||||
Args->CollectFiles("-bex", ".bex");
|
||||
Args->CollectFiles("-exec", ".cfg");
|
||||
Args->CollectFiles("-playdemo", ".lmp");
|
||||
Args->CollectFiles("-file", NULL); // anythnig left goes after -file
|
||||
Args->CollectFiles("-file", NULL); // anything left goes after -file
|
||||
|
||||
PClass::StaticInit ();
|
||||
atterm (C_DeinitConsole);
|
||||
|
||||
gamestate = GS_STARTUP;
|
||||
|
|
|
@ -353,9 +353,9 @@ void FDecalLib::ReadAllDecals ()
|
|||
ReadDecals (sc);
|
||||
}
|
||||
// Supporting code to allow specifying decals directly in the DECORATE lump
|
||||
for (i = 0; i < PClass::m_RuntimeActors.Size(); i++)
|
||||
for (i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||
{
|
||||
AActor *def = (AActor*)GetDefaultByType (PClass::m_RuntimeActors[i]);
|
||||
AActor *def = (AActor*)GetDefaultByType (PClassActor::AllActorClasses[i]);
|
||||
|
||||
FName v = ENamedName(intptr_t(def->DecalGenerator));
|
||||
if (v.IsValidName())
|
||||
|
|
|
@ -180,9 +180,9 @@ CCMD (dumpclasses)
|
|||
|
||||
shown = omitted = 0;
|
||||
DumpInfo::AddType (&tree, root != NULL ? root : RUNTIME_CLASS(DObject));
|
||||
for (i = 0; i < PClass::m_Types.Size(); i++)
|
||||
for (i = 0; i < PClass::AllClasses.Size(); i++)
|
||||
{
|
||||
PClass *cls = PClass::m_Types[i];
|
||||
PClass *cls = PClass::AllClasses[i];
|
||||
if (root == NULL || cls == root || cls->IsDescendantOf(root))
|
||||
{
|
||||
DumpInfo::AddType (&tree, cls);
|
||||
|
|
|
@ -94,7 +94,9 @@ enum
|
|||
CLASSREG_PClassHealth,
|
||||
CLASSREG_PClassPuzzleItem,
|
||||
CLASSREG_PClassWeapon,
|
||||
CLASSREG_PClassPlayerPawn
|
||||
CLASSREG_PClassPlayerPawn,
|
||||
CLASSREG_PClassType,
|
||||
CLASSREG_PClassClass,
|
||||
};
|
||||
|
||||
struct ClassReg
|
||||
|
@ -104,10 +106,11 @@ struct ClassReg
|
|||
ClassReg *ParentType;
|
||||
const size_t *Pointers;
|
||||
void (*ConstructNative)(void *);
|
||||
unsigned int SizeOf:29;
|
||||
unsigned int MetaClassNum:3;
|
||||
unsigned int SizeOf:28;
|
||||
unsigned int MetaClassNum:4;
|
||||
|
||||
PClass *RegisterClass();
|
||||
void SetupClass(PClass *cls);
|
||||
};
|
||||
|
||||
enum EInPlace { EC_InPlace };
|
||||
|
@ -178,6 +181,10 @@ protected: \
|
|||
#define IMPLEMENT_ABSTRACT_CLASS(cls) \
|
||||
_IMP_PCLASS(cls,NULL,NULL)
|
||||
|
||||
#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \
|
||||
_IMP_PCLASS(cls,cls::PointerOffsets,NULL) \
|
||||
const size_t cls::PointerOffsets[] = {
|
||||
|
||||
enum EObjectFlags
|
||||
{
|
||||
// GC flags
|
||||
|
@ -292,6 +299,9 @@ namespace GC
|
|||
// is NULLed instead.
|
||||
void Mark(DObject **obj);
|
||||
|
||||
// Marks an array of objects.
|
||||
void MarkArray(DObject **objs, size_t count);
|
||||
|
||||
// Soft-roots an object.
|
||||
void AddSoftRoot(DObject *obj);
|
||||
|
||||
|
@ -310,6 +320,15 @@ namespace GC
|
|||
obj = t;
|
||||
}
|
||||
template<class T> void Mark(TObjPtr<T> &obj);
|
||||
|
||||
template<class T> void MarkArray(T **obj, size_t count)
|
||||
{
|
||||
MarkArray((DObject **)(obj), count);
|
||||
}
|
||||
template<class T> void MarkArray(TArray<T> &arr)
|
||||
{
|
||||
MarkArray(&arr[0], arr.Size());
|
||||
}
|
||||
}
|
||||
|
||||
// A template class to help with handling read barriers. It does not
|
||||
|
|
|
@ -283,6 +283,22 @@ void Mark(DObject **obj)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MarkArray
|
||||
//
|
||||
// Mark an array of objects gray.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void MarkArray(DObject **obj, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
Mark(obj[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MarkRoot
|
||||
|
@ -341,9 +357,9 @@ static void MarkRoot()
|
|||
}
|
||||
}
|
||||
// Mark classes
|
||||
for (unsigned j = 0; j < PClass::m_Types.Size(); ++j)
|
||||
for (unsigned j = 0; j < PClass::AllClasses.Size(); ++j)
|
||||
{
|
||||
Mark(PClass::m_Types[j]);
|
||||
Mark(PClass::AllClasses[j]);
|
||||
}
|
||||
// Mark bot stuff.
|
||||
Mark(bglobal.firstthing);
|
||||
|
|
799
src/dobjtype.cpp
799
src/dobjtype.cpp
|
@ -3,7 +3,7 @@
|
|||
** Implements the type information class
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2008 Randy Heit
|
||||
** Copyright 1998-2010 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -32,6 +32,8 @@
|
|||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "dobject.h"
|
||||
#include "i_system.h"
|
||||
#include "actor.h"
|
||||
|
@ -41,17 +43,425 @@
|
|||
#include "a_pickups.h"
|
||||
#include "d_player.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
FTypeTable TypeTable;
|
||||
TArray<PClass *> PClass::AllClasses;
|
||||
bool PClass::bShutdown;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
// A harmless non-NULL FlatPointer for classes without pointers.
|
||||
static const size_t TheEnd = ~(size_t)0;
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
void DumpTypeTable()
|
||||
{
|
||||
int used = 0;
|
||||
int min = INT_MAX;
|
||||
int max = 0;
|
||||
int all = 0;
|
||||
int lens[10] = {0};
|
||||
for (size_t i = 0; i < countof(TypeTable.TypeHash); ++i)
|
||||
{
|
||||
int len = 0;
|
||||
Printf("%4d:", i);
|
||||
for (PType *ty = TypeTable.TypeHash[i]; ty != NULL; ty = ty->HashNext)
|
||||
{
|
||||
Printf(" -> %s", ty->IsKindOf(RUNTIME_CLASS(PNamedType)) ? static_cast<PNamedType*>(ty)->TypeName.GetChars(): ty->GetClass()->TypeName.GetChars());
|
||||
len++;
|
||||
all++;
|
||||
}
|
||||
if (len != 0)
|
||||
{
|
||||
used++;
|
||||
if (len < min)
|
||||
min = len;
|
||||
if (len > max)
|
||||
max = len;
|
||||
}
|
||||
if (len < countof(lens))
|
||||
{
|
||||
lens[len]++;
|
||||
}
|
||||
Printf("\n");
|
||||
}
|
||||
Printf("Used buckets: %d/%u (%.2f%%) for %d entries\n", used, countof(TypeTable.TypeHash), double(used)/countof(TypeTable.TypeHash)*100, all);
|
||||
Printf("Min bucket size: %d\n", min);
|
||||
Printf("Max bucket size: %d\n", max);
|
||||
Printf("Avg bucket size: %.2f\n", double(all) / used);
|
||||
int j,k;
|
||||
for (k = k = countof(lens)-1; k > 0; --k)
|
||||
if (lens[k])
|
||||
break;
|
||||
for (j = 0; j <= k; ++j)
|
||||
Printf("Buckets of len %d: %d (%.2f%%)\n", j, lens[j], j!=0?double(lens[j])/used*100:-1.0);
|
||||
}
|
||||
|
||||
/* PClassType *************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PClassType)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassType Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClassType::PClassType()
|
||||
: TypeTableType(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassType :: Derive
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClassType::Derive(PClass *newclass)
|
||||
{
|
||||
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassType)));
|
||||
Super::Derive(newclass);
|
||||
static_cast<PClassType *>(newclass)->TypeTableType = TypeTableType;
|
||||
}
|
||||
|
||||
/* PClassClass ************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PClassClass)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassClass Constructor
|
||||
//
|
||||
// The only thing we want to do here is automatically set TypeTableType
|
||||
// to PClass.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClassClass::PClassClass()
|
||||
{
|
||||
TypeTableType = RUNTIME_CLASS(PClass);
|
||||
}
|
||||
|
||||
/* PType ******************************************************************/
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(PType)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PType::PType()
|
||||
: Size(0), Align(1), HashNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PType::~PType()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PType::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PType :: StaticInit STATIC
|
||||
//
|
||||
// Set up TypeTableType values for every PType child.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PType::StaticInit()
|
||||
{
|
||||
RUNTIME_CLASS(PInt)->TypeTableType = RUNTIME_CLASS(PInt);
|
||||
RUNTIME_CLASS(PFloat)->TypeTableType = RUNTIME_CLASS(PFloat);
|
||||
RUNTIME_CLASS(PString)->TypeTableType = RUNTIME_CLASS(PString);
|
||||
RUNTIME_CLASS(PName)->TypeTableType = RUNTIME_CLASS(PName);
|
||||
RUNTIME_CLASS(PSound)->TypeTableType = RUNTIME_CLASS(PSound);
|
||||
RUNTIME_CLASS(PColor)->TypeTableType = RUNTIME_CLASS(PColor);
|
||||
RUNTIME_CLASS(PPointer)->TypeTableType = RUNTIME_CLASS(PPointer);
|
||||
RUNTIME_CLASS(PClassPointer)->TypeTableType = RUNTIME_CLASS(PPointer); // not sure about this yet
|
||||
RUNTIME_CLASS(PEnum)->TypeTableType = RUNTIME_CLASS(PEnum);
|
||||
RUNTIME_CLASS(PArray)->TypeTableType = RUNTIME_CLASS(PArray);
|
||||
RUNTIME_CLASS(PDynArray)->TypeTableType = RUNTIME_CLASS(PDynArray);
|
||||
RUNTIME_CLASS(PVector)->TypeTableType = RUNTIME_CLASS(PVector);
|
||||
RUNTIME_CLASS(PMap)->TypeTableType = RUNTIME_CLASS(PMap);
|
||||
RUNTIME_CLASS(PStruct)->TypeTableType = RUNTIME_CLASS(PStruct);
|
||||
RUNTIME_CLASS(PPrototype)->TypeTableType = RUNTIME_CLASS(PPrototype);
|
||||
RUNTIME_CLASS(PFunction)->TypeTableType = RUNTIME_CLASS(PFunction);
|
||||
RUNTIME_CLASS(PClass)->TypeTableType = RUNTIME_CLASS(PClass);
|
||||
}
|
||||
|
||||
|
||||
/* PBasicType *************************************************************/
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(PBasicType)
|
||||
|
||||
/* PCompoundType **********************************************************/
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(PCompoundType)
|
||||
|
||||
/* PNamedType *************************************************************/
|
||||
|
||||
IMPLEMENT_ABSTRACT_POINTY_CLASS(PNamedType)
|
||||
DECLARE_POINTER(Outer)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PNamedType :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PNamedType::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
const DObject *outer = (const DObject *)id1;
|
||||
FName name = (ENamedName)(intptr_t)id2;
|
||||
|
||||
return Outer == outer && TypeName == name;
|
||||
}
|
||||
|
||||
/* PInt *******************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PInt)
|
||||
|
||||
/* PFloat *****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PFloat)
|
||||
|
||||
/* PString ****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PString)
|
||||
|
||||
/* PName ******************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PName)
|
||||
|
||||
/* PSound *****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PSound)
|
||||
|
||||
/* PColor *****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PColor)
|
||||
|
||||
/* PPointer ***************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PPointer)
|
||||
DECLARE_POINTER(PointedType)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PPointer :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PPointer::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
assert(id2 == NULL);
|
||||
PType *pointat = (PType *)id1;
|
||||
|
||||
return pointat == PointedType;
|
||||
}
|
||||
|
||||
/* PClassPointer **********************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PClassPointer)
|
||||
DECLARE_POINTER(ClassRestriction)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassPointer :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PClassPointer::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
const PType *pointat = (const PType *)id1;
|
||||
const PClass *classat = (const PClass *)id2;
|
||||
|
||||
assert(pointat->IsKindOf(RUNTIME_CLASS(PClass)));
|
||||
return classat == ClassRestriction;
|
||||
}
|
||||
|
||||
/* PEnum ******************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PEnum)
|
||||
DECLARE_POINTER(ValueType)
|
||||
END_POINTERS
|
||||
|
||||
/* PArray *****************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PArray)
|
||||
DECLARE_POINTER(ElementType)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PArray :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PArray::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
const PType *elemtype = (const PType *)id1;
|
||||
unsigned int count = (unsigned int)(intptr_t)id2;
|
||||
|
||||
return elemtype == ElementType && count == ElementCount;
|
||||
}
|
||||
|
||||
/* PVector ****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PVector)
|
||||
|
||||
/* PDynArray **************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PDynArray)
|
||||
DECLARE_POINTER(ElementType)
|
||||
END_POINTERS
|
||||
|
||||
bool PDynArray::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
assert(id2 == NULL);
|
||||
const PType *elemtype = (const PType *)id1;
|
||||
|
||||
return elemtype == ElementType;
|
||||
}
|
||||
|
||||
/* PMap *******************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PMap)
|
||||
DECLARE_POINTER(KeyType)
|
||||
DECLARE_POINTER(ValueType)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PMap :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PMap::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
const PType *keyty = (const PType *)id1;
|
||||
const PType *valty = (const PType *)id2;
|
||||
|
||||
return keyty == KeyType && valty == ValueType;
|
||||
}
|
||||
|
||||
/* PStruct ****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PStruct)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PStruct :: PropagateMark
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t PStruct::PropagateMark()
|
||||
{
|
||||
GC::MarkArray(Fields);
|
||||
return Fields.Size() * sizeof(void*) + Super::PropagateMark();
|
||||
}
|
||||
|
||||
/* PPrototype *************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PPrototype)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PPrototype :: IsMatch
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool PPrototype::IsMatch(const void *id1, const void *id2) const
|
||||
{
|
||||
const TArray<PType *> *args = (const TArray<PType *> *)id1;
|
||||
const TArray<PType *> *rets = (const TArray<PType *> *)id2;
|
||||
|
||||
return *args == ArgumentTypes && *rets == ReturnTypes;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PPrototype :: PropagateMark
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t PPrototype::PropagateMark()
|
||||
{
|
||||
GC::MarkArray(ArgumentTypes);
|
||||
GC::MarkArray(ReturnTypes);
|
||||
return (ArgumentTypes.Size() + ReturnTypes.Size()) * sizeof(void*) +
|
||||
Super::PropagateMark();
|
||||
}
|
||||
|
||||
/* PFunction **************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PFunction)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PFunction :: PropagataMark
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t PFunction::PropagateMark()
|
||||
{
|
||||
for (unsigned i = 0; i < Variants.Size(); ++i)
|
||||
{
|
||||
GC::Mark(Variants[i].Proto);
|
||||
GC::Mark(Variants[i].Implementation);
|
||||
}
|
||||
return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark();
|
||||
}
|
||||
|
||||
/* PClass *****************************************************************/
|
||||
|
||||
IMPLEMENT_POINTY_CLASS(PClass)
|
||||
DECLARE_POINTER(ParentClass)
|
||||
END_POINTERS
|
||||
|
||||
TArray<PClassActor *> PClass::m_RuntimeActors;
|
||||
TArray<PClass *> PClass::m_Types;
|
||||
PClass *PClass::TypeHash[PClass::HASH_SIZE];
|
||||
bool PClass::bShutdown;
|
||||
|
||||
// A harmless non-NULL FlatPointer for classes without pointers.
|
||||
static const size_t TheEnd = ~(size_t)0;
|
||||
//==========================================================================
|
||||
//
|
||||
// cregcmp
|
||||
//
|
||||
// Sorter to keep built-in types in a deterministic order. (Needed?)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int STACK_ARGS cregcmp (const void *a, const void *b)
|
||||
{
|
||||
|
@ -60,10 +470,20 @@ static int STACK_ARGS cregcmp (const void *a, const void *b)
|
|||
return strcmp(class1->TypeName, class2->TypeName);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: StaticInit STATIC
|
||||
//
|
||||
// Creates class metadata for all built-in types.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::StaticInit ()
|
||||
{
|
||||
atterm (StaticShutdown);
|
||||
|
||||
StaticBootstrap();
|
||||
|
||||
FAutoSegIterator probe(CRegHead, CRegTail);
|
||||
|
||||
while (*++probe != NULL)
|
||||
|
@ -71,24 +491,29 @@ void PClass::StaticInit ()
|
|||
((ClassReg *)*probe)->RegisterClass ();
|
||||
}
|
||||
|
||||
// Keep actors in consistant order. I did this before, though I'm not
|
||||
// sure if this is really necessary to maintain any sort of sync.
|
||||
qsort(&m_Types[0], m_Types.Size(), sizeof(m_Types[0]), cregcmp);
|
||||
for (unsigned int i = 0; i < m_Types.Size(); ++i)
|
||||
{
|
||||
m_Types[i]->ClassIndex = i;
|
||||
}
|
||||
// Keep built-in classes in consistant order. I did this before, though
|
||||
// I'm not sure if this is really necessary to maintain any sort of sync.
|
||||
qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: StaticShutdown STATIC
|
||||
//
|
||||
// Frees FlatPointers belonging to all classes. Only really needed to avoid
|
||||
// memory leak warnings at exit.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::StaticShutdown ()
|
||||
{
|
||||
TArray<size_t *> uniqueFPs(64);
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (i = 0; i < PClass::AllClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClass::m_Types[i] = NULL;
|
||||
PClass *type = PClass::AllClasses[i];
|
||||
PClass::AllClasses[i] = NULL;
|
||||
if (type->FlatPointers != &TheEnd && type->FlatPointers != type->Pointers)
|
||||
{
|
||||
// FlatPointers are shared by many classes, so we must check for
|
||||
|
@ -113,6 +538,43 @@ void PClass::StaticShutdown ()
|
|||
bShutdown = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: StaticBootstrap STATIC
|
||||
//
|
||||
// PClass and PClassClass have intermingling dependencies on their
|
||||
// definitions. To sort this out, we explicitly define them before
|
||||
// proceeding with the RegisterClass loop in StaticInit().
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::StaticBootstrap()
|
||||
{
|
||||
PClassClass *clscls = new PClassClass;
|
||||
PClassClass::RegistrationInfo.SetupClass(clscls);
|
||||
|
||||
PClassClass *cls = new PClassClass;
|
||||
PClass::RegistrationInfo.SetupClass(cls);
|
||||
|
||||
// The PClassClass constructor initialized these to NULL, because the
|
||||
// PClass metadata had not been created yet. Now it has, so we know what
|
||||
// they should be and can insert them into the type table successfully.
|
||||
clscls->TypeTableType = cls;
|
||||
cls->TypeTableType = cls;
|
||||
clscls->InsertIntoHash();
|
||||
cls->InsertIntoHash();
|
||||
|
||||
// Create parent objects before we go so that these definitions are complete.
|
||||
clscls->ParentClass = PClassType::RegistrationInfo.ParentType->RegisterClass();
|
||||
cls->ParentClass = PClass::RegistrationInfo.ParentType->RegisterClass();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass::PClass()
|
||||
{
|
||||
Size = sizeof(DObject);
|
||||
|
@ -122,10 +584,17 @@ PClass::PClass()
|
|||
HashNext = NULL;
|
||||
Defaults = NULL;
|
||||
bRuntimeClass = false;
|
||||
ClassIndex = ~0;
|
||||
ConstructNative = NULL;
|
||||
|
||||
PClass::AllClasses.Push(this);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass::~PClass()
|
||||
{
|
||||
Symbols.ReleaseSymbols();
|
||||
|
@ -136,6 +605,15 @@ PClass::~PClass()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ClassReg :: RegisterClass
|
||||
//
|
||||
// Create metadata describing the built-in class this struct is intended
|
||||
// for.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass *ClassReg::RegisterClass()
|
||||
{
|
||||
static ClassReg *const metaclasses[] =
|
||||
|
@ -148,10 +626,11 @@ PClass *ClassReg::RegisterClass()
|
|||
&PClassPuzzleItem::RegistrationInfo,
|
||||
&PClassWeapon::RegistrationInfo,
|
||||
&PClassPlayerPawn::RegistrationInfo,
|
||||
&PClassType::RegistrationInfo,
|
||||
&PClassClass::RegistrationInfo,
|
||||
};
|
||||
|
||||
// MyClass may have already been created by a previous recursive call.
|
||||
// Or this may be a recursive call for a previously created class.
|
||||
// Skip classes that have already been registered
|
||||
if (MyClass != NULL)
|
||||
{
|
||||
return MyClass;
|
||||
|
@ -165,25 +644,13 @@ PClass *ClassReg::RegisterClass()
|
|||
assert(0 && "Class registry has an invalid meta class identifier");
|
||||
}
|
||||
|
||||
if (this == &PClass::RegistrationInfo)
|
||||
{
|
||||
cls = new PClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (metaclasses[MetaClassNum]->MyClass == NULL)
|
||||
{ // Make sure the meta class is already registered before registering this one
|
||||
metaclasses[MetaClassNum]->RegisterClass();
|
||||
}
|
||||
cls = static_cast<PClass *>(metaclasses[MetaClassNum]->MyClass->CreateNew());
|
||||
}
|
||||
|
||||
MyClass = cls;
|
||||
PClass::m_Types.Push(cls);
|
||||
cls->TypeName = FName(Name+1);
|
||||
cls->Size = SizeOf;
|
||||
cls->Pointers = Pointers;
|
||||
cls->ConstructNative = ConstructNative;
|
||||
SetupClass(cls);
|
||||
cls->InsertIntoHash();
|
||||
if (ParentType != NULL)
|
||||
{
|
||||
|
@ -192,65 +659,76 @@ PClass *ClassReg::RegisterClass()
|
|||
return cls;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ClassReg :: SetupClass
|
||||
//
|
||||
// Copies the class-defining parameters from a ClassReg to the Class object
|
||||
// created for it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ClassReg::SetupClass(PClass *cls)
|
||||
{
|
||||
assert(MyClass == NULL);
|
||||
MyClass = cls;
|
||||
cls->TypeName = FName(Name+1);
|
||||
cls->Size = SizeOf;
|
||||
cls->Pointers = Pointers;
|
||||
cls->ConstructNative = ConstructNative;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: InsertIntoHash
|
||||
//
|
||||
// Add class to the type table.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::InsertIntoHash ()
|
||||
{
|
||||
// Add class to hash table. Classes are inserted into each bucket
|
||||
// in ascending order by name index.
|
||||
unsigned int bucket = TypeName % HASH_SIZE;
|
||||
PClass **hashpos = &TypeHash[bucket];
|
||||
while (*hashpos != NULL)
|
||||
{
|
||||
int lexx = int(TypeName) - int((*hashpos)->TypeName);
|
||||
size_t bucket;
|
||||
PType *found;
|
||||
|
||||
if (lexx > 0)
|
||||
{ // This type should come later in the chain
|
||||
hashpos = &((*hashpos)->HashNext);
|
||||
}
|
||||
else if (lexx == 0)
|
||||
found = TypeTable.FindType(RUNTIME_CLASS(PClass), Outer, (void*)(intptr_t)(int)TypeName, &bucket);
|
||||
if (found != NULL)
|
||||
{ // This type has already been inserted
|
||||
// ... but there is no need whatsoever to make it a fatal error!
|
||||
Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ // Type comes right here
|
||||
break;
|
||||
{
|
||||
TypeTable.AddType(this, RUNTIME_CLASS(PClass), Outer, (void*)(intptr_t)(int)TypeName, bucket);
|
||||
}
|
||||
}
|
||||
HashNext = *hashpos;
|
||||
*hashpos = this;
|
||||
}
|
||||
|
||||
// Find a type, passed the name as a name
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: FindClass
|
||||
//
|
||||
// Find a type, passed the name as a name.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass *PClass::FindClass (FName zaname)
|
||||
{
|
||||
if (zaname == NAME_None)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PClass *cls = TypeHash[zaname % HASH_SIZE];
|
||||
|
||||
while (cls != 0)
|
||||
{
|
||||
int lexx = int(zaname) - int(cls->TypeName);
|
||||
if (lexx > 0)
|
||||
{
|
||||
cls = cls->HashNext;
|
||||
}
|
||||
else if (lexx == 0)
|
||||
{
|
||||
return cls->Size<0? NULL : cls;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass),
|
||||
/*FIXME:Outer*/NULL, (void*)(intptr_t)(int)zaname, NULL));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: CreateNew
|
||||
//
|
||||
// Create a new object that this class represents
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DObject *PClass::CreateNew() const
|
||||
{
|
||||
BYTE *mem = (BYTE *)M_Malloc (Size);
|
||||
|
@ -267,7 +745,14 @@ DObject *PClass::CreateNew() const
|
|||
return (DObject *)mem;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: Derive
|
||||
//
|
||||
// Copies inheritable values into the derived class and other miscellaneous setup.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::Derive(PClass *newclass)
|
||||
{
|
||||
newclass->ParentClass = this;
|
||||
|
@ -275,7 +760,7 @@ void PClass::Derive(PClass *newclass)
|
|||
|
||||
// Set up default instance of the new class.
|
||||
newclass->Defaults = (BYTE *)M_Malloc(newclass->Size);
|
||||
memcpy(newclass->Defaults, Defaults, Size);
|
||||
if (Defaults) memcpy(newclass->Defaults, Defaults, Size);
|
||||
if (newclass->Size > Size)
|
||||
{
|
||||
memset(newclass->Defaults + Size, 0, newclass->Size - Size);
|
||||
|
@ -284,8 +769,15 @@ void PClass::Derive(PClass *newclass)
|
|||
newclass->Symbols.SetParentTable(&this->Symbols);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: CreateDerivedClass
|
||||
//
|
||||
// Create a new class based on an existing class
|
||||
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||
{
|
||||
assert (size >= Size);
|
||||
PClass *type;
|
||||
|
@ -317,20 +809,20 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
|
|||
Derive(type);
|
||||
if (!notnew)
|
||||
{
|
||||
type->ClassIndex = m_Types.Push (type);
|
||||
type->InsertIntoHash();
|
||||
}
|
||||
|
||||
// If this class is for an actor, push it onto the RuntimeActors stack.
|
||||
if (type->IsKindOf(RUNTIME_CLASS(PClassActor)))
|
||||
{
|
||||
m_RuntimeActors.Push(static_cast<PClassActor *>(type));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Add <extension> bytes to the end of this class. Returns the
|
||||
// previous size of the class.
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass:: Extend
|
||||
//
|
||||
// Add <extension> bytes to the end of this class. Returns the previous
|
||||
// size of the class.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
unsigned int PClass::Extend(unsigned int extension)
|
||||
{
|
||||
assert(this->bRuntimeClass);
|
||||
|
@ -342,33 +834,30 @@ unsigned int PClass::Extend(unsigned int extension)
|
|||
return oldsize;
|
||||
}
|
||||
|
||||
// Like FindClass but creates a placeholder if no class
|
||||
// is found. CreateDerivedClass will automatcally fill in
|
||||
// the placeholder when the actual class is defined.
|
||||
PClass *PClass::FindClassTentative (FName name)
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: FindClassTentative
|
||||
//
|
||||
// Like FindClass but creates a placeholder if no class is found.
|
||||
// CreateDerivedClass will automatically fill in the placeholder when the
|
||||
// actual class is defined.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass *PClass::FindClassTentative(FName name)
|
||||
{
|
||||
if (name == NAME_None)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
size_t bucket;
|
||||
|
||||
PClass *cls = TypeHash[name % HASH_SIZE];
|
||||
PType *found = TypeTable.FindType(RUNTIME_CLASS(PClass),
|
||||
/*FIXME:Outer*/NULL, (void*)(intptr_t)(int)name, &bucket);
|
||||
|
||||
while (cls != 0)
|
||||
if (found != NULL)
|
||||
{
|
||||
int lexx = int(name) - int(cls->TypeName);
|
||||
if (lexx > 0)
|
||||
{
|
||||
cls = cls->HashNext;
|
||||
}
|
||||
else if (lexx == 0)
|
||||
{
|
||||
return cls;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
return static_cast<PClass *>(found);
|
||||
}
|
||||
PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
|
||||
DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
|
||||
|
@ -376,16 +865,22 @@ PClass *PClass::FindClassTentative (FName name)
|
|||
type->TypeName = name;
|
||||
type->ParentClass = this;
|
||||
type->Size = -1;
|
||||
type->ClassIndex = m_Types.Push (type);
|
||||
type->bRuntimeClass = true;
|
||||
type->InsertIntoHash();
|
||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), type->Outer, (void*)(intptr_t)(int)name, bucket);
|
||||
return type;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: BuildFlatPointers
|
||||
//
|
||||
// Create the FlatPointers array, if it doesn't exist already.
|
||||
// It comprises all the Pointers from superclasses plus this class's own Pointers.
|
||||
// If this class does not define any new Pointers, then FlatPointers will be set
|
||||
// to the same array as the super class's.
|
||||
// It comprises all the Pointers from superclasses plus this class's own
|
||||
// Pointers. If this class does not define any new Pointers, then
|
||||
// FlatPointers will be set to the same array as the super class.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void PClass::BuildFlatPointers ()
|
||||
{
|
||||
if (FlatPointers != NULL)
|
||||
|
@ -433,6 +928,14 @@ void PClass::BuildFlatPointers ()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: NativeClass
|
||||
//
|
||||
// Finds the underlying native type underlying this class.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const PClass *PClass::NativeClass() const
|
||||
{
|
||||
const PClass *cls = this;
|
||||
|
@ -443,6 +946,12 @@ const PClass *PClass::NativeClass() const
|
|||
return cls;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClass :: PropagateMark
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t PClass::PropagateMark()
|
||||
{
|
||||
size_t marked;
|
||||
|
@ -453,6 +962,74 @@ size_t PClass::PropagateMark()
|
|||
return marked + Super::PropagateMark();
|
||||
}
|
||||
|
||||
/* FTypeTable **************************************************************/
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FTypeTable :: FindType
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PType *FTypeTable::FindType(PClass *metatype, void *parm1, void *parm2, size_t *bucketnum)
|
||||
{
|
||||
size_t bucket = Hash(metatype, parm1, parm2) % HASH_SIZE;
|
||||
if (bucketnum != NULL)
|
||||
{
|
||||
*bucketnum = bucket;
|
||||
}
|
||||
for (PType *type = TypeHash[bucket]; type != NULL; type = type->HashNext)
|
||||
{
|
||||
if (type->GetClass()->TypeTableType == metatype && type->IsMatch(parm1, parm2))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FTypeTable :: AddType
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTypeTable::AddType(PType *type, PClass *metatype, void *parm1, void *parm2, size_t bucket)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
size_t bucketcheck;
|
||||
assert(metatype == type->GetClass()->TypeTableType && "Metatype does not match passed object");
|
||||
assert(FindType(metatype, parm1, parm2, &bucketcheck) == NULL && "Type must not be inserted more than once");
|
||||
assert(bucketcheck == bucket && "Passed bucket was wrong");
|
||||
#endif
|
||||
type->HashNext = TypeHash[bucket];
|
||||
TypeHash[bucket] = type;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FTypeTable :: Hash STATIC
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t FTypeTable::Hash(void *p1, void *p2, void *p3)
|
||||
{
|
||||
size_t i1 = (size_t)p1;
|
||||
size_t i2 = (size_t)p2;
|
||||
size_t i3 = (size_t)p3;
|
||||
|
||||
// Swap the high and low halves of i1. The compiler should be smart enough
|
||||
// to transform this into a ROR or ROL.
|
||||
i1 = (i1 >> (sizeof(size_t)*4)) | (i1 << (sizeof(size_t)*4));
|
||||
|
||||
return (~i1 ^ i2) + i3 * 961748927; // i3 is multiplied by a prime
|
||||
}
|
||||
|
||||
#include "c_dispatch.h"
|
||||
CCMD(typetable)
|
||||
{
|
||||
DumpTypeTable();
|
||||
}
|
||||
|
||||
// Symbol tables ------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
|
||||
|
@ -465,6 +1042,12 @@ IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
|
|||
DECLARE_POINTER(Function)
|
||||
END_POINTERS
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PSymbol::~PSymbol()
|
||||
{
|
||||
}
|
||||
|
|
347
src/dobjtype.h
347
src/dobjtype.h
|
@ -140,28 +140,274 @@ private:
|
|||
friend class DObject;
|
||||
};
|
||||
|
||||
// Basic information shared by all types ------------------------------------
|
||||
|
||||
// Only one copy of a type is ever instantiated at one time.
|
||||
// - Enums, classes, and structs are defined by their names and outer classes.
|
||||
// - Pointers are uniquely defined by the type they point at.
|
||||
// - ClassPointers are also defined by their class restriction.
|
||||
// - Arrays are defined by their element type and count.
|
||||
// - DynArrays are defined by their element type.
|
||||
// - Maps are defined by their key and value types.
|
||||
// - Prototypes are defined by the argument and return types.
|
||||
// - Functions are defined by their names and outer objects.
|
||||
// In table form:
|
||||
// Outer Name Type Type2 Count
|
||||
// Enum * *
|
||||
// Class * *
|
||||
// Struct * *
|
||||
// Function * *
|
||||
// Pointer *
|
||||
// ClassPointer + *
|
||||
// Array * *
|
||||
// DynArray *
|
||||
// Map * *
|
||||
// Prototype *+ *+
|
||||
|
||||
class PClassType;
|
||||
class PType : public DObject
|
||||
{
|
||||
//DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType);
|
||||
// We need to unravel the _WITH_META macro, since PClassType isn't defined yet,
|
||||
// and we can't define it until we've defined PClass. But we can't define that
|
||||
// without defining PType.
|
||||
DECLARE_ABSTRACT_CLASS(PType, DObject)
|
||||
protected:
|
||||
enum { MetaClassNum = CLASSREG_PClassType };
|
||||
public:
|
||||
typedef PClassType MetaClass;
|
||||
MetaClass *GetClass() const;
|
||||
|
||||
unsigned int Size; // this type's size
|
||||
unsigned int Align; // this type's preferred alignment
|
||||
PType *HashNext; // next type in this type table
|
||||
|
||||
PType();
|
||||
virtual ~PType();
|
||||
|
||||
// Returns true if this type matches the two identifiers. Referring to the
|
||||
// above table, any type is identified by at most two characteristics. Each
|
||||
// type that implements this function will cast these to the appropriate type.
|
||||
// It is up to the caller to make sure they are the correct types. There is
|
||||
// only one prototype for this function in order to simplify type table
|
||||
// management.
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
|
||||
static void StaticInit();
|
||||
};
|
||||
|
||||
// Some categorization typing -----------------------------------------------
|
||||
|
||||
class PBasicType : public PType
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(PBasicType, PType);
|
||||
};
|
||||
|
||||
class PCompoundType : public PType
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
|
||||
};
|
||||
|
||||
class PNamedType : public PCompoundType
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
DObject *Outer; // object this type is contained within
|
||||
FName TypeName; // this type's name
|
||||
|
||||
PNamedType() : Outer(NULL) {}
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
// Basic types --------------------------------------------------------------
|
||||
|
||||
class PInt : public PBasicType
|
||||
{
|
||||
DECLARE_CLASS(PInt, PBasicType);
|
||||
};
|
||||
|
||||
class PFloat : public PBasicType
|
||||
{
|
||||
DECLARE_CLASS(PFloat, PBasicType);
|
||||
};
|
||||
|
||||
class PString : public PBasicType
|
||||
{
|
||||
DECLARE_CLASS(PString, PBasicType);
|
||||
};
|
||||
|
||||
// Variations of integer types ----------------------------------------------
|
||||
|
||||
class PName : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PName, PInt);
|
||||
};
|
||||
|
||||
class PSound : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PSound, PInt);
|
||||
};
|
||||
|
||||
class PColor : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PColor, PInt);
|
||||
};
|
||||
|
||||
// Pointers -----------------------------------------------------------------
|
||||
|
||||
class PPointer : public PInt
|
||||
{
|
||||
DECLARE_CLASS(PPointer, PInt);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PType *PointedType;
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
class PClass;
|
||||
class PClassPointer : public PPointer
|
||||
{
|
||||
DECLARE_CLASS(PClassPointer, PPointer);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PClass *ClassRestriction;
|
||||
|
||||
typedef PClass *Type2;
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
// Struct/class fields ------------------------------------------------------
|
||||
|
||||
class PField : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(PField, DObject);
|
||||
public:
|
||||
FName FieldName;
|
||||
};
|
||||
|
||||
class PMemberField : public PField
|
||||
{
|
||||
DECLARE_CLASS(PMemberField, PField);
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
unsigned int FieldOffset;
|
||||
PType *FieldType;
|
||||
};
|
||||
|
||||
// Compound types -----------------------------------------------------------
|
||||
|
||||
class PEnum : public PNamedType
|
||||
{
|
||||
DECLARE_CLASS(PEnum, PNamedType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PType *ValueType;
|
||||
TMap<FName, int> Values;
|
||||
};
|
||||
|
||||
class PArray : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PArray, PCompoundType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PType *ElementType;
|
||||
unsigned int ElementCount;
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
// A vector is an array with extra operations.
|
||||
class PVector : public PArray
|
||||
{
|
||||
DECLARE_CLASS(PVector, PArray);
|
||||
HAS_OBJECT_POINTERS;
|
||||
};
|
||||
|
||||
class PDynArray : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PDynArray, PCompoundType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PType *ElementType;
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
class PMap : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PMap, PCompoundType);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
PType *KeyType;
|
||||
PType *ValueType;
|
||||
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
class PStruct : public PNamedType
|
||||
{
|
||||
DECLARE_CLASS(PStruct, PNamedType);
|
||||
public:
|
||||
TArray<PField *> Fields;
|
||||
|
||||
size_t PropagateMark();
|
||||
};
|
||||
|
||||
class PPrototype : public PCompoundType
|
||||
{
|
||||
DECLARE_CLASS(PPrototype, PCompoundType);
|
||||
public:
|
||||
TArray<PType *> ArgumentTypes;
|
||||
TArray<PType *> ReturnTypes;
|
||||
|
||||
size_t PropagateMark();
|
||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
||||
};
|
||||
|
||||
// TBD: Should we support overloading?
|
||||
class PFunction : public PNamedType
|
||||
{
|
||||
DECLARE_CLASS(PFunction, PNamedType);
|
||||
public:
|
||||
struct Variant
|
||||
{
|
||||
PPrototype *Proto;
|
||||
VMFunction *Implementation;
|
||||
};
|
||||
TArray<Variant> Variants;
|
||||
|
||||
size_t PropagateMark();
|
||||
};
|
||||
|
||||
// Meta-info for every class derived from DObject ---------------------------
|
||||
|
||||
class PClass : public DObject
|
||||
class PClassClass;
|
||||
class PClass : public PStruct
|
||||
{
|
||||
DECLARE_CLASS(PClass, DObject);
|
||||
DECLARE_CLASS(PClass, PStruct);
|
||||
HAS_OBJECT_POINTERS;
|
||||
protected:
|
||||
virtual void Derive(PClass *newclass);
|
||||
// We unravel _WITH_META here just as we did for PType.
|
||||
enum { MetaClassNum = CLASSREG_PClassClass };
|
||||
public:
|
||||
static void StaticInit ();
|
||||
static void StaticShutdown ();
|
||||
typedef PClassClass MetaClass;
|
||||
MetaClass *GetClass() const;
|
||||
|
||||
static void StaticInit();
|
||||
static void StaticShutdown();
|
||||
static void StaticBootstrap();
|
||||
|
||||
// Per-class information -------------------------------------
|
||||
FName TypeName; // this class's name
|
||||
unsigned int Size; // this class's size
|
||||
PClass *ParentClass; // the class this class derives from
|
||||
const size_t *Pointers; // object pointers defined by this class *only*
|
||||
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
|
||||
PClass *HashNext;
|
||||
BYTE *Defaults;
|
||||
bool bRuntimeClass; // class was defined at run-time, not compile-time
|
||||
unsigned short ClassIndex;
|
||||
PSymbolTable Symbols;
|
||||
|
||||
void (*ConstructNative)(void *);
|
||||
|
@ -169,17 +415,17 @@ public:
|
|||
// The rest are all functions and static data ----------------
|
||||
PClass();
|
||||
~PClass();
|
||||
void InsertIntoHash ();
|
||||
DObject *CreateNew () const;
|
||||
PClass *CreateDerivedClass (FName name, unsigned int size);
|
||||
void InsertIntoHash();
|
||||
DObject *CreateNew() const;
|
||||
PClass *CreateDerivedClass(FName name, unsigned int size);
|
||||
unsigned int Extend(unsigned int extension);
|
||||
void InitializeActorInfo ();
|
||||
void BuildFlatPointers ();
|
||||
void InitializeActorInfo();
|
||||
void BuildFlatPointers();
|
||||
const PClass *NativeClass() const;
|
||||
size_t PropagateMark();
|
||||
|
||||
// Returns true if this type is an ancestor of (or same as) the passed type.
|
||||
bool IsAncestorOf (const PClass *ti) const
|
||||
bool IsAncestorOf(const PClass *ti) const
|
||||
{
|
||||
while (ti)
|
||||
{
|
||||
|
@ -189,29 +435,70 @@ public:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
inline bool IsDescendantOf (const PClass *ti) const
|
||||
inline bool IsDescendantOf(const PClass *ti) const
|
||||
{
|
||||
return ti->IsAncestorOf (this);
|
||||
return ti->IsAncestorOf(this);
|
||||
}
|
||||
|
||||
// Find a type, given its name.
|
||||
static PClass *FindClass (const char *name) { return FindClass (FName (name, true)); }
|
||||
static PClass *FindClass (const FString &name) { return FindClass (FName (name, true)); }
|
||||
static PClass *FindClass (ENamedName name) { return FindClass (FName (name)); }
|
||||
static PClass *FindClass (FName name);
|
||||
static PClassActor *FindActor (const char *name) { return FindActor (FName (name, true)); }
|
||||
static PClassActor *FindActor (const FString &name) { return FindActor (FName (name, true)); }
|
||||
static PClassActor *FindActor (ENamedName name) { return FindActor (FName (name)); }
|
||||
static PClassActor *FindActor (FName name);
|
||||
PClass *FindClassTentative (FName name); // not static!
|
||||
static PClass *FindClass(const char *name) { return FindClass(FName(name, true)); }
|
||||
static PClass *FindClass(const FString &name) { return FindClass(FName(name, true)); }
|
||||
static PClass *FindClass(ENamedName name) { return FindClass(FName(name)); }
|
||||
static PClass *FindClass(FName name);
|
||||
static PClassActor *FindActor(const char *name) { return FindActor(FName(name, true)); }
|
||||
static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); }
|
||||
static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); }
|
||||
static PClassActor *FindActor(FName name);
|
||||
PClass *FindClassTentative(FName name); // not static!
|
||||
|
||||
static TArray<PClass *> m_Types;
|
||||
static TArray<PClassActor *> m_RuntimeActors;
|
||||
|
||||
enum { HASH_SIZE = 256 };
|
||||
static PClass *TypeHash[HASH_SIZE];
|
||||
static TArray<PClass *> AllClasses;
|
||||
|
||||
static bool bShutdown;
|
||||
};
|
||||
|
||||
class PClassType : public PClass
|
||||
{
|
||||
DECLARE_CLASS(PClassType, PClass);
|
||||
protected:
|
||||
virtual void Derive(PClass *newclass);
|
||||
public:
|
||||
PClassType();
|
||||
|
||||
PClass *TypeTableType; // The type to use for hashing into the type table
|
||||
};
|
||||
|
||||
inline PType::MetaClass *PType::GetClass() const
|
||||
{
|
||||
return static_cast<MetaClass *>(DObject::GetClass());
|
||||
}
|
||||
|
||||
class PClassClass : public PClassType
|
||||
{
|
||||
DECLARE_CLASS(PClassClass, PClassType);
|
||||
public:
|
||||
PClassClass();
|
||||
};
|
||||
|
||||
inline PClass::MetaClass *PClass::GetClass() const
|
||||
{
|
||||
return static_cast<MetaClass *>(DObject::GetClass());
|
||||
}
|
||||
|
||||
// Type tables --------------------------------------------------------------
|
||||
|
||||
struct FTypeTable
|
||||
{
|
||||
enum { HASH_SIZE = 1021 };
|
||||
|
||||
PType *TypeHash[HASH_SIZE];
|
||||
|
||||
PType *FindType(PClass *metatype, void *parm1, void *parm2, size_t *bucketnum);
|
||||
void AddType(PType *type, PClass *metatype, void *parm1, void *parm2, size_t bucket);
|
||||
|
||||
static size_t Hash(void *p1, void *p2, void *p3);
|
||||
};
|
||||
|
||||
|
||||
extern FTypeTable TypeTable;
|
||||
|
||||
#endif
|
||||
|
|
131
src/farchive.cpp
131
src/farchive.cpp
|
@ -637,12 +637,8 @@ FArchive::FArchive (FFile &file)
|
|||
|
||||
void FArchive::AttachToFile (FFile &file)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
m_HubTravel = false;
|
||||
m_File = &file;
|
||||
m_MaxObjectCount = m_ObjectCount = 0;
|
||||
m_ObjectMap = NULL;
|
||||
if (file.Mode() == FFile::EReading)
|
||||
{
|
||||
m_Loading = true;
|
||||
|
@ -654,19 +650,13 @@ void FArchive::AttachToFile (FFile &file)
|
|||
m_Storing = true;
|
||||
}
|
||||
m_Persistent = file.IsPersistent();
|
||||
m_TypeMap = NULL;
|
||||
m_TypeMap = new TypeMap[PClass::m_Types.Size()];
|
||||
for (i = 0; i < PClass::m_Types.Size(); i++)
|
||||
{
|
||||
m_TypeMap[i].toArchive = TypeMap::NO_INDEX;
|
||||
m_TypeMap[i].toCurrent = NULL;
|
||||
}
|
||||
m_ClassCount = 0;
|
||||
for (i = 0; i < EObjectHashSize; i++)
|
||||
{
|
||||
m_ObjectHash[i] = ~0;
|
||||
m_NameHash[i] = NameMap::NO_INDEX;
|
||||
}
|
||||
|
||||
ClassToArchive.Clear();
|
||||
ArchiveToClass.Clear();
|
||||
|
||||
ObjectToArchive.Clear();
|
||||
ArchiveToObject.Clear();
|
||||
|
||||
m_NumSprites = 0;
|
||||
m_SpriteMap = new int[sprites.Size()];
|
||||
for (size_t s = 0; s < sprites.Size(); ++s)
|
||||
|
@ -678,10 +668,6 @@ void FArchive::AttachToFile (FFile &file)
|
|||
FArchive::~FArchive ()
|
||||
{
|
||||
Close ();
|
||||
if (m_TypeMap)
|
||||
delete[] m_TypeMap;
|
||||
if (m_ObjectMap)
|
||||
M_Free (m_ObjectMap);
|
||||
if (m_SpriteMap)
|
||||
delete[] m_SpriteMap;
|
||||
}
|
||||
|
@ -702,7 +688,7 @@ void FArchive::Close ()
|
|||
{
|
||||
m_File->Close ();
|
||||
m_File = NULL;
|
||||
DPrintf ("Processed %u objects\n", m_ObjectCount);
|
||||
DPrintf ("Processed %u objects\n", ArchiveToObject.Size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1044,6 +1030,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
else
|
||||
{
|
||||
PClass *type = obj->GetClass();
|
||||
DWORD *classarcid;
|
||||
|
||||
if (type == RUNTIME_CLASS(DObject))
|
||||
{
|
||||
|
@ -1052,7 +1039,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
id[0] = NULL_OBJ;
|
||||
Write (id, 1);
|
||||
}
|
||||
else if (m_TypeMap[type->ClassIndex].toArchive == TypeMap::NO_INDEX)
|
||||
else if (NULL == (classarcid = ClassToArchive.CheckKey(type)))
|
||||
{
|
||||
// No instances of this class have been written out yet.
|
||||
// Write out the class, then write out the object. If this
|
||||
|
@ -1085,9 +1072,9 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
// to the saved object. Otherwise, save a reference to the
|
||||
// class, then save the object. Again, if this is a player-
|
||||
// controlled actor, remember that.
|
||||
DWORD index = FindObjectIndex (obj);
|
||||
DWORD *objarcid = ObjectToArchive.CheckKey(obj);
|
||||
|
||||
if (index == TypeMap::NO_INDEX)
|
||||
if (objarcid == NULL)
|
||||
{
|
||||
|
||||
if (obj->IsKindOf (RUNTIME_CLASS (AActor)) &&
|
||||
|
@ -1103,7 +1090,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
id[0] = NEW_OBJ;
|
||||
Write (id, 1);
|
||||
}
|
||||
WriteCount (m_TypeMap[type->ClassIndex].toArchive);
|
||||
WriteCount (*classarcid);
|
||||
// Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell());
|
||||
MapObject (obj);
|
||||
obj->SerializeUserVars (*this);
|
||||
|
@ -1114,7 +1101,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
|
|||
{
|
||||
id[0] = OLD_OBJ;
|
||||
Write (id, 1);
|
||||
WriteCount (index);
|
||||
WriteCount (*objarcid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1141,12 +1128,12 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
|
|||
break;
|
||||
|
||||
case OLD_OBJ:
|
||||
index = ReadCount ();
|
||||
if (index >= m_ObjectCount)
|
||||
index = ReadCount();
|
||||
if (index >= ArchiveToObject.Size())
|
||||
{
|
||||
I_Error ("Object reference too high (%u; max is %u)\n", index, m_ObjectCount);
|
||||
I_Error ("Object reference too high (%u; max is %u)\n", index, ArchiveToObject.Size());
|
||||
}
|
||||
obj = (DObject *)m_ObjectMap[index].object;
|
||||
obj = ArchiveToObject[index];
|
||||
break;
|
||||
|
||||
case NEW_PLYR_CLS_OBJ:
|
||||
|
@ -1363,19 +1350,14 @@ DWORD FArchive::FindName (const char *name, unsigned int bucket) const
|
|||
|
||||
DWORD FArchive::WriteClass (PClass *info)
|
||||
{
|
||||
if (m_ClassCount >= PClass::m_Types.Size())
|
||||
{
|
||||
I_Error ("Too many unique classes have been written.\nOnly %u were registered\n",
|
||||
PClass::m_Types.Size());
|
||||
}
|
||||
if (m_TypeMap[info->ClassIndex].toArchive != TypeMap::NO_INDEX)
|
||||
if (ClassToArchive.CheckKey(info) != NULL)
|
||||
{
|
||||
I_Error ("Attempt to write '%s' twice.\n", info->TypeName.GetChars());
|
||||
}
|
||||
m_TypeMap[info->ClassIndex].toArchive = m_ClassCount;
|
||||
m_TypeMap[m_ClassCount].toCurrent = info;
|
||||
DWORD index = ArchiveToClass.Push(info);
|
||||
ClassToArchive[info] = index;
|
||||
WriteString (info->TypeName.GetChars());
|
||||
return m_ClassCount++;
|
||||
return index;
|
||||
}
|
||||
|
||||
PClass *FArchive::ReadClass ()
|
||||
|
@ -1386,24 +1368,15 @@ PClass *FArchive::ReadClass ()
|
|||
char *val;
|
||||
} typeName;
|
||||
|
||||
if (m_ClassCount >= PClass::m_Types.Size())
|
||||
{
|
||||
I_Error ("Too many unique classes have been read.\nOnly %u were registered\n",
|
||||
PClass::m_Types.Size());
|
||||
}
|
||||
operator<< (typeName.val);
|
||||
FName zaname(typeName.val, true);
|
||||
if (zaname != NAME_None)
|
||||
{
|
||||
for (unsigned int i = PClass::m_Types.Size(); i-- > 0; )
|
||||
PClass *type = PClass::FindClass(zaname);
|
||||
if (type != NULL)
|
||||
{
|
||||
if (PClass::m_Types[i]->TypeName == zaname)
|
||||
{
|
||||
m_TypeMap[i].toArchive = m_ClassCount;
|
||||
m_TypeMap[m_ClassCount].toCurrent = PClass::m_Types[i];
|
||||
m_ClassCount++;
|
||||
return PClass::m_Types[i];
|
||||
}
|
||||
ClassToArchive[type] = ArchiveToClass.Push(type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
I_Error ("Unknown class '%s'\n", typeName.val);
|
||||
|
@ -1425,11 +1398,7 @@ PClass *FArchive::ReadClass (const PClass *wanttype)
|
|||
PClass *FArchive::ReadStoredClass (const PClass *wanttype)
|
||||
{
|
||||
DWORD index = ReadCount ();
|
||||
if (index >= m_ClassCount)
|
||||
{
|
||||
I_Error ("Class reference too high (%u; max is %u)\n", index, m_ClassCount);
|
||||
}
|
||||
PClass *type = m_TypeMap[index].toCurrent;
|
||||
PClass *type = ArchiveToClass[index];
|
||||
if (!type->IsDescendantOf (wanttype))
|
||||
{
|
||||
I_Error ("Expected to extract an object of type '%s'.\n"
|
||||
|
@ -1439,44 +1408,11 @@ PClass *FArchive::ReadStoredClass (const PClass *wanttype)
|
|||
return type;
|
||||
}
|
||||
|
||||
DWORD FArchive::MapObject (const DObject *obj)
|
||||
DWORD FArchive::MapObject (DObject *obj)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (m_ObjectCount >= m_MaxObjectCount)
|
||||
{
|
||||
m_MaxObjectCount = m_MaxObjectCount ? m_MaxObjectCount * 2 : 1024;
|
||||
m_ObjectMap = (ObjectMap *)M_Realloc (m_ObjectMap, sizeof(ObjectMap)*m_MaxObjectCount);
|
||||
for (i = m_ObjectCount; i < m_MaxObjectCount; i++)
|
||||
{
|
||||
m_ObjectMap[i].hashNext = ~0;
|
||||
m_ObjectMap[i].object = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD index = m_ObjectCount++;
|
||||
DWORD hash = HashObject (obj);
|
||||
|
||||
m_ObjectMap[index].object = obj;
|
||||
m_ObjectMap[index].hashNext = m_ObjectHash[hash];
|
||||
m_ObjectHash[hash] = index;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
DWORD FArchive::HashObject (const DObject *obj) const
|
||||
{
|
||||
return (DWORD)((size_t)obj % EObjectHashSize);
|
||||
}
|
||||
|
||||
DWORD FArchive::FindObjectIndex (const DObject *obj) const
|
||||
{
|
||||
DWORD index = m_ObjectHash[HashObject (obj)];
|
||||
while (index != TypeMap::NO_INDEX && m_ObjectMap[index].object != obj)
|
||||
{
|
||||
index = m_ObjectMap[index].hashNext;
|
||||
}
|
||||
return index;
|
||||
DWORD i = ArchiveToObject.Push(obj);
|
||||
ObjectToArchive[obj] = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
void FArchive::UserWriteClass (PClass *type)
|
||||
|
@ -1490,7 +1426,8 @@ void FArchive::UserWriteClass (PClass *type)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (m_TypeMap[type->ClassIndex].toArchive == TypeMap::NO_INDEX)
|
||||
DWORD *arcid;
|
||||
if (NULL == (arcid = ClassToArchive.CheckKey(type)))
|
||||
{
|
||||
id = 1;
|
||||
Write (&id, 1);
|
||||
|
@ -1500,7 +1437,7 @@ void FArchive::UserWriteClass (PClass *type)
|
|||
{
|
||||
id = 0;
|
||||
Write (&id, 1);
|
||||
WriteCount (m_TypeMap[type->ClassIndex].toArchive);
|
||||
WriteCount (*arcid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,13 +209,11 @@ inline FArchive& operator<< (DObject* &object) { return ReadObject (object, RUN
|
|||
protected:
|
||||
enum { EObjectHashSize = 137 };
|
||||
|
||||
DWORD FindObjectIndex (const DObject *obj) const;
|
||||
DWORD MapObject (const DObject *obj);
|
||||
DWORD MapObject (DObject *obj);
|
||||
DWORD WriteClass (PClass *info);
|
||||
PClass *ReadClass ();
|
||||
PClass *ReadClass (const PClass *wanttype);
|
||||
PClass *ReadStoredClass (const PClass *wanttype);
|
||||
DWORD HashObject (const DObject *obj) const;
|
||||
DWORD AddName (const char *name);
|
||||
DWORD AddName (unsigned int start); // Name has already been added to storage
|
||||
DWORD FindName (const char *name) const;
|
||||
|
@ -226,24 +224,12 @@ protected:
|
|||
bool m_Storing; // inserting objects?
|
||||
bool m_HubTravel; // travelling inside a hub?
|
||||
FFile *m_File; // unerlying file object
|
||||
DWORD m_ObjectCount; // # of objects currently serialized
|
||||
DWORD m_MaxObjectCount;
|
||||
DWORD m_ClassCount; // # of unique classes currently serialized
|
||||
|
||||
struct TypeMap
|
||||
{
|
||||
PClass *toCurrent; // maps archive type index to execution type index
|
||||
DWORD toArchive; // maps execution type index to archive type index
|
||||
TMap<PClass *, DWORD> ClassToArchive; // Maps PClass to archive type index
|
||||
TArray<PClass *> ArchiveToClass; // Maps archive type index to PClass
|
||||
|
||||
enum { NO_INDEX = 0xffffffff };
|
||||
} *m_TypeMap;
|
||||
|
||||
struct ObjectMap
|
||||
{
|
||||
const DObject *object;
|
||||
DWORD hashNext;
|
||||
} *m_ObjectMap;
|
||||
DWORD m_ObjectHash[EObjectHashSize];
|
||||
TMap<DObject *, DWORD> ObjectToArchive; // Maps objects to archive index
|
||||
TArray<DObject *> ArchiveToObject; // Maps archive index to objects
|
||||
|
||||
struct NameMap
|
||||
{
|
||||
|
|
|
@ -309,27 +309,27 @@ static void ParseLock(FScanner &sc)
|
|||
static void ClearLocks()
|
||||
{
|
||||
unsigned int i;
|
||||
for(i=0;i<PClass::m_Types.Size();i++)
|
||||
for(i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||
{
|
||||
if (PClass::m_Types[i]->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
||||
if (PClassActor::AllActorClasses[i]->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
||||
{
|
||||
AKey *key = static_cast<AKey*>(GetDefaultByType(PClass::m_Types[i]));
|
||||
AKey *key = static_cast<AKey*>(GetDefaultByType(PClassActor::AllActorClasses[i]));
|
||||
if (key != NULL)
|
||||
{
|
||||
key->KeyNumber = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0;i<256;i++)
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
if (locks[i]!=NULL)
|
||||
if (locks[i] != NULL)
|
||||
{
|
||||
delete locks[i];
|
||||
locks[i]=NULL;
|
||||
locks[i] = NULL;
|
||||
}
|
||||
}
|
||||
currentnumber=0;
|
||||
keysdone=false;
|
||||
currentnumber = 0;
|
||||
keysdone = false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -1643,9 +1643,9 @@ AInventory *ABackpackItem::CreateCopy (AActor *other)
|
|||
{
|
||||
// Find every unique type of ammo. Give it to the player if
|
||||
// he doesn't have it already, and double its maximum capacity.
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClass *type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->ParentClass == RUNTIME_CLASS(AAmmo))
|
||||
{
|
||||
|
|
|
@ -1119,9 +1119,9 @@ void FWeaponSlots::AddExtraWeapons()
|
|||
}
|
||||
|
||||
// Append extra weapons to the slots.
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *cls = PClass::m_Types[i];
|
||||
PClass *cls = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (!cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
|
||||
{
|
||||
|
@ -1569,9 +1569,9 @@ void P_SetupWeapons_ntohton()
|
|||
|
||||
cls = NULL;
|
||||
Weapons_ntoh.Push(cls); // Index 0 is always NULL.
|
||||
for (i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *cls = PClass::m_Types[i];
|
||||
PClassActor *cls = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
|
||||
{
|
||||
|
|
|
@ -2161,7 +2161,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
|
|||
if(statusBar->CPlayer->cls == NULL)
|
||||
return; //No class so we can not continue
|
||||
|
||||
int spawnClass = statusBar->CPlayer->cls->ClassIndex;
|
||||
PClass *spawnClass = statusBar->CPlayer->cls;
|
||||
for(unsigned int i = 0;i < classes.Size();i++)
|
||||
{
|
||||
if(classes[i] == spawnClass)
|
||||
|
@ -2179,7 +2179,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
|
|||
if(stricmp(sc.String, PlayerClasses[c].Type->DisplayName) == 0)
|
||||
{
|
||||
foundClass = true;
|
||||
classes.Push(PlayerClasses[c].Type->ClassIndex);
|
||||
classes.Push(PlayerClasses[c].Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2192,7 +2192,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
|
|||
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
|
||||
}
|
||||
protected:
|
||||
TArray<int> classes;
|
||||
TArray<PClass*> classes;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -327,9 +327,9 @@ static int STACK_ARGS ktcmp(const void * a, const void * b)
|
|||
|
||||
static void SetKeyTypes()
|
||||
{
|
||||
for(unsigned int i = 0; i < PClass::m_Types.Size(); i++)
|
||||
for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||
{
|
||||
PClass *ti = PClass::m_Types[i];
|
||||
PClass *ti = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (ti->IsDescendantOf(RUNTIME_CLASS(AKey)))
|
||||
{
|
||||
|
|
12
src/info.cpp
12
src/info.cpp
|
@ -53,6 +53,8 @@
|
|||
|
||||
extern void LoadActors ();
|
||||
|
||||
TArray<PClassActor *> PClassActor::AllActorClasses;
|
||||
|
||||
bool FState::CallAction(AActor *self, AActor *stateowner, StateCallData *statecall)
|
||||
{
|
||||
if (ActionFunc != NULL)
|
||||
|
@ -151,9 +153,9 @@ void PClassActor::StaticSetActorNums()
|
|||
memset(SpawnableThings, 0, sizeof(SpawnableThings));
|
||||
DoomEdMap.Empty();
|
||||
|
||||
for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
static_cast<PClassActor *>(PClass::m_RuntimeActors[i])->RegisterIDs();
|
||||
static_cast<PClassActor *>(PClassActor::AllActorClasses[i])->RegisterIDs();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +197,9 @@ PClassActor::PClassActor()
|
|||
ExplosionRadius = -1;
|
||||
MissileHeight = 32*FRACUNIT;
|
||||
MeleeDamage = 0;
|
||||
|
||||
// Record this in the master list.
|
||||
AllActorClasses.Push(this);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -308,7 +313,6 @@ void PClassActor::InitializeNativeDefaults()
|
|||
{
|
||||
memset (Defaults, 0, Size);
|
||||
}
|
||||
m_RuntimeActors.Push(this);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -585,7 +589,7 @@ static int STACK_ARGS sortnums (const void *a, const void *b)
|
|||
|
||||
void FDoomEdMap::DumpMapThings ()
|
||||
{
|
||||
TArray<EdSorting> infos (PClass::m_Types.Size());
|
||||
TArray<EdSorting> infos (PClassActor::AllActorClasses.Size());
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DOOMED_HASHSIZE; ++i)
|
||||
|
|
|
@ -194,6 +194,9 @@ public:
|
|||
FSoundID MeleeSound;
|
||||
FName MissileName;
|
||||
fixed_t MissileHeight;
|
||||
|
||||
// For those times when being able to scan every kind of actor is convenient
|
||||
static TArray<PClassActor *> AllActorClasses;
|
||||
};
|
||||
|
||||
inline PClassActor *PClass::FindActor(FName name)
|
||||
|
|
|
@ -603,7 +603,7 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
{
|
||||
bool giveall;
|
||||
int i;
|
||||
PClass *type;
|
||||
PClassActor *type;
|
||||
|
||||
if (player != &players[consoleplayer])
|
||||
Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name);
|
||||
|
@ -648,7 +648,7 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
if (giveall || stricmp (name, "backpack") == 0)
|
||||
{
|
||||
// Select the correct type of backpack based on the game
|
||||
type = PClass::FindClass(gameinfo.backpacktype);
|
||||
type = PClass::FindActor(gameinfo.backpacktype);
|
||||
if (type != NULL)
|
||||
{
|
||||
GiveSpawner (player, static_cast<PClassInventory *>(type), 1);
|
||||
|
@ -662,9 +662,9 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
{
|
||||
// Find every unique type of ammo. Give it to the player if
|
||||
// he doesn't have it already, and set each to its maximum.
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClassActor *type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->ParentClass == RUNTIME_CLASS(AAmmo))
|
||||
{
|
||||
|
@ -719,14 +719,14 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
|
||||
if (giveall || stricmp (name, "keys") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
||||
if (PClassActor::AllActorClasses[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
||||
{
|
||||
AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
|
||||
AKey *key = (AKey *)GetDefaultByType (PClassActor::AllActorClasses[i]);
|
||||
if (key->KeyNumber != 0)
|
||||
{
|
||||
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClass::m_Types[i]), 0,0,0, NO_REPLACE));
|
||||
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClassActor::AllActorClasses[i]), 0,0,0, NO_REPLACE));
|
||||
if (!key->CallTryPickup (player->mo))
|
||||
{
|
||||
key->Destroy ();
|
||||
|
@ -741,9 +741,9 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
if (giveall || stricmp (name, "weapons") == 0)
|
||||
{
|
||||
AWeapon *savedpending = player->PendingWeapon;
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
// Don't give replaced weapons unless the replacement was done by Dehacked.
|
||||
if (type != RUNTIME_CLASS(AWeapon) &&
|
||||
type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) &&
|
||||
|
@ -772,9 +772,9 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
|
||||
if (giveall || stricmp (name, "artifacts") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
|
||||
{
|
||||
AInventory *def = (AInventory*)GetDefaultByType (type);
|
||||
|
@ -793,9 +793,9 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
|
||||
if (giveall || stricmp (name, "puzzlepieces") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)))
|
||||
{
|
||||
AInventory *def = (AInventory*)GetDefaultByType (type);
|
||||
|
@ -812,7 +812,7 @@ void cht_Give (player_t *player, const char *name, int amount)
|
|||
if (giveall)
|
||||
return;
|
||||
|
||||
type = PClass::FindClass (name);
|
||||
type = PClass::FindActor(name);
|
||||
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
|
@ -872,9 +872,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
if (takeall || stricmp (name, "backpack") == 0)
|
||||
{
|
||||
// Take away all types of backpacks the player might own.
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClass *type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->IsDescendantOf(RUNTIME_CLASS (ABackpackItem)))
|
||||
{
|
||||
|
@ -891,9 +891,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "ammo") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClass *type = PClass::m_Types[i];
|
||||
PClass *type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->ParentClass == RUNTIME_CLASS (AAmmo))
|
||||
{
|
||||
|
@ -910,9 +910,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "armor") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS (AArmor)))
|
||||
{
|
||||
|
@ -929,9 +929,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "keys") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS (AKey)))
|
||||
{
|
||||
|
@ -948,9 +948,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "weapons") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type != RUNTIME_CLASS(AWeapon) &&
|
||||
type->IsDescendantOf (RUNTIME_CLASS (AWeapon)))
|
||||
|
@ -973,9 +973,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "artifacts") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS (AInventory)))
|
||||
{
|
||||
|
@ -999,9 +999,9 @@ void cht_Take (player_t *player, const char *name, int amount)
|
|||
|
||||
if (takeall || stricmp (name, "puzzlepieces") == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
type = PClass::m_Types[i];
|
||||
type = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem)))
|
||||
{
|
||||
|
|
|
@ -5,6 +5,8 @@ xx(Null)
|
|||
xx(Super)
|
||||
xx(Object)
|
||||
xx(Actor)
|
||||
xx(Class)
|
||||
xx(ClassClass)
|
||||
|
||||
xx(Untranslated)
|
||||
|
||||
|
|
|
@ -119,9 +119,9 @@ FArchive &operator<< (FArchive &arc, FState *&state)
|
|||
|
||||
PClassActor *FState::StaticFindStateOwner (const FState *state)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClassActor *info = PClass::m_RuntimeActors[i];
|
||||
PClassActor *info = PClassActor::AllActorClasses[i];
|
||||
if (state >= info->OwnedStates &&
|
||||
state < info->OwnedStates + info->NumOwnedStates)
|
||||
{
|
||||
|
@ -966,9 +966,9 @@ void DumpStateHelper(FStateLabels *StateList, const FString &prefix)
|
|||
|
||||
CCMD(dumpstates)
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
PClassActor *info = PClass::m_RuntimeActors[i];
|
||||
PClassActor *info = PClassActor::AllActorClasses[i];
|
||||
Printf(PRINT_LOG, "State labels for %s\n", info->TypeName.GetChars());
|
||||
DumpStateHelper(info->StateList, "");
|
||||
Printf(PRINT_LOG, "----------------------------\n");
|
||||
|
|
|
@ -810,14 +810,14 @@ void APlayerPawn::CheckWeaponSwitch(const PClass *ammotype)
|
|||
|
||||
void APlayerPawn::GiveDeathmatchInventory()
|
||||
{
|
||||
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
|
||||
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i)
|
||||
{
|
||||
if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
||||
if (PClassActor::AllActorClasses[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
|
||||
{
|
||||
AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
|
||||
AKey *key = (AKey *)GetDefaultByType (PClassActor::AllActorClasses[i]);
|
||||
if (key->KeyNumber != 0)
|
||||
{
|
||||
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClass::m_Types[i]), 0,0,0, NO_REPLACE));
|
||||
key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClassActor::AllActorClasses[i]), 0,0,0, NO_REPLACE));
|
||||
if (!key->CallTryPickup (this))
|
||||
{
|
||||
key->Destroy ();
|
||||
|
|
16
src/tarray.h
16
src/tarray.h
|
@ -119,6 +119,22 @@ public:
|
|||
Most = 0;
|
||||
}
|
||||
}
|
||||
// Check equality of two arrays
|
||||
bool operator==(const TArray<T> &other) const
|
||||
{
|
||||
if (Count != other.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < Count; ++i)
|
||||
{
|
||||
if (Array[i] != other.Array[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Return a reference to an element
|
||||
T &operator[] (size_t index) const
|
||||
{
|
||||
|
|
|
@ -119,6 +119,8 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
|
|||
ti = PClass::FindActor(typeName);
|
||||
if (ti == NULL)
|
||||
{
|
||||
extern void DumpTypeTable();
|
||||
DumpTypeTable();
|
||||
sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars());
|
||||
goto create;
|
||||
}
|
||||
|
@ -319,12 +321,9 @@ static void FinishThingdef()
|
|||
}
|
||||
fclose(dump);
|
||||
|
||||
for (i = 0; i < PClass::m_Types.Size(); i++)
|
||||
for (i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||
{
|
||||
PClass * ti = PClass::m_Types[i];
|
||||
|
||||
// Skip non-actors
|
||||
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
|
||||
PClassActor *ti = PClassActor::AllActorClasses[i];
|
||||
|
||||
if (ti->Size == (unsigned)-1)
|
||||
{
|
||||
|
|
|
@ -2490,7 +2490,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
@ -2595,7 +2595,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
@ -2685,7 +2685,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
@ -3503,7 +3503,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
@ -3763,7 +3763,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
@ -3963,7 +3963,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
|
|||
sym = symfunc;
|
||||
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
|
||||
}
|
||||
assert(sym->SymbolType == SYM_VMFunction);
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != NULL);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
|
|
Loading…
Reference in a new issue