Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
ComponentBody.cs
浏览该文件的文档.
1using Engine;
4// ReSharper disable ConditionIsAlwaysTrueOrFalse
5
6namespace Game {
8 public struct CollisionBox {
9 public CollisionBox() { }
10
11 public int BlockValue;
12
14
16
18
23 }
24
26
28
30
32
34
36
38
40
42
43 public Random m_random = new();
44
46
47 public DynamicArray<CollisionBox> m_collisionBoxes = [];
48
49 public DynamicArray<ComponentBody> m_componentBodies = [];
50
51 public DynamicArray<IMovingBlockSet> m_movingBlockSets = [];
52
53 public DynamicArray<CollisionBox> m_bodiesCollisionBoxes = [];
54
55 public DynamicArray<CollisionBox> m_movingBlocksCollisionBoxes = [];
56
58
59 public List<ComponentBody> m_childBodies = [];
60
62
63 public float m_crouchFactor;
64
66
67 public float m_shakingStrength;
68
70
72
74
76
77 public float m_stoppedTime;
78
79 public static Vector3[] m_freeSpaceOffsets;
80
81 public static bool DrawBodiesBounds;
82
83 public const float SleepThresholdSpeed = 1E-05f;
84
85 public float MaxSpeed = 25f;
86
87 public bool CanCrouch;
88
89 public bool TerrainCollidable = true;
90
91 public bool BodyCollidable = true;
92
93 public bool FluidCollidable = true;
94
95 public bool IsRaycastTransparent = false; //不可选中
96
97 public static bool ResetVelocityOnProjectLoad = true;
98 public virtual Vector3 StanceBoxSize => new(BoxSize.X, (CrouchFactor >= 0.8f ? 0.5f : 1f) * BoxSize.Y, BoxSize.Z);
99
100 public virtual bool CanBePushedByOtherBodies { get; set; } = true;
101 public virtual Vector3 BoxSize { get; set; }
102
103 public virtual float Mass { get; set; }
104
105 public virtual float Density { get; set; }
106
107 public virtual Vector2 AirDrag { get; set; }
108
109 public virtual Vector2 WaterDrag { get; set; }
110
111 public virtual float WaterSwayAngle { get; set; }
112
113 public virtual float WaterTurnSpeed { get; set; }
114
115 public bool CanEmbedInIce { get; set; }
116
117 public virtual float ImmersionDepth { get; set; }
118
119 public virtual float ImmersionFactor { get; set; }
120
121 public virtual FluidBlock ImmersionFluidBlock { get; set; }
122
124
125 public virtual int? StandingOnValue { get; set; }
126
127 public virtual ComponentBody StandingOnBody { get; set; }
128
129 public virtual Vector3 StandingOnVelocity { get; set; }
130
131 [Obsolete("Use IsCrouching")]
132 public virtual bool IsSneaking {
133 get => IsCrouching;
134 set => IsCrouching = value;
135 }
136
137 public virtual bool IsCrouching {
138 get => CrouchFactor > 0;
139 set => TargetCrouchFactor = value ? 1 : 0;
140 }
141
142 public virtual Vector3 Velocity {
143 get => m_velocity;
144 set {
145 if (value.LengthSquared() > MaxSpeed * MaxSpeed) {
147 }
148 else {
149 m_velocity = value;
150 }
151 }
152 }
153
154 public virtual float TargetCrouchFactor {
156 set {
157 if (!CanCrouch) {
158 value = 0f;
159 }
160 m_targetCrouchFactor = value;
161 }
162 }
163
164 public virtual float CrouchFactor {
165 get => m_crouchFactor;
166 set {
167 if (!CanCrouch) {
168 value = 0f;
169 }
170 m_crouchFactor = value;
171 }
172 }
173
174 public float CrushedTime { get; set; }
175
176 public virtual bool IsGravityEnabled { get; set; }
177
178 public virtual bool IsGroundDragEnabled { get; set; }
179
180 public virtual bool IsWaterDragEnabled { get; set; }
181
182 public virtual bool IsSmoothRiseEnabled { get; set; }
183
184 public virtual float MaxSmoothRiseHeight { get; set; }
185
186 public virtual Vector3 CollisionVelocityChange { get; set; }
187 public virtual bool CrouchPreventsFalling { get; set; } = true;
188 public virtual bool FixCollisionOnRidingBug { get; set; } = true;
189
190 public virtual BoundingBox BoundingBox {
191 get {
192 Vector3 stanceBoxSize = StanceBoxSize;
193 Vector3 position = Position;
194 return new BoundingBox(
195 position - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f),
196 position + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f)
197 );
198 }
199 }
200
201 public virtual ReadOnlyList<ComponentBody> ChildBodies => new(m_childBodies);
202
203 public virtual ComponentBody ParentBody {
204 get => m_parentBody;
205 set {
206 if (value != m_parentBody) {
207 if (m_parentBody != null) {
208 m_parentBody.m_childBodies.Remove(this);
209 }
210 m_parentBody = value;
211 if (m_parentBody != null) {
212 m_parentBody.m_childBodies.Add(this);
213 }
214 }
215 }
216 }
217
218 public virtual Vector3 ParentBodyPositionOffset { get; set; }
219
220 public virtual Quaternion ParentBodyRotationOffset { get; set; }
221
222 public virtual float FloatUpdateOrder {
223 get {
224 if (m_parentBody == null) {
225 return (float)UpdateOrder.Body;
226 }
227 return m_parentBody.FloatUpdateOrder + 0.01f;
228 }
229 }
230
231 public virtual Action<ComponentBody> CollidedWithBody { get; set; }
232
233 public virtual Action<IMovingBlockSet> CollidedWithMovingBlock { get; set; }
234 public virtual Action<Attackment> Attacked { get; set; }
235
236 static ComponentBody() {
237 List<Vector3> list = [];
238 for (int i = -2; i <= 2; i++) {
239 for (int j = -2; j <= 2; j++) {
240 for (int k = -2; k <= 2; k++) {
241 Vector3 item = new(0.25f * i, 0.25f * j, 0.25f * k);
242 list.Add(item);
243 }
244 }
245 }
246 list.Sort((o1, o2) => Comparer<float>.Default.Compare(o1.LengthSquared(), o2.LengthSquared()));
247 m_freeSpaceOffsets = list.ToArray();
248 }
249
250 public virtual void ApplyImpulse(Vector3 impulse) {
251 m_totalImpulse += impulse;
252 }
253
254 public virtual void ApplyDirectMove(Vector3 directMove) {
255 m_directMove += directMove;
256 }
257
258 public void ApplyShaking(float strength) {
259 m_shakingStrength += strength;
260 }
261
262 public virtual bool IsChildOfBody(ComponentBody componentBody) {
263 if (ParentBody != componentBody) {
264 if (ParentBody != null) {
265 return ParentBody.IsChildOfBody(componentBody);
266 }
267 return false;
268 }
269 return true;
270 }
271
272 public virtual void UnderExplosionStart(Vector3 explosionCenter, float explosionPressure) {
273 float num = Vector3.Distance(Position, explosionCenter);
274 float num2 = 5f * MathF.Sqrt(explosionPressure);
275 float num3 = 1f * MathF.Sqrt(explosionPressure);
276 float strength = num2 / (num / num3 + 1f);
278 "OnComponentBodyExplodedStart",
279 loader => {
280 loader.OnComponentBodyExplodedStart(this, explosionCenter, explosionPressure, ref strength);
281 return false;
282 }
283 );
284 if (strength > 0) {
285 ApplyShaking(strength);
286 }
287 }
288
289 public virtual void UnderExplosion(Vector3 impulse, float damage) {
290 bool setOnFire = true;
291 float fluctuation = 0.5f;
292 float explosionResilience = m_componentHealth?.ExplosionResilience ?? 1f;
293 damage /= explosionResilience;
294 impulse /= explosionResilience;
295 Injury explosionInjury = new ExplosionInjury(damage);
297 "OnComponentBodyExploded",
298 loader => {
299 // ReSharper disable AccessToModifiedClosure
300 loader.OnComponentBodyExploded(this, ref explosionInjury, ref impulse, ref setOnFire, ref fluctuation);
301 // ReSharper restore AccessToModifiedClosure
302 return false;
303 }
304 );
305 impulse *= m_random.Float(1f - fluctuation, 1f + fluctuation);
306 damage *= m_random.Float(1f - fluctuation, 1f + fluctuation);
307 ApplyImpulse(impulse);
308 if (damage > 0f) {
309 Entity.FindComponent<ComponentDamage>()?.Damage(damage);
310 }
311 if (explosionInjury.Amount > 0f) {
312 Entity.FindComponent<ComponentHealth>()?.Injure(explosionInjury);
313 }
314 if (setOnFire) {
315 ComponentOnFire componentOnFire = Entity.FindComponent<ComponentOnFire>();
316 if (componentOnFire != null
317 && m_random.Float(0f, 1f) < MathUtils.Min(damage - 0.1f, 0.5f)) {
318 componentOnFire.SetOnFire(null, m_random.Float(6f, 8f));
319 }
320 }
321 }
322
323 public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
324 base.Load(valuesDictionary, idToEntityMap);
325 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
326 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
327 m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>(true);
329 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
330 m_subsystemParticles = Project.FindSubsystem<SubsystemParticles>(true);
333 m_subsystemPlayers = Project.FindSubsystem<SubsystemPlayers>(true);
334 m_componentHealth = Entity.FindComponent<ComponentHealth>();
335 CanCrouch = Entity.FindComponent<ComponentPlayer>() != null;
336 BoxSize = valuesDictionary.GetValue<Vector3>("BoxSize");
337 Mass = valuesDictionary.GetValue<float>("Mass");
338 Density = valuesDictionary.GetValue<float>("Density");
339 AirDrag = valuesDictionary.GetValue<Vector2>("AirDrag");
340 WaterDrag = valuesDictionary.GetValue<Vector2>("WaterDrag");
341 WaterSwayAngle = valuesDictionary.GetValue<float>("WaterSwayAngle");
342 WaterTurnSpeed = valuesDictionary.GetValue<float>("WaterTurnSpeed");
343 CanEmbedInIce = valuesDictionary.GetValue<bool>("CanEmbedInIce");
344 Velocity = valuesDictionary.GetValue<Vector3>("Velocity").FixNaN();
345 m_embeddedInIceCounter = valuesDictionary.GetValue("EmbeddedInIceCounter", 0);
348 }
349 MaxSmoothRiseHeight = valuesDictionary.GetValue<float>("MaxSmoothRiseHeight");
350 ParentBody = valuesDictionary.GetValue<EntityReference>("ParentBody").GetComponent<ComponentBody>(Entity, idToEntityMap, false);
351 ParentBodyPositionOffset = valuesDictionary.GetValue<Vector3>("ParentBodyPositionOffset");
352 ParentBodyRotationOffset = valuesDictionary.GetValue<Quaternion>("ParentBodyRotationOffset");
353 IsSmoothRiseEnabled = true;
354 IsGravityEnabled = true;
355 IsGroundDragEnabled = true;
356 IsWaterDragEnabled = true;
357 }
358
359 public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap) {
360 base.Save(valuesDictionary, entityToIdMap);
361 if (Velocity != Vector3.Zero) {
362 valuesDictionary.SetValue("Velocity", Velocity.FixNaN());
363 }
364 valuesDictionary.SetValue("EmbeddedInIceCounter", m_embeddedInIceCounter);
366 if (!value.IsNullOrEmpty()) {
367 valuesDictionary.SetValue("ParentBody", value);
368 valuesDictionary.SetValue("ParentBodyPositionOffset", ParentBodyPositionOffset);
369 valuesDictionary.SetValue("ParentBodyRotationOffset", ParentBodyRotationOffset);
370 }
371 }
372
373 public override void OnEntityRemoved() {
374 ParentBody = null;
375 ComponentBody[] array = ChildBodies.ToArray();
376 for (int i = 0; i < array.Length; i++) {
377 array[i].ParentBody = null;
378 }
379 }
380
381 public virtual void Update(float dt) {
382 bool skipVanilla_ = false;
384 "UpdateComponentBody",
385 loader => {
386 loader.UpdateComponentBody(this, dt, skipVanilla_, out bool skipVanilla);
387 skipVanilla_ |= skipVanilla;
388 return false;
389 }
390 );
391 if (skipVanilla_) {
392 return;
393 }
395 if (m_shakingStrength > 1f) {
396 Vector3 vector = default;
397 vector.X = m_shakingStrength * MathF.Sin((float)MathUtils.Remainder(31.0 * m_subsystemTime.GameTime, Math.PI * 2));
398 vector.Y = 0.3f * m_shakingStrength * MathF.Sin((float)MathUtils.Remainder(23.3 * m_subsystemTime.GameTime, Math.PI * 2));
399 vector.Z = m_shakingStrength * MathF.Sin((float)MathUtils.Remainder(27.6 * m_subsystemTime.GameTime, Math.PI * 2));
400 Velocity += vector * dt;
401 m_shakingStrength *= MathUtils.Saturate(1f - 3.5f * dt);
402 }
403 else {
405 }
408 if (m_parentBody != null
409 || m_velocity.LengthSquared() > 9.99999944E-11f
412 m_stoppedTime = 0f;
413 }
414 else {
415 m_stoppedTime += dt;
416 if (m_stoppedTime > 0.5f
417 && !Time.PeriodicEvent(0.25, 0.0)) {
418 return;
419 }
420 }
423 }
425 if (Entity.FindComponent<ComponentRider>().Mount == null) {
427 }
428 }
429 Vector3 position = Position;
430 TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(Terrain.ToCell(position.X), Terrain.ToCell(position.Z));
431 if (chunkAtCell == null
432 || chunkAtCell.State <= TerrainChunkState.InvalidContents4) {
433 if (m_subsystemPlayers.PlayerStartedPlaying) {
435 }
436 return;
437 }
438 if (CanEmbedInIce) {
439 BoundingBox boundingBox = BoundingBox;
440 m_collisionBoxes.Clear();
442 if (IsCollidingWithIce(boundingBox, m_collisionBoxes)) {
444 }
445 else {
447 }
448 if (IsEmbeddedInIce) {
450 return;
451 }
452 }
454 if (BodyCollidable) {
456 }
458 if (TerrainCollidable) {
460 }
461 MoveToFreeSpace(dt);
462 if (IsGravityEnabled) {
463 m_velocity.Y -= 10f * dt;
464 if (ImmersionFactor > 0f && FluidCollidable) {
465 float num = ImmersionFactor
466 * (1f + 0.03f * MathF.Sin((float)MathUtils.Remainder(2.0 * m_subsystemTime.GameTime, 6.2831854820251465)));
467 m_velocity.Y += 10f * (1f / Density * num) * dt;
468 }
469 }
470 float num2 = MathUtils.Saturate(AirDrag.X * dt);
471 float num3 = MathUtils.Saturate(AirDrag.Y * dt);
472 m_velocity.X *= 1f - num2;
473 m_velocity.Y *= 1f - num3;
474 m_velocity.Z *= 1f - num2;
476 && ImmersionFactor > 0f
477 && ImmersionFluidBlock != null
478 && FluidCollidable) {
479 Vector2? vector = m_subsystemFluidBlockBehavior.CalculateFlowSpeed(
480 Terrain.ToCell(position.X),
481 Terrain.ToCell(position.Y),
482 Terrain.ToCell(position.Z)
483 );
484 Vector3 vector2 = vector.HasValue ? new Vector3(vector.Value.X, 0f, vector.Value.Y) : Vector3.Zero;
485 float num4 = 1f;
486 if (ImmersionFluidBlock.FrictionFactor != 1f) {
487 num4 = SimplexNoise.Noise((float)MathUtils.Remainder(6.0 * Time.FrameStartTime + GetHashCode() % 1000, 1000.0)) > 0.5f
488 ? ImmersionFluidBlock.FrictionFactor
489 : 1f;
490 }
491 float f = MathUtils.Saturate(WaterDrag.X * num4 * ImmersionFactor * dt);
492 float f2 = MathUtils.Saturate(WaterDrag.Y * num4 * dt);
493 m_velocity.X = MathUtils.Lerp(m_velocity.X, vector2.X, f);
494 m_velocity.Y = MathUtils.Lerp(m_velocity.Y, vector2.Y, f2);
495 m_velocity.Z = MathUtils.Lerp(m_velocity.Z, vector2.Z, f);
496 if (m_parentBody == null
497 && vector.HasValue
498 && !StandingOnValue.HasValue) {
499 if (WaterTurnSpeed > 0f) {
500 float num5 = MathUtils.Saturate(MathUtils.Lerp(1f, 0f, m_velocity.Length()));
501 Vector2 vector3 = Vector2.Normalize(vector.Value) * num5;
502 Rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, WaterTurnSpeed * (-1f * vector3.X + 0.71f * vector3.Y) * dt);
503 }
504 if (WaterSwayAngle > 0f) {
507 WaterSwayAngle * (float)Math.Sin(200f / Mass * m_subsystemTime.GameTime)
508 );
509 }
510 }
511 }
512 if (m_parentBody != null) {
513 Vector3 vector4 = Vector3.Transform(ParentBodyPositionOffset, m_parentBody.Rotation) + m_parentBody.Position - position;
514 m_velocity = dt > 0f ? vector4 / dt : Vector3.Zero;
516 }
517 StandingOnValue = null;
518 StandingOnBody = null;
520 Vector3 velocity = m_velocity;
521 float num6 = m_velocity.Length();
522 if (num6 > 0f
523 && CrushedTime == 0f) {
524 Vector3 stanceBoxSize = StanceBoxSize;
525 float x = 0.45f * MathUtils.Min(stanceBoxSize.X, stanceBoxSize.Y, stanceBoxSize.Z) / num6;
526 float num7 = dt;
527 while (num7 > 0f) {
528 float num8 = MathUtils.Min(num7, x);
531 num7 -= num8;
532 }
533 }
534 if (ParentBody != null && FixCollisionOnRidingBug) {
535 CollisionVelocityChange = ParentBody.CollisionVelocityChange;
536 }
537 else {
539 }
540 if (IsGroundDragEnabled && StandingOnValue.HasValue) {
542 }
545 && ImmersionDepth > 0.3f
548 m_subsystemAudio.PlayRandomSound("Audio/WaterFallIn", m_random.Float(0.75f, 1f), m_random.Float(-0.3f, 0f), position, 4f, true);
549 m_subsystemParticles.AddParticleSystem(
551 );
552 }
554 && ImmersionDepth > 0f
557 m_subsystemAudio.PlaySound("Audio/SizzleLong", 1f, 0f, position, 4f, true);
558 m_subsystemParticles.AddParticleSystem(
560 );
561 }
562 else if (ImmersionFluidBlock == null) {
563 m_fluidEffectsPlayed = false;
564 }
565 }
566
567 public virtual void UpdateImmersionData() {
568 Vector3 position = Position;
569 int x = Terrain.ToCell(position.X);
570 int y = Terrain.ToCell(position.Y + 0.01f);
571 int z = Terrain.ToCell(position.Z);
572 float? surfaceHeight = m_subsystemFluidBlockBehavior.GetSurfaceHeight(x, y, z, out _);
573 if (surfaceHeight.HasValue) {
574 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x, y, z);
575 ImmersionDepth = MathUtils.Max(surfaceHeight.Value - position.Y, 0f);
578 }
579 else {
580 ImmersionDepth = 0f;
581 ImmersionFactor = 0f;
582 ImmersionFluidBlock = null;
583 }
584 }
585
586 public virtual void MoveToFreeSpace(float dt) {
587 if (MoveToFreeSpaceHelper(0.5f)) {
588 CrushedTime = 0f;
589 return;
590 }
591 if (CrushedTime == 0f) {
592 m_subsystemAudio.PlaySound("Audio/Crushed", 1.5f, m_random.Float(-0.2f, 0.2f), Position, 1f, false);
593 }
594 float targetCrouchFactor = TargetCrouchFactor;
595 float crouchFactor = CrouchFactor;
596 if (CanCrouch && (TargetCrouchFactor != 1f || CrouchFactor != 1f)) {
598 CrouchFactor = 1f;
599 if (MoveToFreeSpaceHelper(0.5f)) {
600 CrushedTime = 0f;
601 return;
602 }
603 }
604 TargetCrouchFactor = targetCrouchFactor;
605 CrouchFactor = crouchFactor;
606 if (MoveToFreeSpaceHelper(1f)) {
607 CrushedTime = 0f;
608 return;
609 }
610 if (CanCrouch && (TargetCrouchFactor != 1f || CrouchFactor != 1f)) {
612 CrouchFactor = 1f;
613 if (MoveToFreeSpaceHelper(1f)) {
614 CrushedTime = 0f;
615 return;
616 }
617 }
618 CrushedTime += dt;
619 }
620
621 public bool IsSpaceFreeToMove(float maxMoveFraction, out Vector3? freePosition, out bool needToTeleport) {
622 needToTeleport = false;
623 freePosition = null;
624 Vector3 stanceBoxSize = StanceBoxSize;
625 Vector3 position = Position;
626 for (int i = 0; i < m_freeSpaceOffsets.Length; i++) {
627 Vector3? vector = null;
628 Vector3 positionToDetect = position + m_freeSpaceOffsets[i];
629 if (Terrain.ToCell(positionToDetect) != Terrain.ToCell(position)) //不能瞬移到不同的格子,只能在相同的格子中瞬移
630 {
631 continue;
632 }
633 BoundingBox boxThere = new(
634 positionToDetect - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f),
635 positionToDetect + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f)
636 );
637 //在检测点处玩家的碰撞箱
638 boxThere.Min += new Vector3(0.01f, MaxSmoothRiseHeight + 0.01f, 0.01f);
639 boxThere.Max -= new Vector3(0.01f);
640 m_collisionBoxes.Clear();
644 if (IsColliding(boxThere, m_collisionBoxes)) //目标碰撞箱存在碰撞
645 {
646 m_stoppedTime = 0f;
647 float pushBack_X = CalculatePushBack(boxThere, 0, m_collisionBoxes, out _);
648 float pushBack_Y = CalculatePushBack(boxThere, 1, m_collisionBoxes, out _);
649 float pushBack_Z = CalculatePushBack(boxThere, 2, m_collisionBoxes, out _);
650 float pushBackXLength = pushBack_X * pushBack_X;
651 float pushBackYLength = pushBack_Y * pushBack_Y;
652 float pushBackZLength = pushBack_Z * pushBack_Z;
653 List<Vector3> list = new();
654 //将pushBack后的点,加入待检查的点当中
655 if (pushBackXLength <= pushBackYLength
656 && pushBackXLength <= pushBackZLength) {
657 list.Add(positionToDetect + new Vector3(pushBack_X, 0f, 0f));
658 if (pushBackYLength <= pushBackZLength) {
659 list.Add(positionToDetect + new Vector3(0f, pushBack_Y, 0f));
660 list.Add(positionToDetect + new Vector3(0f, 0f, pushBack_Z));
661 }
662 else {
663 list.Add(positionToDetect + new Vector3(0f, 0f, pushBack_Z));
664 list.Add(positionToDetect + new Vector3(0f, pushBack_Y, 0f));
665 }
666 }
667 else if (pushBackYLength <= pushBackXLength
668 && pushBackYLength <= pushBackZLength) {
669 list.Add(positionToDetect + new Vector3(0f, pushBack_Y, 0f));
670 if (pushBackXLength <= pushBackZLength) {
671 list.Add(positionToDetect + new Vector3(pushBack_X, 0f, 0f));
672 list.Add(positionToDetect + new Vector3(0f, 0f, pushBack_Z));
673 }
674 else {
675 list.Add(positionToDetect + new Vector3(0f, 0f, pushBack_Z));
676 list.Add(positionToDetect + new Vector3(pushBack_X, 0f, 0f));
677 }
678 }
679 else {
680 list.Add(positionToDetect + new Vector3(0f, 0f, pushBack_Z));
681 if (pushBackXLength <= pushBackYLength) {
682 list.Add(positionToDetect + new Vector3(pushBack_X, 0f, 0f));
683 list.Add(positionToDetect + new Vector3(0f, pushBack_Y, 0f));
684 }
685 else {
686 list.Add(positionToDetect + new Vector3(0f, pushBack_Y, 0f));
687 list.Add(positionToDetect + new Vector3(pushBack_X, 0f, 0f));
688 }
689 }
690 foreach (Vector3 item in list) {
691 if (!(MathF.Abs(item.X - position.X) > stanceBoxSize.X * maxMoveFraction)
692 && !(MathF.Abs(item.Y - position.Y) > stanceBoxSize.Y * maxMoveFraction)
693 && !(MathF.Abs(item.Z - position.Z) > stanceBoxSize.Z * maxMoveFraction)) {
694 boxThere = new BoundingBox(
695 item - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f),
696 item + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f)
697 );
698 boxThere.Min += new Vector3(0.02f, MaxSmoothRiseHeight + 0.02f, 0.02f);
699 boxThere.Max -= new Vector3(0.02f);
700 m_collisionBoxes.Clear();
704 if (!IsColliding(boxThere, m_collisionBoxes)) {
705 vector = item;
706 needToTeleport = true;
707 break;
708 }
709 }
710 }
711 }
712 else {
713 //和目标位置没有碰撞,说明目标位置可以装人
714 vector = positionToDetect;
715 }
716 if (vector.HasValue) {
717 freePosition = vector.Value;
718 return true;
719 }
720 }
721 return false;
722 }
723
724 public bool MoveToFreeSpaceHelper(float maxMoveFraction) {
725 IsSpaceFreeToMove(maxMoveFraction, out Vector3? freePosition, out bool _);
726 if (freePosition.HasValue) {
727 Position = freePosition.Value;
728 return true;
729 }
730 return false;
731 }
732
733 public virtual void MoveWithCollision(float dt, Vector3 move) {
734 Vector3 position = Position;
735 bool isSmoothRising = IsSmoothRiseEnabled && MaxSmoothRiseHeight > 0f && HandleSmoothRise(ref move, position, dt);
736 HandleAxisCollision(1, move.Y, ref position, isSmoothRising);
737 HandleAxisCollision(0, move.X, ref position, isSmoothRising);
738 HandleAxisCollision(2, move.Z, ref position, isSmoothRising);
739 Position = position;
740 }
741
742 public virtual bool HandleSmoothRise(ref Vector3 move, Vector3 position, float dt) {
743 Vector3 stanceBoxSize = StanceBoxSize;
744 BoundingBox box = new(
745 position - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f),
746 position + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f)
747 );
748 box.Min += new Vector3(0.04f, 0f, 0.04f);
749 box.Max -= new Vector3(0.04f, 0f, 0.04f);
750 m_collisionBoxes.Clear();
753 float num = MathUtils.Max(CalculatePushBack(box, 1, m_collisionBoxes, out CollisionBox pushingCollisionBox), 0f);
754 if (!BlocksManager.Blocks[Terrain.ExtractContents(pushingCollisionBox.BlockValue)].NoSmoothRise
755 && num > 0.04f) {
756 float x = MathUtils.Min(4.5f * dt, num);
757 move.Y = MathUtils.Max(move.Y, x);
758 m_velocity.Y = MathUtils.Max(m_velocity.Y, 0f);
759 StandingOnValue = pushingCollisionBox.BlockValue;
760 StandingOnBody = pushingCollisionBox.ComponentBody;
761 m_stoppedTime = 0f;
762 return true;
763 }
764 return false;
765 }
766
767 public virtual void HandleAxisCollision(int axis, float move, ref Vector3 position, bool isSmoothRising) {
768 Vector3 stanceBoxSize = StanceBoxSize;
769 m_collisionBoxes.Clear();
771 && m_crouchFactor >= 1f
772 && axis != 1) {
773 FindCrouchCollisionBoxes(position, new Vector2(stanceBoxSize.X - 0.08f, stanceBoxSize.Z - 0.08f), m_collisionBoxes);
774 }
775 Vector3 vector;
776 switch (axis) {
777 case 0:
778 position.X += move;
779 vector = new Vector3(0f, 0.04f, 0.04f);
780 break;
781 case 1:
782 position.Y += move;
783 vector = new Vector3(0.04f, 0f, 0.04f);
784 break;
785 default:
786 position.Z += move;
787 vector = new Vector3(0.04f, 0.04f, 0f);
788 break;
789 }
790 BoundingBox boundingBox = new(
791 position - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f) + vector,
792 position + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f) - vector
793 );
796 float num;
797 CollisionBox pushingCollisionBox;
798 if (axis != 1 || isSmoothRising) {
799 BoundingBox smoothRiseBox = boundingBox;
800 smoothRiseBox.Min.Y += MaxSmoothRiseHeight;
801 num = CalculateSmoothRisePushBack(boundingBox, smoothRiseBox, axis, m_collisionBoxes, out pushingCollisionBox);
802 }
803 else {
804 num = CalculatePushBack(boundingBox, axis, m_collisionBoxes, out pushingCollisionBox);
805 }
806 BoundingBox box = new(
807 position - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f) + vector,
808 position + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f) - vector
809 );
810 float num2 = CalculatePushBack(box, axis, m_bodiesCollisionBoxes, out CollisionBox pushingCollisionBox2);
811 if (MathF.Abs(num) > MathF.Abs(num2)) {
812 if (num == 0f) {
813 return;
814 }
815 int num3 = Terrain.ExtractContents(pushingCollisionBox.BlockValue);
817 SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(num3);
818 for (int i = 0; i < blockBehaviors.Length; i++) {
819 Vector3 vector2 = (pushingCollisionBox.Box.Min + pushingCollisionBox.Box.Max) / 2f;
821 Terrain.ToCell(vector2.X),
822 Terrain.ToCell(vector2.Y),
823 Terrain.ToCell(vector2.Z),
824 axis,
826 );
827 blockBehaviors[i].OnCollide(cellFace, GetVectorComponent(m_velocity, axis), this);
828 }
829 }
830 switch (axis) {
831 case 0:
832 position.X += num;
833 m_velocity.X = pushingCollisionBox.BlockVelocity.X;
834 break;
835 case 1:
836 position.Y += num;
837 m_velocity.Y = pushingCollisionBox.BlockVelocity.Y;
838 if (move < 0f) {
839 StandingOnValue = pushingCollisionBox.BlockValue;
840 StandingOnBody = pushingCollisionBox.ComponentBody;
841 StandingOnVelocity = pushingCollisionBox.BlockVelocity;
842 }
843 break;
844 default:
845 position.Z += num;
846 m_velocity.Z = pushingCollisionBox.BlockVelocity.Z;
847 break;
848 }
849 }
850 else {
851 if (num2 == 0f) {
852 return;
853 }
854 ComponentBody componentBody = pushingCollisionBox2.ComponentBody;
855 float targetMass = componentBody.CanBePushedByOtherBodies ? componentBody.Mass : 1e9f;
856 switch (axis) {
857 case 0:
859 m_velocity.X,
860 componentBody.m_velocity.X,
861 Mass,
862 targetMass,
863 0.5f,
864 out m_velocity.X,
865 out componentBody.m_velocity.X
866 );
867 position.X += num2;
868 break;
869 case 1:
871 m_velocity.Y,
872 componentBody.m_velocity.Y,
873 Mass,
874 targetMass,
875 0.5f,
876 out m_velocity.Y,
877 out componentBody.m_velocity.Y
878 );
879 position.Y += num2;
880 if (move < 0f) {
881 StandingOnValue = pushingCollisionBox2.BlockValue;
882 StandingOnBody = pushingCollisionBox2.ComponentBody;
883 StandingOnVelocity = new Vector3(componentBody.m_velocity.X, 0f, componentBody.m_velocity.Z);
884 }
885 break;
886 default:
888 m_velocity.Z,
889 componentBody.m_velocity.Z,
890 Mass,
891 targetMass,
892 0.5f,
893 out m_velocity.Z,
894 out componentBody.m_velocity.Z
895 );
896 position.Z += num2;
897 break;
898 }
899 CollidedWithBody?.Invoke(componentBody);
900 componentBody.CollidedWithBody?.Invoke(this);
901 }
902 }
903
904 public virtual void FindBodiesCollisionBoxes(Vector3 position, DynamicArray<CollisionBox> result) {
905 m_componentBodies.Clear();
906 m_subsystemBodies.FindBodiesAroundPoint(new Vector2(position.X, position.Z), 4f, m_componentBodies);
907 for (int i = 0; i < m_componentBodies.Count; i++) {
908 ComponentBody componentBody = m_componentBodies.Array[i];
909 if (!componentBody.BodyCollidable) {
910 continue;
911 }
912 if (componentBody != this
913 && componentBody != m_parentBody
914 && componentBody.m_parentBody != this) {
915 result.Add(new CollisionBox { Box = componentBody.BoundingBox, ComponentBody = componentBody });
916 }
917 }
918 }
919
920 public virtual void FindMovingBlocksCollisionBoxes(Vector3 position, DynamicArray<CollisionBox> result) {
921 Vector3 stanceBoxSize = StanceBoxSize;
922 BoundingBox boundingBox = new(
923 position - new Vector3(stanceBoxSize.X / 2f, 0f, stanceBoxSize.Z / 2f),
924 position + new Vector3(stanceBoxSize.X / 2f, stanceBoxSize.Y, stanceBoxSize.Z / 2f)
925 );
926 boundingBox.Min -= new Vector3(1f);
927 boundingBox.Max += new Vector3(1f);
928 m_movingBlockSets.Clear();
929 m_subsystemMovingBlocks.FindMovingBlocks(boundingBox, false, m_movingBlockSets);
930 for (int i = 0; i < m_movingBlockSets.Count; i++) {
932 IMovingBlockSet movingBlockSet = m_movingBlockSets.Array[i];
933 for (int j = 0; j < movingBlockSet.Blocks.Count; j++) {
934 MovingBlock movingBlock = movingBlockSet.Blocks[j];
935 int num = Terrain.ExtractContents(movingBlock.Value);
936 Block block = BlocksManager.Blocks[num];
937 if (block.IsCollidable_(movingBlock.Value)) {
938 BoundingBox[] customCollisionBoxes = block.GetCustomCollisionBoxes(m_subsystemTerrain, movingBlock.Value);
939 Vector3 vector = new Vector3(movingBlock.Offset) + movingBlockSet.Position;
940 for (int k = 0; k < customCollisionBoxes.Length; k++) {
941 result.Add(
942 new CollisionBox {
943 Box = new BoundingBox(vector + customCollisionBoxes[k].Min, vector + customCollisionBoxes[k].Max),
944 BlockValue = movingBlock.Value,
945 BlockVelocity = movingBlockSet.CurrentVelocity
946 }
947 );
948 }
949 }
950 }
951 }
952 }
953
954 public virtual void FindTerrainCollisionBoxes(BoundingBox box, DynamicArray<CollisionBox> result) {
955 if (!TerrainCollidable) {
956 return;
957 }
958 Point3 point = Terrain.ToCell(box.Min);
959 Point3 point2 = Terrain.ToCell(box.Max);
960 point.Y = MathUtils.Max(point.Y, 0);
961 point2.Y = MathUtils.Min(point2.Y, 255);
962 if (point.Y > point2.Y) {
963 return;
964 }
965 for (int i = point.X; i <= point2.X; i++) {
966 for (int j = point.Z; j <= point2.Z; j++) {
967 TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(i, j);
968 if (chunkAtCell == null) {
969 continue;
970 }
971 int num = TerrainChunk.CalculateCellIndex(i & 0xF, point.Y, j & 0xF);
972 int num2 = point.Y;
973 while (num2 <= point2.Y) {
974 int cellValueFast = chunkAtCell.GetCellValueFast(num);
975 int num3 = Terrain.ExtractContents(cellValueFast);
976 if (num3 != 0) {
977 Block block = BlocksManager.Blocks[num3];
978 if (block.IsCollidable_(cellValueFast) && TerrainCollidable) {
979 BoundingBox[] customCollisionBoxes = block.GetCustomCollisionBoxes(m_subsystemTerrain, cellValueFast);
980 Vector3 vector = new(i, num2, j);
981 for (int k = 0; k < customCollisionBoxes.Length; k++) {
982 result.Add(
983 new CollisionBox {
984 Box = new BoundingBox(vector + customCollisionBoxes[k].Min, vector + customCollisionBoxes[k].Max),
985 BlockValue = cellValueFast
986 }
987 );
988 }
989 }
990 }
991 num2++;
992 num++;
993 }
994 }
995 }
996 }
997
998 public virtual void FindCrouchCollisionBoxes(Vector3 position, Vector2 overhang, DynamicArray<CollisionBox> result) {
999 int num = Terrain.ToCell(position.X);
1000 int num2 = Terrain.ToCell(position.Y);
1001 int num3 = Terrain.ToCell(position.Z);
1002 if (BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num, num2 - 1, num3)]
1003 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3))) {
1004 return;
1005 }
1006 bool num4 = position.X < num + 0.5f;
1007 bool flag = position.Z < num3 + 0.5f;
1008 CollisionBox item;
1009 if (num4) {
1010 if (flag) {
1011 bool isCollidable = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num, num2 - 1, num3 - 1)]
1012 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 - 1));
1013 bool isCollidable2 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num - 1, num2 - 1, num3)]
1014 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3));
1015 bool isCollidable3 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num - 1, num2 - 1, num3 - 1)]
1016 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3 - 1));
1017 if ((isCollidable && !isCollidable2)
1018 || (!isCollidable && !isCollidable2 && isCollidable3)) {
1019 item = new CollisionBox {
1020 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1021 };
1022 result.Add(item);
1023 }
1024 if ((!isCollidable && isCollidable2)
1025 || (!isCollidable && !isCollidable2 && isCollidable3)) {
1026 item = new CollisionBox {
1027 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1028 };
1029 result.Add(item);
1030 }
1031 if (isCollidable && isCollidable2) {
1032 item = new CollisionBox {
1033 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)),
1034 BlockValue = 0
1035 };
1036 result.Add(item);
1037 }
1038 }
1039 else {
1040 bool isCollidable4 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num, num2 - 1, num3 + 1)]
1041 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 + 1));
1042 bool isCollidable5 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num - 1, num2 - 1, num3)]
1043 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3));
1044 bool isCollidable6 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num - 1, num2 - 1, num3 + 1)]
1045 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3 + 1));
1046 if ((isCollidable4 && !isCollidable5)
1047 || (!isCollidable4 && !isCollidable5 && isCollidable6)) {
1048 item = new CollisionBox {
1049 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)), BlockValue = 0
1050 };
1051 result.Add(item);
1052 }
1053 if ((!isCollidable4 && isCollidable5)
1054 || (!isCollidable4 && !isCollidable5 && isCollidable6)) {
1055 item = new CollisionBox {
1056 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1057 };
1058 result.Add(item);
1059 }
1060 if (isCollidable4 && isCollidable5) {
1061 item = new CollisionBox {
1062 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)),
1063 BlockValue = 0
1064 };
1065 result.Add(item);
1066 }
1067 }
1068 }
1069 else if (flag) {
1070 bool isCollidable7 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num, num2 - 1, num3 - 1)]
1071 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 - 1));
1072 bool isCollidable8 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num + 1, num2 - 1, num3)]
1073 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3));
1074 bool isCollidable9 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num + 1, num2 - 1, num3 - 1)]
1075 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3 - 1));
1076 if ((isCollidable7 && !isCollidable8)
1077 || (!isCollidable7 && !isCollidable8 && isCollidable9)) {
1078 item = new CollisionBox {
1079 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1080 };
1081 result.Add(item);
1082 }
1083 if ((!isCollidable7 && isCollidable8)
1084 || (!isCollidable7 && !isCollidable8 && isCollidable9)) {
1085 item = new CollisionBox {
1086 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)), BlockValue = 0
1087 };
1088 result.Add(item);
1089 }
1090 if (isCollidable7 && isCollidable8) {
1091 item = new CollisionBox {
1092 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)),
1093 BlockValue = 0
1094 };
1095 result.Add(item);
1096 }
1097 }
1098 else {
1099 bool isCollidable10 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num, num2 - 1, num3 + 1)]
1100 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 + 1));
1101 bool isCollidable11 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num + 1, num2 - 1, num3)]
1102 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3));
1103 bool isCollidable12 = BlocksManager.Blocks[m_subsystemTerrain.Terrain.GetCellContents(num + 1, num2 - 1, num3 + 1)]
1104 .IsCollidable_(m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3 + 1));
1105 if ((isCollidable10 && !isCollidable11)
1106 || (!isCollidable10 && !isCollidable11 && isCollidable12)) {
1107 item = new CollisionBox {
1108 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)), BlockValue = 0
1109 };
1110 result.Add(item);
1111 }
1112 if ((!isCollidable10 && isCollidable11)
1113 || (!isCollidable10 && !isCollidable11 && isCollidable12)) {
1114 item = new CollisionBox {
1115 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)), BlockValue = 0
1116 };
1117 result.Add(item);
1118 }
1119 if (isCollidable10 && isCollidable11) {
1120 item = new CollisionBox {
1121 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1 - overhang.Y)),
1122 BlockValue = 0
1123 };
1124 result.Add(item);
1125 }
1126 }
1127 }
1128
1129 public virtual bool IsColliding(BoundingBox box, DynamicArray<CollisionBox> collisionBoxes) {
1130 for (int i = 0; i < collisionBoxes.Count; i++) {
1131 if (box.Intersection(collisionBoxes.Array[i].Box)) {
1132 return true;
1133 }
1134 }
1135 return false;
1136 }
1137
1138 public virtual bool IsCollidingWithIce(BoundingBox box, DynamicArray<CollisionBox> collisionBoxes) {
1139 for (int i = 0; i < collisionBoxes.Count; i++) {
1140 CollisionBox collisionBox = collisionBoxes.Array[i];
1141 if (box.Intersection(collisionBox.Box)
1142 && Terrain.ExtractContents(collisionBox.BlockValue) == 62) {
1143 return true;
1144 }
1145 }
1146 return false;
1147 }
1148
1149 public virtual float CalculatePushBack(BoundingBox box,
1150 int axis,
1151 DynamicArray<CollisionBox> collisionBoxes,
1152 out CollisionBox pushingCollisionBox) {
1153 pushingCollisionBox = default;
1154 float num = 0f;
1155 for (int i = 0; i < collisionBoxes.Count; i++) {
1156 float num2 = CalculateBoxBoxOverlap(ref box, ref collisionBoxes.Array[i].Box, axis);
1157 if (MathF.Abs(num2) > MathF.Abs(num)) {
1158 num = num2;
1159 pushingCollisionBox = collisionBoxes.Array[i];
1160 }
1161 }
1162 return num;
1163 }
1164
1165 public virtual float CalculateSmoothRisePushBack(BoundingBox normalBox,
1166 BoundingBox smoothRiseBox,
1167 int axis,
1168 DynamicArray<CollisionBox> collisionBoxes,
1169 out CollisionBox pushingCollisionBox) {
1170 pushingCollisionBox = default;
1171 float num = 0f;
1172 for (int i = 0; i < collisionBoxes.Count; i++) {
1173 float num2 = !BlocksManager.Blocks[Terrain.ExtractContents(collisionBoxes.Array[i].BlockValue)].NoSmoothRise
1174 ? CalculateBoxBoxOverlap(ref smoothRiseBox, ref collisionBoxes.Array[i].Box, axis)
1175 : CalculateBoxBoxOverlap(ref normalBox, ref collisionBoxes.Array[i].Box, axis);
1176 if (MathF.Abs(num2) > MathF.Abs(num)) {
1177 num = num2;
1178 pushingCollisionBox = collisionBoxes.Array[i];
1179 }
1180 }
1181 return num;
1182 }
1183
1184 public static float CalculateBoxBoxOverlap(ref BoundingBox b1, ref BoundingBox b2, int axis) {
1185 if (b1.Max.X <= b2.Min.X
1186 || b1.Min.X >= b2.Max.X
1187 || b1.Max.Y <= b2.Min.Y
1188 || b1.Min.Y >= b2.Max.Y
1189 || b1.Max.Z <= b2.Min.Z
1190 || b1.Min.Z >= b2.Max.Z) {
1191 return 0f;
1192 }
1193 switch (axis) {
1194 case 0: {
1195 float num13 = b1.Min.X + b1.Max.X;
1196 float num14 = b2.Min.X + b2.Max.X;
1197 float num15 = b1.Max.X - b1.Min.X;
1198 float num16 = b2.Max.X - b2.Min.X;
1199 float num17 = num14 - num13;
1200 float num18 = num15 + num16;
1201 return 0.5f * (num17 > 0f ? num17 - num18 : num17 + num18);
1202 }
1203 case 1: {
1204 float num7 = b1.Min.Y + b1.Max.Y;
1205 float num8 = b2.Min.Y + b2.Max.Y;
1206 float num9 = b1.Max.Y - b1.Min.Y;
1207 float num10 = b2.Max.Y - b2.Min.Y;
1208 float num11 = num8 - num7;
1209 float num12 = num9 + num10;
1210 return 0.5f * (num11 > 0f ? num11 - num12 : num11 + num12);
1211 }
1212 default: {
1213 float num = b1.Min.Z + b1.Max.Z;
1214 float num2 = b2.Min.Z + b2.Max.Z;
1215 float num3 = b1.Max.Z - b1.Min.Z;
1216 float num4 = b2.Max.Z - b2.Min.Z;
1217 float num5 = num2 - num;
1218 float num6 = num3 + num4;
1219 return 0.5f * (num5 > 0f ? num5 - num6 : num5 + num6);
1220 }
1221 }
1222 }
1223
1224 public static float GetVectorComponent(Vector3 v, int axis) {
1225 switch (axis) {
1226 case 0: return v.X;
1227 case 1: return v.Y;
1228 default: return v.Z;
1229 }
1230 }
1231
1232 public static void InelasticCollision(float v1,
1233 float v2,
1234 float m1,
1235 float m2,
1236 float cr,
1237 out float result1,
1238 out float result2) {
1239 float num = 1f / (m1 + m2);
1240 result1 = (cr * m2 * (v2 - v1) + m1 * v1 + m2 * v2) * num;
1241 result2 = (cr * m1 * (v1 - v2) + m1 * v1 + m2 * v2) * num;
1242 }
1243
1244 public virtual bool MoveToFreeSpace() {
1245 Vector3 boxSize = BoxSize;
1246 Vector3 position = Position;
1247 for (int i = 0; i < m_freeSpaceOffsets.Length; i++) {
1248 Vector3? vector = null;
1249 Vector3 vector2 = position + m_freeSpaceOffsets[i];
1250 if (Terrain.ToCell(vector2) != Terrain.ToCell(position)) {
1251 continue;
1252 }
1253 BoundingBox box = new(
1254 vector2 - new Vector3(boxSize.X / 2f, 0f, boxSize.Z / 2f),
1255 vector2 + new Vector3(boxSize.X / 2f, boxSize.Y, boxSize.Z / 2f)
1256 );
1257 box.Min += new Vector3(0.01f, MaxSmoothRiseHeight + 0.01f, 0.01f);
1258 box.Max -= new Vector3(0.01f);
1259 m_collisionBoxes.Clear();
1263 if (!IsColliding(box, m_collisionBoxes)) {
1264 vector = vector2;
1265 }
1266 else {
1267 m_stoppedTime = 0f;
1268 float num = CalculatePushBack(box, 0, m_collisionBoxes, out CollisionBox _);
1269 float num2 = CalculatePushBack(box, 1, m_collisionBoxes, out CollisionBox _);
1270 float num3 = CalculatePushBack(box, 2, m_collisionBoxes, out CollisionBox _);
1271 float num4 = num * num;
1272 float num5 = num2 * num2;
1273 float num6 = num3 * num3;
1274 List<Vector3> list = new();
1275 if (num4 <= num5
1276 && num4 <= num6) {
1277 list.Add(vector2 + new Vector3(num, 0f, 0f));
1278 if (num5 <= num6) {
1279 list.Add(vector2 + new Vector3(0f, num2, 0f));
1280 list.Add(vector2 + new Vector3(0f, 0f, num3));
1281 }
1282 else {
1283 list.Add(vector2 + new Vector3(0f, 0f, num3));
1284 list.Add(vector2 + new Vector3(0f, num2, 0f));
1285 }
1286 }
1287 else if (num5 <= num4
1288 && num5 <= num6) {
1289 list.Add(vector2 + new Vector3(0f, num2, 0f));
1290 if (num4 <= num6) {
1291 list.Add(vector2 + new Vector3(num, 0f, 0f));
1292 list.Add(vector2 + new Vector3(0f, 0f, num3));
1293 }
1294 else {
1295 list.Add(vector2 + new Vector3(0f, 0f, num3));
1296 list.Add(vector2 + new Vector3(num, 0f, 0f));
1297 }
1298 }
1299 else {
1300 list.Add(vector2 + new Vector3(0f, 0f, num3));
1301 if (num4 <= num5) {
1302 list.Add(vector2 + new Vector3(num, 0f, 0f));
1303 list.Add(vector2 + new Vector3(0f, num2, 0f));
1304 }
1305 else {
1306 list.Add(vector2 + new Vector3(0f, num2, 0f));
1307 list.Add(vector2 + new Vector3(num, 0f, 0f));
1308 }
1309 }
1310 foreach (Vector3 item in list) {
1311 box = new BoundingBox(
1312 item - new Vector3(boxSize.X / 2f, 0f, boxSize.Z / 2f),
1313 item + new Vector3(boxSize.X / 2f, boxSize.Y, boxSize.Z / 2f)
1314 );
1315 box.Min += new Vector3(0.02f, MaxSmoothRiseHeight + 0.02f, 0.02f);
1316 box.Max -= new Vector3(0.02f);
1317 m_collisionBoxes.Clear();
1321 if (!IsColliding(box, m_collisionBoxes)) {
1322 vector = item;
1323 break;
1324 }
1325 }
1326 }
1327 if (vector.HasValue) {
1328 Position = vector.Value;
1329 return true;
1330 }
1331 }
1332 return false;
1333 }
1334
1335 public virtual void FindSneakCollisionBoxes(Vector3 position, Vector2 overhang, DynamicArray<CollisionBox> result) {
1336 int num = Terrain.ToCell(position.X);
1337 int num2 = Terrain.ToCell(position.Y);
1338 int num3 = Terrain.ToCell(position.Z);
1339 int value = m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3);
1341 return;
1342 }
1343 bool num4 = position.X < num + 0.5f;
1344 bool flag = position.Z < num3 + 0.5f;
1345 CollisionBox item;
1346 if (num4) {
1347 if (flag) {
1348 int value1 = m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 - 1);
1349 int value2 = m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3);
1350 int value3 = m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3 - 1);
1351 bool isCollidable = BlocksManager.Blocks[Terrain.ExtractContents(value1)].IsCollidable_(value1);
1352 bool isCollidable2 = BlocksManager.Blocks[Terrain.ExtractContents(value2)].IsCollidable_(value2);
1353 bool isCollidable3 = BlocksManager.Blocks[Terrain.ExtractContents(value3)].IsCollidable_(value3);
1354 if ((isCollidable && !isCollidable2)
1355 || (!isCollidable && !isCollidable2) & isCollidable3) {
1356 item = new CollisionBox {
1357 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1358 };
1359 result.Add(item);
1360 }
1361 if ((!isCollidable && isCollidable2)
1362 || (!isCollidable && !isCollidable2) & isCollidable3) {
1363 item = new CollisionBox {
1364 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1365 };
1366 result.Add(item);
1367 }
1368 if (isCollidable && isCollidable2) {
1369 item = new CollisionBox {
1370 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)),
1371 BlockValue = 0
1372 };
1373 result.Add(item);
1374 }
1375 }
1376 else {
1377 int value4 = m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 + 1);
1378 int value5 = m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3);
1379 int value6 = m_subsystemTerrain.Terrain.GetCellValue(num - 1, num2 - 1, num3 + 1);
1380 bool isCollidable4 = BlocksManager.Blocks[Terrain.ExtractContents(value4)].IsCollidable_(value4);
1381 bool isCollidable5 = BlocksManager.Blocks[Terrain.ExtractContents(value5)].IsCollidable_(value5);
1382 bool isCollidable6 = BlocksManager.Blocks[Terrain.ExtractContents(value6)].IsCollidable_(value6);
1383 if ((isCollidable4 && !isCollidable5)
1384 || (!isCollidable4 && !isCollidable5) & isCollidable6) {
1385 item = new CollisionBox {
1386 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)), BlockValue = 0
1387 };
1388 result.Add(item);
1389 }
1390 if ((!isCollidable4 && isCollidable5)
1391 || (!isCollidable4 && !isCollidable5) & isCollidable6) {
1392 item = new CollisionBox {
1393 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1394 };
1395 result.Add(item);
1396 }
1397 if (isCollidable4 && isCollidable5) {
1398 item = new CollisionBox {
1399 Box = new BoundingBox(new Vector3(num + overhang.X, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)),
1400 BlockValue = 0
1401 };
1402 result.Add(item);
1403 }
1404 }
1405 }
1406 else if (flag) {
1407 int value7 = m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 - 1);
1408 int value8 = m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3);
1409 int value9 = m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3 - 1);
1410 bool isCollidable7 = BlocksManager.Blocks[Terrain.ExtractContents(value7)].IsCollidable_(value7);
1411 bool isCollidable8 = BlocksManager.Blocks[Terrain.ExtractContents(value8)].IsCollidable_(value8);
1412 bool isCollidable9 = BlocksManager.Blocks[Terrain.ExtractContents(value9)].IsCollidable_(value9);
1413 if ((isCollidable7 && !isCollidable8)
1414 || (!isCollidable7 && !isCollidable8) & isCollidable9) {
1415 item = new CollisionBox {
1416 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1, num2 + 1, num3 + 1)), BlockValue = 0
1417 };
1418 result.Add(item);
1419 }
1420 if ((!isCollidable7 && isCollidable8)
1421 || (!isCollidable7 && !isCollidable8) & isCollidable9) {
1422 item = new CollisionBox {
1423 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)), BlockValue = 0
1424 };
1425 result.Add(item);
1426 }
1427 if (isCollidable7 && isCollidable8) {
1428 item = new CollisionBox {
1429 Box = new BoundingBox(new Vector3(num, num2, num3 + overhang.Y), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)),
1430 BlockValue = 0
1431 };
1432 result.Add(item);
1433 }
1434 }
1435 else {
1436 int value10 = m_subsystemTerrain.Terrain.GetCellValue(num, num2 - 1, num3 + 1);
1437 int value11 = m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3);
1438 int value12 = m_subsystemTerrain.Terrain.GetCellValue(num + 1, num2 - 1, num3 + 1);
1439 bool isCollidable10 = BlocksManager.Blocks[Terrain.ExtractContents(value10)].IsCollidable_(value10);
1440 bool isCollidable11 = BlocksManager.Blocks[Terrain.ExtractContents(value11)].IsCollidable_(value11);
1441 bool isCollidable12 = BlocksManager.Blocks[Terrain.ExtractContents(value12)].IsCollidable_(value12);
1442 if ((isCollidable10 && !isCollidable11)
1443 || (!isCollidable10 && !isCollidable11) & isCollidable12) {
1444 item = new CollisionBox {
1445 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1, num2 + 1, num3 + 1 - overhang.Y)), BlockValue = 0
1446 };
1447 result.Add(item);
1448 }
1449 if ((!isCollidable10 && isCollidable11)
1450 || (!isCollidable10 && !isCollidable11) & isCollidable12) {
1451 item = new CollisionBox {
1452 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1)), BlockValue = 0
1453 };
1454 result.Add(item);
1455 }
1456 if (isCollidable10 && isCollidable11) {
1457 item = new CollisionBox {
1458 Box = new BoundingBox(new Vector3(num, num2, num3), new Vector3(num + 1 - overhang.X, num2 + 1, num3 + 1 - overhang.Y)),
1459 BlockValue = 0
1460 };
1461 result.Add(item);
1462 }
1463 }
1464 }
1465 }
1466}
Engine.Vector3 Vector3
static float Remainder(float x, float y)
static int Min(int x1, int x2)
static float Saturate(float x)
static int Max(int x1, int x2)
static float Lerp(float x1, float x2, float f)
static bool PeriodicEvent(double period, double offset)
定义 Time.cs:63
static double FrameStartTime
定义 Time.cs:42
bool HasCollisionBehavior
virtual bool IsCollidable_(int value)
bool NoSmoothRise
virtual BoundingBox[] GetCustomCollisionBoxes(SubsystemTerrain terrain, int value)
static FluidBlock[] FluidBlocks
DynamicArray< CollisionBox > m_bodiesCollisionBoxes
virtual void HandleAxisCollision(int axis, float move, ref Vector3 position, bool isSmoothRising)
virtual Vector3 ParentBodyPositionOffset
virtual void Update(float dt)
virtual float ImmersionFactor
static float CalculateBoxBoxOverlap(ref BoundingBox b1, ref BoundingBox b2, int axis)
SubsystemTime m_subsystemTime
DynamicArray< IMovingBlockSet > m_movingBlockSets
SubsystemFluidBlockBehavior m_subsystemFluidBlockBehavior
virtual ComponentBody ParentBody
SubsystemAudio m_subsystemAudio
List< ComponentBody > m_childBodies
SubsystemBlockBehaviors m_subsystemBlockBehaviors
virtual float CalculateSmoothRisePushBack(BoundingBox normalBox, BoundingBox smoothRiseBox, int axis, DynamicArray< CollisionBox > collisionBoxes, out CollisionBox pushingCollisionBox)
virtual Vector3 StandingOnVelocity
virtual float CalculatePushBack(BoundingBox box, int axis, DynamicArray< CollisionBox > collisionBoxes, out CollisionBox pushingCollisionBox)
virtual void ApplyImpulse(Vector3 impulse)
virtual void ApplyDirectMove(Vector3 directMove)
virtual ReadOnlyList< ComponentBody > ChildBodies
virtual bool CanBePushedByOtherBodies
virtual Action< Attackment > Attacked
virtual float TargetCrouchFactor
virtual void FindTerrainCollisionBoxes(BoundingBox box, DynamicArray< CollisionBox > result)
virtual Quaternion ParentBodyRotationOffset
ComponentHealth m_componentHealth
SubsystemParticles m_subsystemParticles
const float SleepThresholdSpeed
virtual Vector3 CollisionVelocityChange
virtual void FindSneakCollisionBoxes(Vector3 position, Vector2 overhang, DynamicArray< CollisionBox > result)
DynamicArray< CollisionBox > m_collisionBoxes
virtual bool FixCollisionOnRidingBug
virtual BoundingBox BoundingBox
virtual bool HandleSmoothRise(ref Vector3 move, Vector3 position, float dt)
override void OnEntityRemoved()
virtual float FloatUpdateOrder
override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
virtual void UpdateImmersionData()
virtual ComponentBody StandingOnBody
virtual void MoveToFreeSpace(float dt)
virtual float MaxSmoothRiseHeight
virtual bool IsCollidingWithIce(BoundingBox box, DynamicArray< CollisionBox > collisionBoxes)
virtual void FindBodiesCollisionBoxes(Vector3 position, DynamicArray< CollisionBox > result)
void ApplyShaking(float strength)
static float GetVectorComponent(Vector3 v, int axis)
virtual bool MoveToFreeSpace()
virtual ? int StandingOnValue
virtual bool IsSmoothRiseEnabled
virtual Vector2 WaterDrag
virtual void FindCrouchCollisionBoxes(Vector3 position, Vector2 overhang, DynamicArray< CollisionBox > result)
bool IsSpaceFreeToMove(float maxMoveFraction, out Vector3? freePosition, out bool needToTeleport)
virtual bool CrouchPreventsFalling
virtual bool IsWaterDragEnabled
DynamicArray< CollisionBox > m_movingBlocksCollisionBoxes
virtual void MoveWithCollision(float dt, Vector3 move)
bool MoveToFreeSpaceHelper(float maxMoveFraction)
virtual void FindMovingBlocksCollisionBoxes(Vector3 position, DynamicArray< CollisionBox > result)
static bool ResetVelocityOnProjectLoad
virtual bool IsChildOfBody(ComponentBody componentBody)
virtual bool IsColliding(BoundingBox box, DynamicArray< CollisionBox > collisionBoxes)
SubsystemTerrain m_subsystemTerrain
SubsystemMovingBlocks m_subsystemMovingBlocks
override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
SubsystemPlayers m_subsystemPlayers
virtual bool IsGroundDragEnabled
static Vector3[] m_freeSpaceOffsets
virtual Action< IMovingBlockSet > CollidedWithMovingBlock
SubsystemBodies m_subsystemBodies
DynamicArray< ComponentBody > m_componentBodies
virtual Vector3 StanceBoxSize
virtual void UnderExplosionStart(Vector3 explosionCenter, float explosionPressure)
virtual FluidBlock ImmersionFluidBlock
virtual Action< ComponentBody > CollidedWithBody
static void InelasticCollision(float v1, float v2, float m1, float m2, float cr, out float result1, out float result2)
virtual void UnderExplosion(Vector3 impulse, float damage)
virtual void SetOnFire(ComponentCreature attacker, float duration)
static float Noise(float x)
virtual void OnCollide(CellFace cellFace, float velocity, ComponentBody componentBody)
static int CalculateCellIndex(int x, int y, int z)
TerrainChunkState State
virtual int GetCellValueFast(int index)
static int ExtractContents(int value)
static int ToCell(float x)
ValuesDictionary ValuesDictionary
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
List< MovingBlock > Blocks
UpdateOrder UpdateOrder
bool Intersection(BoundingBox box)
static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
static Vector2 Normalize(Vector2 v)
static Vector3 Lerp(Vector3 v1, Vector3 v2, float f)
static Vector3 Transform(Vector3 v, Matrix m)
static Vector3 Normalize(Vector3 v)
static readonly Vector3 Zero
static float Distance(Vector3 v1, Vector3 v2)
static readonly Vector3 UnitX
static readonly Vector3 UnitY
static CellFace FromAxisAndDirection(int x, int y, int z, int axis, float direction)
ValuesDictionary ValuesDictionaryForMods
模组如果需要添加或使用额外信息,可以在这个ValuesDictionary读写元素
static EntityReference FromId(Component component)