|
| 1 | +namespace Nautilus.MonoBehaviours; |
| 2 | + |
1 | 3 | using System.Collections;
|
2 |
| -using Nautilus.Extensions; |
| 4 | +using System.Collections.Generic; |
3 | 5 | using Nautilus.Handlers;
|
4 | 6 | using Nautilus.Patchers;
|
5 | 7 | using Nautilus.Utility;
|
6 | 8 | using UnityEngine;
|
7 | 9 | using UWE;
|
8 | 10 |
|
9 |
| -namespace Nautilus.MonoBehaviours; |
10 |
| - |
11 | 11 | internal class EntitySpawner : MonoBehaviour
|
12 | 12 | {
|
13 |
| - internal SpawnInfo spawnInfo; |
| 13 | + internal Int3 batchId; |
| 14 | + internal IReadOnlyCollection<SpawnInfo> spawnInfos; |
| 15 | + internal bool global; |
14 | 16 |
|
15 |
| - void Start() |
| 17 | + private IEnumerator Start() |
16 | 18 | {
|
17 |
| - StartCoroutine(SpawnAsync()); |
| 19 | + yield return SpawnAsync(); |
| 20 | + Destroy(gameObject); |
18 | 21 | }
|
19 | 22 |
|
20 |
| - IEnumerator SpawnAsync() |
| 23 | + private IEnumerator SpawnAsync() |
21 | 24 | {
|
22 |
| - string stringToLog = spawnInfo.Type switch |
23 |
| - { |
24 |
| - SpawnInfo.SpawnType.ClassId => spawnInfo.ClassId, |
25 |
| - _ => spawnInfo.TechType.AsString() |
26 |
| - }; |
27 |
| - |
28 |
| - TaskResult<GameObject> task = new(); |
29 |
| - yield return GetPrefabAsync(task); |
30 |
| - |
31 |
| - GameObject prefab = task.Get(); |
32 |
| - if (prefab == null) |
33 |
| - { |
34 |
| - InternalLogger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled."); |
35 |
| - Destroy(gameObject); |
36 |
| - yield break; |
37 |
| - } |
38 |
| - |
39 |
| - if (!prefab.IsPrefab()) |
40 |
| - { |
41 |
| - prefab.SetActive(false); |
42 |
| - } |
43 |
| - |
44 |
| - GameObject obj = UWE.Utils.InstantiateDeactivated(prefab, spawnInfo.SpawnPosition, spawnInfo.Rotation, spawnInfo.ActualScale); |
45 |
| - |
46 |
| - LargeWorldEntity lwe = obj.GetComponent<LargeWorldEntity>(); |
47 |
| - |
48 | 25 | LargeWorldStreamer lws = LargeWorldStreamer.main;
|
49 | 26 | yield return new WaitUntil(() => lws != null && lws.IsReady()); // first we make sure the world streamer is initialized
|
50 | 27 |
|
51 |
| - // non-global objects cannot be spawned in unloaded terrain so we need to wait |
52 |
| - if (lwe is {cellLevel: not (LargeWorldEntity.CellLevel.Batch or LargeWorldEntity.CellLevel.Global)}) |
| 28 | + if (!global) |
53 | 29 | {
|
54 |
| - Int3 batch = lws.GetContainingBatch(spawnInfo.SpawnPosition); |
55 |
| - yield return new WaitUntil(() => lws.IsBatchReadyToCompile(batch)); // then we wait until the terrain is fully loaded (must be checked on each frame for faster spawns) |
| 30 | + // then we wait until the terrain is fully loaded (must be checked on each frame for faster spawns) |
| 31 | + yield return new WaitUntil(() => lws.IsBatchReadyToCompile(batchId)); |
56 | 32 | }
|
57 | 33 |
|
58 | 34 | LargeWorld lw = LargeWorld.main;
|
59 |
| - |
| 35 | + |
60 | 36 | yield return new WaitUntil(() => lw != null && lw.streamer.globalRoot != null); // need to make sure global root is ready too for global spawns.
|
| 37 | + |
| 38 | + foreach (var spawnInfo in spawnInfos) |
| 39 | + { |
| 40 | + string stringToLog = spawnInfo.Type switch |
| 41 | + { |
| 42 | + SpawnInfo.SpawnType.ClassId => spawnInfo.ClassId, |
| 43 | + _ => spawnInfo.TechType.AsString() |
| 44 | + }; |
| 45 | + |
| 46 | + InternalLogger.Debug($"Spawning {stringToLog}"); |
61 | 47 |
|
62 |
| - lw.streamer.cellManager.RegisterEntity(obj); |
| 48 | + TaskResult<GameObject> task = new(); |
| 49 | + yield return GetPrefabAsync(spawnInfo, task); |
63 | 50 |
|
64 |
| - obj.SetActive(true); |
| 51 | + GameObject prefab = task.Get(); |
| 52 | + if (prefab == null) |
| 53 | + { |
| 54 | + InternalLogger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled."); |
| 55 | + continue; |
| 56 | + } |
65 | 57 |
|
66 |
| - LargeWorldStreamerPatcher.savedSpawnInfos.Add(spawnInfo); |
| 58 | + LargeWorldEntity lwe = prefab.GetComponent<LargeWorldEntity>(); |
67 | 59 |
|
68 |
| - Destroy(gameObject); |
| 60 | + if (!lwe) |
| 61 | + { |
| 62 | + InternalLogger.Error($"No LargeWorldEntity component found for prefab '{stringToLog}'; process for Coordinated Spawn canceled."); |
| 63 | + continue; |
| 64 | + } |
| 65 | + |
| 66 | + GameObject obj = Instantiate(prefab, spawnInfo.SpawnPosition, spawnInfo.Rotation); |
| 67 | + obj.transform.localScale = spawnInfo.ActualScale; |
| 68 | + |
| 69 | + obj.SetActive(true); |
| 70 | + |
| 71 | + LargeWorldEntity.Register(obj); |
| 72 | + |
| 73 | + LargeWorldStreamerPatcher.SavedSpawnInfos.Add(spawnInfo); |
| 74 | + InternalLogger.Debug($"spawned {stringToLog}."); |
| 75 | + } |
69 | 76 | }
|
70 | 77 |
|
71 |
| - IEnumerator GetPrefabAsync(IOut<GameObject> gameObject) |
| 78 | + private IEnumerator GetPrefabAsync(SpawnInfo spawnInfo, IOut<GameObject> gameObject) |
72 | 79 | {
|
73 | 80 | GameObject obj;
|
74 | 81 |
|
|
0 commit comments