From 3131c08640c4e9831cdd9f190bb9b4099ed22b4e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 31 Jan 2017 13:41:23 +0100 Subject: [PATCH] - fixed: the restart CCMD must clear out all statically stored pointers to VM functions because they do not survive the shutdown that is needed before loading new data. --- src/dobjtype.cpp | 17 +++++++++++++++++ src/dobjtype.h | 2 ++ src/g_inventory/a_pickups.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 4 ++-- src/m_cheat.cpp | 2 +- src/p_acs.cpp | 4 ++-- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 313ee7389c..7468b6dabb 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -69,6 +69,7 @@ FNamespaceManager Namespaces; FTypeTable TypeTable; TArray PClass::AllClasses; +TArray PClass::FunctionPtrList; bool PClass::bShutdown; bool PClass::bVMOperational; @@ -2840,6 +2841,12 @@ void PClass::StaticShutdown () TArray uniqueFPs(64); unsigned int i, j; + // delete all variables containing pointers to script functions. + for (auto p : FunctionPtrList) + { + *p = nullptr; + } + FunctionPtrList.Clear(); // Make a full garbage collection here so that all destroyed but uncollected higher level objects that still exist can be properly taken down. GC::FullGC(); @@ -3547,6 +3554,16 @@ VMFunction *PClass::FindFunction(FName clsname, FName funcname) return func->Variants[0].Implementation; } +void PClass::FindFunction(VMFunction **pptr, FName clsname, FName funcname) +{ + auto cls = PClass::FindActor(clsname); + if (!cls) return; + auto func = dyn_cast(cls->Symbols.FindSymbol(funcname, true)); + if (!func) return; + *pptr = func->Variants[0].Implementation; + FunctionPtrList.Push(pptr); +} + /* FTypeTable **************************************************************/ diff --git a/src/dobjtype.h b/src/dobjtype.h index 632ef96bbd..2726ebff11 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -848,9 +848,11 @@ public: static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(FName name); static VMFunction *FindFunction(FName cls, FName func); + static void FindFunction(VMFunction **pptr, FName cls, FName func); PClass *FindClassTentative(FName name); static TArray AllClasses; + static TArray FunctionPtrList; static bool bShutdown; static bool bVMOperational; diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index cd4d02f04a..fc35d2da4a 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -522,7 +522,7 @@ DEFINE_ACTION_FUNCTION(AInventory, DoRespawn) bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return) { static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_Inventory, NAME_CallTryPickup); + if (func == nullptr) PClass::FindFunction(&func, NAME_Inventory, NAME_CallTryPickup); VMValue params[2] = { (DObject*)this, toucher }; VMReturn ret[2]; int res; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 5e12bf9d05..c3950571f1 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -1437,7 +1437,7 @@ class CommandDrawNumber : public CommandDrawString { // num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1; static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); + if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, inventoryItem }; int retv; VMReturn ret(&retv); @@ -2830,7 +2830,7 @@ class CommandDrawBar : public SBarInfoCommand // [value, max] = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem); // value++; max++; static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); + if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem }; VMReturn ret[2]; int ival; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 2f99ea61c1..23c2f1ded7 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -478,7 +478,7 @@ void cht_DoCheat (player_t *player, int cheat) if (player->mo != NULL && player->health >= 0) { static VMFunction *gsp = nullptr; - if (gsp == nullptr) gsp = PClass::FindFunction(NAME_Sigil, NAME_GiveSigilPiece); + if (gsp == nullptr) PClass::FindFunction(&gsp, NAME_Sigil, NAME_GiveSigilPiece); if (gsp) { VMValue params[1] = { player->mo }; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 24142e0ec5..e346579c4c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6203,7 +6203,7 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int & static void SetMarineWeapon(AActor *marine, int weapon) { static VMFunction *smw = nullptr; - if (smw == nullptr) smw = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetWeapon); + if (smw == nullptr) PClass::FindFunction(&smw, NAME_ScriptedMarine, NAME_SetWeapon); if (smw) { VMValue params[2] = { marine, weapon }; @@ -6214,7 +6214,7 @@ static void SetMarineWeapon(AActor *marine, int weapon) static void SetMarineSprite(AActor *marine, PClassActor *source) { static VMFunction *sms = nullptr; - if (sms == nullptr) sms = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetSprite); + if (sms == nullptr) PClass::FindFunction(&sms, NAME_ScriptedMarine, NAME_SetSprite); if (sms) { VMValue params[2] = { marine, source };