Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemUpdate.cs
浏览该文件的文档.
1using System.Diagnostics;
2using System.Text;
3using Engine;
6
7namespace Game {
8 public class SubsystemUpdate : Subsystem {
9 public class UpdateableInfo {
10 public float FloatUpdateOrder;
11 }
12
13 public class Comparer : IComparer<IUpdateable> {
14 public static Comparer Instance = new();
15
16 public int Compare(IUpdateable u1, IUpdateable u2) {
17 float num = u1.FloatUpdateOrder - u2.FloatUpdateOrder;
18 if (num != 0) {
19 return Math.Sign(num);
20 }
21 return u1.GetHashCode() - u2.GetHashCode();
22 }
23 }
24
26
27 public float DefaultFixedTimeStep => m_subsystemTime.DefaultFixedTimeStep;
28
29 public int DefaultFixedUpdateStep => m_subsystemTime.DefaultFixedUpdateStep;
30
31 public Dictionary<IUpdateable, UpdateableInfo> m_updateables = [];
32
33 public Dictionary<IUpdateable, bool> m_toAddOrRemove = [];
34
35 public List<IUpdateable> m_sortedUpdateables = [];
36 public Dictionary<Type, DebugInfo> m_debugInfos = [];
37 public Stopwatch m_debugStopwatch = new();
38 public bool UpdateTimeDebug = false;
39
40 public int UpdateablesCount => m_updateables.Count;
41
42 public int UpdatesPerFrame { get; set; }
43
44 public virtual void Update() {
45 for (int i = 0; i < UpdatesPerFrame; i++) {
46 m_subsystemTime.NextFrame();
47 bool flag = false;
48 lock (m_toAddOrRemove) {
49 foreach (KeyValuePair<IUpdateable, bool> item in m_toAddOrRemove) {
50 bool skipVanilla = false;
52 "OnIUpdateableAddOrRemove",
53 loader => {
54 loader.OnIUpdateableAddOrRemove(this, item.Key, item.Value, skipVanilla, out bool skip);
55 skipVanilla |= skip;
56 return false;
57 }
58 );
59 if (!skipVanilla) {
60 if (item.Value) {
61 m_updateables.Add(item.Key, new UpdateableInfo { FloatUpdateOrder = item.Key.FloatUpdateOrder });
62 flag = true;
63 }
64 else {
65 m_updateables.Remove(item.Key);
66 flag = true;
67 }
68 }
69 }
70 m_toAddOrRemove.Clear();
71 }
72 foreach (KeyValuePair<IUpdateable, UpdateableInfo> updateable in m_updateables) {
73 float updateOrder = updateable.Key.FloatUpdateOrder;
74 if (updateOrder != updateable.Value.FloatUpdateOrder) {
75 flag = true;
76 updateable.Value.FloatUpdateOrder = updateOrder;
77 }
78 }
79 if (flag) {
80 m_sortedUpdateables.Clear();
81 foreach (IUpdateable key in m_updateables.Keys) {
82 m_sortedUpdateables.Add(key);
83 }
85 }
86 float dt = m_subsystemTime.GameTimeDelta;
87 if (UpdateTimeDebug) {
88 m_debugStopwatch.Start();
89 }
90 foreach (IUpdateable sortedUpdateable in m_sortedUpdateables) {
91 long ticks = UpdateTimeDebug ? m_debugStopwatch.ElapsedTicks : 0;
92 try {
93 lock (sortedUpdateable) {
94 sortedUpdateable.Update(dt);
95 }
96 }
97 catch (Exception) {
98 // ignored
99 }
100 finally {
101 if (UpdateTimeDebug) {
102 Type type = sortedUpdateable.GetType();
103 long ticksCosted = m_debugStopwatch.ElapsedTicks - ticks;
104 if (!m_debugInfos.TryGetValue(type, out DebugInfo info)) {
105 info = new DebugInfo();
106 m_debugInfos.Add(type, info);
107 }
108 info.Counter++;
109 info.TotalTicksCosted += ticksCosted;
110 if (ticksCosted > info.MaxTicksCosted1) {
111 info.MaxTicksCosted1 = ticksCosted;
112 }
113 else if (ticksCosted > info.MaxTicksCosted2) {
114 info.MaxTicksCosted2 = ticksCosted;
115 }
116 }
117 }
118 }
119 if (UpdateTimeDebug) {
120 m_debugStopwatch.Reset();
121 }
123 "SubsystemUpdate",
124 loader => {
125#pragma warning disable CS0618
126 loader.SubsystemUpdate(dt);
127#pragma warning restore CS0618
128 loader.SubsystemUpdate(this, dt);
129 return false;
130 }
131 );
132 }
133 }
134
135 public void AddUpdateable(IUpdateable updateable) {
136 lock (m_toAddOrRemove) {
137 m_toAddOrRemove[updateable] = true;
138 }
139 }
140
141 public void RemoveUpdateable(IUpdateable updateable) {
142 lock (m_toAddOrRemove) {
143 m_toAddOrRemove[updateable] = false;
144 }
145 }
146
147 public override void Load(ValuesDictionary valuesDictionary) {
148 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
149 foreach (IUpdateable item in Project.FindSubsystems<IUpdateable>()) {
150 AddUpdateable(item);
151 }
152 UpdatesPerFrame = 1;
153 }
154
155 public override void Save(ValuesDictionary valuesDictionary) {
156 if (UpdateTimeDebug) {
157 int maxTypeNameLength = 1;
158 if (m_debugInfos.Keys.Count > 0) {
159 maxTypeNameLength = m_debugInfos.Keys.Max(type => type.FullName?.Length ?? 0) + 1;
160 }
161 StringBuilder stringBuilder = new();
162 stringBuilder.AppendLine("====== SubsystemUpdate Performance Analyze ======");
163 stringBuilder.Append("TypeName".PadRight(maxTypeNameLength));
164 stringBuilder.Append(" Counter TotalTime AverageTime MaxTime1 MaxTime2");
165 foreach ((Type type, DebugInfo info) in m_debugInfos.OrderByDescending(pair => pair.Value.TotalTicksCosted)) {
166 stringBuilder.AppendLine();
167 stringBuilder.Append(type.FullName?.PadRight(maxTypeNameLength));
168 stringBuilder.Append(info.Counter.ToString().PadLeft(11));
169 stringBuilder.Append($"{(float)info.TotalTicksCosted / Stopwatch.Frequency * 1000:F}ms".PadLeft(12));
170 stringBuilder.Append($"{(float)info.TotalTicksCosted / info.Counter / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
171 stringBuilder.Append($"{(float)info.MaxTicksCosted1 / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
172 stringBuilder.Append($"{(float)info.MaxTicksCosted2 / Stopwatch.Frequency * 1000000f:F}μs".PadLeft(12));
173 }
174 Log.Information(stringBuilder.ToString());
175 m_debugInfos.Clear();
176 }
177 }
178
179 public override void OnEntityAdded(Entity entity) {
180 foreach (IUpdateable item in entity.FindComponents<IUpdateable>()) {
181 AddUpdateable(item);
182 }
183 }
184
185 public override void OnEntityRemoved(Entity entity) {
186 foreach (IUpdateable item in entity.FindComponents<IUpdateable>()) {
187 RemoveUpdateable(item);
188 }
189 }
190 }
191
193}
static void Information(object message)
定义 Log.cs:56
int Compare(IUpdateable u1, IUpdateable u2)
override void Load(ValuesDictionary valuesDictionary)
Dictionary< IUpdateable, UpdateableInfo > m_updateables
override void Save(ValuesDictionary valuesDictionary)
override void OnEntityRemoved(Entity entity)
void RemoveUpdateable(IUpdateable updateable)
Dictionary< IUpdateable, bool > m_toAddOrRemove
List< IUpdateable > m_sortedUpdateables
Dictionary< Type, DebugInfo > m_debugInfos
override void OnEntityAdded(Entity entity)
void AddUpdateable(IUpdateable updateable)
ValuesDictionary ValuesDictionary
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
void Update(float dt)