-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPlacementBoard.Loading.cs
More file actions
149 lines (135 loc) · 4.84 KB
/
PlacementBoard.Loading.cs
File metadata and controls
149 lines (135 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
using System;
using System.Collections.Generic;
using System.Reflection;
using Assets.Scripts.Objects;
using Assets.Scripts.Serialization;
namespace LibConstruct;
public abstract partial class PlacementBoard
{
public static bool Loading;
private static readonly Dictionary<long, IBoardRef> LoadingRefs = [];
private readonly List<StructurePair> AwaitingRegister = [];
public static void RepairThingOrder(XmlSaveLoad.WorldData worldData)
{
static IEnumerable<long> BoardIds(ThingSaveData thing)
{
if (thing == null)
yield break;
foreach (var field in thing.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy))
{
if (typeof(PlacementBoardHostSaveData).IsAssignableFrom(field.FieldType))
{
if (field.GetValue(thing) is PlacementBoardHostSaveData boardData)
yield return boardData.BoardId;
}
}
}
var boardToThing = new Dictionary<long, ThingSaveData>();
foreach (var thing in worldData.OrderedThings)
{
foreach (var id in BoardIds(thing))
boardToThing[id] = thing;
}
var seenBoards = new HashSet<long>();
for (var i = 0; i < worldData.OrderedThings.Count; i++)
{
var thing = worldData.OrderedThings[i];
if (thing == null)
continue;
foreach (var id in BoardIds(thing))
seenBoards.Add(id);
foreach (var field in thing.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy))
{
if (!typeof(PlacementBoardStructureSaveData).IsAssignableFrom(field.FieldType))
continue;
if (field.GetValue(thing) is not PlacementBoardStructureSaveData boardData)
continue;
if (seenBoards.Contains(boardData.BoardId))
continue;
// if we get here, this is out of order
UnityEngine.Debug.LogWarning($"reordering board {boardData.BoardId}");
var boardThing = boardToThing[boardData.BoardId];
worldData.OrderedThings.Remove(boardThing);
worldData.OrderedThings.Insert(i, boardThing);
seenBoards.Add(boardData.BoardId);
}
}
}
public static BoardRef<T> LoadRef<T>(long id, long primaryHostId) where T : PlacementBoard, new()
{
if (!Loading)
{
// if we aren't loading, this is being called for a newly created object on a client.
// in that case the primary host should already have the board created
return new BoardRef<T> { Board = (T)FindExisting(id, primaryHostId) };
}
if (id >= NextID)
NextID = id + 1;
if (!LoadingRefs.TryGetValue(id, out var iref))
{
iref = new BoardRef<T>();
LoadingRefs[id] = iref;
}
return (BoardRef<T>)iref;
}
public static PlacementBoard FindExisting(long id, long primaryHostId)
{
var host = Thing.Find<IPlacementBoardHost>(primaryHostId);
foreach (var board in host.GetPlacementBoards())
if (board?.ID == id)
return board;
throw new Exception($"could not find PlacementBoard {id} on host {primaryHostId}");
}
public static void RegisterLoading(IPlacementBoardStructure structure, PlacementBoardStructureSaveData saveData)
{
if (Loading)
{
// board elements are ordered after the primary host so the ref should always be here
var iref = LoadingRefs[saveData.BoardId];
iref.Board.AwaitingRegister.Add(new(structure, saveData));
}
else
{
// if we aren't loading, this is a newly created object on a client and we should just register it directly
var board = FindExisting(saveData.BoardId, saveData.PrimaryHostId);
structure.Transform.SetPositionAndRotation(
board.GridToWorld(saveData.Position),
board.IndexToRotation(saveData.Rotation)
);
board.Register(structure);
}
}
public static void StartLoad()
{
LoadingRefs.Clear();
Loading = true;
}
public static void FinishLoad()
{
foreach (var iref in LoadingRefs.Values)
{
foreach (var (structure, saveData) in iref.Board.AwaitingRegister)
{
var board = iref.Board;
// update the position and rotation of the structure before registering
structure.Transform.SetPositionAndRotation(
board.GridToWorld(saveData.Position),
board.IndexToRotation(saveData.Rotation)
);
board.Register(structure);
}
iref.Board.AwaitingRegister.Clear();
}
LoadingRefs.Clear();
Loading = false;
}
private class StructurePair(IPlacementBoardStructure structure, PlacementBoardStructureSaveData saveData)
{
public IPlacementBoardStructure Structure = structure;
public PlacementBoardStructureSaveData SaveData = saveData;
public void Deconstruct(out IPlacementBoardStructure structure, out PlacementBoardStructureSaveData saveData)
{
(structure, saveData) = (Structure, SaveData);
}
}
}