Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemMetersBlockBehavior.cs
浏览该文件的文档.
1using Engine;
3
4namespace Game {
7
9
11
12 public Dictionary<Point3, int> m_thermometersByPoint = [];
13
14 public DynamicArray<Point3> m_thermometersToSimulate = [];
15
17
18 public const int m_diameterBits = 6;
19
20 public const int m_diameter = 64;
21
22 public const int m_diameterMask = 63;
23
24 public const int m_radius = 32;
25
26 public DynamicArray<int> m_toVisit = [];
27
28 public int[] m_visited = new int[8192];
29
30 public override int[] HandledBlocks => [120, 121];
31
33
34 public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
35 Point3 point = CellFace.FaceToPoint3(Terrain.ExtractData(SubsystemTerrain.Terrain.GetCellValue(x, y, z)));
36 int cellValue = SubsystemTerrain.Terrain.GetCellValue(x - point.X, y - point.Y, z - point.Z);
37 if (BlocksManager.Blocks[Terrain.ExtractContents(cellValue)].IsNonAttachable(cellValue)) {
38 SubsystemTerrain.DestroyCell(
39 0,
40 x,
41 y,
42 z,
43 0,
44 false,
45 false
46 );
47 }
48 }
49
50 public override void OnBlockAdded(int value, int oldValue, int x, int y, int z) {
51 AddRemoveMeter(value, x, y, z);
52 }
53
54 public override void OnBlockRemoved(int value, int oldValue, int x, int y, int z) {
55 AddRemoveMeter(oldValue, x, y, z);
56 }
57
58 public override void OnBlockModified(int value, int oldValue, int x, int y, int z) {
59 AddRemoveMeter(value, x, y, z);
60 }
61
62 public override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded) {
63 AddRemoveMeter(value, x, y, z);
64 }
65
66 public override void OnChunkDiscarding(TerrainChunk chunk) {
67 List<Point3> list = new();
68 foreach (Point3 key in m_thermometersByPoint.Keys) {
69 if (key.X >= chunk.Origin.X
70 && key.X < chunk.Origin.X + 16
71 && key.Z >= chunk.Origin.Y
72 && key.Z < chunk.Origin.Y + 16) {
73 list.Add(key);
74 }
75 }
76 foreach (Point3 item in list) {
77 AddRemoveMeter(0, item.X, item.Y, item.Z);
78 }
79 }
80
81 public override void Load(ValuesDictionary valuesDictionary) {
82 base.Load(valuesDictionary);
83 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
84 m_subsystemWeather = Project.FindSubsystem<SubsystemWeather>(true);
85 m_subsystemSky = Project.FindSubsystem<SubsystemSky>(true);
86 }
87
88 public virtual void Update(float dt) {
90 double period = Math.Max(4 / m_thermometersToSimulate.Count, 0.5);
91 if (m_subsystemTime.PeriodicGameTimeEvent(period, 0.0)) {
93 SimulateThermometer(point.X, point.Y, point.Z, true);
95 }
96 }
97 else if (m_thermometersByPoint.Count > 0) {
100 m_thermometersToSimulate.AddRange((IEnumerable<Point3>)m_thermometersByPoint.Keys);
101 }
102 }
103
104 public int GetThermometerReading(int x, int y, int z) {
105 m_thermometersByPoint.TryGetValue(new Point3(x, y, z), out int value);
106 return value;
107 }
108
120 public void CalculateTemperature(int x,
121 int y,
122 int z,
123 float meterTemperature,
124 float meterInsulation,
125 out float targetTemperature,
126 out float targetTemperatureFlux,
127 out float environmentTemperature) {
128 m_toVisit.Count = 0;
129 Array.Clear(m_visited);
130 Terrain terrain = SubsystemTerrain.Terrain;
131 float num = 0f;
132 float num2 = 0f;
133 float num3 = 0f;
134 float num4 = 0f;
135 float num5 = 0f;
136 float num6 = 0f;
137 m_toVisit.Add(133152);
138 for (int i = 0; i < m_toVisit.Count; i++) {
139 int num7 = m_toVisit.Array[i];
140 if ((m_visited[num7 / 32] & (1 << num7)) != 0) {
141 continue;
142 }
143 m_visited[num7 / 32] |= 1 << num7;
144 int num8 = (num7 & 0x3F) - 32;
145 int num9 = ((num7 >> 6) & 0x3F) - 32;
146 int num10 = ((num7 >> 12) & 0x3F) - 32;
147 int num11 = num8 + x;
148 int num12 = num9 + y;
149 int num13 = num10 + z;
150 TerrainChunk chunkAtCell = terrain.GetChunkAtCell(num11, num13);
151 if (chunkAtCell == null
152 || num12 < 0
153 || num12 >= 256) {
154 continue;
155 }
156 int x2 = num11 & 0xF;
157 int y2 = num12;
158 int z2 = num13 & 0xF;
159 int cellValueFast = chunkAtCell.GetCellValueFast(x2, y2, z2);
160 int num14 = Terrain.ExtractContents(cellValueFast);
161 Block block = BlocksManager.Blocks[num14];
162 float heat = GetHeat(cellValueFast);
163 if (heat > 0f) {
164 int num15 = Math.Abs(num8) + Math.Abs(num9) + Math.Abs(num10);
165 int num16 = num15 <= 0 ? 1 : 4 * num15 * num15 + 2;
166 float num17 = 1f / num16;
167 num5 += num17 * 36f * heat;
168 num6 += num17;
169 }
170 else if (block.IsHeatBlocker(cellValueFast)) {
171 int num18 = Math.Abs(num8) + Math.Abs(num9) + Math.Abs(num10);
172 int num19 = num18 <= 0 ? 1 : 4 * num18 * num18 + 2;
173 float num20 = 1f / num19;
174 float num21 = terrain.SeasonTemperature;
176 float num23 = block is WaterBlock ? MathUtils.Max(chunkAtCell.GetTemperatureFast(x2, z2) + num21 - 7f, 0f) + num22 :
177 !(block is IceBlock) ? MathUtils.Max(chunkAtCell.GetTemperatureFast(x2, z2) + num21, 0f) + num22 :
178 MathUtils.Max(0f + num21 + num22, 0f);
179 num += num20 * num23;
180 num2 += num20;
181 }
182 else if (y >= chunkAtCell.GetTopHeightFast(x2, z2)) {
183 int num24 = Math.Abs(num8) + Math.Abs(num9) + Math.Abs(num10);
184 int num25 = num24 <= 0 ? 1 : 4 * num24 * num24 + 2;
185 float num26 = 1f / num25;
186 PrecipitationShaftInfo precipitationShaftInfo = m_subsystemWeather.GetPrecipitationShaftInfo(x, z);
187 float num27 = terrain.SeasonTemperature;
188 float num28 = y >= precipitationShaftInfo.YLimit ? MathUtils.Lerp(0f, -2f, precipitationShaftInfo.Intensity) : 0f;
189 float num29 = MathUtils.Lerp(-6f, 0f, m_subsystemSky.SkyLightIntensity);
191 num3 += num26 * (MathUtils.Max(chunkAtCell.GetTemperatureFast(x2, z2) + num27, 0f) + num28 + num29 + num30);
192 num4 += num26;
193 }
194 else if (m_toVisit.Count < 4090) {
195 if (num8 > -30) {
196 m_toVisit.Add(num7 - 1);
197 }
198 if (num8 < 30) {
199 m_toVisit.Add(num7 + 1);
200 }
201 if (num9 > -30) {
202 m_toVisit.Add(num7 - 64);
203 }
204 if (num9 < 30) {
205 m_toVisit.Add(num7 + 64);
206 }
207 if (num10 > -30) {
208 m_toVisit.Add(num7 - 4096);
209 }
210 if (num10 < 30) {
211 m_toVisit.Add(num7 + 4096);
212 }
213 }
214 }
215 float num31 = 0f;
216 for (int j = -7; j <= 7; j++) {
217 for (int k = -7; k <= 7; k++) {
218 TerrainChunk chunkAtCell2 = SubsystemTerrain.Terrain.GetChunkAtCell(x + j, z + k);
219 if (chunkAtCell2 == null
220 || chunkAtCell2.State < TerrainChunkState.InvalidLight) {
221 continue;
222 }
223 for (int l = -7; l <= 7; l++) {
224 int num32 = j * j + l * l + k * k;
225 if (num32 > 49
226 || num32 <= 0) {
227 continue;
228 }
229 int x3 = (x + j) & 0xF;
230 int num33 = y + l;
231 int z3 = (z + k) & 0xF;
232 if (num33 >= 0
233 && num33 < 256) {
234 float heat2 = GetHeat(chunkAtCell2.GetCellValueFast(x3, num33, z3));
235 if (heat2 > 0f
236 && !SubsystemTerrain.Raycast(
237 new Vector3(x, y, z) + new Vector3(0.5f, 0.75f, 0.5f),
238 new Vector3(x + j, y + l, z + k) + new Vector3(0.5f, 0.75f, 0.5f),
239 false,
240 true,
241 delegate(int raycastValue, float _) {
242 Block block2 = BlocksManager.Blocks[Terrain.ExtractContents(raycastValue)];
243 return block2.IsCollidable_(raycastValue) && !block2.IsTransparent_(raycastValue);
244 }
245 )
246 .HasValue) {
247 num31 += heat2 * 3f / (num32 + 2);
248 }
249 }
250 }
251 }
252 }
253 float num34 = 0f;
254 float num35 = 0f;
255 if (num31 > 0f) {
256 float num36 = 3f * num31;
257 num34 += 35f * num36;
258 num35 += num36;
259 }
260 if (num2 > 0f) {
261 float num37 = 1f;
262 num34 += num / num2 * num37;
263 num35 += num37;
264 }
265 if (num4 > 0f) {
266 float num38 = 4f * MathF.Pow(num4, 0.25f);
267 num34 += num3 / num4 * num38;
268 num35 += num38;
269 }
270 if (num6 > 0f) {
271 float num39 = 1.5f * MathF.Pow(num6, 0.25f);
272 num34 += num5 / num6 * num39;
273 num35 += num39;
274 }
275 environmentTemperature = num35 > 0f ? num34 / num35 : meterTemperature;
276 if (meterInsulation > 0f) {
277 num34 += meterTemperature * meterInsulation;
278 num35 += meterInsulation;
279 }
280 targetTemperature = num35 > 0f ? num34 / num35 : meterTemperature;
281 targetTemperatureFlux = 0.01f + 0.004f * MathUtils.Max(num35 - meterInsulation, 0f);
282 }
283
284 public static float GetHeat(int value) {
285 int num = Terrain.ExtractContents(value);
286 return BlocksManager.Blocks[num].GetHeat(value);
287 }
288
289 public void SimulateThermometer(int x, int y, int z, bool invalidateTerrainOnChange) {
290 Point3 key = new(x, y, z);
291 if (!m_thermometersByPoint.TryGetValue(key, out int num)) {
292 return;
293 }
295 x,
296 y,
297 z,
298 0f,
299 0f,
300 out float _,
301 out float _,
302 out float environmentTemperature
303 );
304 int num2 = (int)MathF.Round(environmentTemperature);
305 if (num2 == num) {
306 return;
307 }
308 m_thermometersByPoint[new Point3(x, y, z)] = num2;
309 if (invalidateTerrainOnChange) {
310 TerrainChunk chunkAtCell = SubsystemTerrain.Terrain.GetChunkAtCell(x, z);
311 if (chunkAtCell != null) {
312 SubsystemTerrain.TerrainUpdater.DowngradeChunkNeighborhoodState(chunkAtCell.Coords, 0, TerrainChunkState.InvalidVertices1, true);
313 }
314 }
315 }
316
317 public void AddRemoveMeter(int value, int x, int y, int z) {
318 if (Terrain.ExtractContents(value) == 120) {
319 m_thermometersByPoint[new Point3(x, y, z)] = 0;
320 SimulateThermometer(x, y, z, false);
321 }
322 else {
323 m_thermometersByPoint.Remove(new Point3(x, y, z));
324 }
325 }
326 }
327}
Engine.Vector3 Vector3
static int Max(int x1, int x2)
static float Lerp(float x1, float x2, float f)
virtual bool IsTransparent_(int value)
virtual bool IsNonAttachable(int value)
virtual bool IsCollidable_(int value)
virtual bool IsHeatBlocker(int value)
virtual float GetHeat(int value)
void AddRemoveMeter(int value, int x, int y, int z)
override void OnChunkDiscarding(TerrainChunk chunk)
override void OnBlockRemoved(int value, int oldValue, int x, int y, int z)
override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
override void OnBlockAdded(int value, int oldValue, int x, int y, int z)
void CalculateTemperature(int x, int y, int z, float meterTemperature, float meterInsulation, out float targetTemperature, out float targetTemperatureFlux, out float environmentTemperature)
计算温度
void SimulateThermometer(int x, int y, int z, bool invalidateTerrainOnChange)
override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded)
override void Load(ValuesDictionary valuesDictionary)
override void OnBlockModified(int value, int oldValue, int x, int y, int z)
static Func< int, int > GetTemperatureAdjustmentAtHeight
TerrainChunkState State
virtual int GetCellValueFast(int index)
virtual int GetTemperatureFast(int x, int z)
virtual int GetTopHeightFast(int x, int z)
static int ExtractContents(int value)
virtual TerrainChunk GetChunkAtCell(int x, int z)
static int ExtractData(int value)
ValuesDictionary ValuesDictionary
static Point3 FaceToPoint3(int face)