Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemElectricity.cs
浏览该文件的文档.
1using System.Diagnostics;
2using System.Globalization;
3using System.Text;
4using Engine;
7
8namespace Game {
11 new(0, 1, -1, 4, 4, 0),
12 new(0, 1, 0, 0, 4, 5),
13 new(0, 1, -1, 2, 4, 5),
14 new(0, 0, 0, 5, 4, 2),
15 new(-1, 0, -1, 3, 3, 0),
16 new(-1, 0, 0, 0, 3, 1),
17 new(-1, 0, -1, 2, 3, 1),
18 new(0, 0, 0, 1, 3, 2),
19 new(0, -1, -1, 5, 5, 0),
20 new(0, -1, 0, 0, 5, 4),
21 new(0, -1, -1, 2, 5, 4),
22 new(0, 0, 0, 4, 5, 2),
23 new(1, 0, -1, 1, 1, 0),
24 new(1, 0, 0, 0, 1, 3),
25 new(1, 0, -1, 2, 1, 3),
26 new(0, 0, 0, 3, 1, 2),
27 new(0, 0, -1, 2, 2, 0),
28 null,
29 null,
30 null,
31 new(-1, 1, 0, 4, 4, 1),
32 new(0, 1, 0, 1, 4, 5),
33 new(-1, 1, 0, 3, 4, 5),
34 new(0, 0, 0, 5, 4, 3),
35 new(-1, 0, 1, 0, 0, 1),
36 new(0, 0, 1, 1, 0, 2),
37 new(-1, 0, 1, 3, 0, 2),
38 new(0, 0, 0, 2, 0, 3),
39 new(-1, -1, 0, 5, 5, 1),
40 new(0, -1, 0, 1, 5, 4),
41 new(-1, -1, 0, 3, 5, 4),
42 new(0, 0, 0, 4, 5, 3),
43 new(-1, 0, -1, 2, 2, 1),
44 new(0, 0, -1, 1, 2, 0),
45 new(-1, 0, -1, 3, 2, 0),
46 new(0, 0, 0, 0, 2, 3),
47 new(-1, 0, 0, 3, 3, 1),
48 null,
49 null,
50 null,
51 new(0, 1, 1, 4, 4, 2),
52 new(0, 1, 0, 2, 4, 5),
53 new(0, 1, 1, 0, 4, 5),
54 new(0, 0, 0, 5, 4, 0),
55 new(1, 0, 1, 1, 1, 2),
56 new(1, 0, 0, 2, 1, 3),
57 new(1, 0, 1, 0, 1, 3),
58 new(0, 0, 0, 3, 1, 0),
59 new(0, -1, 1, 5, 5, 2),
60 new(0, -1, 0, 2, 5, 4),
61 new(0, -1, 1, 0, 5, 4),
62 new(0, 0, 0, 4, 5, 0),
63 new(-1, 0, 1, 3, 3, 2),
64 new(-1, 0, 0, 2, 3, 1),
65 new(-1, 0, 1, 0, 3, 1),
66 new(0, 0, 0, 1, 3, 0),
67 new(0, 0, 1, 0, 0, 2),
68 null,
69 null,
70 null,
71 new(1, 1, 0, 4, 4, 3),
72 new(0, 1, 0, 3, 4, 5),
73 new(1, 1, 0, 1, 4, 5),
74 new(0, 0, 0, 5, 4, 1),
75 new(1, 0, -1, 2, 2, 3),
76 new(0, 0, -1, 3, 2, 0),
77 new(1, 0, -1, 1, 2, 0),
78 new(0, 0, 0, 0, 2, 1),
79 new(1, -1, 0, 5, 5, 3),
80 new(0, -1, 0, 3, 5, 4),
81 new(1, -1, 0, 1, 5, 4),
82 new(0, 0, 0, 4, 5, 1),
83 new(1, 0, 1, 0, 0, 3),
84 new(0, 0, 1, 3, 0, 2),
85 new(1, 0, 1, 1, 0, 2),
86 new(0, 0, 0, 2, 0, 1),
87 new(1, 0, 0, 1, 1, 3),
88 null,
89 null,
90 null,
91 new(0, -1, -1, 2, 2, 4),
92 new(0, 0, -1, 4, 2, 0),
93 new(0, -1, -1, 5, 2, 0),
94 new(0, 0, 0, 0, 2, 5),
95 new(-1, -1, 0, 3, 3, 4),
96 new(-1, 0, 0, 4, 3, 1),
97 new(-1, -1, 0, 5, 3, 1),
98 new(0, 0, 0, 1, 3, 5),
99 new(0, -1, 1, 0, 0, 4),
100 new(0, 0, 1, 4, 0, 2),
101 new(0, -1, 1, 5, 0, 2),
102 new(0, 0, 0, 2, 0, 5),
103 new(1, -1, 0, 1, 1, 4),
104 new(1, 0, 0, 4, 1, 3),
105 new(1, -1, 0, 5, 1, 3),
106 new(0, 0, 0, 3, 1, 5),
107 new(0, -1, 0, 5, 5, 4),
108 null,
109 null,
110 null,
111 new(0, 1, -1, 2, 2, 5),
112 new(0, 0, -1, 5, 2, 0),
113 new(0, 1, -1, 4, 2, 0),
114 new(0, 0, 0, 0, 2, 4),
115 new(1, 1, 0, 1, 1, 5),
116 new(1, 0, 0, 5, 1, 3),
117 new(1, 1, 0, 4, 1, 3),
118 new(0, 0, 0, 3, 1, 4),
119 new(0, 1, 1, 0, 0, 5),
120 new(0, 0, 1, 5, 0, 2),
121 new(0, 1, 1, 4, 0, 2),
122 new(0, 0, 0, 2, 0, 4),
123 new(-1, 1, 0, 3, 3, 5),
124 new(-1, 0, 0, 5, 3, 1),
125 new(-1, 1, 0, 4, 3, 1),
126 new(0, 0, 0, 1, 3, 4),
127 new(0, 1, 0, 4, 4, 5),
128 null,
129 null,
130 null
131 ];
132
134 null,
141 null,
148 null,
155 null,
162 null,
169 null
170 ];
171
172 public static int[] m_connectorFacesTable = [
173 4,
174 3,
175 5,
176 1,
177 2,
178 4,
179 0,
180 5,
181 2,
182 3,
183 4,
184 1,
185 5,
186 3,
187 0,
188 4,
189 2,
190 5,
191 0,
192 1,
193 2,
194 1,
195 0,
196 3,
197 5,
198 0,
199 1,
200 2,
201 3,
202 4
203 ];
204
206
207 public Dictionary<Point3, float> m_persistentElementsVoltages = [];
208
209 public Dictionary<ElectricElement, bool> m_electricElements = [];
210
211 public Dictionary<CellFace, ElectricElement> m_electricElementsByCellFace = [];
212
213 public Dictionary<Point3, bool> m_pointsToUpdate = [];
214
215 public Dictionary<Point3, ElectricElement> m_electricElementsToAdd = [];
216
217 public Dictionary<ElectricElement, bool> m_electricElementsToRemove = [];
218
219 public Dictionary<Point3, bool> m_wiresToUpdate = [];
220
221 public List<Dictionary<ElectricElement, bool>> m_listsCache = [];
222
223 public Dictionary<int, Dictionary<ElectricElement, bool>> m_futureSimulateLists = [];
224
225 public Dictionary<ElectricElement, bool> m_nextStepSimulateList;
226
227 public DynamicArray<ElectricConnectionPath> m_tmpConnectionPaths = [];
228
229 public Dictionary<CellFace, bool> m_tmpVisited = [];
230
231 public Dictionary<CellFace, bool> m_tmpResult = [];
232
233 public static bool DebugDrawElectrics = false;
234
235 public static int SimulatedElectricElements;
236
237 public const float CircuitStepDuration = 0.01f;
238
239 public Dictionary<Type, DebugInfo> m_debugInfos = [];
240 public Stopwatch m_debugStopwatch = new();
241 public bool UpdateTimeDebug = false;
242
243 public SubsystemTime SubsystemTime { get; set; }
244
246
247 public SubsystemAudio SubsystemAudio { get; set; }
248
249 public int FrameStartCircuitStep { get; set; }
250
251 public int CircuitStep { get; set; }
252
254
255 public void OnElectricElementBlockGenerated(int x, int y, int z) {
256 m_pointsToUpdate[new Point3(x, y, z)] = false;
257 }
258
259 public void OnElectricElementBlockAdded(int x, int y, int z) {
260 m_pointsToUpdate[new Point3(x, y, z)] = true;
261 }
262
263 public void OnElectricElementBlockRemoved(int x, int y, int z) {
264 m_pointsToUpdate[new Point3(x, y, z)] = true;
265 }
266
267 public void OnElectricElementBlockModified(int x, int y, int z) {
268 m_pointsToUpdate[new Point3(x, y, z)] = true;
269 }
270
271 public void OnChunkDiscarding(TerrainChunk chunk) {
272 foreach (CellFace key in m_electricElementsByCellFace.Keys) {
273 if (key.X >= chunk.Origin.X
274 && key.X < chunk.Origin.X + 16
275 && key.Z >= chunk.Origin.Y
276 && key.Z < chunk.Origin.Y + 16) {
277 m_pointsToUpdate[new Point3(key.X, key.Y, key.Z)] = false;
278 }
279 }
280 }
281
282 public static ElectricConnectorDirection? GetConnectorDirection(int mountingFace, int rotation, int connectorFace) {
283 ElectricConnectorDirection? result = m_connectorDirectionsTable[6 * mountingFace + connectorFace];
284 if (result.HasValue) {
285 if (result.Value < ElectricConnectorDirection.In) {
286 return (ElectricConnectorDirection)((int)(result.Value + rotation) % 4);
287 }
288 return result;
289 }
290 return null;
291 }
292
293 public static int GetConnectorFace(int mountingFace, ElectricConnectorDirection connectionDirection) =>
294 m_connectorFacesTable[(int)(5 * mountingFace + connectionDirection)];
295
296 public void GetAllConnectedNeighbors(int x, int y, int z, int mountingFace, DynamicArray<ElectricConnectionPath> list) {
297 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x, y, z);
298 if (BlocksManager.Blocks[Terrain.ExtractContents(cellValue)] is not IElectricElementBlock electricElementBlock) {
299 return;
300 }
301 for (ElectricConnectorDirection electricConnectorDirection = ElectricConnectorDirection.Top;
302 electricConnectorDirection < (ElectricConnectorDirection)5;
303 electricConnectorDirection++) {
304 for (int i = 0; i < 4; i++) {
305 ElectricConnectionPath electricConnectionPath =
306 m_connectionPathsTable[20 * mountingFace + 4 * (int)electricConnectorDirection + i];
307 if (electricConnectionPath == null) {
308 break;
309 }
310 ElectricConnectorType? connectorType = electricElementBlock.GetConnectorType(
312 cellValue,
313 mountingFace,
314 electricConnectionPath.ConnectorFace,
315 x,
316 y,
317 z
318 );
319 if (!connectorType.HasValue) {
320 break;
321 }
322 int x2 = x + electricConnectionPath.NeighborOffsetX;
323 int y2 = y + electricConnectionPath.NeighborOffsetY;
324 int z2 = z + electricConnectionPath.NeighborOffsetZ;
325 int cellValue2 = SubsystemTerrain.Terrain.GetCellValue(x2, y2, z2);
327 if (electricElementBlock2 == null) {
328 continue;
329 }
330 ElectricConnectorType? connectorType2 = electricElementBlock2.GetConnectorType(
332 cellValue2,
333 electricConnectionPath.NeighborFace,
334 electricConnectionPath.NeighborConnectorFace,
335 x2,
336 y2,
337 z2
338 );
339 if (connectorType2.HasValue
340 && ((connectorType.Value != 0 && connectorType2.Value != ElectricConnectorType.Output)
341 || (connectorType.Value != ElectricConnectorType.Output && connectorType2.Value != 0))) {
342 int connectionMask = electricElementBlock.GetConnectionMask(cellValue);
343 int connectionMask2 = electricElementBlock2.GetConnectionMask(cellValue2);
344 if ((connectionMask & connectionMask2) != 0) {
345 list.Add(electricConnectionPath);
346 }
347 }
348 }
349 }
350 }
351
352 public ElectricElement GetElectricElement(int x, int y, int z, int mountingFace) {
353 m_electricElementsByCellFace.TryGetValue(new CellFace(x, y, z, mountingFace), out ElectricElement value);
354 return value;
355 }
356
357 public void QueueElectricElementForSimulation(ElectricElement electricElement, int circuitStep) {
358 if (circuitStep == CircuitStep + 1) {
359 if (m_nextStepSimulateList == null
360 && !m_futureSimulateLists.TryGetValue(CircuitStep + 1, out m_nextStepSimulateList)) {
363 }
364 m_nextStepSimulateList[electricElement] = true;
365 }
366 else if (circuitStep > CircuitStep + 1) {
367 if (!m_futureSimulateLists.TryGetValue(circuitStep, out Dictionary<ElectricElement, bool> value)) {
368 value = GetListFromCache();
369 m_futureSimulateLists.Add(circuitStep, value);
370 }
371 value[electricElement] = true;
372 }
373 }
374
375 public void QueueElectricElementConnectionsForSimulation(ElectricElement electricElement, int circuitStep) {
376 foreach (ElectricConnection connection in electricElement.Connections) {
377 if (connection.ConnectorType != 0
378 && connection.NeighborConnectorType != ElectricConnectorType.Output) {
380 }
381 }
382 }
383
384 public float? ReadPersistentVoltage(Point3 point) {
385 if (m_persistentElementsVoltages.TryGetValue(point, out float value)) {
386 return value;
387 }
388 return null;
389 }
390
391 public void WritePersistentVoltage(Point3 point, float voltage) {
392 m_persistentElementsVoltages[point] = voltage;
393 }
394
395 public virtual void Update(float dt) {
399 while (m_remainingSimulationTime >= 0.01f) {
401 ++CircuitStep;
404 if (m_futureSimulateLists.Remove(CircuitStep, out Dictionary<ElectricElement, bool> value)) {
405 SimulatedElectricElements += value.Count;
406 if (UpdateTimeDebug) {
407 m_debugStopwatch.Start();
408 }
409 foreach (ElectricElement key in value.Keys) {
410 if (m_electricElements.ContainsKey(key)) {
411 long startTick = UpdateTimeDebug ? m_debugStopwatch.ElapsedTicks : 0;
412 Type type = key.GetType();
413 try {
415 }
416 catch (Exception e) {
417#if DEBUG
418 Console.WriteLine($"Error in simulating {type.Name}: {e}");
419#endif
420 throw;
421 }
422 finally {
423 if (UpdateTimeDebug) {
424 long ticksCosted = m_debugStopwatch.ElapsedTicks - startTick;
425 if (!m_debugInfos.TryGetValue(type, out DebugInfo info)) {
426 info = new DebugInfo();
427 m_debugInfos.Add(type, info);
428 }
429 info.Counter++;
430 info.TotalTicksCosted += ticksCosted;
431 if (ticksCosted > info.MaxTicksCosted1) {
432 info.MaxTicksCosted1 = ticksCosted;
433 }
434 else if (ticksCosted > info.MaxTicksCosted2) {
435 info.MaxTicksCosted2 = ticksCosted;
436 }
437 }
438 }
439 }
440 }
441 if (UpdateTimeDebug) {
442 m_debugStopwatch.Reset();
443 }
444 ReturnListToCache(value);
445 }
446 }
447 if (DebugDrawElectrics) {
448 DebugDraw();
449 }
450 }
451
452 public override void Load(ValuesDictionary valuesDictionary) {
453 SubsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
454 SubsystemTime = Project.FindSubsystem<SubsystemTime>(true);
455 SubsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
456 string[] array = valuesDictionary.GetValue<string>("VoltagesByCell").Split([';'], StringSplitOptions.RemoveEmptyEntries);
457 int num = 0;
458 while (true) {
459 if (num < array.Length) {
460 string[] array2 = array[num].Split([","], StringSplitOptions.None);
461 if (array2.Length != 4) {
462 break;
463 }
464 int x = int.Parse(array2[0], CultureInfo.InvariantCulture);
465 int y = int.Parse(array2[1], CultureInfo.InvariantCulture);
466 int z = int.Parse(array2[2], CultureInfo.InvariantCulture);
467 float value = float.Parse(array2[3], CultureInfo.InvariantCulture);
468 m_persistentElementsVoltages[new Point3(x, y, z)] = value;
469 num++;
470 continue;
471 }
472 return;
473 }
474 throw new InvalidOperationException("Invalid number of tokens.");
475 }
476
477 public override void Save(ValuesDictionary valuesDictionary) {
478 int num = 0;
479 StringBuilder stringBuilder = new();
480 foreach (KeyValuePair<Point3, float> persistentElementsVoltage in m_persistentElementsVoltages) {
481 if (num > 500) {
482 break;
483 }
484 stringBuilder.Append(persistentElementsVoltage.Key.X.ToString(CultureInfo.InvariantCulture));
485 stringBuilder.Append(',');
486 stringBuilder.Append(persistentElementsVoltage.Key.Y.ToString(CultureInfo.InvariantCulture));
487 stringBuilder.Append(',');
488 stringBuilder.Append(persistentElementsVoltage.Key.Z.ToString(CultureInfo.InvariantCulture));
489 stringBuilder.Append(',');
490 stringBuilder.Append(persistentElementsVoltage.Value.ToString(CultureInfo.InvariantCulture));
491 stringBuilder.Append(';');
492 num++;
493 }
494 valuesDictionary.SetValue("VoltagesByCell", stringBuilder.ToString());
495 if (UpdateTimeDebug) {
496 int maxTypeNameLength = 1;
497 if (m_debugInfos.Keys.Count > 0) {
498 maxTypeNameLength = m_debugInfos.Keys.Max(type => type.FullName?.Length ?? 0) + 1;
499 }
500 StringBuilder stringBuilder2 = new();
501 stringBuilder2.AppendLine("====== SubsystemElectricity Performance Analyze ======");
502 stringBuilder2.Append("TypeName".PadRight(maxTypeNameLength));
503 stringBuilder2.Append(" Counter TotalTime AverageTime MaxTime1 MaxTime2");
504 foreach ((Type type, DebugInfo info) in m_debugInfos.OrderByDescending(pair => pair.Value.TotalTicksCosted)) {
505 stringBuilder2.AppendLine();
506 stringBuilder2.Append(type.FullName?.PadRight(maxTypeNameLength));
507 stringBuilder2.Append(info.Counter.ToString().PadLeft(11));
508 stringBuilder2.Append($"{(float)info.TotalTicksCosted / Stopwatch.Frequency * 1000:F}ms".PadLeft(12));
509 stringBuilder2.Append($"{(float)info.TotalTicksCosted / info.Counter / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
510 stringBuilder2.Append($"{(float)info.MaxTicksCosted1 / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
511 stringBuilder2.Append($"{(float)info.MaxTicksCosted2 / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
512 }
513 Log.Information(stringBuilder2.ToString());
514 m_debugInfos.Clear();
515 }
516 }
517
518 public static ElectricConnectionPath GetConnectionPath(int mountingFace, ElectricConnectorDirection localConnector, int neighborIndex) =>
519 m_connectionPathsTable[16 * mountingFace + 4 * (int)localConnector + neighborIndex];
520
521 public void SimulateElectricElement(ElectricElement electricElement) {
522 if (electricElement.Simulate()) {
524 }
525 }
526
527 public void AddElectricElement(ElectricElement electricElement) {
528 m_electricElements.Add(electricElement, true);
529 foreach (CellFace cellFace2 in electricElement.CellFaces) {
530 m_electricElementsByCellFace.Add(cellFace2, electricElement);
531 m_tmpConnectionPaths.Clear();
532 GetAllConnectedNeighbors(cellFace2.X, cellFace2.Y, cellFace2.Z, cellFace2.Face, m_tmpConnectionPaths);
533 foreach (ElectricConnectionPath tmpConnectionPath in m_tmpConnectionPaths) {
534 CellFace cellFace = new(
535 cellFace2.X + tmpConnectionPath.NeighborOffsetX,
536 cellFace2.Y + tmpConnectionPath.NeighborOffsetY,
537 cellFace2.Z + tmpConnectionPath.NeighborOffsetZ,
538 tmpConnectionPath.NeighborFace
539 );
540 if (m_electricElementsByCellFace.TryGetValue(cellFace, out ElectricElement value)
541 && value != electricElement) {
542 int cellValue = SubsystemTerrain.Terrain.GetCellValue(cellFace2.X, cellFace2.Y, cellFace2.Z);
543 int num = Terrain.ExtractContents(cellValue);
544 ElectricConnectorType value2 = ((IElectricElementBlock)BlocksManager.Blocks[num]).GetConnectorType(
546 cellValue,
547 cellFace2.Face,
548 tmpConnectionPath.ConnectorFace,
549 cellFace2.X,
550 cellFace2.Y,
551 cellFace2.Z
552 )!.Value;
553 int cellValue2 = SubsystemTerrain.Terrain.GetCellValue(cellFace.X, cellFace.Y, cellFace.Z);
554 int num2 = Terrain.ExtractContents(cellValue2);
555 ElectricConnectorType value3 = ((IElectricElementBlock)BlocksManager.Blocks[num2]).GetConnectorType(
557 cellValue2,
558 cellFace.Face,
559 tmpConnectionPath.NeighborConnectorFace,
560 cellFace.X,
561 cellFace.Y,
562 cellFace.Z
563 )!.Value;
564 electricElement.Connections.Add(
566 CellFace = cellFace2,
567 ConnectorFace = tmpConnectionPath.ConnectorFace,
568 ConnectorType = value2,
569 NeighborElectricElement = value,
570 NeighborCellFace = cellFace,
571 NeighborConnectorFace = tmpConnectionPath.NeighborConnectorFace,
572 NeighborConnectorType = value3
573 }
574 );
575 value.Connections.Add(
577 CellFace = cellFace,
578 ConnectorFace = tmpConnectionPath.NeighborConnectorFace,
579 ConnectorType = value3,
580 NeighborElectricElement = electricElement,
581 NeighborCellFace = cellFace2,
582 NeighborConnectorFace = tmpConnectionPath.ConnectorFace,
583 NeighborConnectorType = value2
584 }
585 );
586 }
587 }
588 }
591 electricElement.OnAdded();
592 }
593
594 public void RemoveElectricElement(ElectricElement electricElement) {
595 electricElement.OnRemoved();
597 m_electricElements.Remove(electricElement);
598 foreach (CellFace cellFace in electricElement.CellFaces) {
599 m_electricElementsByCellFace.Remove(cellFace);
600 }
601 foreach (ElectricConnection connection in electricElement.Connections) {
602 int num = connection.NeighborElectricElement.Connections.FirstIndex(c => c.NeighborElectricElement == electricElement);
603 if (num >= 0) {
604 connection.NeighborElectricElement.Connections.RemoveAt(num);
605 }
606 }
607 }
608
609 public virtual void UpdateElectricElements() {
610 foreach (KeyValuePair<Point3, bool> item in m_pointsToUpdate) {
611 Point3 key = item.Key;
612 int cellValue = SubsystemTerrain.Terrain.GetCellValue(key.X, key.Y, key.Z);
613 for (int i = 0; i < 6; i++) {
614 ElectricElement electricElement = GetElectricElement(key.X, key.Y, key.Z, i);
615 if (electricElement != null) {
616 if (electricElement is WireDomainElectricElement) {
617 m_wiresToUpdate[key] = true;
618 }
619 else {
620 m_electricElementsToRemove[electricElement] = true;
621 }
622 }
623 }
624 if (item.Value) {
626 }
627 int num = Terrain.ExtractContents(cellValue);
629 m_wiresToUpdate[key] = true;
630 }
631 else {
632 if (BlocksManager.Blocks[num] is IElectricElementBlock electricElementBlock) {
633 ElectricElement electricElement2 = electricElementBlock.CreateElectricElement(this, cellValue, key.X, key.Y, key.Z);
634 if (electricElement2 != null) {
635 m_electricElementsToAdd[key] = electricElement2;
636 }
637 }
638 }
639 }
641 foreach (KeyValuePair<ElectricElement, bool> item2 in m_electricElementsToRemove) {
642 RemoveElectricElement(item2.Key);
643 }
645 foreach (ElectricElement value in m_electricElementsToAdd.Values) {
646 AddElectricElement(value);
647 }
648 m_pointsToUpdate.Clear();
649 m_wiresToUpdate.Clear();
652 }
653
654 public void AddWireDomains() {
655 m_tmpVisited.Clear();
656 foreach (Point3 key in m_wiresToUpdate.Keys) {
657 for (int i = key.X - 1; i <= key.X + 1; i++) {
658 for (int j = key.Y - 1; j <= key.Y + 1; j++) {
659 for (int k = key.Z - 1; k <= key.Z + 1; k++) {
660 for (int l = 0; l < 6; l++) {
661 m_tmpResult.Clear();
663 if (m_tmpResult.Count > 0) {
664 WireDomainElectricElement electricElement = new(this, m_tmpResult.Keys);
665 AddElectricElement(electricElement);
666 }
667 }
668 }
669 }
670 }
671 }
672 }
673
674 public void RemoveWireDomains() {
675 foreach (Point3 key in m_wiresToUpdate.Keys) {
676 for (int i = key.X - 1; i <= key.X + 1; i++) {
677 for (int j = key.Y - 1; j <= key.Y + 1; j++) {
678 for (int k = key.Z - 1; k <= key.Z + 1; k++) {
679 for (int l = 0; l < 6; l++) {
680 if (m_electricElementsByCellFace.TryGetValue(new CellFace(i, j, k, l), out ElectricElement value)
681 && value is WireDomainElectricElement) {
683 }
684 }
685 }
686 }
687 }
688 }
689 }
690
691 public void ScanWireDomain(CellFace startCellFace, Dictionary<CellFace, bool> visited, Dictionary<CellFace, bool> result) {
692 DynamicArray<CellFace> dynamicArray = [startCellFace];
693 while (dynamicArray.Count > 0) {
694 CellFace key = dynamicArray.Array[--dynamicArray.Count];
695 if (visited.ContainsKey(key)) {
696 continue;
697 }
698 TerrainChunk chunkAtCell = SubsystemTerrain.Terrain.GetChunkAtCell(key.X, key.Z);
699 if (chunkAtCell == null
700 || !chunkAtCell.AreBehaviorsNotified) {
701 continue;
702 }
703 int cellValue = SubsystemTerrain.Terrain.GetCellValue(key.X, key.Y, key.Z);
704 int num = Terrain.ExtractContents(cellValue);
705 if (BlocksManager.Blocks[num] is not IElectricWireElementBlock electricWireElementBlock) {
706 continue;
707 }
708 int connectedWireFacesMask = electricWireElementBlock.GetConnectedWireFacesMask(cellValue, key.Face);
709 if (connectedWireFacesMask == 0) {
710 continue;
711 }
712 for (int i = 0; i < 6; i++) {
713 if ((connectedWireFacesMask & (1 << i)) != 0) {
714 CellFace key2 = new(key.X, key.Y, key.Z, i);
715 visited.Add(key2, true);
716 result.Add(key2, true);
717 m_tmpConnectionPaths.Clear();
718 GetAllConnectedNeighbors(key2.X, key2.Y, key2.Z, key2.Face, m_tmpConnectionPaths);
719 foreach (ElectricConnectionPath tmpConnectionPath in m_tmpConnectionPaths) {
720 int x = key2.X + tmpConnectionPath.NeighborOffsetX;
721 int y = key2.Y + tmpConnectionPath.NeighborOffsetY;
722 int z = key2.Z + tmpConnectionPath.NeighborOffsetZ;
723 dynamicArray.Add(new CellFace(x, y, z, tmpConnectionPath.NeighborFace));
724 }
725 }
726 }
727 }
728 }
729
730 public Dictionary<ElectricElement, bool> GetListFromCache() {
731 if (m_listsCache.Count > 0) {
732 Dictionary<ElectricElement, bool> result = m_listsCache[^1];
733 m_listsCache.RemoveAt(m_listsCache.Count - 1);
734 return result;
735 }
736 return [];
737 }
738
739 public void ReturnListToCache(Dictionary<ElectricElement, bool> list) {
740 list.Clear();
741 m_listsCache.Add(list);
742 }
743
744 public void DebugDraw() { }
745 }
746}
static void Information(object message)
定义 Log.cs:56
static int Min(int x1, int x2)
ElectricConnectorType ConnectorType
ElectricConnectorType NeighborConnectorType
List< ElectricConnection > Connections
void AddElectricElement(ElectricElement electricElement)
Dictionary< ElectricElement, bool > m_nextStepSimulateList
static ElectricConnectionPath[] m_connectionPathsTable
override void Load(ValuesDictionary valuesDictionary)
DynamicArray< ElectricConnectionPath > m_tmpConnectionPaths
Dictionary< CellFace, bool > m_tmpResult
void QueueElectricElementConnectionsForSimulation(ElectricElement electricElement, int circuitStep)
override void Save(ValuesDictionary valuesDictionary)
Dictionary< Point3, bool > m_wiresToUpdate
Dictionary< int, Dictionary< ElectricElement, bool > > m_futureSimulateLists
static ? ElectricConnectorDirection GetConnectorDirection(int mountingFace, int rotation, int connectorFace)
void OnElectricElementBlockModified(int x, int y, int z)
void ReturnListToCache(Dictionary< ElectricElement, bool > list)
void RemoveElectricElement(ElectricElement electricElement)
void OnElectricElementBlockRemoved(int x, int y, int z)
void ScanWireDomain(CellFace startCellFace, Dictionary< CellFace, bool > visited, Dictionary< CellFace, bool > result)
Dictionary< ElectricElement, bool > GetListFromCache()
Dictionary< Point3, ElectricElement > m_electricElementsToAdd
void WritePersistentVoltage(Point3 point, float voltage)
void OnElectricElementBlockGenerated(int x, int y, int z)
void OnElectricElementBlockAdded(int x, int y, int z)
Dictionary< Point3, bool > m_pointsToUpdate
Dictionary< CellFace, bool > m_tmpVisited
void GetAllConnectedNeighbors(int x, int y, int z, int mountingFace, DynamicArray< ElectricConnectionPath > list)
static ? ElectricConnectorDirection[] m_connectorDirectionsTable
Dictionary< Point3, float > m_persistentElementsVoltages
Dictionary< Type, DebugInfo > m_debugInfos
static ElectricConnectionPath GetConnectionPath(int mountingFace, ElectricConnectorDirection localConnector, int neighborIndex)
Dictionary< CellFace, ElectricElement > m_electricElementsByCellFace
Dictionary< ElectricElement, bool > m_electricElementsToRemove
List< Dictionary< ElectricElement, bool > > m_listsCache
void QueueElectricElementForSimulation(ElectricElement electricElement, int circuitStep)
static int GetConnectorFace(int mountingFace, ElectricConnectorDirection connectionDirection)
ElectricElement GetElectricElement(int x, int y, int z, int mountingFace)
void OnChunkDiscarding(TerrainChunk chunk)
void SimulateElectricElement(ElectricElement electricElement)
Dictionary< ElectricElement, bool > m_electricElements
static int ExtractContents(int value)
ValuesDictionary ValuesDictionary
int GetConnectionMask(int value)
ElectricConnectorType? GetConnectorType(SubsystemTerrain terrain, int value, int face, int connectorFace, int x, int y, int z)