- disabled the scripted virtual function module after finding out that it only works if each single class that may serve as a parent for scripting is explicitly declared.

Needless to say, this is simply too volatile and would require constant active maintenance, not to mention a huge amount of work up front to get going.
It also hid a nasty problem with the Destroy method. Due to the way the garbage collector works, Destroy cannot be exposed to scripts as-is. It may be called from scripts but it may not be overridden from scripts because the garbage collector can call this function after all data needed for calling a scripted override has already been destroyed because if that data is also being collected there is no guarantee that proper order of destruction is observed. So for now Destroy is just a normal native method to scripted classes
This commit is contained in:
Christoph Oelckers 2016-11-24 21:36:02 +01:00
commit 66d28a24b8
149 changed files with 727 additions and 759 deletions

View file

@ -48,7 +48,7 @@ extern cycle_t BotSupportCycles;
extern cycle_t ActionCycles;
extern int BotWTG;
IMPLEMENT_CLASS(DThinker, false, false, false, true)
IMPLEMENT_CLASS(DThinker, false, false)
DThinker *NextToThink;
@ -56,6 +56,12 @@ FThinkerList DThinker::Thinkers[MAX_STATNUM+2];
FThinkerList DThinker::FreshThinkers[MAX_STATNUM+1];
bool DThinker::bSerialOverride = false;
//==========================================================================
//
//
//
//==========================================================================
void FThinkerList::AddTail(DThinker *thinker)
{
assert(thinker->PrevThinker == NULL && thinker->NextThinker == NULL);
@ -80,6 +86,12 @@ void FThinkerList::AddTail(DThinker *thinker)
GC::WriteBarrier(Sentinel, thinker);
}
//==========================================================================
//
//
//
//==========================================================================
DThinker *FThinkerList::GetHead() const
{
if (Sentinel == NULL || Sentinel->NextThinker == Sentinel)
@ -90,6 +102,12 @@ DThinker *FThinkerList::GetHead() const
return Sentinel->NextThinker;
}
//==========================================================================
//
//
//
//==========================================================================
DThinker *FThinkerList::GetTail() const
{
if (Sentinel == NULL || Sentinel->PrevThinker == Sentinel)
@ -99,11 +117,23 @@ DThinker *FThinkerList::GetTail() const
return Sentinel->PrevThinker;
}
//==========================================================================
//
//
//
//==========================================================================
bool FThinkerList::IsEmpty() const
{
return Sentinel == NULL || Sentinel->NextThinker == NULL;
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::SaveList(FSerializer &arc, DThinker *node)
{
if (node != NULL)
@ -234,6 +264,12 @@ void DThinker::Destroy ()
Super::Destroy();
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::Remove()
{
if (this == NextToThink)
@ -254,6 +290,12 @@ void DThinker::Remove()
PrevThinker = NULL;
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::PostBeginPlay ()
{
}
@ -261,15 +303,41 @@ void DThinker::PostBeginPlay ()
DEFINE_ACTION_FUNCTION(DThinker, PostBeginPlay)
{
PARAM_SELF_PROLOGUE(DThinker);
self->VMSuperCall();
self->PostBeginPlay();
return 0;
}
void DThinker::CallPostBeginPlay()
{
IFVIRTUAL(DThinker, PostBeginPlay)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
stack.Call(func, params, 1, nullptr, 0, nullptr);
}
else
{
PostBeginPlay();
}
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::PostSerialize()
{
}
//==========================================================================
//
//
//
//==========================================================================
DThinker *DThinker::FirstThinker (int statnum)
{
DThinker *node;
@ -290,6 +358,12 @@ DThinker *DThinker::FirstThinker (int statnum)
return node;
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::ChangeStatNum (int statnum)
{
FThinkerList *list;
@ -313,7 +387,12 @@ void DThinker::ChangeStatNum (int statnum)
list->AddTail(this);
}
//==========================================================================
//
// Mark the first thinker of each list
//
//==========================================================================
void DThinker::MarkRoots()
{
for (int i = 0; i <= MAX_STATNUM; ++i)
@ -324,7 +403,12 @@ void DThinker::MarkRoots()
GC::Mark(Thinkers[MAX_STATNUM+1].Sentinel);
}
//==========================================================================
//
// Destroy every thinker
//
//==========================================================================
void DThinker::DestroyAllThinkers ()
{
int i;
@ -341,6 +425,12 @@ void DThinker::DestroyAllThinkers ()
GC::FullGC();
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::DestroyThinkersInList (FThinkerList &list)
{
if (list.Sentinel != NULL)
@ -355,6 +445,12 @@ void DThinker::DestroyThinkersInList (FThinkerList &list)
}
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::RunThinkers ()
{
int i, count;
@ -385,6 +481,12 @@ void DThinker::RunThinkers ()
ThinkCycles.Unclock();
}
//==========================================================================
//
//
//
//==========================================================================
int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
{
int count = 0;
@ -407,7 +509,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
node->Remove();
dest->AddTail(node);
}
node->PostBeginPlay();
node->CallPostBeginPlay();
}
else if (dest != NULL)
{
@ -416,7 +518,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
if (!(node->ObjectFlags & OF_EuthanizeMe))
{ // Only tick thinkers not scheduled for destruction
node->Tick();
node->CallTick();
node->ObjectFlags &= ~OF_JustSpawned;
GC::CheckGC();
}
@ -425,6 +527,12 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
return count;
}
//==========================================================================
//
//
//
//==========================================================================
void DThinker::Tick ()
{
}
@ -432,11 +540,28 @@ void DThinker::Tick ()
DEFINE_ACTION_FUNCTION(DThinker, Tick)
{
PARAM_SELF_PROLOGUE(DThinker);
self->VMSuperCall();
self->Tick();
return 0;
}
void DThinker::CallTick()
{
IFVIRTUAL(DThinker, Tick)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
stack.Call(func, params, 1, nullptr, 0, nullptr);
}
else Tick();
}
//==========================================================================
//
//
//
//==========================================================================
size_t DThinker::PropagateMark()
{
// Do not choke on partially initialized objects (as happens when loading a savegame fails)
@ -450,6 +575,12 @@ size_t DThinker::PropagateMark()
return Super::PropagateMark();
}
//==========================================================================
//
//
//
//==========================================================================
FThinkerIterator::FThinkerIterator (const PClass *type, int statnum)
{
if ((unsigned)statnum > MAX_STATNUM)
@ -467,6 +598,12 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum)
m_SearchingFresh = false;
}
//==========================================================================
//
//
//
//==========================================================================
FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *prev)
{
if ((unsigned)statnum > MAX_STATNUM)
@ -491,12 +628,24 @@ FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *p
}
}
//==========================================================================
//
//
//
//==========================================================================
void FThinkerIterator::Reinit ()
{
m_CurrThinker = DThinker::Thinkers[m_Stat].GetHead();
m_SearchingFresh = false;
}
//==========================================================================
//
//
//
//==========================================================================
DThinker *FThinkerIterator::Next (bool exact)
{
if (m_ParentType == NULL)
@ -542,8 +691,13 @@ DThinker *FThinkerIterator::Next (bool exact)
return NULL;
}
//==========================================================================
//
// This is for scripting, which needs the iterator wrapped into an object with the needed functions exported.
// Unfortunately we cannot have templated type conversions in scripts.
//
//==========================================================================
class DThinkerIterator : public DObject, public FThinkerIterator
{
DECLARE_CLASS(DThinkerIterator, DObject)
@ -555,7 +709,7 @@ public:
}
};
IMPLEMENT_CLASS(DThinkerIterator, false, false, false, false);
IMPLEMENT_CLASS(DThinkerIterator, false, false);
DEFINE_ACTION_FUNCTION(DThinkerIterator, Create)
{
PARAM_PROLOGUE;
@ -577,8 +731,11 @@ DEFINE_ACTION_FUNCTION(DThinkerIterator, Reinit)
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
ADD_STAT (think)
{