mirror of https://github.com/ZDoom/gzdoom-gles.git
- fixed: It is not guaranteed that the class object that is created by FindClassTentative actually matches the real object that is required later, so it needs to be replaced wherever it could be referenced once the real object is created.
- removed some unneeded code from earlier attempts to fix the class type resolving issue.
This commit is contained in:
parent
ff70cf1ee7
commit
b484cbf18a
|
@ -80,6 +80,7 @@ public:
|
||||||
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
|
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
|
||||||
void SetPainFlash(FName type, PalEntry color);
|
void SetPainFlash(FName type, PalEntry color);
|
||||||
bool GetPainFlash(FName type, PalEntry *color) const;
|
bool GetPainFlash(FName type, PalEntry *color) const;
|
||||||
|
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||||
|
|
||||||
FString DisplayName; // Display name (used in menus, etc.)
|
FString DisplayName; // Display name (used in menus, etc.)
|
||||||
FString SoundClass; // Sound class
|
FString SoundClass; // Sound class
|
||||||
|
|
|
@ -98,6 +98,7 @@ enum
|
||||||
CLASSREG_PClassPlayerPawn,
|
CLASSREG_PClassPlayerPawn,
|
||||||
CLASSREG_PClassType,
|
CLASSREG_PClassType,
|
||||||
CLASSREG_PClassClass,
|
CLASSREG_PClassClass,
|
||||||
|
CLASSREG_PClassWeaponPiece
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClassReg
|
struct ClassReg
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "autosegs.h"
|
#include "autosegs.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "a_pickups.h"
|
#include "a_pickups.h"
|
||||||
|
#include "a_weaponpiece.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "fragglescript/t_fs.h"
|
#include "fragglescript/t_fs.h"
|
||||||
|
|
||||||
|
@ -2163,6 +2164,7 @@ PClass *ClassReg::RegisterClass()
|
||||||
&PClassPlayerPawn::RegistrationInfo,
|
&PClassPlayerPawn::RegistrationInfo,
|
||||||
&PClassType::RegistrationInfo,
|
&PClassType::RegistrationInfo,
|
||||||
&PClassClass::RegistrationInfo,
|
&PClassClass::RegistrationInfo,
|
||||||
|
&PClassWeaponPiece::RegistrationInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip classes that have already been registered
|
// Skip classes that have already been registered
|
||||||
|
@ -2318,34 +2320,29 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
assert (size >= Size);
|
assert (size >= Size);
|
||||||
PClass *type;
|
PClass *type;
|
||||||
bool notnew;
|
bool notnew;
|
||||||
|
size_t bucket;
|
||||||
|
|
||||||
const PClass *existclass = FindClass(name);
|
PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket));
|
||||||
|
|
||||||
// This is a placeholder so fill it in
|
// This is a placeholder so fill it in
|
||||||
if (existclass != NULL && (existclass->Size == TClass_Fatal || existclass->Size == TClass_Nonfatal))
|
if (existclass != NULL && (existclass->Size == TentativeClass))
|
||||||
{
|
{
|
||||||
type = const_cast<PClass*>(existclass);
|
type = const_cast<PClass*>(existclass);
|
||||||
if (!IsDescendantOf(type->ParentClass))
|
if (!IsDescendantOf(type->ParentClass))
|
||||||
{
|
{
|
||||||
if (existclass->Size == TClass_Fatal)
|
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
|
||||||
{
|
|
||||||
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Printf(TEXTCOLOR_RED "%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DPrintf("Defining placeholder class %s\n", name.GetChars());
|
DPrintf("Defining placeholder class %s\n", name.GetChars());
|
||||||
notnew = true;
|
notnew = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new type object of the same type as us. (We may be a derived class of PClass.)
|
|
||||||
type = static_cast<PClass *>(GetClass()->CreateNew());
|
|
||||||
notnew = false;
|
notnew = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new type object of the same type as us. (We may be a derived class of PClass.)
|
||||||
|
type = static_cast<PClass *>(GetClass()->CreateNew());
|
||||||
|
|
||||||
type->TypeName = name;
|
type->TypeName = name;
|
||||||
type->Size = size;
|
type->Size = size;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
|
@ -2354,6 +2351,18 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
{
|
{
|
||||||
type->InsertIntoHash();
|
type->InsertIntoHash();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PClassActor::AllActorClasses.Pop(); // remove the newly added class from the list
|
||||||
|
// todo: replace all affected fields
|
||||||
|
for (unsigned i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||||
|
{
|
||||||
|
PClassActor::AllActorClasses[i]->ReplaceClassRef(existclass, type);
|
||||||
|
if (PClassActor::AllActorClasses[i] == existclass)
|
||||||
|
PClassActor::AllActorClasses[i] = static_cast<PClassActor*>(type);
|
||||||
|
}
|
||||||
|
TypeTable.ReplaceType(type, existclass, bucket);
|
||||||
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2403,11 +2412,11 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
|
||||||
return static_cast<PClass *>(found);
|
return static_cast<PClass *>(found);
|
||||||
}
|
}
|
||||||
PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
|
PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
|
||||||
DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
|
Printf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
|
||||||
|
|
||||||
type->TypeName = name;
|
type->TypeName = name;
|
||||||
type->ParentClass = this;
|
type->ParentClass = this;
|
||||||
type->Size = fatal? TClass_Fatal : TClass_Nonfatal;
|
type->Size = TentativeClass;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
||||||
return type;
|
return type;
|
||||||
|
|
|
@ -601,8 +601,7 @@ public:
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TClass_Fatal = UINT_MAX,
|
TentativeClass = UINT_MAX,
|
||||||
TClass_Nonfatal = UINT_MAX - 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PClassClass;
|
class PClassClass;
|
||||||
|
|
|
@ -39,6 +39,18 @@ void PClassInventory::Derive(PClass *newclass)
|
||||||
newc->PickupMessage = PickupMessage;
|
newc->PickupMessage = PickupMessage;
|
||||||
newc->GiveQuest = GiveQuest;
|
newc->GiveQuest = GiveQuest;
|
||||||
newc->AltHUDIcon = AltHUDIcon;
|
newc->AltHUDIcon = AltHUDIcon;
|
||||||
|
newc->ForbiddenToPlayerClass = ForbiddenToPlayerClass;
|
||||||
|
newc->RestrictedToPlayerClass = RestrictedToPlayerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||||
|
{
|
||||||
|
Super::ReplaceClassRef(oldclass, newclass);
|
||||||
|
AInventory *def = (AInventory*)Defaults;
|
||||||
|
if (def != NULL)
|
||||||
|
{
|
||||||
|
if (def->PickupFlash == oldclass) def->PickupFlash = static_cast<PClassActor *>(newclass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_CLASS(PClassAmmo)
|
IMPLEMENT_CLASS(PClassAmmo)
|
||||||
|
|
|
@ -139,6 +139,7 @@ protected:
|
||||||
virtual void Derive(PClass *newclass);
|
virtual void Derive(PClass *newclass);
|
||||||
public:
|
public:
|
||||||
PClassInventory();
|
PClassInventory();
|
||||||
|
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||||
|
|
||||||
FString PickupMessage;
|
FString PickupMessage;
|
||||||
int GiveQuest; // Optionally give one of the quest items.
|
int GiveQuest; // Optionally give one of the quest items.
|
||||||
|
@ -269,6 +270,7 @@ protected:
|
||||||
virtual void Derive(PClass *newclass);
|
virtual void Derive(PClass *newclass);
|
||||||
public:
|
public:
|
||||||
PClassWeapon();
|
PClassWeapon();
|
||||||
|
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||||
|
|
||||||
int SlotNumber;
|
int SlotNumber;
|
||||||
fixed_t SlotPriority;
|
fixed_t SlotPriority;
|
||||||
|
|
|
@ -3,8 +3,20 @@
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(PClassWeaponPiece)
|
||||||
IMPLEMENT_CLASS (AWeaponHolder)
|
IMPLEMENT_CLASS (AWeaponHolder)
|
||||||
|
|
||||||
|
void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||||
|
{
|
||||||
|
Super::ReplaceClassRef(oldclass, newclass);
|
||||||
|
AWeaponPiece *def = (AWeaponPiece*)Defaults;
|
||||||
|
if (def != NULL)
|
||||||
|
{
|
||||||
|
if (def->WeaponClass == oldclass) def->WeaponClass = static_cast<PClassWeapon *>(newclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AWeaponHolder::Serialize (FArchive &arc)
|
void AWeaponHolder::Serialize (FArchive &arc)
|
||||||
{
|
{
|
||||||
Super::Serialize(arc);
|
Super::Serialize(arc);
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
|
|
||||||
|
// Ammo: Something a weapon needs to operate
|
||||||
|
class PClassWeaponPiece : public PClassInventory
|
||||||
|
{
|
||||||
|
DECLARE_CLASS(PClassWeaponPiece, PClassInventory)
|
||||||
|
protected:
|
||||||
|
public:
|
||||||
|
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||||
|
};
|
||||||
|
|
||||||
class AWeaponPiece : public AInventory
|
class AWeaponPiece : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (AWeaponPiece, AInventory)
|
DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece)
|
||||||
HAS_OBJECT_POINTERS
|
HAS_OBJECT_POINTERS
|
||||||
protected:
|
protected:
|
||||||
bool PrivateShouldStay ();
|
bool PrivateShouldStay ();
|
||||||
|
|
|
@ -54,6 +54,19 @@ void PClassWeapon::Derive(PClass *newclass)
|
||||||
newc->SlotPriority = SlotPriority;
|
newc->SlotPriority = SlotPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||||
|
{
|
||||||
|
Super::ReplaceClassRef(oldclass, newclass);
|
||||||
|
AWeapon *def = (AWeapon*)Defaults;
|
||||||
|
if (def != NULL)
|
||||||
|
{
|
||||||
|
if (def->AmmoType1 == oldclass) def->AmmoType1 = static_cast<PClassAmmo *>(newclass);
|
||||||
|
if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast<PClassAmmo *>(newclass);
|
||||||
|
if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast<PClassWeapon *>(newclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AWeapon :: Serialize
|
// AWeapon :: Serialize
|
||||||
|
|
31
src/info.cpp
31
src/info.cpp
|
@ -522,6 +522,37 @@ void PClassActor::SetPainChance(FName type, int chance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClassActor :: ReplaceClassRef
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++)
|
||||||
|
{
|
||||||
|
if (VisibleToPlayerClass[i] == oldclass)
|
||||||
|
VisibleToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++)
|
||||||
|
{
|
||||||
|
if (ForbiddenToPlayerClass[i] == oldclass)
|
||||||
|
ForbiddenToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++)
|
||||||
|
{
|
||||||
|
if (RestrictedToPlayerClass[i] == oldclass)
|
||||||
|
RestrictedToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
|
||||||
|
}
|
||||||
|
AActor *def = (AActor*)Defaults;
|
||||||
|
if (def != NULL)
|
||||||
|
{
|
||||||
|
if (def->TeleFogSourceType == oldclass) def->TeleFogSourceType = static_cast<PClassActor *>(newclass);
|
||||||
|
if (def->TeleFogDestType == oldclass) def->TeleFogDestType = static_cast<PClassActor *>(newclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// DmgFactors :: CheckFactor
|
// DmgFactors :: CheckFactor
|
||||||
|
|
|
@ -200,6 +200,7 @@ public:
|
||||||
PClassActor();
|
PClassActor();
|
||||||
~PClassActor();
|
~PClassActor();
|
||||||
|
|
||||||
|
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||||
void BuildDefaults();
|
void BuildDefaults();
|
||||||
void ApplyDefaults(BYTE *defaults);
|
void ApplyDefaults(BYTE *defaults);
|
||||||
void RegisterIDs();
|
void RegisterIDs();
|
||||||
|
|
|
@ -581,6 +581,16 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PClassPlayerPawn::ReplaceClassRef(PClass *oldclass, PClass *newclass)
|
||||||
|
{
|
||||||
|
Super::ReplaceClassRef(oldclass, newclass);
|
||||||
|
APlayerPawn *def = (APlayerPawn*)Defaults;
|
||||||
|
if (def != NULL)
|
||||||
|
{
|
||||||
|
if (def->FlechetteType == oldclass) def->FlechetteType = static_cast<PClassInventory *>(newclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// player_t :: SendPitchLimits
|
// player_t :: SendPitchLimits
|
||||||
|
|
|
@ -340,15 +340,10 @@ static void FinishThingdef()
|
||||||
{
|
{
|
||||||
PClassActor *ti = PClassActor::AllActorClasses[i];
|
PClassActor *ti = PClassActor::AllActorClasses[i];
|
||||||
|
|
||||||
if (ti->Size == TClass_Fatal || ti->Size == TClass_Nonfatal)
|
if (ti->Size == TentativeClass)
|
||||||
{
|
{
|
||||||
Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
|
Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
|
||||||
if (ti->Size == TClass_Fatal) errorcount++;
|
errorcount++;
|
||||||
else
|
|
||||||
{
|
|
||||||
// In order to prevent a crash, this class needs to be completed, even though it defines nothing.
|
|
||||||
ti->ParentClass->CreateDerivedClass(ti->TypeName, ti->ParentClass->Size);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue