mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- 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
13 changed files with 119 additions and 24 deletions
|
@ -80,6 +80,7 @@ public:
|
|||
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
|
||||
void SetPainFlash(FName type, PalEntry color);
|
||||
bool GetPainFlash(FName type, PalEntry *color) const;
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
|
||||
FString DisplayName; // Display name (used in menus, etc.)
|
||||
FString SoundClass; // Sound class
|
||||
|
|
|
@ -98,6 +98,7 @@ enum
|
|||
CLASSREG_PClassPlayerPawn,
|
||||
CLASSREG_PClassType,
|
||||
CLASSREG_PClassClass,
|
||||
CLASSREG_PClassWeaponPiece
|
||||
};
|
||||
|
||||
struct ClassReg
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "autosegs.h"
|
||||
#include "v_text.h"
|
||||
#include "a_pickups.h"
|
||||
#include "a_weaponpiece.h"
|
||||
#include "d_player.h"
|
||||
#include "fragglescript/t_fs.h"
|
||||
|
||||
|
@ -2163,6 +2164,7 @@ PClass *ClassReg::RegisterClass()
|
|||
&PClassPlayerPawn::RegistrationInfo,
|
||||
&PClassType::RegistrationInfo,
|
||||
&PClassClass::RegistrationInfo,
|
||||
&PClassWeaponPiece::RegistrationInfo,
|
||||
};
|
||||
|
||||
// Skip classes that have already been registered
|
||||
|
@ -2318,34 +2320,29 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
|||
assert (size >= Size);
|
||||
PClass *type;
|
||||
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
|
||||
if (existclass != NULL && (existclass->Size == TClass_Fatal || existclass->Size == TClass_Nonfatal))
|
||||
if (existclass != NULL && (existclass->Size == TentativeClass))
|
||||
{
|
||||
type = const_cast<PClass*>(existclass);
|
||||
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());
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "%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());
|
||||
}
|
||||
DPrintf("Defining placeholder class %s\n", name.GetChars());
|
||||
notnew = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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->Size = size;
|
||||
type->bRuntimeClass = true;
|
||||
|
@ -2354,6 +2351,18 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2403,11 +2412,11 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
|
|||
return static_cast<PClass *>(found);
|
||||
}
|
||||
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->ParentClass = this;
|
||||
type->Size = fatal? TClass_Fatal : TClass_Nonfatal;
|
||||
type->Size = TentativeClass;
|
||||
type->bRuntimeClass = true;
|
||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
||||
return type;
|
||||
|
|
|
@ -601,8 +601,7 @@ public:
|
|||
|
||||
enum
|
||||
{
|
||||
TClass_Fatal = UINT_MAX,
|
||||
TClass_Nonfatal = UINT_MAX - 1
|
||||
TentativeClass = UINT_MAX,
|
||||
};
|
||||
|
||||
class PClassClass;
|
||||
|
|
|
@ -39,6 +39,18 @@ void PClassInventory::Derive(PClass *newclass)
|
|||
newc->PickupMessage = PickupMessage;
|
||||
newc->GiveQuest = GiveQuest;
|
||||
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)
|
||||
|
|
|
@ -139,6 +139,7 @@ protected:
|
|||
virtual void Derive(PClass *newclass);
|
||||
public:
|
||||
PClassInventory();
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
|
||||
FString PickupMessage;
|
||||
int GiveQuest; // Optionally give one of the quest items.
|
||||
|
@ -269,6 +270,7 @@ protected:
|
|||
virtual void Derive(PClass *newclass);
|
||||
public:
|
||||
PClassWeapon();
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
|
||||
int SlotNumber;
|
||||
fixed_t SlotPriority;
|
||||
|
|
|
@ -3,8 +3,20 @@
|
|||
#include "doomstat.h"
|
||||
#include "farchive.h"
|
||||
|
||||
IMPLEMENT_CLASS(PClassWeaponPiece)
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
DECLARE_CLASS (AWeaponPiece, AInventory)
|
||||
DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece)
|
||||
HAS_OBJECT_POINTERS
|
||||
protected:
|
||||
bool PrivateShouldStay ();
|
||||
|
|
|
@ -54,6 +54,19 @@ void PClassWeapon::Derive(PClass *newclass)
|
|||
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
|
||||
|
|
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
|
||||
|
|
|
@ -200,6 +200,7 @@ public:
|
|||
PClassActor();
|
||||
~PClassActor();
|
||||
|
||||
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
|
||||
void BuildDefaults();
|
||||
void ApplyDefaults(BYTE *defaults);
|
||||
void RegisterIDs();
|
||||
|
|
|
@ -581,6 +581,16 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const
|
|||
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
|
||||
|
|
|
@ -340,15 +340,10 @@ static void FinishThingdef()
|
|||
{
|
||||
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());
|
||||
if (ti->Size == TClass_Fatal) 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);
|
||||
}
|
||||
errorcount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue