Merge branch 'master' into 2020-04-28-tool-component
# Conflicts: # Content.Server/GameObjects/Components/AnchorableComponent.cs # Content.Server/GameObjects/Components/Gravity/GravityGeneratorComponent.cs # Content.Server/GameObjects/Components/Interactable/Tools/CrowbarComponent.cs # Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs # Content.Server/GameObjects/Components/WiresComponent.cs # Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs # Resources/Prototypes/Entities/Items/tools.yml
This commit is contained in:
@@ -11,6 +11,7 @@ using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Reflection;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
@@ -101,7 +102,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
var processorId = args[0];
|
||||
var entId = new EntityUid(int.Parse(args[1]));
|
||||
var ent = IoCManager.Resolve<IEntityManager>().GetEntity(entId);
|
||||
var aiSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AiSystem>();
|
||||
var aiSystem = EntitySystem.Get<AiSystem>();
|
||||
|
||||
if (!aiSystem.ProcessorTypeExists(processorId))
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Interactable;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.Components.Timing;
|
||||
using Content.Server.Interfaces.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Interactable;
|
||||
using Content.Server.Utility;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Physics;
|
||||
@@ -21,6 +21,7 @@ using Robust.Shared.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.Interfaces.Physics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -30,36 +31,53 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being clicked on or "attacked" by a user with an object in their hand
|
||||
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
|
||||
/// </summary>
|
||||
public interface IAttackBy
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when using one object on another
|
||||
/// Called when using one object on another when user is in range of the target entity.
|
||||
/// </summary>
|
||||
bool AttackBy(AttackByEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class AttackByEventArgs : EventArgs
|
||||
public class AttackByEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public GridCoordinates ClickLocation { get; set; }
|
||||
public IEntity AttackWith { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
}
|
||||
|
||||
public interface ITargetedAttackEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Performer of the attack
|
||||
/// </summary>
|
||||
IEntity User { get; }
|
||||
/// <summary>
|
||||
/// Target of the attack
|
||||
/// </summary>
|
||||
IEntity Attacked { get; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being clicked on or "attacked" by a user with an empty hand
|
||||
/// who is in range and has unobstructed reach of the target entity (allows inside blockers).
|
||||
/// </summary>
|
||||
public interface IAttackHand
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when a player directly interacts with an empty hand
|
||||
/// Called when a player directly interacts with an empty hand when user is in range of the target entity.
|
||||
/// </summary>
|
||||
bool AttackHand(AttackHandEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class AttackHandEventArgs : EventArgs
|
||||
public class AttackHandEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,8 +101,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components a behavior when clicking on another object and no interaction occurs
|
||||
/// Doesn't pass what you clicked on as an argument, but if it becomes necessary we can add it later
|
||||
/// This interface gives components a behavior when clicking on another object and no interaction occurs,
|
||||
/// at any range.
|
||||
/// </summary>
|
||||
public interface IAfterAttack
|
||||
{
|
||||
@@ -119,19 +137,21 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being activated in the world.
|
||||
/// This interface gives components behavior when being activated in the world when the user
|
||||
/// is in range and has unobstructed access to the target entity (allows inside blockers).
|
||||
/// </summary>
|
||||
public interface IActivate
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when this component is activated by another entity.
|
||||
/// Called when this component is activated by another entity who is in range.
|
||||
/// </summary>
|
||||
void Activate(ActivateEventArgs eventArgs);
|
||||
}
|
||||
|
||||
public class ActivateEventArgs : EventArgs
|
||||
public class ActivateEventArgs : EventArgs, ITargetedAttackEventArgs
|
||||
{
|
||||
public IEntity User { get; set; }
|
||||
public IEntity Attacked { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -295,6 +315,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IMapManager _mapManager;
|
||||
[Dependency] private readonly IPhysicsManager _physicsManager;
|
||||
[Dependency] private readonly ILocalizationManager _localizationManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public const float InteractionRange = 2;
|
||||
@@ -362,7 +383,12 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
activateComp.Activate(new ActivateEventArgs {User = user});
|
||||
// all activates should only fire when in range / unbostructed
|
||||
var activateEventArgs = new ActivateEventArgs {User = user, Attacked = used};
|
||||
if (InteractionChecks.InRangeUnobstructed(activateEventArgs))
|
||||
{
|
||||
activateComp.Activate(activateEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HandleWideAttack(ICommonSession session, GridCoordinates coords, EntityUid uid)
|
||||
@@ -559,14 +585,20 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
var attackBys = attacked.GetAllComponents<IAttackBy>().ToList();
|
||||
var attackByEventArgs = new AttackByEventArgs
|
||||
{
|
||||
User = user, ClickLocation = clickLocation, AttackWith = weapon
|
||||
User = user, ClickLocation = clickLocation, AttackWith = weapon, Attacked = attacked
|
||||
};
|
||||
|
||||
foreach (var attackBy in attackBys)
|
||||
// all AttackBys should only happen when in range / unobstructed, so no range check is needed
|
||||
if (InteractionChecks.InRangeUnobstructed(attackByEventArgs))
|
||||
{
|
||||
if (attackBy.AttackBy(attackByEventArgs))
|
||||
// If an AttackBy returns a status completion we finish our attack
|
||||
return;
|
||||
foreach (var attackBy in attackBys)
|
||||
{
|
||||
if (attackBy.AttackBy(attackByEventArgs))
|
||||
{
|
||||
// If an AttackBy returns a status completion we finish our attack
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var afterAtkMsg = new AfterAttackMessage(user, weapon, attacked, clickLocation);
|
||||
@@ -603,14 +635,18 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
}
|
||||
|
||||
var attackHands = attacked.GetAllComponents<IAttackHand>().ToList();
|
||||
var attackHandEventArgs = new AttackHandEventArgs {User = user};
|
||||
var attackHandEventArgs = new AttackHandEventArgs {User = user, Attacked = attacked};
|
||||
|
||||
foreach (var attackHand in attackHands)
|
||||
// all attackHands should only fire when in range / unbostructed
|
||||
if (InteractionChecks.InRangeUnobstructed(attackHandEventArgs))
|
||||
{
|
||||
if (attackHand.AttackHand(attackHandEventArgs))
|
||||
foreach (var attackHand in attackHands)
|
||||
{
|
||||
// If an AttackHand returns a status completion we finish our attack
|
||||
return;
|
||||
if (attackHand.AttackHand(attackHandEventArgs))
|
||||
{
|
||||
// If an AttackHand returns a status completion we finish our attack
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
@@ -105,7 +106,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (!TryGetAttachedComponent(session as IPlayerSession, out HandsComponent handsComp))
|
||||
return;
|
||||
|
||||
var interactionSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<InteractionSystem>();
|
||||
var interactionSystem = EntitySystem.Get<InteractionSystem>();
|
||||
|
||||
var oldItem = handsComp.GetActiveHand;
|
||||
|
||||
@@ -133,9 +134,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
if (handsComp.GetActiveHand == null)
|
||||
return false;
|
||||
|
||||
var interactionSystem = _entitySystemManager.GetEntitySystem<InteractionSystem>();
|
||||
|
||||
if(interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, ignoredEnt: ent))
|
||||
if(EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, ignoredEnt: ent))
|
||||
if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
|
||||
{
|
||||
handsComp.Drop(handsComp.ActiveIndex, coords);
|
||||
|
||||
25
Content.Server/GameObjects/EntitySystems/InstrumentSystem.cs
Normal file
25
Content.Server/GameObjects/EntitySystems/InstrumentSystem.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Content.Server.GameObjects.Components.Instruments;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
public class InstrumentSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
EntityQuery = new TypeEntityQuery(typeof(InstrumentComponent));
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var entity in RelevantEntities)
|
||||
{
|
||||
entity.GetComponent<InstrumentComponent>().Update(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using Content.Server.Observer;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Physics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameObjects.EntitySystems;
|
||||
@@ -148,7 +149,13 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
private void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, PhysicsComponent physics, CollidableComponent collider = null)
|
||||
{
|
||||
bool weightless = false;
|
||||
if (physics.Controller == null)
|
||||
{
|
||||
// Set up controller
|
||||
physics.SetController<MoverController>();
|
||||
}
|
||||
|
||||
var weightless = false;
|
||||
|
||||
var tile = _mapManager.GetGrid(transform.GridID).GetTileRef(transform.GridPosition).Tile;
|
||||
|
||||
@@ -167,27 +174,27 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
&& !entity.HasComponent<ItemComponent>(); // This can't be an item
|
||||
}
|
||||
}
|
||||
|
||||
if (!touching)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner))
|
||||
{
|
||||
if (physics.LinearVelocity != Vector2.Zero)
|
||||
physics.LinearVelocity = Vector2.Zero;
|
||||
|
||||
if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless)
|
||||
{
|
||||
(physics.Controller as MoverController)?.StopMoving();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (weightless)
|
||||
{
|
||||
physics.LinearVelocity = mover.VelocityDir * mover.CurrentPushSpeed;
|
||||
(physics.Controller as MoverController)?.Push(mover.VelocityDir, mover.CurrentPushSpeed);
|
||||
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||
return;
|
||||
}
|
||||
|
||||
physics.LinearVelocity = mover.VelocityDir * (mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
||||
(physics.Controller as MoverController)?.Move(mover.VelocityDir,
|
||||
mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
||||
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||
|
||||
// Handle footsteps.
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
public class VerbSystem : EntitySystem
|
||||
{
|
||||
#pragma warning disable 649
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntityManager _entityManager;
|
||||
#pragma warning restore 649
|
||||
#pragma warning restore 649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -90,19 +90,19 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
var userEntity = player.AttachedEntity;
|
||||
|
||||
var data = new List<VerbsResponseMessage.VerbData>();
|
||||
var data = new List<VerbsResponseMessage.NetVerbData>();
|
||||
//Get verbs, component dependent.
|
||||
foreach (var (component, verb) in VerbUtility.GetVerbs(entity))
|
||||
{
|
||||
if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
continue;
|
||||
if (VerbUtility.IsVerbInvisible(verb, userEntity, component, out var vis))
|
||||
|
||||
var verbData = verb.GetData(userEntity, component);
|
||||
if (verbData.IsInvisible)
|
||||
continue;
|
||||
|
||||
// TODO: These keys being giant strings is inefficient as hell.
|
||||
data.Add(new VerbsResponseMessage.VerbData(verb.GetText(userEntity, component),
|
||||
$"{component.GetType()}:{verb.GetType()}", verb.GetCategory(userEntity, component),
|
||||
vis == VerbVisibility.Visible));
|
||||
data.Add(new VerbsResponseMessage.NetVerbData(verbData, $"{component.GetType()}:{verb.GetType()}"));
|
||||
}
|
||||
|
||||
//Get global verbs. Visible for all entities regardless of their components.
|
||||
@@ -110,14 +110,15 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity))
|
||||
continue;
|
||||
if (VerbUtility.IsVerbInvisible(globalVerb, userEntity, entity, out var vis))
|
||||
|
||||
var verbData = globalVerb.GetData(userEntity, entity);
|
||||
if (verbData.IsInvisible)
|
||||
continue;
|
||||
|
||||
data.Add(new VerbsResponseMessage.VerbData(globalVerb.GetText(userEntity, entity),
|
||||
globalVerb.GetType().ToString(), globalVerb.GetCategory(userEntity, entity), vis == VerbVisibility.Visible));
|
||||
data.Add(new VerbsResponseMessage.NetVerbData(verbData, globalVerb.GetType().ToString()));
|
||||
}
|
||||
|
||||
var response = new VerbsResponseMessage(data, req.EntityUid);
|
||||
var response = new VerbsResponseMessage(data.ToArray(), req.EntityUid);
|
||||
RaiseNetworkEvent(response, player.ConnectedClient);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user