/// <summary> /// Alternative interactions on an entity. /// </summary> /// <remarks> /// Uses the context menu verb list, and acts out the first verb marked as an alternative interaction. Note /// that this does not have any checks to see whether this interaction is valid, as these are all done in <see /// cref="UserInteraction(IEntity, EntityCoordinates, EntityUid, bool)"/> /// </remarks> public void AltInteract(IEntity user, IEntity target) { // TODO VERB SYSTEM when ECS-ing verbs and re-writing VerbUtility.GetVerbs, maybe sort verbs by some // priority property, such that which verbs appear first is more predictable?. // Iterate through list of verbs that apply to target. We do not include global verbs here. If in the future // alt click should also support global verbs, this needs to be changed. foreach (var(component, verb) in VerbUtility.GetVerbs(target)) { // Check that the verb marked as an alternative interaction? if (!verb.AlternativeInteraction) { continue; } // Can the verb be acted out? if (!VerbUtility.VerbAccessChecks(user, target, verb)) { continue; } // Is the verb currently enabled? var verbData = verb.GetData(user, component); if (verbData.IsInvisible || verbData.IsDisabled) { continue; } // Act out the verb. Note that, if there is more than one AlternativeInteraction verb, only the first // one is activated. The priority is effectively determined by the order in which VerbUtility.GetVerbs() // returns the verbs. verb.Activate(user, component); 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; if (userEntity == null) { Logger.Warning($"{nameof(UseVerb)} called by player {player} with no attached entity."); return; } var data = new List <VerbsResponseMessage.NetVerbData>(); //Get verbs, component dependent. foreach (var(component, verb) in VerbUtility.GetVerbs(entity)) { if (!VerbUtility.VerbAccessChecks(userEntity, entity, verb)) { 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 (!VerbUtility.VerbAccessChecks(userEntity, entity, globalVerb)) { 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); }
private void UseVerb(UseVerbMessage use) { var channel = use.NetChannel; if (channel == null) { return; } if (!_entityManager.TryGetEntity(use.EntityUid, out var entity)) { return; } var session = _playerManager.GetSessionByChannel(channel); 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) { var channel = req.NetChannel; if (channel == null) { return; } if (!_entityManager.TryGetEntity(req.EntityUid, out var entity)) { return; } var session = _playerManager.GetSessionByChannel(channel); var userEntity = session.AttachedEntity; var data = new List <VerbsResponseMessage.VerbData>(); //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)) { 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)); } //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; } if (VerbUtility.IsVerbInvisible(globalVerb, userEntity, entity, out var vis)) { continue; } data.Add(new VerbsResponseMessage.VerbData(globalVerb.GetText(userEntity, entity), globalVerb.GetType().ToString(), globalVerb.GetCategory(userEntity, entity), vis == VerbVisibility.Visible)); } var response = new VerbsResponseMessage(data, req.EntityUid); RaiseNetworkEvent(response, channel); }
private void RequestVerbs(RequestVerbsMessage req, EntitySessionEventArgs eventArgs) { var player = (IPlayerSession)eventArgs.SenderSession; if (!_entityManager.TryGetEntity(req.EntityUid, out var entity)) { return; } var userEntity = player.AttachedEntity; 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; } 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); }
private void UseVerb(UseVerbMessage use, EntitySessionEventArgs eventArgs) { if (!_entityManager.TryGetEntity(use.EntityUid, out var entity)) { return; } var session = eventArgs.SenderSession; var userEntity = session.AttachedEntity; if (userEntity == null) { Logger.Warning($"{nameof(UseVerb)} called by player {session} with no attached entity."); return; } foreach (var(component, verb) in VerbUtility.GetVerbs(entity)) { if ($"{component.GetType()}:{verb.GetType()}" != use.VerbKey) { continue; } if (!VerbUtility.VerbAccessChecks(userEntity, entity, verb)) { break; } verb.Activate(userEntity, component); break; } foreach (var globalVerb in VerbUtility.GetGlobalVerbs(Assembly.GetExecutingAssembly())) { if (globalVerb.GetType().ToString() != use.VerbKey) { continue; } if (!VerbUtility.VerbAccessChecks(userEntity, entity, globalVerb)) { break; } globalVerb.Activate(userEntity, entity); break; } }
public override void HandleNetMessage(INetChannel channel, EntitySystemMessage message) { base.HandleNetMessage(channel, message); switch (message) { case RequestVerbsMessage req: { if (!_entityManager.TryGetEntity(req.EntityUid, out var entity)) { return; } var session = _playerManager.GetSessionByChannel(channel); var userEntity = session.AttachedEntity; var data = new List <VerbsResponseMessage.VerbData>(); foreach (var(component, verb) in VerbUtility.GetVerbs(entity)) { if (verb.RequireInteractionRange) { var distanceSquared = (userEntity.Transform.WorldPosition - entity.Transform.WorldPosition) .LengthSquared; if (distanceSquared > Verb.InteractionRangeSquared) { continue; } } var vis = verb.GetVisibility(userEntity, component); if (vis == VerbVisibility.Invisible) { continue; } // TODO: These keys being giant strings is inefficient as hell. data.Add(new VerbsResponseMessage.VerbData(verb.GetText(userEntity, component), $"{component.GetType()}:{verb.GetType()}", vis == VerbVisibility.Visible)); } var response = new VerbsResponseMessage(data, req.EntityUid); RaiseNetworkEvent(response, channel); break; } case UseVerbMessage use: { if (!_entityManager.TryGetEntity(use.EntityUid, out var entity)) { return; } var session = _playerManager.GetSessionByChannel(channel); 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 > Verb.InteractionRangeSquared) { break; } } verb.Activate(userEntity, component); break; } break; } } }