Files
RobustToolbox/Robust.Shared/GameObjects/Components/Collidable/CollidableComponent.cs
T
Tyler YoungandGitHub 214f9f0323 Implement client bubble PVS. (#983)
* bubble implementation

include contained entities

fix line edit crash when clipboard contents are null somehow

use CVar for update bubble range

remove seenMovers that get NaN'd out of MaxUpdateRange - huge reduction in network traffic from bullets

cut default of MaxUpdateRange down to 12.5 for now

maybe handle teleported things

handle removing player state on disconnect

fixed positional audio errors

make UpdateEntityTree also update player's last seen ents

make net.maxupdaterange cvar tunable at runtime w/o impacting performance

back to position nan as means to hide from client

revert work pooling as the wrong player was getting the wrong game state

ffs needed to think less about *if* something is *seen* and more about *when* it must be *unseen*

clean up usings

handle parenting and sequencing issues that arise on the client

gather needed ents to update recursively

applied suggestions from code review

fix missing recursively contained ents

make assumption that client last saw things on first tick instead of tick zero, as zero would be the "from tick" and first would be he "to tick"

add First tick as constant to GameTick due to relevance above

renamed includedEnts to checkedEnts to make usage more clear

added comments

inverted some conditions to flatten parts of the pvs logic

fixed sending states when already seen (lastChange < lastSeen to lastChange <= lastSeen)

fix sending states when no actual changes (other bugs?)

local caching of currentTick, remove priorTick

* make TransformComponent's Parent setter call Dirty() to handle replicating network state if AttachParent isn't invoked

* fixed parent changed by setting Parent on Transform not updating parent's Children collection and other stuff

rotating parent entities now are visible with their orbiting children if one of their children moves into view

* break out duplicated code as GetLastSeen

* remove unused net.parallelstates

introduce net.pvs to configure enabling/disabling PVS
2020-02-23 14:42:54 +01:00

231 lines
6.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Physics;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Robust.Shared.GameObjects.Components
{
public class CollidableComponent : Component, ICollidableComponent
{
#pragma warning disable 649
[Dependency] private readonly IPhysicsManager _physicsManager;
#pragma warning restore 649
private bool _collisionEnabled;
private bool _isHardCollidable;
private bool _isScrapingFloor;
private BodyType _bodyType;
private List<IPhysShape> _physShapes = new List<IPhysShape>();
/// <inheritdoc />
public override string Name => "Collidable";
/// <inheritdoc />
public override uint? NetID => NetIDs.COLLIDABLE;
/// <inheritdoc />
public MapId MapID => Owner.Transform.MapID;
/// <inheritdoc />
public int ProxyId { get; set; }
/// <inheritdoc />
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _collisionEnabled, "on", true);
serializer.DataField(ref _isHardCollidable, "hard", true);
serializer.DataField(ref _isScrapingFloor, "IsScrapingFloor", false);
serializer.DataField(ref _bodyType, "bodyType", BodyType.None);
serializer.DataField(ref _physShapes, "shapes", new List<IPhysShape>{new PhysShapeAabb()});
}
/// <inheritdoc />
public override ComponentState GetComponentState()
{
return new CollidableComponentState(_collisionEnabled, _isHardCollidable, _isScrapingFloor, _physShapes);
}
/// <inheritdoc />
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
{
if (curState == null)
return;
var newState = (CollidableComponentState)curState;
_collisionEnabled = newState.CollisionEnabled;
_isHardCollidable = newState.HardCollidable;
_isScrapingFloor = newState.ScrapingFloor;
//TODO: Is this always true?
if (newState.PhysShapes != null)
{
_physShapes = newState.PhysShapes;
foreach (var shape in _physShapes)
{
shape.ApplyState();
}
Dirty();
UpdateEntityTree();
}
}
/// <inheritdoc />
[ViewVariables]
Box2 IPhysBody.WorldAABB
{
get
{
var pos = Owner.Transform.WorldPosition;
return ((IPhysBody)this).AABB.Translated(pos);
}
}
/// <inheritdoc />
[ViewVariables]
Box2 IPhysBody.AABB
{
get
{
var angle = Owner.Transform.WorldRotation;
var bounds = new Box2();
foreach (var shape in _physShapes)
{
var shapeBounds = shape.CalculateLocalBounds(angle);
bounds = bounds.IsEmpty() ? shapeBounds : bounds.Union(shapeBounds);
}
return bounds;
}
}
/// <inheritdoc />
[ViewVariables]
public List<IPhysShape> PhysicsShapes => _physShapes;
/// <summary>
/// Enables or disabled collision processing of this component.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool CollisionEnabled
{
get => _collisionEnabled;
set => _collisionEnabled = value;
}
/// <inheritdoc />
[ViewVariables(VVAccess.ReadWrite)]
public bool IsHardCollidable
{
get => _isHardCollidable;
set => _isHardCollidable = value;
}
/// <summary>
/// Bitmask of the collision layers this component is a part of.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public int CollisionLayer
{
get
{
var layers = 0x0;
foreach (var shape in _physShapes)
layers = layers | shape.CollisionLayer;
return layers;
}
}
/// <summary>
/// Bitmask of the layers this component collides with.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public int CollisionMask
{
get
{
var mask = 0x0;
foreach (var shape in _physShapes)
mask = mask | shape.CollisionMask;
return mask;
}
}
[ViewVariables(VVAccess.ReadWrite)]
public bool IsScrapingFloor
{
get => _isScrapingFloor;
set => _isScrapingFloor = value;
}
/// <inheritdoc />
void IPhysBody.Bumped(IEntity bumpedby)
{
SendMessage(new BumpedEntMsg(bumpedby));
UpdateEntityTree();
}
/// <inheritdoc />
void IPhysBody.Bump(List<IEntity> bumpedinto)
{
var collidecomponents = Owner.GetAllComponents<ICollideBehavior>().ToList();
for (var i = 0; i < collidecomponents.Count; i++)
{
collidecomponents[i].CollideWith(bumpedinto);
}
}
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
// normally ExposeData would create this
if (_physShapes == null)
_physShapes = new List<IPhysShape> { new PhysShapeAabb() };
}
/// <inheritdoc />
protected override void Startup()
{
base.Startup();
_physicsManager.AddBody(this);
}
/// <inheritdoc />
protected override void Shutdown()
{
_physicsManager.RemoveBody(this);
base.Shutdown();
}
/// <inheritdoc />
public bool TryCollision(Vector2 offset, bool bump = false)
{
if (!_collisionEnabled || CollisionMask == 0x0)
return false;
return _physicsManager.TryCollide(Owner, offset, bump);
}
public bool UpdatePhysicsTree()
=> _physicsManager.Update(this);
private bool UpdateEntityTree() => Owner.EntityManager.UpdateEntityTree(Owner);
}
}