mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Moves all of the PhysicsComponent data to the CollidableComponent, and marks the PhysicsComponent as obsolete.
This commit is contained in:
@@ -103,7 +103,7 @@ namespace Robust.Client.Debugging
|
||||
var physBody = (IPhysBody)boundingBox;
|
||||
|
||||
// all entities have a TransformComponent
|
||||
var transform = physBody.Owner.Transform;
|
||||
var transform = physBody.Entity.Transform;
|
||||
|
||||
// if not on the same map, continue
|
||||
if (transform.MapID != _eyeManager.CurrentMap || !transform.IsMapTransform)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Physics;
|
||||
@@ -11,7 +12,35 @@ using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
public class CollidableComponent : Component, ICollidableComponent
|
||||
public interface ICollideBehavior
|
||||
{
|
||||
void CollideWith(IEntity collidedWith);
|
||||
|
||||
/// <summary>
|
||||
/// Called after all collisions have been processed, as well as how many collisions occured
|
||||
/// </summary>
|
||||
/// <param name="collisionCount"></param>
|
||||
void PostCollide(int collisionCount) { }
|
||||
}
|
||||
|
||||
public interface ICollideSpecial
|
||||
{
|
||||
bool PreventCollide(IPhysBody collidedwith);
|
||||
}
|
||||
|
||||
public partial interface ICollidableComponent : IComponent, IPhysBody
|
||||
{
|
||||
public bool Hard { get; set; }
|
||||
bool IsColliding(Vector2 offset, bool approximate = true);
|
||||
|
||||
IEnumerable<IEntity> GetCollidingEntities(Vector2 offset, bool approximate = true);
|
||||
bool UpdatePhysicsTree();
|
||||
|
||||
void RemovedFromPhysicsTree(MapId mapId);
|
||||
void AddedToPhysicsTree(MapId mapId);
|
||||
}
|
||||
|
||||
public partial class CollidableComponent : Component, ICollidableComponent
|
||||
{
|
||||
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
|
||||
|
||||
@@ -27,6 +56,8 @@ namespace Robust.Shared.GameObjects.Components
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.COLLIDABLE;
|
||||
|
||||
public IEntity Entity => Owner;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MapId MapID => Owner.Transform.MapID;
|
||||
|
||||
@@ -68,13 +99,13 @@ namespace Robust.Shared.GameObjects.Components
|
||||
serializer.DataField(ref _isHard, "hard", true);
|
||||
serializer.DataField(ref _status, "Status", BodyStatus.OnGround);
|
||||
serializer.DataField(ref _bodyType, "bodyType", BodyType.Static);
|
||||
serializer.DataField(ref _physShapes, "shapes", new List<IPhysShape>{new PhysShapeAabb()});
|
||||
serializer.DataField(ref _physShapes, "shapes", new List<IPhysShape> {new PhysShapeAabb()});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new CollidableComponentState(_canCollide, _status, _physShapes, _isHard);
|
||||
return new CollidableComponentState(_canCollide, _status, _physShapes, _isHard, _mass, LinearVelocity, AngularVelocity, Anchored);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -83,7 +114,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
if (curState == null)
|
||||
return;
|
||||
|
||||
var newState = (CollidableComponentState)curState;
|
||||
var newState = (CollidableComponentState) curState;
|
||||
|
||||
_canCollide = newState.CanCollide;
|
||||
_status = newState.Status;
|
||||
@@ -102,6 +133,20 @@ namespace Robust.Shared.GameObjects.Components
|
||||
Dirty();
|
||||
UpdateEntityTree();
|
||||
}
|
||||
|
||||
Mass = newState.Mass / 1000f; // gram to kilogram
|
||||
|
||||
LinearVelocity = newState.LinearVelocity;
|
||||
// Logger.Debug($"{IGameTiming.TickStampStatic}: [{Owner}] {LinearVelocity}");
|
||||
AngularVelocity = newState.AngularVelocity;
|
||||
Anchored = newState.Anchored;
|
||||
// TODO: Does it make sense to reset controllers here?
|
||||
// This caused space movement to break in content and I'm not 100% sure this is a good fix.
|
||||
// Look man the CM test is in 5 hours cut me some slack.
|
||||
//_controller = null;
|
||||
// Reset predict flag to false to avoid predicting stuff too long.
|
||||
// Another possibly bad hack for content at the moment.
|
||||
Predict = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -111,7 +156,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
get
|
||||
{
|
||||
var pos = Owner.Transform.WorldPosition;
|
||||
return ((IPhysBody)this).AABB.Translated(pos);
|
||||
return ((IPhysBody) this).AABB.Translated(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +193,9 @@ namespace Robust.Shared.GameObjects.Components
|
||||
set
|
||||
{
|
||||
_canCollide = value;
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new CollisionChangeMessage(Owner.Uid, _canCollide));
|
||||
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local,
|
||||
new CollisionChangeMessage(Owner.Uid, _canCollide));
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
@@ -180,6 +227,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
get
|
||||
{
|
||||
var layers = 0x0;
|
||||
|
||||
foreach (var shape in _physShapes)
|
||||
layers = layers | shape.CollisionLayer;
|
||||
return layers;
|
||||
@@ -195,23 +243,13 @@ namespace Robust.Shared.GameObjects.Components
|
||||
get
|
||||
{
|
||||
var mask = 0x0;
|
||||
|
||||
foreach (var shape in _physShapes)
|
||||
mask = mask | shape.CollisionMask;
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public BodyStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
_status = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -220,7 +258,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
// normally ExposeData would create this
|
||||
if (_physShapes == null)
|
||||
{
|
||||
_physShapes = new List<IPhysShape> { new PhysShapeAabb() };
|
||||
_physShapes = new List<IPhysShape> {new PhysShapeAabb()};
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -230,7 +268,8 @@ namespace Robust.Shared.GameObjects.Components
|
||||
}
|
||||
}
|
||||
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new CollisionChangeMessage(Owner.Uid, _canCollide));
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local,
|
||||
new CollisionChangeMessage(Owner.Uid, _canCollide));
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
@@ -242,13 +281,11 @@ namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
ShapeRemoved(shape);
|
||||
}
|
||||
|
||||
|
||||
// Should we not call this if !_canCollide? PathfindingSystem doesn't care at least.
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new CollisionChangeMessage(Owner.Uid, false));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ShapeAdded(IPhysShape shape)
|
||||
{
|
||||
shape.OnDataChanged += ShapeDataChanged;
|
||||
@@ -269,6 +306,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
/// <inheritdoc />
|
||||
protected override void Shutdown()
|
||||
{
|
||||
RemoveController();
|
||||
_physicsManager.RemoveBody(this);
|
||||
base.Shutdown();
|
||||
}
|
||||
@@ -365,6 +403,7 @@ namespace Robust.Shared.GameObjects.Components
|
||||
public bool Remove(IPhysShape item)
|
||||
{
|
||||
var found = _owner._physShapes.Remove(item);
|
||||
|
||||
if (found)
|
||||
{
|
||||
ItemRemoved(item);
|
||||
@@ -419,4 +458,11 @@ namespace Robust.Shared.GameObjects.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum BodyStatus
|
||||
{
|
||||
OnGround,
|
||||
InAir
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.Shared.Interfaces.Physics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
public partial interface ICollidableComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Current mass of the entity in kilograms.
|
||||
/// </summary>
|
||||
float Mass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current linear velocity of the entity in meters per second.
|
||||
/// </summary>
|
||||
Vector2 LinearVelocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current angular velocity of the entity in radians per sec.
|
||||
/// </summary>
|
||||
float AngularVelocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current momentum of the entity in kilogram meters per second
|
||||
/// </summary>
|
||||
Vector2 Momentum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current status of the object
|
||||
/// </summary>
|
||||
BodyStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents a virtual controller acting on the physics component.
|
||||
/// </summary>
|
||||
VirtualController? Controller { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component is on the ground
|
||||
/// </summary>
|
||||
bool OnGround { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity is anchored in place.
|
||||
/// </summary>
|
||||
bool Anchored { get; set; }
|
||||
|
||||
event Action? AnchoredChanged;
|
||||
|
||||
bool Predict { get; set; }
|
||||
void SetController<T>() where T : VirtualController, new();
|
||||
void RemoveController();
|
||||
}
|
||||
|
||||
partial class CollidableComponent : ICollidableComponent
|
||||
{
|
||||
private float _mass;
|
||||
private Vector2 _linVelocity;
|
||||
private float _angVelocity;
|
||||
private VirtualController? _controller;
|
||||
private bool _anchored;
|
||||
|
||||
/// <summary>
|
||||
/// Current mass of the entity in kilograms.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Mass
|
||||
{
|
||||
get => _mass;
|
||||
set
|
||||
{
|
||||
_mass = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current linear velocity of the entity in meters per second.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 LinearVelocity
|
||||
{
|
||||
get => _linVelocity;
|
||||
set
|
||||
{
|
||||
if (_linVelocity == value)
|
||||
return;
|
||||
|
||||
_linVelocity = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current angular velocity of the entity in radians per sec.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float AngularVelocity
|
||||
{
|
||||
get => _angVelocity;
|
||||
set
|
||||
{
|
||||
if (_angVelocity.Equals(value))
|
||||
return;
|
||||
|
||||
_angVelocity = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current momentum of the entity in kilogram meters per second
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 Momentum
|
||||
{
|
||||
get => LinearVelocity * Mass;
|
||||
set => LinearVelocity = value / Mass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current status of the object
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public BodyStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
_status = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a virtual controller acting on the physics component.
|
||||
/// </summary>
|
||||
public VirtualController? Controller
|
||||
{
|
||||
get => _controller;
|
||||
set => _controller = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component is on the ground
|
||||
/// </summary>
|
||||
public bool OnGround => Status == BodyStatus.OnGround &&
|
||||
!IoCManager.Resolve<IPhysicsManager>()
|
||||
.IsWeightless(Owner.Transform.GridPosition);
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity is anchored in place.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Anchored
|
||||
{
|
||||
get => _anchored;
|
||||
set
|
||||
{
|
||||
_anchored = value;
|
||||
AnchoredChanged?.Invoke();
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public event Action? AnchoredChanged;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Predict { get; set; }
|
||||
|
||||
[Obsolete("This only exists for legacy reasons.")]
|
||||
public bool CanMove([NotNullWhen(true)]IPhysicsComponent physics)
|
||||
{
|
||||
return Owner.TryGetComponent(out physics) && !Anchored;
|
||||
}
|
||||
|
||||
public void SetController<T>() where T : VirtualController, new()
|
||||
{
|
||||
_controller = new T { ControlledComponent = this };
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public void RemoveController()
|
||||
{
|
||||
if (_controller != null)
|
||||
{
|
||||
_controller.ControlledComponent = null;
|
||||
_controller = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
@@ -13,13 +14,38 @@ namespace Robust.Shared.GameObjects.Components
|
||||
public readonly List<IPhysShape> PhysShapes;
|
||||
public readonly bool Hard;
|
||||
|
||||
public CollidableComponentState(bool canCollide, BodyStatus status, List<IPhysShape> physShapes, bool hard)
|
||||
|
||||
/// <summary>
|
||||
/// Current mass of the entity, stored in grams.
|
||||
/// </summary>
|
||||
public readonly int Mass;
|
||||
public readonly Vector2 LinearVelocity;
|
||||
public readonly float AngularVelocity;
|
||||
public readonly bool Anchored;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="canCollide"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="physShapes"></param>
|
||||
/// <param name="hard"></param>
|
||||
/// <param name="mass">Current Mass of the entity.</param>
|
||||
/// <param name="linearVelocity">Current linear velocity of the entity in meters per second.</param>
|
||||
/// <param name="angularVelocity">Current angular velocity of the entity in radians per sec.</param>
|
||||
/// <param name="anchored">Whether or not the entity is anchored in place.</param>
|
||||
public CollidableComponentState(bool canCollide, BodyStatus status, List<IPhysShape> physShapes, bool hard, float mass, Vector2 linearVelocity, float angularVelocity, bool anchored)
|
||||
: base(NetIDs.COLLIDABLE)
|
||||
{
|
||||
CanCollide = canCollide;
|
||||
Status = status;
|
||||
PhysShapes = physShapes;
|
||||
Hard = hard;
|
||||
|
||||
LinearVelocity = linearVelocity;
|
||||
AngularVelocity = angularVelocity;
|
||||
Mass = (int)Math.Round(mass * 1000); // rounds kg to nearest gram
|
||||
Anchored = anchored;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
public interface ICollidableComponent : IComponent, IPhysBody
|
||||
{
|
||||
public bool Hard { get; set; }
|
||||
BodyStatus Status { get; set; }
|
||||
bool IsColliding(Vector2 offset, bool approximate = true);
|
||||
|
||||
IEnumerable<IEntity> GetCollidingEntities(Vector2 offset, bool approximate = true);
|
||||
bool UpdatePhysicsTree();
|
||||
|
||||
void RemovedFromPhysicsTree(MapId mapId);
|
||||
void AddedToPhysicsTree(MapId mapId);
|
||||
}
|
||||
|
||||
public interface ICollideSpecial
|
||||
{
|
||||
bool PreventCollide(IPhysBody collidedwith);
|
||||
}
|
||||
|
||||
public interface ICollideBehavior
|
||||
{
|
||||
void CollideWith(IEntity collidedWith);
|
||||
|
||||
/// <summary>
|
||||
/// Called after all collisions have been processed, as well as how many collisions occured
|
||||
/// </summary>
|
||||
/// <param name="collisionCount"></param>
|
||||
void PostCollide(int collisionCount) { }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Physics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
[Obsolete("Use the ICollidableComponent interface, or use ICollidableComponent.Anchored if you are using this to check if the entity can be moved.")]
|
||||
public interface IPhysicsComponent : IComponent
|
||||
{
|
||||
/// <summary>
|
||||
@@ -54,19 +53,26 @@ namespace Robust.Shared.GameObjects.Components
|
||||
event Action? AnchoredChanged;
|
||||
|
||||
bool Predict { get; set; }
|
||||
void SetController<T>() where T: VirtualController, new();
|
||||
|
||||
void SetController<T>()
|
||||
where T : VirtualController, new();
|
||||
|
||||
void RemoveController();
|
||||
}
|
||||
|
||||
[Obsolete("Migrate to CollidableComponent")]
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IPhysicsComponent))]
|
||||
public class PhysicsComponent: Component, IPhysicsComponent
|
||||
public class PhysicsComponent : Component, IPhysicsComponent
|
||||
{
|
||||
private ICollidableComponent _collidableComponent = default!;
|
||||
private bool _upgradeCollidable;
|
||||
|
||||
private float _mass;
|
||||
private Vector2 _linVelocity;
|
||||
private float _angVelocity;
|
||||
private VirtualController? _controller;
|
||||
private BodyStatus _status;
|
||||
private VirtualController? _controller;
|
||||
private bool _anchored;
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -75,181 +81,119 @@ namespace Robust.Shared.GameObjects.Components
|
||||
/// <inheritdoc />
|
||||
public override uint? NetID => NetIDs.PHYSICS;
|
||||
|
||||
/// <summary>
|
||||
/// Current mass of the entity in kilograms.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Mass
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
get => _mass;
|
||||
set
|
||||
base.Initialize();
|
||||
|
||||
if (!Owner.EnsureComponent(out CollidableComponent comp))
|
||||
{
|
||||
_mass = value;
|
||||
Dirty();
|
||||
Logger.ErrorS("physics", $"Entity {Owner} is missing a {nameof(CollidableComponent)}, adding one for you.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current linear velocity of the entity in meters per second.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 LinearVelocity
|
||||
{
|
||||
get => _linVelocity;
|
||||
set
|
||||
_collidableComponent = comp;
|
||||
|
||||
if (_upgradeCollidable)
|
||||
{
|
||||
if(_linVelocity == value)
|
||||
return;
|
||||
|
||||
_linVelocity = value;
|
||||
Dirty();
|
||||
_collidableComponent.Mass = _mass;
|
||||
_collidableComponent.LinearVelocity = _linVelocity;
|
||||
_collidableComponent.AngularVelocity = _angVelocity;
|
||||
_collidableComponent.Anchored = _anchored;
|
||||
_collidableComponent.Status = _status;
|
||||
_collidableComponent.Controller = _controller;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current angular velocity of the entity in radians per sec.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float AngularVelocity
|
||||
{
|
||||
get => _angVelocity;
|
||||
set
|
||||
{
|
||||
if(_angVelocity.Equals(value))
|
||||
return;
|
||||
|
||||
_angVelocity = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current momentum of the entity in kilogram meters per second
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 Momentum
|
||||
{
|
||||
get => LinearVelocity * Mass;
|
||||
set => LinearVelocity = value / Mass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current status of the object
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public BodyStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
_status = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a virtual controller acting on the physics component.
|
||||
/// </summary>
|
||||
public VirtualController? Controller
|
||||
{
|
||||
get => _controller;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component is on the ground
|
||||
/// </summary>
|
||||
public bool OnGround => Status == BodyStatus.OnGround &&
|
||||
!IoCManager.Resolve<IPhysicsManager>()
|
||||
.IsWeightless(Owner.Transform.GridPosition);
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the entity is anchored in place.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Anchored
|
||||
{
|
||||
get => _anchored;
|
||||
set
|
||||
{
|
||||
_anchored = value;
|
||||
AnchoredChanged?.Invoke();
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public event Action? AnchoredChanged;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool Predict { get; set; }
|
||||
|
||||
public void SetController<T>() where T: VirtualController, new()
|
||||
{
|
||||
_controller = new T {ControlledComponent = this};
|
||||
Dirty();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
|
||||
serializer.DataField<float>(ref _mass, "mass", 1);
|
||||
serializer.DataField(ref _linVelocity, "vel", Vector2.Zero);
|
||||
serializer.DataField(ref _angVelocity, "avel", 0.0f);
|
||||
serializer.DataField(ref _anchored, "Anchored", false);
|
||||
serializer.DataField(ref _status, "Status", BodyStatus.OnGround);
|
||||
serializer.DataField(ref _controller, "Controller", null);
|
||||
if(serializer.Reading) // Prevents the obsolete component from writing
|
||||
{
|
||||
if(!serializer.ReadDataField("upgraded", false))
|
||||
{
|
||||
_upgradeCollidable = true;
|
||||
serializer.DataField<float>(ref _mass, "mass", 1);
|
||||
serializer.DataField(ref _linVelocity, "vel", Vector2.Zero);
|
||||
serializer.DataField(ref _angVelocity, "avel", 0.0f);
|
||||
serializer.DataField(ref _anchored, "Anchored", false);
|
||||
serializer.DataField(ref _status, "Status", BodyStatus.OnGround);
|
||||
serializer.DataField(ref _controller, "Controller", null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var upgrade = true;
|
||||
serializer.DataField(ref upgrade, "upgraded", true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ComponentState GetComponentState()
|
||||
#region IPhysicsComponent Proxy
|
||||
|
||||
public float Mass
|
||||
{
|
||||
return new PhysicsComponentState(_mass, LinearVelocity, AngularVelocity, Anchored);
|
||||
get => _collidableComponent.Mass;
|
||||
set => _collidableComponent.Mass = value;
|
||||
}
|
||||
|
||||
public Vector2 LinearVelocity
|
||||
{
|
||||
get => _collidableComponent.LinearVelocity;
|
||||
set => _collidableComponent.LinearVelocity = value;
|
||||
}
|
||||
|
||||
public float AngularVelocity
|
||||
{
|
||||
get => _collidableComponent.AngularVelocity;
|
||||
set => _collidableComponent.AngularVelocity = value;
|
||||
}
|
||||
|
||||
public Vector2 Momentum
|
||||
{
|
||||
get => _collidableComponent.Momentum;
|
||||
set => _collidableComponent.Momentum = value;
|
||||
}
|
||||
|
||||
public BodyStatus Status
|
||||
{
|
||||
get => _collidableComponent.Status;
|
||||
set => _collidableComponent.Status = value;
|
||||
}
|
||||
|
||||
public VirtualController? Controller => _collidableComponent.Controller;
|
||||
|
||||
public bool OnGround => _collidableComponent.OnGround;
|
||||
|
||||
public bool Anchored
|
||||
{
|
||||
get => _collidableComponent.Anchored;
|
||||
set => _collidableComponent.Anchored = value;
|
||||
}
|
||||
|
||||
public event Action? AnchoredChanged
|
||||
{
|
||||
add => _collidableComponent.AnchoredChanged += value;
|
||||
remove => _collidableComponent.AnchoredChanged -= value;
|
||||
}
|
||||
|
||||
public bool Predict
|
||||
{
|
||||
get => _collidableComponent.Predict;
|
||||
set => _collidableComponent.Predict = value;
|
||||
}
|
||||
|
||||
public void SetController<T>()
|
||||
where T : VirtualController, new()
|
||||
{
|
||||
_collidableComponent.SetController<T>();
|
||||
}
|
||||
|
||||
public void RemoveController()
|
||||
{
|
||||
if (_controller != null)
|
||||
{
|
||||
_controller.ControlledComponent = null;
|
||||
_controller = null;
|
||||
}
|
||||
_collidableComponent.RemoveController();
|
||||
}
|
||||
|
||||
protected override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
RemoveController();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
if (curState == null)
|
||||
return;
|
||||
|
||||
var newState = (PhysicsComponentState)curState;
|
||||
Mass = newState.Mass / 1000f; // gram to kilogram
|
||||
|
||||
LinearVelocity = newState.LinearVelocity;
|
||||
// Logger.Debug($"{IGameTiming.TickStampStatic}: [{Owner}] {LinearVelocity}");
|
||||
AngularVelocity = newState.AngularVelocity;
|
||||
Anchored = newState.Anchored;
|
||||
// TODO: Does it make sense to reset controllers here?
|
||||
// This caused space movement to break in content and I'm not 100% sure this is a good fix.
|
||||
// Look man the CM test is in 5 hours cut me some slack.
|
||||
//_controller = null;
|
||||
// Reset predict flag to false to avoid predicting stuff too long.
|
||||
// Another possibly bad hack for content at the moment.
|
||||
Predict = false;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum BodyStatus
|
||||
{
|
||||
OnGround,
|
||||
InAir
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Shared.GameObjects.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialized state of a PhysicsComponent.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class PhysicsComponentState : ComponentState
|
||||
{
|
||||
/// <summary>
|
||||
/// Current mass of the entity, stored in grams.
|
||||
/// </summary>
|
||||
public readonly int Mass;
|
||||
|
||||
public readonly Vector2 LinearVelocity;
|
||||
public readonly float AngularVelocity;
|
||||
public readonly bool Anchored;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new state snapshot of a PhysicsComponent.
|
||||
/// </summary>
|
||||
/// <param name="mass">Current Mass of the entity.</param>
|
||||
/// <param name="linearVelocity">Current linear velocity of the entity in meters per second.</param>
|
||||
/// <param name="angularVelocity">Current angular velocity of the entity in radians per sec.</param>
|
||||
/// <param name="anchored">Whether or not the entity is anchored in place.</param>
|
||||
public PhysicsComponentState(float mass, Vector2 linearVelocity, float angularVelocity, bool anchored)
|
||||
: base(NetIDs.PHYSICS)
|
||||
{
|
||||
LinearVelocity = linearVelocity;
|
||||
AngularVelocity = angularVelocity;
|
||||
Mass = (int) Math.Round(mass *1000); // rounds kg to nearest gram
|
||||
Anchored = anchored;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,10 +118,10 @@ namespace Robust.Shared.GameObjects.Systems
|
||||
foreach (var collision in _collisionCache)
|
||||
{
|
||||
// Apply onCollide behavior
|
||||
var aBehaviors = collision.A.Owner.GetAllComponents<ICollideBehavior>();
|
||||
var aBehaviors = collision.A.Entity.GetAllComponents<ICollideBehavior>();
|
||||
foreach (var behavior in aBehaviors)
|
||||
{
|
||||
var entity = collision.B.Owner;
|
||||
var entity = collision.B.Entity;
|
||||
if (entity.Deleted) continue;
|
||||
behavior.CollideWith(entity);
|
||||
if (collisionsWith.ContainsKey(behavior))
|
||||
@@ -133,10 +133,10 @@ namespace Robust.Shared.GameObjects.Systems
|
||||
collisionsWith[behavior] = 1;
|
||||
}
|
||||
}
|
||||
var bBehaviors = collision.B.Owner.GetAllComponents<ICollideBehavior>();
|
||||
var bBehaviors = collision.B.Entity.GetAllComponents<ICollideBehavior>();
|
||||
foreach (var behavior in bBehaviors)
|
||||
{
|
||||
var entity = collision.A.Owner;
|
||||
var entity = collision.A.Entity;
|
||||
if (entity.Deleted) continue;
|
||||
behavior.CollideWith(entity);
|
||||
if (collisionsWith.ContainsKey(behavior))
|
||||
@@ -183,7 +183,7 @@ namespace Robust.Shared.GameObjects.Systems
|
||||
{
|
||||
foreach (var b in a.GetCollidingEntities(Vector2.Zero))
|
||||
{
|
||||
var aUid = ((IPhysBody)a).Owner.Uid;
|
||||
var aUid = ((IPhysBody)a).Entity.Uid;
|
||||
var bUid = b.Uid;
|
||||
|
||||
if (bUid.CompareTo(aUid) > 0)
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Robust.Shared.Physics
|
||||
/// <summary>
|
||||
/// Entity that this physBody represents.
|
||||
/// </summary>
|
||||
IEntity Owner { get; }
|
||||
IEntity Entity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// AABB of this entity in world space.
|
||||
|
||||
@@ -106,17 +106,17 @@ namespace Robust.Shared.Physics
|
||||
|
||||
public IEnumerable<IEntity> GetCollidingEntities(IPhysBody physBody, Vector2 offset, bool approximate = true)
|
||||
{
|
||||
var modifiers = physBody.Owner.GetAllComponents<ICollideSpecial>();
|
||||
var modifiers = physBody.Entity.GetAllComponents<ICollideSpecial>();
|
||||
foreach ( var body in this[physBody.MapID].Query(physBody.WorldAABB, approximate))
|
||||
{
|
||||
if (body.Owner.Deleted) {
|
||||
if (body.Entity.Deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CollidesOnMask(physBody, body))
|
||||
{
|
||||
var preventCollision = false;
|
||||
var otherModifiers = body.Owner.GetAllComponents<ICollideSpecial>();
|
||||
var otherModifiers = body.Entity.GetAllComponents<ICollideSpecial>();
|
||||
foreach (var modifier in modifiers)
|
||||
{
|
||||
preventCollision |= modifier.PreventCollide(body);
|
||||
@@ -127,7 +127,7 @@ namespace Robust.Shared.Physics
|
||||
}
|
||||
|
||||
if (preventCollision) continue;
|
||||
yield return body.Owner;
|
||||
yield return body.Entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ namespace Robust.Shared.Physics
|
||||
{
|
||||
if (!this[physBody.MapID].Add(physBody))
|
||||
{
|
||||
Logger.WarningS("phys", $"PhysicsBody already registered! {physBody.Owner}");
|
||||
Logger.WarningS("phys", $"PhysicsBody already registered! {physBody.Entity}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace Robust.Shared.Physics
|
||||
{
|
||||
var removed = false;
|
||||
|
||||
if (physBody.Owner.Deleted || physBody.Owner.Transform.Deleted)
|
||||
if (physBody.Entity.Deleted || physBody.Entity.Transform.Deleted)
|
||||
{
|
||||
foreach (var mapId in _mapManager.GetAllMapIds())
|
||||
{
|
||||
@@ -220,7 +220,7 @@ namespace Robust.Shared.Physics
|
||||
}
|
||||
|
||||
if (!removed)
|
||||
Logger.WarningS("phys", $"Trying to remove unregistered PhysicsBody! {physBody.Owner.Uid}");
|
||||
Logger.WarningS("phys", $"Trying to remove unregistered PhysicsBody! {physBody.Entity.Uid}");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -250,12 +250,12 @@ namespace Robust.Shared.Physics
|
||||
return true;
|
||||
}
|
||||
|
||||
if (predicate != null && predicate.Invoke(body.Owner))
|
||||
if (predicate != null && predicate.Invoke(body.Entity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var result = new RayCastResults(distFromOrigin, point, body.Owner);
|
||||
var result = new RayCastResults(distFromOrigin, point, body.Entity);
|
||||
results.Add(result);
|
||||
DebugDrawRay?.Invoke(new DebugRayData(ray, maxLength, result));
|
||||
return true;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Robust.Shared.Physics
|
||||
/// </summary>
|
||||
public abstract class VirtualController
|
||||
{
|
||||
public abstract IPhysicsComponent? ControlledComponent { set; }
|
||||
public abstract ICollidableComponent? ControlledComponent { set; }
|
||||
|
||||
/// <summary>
|
||||
/// Modify a physics component before processing impulses
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=gameobjects_005Ccomponents_005Ccollidable/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=gameobjects_005Ccomponents_005Cphysics/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -141,7 +141,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
|
||||
var mock = new Mock<IPhysBody>();
|
||||
mock.Setup(foo => foo.WorldAABB).Returns(box);
|
||||
mock.Setup(foo => foo.Owner).Returns(new Entity()); // requires IPhysBody not have null owner
|
||||
mock.Setup(foo => foo.Entity).Returns(new Entity()); // requires IPhysBody not have null owner
|
||||
mock.Setup(foo => foo.CanCollide).Returns(true);
|
||||
mock.Setup(foo => foo.CollisionLayer).Returns(1);
|
||||
mock.Setup(foo => foo.CollisionMask).Returns(1);
|
||||
@@ -170,7 +170,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
|
||||
var mock = new Mock<IPhysBody>();
|
||||
mock.Setup(foo => foo.WorldAABB).Returns(box);
|
||||
mock.Setup(foo => foo.Owner).Returns(new Entity()); // requires IPhysBody not have null owner
|
||||
mock.Setup(foo => foo.Entity).Returns(new Entity()); // requires IPhysBody not have null owner
|
||||
mock.Setup(foo => foo.CanCollide).Returns(true);
|
||||
mock.Setup(foo => foo.CollisionLayer).Returns(1);
|
||||
mock.Setup(foo => foo.CollisionMask).Returns(1);
|
||||
@@ -197,7 +197,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
|
||||
var m1 = new Mock<IPhysBody>();
|
||||
m1.Setup(foo => foo.WorldAABB).Returns(b1);
|
||||
m1.Setup(foo => foo.Owner).Returns(e1);
|
||||
m1.Setup(foo => foo.Entity).Returns(e1);
|
||||
m1.Setup(foo => foo.CanCollide).Returns(true);
|
||||
m1.Setup(foo => foo.CollisionLayer).Returns(1);
|
||||
m1.Setup(foo => foo.CollisionMask).Returns(1);
|
||||
@@ -205,7 +205,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
|
||||
var m2 = new Mock<IPhysBody>();
|
||||
m2.Setup(foo => foo.WorldAABB).Returns(b2);
|
||||
m2.Setup(foo => foo.Owner).Returns(e2);
|
||||
m2.Setup(foo => foo.Entity).Returns(e2);
|
||||
m2.Setup(foo => foo.CanCollide).Returns(true);
|
||||
m2.Setup(foo => foo.CollisionLayer).Returns(1);
|
||||
m2.Setup(foo => foo.CollisionMask).Returns(1);
|
||||
@@ -239,7 +239,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
mock0.Setup(foo => foo.CanCollide).Returns(true);
|
||||
mock0.Setup(foo => foo.CollisionLayer).Returns(0x4);
|
||||
mock0.Setup(foo => foo.CollisionMask).Returns(0x04);
|
||||
mock0.Setup(foo => foo.Owner).Returns(mockEntity0);
|
||||
mock0.Setup(foo => foo.Entity).Returns(mockEntity0);
|
||||
var staticBody = mock0.Object;
|
||||
manager.AddBody(staticBody);
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace Robust.UnitTesting.Shared.Physics
|
||||
mock1.Setup(foo => foo.CanCollide).Returns(true);
|
||||
mock1.Setup(foo => foo.CollisionLayer).Returns(0x4);
|
||||
mock1.Setup(foo => foo.CollisionMask).Returns(0x04);
|
||||
mock1.Setup(foo => foo.Owner).Returns(mockEntity1);
|
||||
mock1.Setup(foo => foo.Entity).Returns(mockEntity1);
|
||||
var testBody = mock1.Object;
|
||||
manager.AddBody(testBody);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user