public override void MouseDown(MouseButtonEventArgs eventargs) { if (playerManager.LocalPlayer == null || placementManager.MouseDown(eventargs)) { return; } var map = playerManager.LocalPlayer.ControlledEntity.GetComponent <ITransformComponent>().MapID; var mousePosWorld = eyeManager.ScreenToWorld(new ScreenCoordinates(eventargs.Position, map)); IEntity entityToClick = GetEntityUnderPosition(mousePosWorld); //First possible exit point for click, acceptable due to being clientside if (entityToClick != null && placementManager.Eraser && placementManager.IsActive) { placementManager.HandleDeletion(entityToClick); return; } ClickType clicktype = eventargs.ClickType; //Dispatches clicks to relevant clickable components, another single exit point for UI if (entityToClick != null) { var clickable = entityToClick.GetComponent <IClientClickableComponent>(); switch (eventargs.ClickType) { case ClickType.Left: clickable.DispatchClick(playerManager.LocalPlayer.ControlledEntity, ClickType.Left); break; case ClickType.Right: clickable.DispatchClick(playerManager.LocalPlayer.ControlledEntity, ClickType.Right); break; /* * //Acceptable click exit due to being a UI behavior * case Mouse.Button.Middle: * OpenEntityEditWindow(entToClick); * return; */ } } //Assemble information to send to server about click if (clicktype != ClickType.None) { var UID = EntityUid.Invalid; if (entityToClick != null) { UID = entityToClick.Uid; } ClickEventMessage message = new ClickEventMessage(UID, clicktype, mousePosWorld); IoCManager.Resolve <IEntityNetworkManager>().SendSystemNetworkMessage(message); } }
public void Examine(ClickEventMessage msg, IEntity player) { //Get entity clicked upon from UID if valid UID, if not assume no entity clicked upon and null IEntity examined = null; if (msg.Uid.IsValid()) { examined = EntityManager.GetEntity(msg.Uid); } if (examined == null) { return; } //Verify player has a transform component if (!player.TryGetComponent <IServerTransformComponent>(out var playerTransform)) { return; } //Verify player is on the same map as the entity he clicked on else if (msg.Coordinates.MapID != playerTransform.MapID) { Logger.Warning(string.Format("Player named {0} clicked on a map he isn't located on", player.Name)); return; } //Start a stringbuilder since we have no idea how many times this could be appended to StringBuilder fullexaminetext = new StringBuilder("This is " + examined.Name); //Add an entity description if one is declared if (!string.IsNullOrEmpty(examined.Description)) { fullexaminetext.Append(Environment.NewLine + examined.Description); } //Add component statuses from components that report one foreach (var examinecomponents in examined.GetAllComponents <IExamine>()) { string componentdescription = examinecomponents.Examine(); if (!string.IsNullOrEmpty(componentdescription)) { fullexaminetext.Append(Environment.NewLine + componentdescription); } } //Send to client chat channel //TODO: Fix fact you can only send to all clients because you cant resolve clients from player entities IoCManager.Resolve <IChatManager>().DispatchMessage(SS14.Shared.Console.ChatChannel.Visual, fullexaminetext.ToString()); }
/// <summary> /// Parse click to the relevant entity system /// </summary> /// <param name="message"></param> /// <param name="player"></param> private void ParseClickMessage(ClickEventMessage message, IEntity player) { switch (message.Click) { case ClickType.Left: EntitySystemManager.GetEntitySystem <InteractionSystem>().UserInteraction(message, player); break; case (ClickType.Left | ClickType.Shift): EntitySystemManager.GetEntitySystem <ExamineSystem>().Examine(message, player); break; case ClickType.Right: //Verb System break; } }
private void UserInteraction(ClickEventMessage msg, IEntity player) { //Verify click type if (msg.Click != ClickType.Left) { return; } //Get entity clicked upon from UID if valid UID, if not assume no entity clicked upon and null IEntity attacked = null; if (msg.Uid.IsValid()) { attacked = EntityManager.GetEntity(msg.Uid); } //Verify player has a transform component if (!player.TryGetComponent <IServerTransformComponent>(out var playerTransform)) { return; } //Verify player is on the same map as the entity he clicked on else if (msg.Coordinates.MapID != playerTransform.MapID) { Logger.Warning(string.Format("Player named {0} clicked on a map he isn't located on", player.Name)); return; } //Verify player has a hand, and find what object he is currently holding in his active hand if (!player.TryGetComponent <IHandsComponent>(out var hands)) { return; } var item = hands.GetHand(hands.ActiveIndex)?.Owner; //TODO: Mob status code that allows or rejects interactions based on current mob status //Check if client should be able to see that object to click on it in the first place, prevent using locaters by firing a laser or something //Off entity click handling if (attacked == null) { if (item != null) { //AFTERATTACK: Check if we clicked on an empty location, if so the only interaction we can do is afterattack InteractAfterattack(player, item, msg.Coordinates); return; } return; } //USE: Check if we clicked on the item we are holding in our active hand to use it else if (attacked == item && item != null) { UseInteraction(player, item); return; } //Check if ClickLocation is in object bounds here, if not lets log as warning and see why if (attacked != null && attacked.TryGetComponent(out BoundingBoxComponent boundingbox)) { if (!boundingbox.WorldAABB.Contains(msg.Coordinates.Position)) { Logger.Warning(string.Format("Player {0} clicked {1} outside of its bounding box component somehow", player.Name, attacked.Name)); return; } } //RANGEDATTACK/AFTERATTACK: Check distance between user and clicked item, if too large parse it in the ranged function //TODO: have range based upon the item being used? or base it upon some variables of the player himself? var distance = (playerTransform.WorldPosition - attacked.GetComponent <IServerTransformComponent>().WorldPosition).LengthSquared; if (distance > INTERACTION_RANGE_SQUARED) { if (item != null) { RangedInteraction(player, item, attacked, msg.Coordinates); return; } return; //Add some form of ranged attackhand here if you need it someday, or perhaps just ways to modify the range of attackhand } //We are close to the nearby object and the object isn't contained in our active hand //ATTACKBY/AFTERATTACK: We will either use the item on the nearby object if (item != null) { Interaction(player, item, attacked, msg.Coordinates); } //ATTACKHAND: Since our hand is empty we will use attackhand else { Interaction(player, attacked); } }
public override void MouseDown(MouseButtonEventArgs eventargs) { if (playerManager.LocalPlayer == null || placementManager.MouseDown(eventargs)) { return; } var map = playerManager.LocalPlayer.ControlledEntity.GetComponent <ITransformComponent>().MapID; var mousePosWorld = eyeManager.ScreenToWorld(new ScreenCoordinates(eventargs.Position, map)); // Find all the entities intersecting our click var entities = _entityManager.GetEntitiesIntersecting(mousePosWorld.MapID, mousePosWorld.Position); // Check the entities against whether or not we can click them var clickedEntities = new List <(IEntity clicked, int drawDepth)>(); foreach (IEntity entity in entities) { if (entity.TryGetComponent <IClientClickableComponent>(out var component) && entity.GetComponent <ITransformComponent>().IsMapTransform && component.CheckClick(mousePosWorld, out int drawdepthofclicked)) { clickedEntities.Add((entity, drawdepthofclicked)); } } IEntity entityToClick; if (clickedEntities.Any()) { entityToClick = (from cd in clickedEntities orderby cd.drawDepth ascending, cd.clicked.GetComponent <ITransformComponent>().LocalPosition .Y ascending select cd.clicked).Last(); } else { entityToClick = null; } //First possible exit point for click, acceptable due to being clientside if (entityToClick != null && placementManager.Eraser && placementManager.IsActive) { placementManager.HandleDeletion(entityToClick); return; } ClickType clicktype = eventargs.ClickType; //Dispatches clicks to relevant clickable components, another single exit point for UI if (entityToClick != null) { var clickable = entityToClick.GetComponent <IClientClickableComponent>(); switch (eventargs.ClickType) { case ClickType.Left: clickable.DispatchClick(playerManager.LocalPlayer.ControlledEntity, ClickType.Left); break; case ClickType.Right: clickable.DispatchClick(playerManager.LocalPlayer.ControlledEntity, ClickType.Right); break; /* * //Acceptable click exit due to being a UI behavior * case Mouse.Button.Middle: * OpenEntityEditWindow(entToClick); * return; */ } } //Assemble information to send to server about click if (clicktype != ClickType.None) { var UID = EntityUid.Invalid; if (entityToClick != null) { UID = entityToClick.Uid; } ClickEventMessage message = new ClickEventMessage(UID, clicktype, mousePosWorld); IoCManager.Resolve <IEntityNetworkManager>().SendSystemNetworkMessage(message); } }
/// <summary> /// 返回具体事件类型 /// </summary> /// <param name="node"></param> /// <returns></returns> protected RequestMessage ToMessage(XmlNode node) { RequestMessage message = null; switch (this.Event) { case EventType.Click: ClickEventMessage cm = this.Copy <ClickEventMessage>(); cm.EventKey = GetValue(node, "EventKey"); message = cm; break; case EventType.Scan: //是二维码扫描事件 QCodeEventMessage m = this.Copy <QCodeEventMessage>(); m.Ticket = GetValue(node, "Ticket"); m.EventKey = GetValue(node, "EventKey"); message = m; break; case EventType.Location: //是地理位置事件 LocationEventMessage lm = this.Copy <LocationEventMessage>(); lm.Latitude = Convert.ToDouble(GetValue(node, "Latitude")); lm.Longitude = Convert.ToDouble(GetValue(node, "Longitude")); lm.Precision = Convert.ToDouble(GetValue(node, "Precision")); message = lm; break; case EventType.View: ViewEventMessage vm = this.Copy <ViewEventMessage>(); vm.EventKey = GetValue(node, "EventKey"); message = vm; break; case EventType.Subscribe: //分2种 用户未关注时,进行关注后的事件推送 / 关注事件 string ticekt = GetValue(node, "Ticket"); if (ticekt == null) { //是关注事件 message = this.Copy <SubscribeEventMessage>(); } else { QCodeEventMessage mm = this.Copy <QCodeEventMessage>(); mm.Ticket = GetValue(node, "Ticket"); mm.EventKey = GetValue(node, "EventKey"); message = mm; } break; case EventType.UnSubscribe: //是取消关注事件 message = this.Copy <SubscribeEventMessage>(); break; default: message = this; break; } return(message); }
public virtual void RaiseClick(ClickEventMessage message) { //TODO: Check modifiers here and modify the click type of the message? RaiseNetworkEvent(message); }