11#include " Ecsact.h"
22#include " CoreGlobals.h"
33#include " EcsactUnreal/EcsactSettings.h"
4+ #include " Engine/World.h"
45#include " HAL/PlatformProcess.h"
56#include " Logging/LogVerbosity.h"
67#include " Misc/Paths.h"
@@ -64,7 +65,6 @@ auto FEcsactModule::LoadEcsactRuntime() -> void {
6465 static_assert (true , " require ;" )
6566 FOR_EACH_ECSACT_API_FN (LOAD_ECSACT_FN);
6667#undef LOAD_ECSACT_FN
67- StartRunner ();
6868}
6969
7070auto FEcsactModule::UnloadEcsactRuntime () -> void {
@@ -74,7 +74,9 @@ auto FEcsactModule::UnloadEcsactRuntime() -> void {
7474 ecsact_async_disconnect ();
7575 }
7676
77- StopRunner ();
77+ for (auto i = 0 ; RunnerWorlds.Num () > i; ++i) {
78+ StopRunner (i);
79+ }
7880
7981#define RESET_ECSACT_FN (fn, UNUSED_PARAM ) fn = nullptr
8082 FOR_EACH_ECSACT_API_FN (RESET_ECSACT_FN);
@@ -95,8 +97,53 @@ auto FEcsactModule::StartupModule() -> void {
9597 }
9698#if WITH_EDITOR
9799 FEditorDelegates::PreBeginPIE.AddRaw (this , &FEcsactModule::OnPreBeginPIE);
98- FEditorDelegates::EndPIE .AddRaw (this , &FEcsactModule::OnPrePIEEnded );
100+ FEditorDelegates::ShutdownPIE .AddRaw (this , &FEcsactModule::OnShutdownPIE );
99101#endif
102+ FWorldDelegates::OnPreWorldInitialization.AddRaw (
103+ this ,
104+ &FEcsactModule::OnPreWorldInitialization
105+ );
106+ FWorldDelegates::OnPostWorldCleanup.AddRaw (
107+ this ,
108+ &FEcsactModule::OnPostWorldCleanup
109+ );
110+ }
111+
112+ auto FEcsactModule::OnPreWorldInitialization ( //
113+ UWorld* World,
114+ const UWorld::InitializationValues IVS
115+ ) -> void {
116+ switch (World->WorldType .GetValue ()) {
117+ case EWorldType::None:
118+ case EWorldType::Editor:
119+ case EWorldType::EditorPreview:
120+ case EWorldType::GamePreview:
121+ case EWorldType::GameRPC:
122+ case EWorldType::Inactive:
123+ return ;
124+ case EWorldType::PIE:
125+ case EWorldType::Game:
126+ break ;
127+ }
128+
129+ auto index = RunnerWorlds.Num ();
130+ RunnerWorlds.Add (World);
131+ Runners.AddDefaulted ();
132+ check (RunnerWorlds.Num () == Runners.Num ());
133+ StartRunner (index);
134+ }
135+
136+ auto FEcsactModule::OnPostWorldCleanup ( //
137+ UWorld* World,
138+ bool bSessionEnded,
139+ bool bCleanupResources
140+ ) -> void {
141+ for (auto i = 0 ; RunnerWorlds.Num () > i; ++i) {
142+ if (RunnerWorlds[i].Get () == World) {
143+ StopRunner (i);
144+ break ;
145+ }
146+ }
100147}
101148
102149auto FEcsactModule::ShutdownModule () -> void {
@@ -116,55 +163,91 @@ auto FEcsactModule::OnPreBeginPIE(bool _) -> void {
116163 LoadEcsactRuntime ();
117164}
118165
119- auto FEcsactModule::OnPrePIEEnded (bool _) -> void {
166+ auto FEcsactModule::OnShutdownPIE (bool _) -> void {
120167 UnloadEcsactRuntime ();
121168}
122169
123- auto FEcsactModule::StartRunner () -> void {
170+ auto FEcsactModule::StartRunner (int32 Index ) -> void {
124171 const auto * settings = GetDefault<UEcsactSettings>();
125172
126- if (Runner != nullptr ) {
173+ if (Index >= Runners.Num ()) {
174+ UE_LOG (
175+ Ecsact,
176+ Error,
177+ TEXT (" StartRunner() was called before the associated world was "
178+ " initialized" )
179+ );
180+ return ;
181+ }
182+
183+ for (auto Runner : Runners) {
184+ if (Runner.IsValid ()) {
185+ UE_LOG (
186+ Ecsact,
187+ Error,
188+ TEXT (" Multiple Ecsact runners are not supported at this time" )
189+ );
190+ return ;
191+ }
192+ }
193+
194+ if (auto Runner = Runners[Index].Get (); Runner) {
127195 UE_LOG (
128196 Ecsact,
129197 Warning,
130198 TEXT (" StartRunner() was called while runner was already running. "
131199 " Stopping previous one before starting new." )
132200 );
133- StopRunner ();
201+ StopRunner (Index);
202+ }
203+
204+ auto World = RunnerWorlds[Index].Get ();
205+
206+ if (!World) {
207+ UE_LOG (Ecsact, Error, TEXT (" StartRunner() was called on invalid world" ));
208+ return ;
134209 }
135210
136211 switch (settings->Runner ) {
137212 case EEcsactRuntimeRunnerType::Automatic:
138213 if (ecsact_async_flush_events == nullptr ) {
139- Runner = NewObject<UEcsactSyncRunner>();
214+ Runners[Index] = NewObject<UEcsactSyncRunner>();
140215 } else {
141- Runner = NewObject<UEcsactAsyncRunner>();
216+ Runners[Index] = NewObject<UEcsactAsyncRunner>();
142217 }
143218 break ;
144219 case EEcsactRuntimeRunnerType::Asynchronous:
145- Runner = NewObject<UEcsactAsyncRunner>();
220+ Runners[Index] = NewObject<UEcsactAsyncRunner>();
146221 break ;
147222 case EEcsactRuntimeRunnerType::Custom:
148223 if (settings->CustomRunnerClass != nullptr ) {
149- Runner = NewObject<UEcsactRunner>(nullptr , settings->CustomRunnerClass );
224+ Runners[Index] =
225+ NewObject<UEcsactRunner>(nullptr , settings->CustomRunnerClass );
150226 }
151227 break ;
152228 }
153229
154- if (Runner != nullptr ) {
230+ if (auto Runner = Runners[Index]. Get (); Runner ) {
155231 UE_LOG (
156232 Ecsact,
157233 Log,
158234 TEXT (" Starting ecsact runner: %s" ),
159235 *Runner->GetClass ()->GetName ()
160236 );
237+ Runner->World = World;
161238 Runner->AddToRoot ();
162239 Runner->Start ();
163240 }
164241}
165242
166- auto FEcsactModule::StopRunner () -> void {
167- if (Runner != nullptr ) {
243+ auto FEcsactModule::StopRunner (int32 Index) -> void {
244+ if (Index >= Runners.Num ()) {
245+ return ;
246+ }
247+
248+ auto Runner = Runners[Index].Get ();
249+
250+ if (Runner) {
168251 UE_LOG (
169252 Ecsact,
170253 Log,
@@ -174,7 +257,7 @@ auto FEcsactModule::StopRunner() -> void {
174257 Runner->Stop ();
175258 Runner->RemoveFromRoot ();
176259 Runner->MarkAsGarbage ();
177- Runner .Reset ();
260+ Runners[Index] .Reset ();
178261 }
179262}
180263
0 commit comments