//only intended to be used by core if2 classes public static void SendTileApply(TileApply tileApply, InteractableTiles interactableTiles, TileInteraction tileInteraction, int tileInteractionIndex) { //if we are client and the interaction has client prediction, trigger it. //Note that client prediction is not triggered for server player. if (!CustomNetworkManager.IsServer) { Logger.LogTraceFormat("Predicting TileApply interaction {0}", Category.Interaction, tileApply); tileInteraction.ClientPredictInteraction(tileApply); } if (!tileApply.Performer.Equals(PlayerManager.LocalPlayer)) { Logger.LogError("Client attempting to perform an interaction on behalf of another player." + " This is not allowed. Client can only perform an interaction as themselves. Message" + " will not be sent.", Category.NetMessage); return; } var msg = new RequestInteractMessage() { ComponentType = typeof(InteractableTiles), InteractionType = typeof(TileApply), ProcessorObject = interactableTiles.GetComponent <NetworkIdentity>().netId, Intent = tileApply.Intent, TargetVector = tileApply.TargetVector, TileInteractionIndex = tileInteractionIndex }; msg.Send(); }
/// <summary> /// Use this on client side to request an interaction. This can be used to trigger /// interactions manually outside of the normal interaction logic. /// Request the server to perform the indicated interaction using the specified /// component (or let the server determine the component if interactableComponent is null). The server will still validate the interaction and only perform /// it if it validates. /// /// Note that if interactableComponent implements IClientSideInteractable for this interaction type, /// nothing will be done. /// </summary> /// <param name="interaction">interaction to perform</param> /// <param name="interactableComponent">component to handle the interaction, null /// if the server should determine which component will trigger from the interaction</param> /// <typeparam name="T">type of interaction</typeparam> public static void RequestInteract <T>(T interaction, IBaseInteractable <T> interactableComponent = null) where T : Interaction { if (!Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction)) { return; } RequestInteractMessage.Send(interaction, interactableComponent); }
private void OnFlipClicked() { if (!Validations.IsInReach(gameObject.RegisterTile(), PlayerManager.LocalPlayerScript.registerTile, false)) { return; } var menuApply = ContextMenuApply.ByLocalPlayer(gameObject, "Flip"); RequestInteractMessage.Send(menuApply, this); }
/// <summary> /// Send a request to the server to validate + perform the interaction. /// </summary> /// <param name="info">info on the interaction being performed. Each object involved in the interaction /// must have a networkidentity.</param> /// <param name="processor">component which will process the interaction on the server-side. The processor's /// info and result types must match the info and result type of one of the interaction type constants /// defined in InteractionType. /// /// This component /// must live on a GameObject with a network identity, and there must only be one instance of this component /// on the object. For organization, we suggest that the component which is sending this message /// should be the processor, as such this parameter should almost always be passed using the "this" keyword, and /// should almost always be either a component on the target object or a component on the used object</param> /// <typeparamref name="T">Interaction subtype /// for the interaction that the processor can handle (such as MouseDrop for a mouse drop interaction). /// Must be a subtype of Interaction.</typeparamref> /// <returns></returns> public static RequestInteractMessage Send <T>(T info, IInteractionProcessor <T> processor) where T : Interaction { if (!info.Performer.Equals(PlayerManager.LocalPlayer)) { Logger.LogError("Client attempting to perform an interaction on behalf of another player." + " This is not allowed. Client can only perform an interaction as themselves. Message" + " will not be sent.", Category.NetMessage); return(null); } if (!(processor is Component)) { Logger.LogError("processor must be a component, but isn't. The message will not be sent.", Category.NetMessage); return(null); } short typeID; var processorObject = (processor as Component).gameObject; if (InteractionTypeToID.TryGetValue(typeof(T), out typeID)) { RequestInteractMessage msg = null; //send the message appropriate to the specific interaction type if (typeof(T) == typeof(MouseDrop)) { msg = CreateMouseDropMessage(info as MouseDrop, processorObject, typeID); } else if (typeof(T) == typeof(HandApply)) { msg = CreateHandApplyMessage(info as HandApply, processorObject, typeID); } //TODO: Other types if (msg != null) { msg.Send(); return(msg); } else { Logger.LogErrorFormat("Interaction type was {0} - we couldn't determine what to do for this interaction" + " type, most likely because it hasn't been implemented yet." + " Please implement handling for this interaction type in RequestInteractMessage.Send()", Category.NetMessage, nameof(T)); return(null); } } else { Logger.LogError("Interaction's concrete type could not be mapped to an ID, this is most likely" + " a programming error. Message will not be sent", Category.NetMessage); return(null); } }
public InteractionResult Interact(HandApply interaction) { ValidationResult validationResult = CanApply.ONLY_IF_CONSCIOUS.Validate(interaction, NetworkSide.CLIENT); if (validationResult == ValidationResult.SUCCESS) { RequestInteractMessage.Send(interaction, this); return(InteractionResult.SOMETHING_HAPPENED); } return(InteractionResult.NOTHING_HAPPENED); }
/// <summary> /// Coordinator will perform client side validation of the interaction using its validators. If any /// validator fails, validation will fail and NOTHING_HAPPENED will be returned. /// If validation succeeds, it will send RequestInteractMessage to the server to request the server /// to perform the interaction. /// </summary> /// <param name="interaction">interaction being performed.</param> /// <returns>SOMETHING_HAPPENED if interaction validated and message was sent, NOTHING_HAPPENED otherwise</returns> public InteractionResult ClientValidateAndRequest(T interaction) { foreach (var validator in validations) { if (validator.Validate(interaction, NetworkSide.CLIENT) == ValidationResult.FAIL) { return(InteractionResult.NOTHING_HAPPENED); } } RequestInteractMessage.Send(interaction, processor); return(InteractionResult.SOMETHING_HAPPENED); }
public static void SendTileMouseDrop(TileMouseDrop mouseDrop, InteractableTiles interactableTiles) { if (!mouseDrop.Performer.Equals(PlayerManager.LocalPlayer)) { Logger.LogError("Client attempting to perform an interaction on behalf of another player." + " This is not allowed. Client can only perform an interaction as themselves. Message" + " will not be sent.", Category.NetMessage); return; } var msg = new RequestInteractMessage() { ComponentType = typeof(InteractableTiles), InteractionType = typeof(TileMouseDrop), ProcessorObject = interactableTiles.GetComponent <NetworkIdentity>().netId, Intent = mouseDrop.Intent, UsedObject = mouseDrop.UsedObject.NetId(), TargetVector = mouseDrop.TargetVector }; msg.Send(); }
private void OnRotateClicked() { var menuApply = ContextMenuApply.ByLocalPlayer(gameObject, "Rotate"); RequestInteractMessage.Send(menuApply, this); }
//only intended to be used by core if2 classes, please use InteractionUtils.RequestInteract instead. public static void Send <T>(T interaction, IBaseInteractable <T> interactableComponent) where T : Interaction { if (typeof(T) == typeof(TileApply)) { Logger.LogError("Cannot use Send with TileApply, please use SendTileApply instead.", Category.Interaction); return; } //never send anything for client-side-only interactions if (interactableComponent is IClientInteractable <T> && !(interactableComponent is IInteractable <T>)) { Logger.LogWarningFormat("Interaction request {0} will not be sent because interactable component {1} is" + " IClientInteractable only (client-side only).", Category.Interaction, interaction, interactableComponent); return; } //if we are client and the interaction has client prediction, trigger it. //Note that client prediction is not triggered for server player. if (!CustomNetworkManager.IsServer && interactableComponent is IPredictedInteractable <T> predictedInteractable) { Logger.LogTraceFormat("Predicting {0} interaction for {1} on {2}", Category.Interaction, typeof(T).Name, interactableComponent.GetType().Name, ((Component)interactableComponent).gameObject.name); predictedInteractable.ClientPredictInteraction(interaction); } if (!interaction.Performer.Equals(PlayerManager.LocalPlayer)) { Logger.LogError("Client attempting to perform an interaction on behalf of another player." + " This is not allowed. Client can only perform an interaction as themselves. Message" + " will not be sent.", Category.NetMessage); return; } if (!(interactableComponent is Component)) { Logger.LogError("interactableComponent must be a component, but isn't. The message will not be sent.", Category.NetMessage); return; } var comp = interactableComponent as Component; var msg = new RequestInteractMessage() { ComponentType = interactableComponent.GetType(), InteractionType = typeof(T), ProcessorObject = comp.GetComponent <NetworkIdentity>().netId, Intent = interaction.Intent }; if (typeof(T) == typeof(PositionalHandApply)) { var casted = interaction as PositionalHandApply; msg.TargetObject = casted.TargetObject.NetId(); msg.TargetVector = casted.TargetVector; msg.TargetBodyPart = casted.TargetBodyPart; } else if (typeof(T) == typeof(HandApply)) { var casted = interaction as HandApply; msg.TargetObject = casted.TargetObject.NetId(); msg.TargetBodyPart = casted.TargetBodyPart; msg.IsAltUsed = casted.IsAltClick; } else if (typeof(T) == typeof(AimApply)) { var casted = interaction as AimApply; msg.TargetVector = casted.TargetVector; msg.MouseButtonState = casted.MouseButtonState; } else if (typeof(T) == typeof(MouseDrop)) { var casted = interaction as MouseDrop; msg.TargetObject = casted.TargetObject.NetId(); msg.UsedObject = casted.UsedObject.NetId(); } else if (typeof(T) == typeof(InventoryApply)) { var casted = interaction as InventoryApply; msg.Storage = casted.TargetSlot.ItemStorageNetID; msg.SlotIndex = casted.TargetSlot.SlotIdentifier.SlotIndex; msg.NamedSlot = casted.TargetSlot.SlotIdentifier.NamedSlot.GetValueOrDefault(NamedSlot.none); msg.UsedObject = casted.UsedObject.NetId(); msg.IsAltUsed = casted.IsAltClick; } msg.Send(); }
/// <summary> /// Used for the right click action, sends a message requesting uncuffing /// </summary> public void OnUncuffClicked() { RequestInteractMessage.Send(ContextMenuApply.ByLocalPlayer(gameObject, "Uncuff"), this); }
/// <summary> /// Use this on client side to request an interaction. This can be used to trigger /// interactions manually outside of the normal interaction logic. /// Request the server to perform the indicated interaction using the specified /// component. The server will still validate the interaction and only perform /// it if it validates. /// /// Note that if interactableComponent implements IClientSideInteractable for this interaction type, /// nothing will be done. /// </summary> /// <param name="interaction">interaction to perform</param> /// <param name="interactableComponent">component to handle the interaction</param> /// <typeparam name="T"></typeparam> public static void RequestInteract <T>(T interaction, IBaseInteractable <T> interactableComponent) where T : Interaction { RequestInteractMessage.Send(interaction, interactableComponent); }
//only intended to be used by core if2 classes, please use InteractionUtils.RequestInteract instead. public static void Send <T>(T interaction, IBaseInteractable <T> interactableComponent) where T : Interaction { //never send anything for client-side-only interactions if (interactableComponent is IClientInteractable <T> ) { return; } //if we are client and the interaction has client prediction, trigger it. //Note that client prediction is not triggered for server player. if (!CustomNetworkManager.IsServer && interactableComponent is IPredictedInteractable <T> predictedInteractable) { Logger.LogTraceFormat("Predicting {0} interaction for {1} on {2}", Category.Interaction, typeof(T).Name, interactableComponent.GetType().Name, ((Component)interactableComponent).gameObject.name); predictedInteractable.ClientPredictInteraction(interaction); } if (!interaction.Performer.Equals(PlayerManager.LocalPlayer)) { Logger.LogError("Client attempting to perform an interaction on behalf of another player." + " This is not allowed. Client can only perform an interaction as themselves. Message" + " will not be sent.", Category.NetMessage); return; } if (!(interactableComponent is Component)) { Logger.LogError("interactableComponent must be a component, but isn't. The message will not be sent.", Category.NetMessage); return; } var comp = interactableComponent as Component; var msg = new RequestInteractMessage() { ComponentType = interactableComponent.GetType(), InteractionType = typeof(T), ProcessorObject = comp.GetComponent <NetworkIdentity>().netId }; if (typeof(T) == typeof(PositionalHandApply)) { var casted = interaction as PositionalHandApply; msg.TargetObject = casted.TargetObject.GetComponent <NetworkIdentity>().netId; msg.TargetVector = casted.TargetVector; } else if (typeof(T) == typeof(HandApply)) { var casted = interaction as HandApply; msg.TargetObject = casted.TargetObject.GetComponent <NetworkIdentity>().netId; msg.TargetBodyPart = casted.TargetBodyPart; } else if (typeof(T) == typeof(AimApply)) { var casted = interaction as AimApply; msg.TargetVector = casted.TargetVector; msg.MouseButtonState = casted.MouseButtonState; } else if (typeof(T) == typeof(MouseDrop)) { var casted = interaction as MouseDrop; msg.TargetObject = casted.TargetObject.GetComponent <NetworkIdentity>().netId; msg.UsedObject = casted.UsedObject.GetComponent <NetworkIdentity>().netId; } msg.Send(); }