- 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:
Randy Heit 2010-04-16 02:57:51 +00:00
parent 900324c205
commit ee55e0319f
24 changed files with 1204 additions and 350 deletions

View file

@ -1453,9 +1453,9 @@ static int PatchAmmo (int ammoNum)
// Fix per-ammo/max-ammo amounts for descendants of the base ammo class // Fix per-ammo/max-ammo amounts for descendants of the base ammo class
if (oldclip != *per) 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) if (type == ammoType)
continue; continue;

View file

@ -1754,14 +1754,16 @@ void D_DoomMain (void)
#endif #endif
#endif #endif
PClass::StaticInit();
PType::StaticInit();
// Combine different file parameters with their pre-switch bits. // Combine different file parameters with their pre-switch bits.
Args->CollectFiles("-deh", ".deh"); Args->CollectFiles("-deh", ".deh");
Args->CollectFiles("-bex", ".bex"); Args->CollectFiles("-bex", ".bex");
Args->CollectFiles("-exec", ".cfg"); Args->CollectFiles("-exec", ".cfg");
Args->CollectFiles("-playdemo", ".lmp"); 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); atterm (C_DeinitConsole);
gamestate = GS_STARTUP; gamestate = GS_STARTUP;

View file

@ -353,9 +353,9 @@ void FDecalLib::ReadAllDecals ()
ReadDecals (sc); ReadDecals (sc);
} }
// Supporting code to allow specifying decals directly in the DECORATE lump // 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)); FName v = ENamedName(intptr_t(def->DecalGenerator));
if (v.IsValidName()) if (v.IsValidName())

View file

@ -180,9 +180,9 @@ CCMD (dumpclasses)
shown = omitted = 0; shown = omitted = 0;
DumpInfo::AddType (&tree, root != NULL ? root : RUNTIME_CLASS(DObject)); 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)) if (root == NULL || cls == root || cls->IsDescendantOf(root))
{ {
DumpInfo::AddType (&tree, cls); DumpInfo::AddType (&tree, cls);

View file

@ -94,7 +94,9 @@ enum
CLASSREG_PClassHealth, CLASSREG_PClassHealth,
CLASSREG_PClassPuzzleItem, CLASSREG_PClassPuzzleItem,
CLASSREG_PClassWeapon, CLASSREG_PClassWeapon,
CLASSREG_PClassPlayerPawn CLASSREG_PClassPlayerPawn,
CLASSREG_PClassType,
CLASSREG_PClassClass,
}; };
struct ClassReg struct ClassReg
@ -104,10 +106,11 @@ struct ClassReg
ClassReg *ParentType; ClassReg *ParentType;
const size_t *Pointers; const size_t *Pointers;
void (*ConstructNative)(void *); void (*ConstructNative)(void *);
unsigned int SizeOf:29; unsigned int SizeOf:28;
unsigned int MetaClassNum:3; unsigned int MetaClassNum:4;
PClass *RegisterClass(); PClass *RegisterClass();
void SetupClass(PClass *cls);
}; };
enum EInPlace { EC_InPlace }; enum EInPlace { EC_InPlace };
@ -178,6 +181,10 @@ protected: \
#define IMPLEMENT_ABSTRACT_CLASS(cls) \ #define IMPLEMENT_ABSTRACT_CLASS(cls) \
_IMP_PCLASS(cls,NULL,NULL) _IMP_PCLASS(cls,NULL,NULL)
#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \
_IMP_PCLASS(cls,cls::PointerOffsets,NULL) \
const size_t cls::PointerOffsets[] = {
enum EObjectFlags enum EObjectFlags
{ {
// GC flags // GC flags
@ -292,6 +299,9 @@ namespace GC
// is NULLed instead. // is NULLed instead.
void Mark(DObject **obj); void Mark(DObject **obj);
// Marks an array of objects.
void MarkArray(DObject **objs, size_t count);
// Soft-roots an object. // Soft-roots an object.
void AddSoftRoot(DObject *obj); void AddSoftRoot(DObject *obj);
@ -310,6 +320,15 @@ namespace GC
obj = t; obj = t;
} }
template<class T> void Mark(TObjPtr<T> &obj); 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 // A template class to help with handling read barriers. It does not

View file

@ -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 // MarkRoot
@ -341,9 +357,9 @@ static void MarkRoot()
} }
} }
// Mark classes // 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 bot stuff.
Mark(bglobal.firstthing); Mark(bglobal.firstthing);

