using UnityEngine; using Mirror; using UnityEngine.EventSystems; using System.Collections; using LegacyTouchPhase = UnityEngine.TouchPhase; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif public class NetPlayer : NetworkBehaviour { [SyncVar] public int userId; [SyncVar] public Team myTeam; // set the team to red if there are no other players, if not set blue public override void OnStartLocalPlayer() { base.OnStartLocalPlayer(); #if UNITY_EDITOR // Count current NetPlayers in the scene if(Cupid.RoomPort == -1){ //Without cupid, set the team to red bool cloneWorkspace = LoginManager.EditorWorkspaceLooksLikeClone(); SetMyTeam(cloneWorkspace ? Team.Red : Team.Blue); SetMyData(cloneWorkspace ? 0: 1 ); }else{ SetMyTeam(GameManager.MyTeam); SetMyData(GameManager.MyTeam == Team.Red ? GameManager.RedPlayer.UserId : GameManager.BluePlayer.UserId); } #else SetMyTeam(GameManager.MyTeam); SetMyData(GameManager.MyTeam == Team.Red ? GameManager.RedPlayer.UserId : GameManager.BluePlayer.UserId); #endif TeamSpecificEffects.instance.SetTeamSpecificEffects(myTeam); } void SetMyData(int uid){ if(isServer){ setMyData(uid); }else{ CmdSetMyData(uid); setMyData(uid); } } void setMyData(int uid){ userId= uid; } [Command] void CmdSetMyData(int uid){ userId=uid; } void SetMyTeam(Team team){ if(isServer){ setMyTeam(team); }else{ CmdSetTeam(team); setMyTeam(team); } } void setMyTeam(Team team){ myTeam = team; if (GameManager.instance != null) GameManager.instance.OnMatchPlayerTeamAssigned(team); } [Command] void CmdSetTeam(Team team){ setMyTeam(team); Logger.Log($"Client {netId} set team to {team}"); if(team == Team.Red){ RedPlayer = this; }else{ BluePlayer = this; } } public static NetPlayer localPlayer; public static NetPlayer RedPlayer; public static NetPlayer BluePlayer; public static Vector2 curPosition; public Vector2 startPosition; public float curPuckPullForce; // Single drag at a time; extra fingers are ignored while isDragging. bool isDragging; Vector2 lastDragScreenPosition; bool serverDragActive; #region EMOTES public void SendTextEmote(string txtName){ if(isServer){ RpcSendTextEmote(txtName); ShowTextEmote(txtName); }else{ CmdSendTextEmote(txtName); } } [Command] void CmdSendTextEmote(string txtName){ RpcSendTextEmote(txtName); ShowTextEmote(txtName); Logger.Log($"Client {netId} sent text emote {txtName}"); } [ClientRpc] void RpcSendTextEmote(string txtName){ ShowTextEmote(txtName); } void ShowTextEmote(string txtName){ GameCanvas.instance.ShowTextEmote(txtName, myTeam); } public void SendEmojiEmote(int id){ if(isServer){ RpcSendEmojiEmote(id); ShowEmojiEmote(id); }else{ CmdSendEmojiEmote(id); } } [Command] void CmdSendEmojiEmote(int id){ RpcSendEmojiEmote(id); ShowEmojiEmote(id); Logger.Log($"Client {netId} sent emoji emote {id}"); } [ClientRpc] void RpcSendEmojiEmote(int id){ ShowEmojiEmote(id); } void ShowEmojiEmote(int id){ GameCanvas.instance.ShowEmojiEmote(id, myTeam); } #endregion void Start(){ if(isLocalPlayer){ localPlayer = this; SetupInputPanel(); } } void OnDestroy(){ if(localPlayer == this){ localPlayer = null; } } void SetupInputPanel(){ EventTrigger.Entry entry = new EventTrigger.Entry(); entry.eventID = EventTriggerType.PointerDown; entry.callback.AddListener(OnPointerDown); GameCanvas.instance.gameInputPanel.triggers.Add(entry); entry = new EventTrigger.Entry(); entry.eventID = EventTriggerType.PointerUp; entry.callback.AddListener(OnPointerUp); GameCanvas.instance.gameInputPanel.triggers.Add(entry); entry = new EventTrigger.Entry(); entry.eventID = EventTriggerType.Drag; entry.callback.AddListener(OnDrag); GameCanvas.instance.gameInputPanel.triggers.Add(entry); } bool TryGetPointerEvent(BaseEventData eventData, out PointerEventData pointerEventData) { pointerEventData = eventData as PointerEventData; return pointerEventData != null; } static int CountPressedTouches() { #if ENABLE_INPUT_SYSTEM if (Touchscreen.current != null) { int count = 0; var touches = Touchscreen.current.touches; for (int i = 0; i < touches.Count; i++) { if (touches[i].press.isPressed) count++; } return count; } #endif return Input.touchCount; } void UpdateDragScreenPosition(Vector2 screenPosition) { lastDragScreenPosition = screenPosition; curPosition = screenPosition; if (GameManager.SelectedPuck != null) curPuckPullForce = GameManager.SelectedPuck.lineEnd.magnitude; } void Update() { if (!isLocalPlayer || !isDragging) return; if (!TryReadPointerHeld(out Vector2 screenPosition, out bool isPressed)) { curPosition = lastDragScreenPosition; return; } UpdateDragScreenPosition(screenPosition); if (!isPressed && CountPressedTouches() == 0) CompleteActivePointerDrag(); } bool TryReadPointerHeld(out Vector2 screenPosition, out bool isPressed) { screenPosition = lastDragScreenPosition; isPressed = false; #if ENABLE_INPUT_SYSTEM if (Touchscreen.current != null) { var primary = Touchscreen.current.primaryTouch; if (primary.press.isPressed) { screenPosition = primary.position.ReadValue(); isPressed = true; return true; } if (primary.press.wasReleasedThisFrame) { screenPosition = primary.position.ReadValue(); return true; } var touches = Touchscreen.current.touches; for (int i = 0; i < touches.Count; i++) { var touch = touches[i]; if (!touch.press.isPressed) continue; screenPosition = touch.position.ReadValue(); isPressed = true; return true; } } if (Mouse.current != null) { if (Mouse.current.leftButton.isPressed) { screenPosition = Mouse.current.position.ReadValue(); isPressed = true; return true; } if (Mouse.current.leftButton.wasReleasedThisFrame) { screenPosition = Mouse.current.position.ReadValue(); return true; } } #endif if (Input.touchCount > 0) { UnityEngine.Touch touch = Input.GetTouch(0); screenPosition = touch.position; isPressed = touch.phase != LegacyTouchPhase.Ended && touch.phase != LegacyTouchPhase.Canceled; return true; } if (Input.GetMouseButton(0)) { screenPosition = Input.mousePosition; isPressed = true; return true; } if (Input.GetMouseButtonUp(0)) { screenPosition = Input.mousePosition; return true; } return false; } void CompleteActivePointerDrag() { if (!isDragging) return; if (CountPressedTouches() > 0) return; isDragging = false; if (GameManager.SelectedPuck == null) return; if (GameManager.instance == null) return; if (GameManager.instance.SelectedTeam != myTeam) return; Vector2 direction = GameManager.SelectedPuck.lineEnd; CmdOnPointerUp(direction); if (CameraEffects.instance != null) CameraEffects.instance.ReleaseStretchFactor(); } void OnPointerDown(BaseEventData eventData){ if(GameManager.instance == null){return;} if(GameManager.instance.SelectedTeam != myTeam){return;} if(GameManager.instance.m_isMoving){return;} if(isDragging){return;} if(CountPressedTouches() > 1){return;} if(!TryGetPointerEvent(eventData, out PointerEventData pointerEventData)){return;} Vector2 position = pointerEventData.position; Vector3 worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(position.x, position.y, Camera.main.nearClipPlane)); Puck closestPuck = GameManager.instance.GetClosestPuck(worldPosition); if (closestPuck == null) return; isDragging = true; UpdateDragScreenPosition(position); GameManager.SelectedPuck = closestPuck; CmdOnPointerDown(worldPosition); } [Command] void CmdOnPointerDown(Vector2 position){ if (GameManager.instance == null) return; if (serverDragActive) return; if (GameManager.instance.SelectedTeam != myTeam) return; Puck closestPuck = GameManager.instance.GetClosestPuck(position); if (closestPuck == null || closestPuck.gameObject == null) return; serverDragActive = true; GameManager.SelectedPuck = closestPuck; RpcOnPointerDown(closestPuck.gameObject); } [ClientRpc] void RpcOnPointerDown(GameObject puckGo){ if(puckGo == null){return;} if(!isLocalPlayer){return;} Puck puck = puckGo.GetComponent(); if(puck!=GameManager.SelectedPuck){ Debug.LogError("Selected puck changed on client, This cant happen. Resetting to servers choice", gameObject); } GameManager.SelectedPuck = puck; } void OnDrag(BaseEventData eventData){ if(!isDragging){return;} if(!TryGetPointerEvent(eventData, out PointerEventData pointerEventData)){return;} UpdateDragScreenPosition(pointerEventData.position); } void OnPointerUp(BaseEventData eventData){ if(!isDragging){return;} if(TryGetPointerEvent(eventData, out PointerEventData pointerEventData)) UpdateDragScreenPosition(pointerEventData.position); if (CountPressedTouches() > 0) return; CompleteActivePointerDrag(); } [Command] void CmdOnPointerUp(Vector2 direction){ serverDragActive = false; if (GameManager.instance == null) return; if (GameManager.instance.SelectedTeam != myTeam) return; Debug.Log("Pointer up"); GameManager.instance.OnPointerUp(direction); RpcOnPointerUp(); } [ClientRpc] void RpcOnPointerUp(){ } /// /// Request a rematch with the opponent. /// public void RequestRematch(){ if(isServer){ GameOverCanvas.instance.OnRematchRequested(); RpcRequestRematch(); }else{ CmdRequestRematch(); } } [Command] void CmdRequestRematch(){ Logger.Log("Rematch requested"); if(isServerOnly){ //server }else{ GameOverCanvas.instance.OnRematchRequested(); } RpcRequestRematch(); } [ClientRpc] void RpcRequestRematch(){ GameOverCanvas.instance.OnRematchRequested(); } public void AcceptRematch( int betRcCoins){ if(isServer){ OnRematchAcceptedServer(betRcCoins); }else{ CmdAcceptRematch(betRcCoins); } } [Command] void CmdAcceptRematch(int betRcCoins){ OnRematchAcceptedServer(betRcCoins); } void OnRematchAcceptedServer(int betRcCoins ){ if(!isServer){ return; } if(betRcCoins <= 0){ OnRematchCancelledServer(); return; } GameManager.DedicatedRematchResult resp = GameManager.RequestDedicatedRematch(RedPlayer.userId, BluePlayer.userId, betRcCoins); if(resp.Success && resp.Response != null){ string matchmadeResponseString = JsonUtility.ToJson(resp.Response); RpcRematchConfirmed(matchmadeResponseString); Logger.Log("Rematch was confirmed, closing in 5 secs. new room :"); Logger.Log(matchmadeResponseString); StartCoroutine(CoroutineOnRematchConfirmedServer()); } } IEnumerator CoroutineOnRematchConfirmedServer(){ yield return new WaitForSeconds(5f); Logger.Log("Exiting for rematch."); GameManager.ReportDedicatedMatchRoomClosed(); Application.Quit(); } [ClientRpc] void RpcRematchConfirmed(string matchmadeResponseString){ if (string.IsNullOrEmpty(matchmadeResponseString)) return; MatchmadeResponse env = JsonUtility.FromJson(matchmadeResponseString); if (env == null || !env.ok) return; Team? teamHint = LoginManager.MatchYourTeam; if (!teamHint.HasValue) teamHint = GameManager.MyTeam; int userId = localPlayer != null ? localPlayer.userId : (LoginManager.CurrentUser != null ? LoginManager.CurrentUser.id : 0); MatchmadeTeamPayload branch = MatchmadeResponse.SelectTeamPayload(env, userId, teamHint); if (branch == null || !MatchmadeResponse.TryResolveMyAndOpponent(env, branch, userId, out MatchmadePlayer myPlayer, out MatchmadePlayer opponentPlayer)) { Debug.LogWarning("RpcRematchConfirmed: could not resolve roster for rematch UI"); return; } string yt = (branch.your_team ?? "").Trim().ToLowerInvariant(); Team myTeam = yt == "blue" ? Team.Blue : Team.Red; if (myTeam == Team.Red) { GameManager.RedPlayer = myPlayer; GameManager.BluePlayer = opponentPlayer; } else { GameManager.BluePlayer = myPlayer; GameManager.RedPlayer = opponentPlayer; } GameManager.MyTeam = myTeam; int rcPrizeCoins = env.rc_prize > 0 ? env.rc_prize : branch.rc_prize; GameManager.MatchRcPrizeCoins = rcPrizeCoins; if (LevelLoadManager.instance != null) LevelLoadManager.instance.SetupMatchMade(myTeam, myPlayer, opponentPlayer, CoinHelper.FormatString(rcPrizeCoins) + " RC"); GameManager.ConfigureDedicatedMatchReporting(branch.match_id); Cupid.RoomPort = branch.Port; LoginManager.SetMatchYourTeam(branch.your_team); GameManager.instance.Leave("Game"); } void OnRematchCancelledServer(){ if(!isServer){ return; } RpcCancelRematch(); if(!isServerOnly){ CancelRematch(); } } [ClientRpc] void RpcCancelRematch(){ CancelRematch(); } void CancelRematch(){ GameOverCanvas.instance.OnRematchCancelled(); } }