Skip to content

Commit 8848953

Browse files
committed
Refactor persistence manager to rely on async only
1 parent 2237c69 commit 8848953

File tree

1 file changed

+102
-40
lines changed

1 file changed

+102
-40
lines changed

src/Scripts/Game/EPF_PersistenceManager.c

Lines changed: 102 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class EPF_PersistenceManager
4444

4545
// Setup buffers, discarded after world init
4646
protected ref map<string, EPF_PersistenceComponent> m_mBakedRoots;
47+
protected int m_iPendingLoadTypes;
4748

4849
//------------------------------------------------------------------------------------------------
4950
//! Check if current game instance is intended to run the persistence system. Only the mission host should do so.
@@ -247,10 +248,17 @@ class EPF_PersistenceManager
247248
//! \return entity instance or null if not found
248249
EPF_PersistenceComponent FindPersistenceComponentById(string persistentId)
249250
{
251+
if (!CheckLoaded())
252+
return null;
253+
250254
FlushRegistrations();
251255
EPF_PersistenceComponent result;
252-
if (m_mRootAutoSave.Find(persistentId, result)) return result;
253-
if (m_mRootShutdown.Find(persistentId, result)) return result;
256+
if (m_mRootAutoSave.Find(persistentId, result))
257+
return result;
258+
259+
if (m_mRootShutdown.Find(persistentId, result))
260+
return result;
261+
254262
return m_mUncategorizedEntities.Get(persistentId);
255263
}
256264

@@ -259,18 +267,25 @@ class EPF_PersistenceManager
259267
//! \return scripted state instance or null if not found
260268
EPF_PersistentScriptedState FindScriptedStateByPersistentId(string persistentId)
261269
{
270+
if (!CheckLoaded())
271+
return null;
272+
262273
FlushRegistrations();
263274
EPF_PersistentScriptedState result;
264-
if (m_mScriptedStateAutoSave.Find(persistentId, result)) return result;
265-
if (m_mScriptedStateShutdown.Find(persistentId, result)) return result;
275+
if (m_mScriptedStateAutoSave.Find(persistentId, result))
276+
return result;
277+
278+
if (m_mScriptedStateShutdown.Find(persistentId, result))
279+
return result;
280+
266281
return m_mScriptedStateUncategorized.Get(persistentId);
267282
}
268283

