using System; using UnityEngine; using UnityEngine.InputSystem; using NeonTea.Quakeball.Interface; using NeonTea.Quakeball.Networking.Packets; namespace NeonTea.Quakeball.Players { /// A controller class for a local player. Handles input and updates the relevant components. [RequireComponent(typeof(Player))] public class LocalPlayer : MonoBehaviour { public int DisableInput; public float SyncInterval = 1; public float MovementUpdateInterval = 1f; public Player Player { private set; get; } public InputAction LookAction { private set; get; } private InputAction MoveAction; private InputAction CrouchAction; private InputAction JumpAction; private InputAction ShootAction; private InputAction SwitchUpAction; private InputAction[] WeaponSwitchActions = new InputAction[9]; private float PreviousPlayerUpdate = -1; private float PreviousPlayerFullSync = -1; private bool WantsToJump = false; private void Awake() { Player = GetComponent(); CrouchAction = new InputAction("crouch", binding: "/buttonEast"); CrouchAction.AddBinding("/leftShift"); JumpAction = new InputAction("crouch", binding: "/buttonSouth"); JumpAction.AddBinding("/space"); JumpAction.performed += _ => { WantsToJump = true; }; LookAction = new InputAction("look", binding: "/leftStick"); LookAction.AddBinding("/delta"); MoveAction = new InputAction("move", binding: "/rightStick"); MoveAction.AddCompositeBinding("Dpad") .With("Up", "/w") .With("Down", "/s") .With("Left", "/a") .With("Right", "/d"); ShootAction = new InputAction("Shoot", binding: "/leftButton"); ShootAction.performed += _ => { if (Networking.Net.Singleton.Instance != null) { ShootData shootData = new ShootData(Player.Pitch, Player.Yaw, Player.CreateSyncPacket()); Networking.Net.Singleton.Instance.LocalPlayerAction(PlayerAction.Shoot, shootData); } Player.Shoot(); }; Action CreateLambda(int number) { return (context) => { Player.SwitchItem(number); Player.CurrentItem.Animator.enabled = true; }; } for (int i = 0; i < 9; i++) { WeaponSwitchActions[i] = new InputAction($"Switch to weapon {i + 1}", binding: $"/{i + 1}"); WeaponSwitchActions[i].performed += CreateLambda(i); } Terminal.Singleton.RegisterCommand("tp", args => { if (args.Length != 3) { return false; } transform.position = new Vector3(float.Parse(args[0]), float.Parse(args[1]), float.Parse(args[2])); return true; }, "tp x y z - Teleports the local player to the specified coordinates."); } private void Update() { if (DisableInput > 0 || !Application.isFocused) { CrouchAction.Disable(); JumpAction.Disable(); LookAction.Disable(); MoveAction.Disable(); ShootAction.Disable(); foreach (InputAction action in WeaponSwitchActions) { action.Disable(); } Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } else { CrouchAction.Enable(); JumpAction.Enable(); LookAction.Enable(); MoveAction.Enable(); ShootAction.Enable(); foreach (InputAction action in WeaponSwitchActions) { action.Enable(); } Cursor.visible = false; Cursor.lockState = CursorLockMode.Locked; } OptionsData Opts = Options.Get(); Vector2 LookInput = LookAction.ReadValue() * Opts.LookSensitivity; Player.Pitch = Mathf.Clamp(Player.Pitch - LookInput.y * (Opts.InvertVerticalLook ? -1 : 1), -90, 90); Player.Yaw += LookInput.x; if (Time.time - PreviousPlayerUpdate >= MovementUpdateInterval) { PreviousPlayerUpdate = Time.time; if (Player.IsDead) { return; } Vector2 MovementInput = MoveAction.ReadValue(); Vector3 Move = new Vector3(MovementInput.x, 0, MovementInput.y); Move = Quaternion.Euler(0, Player.Yaw, 0) * Move; Player.MoveDirection = Move; Player.CurrentMoveStyle = CrouchAction.ReadValue() > 0 ? (byte)1 : (byte)0; if (Networking.Net.Singleton.Instance != null) { Networking.Net.Singleton.Instance.UpdateLocalPlayer(); } if (WantsToJump) { bool Jumped = Player.Jump(); if (Jumped && Networking.Net.Singleton.Instance != null) { Networking.Net.Singleton.Instance.LocalPlayerAction(PlayerAction.Jump); } } WantsToJump = false; } if (Time.time - PreviousPlayerFullSync >= SyncInterval) { PreviousPlayerFullSync = Time.time; if (Networking.Net.Singleton.Instance != null) { Networking.Net.Singleton.Instance.SendPlayerSync(); } } } } }