File diff suppressed because it is too large Load diff

View file

@ -140,28 +140,274 @@ private:
friend class DObject; 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 --------------------------- // 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; HAS_OBJECT_POINTERS;
protected: protected:
virtual void Derive(PClass *newclass); virtual void Derive(PClass *newclass);
// We unravel _WITH_META here just as we did for PType.
enum { MetaClassNum = CLASSREG_PClassClass };
public: public:
static void StaticInit (); typedef PClassClass MetaClass;
static void StaticShutdown (); MetaClass *GetClass() const;
static void StaticInit();
static void StaticShutdown();
static void StaticBootstrap();
// Per-class information ------------------------------------- // Per-class information -------------------------------------
FName TypeName; // this class's name
unsigned int Size; // this class's size
PClass *ParentClass; // the class this class derives from PClass *ParentClass; // the class this class derives from
const size_t *Pointers; // object pointers defined by this class *only* 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 const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
PClass *HashNext;
BYTE *Defaults; BYTE *Defaults;
bool bRuntimeClass; // class was defined at run-time, not compile-time bool bRuntimeClass; // class was defined at run-time, not compile-time
unsigned short ClassIndex;
PSymbolTable Symbols; PSymbolTable Symbols;
void (*ConstructNative)(void *); void (*ConstructNative)(void *);
@ -169,17 +415,17 @@ public:
// The rest are all functions and static data ---------------- // The rest are all functions and static data ----------------
PClass(); PClass();
~PClass(); ~PClass();
void InsertIntoHash (); void InsertIntoHash();
DObject *CreateNew () const; DObject *CreateNew() const;
PClass *CreateDerivedClass (FName name, unsigned int size); PClass *CreateDerivedClass(FName name, unsigned int size);
unsigned int Extend(unsigned int extension); unsigned int Extend(unsigned int extension);
void InitializeActorInfo (); void InitializeActorInfo();
void BuildFlatPointers (); void BuildFlatPointers();
const PClass *NativeClass() const; const PClass *NativeClass() const;
size_t PropagateMark(); size_t PropagateMark();
// Returns true if this type is an ancestor of (or same as) the passed type. // 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) while (ti)
{ {
@ -189,29 +435,70 @@ public:
} }
return false; 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. // Find a type, given its name.
static PClass *FindClass (const char *name) { return FindClass (FName (name, true)); } 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(const FString &name) { return FindClass(FName(name, true)); }
static PClass *FindClass (ENamedName name) { return FindClass (FName (name)); } static PClass *FindClass(ENamedName name) { return FindClass(FName(name)); }
static PClass *FindClass (FName name); static PClass *FindClass(FName name);
static PClassActor *FindActor (const char *name) { return FindActor (FName (name, true)); } 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(const FString &name) { return FindActor(FName(name, true)); }
static PClassActor *FindActor (ENamedName name) { return FindActor (FName (name)); } static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); }
static PClassActor *FindActor (FName name); static PClassActor *FindActor(FName name);
PClass *FindClassTentative (FName name); // not static! PClass *FindClassTentative(FName name); // not static!
static TArray<PClass *> m_Types; static TArray<PClass *> AllClasses;
static TArray<PClassActor *> m_RuntimeActors;
enum { HASH_SIZE = 256 };
static PClass *TypeHash[HASH_SIZE];
static bool bShutdown; 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 #endif

View file

