void Events_SavedChanges(object sender, EntitySessionEventArgs args) { var session = (EntitySession)args.Session; bool fullSetCacheUpdated = false; // important - use for-i loop here for (int i = 0; i < session.RecordsChanged.Count; i++) { var rec = session.RecordsChanged[i]; switch (rec.EntityInfo.CacheType) { case CacheType.FullSet: fullSetCacheUpdated = true; break; case CacheType.Sparse: switch (rec.StatusBeforeSave) { case EntityStatus.Deleting: _sparseCache.Remove(rec); break; default: _sparseCache.Add(rec); break; }//switch break; } } if (fullSetCacheUpdated) { _fullSetCache.Invalidate(); //it will be reloaded //_maxKnownVersion++; //tick up the version } }//method
protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs) { base.OnBwoinkTextMessage(message, eventArgs); var senderSession = (IPlayerSession)eventArgs.SenderSession; // TODO: Sanitize text? // Confirm that this person is actually allowed to send a message here. if ((senderSession.UserId != message.ChannelId) && (_adminManager.GetAdminData(senderSession) == null)) { // Unauthorized bwoink (log?) return; } var msg = new BwoinkTextMessage(message.ChannelId, senderSession.UserId, $"{senderSession.Name}: {message.Text}"); LogBwoink(msg); var targets = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient); // Admins foreach (var channel in targets) { RaiseNetworkEvent(msg, channel); } // And involved player if (_playerManager.TryGetSessionById(message.ChannelId, out var session)) { if (!targets.Contains(session.ConnectedClient)) { RaiseNetworkEvent(msg, session.ConnectedClient); } } }
/// <summary> /// Move an entity which is dragged by the user, but check if they are allowed to do so and to these coordinates /// </summary> private void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args) { if (args.SenderSession as IPlayerSession is not { AttachedEntity : { } playerEntity } playerSession) { return; } if (!EntityManager.TryGetComponent(msg.TableUid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) { return; } // Check if player is actually playing at this table if (!session.Players.ContainsKey(playerSession)) { return; } if (!CanSeeTable(playerEntity, msg.TableUid) || !CanDrag(playerEntity, msg.MovedEntityUid, out _)) { return; } // TODO: some permission system, disallow movement if you're not permitted to move the item // Move the entity and dirty it (we use the map ID from the entity so noone can try to be funny and move the item to another map) var transform = EntityManager.GetComponent <TransformComponent>(msg.MovedEntityUid); var entityCoordinates = new EntityCoordinates(_mapManager.GetMapEntityId(transform.MapID), msg.Coordinates.Position); transform.Coordinates = entityCoordinates; }
private void HandleVerbRequest(RequestServerVerbsEvent args, EntitySessionEventArgs eventArgs) { var player = (IPlayerSession)eventArgs.SenderSession; if (!EntityManager.EntityExists(args.EntityUid)) { Logger.Warning($"{nameof(HandleVerbRequest)} called on a non-existent entity with id {args.EntityUid} by player {player}."); return; } if (player.AttachedEntity is not { } attached) { Logger.Warning($"{nameof(HandleVerbRequest)} called by player {player} with no attached entity."); return; } // We do not verify that the user has access to the requested entity. The individual verbs should check // this, and some verbs (e.g. view variables) won't even care about whether an entity is accessible through // the entity menu or not. var force = args.AdminRequest && eventArgs.SenderSession is IPlayerSession playerSession && _adminMgr.HasAdminFlag(playerSession, AdminFlags.Admin); var response = new VerbsResponseEvent(args.EntityUid, GetLocalVerbs(args.EntityUid, attached, args.Type, force)); RaiseNetworkEvent(response, player.ConnectedClient); }
private void HandleExecuteVerb(ExecuteVerbEvent args, EntitySessionEventArgs eventArgs) { var user = eventArgs.SenderSession.AttachedEntity; if (user == null) { return; } // It is possible that client-side prediction can cause this event to be raised after the target entity has // been deleted. So we need to check that the entity still exists. if (Deleted(args.Target) || Deleted(user)) { return; } // Get the list of verbs. This effectively also checks that the requested verb is in fact a valid verb that // the user can perform. var verbs = GetLocalVerbs(args.Target, user.Value, args.RequestedVerb.GetType()); // Note that GetLocalVerbs might waste time checking & preparing unrelated verbs even though we know // precisely which one we want to run. However, MOST entities will only have 1 or 2 verbs of a given type. // The one exception here is the "other" verb type, which has 3-4 verbs + all the debug verbs. // Find the requested verb. if (verbs.TryGetValue(args.RequestedVerb, out var verb)) { ExecuteVerb(verb, user.Value, args.Target); } }
private void HandleActivateItemInHand(RequestActivateInHandEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity != null) { TryActivateItemInHand(args.SenderSession.AttachedEntity.Value); } }
private void HandleMoveItemFromHand(RequestMoveHandItemEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity != null) { TryMoveHeldEntityToActiveHand(args.SenderSession.AttachedEntity.Value, msg.HandName); } }
private void HandleActivateInHand(ActivateInHandMsg msg, EntitySessionEventArgs args) { if (TryComp(args.SenderSession.AttachedEntity, out SharedHandsComponent? hands)) { hands.ActivateHeldEntity(msg.HandName); } }
private void OnDraggingPlayerChanged(TabletopDraggingPlayerChangedEvent msg, EntitySessionEventArgs args) { var dragged = msg.DraggedEntityUid; if (!EntityManager.TryGetComponent <TabletopDraggableComponent?>(dragged, out var draggableComponent)) { return; } draggableComponent.DraggingPlayer = msg.IsDragging ? args.SenderSession.UserId : null; if (!EntityManager.TryGetComponent <AppearanceComponent?>(dragged, out var appearance)) { return; } if (draggableComponent.DraggingPlayer != null) { appearance.SetData(TabletopItemVisuals.Scale, new Vector2(1.25f, 1.25f)); appearance.SetData(TabletopItemVisuals.DrawDepth, (int)DrawDepth.Items + 1); } else { appearance.SetData(TabletopItemVisuals.Scale, Vector2.One); appearance.SetData(TabletopItemVisuals.DrawDepth, (int)DrawDepth.Items); } }
private void HandleInteractUsingInHand(ClientInteractUsingInHandMsg msg, EntitySessionEventArgs args) { if (TryComp(args.SenderSession.AttachedEntity, out SharedHandsComponent? hands)) { hands.InteractHandWithActiveHand(msg.HandName); } }
private void HandleUseInHand(UseInHandMsg msg, EntitySessionEventArgs args) { if (TryComp(args.SenderSession.AttachedEntity, out SharedHandsComponent? hands)) { hands.ActivateItem(); } }
private void HandleMoveItemFromHand(MoveItemFromHandMsg msg, EntitySessionEventArgs args) { if (TryComp(args.SenderSession.AttachedEntity, out SharedHandsComponent? hands)) { hands.TryMoveHeldEntityToActiveHand(msg.HandName); } }
private void OnFirePos(FirePosEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity is not { Valid : true } user) { return; } if (!msg.Coordinates.IsValid(EntityManager)) { return; } if (!TryComp(user, out HandsComponent? handsComponent)) { return; } // TODO: Not exactly robust var gun = handsComponent.GetActiveHand()?.HeldEntity; if (gun == null || !TryComp(gun, out ServerRangedWeaponComponent? weapon)) { return; } // map pos TryFire(user, msg.Coordinates, weapon); }
private void HandleInteractUsingInHand(RequestHandInteractUsingEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity != null) { TryInteractHandWithActiveHand(args.SenderSession.AttachedEntity.Value, msg.HandName); } }
protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySessionEventArgs eventArgs) { base.OnBwoinkTextMessage(message, eventArgs); var senderSession = (IPlayerSession)eventArgs.SenderSession; // TODO: Sanitize text? // Confirm that this person is actually allowed to send a message here. var senderPersonalChannel = senderSession.UserId == message.ChannelId; var senderAdmin = _adminManager.GetAdminData(senderSession); var authorized = senderPersonalChannel || senderAdmin != null; if (!authorized) { // Unauthorized bwoink (log?) return; } var escapedText = Basic.EscapeText(message.Text); var bwoinkText = senderAdmin switch { var x when x is not null && x.Flags == AdminFlags.Adminhelp => $"[color=purple]{senderSession.Name}[/color]: {escapedText}", var x when x is not null && x.HasFlag(AdminFlags.Adminhelp) => $"[color=red]{senderSession.Name}[/color]: {escapedText}", _ => $"{senderSession.Name}: {escapedText}", }; var msg = new BwoinkTextMessage(message.ChannelId, senderSession.UserId, bwoinkText); LogBwoink(msg); // Admins var targets = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient).ToList(); // And involved player if (_playerManager.TryGetSessionById(message.ChannelId, out var session)) { if (!targets.Contains(session.ConnectedClient)) { targets.Add(session.ConnectedClient); } } foreach (var channel in targets) { RaiseNetworkEvent(msg, channel); } if (targets.Count == 1) { var systemText = senderPersonalChannel ? Loc.GetString("bwoink-system-starmute-message-no-other-users-primary") : Loc.GetString("bwoink-system-starmute-message-no-other-users-secondary"); var starMuteMsg = new BwoinkTextMessage(message.ChannelId, SystemUserId, systemText); RaiseNetworkEvent(starMuteMsg, senderSession.ConnectedClient); } }
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 HandleSetHand(RequestSetHandEvent msg, EntitySessionEventArgs eventArgs) { if (eventArgs.SenderSession.AttachedEntity == null) { return; } TrySetActiveHand(eventArgs.SenderSession.AttachedEntity.Value, msg.HandName); }
private void HandleInteractUsingInHand(ClientInteractUsingInHandMsg msg, EntitySessionEventArgs args) { if (!TryGetHandsComp(args.SenderSession, out var hands)) { return; } hands.InteractHandWithActiveHand(msg.HandName); }
private void HandleActivateInHand(ActivateInHandMsg msg, EntitySessionEventArgs args) { if (!TryGetHandsComp(args.SenderSession, out var hands)) { return; } hands.ActivateHeldEntity(msg.HandName); }
private void HandleUseInHand(UseInHandMsg msg, EntitySessionEventArgs args) { if (!TryGetHandsComp(args.SenderSession, out var hands)) { return; } hands.ActivateItem(); }
private void HandleMoveItemFromHand(MoveItemFromHandMsg msg, EntitySessionEventArgs args) { if (!TryGetHandsComp(args.SenderSession, out var hands)) { return; } hands.TryMoveHeldEntityToActiveHand(msg.HandName); }
private void HandleDrop(RequestDropHeldEntityEvent msg, EntitySessionEventArgs eventArgs) { var entity = eventArgs.SenderSession?.AttachedEntity; if (entity == null || !entity.TryGetComponent(out SharedHandsComponent? hands)) return; hands.TryDropHand(msg.HandName, msg.DropTarget); }
private void HandleSetHand(RequestSetHandEvent msg, EntitySessionEventArgs eventArgs) { var entity = eventArgs.SenderSession?.AttachedEntity; if (entity == null || !entity.TryGetComponent(out SharedHandsComponent? hands)) return; hands.ActiveHand = msg.HandName; }
/// <summary> /// Will attempt to equip or unequip an item to/from the clicked slot. If the user clicked on an occupied slot /// with some entity, will instead attempt to interact with this entity. /// </summary> private void OnUseSlot(UseSlotNetworkMessage ev, EntitySessionEventArgs eventArgs) { if (eventArgs.SenderSession.AttachedEntity is not EntityUid { Valid : true } actor) { return; } if (!TryComp(actor, out InventoryComponent? inventory) || !TryComp <SharedHandsComponent>(actor, out var hands)) { return; } hands.TryGetActiveHeldEntity(out var held); TryGetSlotEntity(actor, ev.Slot, out var itemUid, inventory); // attempt to perform some interaction if (held != null && itemUid != null) { _interactionSystem.InteractUsing(actor, held.Value, itemUid.Value, new EntityCoordinates(), predicted: true); return; } // un-equip to hands if (itemUid != null) { if (hands.CanPickupEntityToActiveHand(itemUid.Value) && TryUnequip(actor, ev.Slot, inventory: inventory)) { hands.PutInHand(itemUid.Value, false); } return; } // finally, just try to equip the held item. if (held == null) { return; } // before we drop the item, check that it can be equipped in the first place. if (!CanEquip(actor, held.Value, ev.Slot, out var reason)) { if (_gameTiming.IsFirstTimePredicted) { _popup.PopupCursor(Loc.GetString(reason), Filter.Local()); } return; } if (hands.TryDropNoInteraction()) { TryEquip(actor, actor, held.Value, ev.Slot, predicted: true, inventory: inventory); } }
private void HandleDragDropRequestEvent(DragDropRequestEvent msg, EntitySessionEventArgs args) { if (!ValidateClientInput(args.SenderSession, msg.DropLocation, msg.Target, out var userEntity)) { Logger.InfoS("system.interaction", $"DragDropRequestEvent input validation failed"); return; } if (!_actionBlockerSystem.CanInteract(userEntity.Value)) { return; } if (!EntityManager.EntityExists(msg.Dropped)) { return; } if (!EntityManager.EntityExists(msg.Target)) { return; } var interactionArgs = new DragDropEvent(userEntity.Value, msg.DropLocation, msg.Dropped, msg.Target); // must be in range of both the target and the object they are drag / dropping // Client also does this check but ya know we gotta validate it. if (!interactionArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) { return; } // trigger dragdrops on the dropped entity RaiseLocalEvent(msg.Dropped, interactionArgs); foreach (var dragDrop in EntityManager.GetComponents <IDraggable>(msg.Dropped)) { if (dragDrop.CanDrop(interactionArgs) && dragDrop.Drop(interactionArgs)) { return; } } // trigger dragdropons on the targeted entity RaiseLocalEvent(msg.Target, interactionArgs, false); foreach (var dragDropOn in EntityManager.GetComponents <IDragDropOn>(msg.Target)) { if (dragDropOn.CanDragDropOn(interactionArgs) && dragDropOn.DragDropOn(interactionArgs)) { return; } } }
public static void RaisePredictiveEvent <T>(this IEntityManager entityManager, T msg) where T : EntitySystemMessage { var sequence = IoCManager.Resolve <IClientGameStateManager>().SystemMessageDispatched(msg); entityManager.EntityNetManager.SendSystemNetworkMessage(msg, sequence); var eventArgs = new EntitySessionEventArgs(IoCManager.Resolve <IPlayerManager>().LocalPlayer.Session); entityManager.EventBus.RaiseEvent(EventSource.Local, msg); entityManager.EventBus.RaiseEvent(EventSource.Local, new EntitySessionMessage <T>(eventArgs, msg)); }
/// <summary> /// Move an entity which is dragged by the user, but check if they are allowed to do so and to these coordinates /// </summary> private void OnTabletopMove(TabletopMoveEvent msg, EntitySessionEventArgs args) { if (args.SenderSession as IPlayerSession is not { AttachedEntity : { } playerEntity } playerSession) { return; } if (!EntityManager.TryGetComponent(msg.TableUid, out TabletopGameComponent? tabletop) || tabletop.Session is not { } session) { return; } // Check if player is actually playing at this table if (!session.Players.ContainsKey(playerSession)) { return; } // Return if can not see table or stunned/no hands if (!EntityManager.TryGetEntity(msg.TableUid, out var table)) { return; } if (!CanSeeTable(playerEntity, table) || StunnedOrNoHands(playerEntity)) { return; } // Check if moved entity exists and has tabletop draggable component if (!EntityManager.TryGetEntity(msg.MovedEntityUid, out var movedEntity)) { return; } if (!EntityManager.HasComponent <TabletopDraggableComponent>(movedEntity.Uid)) { return; } // TODO: some permission system, disallow movement if you're not permitted to move the item // Move the entity and dirty it (we use the map ID from the entity so noone can try to be funny and move the item to another map) var transform = EntityManager.GetComponent <ITransformComponent>(movedEntity.Uid); var entityCoordinates = new EntityCoordinates(_mapManager.GetMapEntityId(transform.MapID), msg.Coordinates.Position); transform.Coordinates = entityCoordinates; movedEntity.Dirty(); }
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; 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 OnRequestCharacterInfoEvent(RequestCharacterInfoEvent msg, EntitySessionEventArgs args) { if (!args.SenderSession.AttachedEntity.HasValue || args.SenderSession.AttachedEntity != msg.EntityUid) { return; } var entity = args.SenderSession.AttachedEntity.Value; var conditions = new Dictionary <string, List <ConditionInfo> >(); var jobTitle = "No Profession"; var briefing = "!!ERROR: No Briefing!!"; //should never show on the UI unless there's a bug if (EntityManager.TryGetComponent(entity, out MindComponent? mindComponent) && mindComponent.Mind != null) { var mind = mindComponent.Mind; // Get objectives foreach (var objective in mind.AllObjectives) { if (!conditions.ContainsKey(objective.Prototype.Issuer)) { conditions[objective.Prototype.Issuer] = new List <ConditionInfo>(); } foreach (var condition in objective.Conditions) { conditions[objective.Prototype.Issuer].Add(new ConditionInfo(condition.Title, condition.Description, condition.Icon, condition.Progress)); } } // Get job title foreach (var role in mind.AllRoles) { if (role.GetType() != typeof(Job)) { continue; } jobTitle = role.Name; break; } // Get briefing briefing = mind.Briefing; } RaiseNetworkEvent(new CharacterInfoEvent(entity, jobTitle, conditions, briefing), Filter.SinglePlayer(args.SenderSession)); }