Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemPistonBlockBehavior.cs
浏览该文件的文档.
1using Engine;
3
4namespace Game {
6 public class QueuedAction {
7 public int StoppedFrame;
8
9 public bool Stop;
10
11 public int? Move;
12 }
13
15
17
19
21
23
25
26 public Dictionary<Point3, QueuedAction> m_actions = [];
27
28 public List<KeyValuePair<Point3, QueuedAction>> m_tmpActions = [];
29
30 public DynamicArray<MovingBlock> m_movingBlocks = [];
31
32 public const string IdString = "Piston";
33
34 public const int PistonMaxMovedBlocks = 8;
35
36 public const int PistonMaxExtension = 8;
37
38 public const int PistonMaxSpeedSetting = 3;
39
40 public UpdateOrder UpdateOrder => m_subsystemMovingBlocks.UpdateOrder + 1;
41
42 public override int[] HandledBlocks => [];
43
44 public void AdjustPiston(Point3 position, int length) {
45 if (!m_actions.TryGetValue(position, out QueuedAction value)) {
46 value = new QueuedAction();
47 m_actions[position] = value;
48 }
49 value.Move = length;
50 }
51
52 public virtual void Update(float dt) {
53 if (m_subsystemTime.PeriodicGameTimeEvent(0.125, 0.0)) {
55 }
57 }
58
59 public override bool OnEditInventoryItem(IInventory inventory, int slotIndex, ComponentPlayer componentPlayer) {
60 if (componentPlayer.DragHostWidget.IsDragInProgress) {
61 return false;
62 }
63 int value = inventory.GetSlotValue(slotIndex);
64 int count = inventory.GetSlotCount(slotIndex);
65 int data = Terrain.ExtractData(value);
67 componentPlayer.GuiWidget,
69 data,
70 delegate(int newData) {
71 int num = Terrain.ReplaceData(value, newData);
72 if (num != value) {
73 inventory.RemoveSlotItems(slotIndex, count);
74 inventory.AddSlotItems(slotIndex, num, count);
75 }
76 }
77 )
78 );
79 return true;
80 }
81
82 public override bool OnEditBlock(int x, int y, int z, int value, ComponentPlayer componentPlayer) {
83 int contents = Terrain.ExtractContents(value);
84 int data = Terrain.ExtractData(value);
86 componentPlayer.GuiWidget,
88 data,
89 delegate(int newData) {
90 if (newData != data
91 && SubsystemTerrain.Terrain.GetCellContents(x, y, z) == contents) {
92 int value2 = Terrain.ReplaceData(value, newData);
93 SubsystemTerrain.ChangeCell(x, y, z, value2);
94 SubsystemElectricity subsystemElectricity = Project.FindSubsystem<SubsystemElectricity>(true);
95 ElectricElement electricElement = subsystemElectricity.GetElectricElement(x, y, z, 0);
96 if (electricElement != null) {
97 subsystemElectricity.QueueElectricElementForSimulation(electricElement, subsystemElectricity.CircuitStep + 1);
98 }
99 }
100 }
101 )
102 );
103 return true;
104 }
105
106 public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
107 int num = Terrain.ExtractContents(value);
108 int data = Terrain.ExtractData(value);
109 switch (num) {
110 case 237: {
111 StopPiston(new Point3(x, y, z));
112 int face2 = PistonBlock.GetFace(data);
113 Point3 point2 = CellFace.FaceToPoint3(face2);
114 int cellValue3 = m_subsystemTerrain.Terrain.GetCellValue(x + point2.X, y + point2.Y, z + point2.Z);
115 int num4 = Terrain.ExtractContents(cellValue3);
116 int data4 = Terrain.ExtractData(cellValue3);
117 if (num4 == 238
118 && PistonHeadBlock.GetFace(data4) == face2) {
119 m_subsystemTerrain.DestroyCell(
120 0,
121 x + point2.X,
122 y + point2.Y,
123 z + point2.Z,
124 0,
125 false,
126 false
127 );
128 }
129 break;
130 }
131 case 238:
133 int face = PistonHeadBlock.GetFace(data);
134 Point3 point = CellFace.FaceToPoint3(face);
135 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x + point.X, y + point.Y, z + point.Z);
136 int cellValue2 = m_subsystemTerrain.Terrain.GetCellValue(x - point.X, y - point.Y, z - point.Z);
137 int num2 = Terrain.ExtractContents(cellValue);
138 int num3 = Terrain.ExtractContents(cellValue2);
139 int data2 = Terrain.ExtractData(cellValue);
140 int data3 = Terrain.ExtractData(cellValue2);
141 if (num2 == 238
142 && PistonHeadBlock.GetFace(data2) == face) {
143 m_subsystemTerrain.DestroyCell(
144 0,
145 x + point.X,
146 y + point.Y,
147 z + point.Z,
148 0,
149 false,
150 false
151 );
152 }
153 if (num3 == 237
154 && PistonBlock.GetFace(data3) == face) {
155 m_subsystemTerrain.DestroyCell(
156 0,
157 x - point.X,
158 y - point.Y,
159 z - point.Z,
160 0,
161 false,
162 false
163 );
164 }
165 else if (num3 == 238
166 && PistonHeadBlock.GetFace(data3) == face) {
167 m_subsystemTerrain.DestroyCell(
168 0,
169 x - point.X,
170 y - point.Y,
171 z - point.Z,
172 0,
173 false,
174 false
175 );
176 }
177 }
178 break;
179 }
180 }
181
182 public override void OnChunkDiscarding(TerrainChunk chunk) {
183 BoundingBox boundingBox = new(chunk.BoundingBox.Min - new Vector3(16f), chunk.BoundingBox.Max + new Vector3(16f));
184 DynamicArray<IMovingBlockSet> dynamicArray = new();
185 m_subsystemMovingBlocks.FindMovingBlocks(boundingBox, false, dynamicArray);
186 foreach (IMovingBlockSet item in dynamicArray) {
187 if (item.Id == "Piston") {
188 StopPiston((Point3)item.Tag);
189 }
190 }
191 }
192
193 public override void Load(ValuesDictionary valuesDictionary) {
194 base.Load(valuesDictionary);
195 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
196 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
197 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
199 m_subsystemPlayers = Project.FindSubsystem<SubsystemPlayers>(true);
200 m_subsystemMovingBlocks.Stopped += MovingBlocksStopped;
201 m_subsystemMovingBlocks.CollidedWithTerrain += MovingBlocksCollidedWithTerrain;
202 }
203
204 public void ProcessQueuedActions() {
205 m_tmpActions.Clear();
206 m_tmpActions.AddRange(m_actions);
207 foreach (KeyValuePair<Point3, QueuedAction> tmpAction in m_tmpActions) {
208 Point3 key = tmpAction.Key;
209 QueuedAction value = tmpAction.Value;
210 if (Terrain.ExtractContents(m_subsystemTerrain.Terrain.GetCellValue(key.X, key.Y, key.Z)) != 237) {
211 StopPiston(key);
212 value.Move = null;
213 value.Stop = false;
214 }
215 else if (value.Stop) {
216 StopPiston(key);
217 value.Stop = false;
218 value.StoppedFrame = Time.FrameIndex;
219 }
220 }
221 foreach (KeyValuePair<Point3, QueuedAction> tmpAction2 in m_tmpActions) {
222 Point3 key2 = tmpAction2.Key;
223 QueuedAction value2 = tmpAction2.Value;
224 if (value2.Move.HasValue
225 && !value2.Stop
226 && Time.FrameIndex != value2.StoppedFrame
227 && m_subsystemMovingBlocks.FindMovingBlocks("Piston", key2) == null) {
228 bool flag = true;
229 for (int i = -1; i <= 1; i++) {
230 for (int j = -1; j <= 1; j++) {
231 TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(key2.X + i * 16, key2.Z + j * 16);
232 if (chunkAtCell == null
233 || (chunkAtCell.State <= TerrainChunkState.InvalidContents4 && m_subsystemPlayers.PlayerStartedPlaying)) {
234 flag = false;
235 }
236 }
237 }
238 if (flag && MovePiston(key2, value2.Move.Value)) {
239 value2.Move = null;
240 }
241 }
242 }
243 foreach (KeyValuePair<Point3, QueuedAction> tmpAction3 in m_tmpActions) {
244 Point3 key3 = tmpAction3.Key;
245 QueuedAction value3 = tmpAction3.Value;
246 if (!value3.Move.HasValue
247 && !value3.Stop) {
248 m_actions.Remove(key3);
249 }
250 }
251 }
252
253 public virtual void UpdateMovableBlocks() {
254 foreach (IMovingBlockSet movingBlockSet in m_subsystemMovingBlocks.MovingBlockSets) {
255 if (movingBlockSet.Id == "Piston") {
256 Point3 point = (Point3)movingBlockSet.Tag;
257 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(point.X, point.Y, point.Z);
258 if (Terrain.ExtractContents(cellValue) == 237) {
259 int data = Terrain.ExtractData(cellValue);
260 PistonMode mode = PistonBlock.GetMode(data);
261 int face = PistonBlock.GetFace(data);
262 Point3 p = CellFace.FaceToPoint3(face);
263 int num = int.MaxValue;
264 foreach (MovingBlock block in movingBlockSet.Blocks) {
265 num = MathUtils.Min(num, block.Offset.X * p.X + block.Offset.Y * p.Y + block.Offset.Z * p.Z);
266 }
267 float num2 = movingBlockSet.Position.X * p.X + movingBlockSet.Position.Y * p.Y + movingBlockSet.Position.Z * p.Z;
268 float num3 = point.X * p.X + point.Y * p.Y + point.Z * p.Z;
269 if (num2 > num3) {
270 if (num + num2 - num3 > 1f) {
271 movingBlockSet.SetBlock(
272 p * (num - 1),
274 238,
275 0,
277 )
278 );
279 }
280 }
281 else if (num2 < num3
282 && num + num2 - num3 <= 0f) {
283 movingBlockSet.SetBlock(p * num, 0);
284 }
285 }
286 }
287 }
288 }
289
290 public static void GetSpeedAndSmoothness(int pistonSpeed, out float speed, out Vector2 smoothness) {
291 switch (pistonSpeed) {
292 default:
293 speed = 5f;
294 smoothness = new Vector2(0f, 0.5f);
295 break;
296 case 1:
297 speed = 4.5f;
298 smoothness = new Vector2(0.6f, 0.6f);
299 break;
300 case 2:
301 speed = 4f;
302 smoothness = new Vector2(0.9f, 0.9f);
303 break;
304 case 3:
305 speed = 3.5f;
306 smoothness = new Vector2(1.2f, 1.2f);
307 break;
308 }
309 }
310
311 public bool MovePiston(Point3 position, int length) {
312 Terrain terrain = m_subsystemTerrain.Terrain;
313 int data = Terrain.ExtractData(terrain.GetCellValue(position.X, position.Y, position.Z));
314 int face = PistonBlock.GetFace(data);
315 PistonMode mode = PistonBlock.GetMode(data);
316 int maxExtension = PistonBlock.GetMaxExtension(data);
317 int pullCount = PistonBlock.GetPullCount(data);
318 int speed = PistonBlock.GetSpeed(data);
319 Point3 point = CellFace.FaceToPoint3(face);
320 length = Math.Clamp(length, 0, maxExtension + 1);
321 int num = 0;
322 m_movingBlocks.Clear();
323 Point3 offset = point;
324 MovingBlock item;
325 while (m_movingBlocks.Count < 8) {
326 int cellValue = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z);
327 int num2 = Terrain.ExtractContents(cellValue);
328 int face2 = PistonHeadBlock.GetFace(Terrain.ExtractData(cellValue));
329 if (num2 != 238
330 || face2 != face) {
331 break;
332 }
333 DynamicArray<MovingBlock> movingBlocks = m_movingBlocks;
334 item = new MovingBlock { Offset = offset, Value = cellValue };
335 movingBlocks.Add(item);
336 offset += point;
337 num++;
338 }
339 if (length > num) {
340 DynamicArray<MovingBlock> movingBlocks2 = m_movingBlocks;
341 item = new MovingBlock {
342 Offset = Point3.Zero,
343 Value = Terrain.MakeBlockValue(
344 238,
345 0,
347 )
348 };
349 movingBlocks2.Add(item);
350 int num3 = 0;
351 while (num3 < 8) {
352 int cellValue2 = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z);
353 if (!IsBlockMovable(cellValue2, face, position.Y + offset.Y, out bool isEnd)) {
354 break;
355 }
356 DynamicArray<MovingBlock> movingBlocks3 = m_movingBlocks;
357 item = new MovingBlock { Offset = offset, Value = cellValue2 };
358 movingBlocks3.Add(item);
359 num3++;
360 offset += point;
361 if (isEnd) {
362 break;
363 }
364 }
365 if (!IsBlockBlocking(terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z))) {
366 GetSpeedAndSmoothness(speed, out float speed2, out Vector2 smoothness);
367 Point3 p = position + (length - num) * point;
368 IMovingBlockSet movingBlockSet = m_subsystemMovingBlocks.AddMovingBlockSet(
369 new Vector3(position) + 0.01f * new Vector3(point),
370 new Vector3(p),
371 speed2,
372 0f,
373 0f,
374 smoothness,
376 "Piston",
377 position,
378 true
379 );
380 if (movingBlockSet != null) {
382 try {
383 foreach (MovingBlock movingBlock in m_movingBlocks) {
384 if (movingBlock.Offset != Point3.Zero) {
385 m_subsystemTerrain.ChangeCell(
386 position.X + movingBlock.Offset.X,
387 position.Y + movingBlock.Offset.Y,
388 position.Z + movingBlock.Offset.Z,
389 0,
390 true,
391 movingBlock
392 );
393 }
394 }
395 }
396 finally {
398 }
399 m_subsystemTerrain.ChangeCell(
400 position.X,
401 position.Y,
402 position.Z,
404 );
405 m_subsystemAudio.PlaySound("Audio/Piston", 1f, 0f, new Vector3(position), 2f, true);
406 }
407 }
408 return false;
409 }
410 if (length < num) {
411 if (mode != 0) {
412 int num4 = 0;
413 for (int i = 0; i < pullCount + 1; i++) {
414 int cellValue3 = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z);
415 if (!IsBlockMovable(cellValue3, face, position.Y + offset.Y, out bool isEnd2)) {
416 break;
417 }
418 DynamicArray<MovingBlock> movingBlocks4 = m_movingBlocks;
419 item = new MovingBlock { Offset = offset, Value = cellValue3 };
420 movingBlocks4.Add(item);
421 offset += point;
422 num4++;
423 if (isEnd2) {
424 break;
425 }
426 }
427 if (mode == PistonMode.StrictPulling
428 && num4 < pullCount + 1) {
429 return false;
430 }
431 }
432 GetSpeedAndSmoothness(speed, out float speed3, out Vector2 smoothness2);
433 float s = length == 0 ? 0.01f : 0f;
434 Vector3 targetPosition = new Vector3(position) + (length - num) * new Vector3(point) + s * new Vector3(point);
435 IMovingBlockSet movingBlockSet = m_subsystemMovingBlocks.AddMovingBlockSet(
436 new Vector3(position),
437 targetPosition,
438 speed3,
439 0f,
440 0f,
441 smoothness2,
443 "Piston",
444 position,
445 true
446 );
447 if (movingBlockSet != null) {
449 try {
450 foreach (MovingBlock movingBlock2 in m_movingBlocks) {
451 m_subsystemTerrain.ChangeCell(
452 position.X + movingBlock2.Offset.X,
453 position.Y + movingBlock2.Offset.Y,
454 position.Z + movingBlock2.Offset.Z,
455 0,
456 false,
457 movingBlock2
458 );
459 }
460 }
461 finally {
463 }
464 m_subsystemAudio.PlaySound("Audio/Piston", 1f, 0f, new Vector3(position), 2f, true);
465 }
466 return false;
467 }
468 return true;
469 }
470
471 public void StopPiston(Point3 position) {
472 IMovingBlockSet movingBlockSet = m_subsystemMovingBlocks.FindMovingBlocks("Piston", position);
473 if (movingBlockSet != null) {
474 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(position.X, position.Y, position.Z);
475 int num = Terrain.ExtractContents(cellValue);
476 int data = Terrain.ExtractData(cellValue);
477 bool flag = num == 237;
478 bool isExtended = false;
479 m_subsystemMovingBlocks.RemoveMovingBlockSet(movingBlockSet);
480 foreach (MovingBlock block in movingBlockSet.Blocks) {
481 int x = Terrain.ToCell(MathF.Round(movingBlockSet.Position.X)) + block.Offset.X;
482 int y = Terrain.ToCell(MathF.Round(movingBlockSet.Position.Y)) + block.Offset.Y;
483 int z = Terrain.ToCell(MathF.Round(movingBlockSet.Position.Z)) + block.Offset.Z;
484 if (!(new Point3(x, y, z) == position)) {
485 int num2 = Terrain.ExtractContents(block.Value);
486 if (flag || num2 != 238) {
487 m_subsystemMovingBlocks.AddTerrainBlock(x, y, z, block.Value, block);
488 if (num2 == 238) {
489 isExtended = true;
490 }
491 }
492 }
493 }
494 if (flag) {
495 m_subsystemTerrain.ChangeCell(
496 position.X,
497 position.Y,
498 position.Z,
499 Terrain.MakeBlockValue(237, 0, PistonBlock.SetIsExtended(data, isExtended))
500 );
501 }
502 }
503 }
504
506 if (movingBlockSet.Id != "Piston") {
507 return;
508 }
509 Point3 point = (Point3)movingBlockSet.Tag;
510 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(point.X, point.Y, point.Z);
511 if (Terrain.ExtractContents(cellValue) != 237) {
512 return;
513 }
515 int num = p.X * point2.X + p.Y * point2.Y + p.Z * point2.Z;
516 int num2 = point.X * point2.X + point.Y * point2.Y + point.Z * point2.Z;
517 if (num > num2) {
518 if (IsBlockBlocking(SubsystemTerrain.Terrain.GetCellValue(p.X, p.Y, p.Z))) {
519 movingBlockSet.Stop();
520 }
521 else {
522 SubsystemTerrain.DestroyCell(
523 0,
524 p.X,
525 p.Y,
526 p.Z,
527 0,
528 false,
529 false
530 );
531 }
532 }
533 }
534
535 public void MovingBlocksStopped(IMovingBlockSet movingBlockSet) {
536 if (movingBlockSet.Id != "Piston"
537 || movingBlockSet.Tag is not Point3 tag) {
538 return;
539 }
540 if (Terrain.ExtractContents(m_subsystemTerrain.Terrain.GetCellValue(tag.X, tag.Y, tag.Z)) == 237) {
541 if (!m_actions.TryGetValue(tag, out QueuedAction value)) {
542 value = new QueuedAction();
543 m_actions.Add(tag, value);
544 }
545 value.Stop = true;
546 }
547 }
548
549 public static bool IsBlockMovable(int value, int pistonFace, int y, out bool isEnd) {
550 int num = Terrain.ExtractContents(value);
551 Terrain.ExtractData(value);
552 Block block = BlocksManager.Blocks[num];
553 return block.IsMovableByPiston(value, pistonFace, y, out isEnd);
554 }
555
556 public static bool IsBlockBlocking(int value) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsBlockingPiston(value);
557 }
558}
Engine.Vector3 Vector3
static int Min(int x1, int x2)
static int FrameIndex
定义 Time.cs:26
virtual bool IsMovableByPiston(int value, int pistonFace, int y, out bool isEnd)
virtual bool IsBlockingPiston(int value)
static void ShowDialog(ContainerWidget parentWidget, Dialog dialog)
static PistonMode GetMode(int data)
static int GetPullCount(int data)
static int GetFace(int data)
static int GetMaxExtension(int data)
static int SetIsExtended(int data, bool isExtended)
static int GetSpeed(int data)
static int GetFace(int data)
static int SetFace(int data, int face)
static int SetMode(int data, PistonMode mode)
static int SetIsShaft(int data, bool isShaft)
void QueueElectricElementForSimulation(ElectricElement electricElement, int circuitStep)
ElectricElement GetElectricElement(int x, int y, int z, int mountingFace)
void MovingBlocksCollidedWithTerrain(IMovingBlockSet movingBlockSet, Point3 p)
override void Load(ValuesDictionary valuesDictionary)
static void GetSpeedAndSmoothness(int pistonSpeed, out float speed, out Vector2 smoothness)
override bool OnEditInventoryItem(IInventory inventory, int slotIndex, ComponentPlayer componentPlayer)
override bool OnEditBlock(int x, int y, int z, int value, ComponentPlayer componentPlayer)
override void OnChunkDiscarding(TerrainChunk chunk)
override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
List< KeyValuePair< Point3, QueuedAction > > m_tmpActions
static bool IsBlockMovable(int value, int pistonFace, int y, out bool isEnd)
void MovingBlocksStopped(IMovingBlockSet movingBlockSet)
TerrainChunkState State
static int ExtractContents(int value)
static int ReplaceData(int value, int data)
virtual int GetCellValue(int x, int y, int z)
static int ToCell(float x)
static int MakeBlockValue(int contents)
static int ExtractData(int value)
ValuesDictionary ValuesDictionary
int RemoveSlotItems(int slotIndex, int count)
实际移除的数量
int GetSlotCount(int slotIndex)
void AddSlotItems(int slotIndex, int value, int count)
int GetSlotValue(int slotIndex)
List< MovingBlock > Blocks
void SetBlock(Point3 offset, int value)
static readonly Point3 Zero
static Point3 FaceToPoint3(int face)