using System.Collections.Generic; using System.Reflection; using Content.Shared.GameObjects; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using static Content.Shared.GameObjects.EntitySystemMessages.VerbSystemMessages; using Logger = Robust.Shared.Log.Logger; namespace Content.Server.Interfaces.GameObjects.Components.Interaction { public class VerbSystem : EntitySystem { #pragma warning disable 649 [Dependency] private readonly IEntityManager _entityManager; #pragma warning restore 649 public override void Initialize() { base.Initialize(); SubscribeNetworkEvent(RequestVerbs); SubscribeNetworkEvent(UseVerb); IoCManager.InjectDependencies(this); } private void UseVerb(UseVerbMessage use, EntitySessionEventArgs eventArgs) { if (!_entityManager.TryGetEntity(use.EntityUid, out var entity)) { return; } var session = eventArgs.SenderSession; var userEntity = session.AttachedEntity; foreach (var (component, verb) in VerbUtility.GetVerbs(entity)) { if ($"{component.GetType()}:{verb.GetType()}" != use.VerbKey) { continue; } if (verb.RequireInteractionRange) { var distanceSquared = (userEntity.Transform.WorldPosition - entity.Transform.WorldPosition) .LengthSquared; if (distanceSquared > VerbUtility.InteractionRangeSquared) { break; } } verb.Activate(userEntity, component); break; } foreach (var globalVerb in VerbUtility.GetGlobalVerbs(Assembly.GetExecutingAssembly())) { if (globalVerb.GetType().ToString() != use.VerbKey) { continue; } if (globalVerb.RequireInteractionRange) { var distanceSquared = (userEntity.Transform.WorldPosition - entity.Transform.WorldPosition) .LengthSquared; if (distanceSquared > VerbUtility.InteractionRangeSquared) { break; } } globalVerb.Activate(userEntity, entity); break; } } private void RequestVerbs(RequestVerbsMessage req, EntitySessionEventArgs eventArgs) { var player = (IPlayerSession) eventArgs.SenderSession; if (!_entityManager.TryGetEntity(req.EntityUid, out var entity)) { Logger.Warning($"{nameof(RequestVerbs)} called on a nonexistant entity with id {req.EntityUid} by player {player}."); return; } var userEntity = player.AttachedEntity; var data = new List(); //Get verbs, component dependent. foreach (var (component, verb) in VerbUtility.GetVerbs(entity)) { if (verb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity)) continue; var verbData = verb.GetData(userEntity, component); if (verbData.IsInvisible) continue; // TODO: These keys being giant strings is inefficient as hell. data.Add(new VerbsResponseMessage.NetVerbData(verbData, $"{component.GetType()}:{verb.GetType()}")); } //Get global verbs. Visible for all entities regardless of their components. foreach (var globalVerb in VerbUtility.GetGlobalVerbs(Assembly.GetExecutingAssembly())) { if (globalVerb.RequireInteractionRange && !VerbUtility.InVerbUseRange(userEntity, entity)) continue; var verbData = globalVerb.GetData(userEntity, entity); if (verbData.IsInvisible) continue; data.Add(new VerbsResponseMessage.NetVerbData(verbData, globalVerb.GetType().ToString())); } var response = new VerbsResponseMessage(data.ToArray(), req.EntityUid); RaiseNetworkEvent(response, player.ConnectedClient); } } }