forked from Mirrors/openclonk
Rework prop list renumbering on section load (again).
Turns out changing prop list numbers while they are still indexed by number in the hash map was a bad idea. Existing prop lists are now de-numbered, pushed to an external shelve and re-numbered when added after section load.stable-5.4
parent
1cca6fd1ad
commit
25ddb14dca
|
@ -36,6 +36,7 @@
|
|||
C4Set<C4PropList *> C4PropList::PropLists;
|
||||
#endif
|
||||
C4Set<C4PropListNumbered *> C4PropListNumbered::PropLists;
|
||||
std::vector<C4PropListNumbered *> C4PropListNumbered::ShelvedPropLists;
|
||||
int32_t C4PropListNumbered::EnumerationIndex = 0;
|
||||
C4StringTable Strings;
|
||||
C4AulScriptEngine ScriptEngine;
|
||||
|
|
|
@ -617,6 +617,7 @@ void C4Game::Clear()
|
|||
::FontLoader.Clear();
|
||||
#endif
|
||||
|
||||
C4PropListNumbered::ClearShelve(); // may be nonempty if there was a fatal error during section load
|
||||
ScriptEngine.Clear();
|
||||
MainSysLangStringTable.Clear();
|
||||
ScenarioLangStringTable.Clear();
|
||||
|
@ -1635,7 +1636,7 @@ void C4Game::CompileFunc(StdCompiler *pComp, CompileSettings comp, C4ValueNumber
|
|||
|
||||
// Section load: Clear existing prop list numbering to make room for the new objects
|
||||
// Numbers will be re-acquired in C4GameObjects::PostLoad
|
||||
if (comp.fScenarioSection) C4PropListNumbered::ClearAllProplistNumbers();
|
||||
if (comp.fScenarioSection) C4PropListNumbered::ShelveNumberedPropLists();
|
||||
|
||||
pComp->Value(mkParAdapt(Objects, !comp.fExact, numbers));
|
||||
|
||||
|
@ -3330,6 +3331,8 @@ bool C4Game::LoadScenarioSection(const char *szSection, DWORD dwFlags)
|
|||
DebugLog("LoadScenarioSection: Error reiniting game");
|
||||
return false;
|
||||
}
|
||||
// restore shelved proplists in case loading failed
|
||||
C4PropListNumbered::UnshelveNumberedPropLists();
|
||||
// set new current section
|
||||
pCurrentScenarioSection = pLoadSect;
|
||||
SCopy(pCurrentScenarioSection->szName, CurrentScenarioSection);
|
||||
|
|
|
@ -234,7 +234,6 @@ int C4GameObjects::PostLoad(bool fKeepInactive, C4ValueNumbers * numbers)
|
|||
// Process objects
|
||||
C4ObjectLink *cLnk;
|
||||
C4Object *pObj;
|
||||
bool fObjectNumberCollision = false;
|
||||
int32_t iMaxObjectNumber = 0;
|
||||
for (cLnk = Last; cLnk; cLnk = cLnk->Prev)
|
||||
{
|
||||
|
@ -262,7 +261,7 @@ int C4GameObjects::PostLoad(bool fKeepInactive, C4ValueNumbers * numbers)
|
|||
if (fKeepInactive)
|
||||
{
|
||||
InactiveObjects.First=pInFirst;
|
||||
C4PropListNumbered::AcquireAllProplistNumbers();
|
||||
C4PropListNumbered::UnshelveNumberedPropLists();
|
||||
}
|
||||
|
||||
// special checks:
|
||||
|
|
|
@ -108,45 +108,60 @@ void C4PropListNumbered::ResetEnumerationIndex()
|
|||
EnumerationIndex = 0;
|
||||
}
|
||||
|
||||
void C4PropListNumbered::ClearAllProplistNumbers()
|
||||
void C4PropListNumbered::ShelveNumberedPropLists()
|
||||
{
|
||||
// unnumber all proplists. To be used on remaining objects before a savegame load.
|
||||
C4PropListNumbered *const* p = PropLists.First();
|
||||
while (p)
|
||||
// unnumber all proplists and put them on the shelve. To be used on remaining objects before a savegame load.
|
||||
assert(ShelvedPropLists.empty());
|
||||
ShelvedPropLists.reserve(PropLists.GetSize());
|
||||
C4PropListNumbered *const* p_next = PropLists.First(), *const* p;
|
||||
while ((p = p_next))
|
||||
{
|
||||
(*p)->ClearNumber();
|
||||
p = PropLists.Next(p);
|
||||
p_next = PropLists.Next(p);
|
||||
C4PropListNumbered *pl = *p;
|
||||
if (pl->Number != -1)
|
||||
{
|
||||
pl->ClearNumber();
|
||||
ShelvedPropLists.push_back(pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C4PropListNumbered::AcquireAllProplistNumbers()
|
||||
void C4PropListNumbered::UnshelveNumberedPropLists()
|
||||
{
|
||||
C4PropListNumbered *const* p = PropLists.First();
|
||||
while (p)
|
||||
{
|
||||
if (!(*p)->Number) (*p)->AcquireNumber(true);
|
||||
p = PropLists.Next(p);
|
||||
}
|
||||
// re-insert shelved proplists into main list and give them a number
|
||||
for (std::vector<C4PropListNumbered *>::iterator i=ShelvedPropLists.begin(); i!=ShelvedPropLists.end(); ++i)
|
||||
(*i)->AcquireNumber();
|
||||
ShelvedPropLists.clear();
|
||||
}
|
||||
|
||||
void C4PropListNumbered::ClearShelve()
|
||||
{
|
||||
// cleanup shelve - used in game clear, un unsuccessful section load, etc.
|
||||
ShelvedPropLists.clear();
|
||||
}
|
||||
|
||||
C4PropListNumbered::C4PropListNumbered(C4PropList * prototype): C4PropList(prototype), Number(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void C4PropListNumbered::AcquireNumber(bool check_double_add)
|
||||
void C4PropListNumbered::AcquireNumber()
|
||||
{
|
||||
// Enumerate object
|
||||
do
|
||||
Number = ++EnumerationIndex;
|
||||
while (PropLists.Get(Number));
|
||||
// Add to list (unless it's already in there)
|
||||
if (!check_double_add || !C4PropListNumbered::CheckPropList(this)) PropLists.Add(this);
|
||||
// Add to list
|
||||
PropLists.Add(this);
|
||||
}
|
||||
|
||||
void C4PropListNumbered::ClearNumber()
|
||||
{
|
||||
// Make proplist invisible during denumeration process
|
||||
Number = 0;
|
||||
if (Number != -1)
|
||||
{
|
||||
PropLists.Remove(this);
|
||||
Number = -1;
|
||||
}
|
||||
}
|
||||
|
||||
C4PropListNumbered* C4PropListNumbered::GetPropListNumbered()
|
||||
|
|
|
@ -177,14 +177,16 @@ public:
|
|||
static void SetEnumerationIndex(int32_t iMaxObjectNumber);
|
||||
static int32_t GetEnumerationIndex() { return EnumerationIndex; }
|
||||
static void ResetEnumerationIndex();
|
||||
static void ClearAllProplistNumbers(); // unnumber all proplists. To be used on remaining objects before a savegame load.
|
||||
static void AcquireAllProplistNumbers(); // acquire a number on all proplists that are currently unnumbered
|
||||
static void ShelveNumberedPropLists(); // unnumber all proplists and put them on the shelve. To be used on remaining objects before a savegame load.
|
||||
static void UnshelveNumberedPropLists(); // re-insert shelved proplists into main list
|
||||
static void ClearShelve();
|
||||
protected:
|
||||
C4PropListNumbered(C4PropList * prototype = 0);
|
||||
void AcquireNumber(bool check_double_add=false); // acquire a number and add to internal list. if check_double_add is set, check if the proplist is already in the list before
|
||||
void ClearNumber();
|
||||
void AcquireNumber(); // acquire a number and add to internal list
|
||||
void ClearNumber(); // clear number and remove from internal list
|
||||
|
||||
static C4Set<C4PropListNumbered *> PropLists;
|
||||
static std::vector<C4PropListNumbered *> ShelvedPropLists; // temporary storage for existing proplists while a new section loaded
|
||||
static int32_t EnumerationIndex;
|
||||
friend class C4Game;
|
||||
friend class C4GameObjects;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
C4Set<C4PropList *> C4PropList::PropLists;
|
||||
#endif
|
||||
C4Set<C4PropListNumbered *> C4PropListNumbered::PropLists;
|
||||
std::vector<C4PropListNumbered *> C4PropListNumbered::ShelvedPropLists;
|
||||
int32_t C4PropListNumbered::EnumerationIndex = 0;
|
||||
C4StringTable Strings;
|
||||
C4AulScriptEngine ScriptEngine;
|
||||
|
|
Loading…
Reference in New Issue