using RiptideNetworking; using System.Collections; using System.Collections.Generic; using UnityEngine; public enum Team : byte { none, green, orange } [RequireComponent(typeof(PlayerMovement))] public class Player : MonoBehaviour { public static Dictionary list = new Dictionary(); public ushort Id { get; private set; } public string Username { get; private set; } public bool IsAlive => health > 0f; public PlayerMovement Movement => movement; [SerializeField] private float respawnSeconds; [SerializeField] private float health; [SerializeField] private float maxHealth; [SerializeField] private PlayerMovement movement; [SerializeField] private WeaponManager weaponManager; private Team team; private void OnValidate() { if (movement == null) movement = GetComponent(); if (weaponManager == null) weaponManager = GetComponent(); } private void Start() { DontDestroyOnLoad(gameObject); } private void OnDestroy() { list.Remove(Id); } public void TakeDamage(float amount) { health -= amount; if (health <= 0f) { health = 0f; Die(); } else SendHealthChanged(); } private void Die() { movement.Enabled(false); StartCoroutine(DelayedRespawn()); SendDied(); } private IEnumerator DelayedRespawn() { yield return new WaitForSeconds(respawnSeconds); InstantRespawn(); } public void InstantRespawn() { TeleportToTeamSpawnpoint(); movement.Enabled(true); health = maxHealth; weaponManager.ResetWeapons(); SendRespawned(); } private void TeleportToTeamSpawnpoint() { if (team == Team.green) movement.Teleport(GameLogic.Singleton.GreenSpawn.position); else if (team == Team.orange) movement.Teleport(GameLogic.Singleton.OrangeSpawn.position); } public static void Spawn(ushort id, string username) { foreach (Player otherPlayer in list.Values) otherPlayer.SendSpawned(id); Player player = Instantiate(GameLogic.Singleton.PlayerPrefab, new Vector3(0f, 1f, 0f), Quaternion.identity).GetComponent(); player.name = $"Player {id} ({(string.IsNullOrEmpty(username) ? "Guest" : username)})"; player.Id = id; player.Username = string.IsNullOrEmpty(username) ? $"Guest {id}" : username; player.team = id % 2 == 0 ? Team.orange : Team.green; // NOTE: if players leave this can lead to uneven teams (eg: player 2 leaves, rejoins as player 3, now the only 2 players in the game are on the same team because both their IDs are odd numbers) if (GameLogic.Singleton.IsGameInProgress) player.TeleportToTeamSpawnpoint(); // Ensure players joining into an ongoing game are spawned at their team's spawnpoint player.SendSpawned(); list.Add(id, player); } #region Messages private void SendSpawned() { NetworkManager.Singleton.Server.SendToAll(AddSpawnData(Message.Create(MessageSendMode.reliable, ServerToClientId.playerSpawned))); } private void SendSpawned(ushort toClientId) { NetworkManager.Singleton.Server.Send(AddSpawnData(Message.Create(MessageSendMode.reliable, ServerToClientId.playerSpawned)), toClientId); } private Message AddSpawnData(Message message) { message.AddUShort(Id); message.AddString(Username); message.AddByte((byte)team); message.AddVector3(transform.position); return message; } private void SendHealthChanged() { Message message = Message.Create(MessageSendMode.reliable, ServerToClientId.playerHealthChanged); message.AddFloat(health); NetworkManager.Singleton.Server.Send(message, Id); } private void SendDied() { Message message = Message.Create(MessageSendMode.reliable, ServerToClientId.playerDied); message.AddUShort(Id); message.AddVector3(transform.position); NetworkManager.Singleton.Server.SendToAll(message); } private void SendRespawned() { Message message = Message.Create(MessageSendMode.reliable, ServerToClientId.playerRespawned); message.AddUShort(Id); message.AddVector3(transform.position); NetworkManager.Singleton.Server.SendToAll(message); } [MessageHandler((ushort)ClientToServerId.name)] private static void Name(ushort fromClientId, Message message) { Spawn(fromClientId, message.GetString()); } [MessageHandler((ushort)ClientToServerId.input)] private static void Input(ushort fromClientId, Message message) { if (list.TryGetValue(fromClientId, out Player player)) player.Movement.SetInput(message.GetBools(6), message.GetVector3()); } [MessageHandler((ushort)ClientToServerId.switchActiveWeapon)] private static void SwitchActiveWeapon(ushort fromClientId, Message message) { if (list.TryGetValue(fromClientId, out Player player)) player.weaponManager.SetActiveWeapon((WeaponType)message.GetByte()); } [MessageHandler((ushort)ClientToServerId.primaryUse)] private static void PrimaryUse(ushort fromClientId, Message message) { if (list.TryGetValue(fromClientId, out Player player)) player.weaponManager.PrimaryUsePressed(); } [MessageHandler((ushort)ClientToServerId.reload)] private static void Reload(ushort fromClientId, Message message) { if (list.TryGetValue(fromClientId, out Player player)) player.weaponManager.Reload(); } #endregion }