@ -637,12 +637,8 @@ FArchive::FArchive (FFile &file)
void FArchive::AttachToFile (FFile &file) void FArchive::AttachToFile (FFile &file)
{ {
unsigned int i;
m_HubTravel = false; m_HubTravel = false;
m_File = &file; m_File = &file;
m_MaxObjectCount = m_ObjectCount = 0;
m_ObjectMap = NULL;
if (file.Mode() == FFile::EReading) if (file.Mode() == FFile::EReading)
{ {
m_Loading = true; m_Loading = true;
@ -654,19 +650,13 @@ void FArchive::AttachToFile (FFile &file)
m_Storing = true; m_Storing = true;
} }
m_Persistent = file.IsPersistent(); m_Persistent = file.IsPersistent();
m_TypeMap = NULL;
m_TypeMap = new TypeMap[PClass::m_Types.Size()]; ClassToArchive.Clear();
for (i = 0; i < PClass::m_Types.Size(); i++) ArchiveToClass.Clear();
{
m_TypeMap[i].toArchive = TypeMap::NO_INDEX; ObjectToArchive.Clear();
m_TypeMap[i].toCurrent = NULL; ArchiveToObject.Clear();
}
m_ClassCount = 0;
for (i = 0; i < EObjectHashSize; i++)
{
m_ObjectHash[i] = ~0;
m_NameHash[i] = NameMap::NO_INDEX;
}
m_NumSprites = 0; m_NumSprites = 0;
m_SpriteMap = new int[sprites.Size()]; m_SpriteMap = new int[sprites.Size()];
for (size_t s = 0; s < sprites.Size(); ++s) for (size_t s = 0; s < sprites.Size(); ++s)
@ -678,10 +668,6 @@ void FArchive::AttachToFile (FFile &file)
FArchive::~FArchive () FArchive::~FArchive ()
{ {
Close (); Close ();
if (m_TypeMap)
delete[] m_TypeMap;
if (m_ObjectMap)
M_Free (m_ObjectMap);
if (m_SpriteMap) if (m_SpriteMap)
delete[] m_SpriteMap; delete[] m_SpriteMap;
} }
@ -702,7 +688,7 @@ void FArchive::Close ()
{ {
m_File->Close (); m_File->Close ();
m_File = NULL; 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 else
{ {
PClass *type = obj->GetClass(); PClass *type = obj->GetClass();
DWORD *classarcid;
if (type == RUNTIME_CLASS(DObject)) if (type == RUNTIME_CLASS(DObject))
{ {
@ -1052,7 +1039,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
id[0] = NULL_OBJ; id[0] = NULL_OBJ;
Write (id, 1); 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. // No instances of this class have been written out yet.
// Write out the class, then write out the object. If this // 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 // to the saved object. Otherwise, save a reference to the
// class, then save the object. Again, if this is a player- // class, then save the object. Again, if this is a player-
// controlled actor, remember that. // 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)) && if (obj->IsKindOf (RUNTIME_CLASS (AActor)) &&
@ -1103,7 +1090,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
id[0] = NEW_OBJ; id[0] = NEW_OBJ;
Write (id, 1); Write (id, 1);
} }
WriteCount (m_TypeMap[type->ClassIndex].toArchive); WriteCount (*classarcid);
// Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell()); // Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell());
MapObject (obj); MapObject (obj);
obj->SerializeUserVars (*this); obj->SerializeUserVars (*this);
@ -1114,7 +1101,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
{ {
id[0] = OLD_OBJ; id[0] = OLD_OBJ;
Write (id, 1); Write (id, 1);
WriteCount (index); WriteCount (*objarcid);
} }
} }
} }
@ -1141,12 +1128,12 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
break; break;
case OLD_OBJ: case OLD_OBJ:
index = ReadCount (); index = ReadCount();
if (index >= m_ObjectCount) 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; break;
case NEW_PLYR_CLS_OBJ: case NEW_PLYR_CLS_OBJ:
@ -1363,19 +1350,14 @@ DWORD FArchive::FindName (const char *name, unsigned int bucket) const
DWORD FArchive::WriteClass (PClass *info) DWORD FArchive::WriteClass (PClass *info)
{ {
if (m_ClassCount >= PClass::m_Types.Size()) if (ClassToArchive.CheckKey(info) != NULL)
{
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)
{ {
I_Error ("Attempt to write '%s' twice.\n", info->TypeName.GetChars()); I_Error ("Attempt to write '%s' twice.\n", info->TypeName.GetChars());
} }
m_TypeMap[info->ClassIndex].toArchive = m_ClassCount; DWORD index = ArchiveToClass.Push(info);
m_TypeMap[m_ClassCount].toCurrent = info; ClassToArchive[info] = index;
WriteString (info->TypeName.GetChars()); WriteString (info->TypeName.GetChars());
return m_ClassCount++; return index;
} }
PClass *FArchive::ReadClass () PClass *FArchive::ReadClass ()
@ -1386,24 +1368,15 @@ PClass *FArchive::ReadClass ()
char *val; char *val;
} typeName; } 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); operator<< (typeName.val);
FName zaname(typeName.val, true); FName zaname(typeName.val, true);
if (zaname != NAME_None) 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) ClassToArchive[type] = ArchiveToClass.Push(type);
{ return type;
m_TypeMap[i].toArchive = m_ClassCount;
m_TypeMap[m_ClassCount].toCurrent = PClass::m_Types[i];
m_ClassCount++;
return PClass::m_Types[i];
}
} }
} }
I_Error ("Unknown class '%s'\n", typeName.val); I_Error ("Unknown class '%s'\n", typeName.val);
@ -1425,11 +1398,7 @@ PClass *FArchive::ReadClass (const PClass *wanttype)
PClass *FArchive::ReadStoredClass (const PClass *wanttype) PClass *FArchive::ReadStoredClass (const PClass *wanttype)
{ {
DWORD index = ReadCount (); DWORD index = ReadCount ();
if (index >= m_ClassCount) PClass *type = ArchiveToClass[index];
{
I_Error ("Class reference too high (%u; max is %u)\n", index, m_ClassCount);
}
PClass *type = m_TypeMap[index].toCurrent;
if (!type->IsDescendantOf (wanttype)) if (!type->IsDescendantOf (wanttype))
{ {
I_Error ("Expected to extract an object of type '%s'.\n" I_Error ("Expected to extract an object of type '%s'.\n"
@ -1439,44 +1408,11 @@ PClass *FArchive::ReadStoredClass (const PClass *wanttype)
return type; return type;
} }
DWORD FArchive::MapObject (const DObject *obj) DWORD FArchive::MapObject (DObject *obj)
{ {
DWORD i; DWORD i = ArchiveToObject.Push(obj);
ObjectToArchive[obj] = i;
if (m_ObjectCount >= m_MaxObjectCount) return i;
{
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;
} }
void FArchive::UserWriteClass (PClass *type) void FArchive::UserWriteClass (PClass *type)
@ -1490,7 +1426,8 @@ void FArchive::UserWriteClass (PClass *type)
} }
else else
{ {
if (m_TypeMap[type->ClassIndex].toArchive == TypeMap::NO_INDEX) DWORD *arcid;
if (NULL == (arcid = ClassToArchive.CheckKey(type)))
{ {
id = 1; id = 1;
Write (&id, 1); Write (&id, 1);
@ -1500,7 +1437,7 @@ void FArchive::UserWriteClass (PClass *type)
{ {
id = 0; id = 0;
Write (&id, 1); Write (&id, 1);
WriteCount (m_TypeMap[type->ClassIndex].toArchive); WriteCount (*arcid);
} }
} }
} }

View file

@ -209,13 +209,11 @@ inline FArchive& operator<< (DObject* &object) { return ReadObject (object, RUN
protected: protected:
enum { EObjectHashSize = 137 }; enum { EObjectHashSize = 137 };
DWORD FindObjectIndex (const DObject *obj) const; DWORD MapObject (DObject *obj);
DWORD MapObject (const DObject *obj);
DWORD WriteClass (PClass *info); DWORD WriteClass (PClass *info);
PClass *ReadClass (); PClass *ReadClass ();
PClass *ReadClass (const PClass *wanttype); PClass *ReadClass (const PClass *wanttype);
PClass *ReadStoredClass (const PClass *wanttype); PClass *ReadStoredClass (const PClass *wanttype);
DWORD HashObject (const DObject *obj) const;
DWORD AddName (const char *name); DWORD AddName (const char *name);
DWORD AddName (unsigned int start); // Name has already been added to storage DWORD AddName (unsigned int start); // Name has already been added to storage
DWORD FindName (const char *name) const; DWORD FindName (const char *name) const;
@ -226,24 +224,12 @@ protected:
bool m_Storing; // inserting objects? bool m_Storing; // inserting objects?
bool m_HubTravel; // travelling inside a hub? bool m_HubTravel; // travelling inside a hub?
FFile *m_File; // unerlying file object 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 TMap<PClass *, DWORD> ClassToArchive; // Maps PClass to archive type index
{ TArray<PClass *> ArchiveToClass; // Maps archive type index to PClass
PClass *toCurrent; // maps archive type index to execution type index
DWORD toArchive; // maps execution type index to archive type index
enum { NO_INDEX = 0xffffffff }; TMap<DObject *, DWORD> ObjectToArchive; // Maps objects to archive index
} *m_TypeMap; TArray<DObject *> ArchiveToObject; // Maps archive index to objects
struct ObjectMap
{
const DObject *object;
DWORD hashNext;
} *m_ObjectMap;
DWORD m_ObjectHash[EObjectHashSize];
struct NameMap struct NameMap
{ {

View file

@ -309,27 +309,27 @@ static void ParseLock(FScanner &sc)
static void ClearLocks() static void ClearLocks()
{ {
unsigned int i; 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) if (key != NULL)
{ {
key->KeyNumber = 0; 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]; delete locks[i];
locks[i]=NULL; locks[i] = NULL;
} }
} }
currentnumber=0; currentnumber = 0;
keysdone=false; keysdone = false;
} }
//=========================================================================== //===========================================================================

View file

@ -1643,9 +1643,9 @@ AInventory *ABackpackItem::CreateCopy (AActor *other)
{ {
// Find every unique type of ammo. Give it to the player if // Find every unique type of ammo. Give it to the player if
// he doesn't have it already, and double its maximum capacity. // 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)) if (type->ParentClass == RUNTIME_CLASS(AAmmo))
{ {

View file

@ -1119,9 +1119,9 @@ void FWeaponSlots::AddExtraWeapons()
} }
// Append extra weapons to the slots. // 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))) if (!cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{ {
@ -1569,9 +1569,9 @@ void P_SetupWeapons_ntohton()
cls = NULL; cls = NULL;
Weapons_ntoh.Push(cls); // Index 0 is always 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))) if (cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{ {

View file

@ -2161,7 +2161,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
if(statusBar->CPlayer->cls == NULL) if(statusBar->CPlayer->cls == NULL)
return; //No class so we can not continue 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++) for(unsigned int i = 0;i < classes.Size();i++)
{ {
if(classes[i] == spawnClass) if(classes[i] == spawnClass)
@ -2179,7 +2179,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
if(stricmp(sc.String, PlayerClasses[c].Type->DisplayName) == 0) if(stricmp(sc.String, PlayerClasses[c].Type->DisplayName) == 0)
{ {
foundClass = true; foundClass = true;
classes.Push(PlayerClasses[c].Type->ClassIndex); classes.Push(PlayerClasses[c].Type);
break; break;
} }
} }
@ -2192,7 +2192,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
} }
protected: protected:
TArray<int> classes; TArray<PClass*> classes;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -327,9 +327,9 @@ static int STACK_ARGS ktcmp(const void * a, const void * b)
static void SetKeyTypes() 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))) if (ti->IsDescendantOf(RUNTIME_CLASS(AKey)))
{ {

View file

@ -53,6 +53,8 @@
extern void LoadActors (); extern void LoadActors ();
TArray<PClassActor *> PClassActor::AllActorClasses;
bool FState::CallAction(AActor *self, AActor *stateowner, StateCallData *statecall) bool FState::CallAction(AActor *self, AActor *stateowner, StateCallData *statecall)
{ {
if (ActionFunc != NULL) if (ActionFunc != NULL)
@ -151,9 +153,9 @@ void PClassActor::StaticSetActorNums()
memset(SpawnableThings, 0, sizeof(SpawnableThings)); memset(SpawnableThings, 0, sizeof(SpawnableThings));
DoomEdMap.Empty(); 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; ExplosionRadius = -1;
MissileHeight = 32*FRACUNIT; MissileHeight = 32*FRACUNIT;
MeleeDamage = 0; MeleeDamage = 0;
// Record this in the master list.
AllActorClasses.Push(this);
} }
//========================================================================== //==========================================================================
@ -308,7 +313,6 @@ void PClassActor::InitializeNativeDefaults()
{ {
memset (Defaults, 0, Size); 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 () void FDoomEdMap::DumpMapThings ()
{ {
TArray<EdSorting> infos (PClass::m_Types.Size()); TArray<EdSorting> infos (PClassActor::AllActorClasses.Size());
int i; int i;
for (i = 0; i < DOOMED_HASHSIZE; ++i) for (i = 0; i < DOOMED_HASHSIZE; ++i)

View file

@ -194,6 +194,9 @@ public:
FSoundID MeleeSound; FSoundID MeleeSound;
FName MissileName; FName MissileName;
fixed_t MissileHeight; 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) inline PClassActor *PClass::FindActor(FName name)

View file

@ -603,7 +603,7 @@ void cht_Give (player_t *player, const char *name, int amount)
{ {
bool giveall; bool giveall;
int i; int i;
PClass *type; PClassActor *type;
if (player != &players[consoleplayer]) if (player != &players[consoleplayer])
Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name); 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) if (giveall || stricmp (name, "backpack") == 0)
{ {
// Select the correct type of backpack based on the game // Select the correct type of backpack based on the game
type = PClass::FindClass(gameinfo.backpacktype); type = PClass::FindActor(gameinfo.backpacktype);
if (type != NULL) if (type != NULL)
{ {
GiveSpawner (player, static_cast<PClassInventory *>(type), 1); 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 // Find every unique type of ammo. Give it to the player if
// he doesn't have it already, and set each to its maximum. // 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)) 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) 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) 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)) if (!key->CallTryPickup (player->mo))
{ {
key->Destroy (); key->Destroy ();
@ -741,9 +741,9 @@ void cht_Give (player_t *player, const char *name, int amount)
if (giveall || stricmp (name, "weapons") == 0) if (giveall || stricmp (name, "weapons") == 0)
{ {
AWeapon *savedpending = player->PendingWeapon; 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. // Don't give replaced weapons unless the replacement was done by Dehacked.
if (type != RUNTIME_CLASS(AWeapon) && if (type != RUNTIME_CLASS(AWeapon) &&
type->IsDescendantOf (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) 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))) if (type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
{ {
AInventory *def = (AInventory*)GetDefaultByType (type); 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) 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))) if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)))
{ {
AInventory *def = (AInventory*)GetDefaultByType (type); AInventory *def = (AInventory*)GetDefaultByType (type);
@ -812,7 +812,7 @@ void cht_Give (player_t *player, const char *name, int amount)
if (giveall) if (giveall)
return; return;
type = PClass::FindClass (name); type = PClass::FindActor(name);
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory))) if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
{ {
if (player == &players[consoleplayer]) 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) if (takeall || stricmp (name, "backpack") == 0)
{ {
// Take away all types of backpacks the player might own. // 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))) 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) 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)) 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) 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))) 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) 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))) 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) 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) && if (type != RUNTIME_CLASS(AWeapon) &&
type->IsDescendantOf (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) 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))) 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) 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))) if (type->IsDescendantOf (RUNTIME_CLASS (APuzzleItem)))
{ {

View file

@ -5,6 +5,8 @@ xx(Null)
xx(Super) xx(Super)
xx(Object) xx(Object)
xx(Actor) xx(Actor)
xx(Class)
xx(ClassClass)
xx(Untranslated) xx(Untranslated)

View file

@ -119,9 +119,9 @@ FArchive &operator<< (FArchive &arc, FState *&state)
PClassActor *FState::StaticFindStateOwner (const 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 && if (state >= info->OwnedStates &&
state < info->OwnedStates + info->NumOwnedStates) state < info->OwnedStates + info->NumOwnedStates)
{ {
@ -966,9 +966,9 @@ void DumpStateHelper(FStateLabels *StateList, const FString &prefix)
CCMD(dumpstates) 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()); Printf(PRINT_LOG, "State labels for %s\n", info->TypeName.GetChars());
DumpStateHelper(info->StateList, ""); DumpStateHelper(info->StateList, "");
Printf(PRINT_LOG, "----------------------------\n"); Printf(PRINT_LOG, "----------------------------\n");

View file

@ -810,14 +810,14 @@ void APlayerPawn::CheckWeaponSwitch(const PClass *ammotype)
void APlayerPawn::GiveDeathmatchInventory() 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) 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)) if (!key->CallTryPickup (this))
{ {
key->Destroy (); key->Destroy ();

View file

@ -119,6 +119,22 @@ public:
Most = 0; 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 // Return a reference to an element
T &operator[] (size_t index) const T &operator[] (size_t index) const
{ {

View file

@ -119,6 +119,8 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
ti = PClass::FindActor(typeName); ti = PClass::FindActor(typeName);
if (ti == NULL) if (ti == NULL)
{ {
extern void DumpTypeTable();
DumpTypeTable();
sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars()); sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars());
goto create; goto create;
} }
@ -319,12 +321,9 @@ static void FinishThingdef()
} }
fclose(dump); 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]; PClassActor *ti = PClassActor::AllActorClasses[i];
// Skip non-actors
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
if (ti->Size == (unsigned)-1) if (ti->Size == (unsigned)-1)
{ {

View file

@ -2490,7 +2490,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -2595,7 +2595,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -2685,7 +2685,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3503,7 +3503,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3763,7 +3763,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
@ -3963,7 +3963,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
sym = symfunc; sym = symfunc;
RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym); RUNTIME_CLASS(AActor)->Symbols.AddSymbol(sym);
} }
assert(sym->SymbolType == SYM_VMFunction); assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != NULL); assert(((PSymbolVMFunction *)sym)->Function != NULL);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;