269284
//------------------------------------------------------------------------------------------------
270285
//! Manually trigger the global auto-save. Resets the timer until the next auto-save cycle. If an auto-save is already in progress it will do nothing.
271286
void AutoSave()
272287
{
273-
if (m_bAutoSaveActive)
288+
if (m_bAutoSaveActive || !CheckLoaded())
274289
return;
275290

276291
m_bAutoSaveActive = true;
@@ -499,7 +514,7 @@ class EPF_PersistenceManager
499514
//------------------------------------------------------------------------------------------------
500515
void UpdateRootEntityCollection(notnull EPF_PersistenceComponent persistenceComponent, string id, bool isRootEntity)
501516
{
502-
if (m_eState < EPF_EPersistenceManagerState.ACTIVE)
517+
if (m_eState < EPF_EPersistenceManagerState.SETUP)
503518
{
504519
if (m_mBakedRoots && EPF_BitFlags.CheckFlags(persistenceComponent.GetFlags(), EPF_EPersistenceFlags.BAKED))
505520
{
@@ -529,6 +544,9 @@ class EPF_PersistenceManager
529544
//------------------------------------------------------------------------------------------------
530545
void ForceSelfSpawn(notnull EPF_PersistenceComponent persistenceComponent)
531546
{
547+
if (!CheckLoaded())
548+
return;
549+
532550
EPF_PersistenceComponentClass settings = EPF_ComponentData<EPF_PersistenceComponentClass>.Get(persistenceComponent);
533551
m_pRootEntityCollection.ForceSelfSpawn(persistenceComponent, persistenceComponent.GetPersistentId(), settings);
534552
}
@@ -638,6 +656,18 @@ class EPF_PersistenceManager
638656
m_aPendingScriptedStateRegistrations.Clear();
639657
}
640658

659+
//------------------------------------------------------------------------------------------------
660+
protected bool CheckLoaded()
661+
{
662+
if (m_eState < EPF_EPersistenceManagerState.SETUP)
663+
{
664+
Debug.Error("Attempted to call persistence operation before setup phase. Await setup/completion using GetOnStateChangeEvent/GetOnActiveEvent.");
665+
return false;
666+
}
667+
668+
return true;
669+
}
670+
641671
//------------------------------------------------------------------------------------------------
642672
event void OnPostInit(IEntity gameMode, EPF_PersistenceManagerComponentClass settings)
643673
{
@@ -655,14 +685,6 @@ class EPF_PersistenceManager
655685
if (!m_pDbContext)
656686
return;
657687

658-
string rootEntityCollectionId = string.Format("00EC%1-0000-0000-0000-000000000000", EPF_PersistenceIdGenerator.GetHiveId().ToString(4));
659-
m_pRootEntityCollection = EDF_DbEntityHelper<EPF_PersistentRootEntityCollection>.GetRepository(m_pDbContext).Find(rootEntityCollectionId).GetEntity();
660-
if (!m_pRootEntityCollection)
661-
{
662-
m_pRootEntityCollection = new EPF_PersistentRootEntityCollection();
663-
m_pRootEntityCollection.SetId(rootEntityCollectionId);
664-
}
665-
666688
SetState(EPF_EPersistenceManagerState.POST_INIT);
667689
}
668690

@@ -685,7 +707,31 @@ class EPF_PersistenceManager
685707
{
686708
Print("Persistence initial world load started...", LogLevel.DEBUG);
687709

710+
// Flush all pending objects so they register as baked
688711
FlushRegistrations();
712+
713+
EDF_DbFindCallbackSingle<EPF_PersistentRootEntityCollection> callback(this, "OnRootEntityCollectionLoaded");
714+
EDF_DbEntityHelper<EPF_PersistentRootEntityCollection>.GetRepository(m_pDbContext)
715+
.FindAsync(GetRootEntityCollectionId(), callback);
716+
}
717+
718+
//------------------------------------------------------------------------------------------------
719+
protected string GetRootEntityCollectionId()
720+
{
721+
return string.Format("00EC%1-0000-0000-0000-000000000000", EPF_PersistenceIdGenerator.GetHiveId().ToString(4));
722+
}
723+
724+
//------------------------------------------------------------------------------------------------
725+
protected void OnRootEntityCollectionLoaded(EDF_EDbOperationStatusCode statusCode, EPF_PersistentRootEntityCollection rootEntityCollection)
726+
{
727+
m_pRootEntityCollection = rootEntityCollection;
728+
if (!m_pRootEntityCollection)
729+
{
730+
m_pRootEntityCollection = new EPF_PersistentRootEntityCollection();
731+
m_pRootEntityCollection.SetId(GetRootEntityCollectionId());
732+
}
733+
734+
// Anything spawned after this is considered dynamic
689735
SetState(EPF_EPersistenceManagerState.SETUP);
690736

691737
// Remove baked entities that shall no longer be root entities in the world
@@ -737,53 +783,69 @@ class EPF_PersistenceManager
737783
loadIds.Insert(id);
738784
}
739785

786+
// Save any mapping or root entity changes detected during world init
787+
m_pRootEntityCollection.Save(m_pDbContext);
788+
740789
// Load all known initial entity types from db, both baked and dynamic in one bulk operation
790+
m_iPendingLoadTypes = bulkLoad.Count();
741791
foreach (typename saveDataType, array<string> persistentIds : bulkLoad)
742792
{
743-
array<ref EDF_DbEntity> findResults = m_pDbContext.FindAll(saveDataType, EDF_DbFind.Id().EqualsAnyOf(persistentIds)).GetEntities();
744-
if (!findResults) continue;
793+
EDF_DbFindCallbackMultipleUntyped callback(this, "OnTypeCollectionLoaded");
794+
m_pDbContext.FindAllAsync(saveDataType, EDF_DbFind.Id().EqualsAnyOf(persistentIds), callback: callback);
795+
}
796+
}
745797

746-
foreach (EDF_DbEntity findResult : findResults)
798+
//------------------------------------------------------------------------------------------------
799+
protected void OnTypeCollectionLoaded(EDF_EDbOperationStatusCode code, array<ref EDF_DbEntity> findResults)
800+
{
801+
foreach (EDF_DbEntity findResult : findResults)
802+
{
803+
EPF_EntitySaveData saveData = EPF_EntitySaveData.Cast(findResult);
804+
if (!saveData)
747805
{
748-
EPF_EntitySaveData saveData = EPF_EntitySaveData.Cast(findResult);
749-
if (!saveData)
750-
{
751-
Debug.Error(string.Format("Unexpected database find result type '%1' encountered during entity load. Ignored.", findResult.Type().ToString()));
752-
continue;
753-
}
754-
755-
// Load data for baked roots
756-
EPF_PersistenceComponent persistenceComponent = m_mBakedRoots.Get(saveData.GetId());
757-
if (persistenceComponent)
758-
{
759-
persistenceComponent.Load(saveData);
760-
continue;
761-
}
806+
Debug.Error(string.Format("Unexpected database find result type '%1' encountered during entity load. Ignored.", findResult.Type().ToString()));
807+
continue;
808+
}
762809

763-
// Spawn additional dynamic entites
764-
SpawnWorldEntity(saveData);
810+
// Load data for baked roots
811+
EPF_PersistenceComponent persistenceComponent = m_mBakedRoots.Get(saveData.GetId());
812+
if (persistenceComponent)
813+
{
814+
persistenceComponent.Load(saveData);
815+
continue;
765816
}
817+
818+
// Spawn additional dynamic entites
819+
SpawnWorldEntity(saveData);
766820
}
767821

768-
// Save any mapping or root entity changes detected during world init
769-
m_pRootEntityCollection.Save(m_pDbContext);
822+
if (--m_iPendingLoadTypes == 0)
823+
OnPostSetup();
824+
}
770825

826+
//------------------------------------------------------------------------------------------------
827+
protected void OnPostSetup()
828+
{
771829
// Free memory as it not needed after setup
772830
m_mBakedRoots = null;
773-
774831
Print("Persistence initial world load complete.", LogLevel.DEBUG);
775-
776832
SetState(EPF_EPersistenceManagerState.ACTIVE);
777833
}
778834

779835
//------------------------------------------------------------------------------------------------
780836
event void OnGameEnd()
781837
{
782838
Print("Persistence shutting down...", LogLevel.DEBUG);
839+
840+
bool wasActive = m_eState == EPF_EPersistenceManagerState.ACTIVE;
783841
SetState(EPF_EPersistenceManagerState.SHUTDOWN);
784-
AutoSave(); // Trigger auto-save
785-
AutoSaveTick(); // Execute auto-save instantly till end
786-
ShutDownSave(); // Save those who only save on shutdown
842+
if (wasActive)
843+
{
844+
AutoSave(); // Trigger auto-save
845+
AutoSaveTick(); // Execute auto-save instantly till end
846+
ShutDownSave(); // Save those who only save on shutdown
847+
}
848+
787849
Reset();
788850
Print("Persistence shut down successfully.", LogLevel.DEBUG);
789851
}

0 commit comments

Comments
 (0)