Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemSpawn.cs
浏览该文件的文档.
1using System.Globalization;
2using System.Text;
3using Engine;
7
8namespace Game {
11
13
15
17
19
20 public Random m_random = new();
21
22 public double m_nextDiscardOldChunksTime = 1.0;
23
24 public double m_nextVisitedTime = 1.0;
25
26 public double m_nextChunkSpawnTime = 1.0;
27
28 public double m_nextDespawnTime = 1.0;
29
30 public Dictionary<Point2, SpawnChunk> m_chunks = [];
31
32 public Dictionary<ComponentSpawn, bool> m_spawns = [];
33
34 // ReSharper disable CollectionNeverQueried.Global
35 public Dictionary<int, SpawnEntityData> m_spawnEntityDatas = new();
36 // ReSharper restore CollectionNeverQueried.Global
37
38 public float MaxChunkAge = 76800f;
39
40 public float VisitedRadius = 8f;
41
42 public float SpawnRadius = 48f;
43
44 public float DespawnRadius = 60f;
45
46 public Dictionary<ComponentSpawn, bool>.KeyCollection Spawns => m_spawns.Keys;
47
49
50 public virtual Action<SpawnChunk> SpawningChunk { get; set; }
51
52 public virtual SpawnChunk GetSpawnChunk(Point2 point) {
53 m_chunks.TryGetValue(point, out SpawnChunk value);
54 return value;
55 }
56
57 public virtual void Update(float dt) {
59 m_nextDiscardOldChunksTime = m_subsystemTime.GameTime + 60.0;
61 }
62 if (m_subsystemTime.GameTime >= m_nextVisitedTime) {
63 m_nextVisitedTime = m_subsystemTime.GameTime + 5.0;
65 }
66 if (m_subsystemTime.GameTime >= m_nextChunkSpawnTime) {
67 m_nextChunkSpawnTime = m_subsystemTime.GameTime + 4.0;
69 }
70 if (m_subsystemTime.GameTime >= m_nextDespawnTime) {
71 m_nextDespawnTime = m_subsystemTime.GameTime + 2.0;
73 }
74 }
75
76 public override void Load(ValuesDictionary valuesDictionary) {
77 m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(true);
78 m_subsystemPlayers = Project.FindSubsystem<SubsystemPlayers>(true);
79 m_subsystemViews = Project.FindSubsystem<SubsystemGameWidgets>(true);
80 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
81 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
82 foreach (KeyValuePair<string, object> item in valuesDictionary.GetValue<ValuesDictionary>("Chunks")) {
83 ValuesDictionary valuesDictionary2 = (ValuesDictionary)item.Value;
84 SpawnChunk spawnChunk = new() {
86 IsSpawned = valuesDictionary2.GetValue<bool>("IsSpawned"),
87 LastVisitedTime = valuesDictionary2.GetValue<double>("LastVisitedTime")
88 };
89 object obj = valuesDictionary2.GetValue("SpawnsData", new object());
90 if (obj is string str) {
91 LoadSpawnsData(str, spawnChunk.SpawnsData);
92 }
93 else if (obj is ValuesDictionary data) {
94#pragma warning disable CS0612 // 类型或成员已过时
95 LoadSpawnsData(data, spawnChunk.SpawnsData);
96#pragma warning restore CS0612 // 类型或成员已过时
97 }
98 m_chunks[spawnChunk.Point] = spawnChunk;
99 }
100 }
101
102 public override void Save(ValuesDictionary valuesDictionary) {
103 ValuesDictionary valuesDictionary2 = new();
104 valuesDictionary.SetValue("Chunks", valuesDictionary2);
105 foreach (SpawnChunk value2 in m_chunks.Values) {
106 if (value2.LastVisitedTime.HasValue) {
107 ValuesDictionary valuesDictionary3 = new();
108 valuesDictionary2.SetValue(HumanReadableConverter.ConvertToString(value2.Point), valuesDictionary3);
109 valuesDictionary3.SetValue("IsSpawned", value2.IsSpawned);
110 valuesDictionary3.SetValue("LastVisitedTime", value2.LastVisitedTime.Value);
111 /*ValuesDictionary v = [];
112 SaveSpawnsData(v, value2.SpawnsData);
113 valuesDictionary3.SetValue("SpawnsData", v);*/
114 string text = SaveSpawnsData(value2.SpawnsData);
115 if (!string.IsNullOrEmpty(text)) {
116 valuesDictionary3.SetValue("SpawnsData", text);
117 }
118 }
119 }
120 }
121
122 public override void OnEntityAdded(Entity entity) {
123 foreach (ComponentSpawn item in entity.FindComponents<ComponentSpawn>()) {
124 m_spawns.Add(item, true);
125 }
126 }
127
128 public override void OnEntityRemoved(Entity entity) {
129 foreach (ComponentSpawn item in entity.FindComponents<ComponentSpawn>()) {
130 m_spawns.Remove(item);
131 }
132 }
133
135 SpawnChunk spawnChunk = GetSpawnChunk(point);
136 if (spawnChunk == null) {
137 spawnChunk = new SpawnChunk { Point = point };
138 m_chunks.Add(point, spawnChunk);
139 }
140 return spawnChunk;
141 }
142
143 public virtual void DiscardOldChunks() {
144 List<Point2> list = new();
145 foreach (SpawnChunk value in m_chunks.Values) {
146 if (!value.LastVisitedTime.HasValue
147 || m_subsystemGameInfo.TotalElapsedGameTime - value.LastVisitedTime.Value > MaxChunkAge) {
148 list.Add(value.Point);
149 }
150 }
151 foreach (Point2 item in list) {
152 m_chunks.Remove(item);
153 }
154 }
155
156 public virtual void UpdateLastVisitedTime() {
157 foreach (ComponentPlayer componentPlayer in m_subsystemPlayers.ComponentPlayers) {
158 Vector2 v = new(componentPlayer.ComponentBody.Position.X, componentPlayer.ComponentBody.Position.Z);
159 Vector2 p = v - new Vector2(VisitedRadius);
160 Vector2 p2 = v + new Vector2(VisitedRadius);
161 Point2 point = Terrain.ToChunk(p);
162 Point2 point2 = Terrain.ToChunk(p2);
163 for (int i = point.X; i <= point2.X; i++) {
164 for (int j = point.Y; j <= point2.Y; j++) {
165 SpawnChunk spawnChunk = GetSpawnChunk(new Point2(i, j));
166 if (spawnChunk != null) {
167 spawnChunk.LastVisitedTime = m_subsystemGameInfo.TotalElapsedGameTime;
168 }
169 }
170 }
171 }
172 }
173
174 public virtual void SpawnChunks() {
175 //List<SpawnChunk> list = new();
176 foreach (GameWidget gameWidget in m_subsystemViews.GameWidgets) {
177 Vector2 v = new(gameWidget.ActiveCamera.ViewPosition.X, gameWidget.ActiveCamera.ViewPosition.Z);
178 Vector2 p = v - new Vector2(SpawnRadius);
179 Vector2 p2 = v + new Vector2(SpawnRadius);
180 Point2 point = Terrain.ToChunk(p);
181 Point2 point2 = Terrain.ToChunk(p2);
182 for (int i = point.X; i <= point2.X; i++) {
183 for (int j = point.Y; j <= point2.Y; j++) {
184 Vector2 v2 = new((i + 0.5f) * 16f, (j + 0.5f) * 16f);
186 TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(Terrain.ToCell(v2.X), Terrain.ToCell(v2.Y));
187 if (chunkAtCell != null
188 && chunkAtCell.State > TerrainChunkState.InvalidPropagatedLight) {
189 Point2 point3 = new(i, j);
190 SpawnChunk orCreateSpawnChunk = GetOrCreateSpawnChunk(point3);
191 foreach (SpawnEntityData spawnsDatum in orCreateSpawnChunk.SpawnsData) {
192 SpawnEntity(spawnsDatum);
193 }
194 orCreateSpawnChunk.SpawnsData.Clear();
195 SpawningChunk?.Invoke(orCreateSpawnChunk);
196 orCreateSpawnChunk.IsSpawned = true;
197 }
198 }
199 }
200 }
201 }
202 /*foreach (SpawnChunk item in list)
203 {
204 foreach (SpawnEntityData spawnsDatum2 in item.SpawnsData)
205 {
206 SpawnEntity(spawnsDatum2);
207 }
208 item.SpawnsData.Clear();
209 }*/
210 }
211
212 public virtual void DespawnChunks() {
213 List<ComponentSpawn> list = new(0);
214 foreach (ComponentSpawn key in m_spawns.Keys) {
215 if (key.AutoDespawn
216 && !key.IsDespawning) {
217 bool flag = true;
218 Vector3 position = key.ComponentFrame.Position;
219 Vector2 v = new(position.X, position.Z);
220 foreach (GameWidget gameWidget in m_subsystemViews.GameWidgets) {
221 Vector3 viewPosition = gameWidget.ActiveCamera.ViewPosition;
222 Vector2 v2 = new(viewPosition.X, viewPosition.Z);
224 flag = false;
225 break;
226 }
227 }
228 if (flag) {
229 list.Add(key);
230 }
231 }
232 }
233 foreach (ComponentSpawn item in list) {
235 SpawnEntityData data = new() {
236 TemplateName = item.Entity.ValuesDictionary.DatabaseObject.Name,
237 Position = item.ComponentFrame.Position,
238 ConstantSpawn = item.ComponentCreature?.ConstantSpawn ?? false,
239 Data = string.Empty,
240 EntityId = item.Entity.Id
241 };
243 "OnSaveSpawnData",
244 loader => {
245 loader.OnSaveSpawnData(item, data);
246 return true;
247 }
248 );
249 GetOrCreateSpawnChunk(point).SpawnsData.Add(data);
250 m_spawnEntityDatas[data.EntityId] = data;
251 item.Despawn();
252 }
253 }
254
255 public virtual Entity SpawnEntity(SpawnEntityData data) {
256 try {
258 Entity entity = Project.CreateEntity(valuesDictionary, data.EntityId);
260 "OnReadSpawnData",
261 loader => {
262 loader.OnReadSpawnData(entity, data);
263 return true;
264 }
265 );
266 entity.FindComponent<ComponentBody>(true).Position = data.Position;
269 m_random.Float(0f, (float)Math.PI * 2f)
270 );
271 ComponentCreature componentCreature = entity.FindComponent<ComponentCreature>();
272 if (componentCreature != null) {
273 componentCreature.ConstantSpawn = data.ConstantSpawn;
274 }
275 Project.AddEntity(entity);
276 return entity;
277 }
278 catch (Exception ex) {
279 Log.Error($"Unable to spawn entity with template \"{data.TemplateName}\". Reason: {ex}");
280 return null;
281 }
282 }
283
284 [Obsolete]
285 public virtual void LoadSpawnsData(ValuesDictionary loadData, List<SpawnEntityData> creaturesData) {
286 foreach ((ValuesDictionary item, SpawnEntityData data) in from ValuesDictionary item in loadData.Values
287 let data = new SpawnEntityData()
288 select (item, data)) {
289 data.ConstantSpawn = item.GetValue<bool>("c");
290 data.Position = item.GetValue<Vector3>("p");
291 data.TemplateName = item.GetValue<string>("n");
292 object obj = item.GetValue("d", new object());
293 data.Data = obj is string str ? str : string.Empty;
294 creaturesData.Add(data);
295 }
296 }
297
298 public virtual void LoadSpawnsData(string data, List<SpawnEntityData> creaturesData) {
299 string[] array = data.Split([';'], StringSplitOptions.RemoveEmptyEntries);
300 for (int i = 0; i < array.Length; i++) {
301 string[] array2 = array[i].Split(new[] { ',' });
302 if (array2.Length < 4) {
303 throw new InvalidOperationException("Invalid spawn data string.");
304 }
305 SpawnEntityData spawnEntityData = new() {
306 TemplateName = array2[0],
307 Position = new Vector3 {
308 X = float.Parse(array2[1], CultureInfo.InvariantCulture),
309 Y = float.Parse(array2[2], CultureInfo.InvariantCulture),
310 Z = float.Parse(array2[3], CultureInfo.InvariantCulture)
311 }
312 };
313 if (array2.Length >= 5) {
314 spawnEntityData.ConstantSpawn = bool.Parse(array2[4]);
315 }
316 spawnEntityData.Data = array2.Length >= 6 ? array2[5] : string.Empty;
317 if (array2.Length >= 7) {
318 spawnEntityData.EntityId = int.Parse(array2[6]);
319 }
320 creaturesData.Add(spawnEntityData);
321 m_spawnEntityDatas[spawnEntityData.EntityId] = spawnEntityData;
322 }
323 }
324
325 [Obsolete]
326 public virtual void SaveSpawnsData(ValuesDictionary saveData, List<SpawnEntityData> spawnsData) {
327 int i = 0;
328 foreach (SpawnEntityData d in spawnsData) {
329 ValuesDictionary v2 = [];
330 v2.SetValue("c", d.ConstantSpawn);
331 v2.SetValue("p", d.Position);
332 v2.SetValue("n", d.TemplateName);
333 v2.SetValue("d", d.Data);
334 saveData.SetValue($"{i++}", v2);
335 }
336 }
337
338 public virtual string SaveSpawnsData(List<SpawnEntityData> spawnsData) {
339 StringBuilder stringBuilder = new();
340 foreach (SpawnEntityData spawnEntityData in spawnsData) {
341 stringBuilder.Append(spawnEntityData.TemplateName);
342 stringBuilder.Append(',');
343 stringBuilder.Append((MathF.Round(spawnEntityData.Position.X * 10f) / 10f).ToString(CultureInfo.InvariantCulture));
344 stringBuilder.Append(',');
345 stringBuilder.Append((MathF.Round(spawnEntityData.Position.Y * 10f) / 10f).ToString(CultureInfo.InvariantCulture));
346 stringBuilder.Append(',');
347 stringBuilder.Append((MathF.Round(spawnEntityData.Position.Z * 10f) / 10f).ToString(CultureInfo.InvariantCulture));
348 stringBuilder.Append(',');
349 stringBuilder.Append(spawnEntityData.ConstantSpawn.ToString());
350 stringBuilder.Append(',');
351 if (spawnEntityData.Data?.Length > 0) {
352 stringBuilder.Append(spawnEntityData.Data);
353 }
354 stringBuilder.Append(',');
355 stringBuilder.Append(spawnEntityData.EntityId.ToString());
356 stringBuilder.Append(';');
357 }
358 return stringBuilder.ToString();
359 }
360 }
361}
static void Error(object message)
定义 Log.cs:80
static object ConvertFromString(Type type, string data)
Vector3 ViewPosition
ComponentCreature ComponentCreature
ComponentFrame ComponentFrame
static ValuesDictionary FindEntityValuesDictionary(string entityTemplateName, bool throwIfNotFound)
List< SpawnEntityData > SpawnsData
Dictionary< int, SpawnEntityData > m_spawnEntityDatas
virtual void Update(float dt)
virtual SpawnChunk GetSpawnChunk(Point2 point)
virtual void DiscardOldChunks()
virtual void SaveSpawnsData(ValuesDictionary saveData, List< SpawnEntityData > spawnsData)
virtual void UpdateLastVisitedTime()
virtual Entity SpawnEntity(SpawnEntityData data)
SubsystemGameInfo m_subsystemGameInfo
virtual void LoadSpawnsData(ValuesDictionary loadData, List< SpawnEntityData > creaturesData)
SubsystemTerrain m_subsystemTerrain
override void OnEntityRemoved(Entity entity)
Dictionary< ComponentSpawn, bool > m_spawns
override void Save(ValuesDictionary valuesDictionary)
virtual SpawnChunk GetOrCreateSpawnChunk(Point2 point)
Dictionary< ComponentSpawn, bool >.KeyCollection Spawns
SubsystemGameWidgets m_subsystemViews
virtual Action< SpawnChunk > SpawningChunk
SubsystemPlayers m_subsystemPlayers
override void Load(ValuesDictionary valuesDictionary)
Dictionary< Point2, SpawnChunk > m_chunks
override void OnEntityAdded(Entity entity)
virtual void LoadSpawnsData(string data, List< SpawnEntityData > creaturesData)
virtual string SaveSpawnsData(List< SpawnEntityData > spawnsData)
TerrainChunkState State
static Point2 ToChunk(Vector2 p)
static int ToCell(float x)
ValuesDictionary ValuesDictionary
Component FindComponent(Type type, string name, bool throwOnError)
ValuesDictionary ValuesDictionary
Camera ActiveCamera
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
static float DistanceSquared(Vector2 v1, Vector2 v2)
static readonly Vector3 UnitY