1using System.Diagnostics;
2using System.Globalization;
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),
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),
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),
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),
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),
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),
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) {
284 if (result.HasValue) {
303 electricConnectorDirection++) {
304 for (
int i = 0; i < 4; i++) {
307 if (electricConnectionPath ==
null) {
319 if (!connectorType.HasValue) {
327 if (electricElementBlock2 ==
null) {
339 if (connectorType2.HasValue
342 int connectionMask = electricElementBlock.GetConnectionMask(cellValue);
344 if ((connectionMask & connectionMask2) != 0) {
345 list.
Add(electricConnectionPath);
371 value[electricElement] =
true;
412 Type type = key.GetType();
416 catch (Exception e) {
418 Console.WriteLine($
"Error in simulating {type.Name}: {e}");
424 long ticksCosted = m_debugStopwatch.ElapsedTicks - startTick;
430 info.TotalTicksCosted += ticksCosted;
431 if (ticksCosted > info.MaxTicksCosted1) {
432 info.MaxTicksCosted1 = ticksCosted;
434 else if (ticksCosted > info.MaxTicksCosted2) {
435 info.MaxTicksCosted2 = ticksCosted;
456 string[] array = valuesDictionary.GetValue<
string>(
"VoltagesByCell").Split([
';'], StringSplitOptions.RemoveEmptyEntries);
459 if (num < array.Length) {
460 string[] array2 = array[num].Split([
","], StringSplitOptions.None);
461 if (array2.Length != 4) {
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);
474 throw new InvalidOperationException(
"Invalid number of tokens.");
479 StringBuilder stringBuilder =
new();
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(
';');
494 valuesDictionary.SetValue(
"VoltagesByCell", stringBuilder.ToString());
496 int maxTypeNameLength = 1;
498 maxTypeNameLength =
m_debugInfos.Keys.Max(type => type.FullName?.Length ?? 0) + 1;
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));
529 foreach (
CellFace cellFace2
in electricElement.CellFaces) {
538 tmpConnectionPath.NeighborFace
541 && value != electricElement) {
542 int cellValue =
SubsystemTerrain.Terrain.GetCellValue(cellFace2.
X, cellFace2.
Y, cellFace2.
Z);
553 int cellValue2 =
SubsystemTerrain.Terrain.GetCellValue(cellFace.
X, cellFace.
Y, cellFace.
Z);
564 electricElement.Connections.Add(
568 ConnectorType = value2,
569 NeighborElectricElement = value,
570 NeighborCellFace = cellFace,
572 NeighborConnectorType = value3
575 value.Connections.Add(
579 ConnectorType = value3,
580 NeighborElectricElement = electricElement,
581 NeighborCellFace = cellFace2,
583 NeighborConnectorType = value2
591 electricElement.OnAdded();
598 foreach (
CellFace cellFace
in electricElement.CellFaces) {
613 for (
int i = 0; i < 6; i++) {
615 if (electricElement !=
null) {
633 ElectricElement electricElement2 = electricElementBlock.CreateElectricElement(
this, cellValue, key.
X, key.
Y, key.
Z);
634 if (electricElement2 !=
null) {
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++) {
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++) {
691 public void ScanWireDomain(
CellFace startCellFace, Dictionary<CellFace, bool> visited, Dictionary<CellFace, bool> result) {
692 DynamicArray<CellFace> dynamicArray = [startCellFace];
693 while (dynamicArray.
Count > 0) {
695 if (visited.ContainsKey(key)) {
699 if (chunkAtCell ==
null
708 int connectedWireFacesMask = electricWireElementBlock.GetConnectedWireFacesMask(cellValue, key.
Face);
709 if (connectedWireFacesMask == 0) {
712 for (
int i = 0; i < 6; i++) {
713 if ((connectedWireFacesMask & (1 << i)) != 0) {
715 visited.Add(key2,
true);
716 result.Add(key2,
true);
732 Dictionary<ElectricElement, bool> result =
m_listsCache[^1];
static void Information(object message)
static int Min(int x1, int x2)
ElectricElement NeighborElectricElement
ElectricConnectorType ConnectorType
ElectricConnectorType NeighborConnectorType
readonly int ConnectorFace
readonly int NeighborOffsetY
readonly int NeighborOffsetZ
readonly int NeighborOffsetX
readonly int NeighborConnectorFace
readonly int NeighborFace
List< ElectricConnection > Connections
SubsystemAudio SubsystemAudio
void AddElectricElement(ElectricElement electricElement)
Dictionary< ElectricElement, bool > m_nextStepSimulateList
static ElectricConnectionPath[] m_connectionPathsTable
override void Load(ValuesDictionary valuesDictionary)
static int[] m_connectorFacesTable
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)
static int SimulatedElectricElements
virtual void UpdateElectricElements()
void OnElectricElementBlockRemoved(int x, int y, int z)
Stopwatch m_debugStopwatch
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)
static bool DebugDrawElectrics
SubsystemTime SubsystemTime
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
float? ReadPersistentVoltage(Point3 point)
static ElectricConnectionPath GetConnectionPath(int mountingFace, ElectricConnectorDirection localConnector, int neighborIndex)
Dictionary< CellFace, ElectricElement > m_electricElementsByCellFace
Dictionary< ElectricElement, bool > m_electricElementsToRemove
float m_remainingSimulationTime
List< Dictionary< ElectricElement, bool > > m_listsCache
int FrameStartCircuitStep
SubsystemTerrain SubsystemTerrain
void QueueElectricElementForSimulation(ElectricElement electricElement, int circuitStep)
static int GetConnectorFace(int mountingFace, ElectricConnectorDirection connectionDirection)
const float CircuitStepDuration
virtual void Update(float dt)
ElectricElement GetElectricElement(int x, int y, int z, int mountingFace)
void OnChunkDiscarding(TerrainChunk chunk)
void SimulateElectricElement(ElectricElement electricElement)
Dictionary< ElectricElement, bool > m_electricElements
bool AreBehaviorsNotified
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)
ElectricConnectorDirection