Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemFireBlockBehavior.cs
浏览该文件的文档.
1using Engine;
3
4namespace Game {
6 public class FireData {
7 public Point3 Point;
8
9 public float Time0;
10
11 public float Time1;
12
13 public float Time2;
14
15 public float Time3;
16
17 public float Time5;
18
19 public float FireExpandability;
20 }
21
23
25
27
29
31
32 public Dictionary<Point3, float> m_expansionProbabilities = [];
33
34 public Dictionary<Point3, FireData> m_fireData = [];
35
36 public DynamicArray<Point3> m_firePointsCopy = [];
37
38 public Dictionary<Point3, float> m_toBurnAway = [];
39
40 public Dictionary<Point3, float> m_toExpand = [];
41
42 public int m_copyIndex;
43
44 public float m_remainderToScan;
45
46 public double m_lastScanTime;
47
48 public float m_lastScanDuration;
49
50 public Random m_random = new();
51
52 public float m_fireSoundVolume;
53
55
57
58 public override int[] HandledBlocks => [104];
59
60 public bool IsCellOnFire(int x, int y, int z) {
61 for (int i = 0; i < 4; i++) {
62 Point3 point = CellFace.FaceToPoint3(i);
63 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x + point.X, y + point.Y, z + point.Z);
64 if (Terrain.ExtractContents(cellValue) == 104) {
65 int num = Terrain.ExtractData(cellValue);
66 int num2 = CellFace.OppositeFace(i);
67 if ((num & (1 << num2)) != 0) {
68 return true;
69 }
70 }
71 }
72 int cellValue2 = SubsystemTerrain.Terrain.GetCellValue(x, y + 1, z);
73 if (Terrain.ExtractContents(cellValue2) == 104
74 && Terrain.ExtractData(cellValue2) == 0) {
75 return true;
76 }
77 return false;
78 }
79
80 public bool SetCellOnFire(int x, int y, int z, float fireExpandability) {
81 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x, y, z);
82 int num = Terrain.ExtractContents(cellValue);
83 if (BlocksManager.Blocks[num].GetFireDuration(cellValue) == 0f) {
84 return false;
85 }
86 bool result = false;
87 for (int i = 0; i < 5; i++) {
88 Point3 point = CellFace.FaceToPoint3(i);
89 int cellValue2 = SubsystemTerrain.Terrain.GetCellValue(x + point.X, y + point.Y, z + point.Z);
90 int num2 = Terrain.ExtractContents(cellValue2);
91 if (num2 == 0
92 || num2 == 104
93 || num2 == 61) {
94 int num3 = num2 == 104 ? Terrain.ExtractData(cellValue2) : 0;
95 int num4 = CellFace.OppositeFace(i);
96 num3 |= (1 << num4) & 0xF;
97 cellValue = Terrain.ReplaceData(Terrain.ReplaceContents(104), num3);
98 AddFire(x + point.X, y + point.Y, z + point.Z, fireExpandability);
99 SubsystemTerrain.ChangeCell(x + point.X, y + point.Y, z + point.Z, cellValue);
100 result = true;
101 }
102 }
103 return result;
104 }
105
106 public virtual void Update(float dt) {
107 if (m_firePointsCopy.Count == 0) {
108 m_firePointsCopy.Count += m_fireData.Count;
109 m_fireData.Keys.CopyTo(m_firePointsCopy.Array, 0);
110 m_copyIndex = 0;
113 if (m_firePointsCopy.Count == 0) {
115 }
116 }
117 if (m_firePointsCopy.Count > 0) {
118 float num = MathUtils.Min(1f * dt * m_firePointsCopy.Count + m_remainderToScan, 50f);
119 int num2 = (int)num;
120 m_remainderToScan = num - num2;
121 int num3 = MathUtils.Min(m_copyIndex + num2, m_firePointsCopy.Count);
122 while (m_copyIndex < num3) {
123 if (m_fireData.TryGetValue(m_firePointsCopy.Array[m_copyIndex], out FireData value)) {
124 int x = value.Point.X;
125 int y = value.Point.Y;
126 int z = value.Point.Z;
127 int num4 = Terrain.ExtractData(SubsystemTerrain.Terrain.GetCellValue(x, y, z));
128 m_fireSoundIntensity += 1f / (m_subsystemAudio.CalculateListenerDistanceSquared(new Vector3(x, y, z)) + 0.01f);
129 if ((num4 & 1) != 0) {
130 value.Time0 -= m_lastScanDuration;
131 if (value.Time0 <= 0f) {
132 QueueBurnAway(x, y, z + 1, value.FireExpandability * 0.85f);
133 }
134 foreach (KeyValuePair<Point3, float> expansionProbability in m_expansionProbabilities) {
135 if (m_random.Float(0f, 1f) < expansionProbability.Value * m_lastScanDuration * value.FireExpandability) {
136 m_toExpand[new Point3(
137 x + expansionProbability.Key.X,
138 y + expansionProbability.Key.Y,
139 z + 1 + expansionProbability.Key.Z
140 )] = value.FireExpandability * 0.85f;
141 }
142 }
143 }
144 if ((num4 & 2) != 0) {
145 value.Time1 -= m_lastScanDuration;
146 if (value.Time1 <= 0f) {
147 QueueBurnAway(x + 1, y, z, value.FireExpandability * 0.85f);
148 }
149 foreach (KeyValuePair<Point3, float> expansionProbability2 in m_expansionProbabilities) {
150 if (m_random.Float(0f, 1f) < expansionProbability2.Value * m_lastScanDuration * value.FireExpandability) {
151 m_toExpand[new Point3(
152 x + 1 + expansionProbability2.Key.X,
153 y + expansionProbability2.Key.Y,
154 z + expansionProbability2.Key.Z
155 )] = value.FireExpandability * 0.85f;
156 }
157 }
158 }
159 if ((num4 & 4) != 0) {
160 value.Time2 -= m_lastScanDuration;
161 if (value.Time2 <= 0f) {
162 QueueBurnAway(x, y, z - 1, value.FireExpandability * 0.85f);
163 }
164 foreach (KeyValuePair<Point3, float> expansionProbability3 in m_expansionProbabilities) {
165 if (m_random.Float(0f, 1f) < expansionProbability3.Value * m_lastScanDuration * value.FireExpandability) {
166 m_toExpand[new Point3(
167 x + expansionProbability3.Key.X,
168 y + expansionProbability3.Key.Y,
169 z - 1 + expansionProbability3.Key.Z
170 )] = value.FireExpandability * 0.85f;
171 }
172 }
173 }
174 if ((num4 & 8) != 0) {
175 value.Time3 -= m_lastScanDuration;
176 if (value.Time3 <= 0f) {
177 QueueBurnAway(x - 1, y, z, value.FireExpandability * 0.85f);
178 }
179 foreach (KeyValuePair<Point3, float> expansionProbability4 in m_expansionProbabilities) {
180 if (m_random.Float(0f, 1f) < expansionProbability4.Value * m_lastScanDuration * value.FireExpandability) {
181 m_toExpand[new Point3(
182 x - 1 + expansionProbability4.Key.X,
183 y + expansionProbability4.Key.Y,
184 z + expansionProbability4.Key.Z
185 )] = value.FireExpandability * 0.85f;
186 }
187 }
188 }
189 if (num4 == 0) {
190 value.Time5 -= m_lastScanDuration;
191 if (value.Time5 <= 0f) {
192 QueueBurnAway(x, y - 1, z, value.FireExpandability * 0.85f);
193 }
194 }
195 }
196 m_copyIndex++;
197 }
198 if (m_copyIndex >= m_firePointsCopy.Count) {
200 m_firePointsCopy.Clear();
202 }
203 }
204 if (m_subsystemTime.PeriodicGameTimeEvent(5.0, 0.0)) {
205 int num5 = 0;
206 int num6 = 0;
207 foreach (KeyValuePair<Point3, float> item in m_toBurnAway) {
208 Point3 key = item.Key;
209 float value2 = item.Value;
210 SubsystemTerrain.ChangeCell(key.X, key.Y, key.Z, Terrain.ReplaceContents(0));
211 if (value2 > 0.25f) {
212 for (int i = 0; i < 5; i++) {
213 Point3 point = CellFace.FaceToPoint3(i);
214 SetCellOnFire(key.X + point.X, key.Y + point.Y, key.Z + point.Z, value2);
215 }
216 }
217 float num7 = m_subsystemViews.CalculateDistanceFromNearestView(new Vector3(key));
218 if (num5 < 15
219 && num7 < 24f) {
220 m_subsystemParticles.AddParticleSystem(new BurntDebrisParticleSystem(SubsystemTerrain, key.X, key.Y, key.Z));
221 num5++;
222 }
223 if (num6 < 4
224 && num7 < 16f) {
225 m_subsystemAudio.PlayRandomSound(
226 "Audio/Sizzles",
227 1f,
228 m_random.Float(-0.25f, 0.25f),
229 new Vector3(key.X, key.Y, key.Z),
230 3f,
231 true
232 );
233 num6++;
234 }
235 }
236 foreach (KeyValuePair<Point3, float> item2 in m_toExpand) {
237 SetCellOnFire(item2.Key.X, item2.Key.Y, item2.Key.Z, item2.Value);
238 }
239 m_toBurnAway.Clear();
240 m_toExpand.Clear();
241 }
242 m_subsystemAmbientSounds.FireSoundVolume = MathUtils.Max(m_subsystemAmbientSounds.FireSoundVolume, m_fireSoundVolume);
243 }
244
245 public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
246 int num = Terrain.ExtractData(SubsystemTerrain.Terrain.GetCellValue(x, y, z));
247 int cellValue_px = SubsystemTerrain.Terrain.GetCellValue(x + 1, y, z);
248 int cellValue_nx = SubsystemTerrain.Terrain.GetCellValue(x - 1, y, z);
249 int cellValue_py = SubsystemTerrain.Terrain.GetCellValue(x, y + 1, z);
250 int cellValue_ny = SubsystemTerrain.Terrain.GetCellValue(x, y - 1, z);
251 int cellValue_pz = SubsystemTerrain.Terrain.GetCellValue(x, y, z + 1);
252 int cellValue_nz = SubsystemTerrain.Terrain.GetCellValue(x, y, z - 1);
253 if ((num & 1) != 0
254 && BlocksManager.Blocks[Terrain.ExtractContents(cellValue_pz)].GetFireDuration(cellValue_pz) == 0f) {
255 num &= -2;
256 }
257 if ((num & 2) != 0
258 && BlocksManager.Blocks[Terrain.ExtractContents(cellValue_px)].GetFireDuration(cellValue_px) == 0f) {
259 num &= -3;
260 }
261 if ((num & 4) != 0
262 && BlocksManager.Blocks[Terrain.ExtractContents(cellValue_nz)].GetFireDuration(cellValue_nz) == 0f) {
263 num &= -5;
264 }
265 if ((num & 8) != 0
266 && BlocksManager.Blocks[Terrain.ExtractContents(cellValue_nx)].GetFireDuration(cellValue_nx) == 0f) {
267 num &= -9;
268 }
269 if (m_fireData.TryGetValue(new Point3(x, y, z), out FireData value)) {
270 if ((num & 1) != 0
271 && neighborX == x
272 && neighborY == y
273 && neighborZ == z + 1) {
274 InitializeFireDataTime(value, 0);
275 }
276 if ((num & 2) != 0
277 && neighborX == x + 1
278 && neighborY == y
279 && neighborZ == z) {
280 InitializeFireDataTime(value, 1);
281 }
282 if ((num & 4) != 0
283 && neighborX == x
284 && neighborY == y
285 && neighborZ == z - 1) {
286 InitializeFireDataTime(value, 2);
287 }
288 if ((num & 8) != 0
289 && neighborX == x - 1
290 && neighborY == y
291 && neighborZ == z) {
292 InitializeFireDataTime(value, 3);
293 }
294 if (num == 0
295 && neighborX == x
296 && neighborY == y - 1
297 && neighborZ == z) {
298 InitializeFireDataTime(value, 5);
299 }
300 }
301 int contents = 104;
302 if (num == 0
303 && BlocksManager.Blocks[Terrain.ExtractContents(cellValue_ny)].GetFireDuration(cellValue_ny) == 0f) {
304 contents = 0;
305 }
306 int value2 = Terrain.ReplaceData(Terrain.ReplaceContents(contents), num);
307 SubsystemTerrain.ChangeCell(x, y, z, value2);
308 }
309
310 public override void OnBlockAdded(int value, int oldValue, int x, int y, int z) {
311 AddFire(x, y, z, 1f);
312 }
313
314 public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
315 RemoveFire(x, y, z);
316 }
317
318 public override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded) {
319 AddFire(x, y, z, 1f);
320 }
321
322 public override void OnChunkDiscarding(TerrainChunk chunk) {
323 List<Point3> list = new();
324 foreach (Point3 key in m_fireData.Keys) {
325 if (key.X >= chunk.Origin.X
326 && key.X < chunk.Origin.X + 16
327 && key.Z >= chunk.Origin.Y
328 && key.Z < chunk.Origin.Y + 16) {
329 list.Add(key);
330 }
331 }
332 foreach (Point3 item in list) {
333 RemoveFire(item.X, item.Y, item.Z);
334 }
335 }
336
337 public override void Load(ValuesDictionary valuesDictionary) {
338 base.Load(valuesDictionary);
339 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
340 m_subsystemParticles = Project.FindSubsystem<SubsystemParticles>(true);
341 m_subsystemViews = Project.FindSubsystem<SubsystemGameWidgets>(true);
342 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
344 for (int i = -2; i <= 2; i++) {
345 for (int j = -1; j <= 2; j++) {
346 for (int k = -2; k <= 2; k++) {
347 if (i != 0
348 || j != 0
349 || k != 0) {
350 float num = j < 0 ? 1.5f : 2.5f;
351 if (MathF.Sqrt(i * i + j * j + k * k) <= num) {
352 float num2 = MathF.Sqrt(i * i + k * k);
353 float num3 = j > 0 ? 0.5f * j : -j;
354 m_expansionProbabilities[new Point3(i, j, k)] = 0.02f / (num2 + num3);
355 }
356 }
357 }
358 }
359 }
360 }
361
362 public void AddFire(int x, int y, int z, float expandability) {
363 Point3 point = new(x, y, z);
364 if (!m_fireData.ContainsKey(point)) {
365 FireData fireData = new() { Point = point, FireExpandability = expandability };
366 InitializeFireDataTimes(fireData);
367 m_fireData[point] = fireData;
368 }
369 }
370
371 public void RemoveFire(int x, int y, int z) {
372 Point3 key = new(x, y, z);
373 m_fireData.Remove(key);
374 }
375
376 public void InitializeFireDataTimes(FireData fireData) {
377 InitializeFireDataTime(fireData, 0);
378 InitializeFireDataTime(fireData, 1);
379 InitializeFireDataTime(fireData, 2);
380 InitializeFireDataTime(fireData, 3);
381 InitializeFireDataTime(fireData, 5);
382 }
383
384 public void InitializeFireDataTime(FireData fireData, int face) {
385 Point3 point = CellFace.FaceToPoint3(face);
386 int x = fireData.Point.X + point.X;
387 int y = fireData.Point.Y + point.Y;
388 int z = fireData.Point.Z + point.Z;
389 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x, y, z);
391 switch (face) {
392 case 4: break;
393 case 0: fireData.Time0 = block.GetFireDuration(cellValue) * m_random.Float(0.75f, 1.25f); break;
394 case 1: fireData.Time1 = block.GetFireDuration(cellValue) * m_random.Float(0.75f, 1.25f); break;
395 case 2: fireData.Time2 = block.GetFireDuration(cellValue) * m_random.Float(0.75f, 1.25f); break;
396 case 3: fireData.Time3 = block.GetFireDuration(cellValue) * m_random.Float(0.75f, 1.25f); break;
397 case 5: fireData.Time5 = block.GetFireDuration(cellValue) * m_random.Float(0.75f, 1.25f); break;
398 }
399 }
400
401 public void QueueBurnAway(int x, int y, int z, float expandability) {
402 Point3 key = new(x, y, z);
403 m_toBurnAway.TryAdd(key, expandability);
404 }
405 }
406}
Engine.Vector3 Vector3
static int Min(int x1, int x2)
static int Max(int x1, int x2)
virtual float GetFireDuration(int value)
override void OnChunkDiscarding(TerrainChunk chunk)
override void OnBlockAdded(int value, int oldValue, int x, int y, int z)
override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
void QueueBurnAway(int x, int y, int z, float expandability)
Dictionary< Point3, float > m_expansionProbabilities
override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded)
void AddFire(int x, int y, int z, float expandability)
bool SetCellOnFire(int x, int y, int z, float fireExpandability)
override void Load(ValuesDictionary valuesDictionary)
void InitializeFireDataTime(FireData fireData, int face)
static int ExtractContents(int value)
static int ReplaceData(int value, int data)
static int ReplaceContents(int value, int contents)
方块值的最低10位,替换为目标Content
static int ExtractData(int value)
ValuesDictionary ValuesDictionary
static int OppositeFace(int face)
static Point3 FaceToPoint3(int face)