using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines; using Common; using DamageNumbersPro; using DragonLi.Core; using Mirror; using UnityEngine; using UnityEngine.PlayerLoop; using XPlugin.Data.JsonLiteDB; using static XPlugin.Data.JsonLiteDB.JsonLiteDB; using LitJson; using Pathfinding; using DarkTonic.MasterAudio; using NaughtyAttributes; using Unity.Mathematics; using UnityEngine.UIElements; using Random = UnityEngine.Random; /// /// 游戏状态 /// public enum GameState { None = 0, Playing = 1, /// /// 胜利 /// Victory = 2, /// /// 失败 /// Failur = 3, Settle, Waiting= 5, } public class GameManager : NetworkBehaviour { public static GameManager Ins { get; private set; } #region 预制体 public GameObject redDoorPre; public GameObject blueDoorPre; public GameObject AirdropPlanePre;//空投飞机 public GameObject[] airdropItems;//空头道具 public GameObject startGameItemPre; public GameObject damageNumberPre; public GameObject redDamageNumberPre; // 怪物ui预制体 public GameObject EnemyUIPre; #endregion #region 实例化后物体 public GameObject redDoor; public GameObject blueDoor; #endregion // json数据库 private JsonLiteDB DB; // 怪物信息集合 public Dictionary> EnemyInfos = new Dictionary>(); // 枪械信息集合 public Dictionary> GunInfos = new Dictionary>(); /// /// 所有敌人UI /// public Dictionary EnemyUIList = new Dictionary(); public Dictionary SettleInfos = new Dictionary(); public List allPlayers = new List(); // 游玩结束时间 [NonSerialized] [SyncVar] public long vistEnd = 0; // 总游玩时长 private int vistAllTime = (int)(60 * 10f); [SyncVar] public string settleData = ""; [SyncVar] public GameState gameState = GameState.None; [NonSerialized] [SyncVar] public int BlueScore = 0; [NonSerialized] [SyncVar] public int RedScore = 0; [NonSerialized] [SyncVar] public int RedRoundScore = 0; [NonSerialized] [SyncVar] public int BlueRoundScore = 0; void Awake() { Ins = this; } void Start() { if (isClient) { AuthorPanel.Show(); } } /// /// 创建门 /// [Server] public void CreateDoor(Transform redPos, Transform bluePos,Transform startGamePos) { SetGameState(GameState.Waiting); if(!isServer) return; //创建红色门 redDoor = Instantiate(redDoorPre,redPos.position,Quaternion.identity); NetworkServer.Spawn(redDoor); //创建蓝色门 blueDoor = Instantiate(blueDoorPre,bluePos.position,Quaternion.identity); NetworkServer.Spawn(blueDoor); //创建开始球 GameObject gameStartObj = Instantiate(startGameItemPre,startGamePos.position,Quaternion.identity); NetworkServer.Spawn(gameStartObj); //测试枪械 //GameLocal.Ins.self.GivePistol(); } [Server] // public void CreateDamageNumber(float damage ,Vector3 pos,bool isCritical) // { // if (damageNumberPre == null || redDamageNumberPre == null) // { // Debug.LogWarning("伤害字体预制体未设置!"); // return; // } // // GameObject prefab = isCritical ? redDamageNumberPre : damageNumberPre; // GameObject obj = Instantiate(prefab, pos, Quaternion.identity); // // // DamageNumbersPro 的核心组件 // var dmg = obj.GetComponent(); // if (dmg != null) // { // dmg.worldPos = pos; // dmg.damageValue = isCritical? damage*2 : damage; // dmg.OnStartClient(); // } // // // 网络生成(让客户端也能看到) // NetworkServer.Spawn(obj); // CoroutineTaskManager.Instance.WaitSecondTodo(() => // { // NetworkServer.Destroy(obj); // }, 10); // // } [ClientRpc] public void RpcShowDamageNumber(float damage, Vector3 pos, bool isCritical) { GameObject prefab = isCritical ? redDamageNumberPre : damageNumberPre; if (prefab == null) return; GameObject obj = Instantiate(prefab, pos, Quaternion.identity); var dmg = obj.GetComponent(); if (dmg != null) { dmg.worldPos = pos; dmg.damageValue = isCritical? damage*2 : damage; dmg.OnStartClient(); } Destroy(obj, 10f); } [Server] public void GameStart() { AutoAssignTeams(); gameState = GameState.Playing; vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime; _airdropTime = 25; _curAirdropTime = _airdropTime; RpcShowHUD(); ChangeBgmRpc(1); StartAirDrop(); //AstarPath.active.Scan(); NetworkServer.Destroy(redDoor); NetworkServer.Destroy(blueDoor); // 延迟1s后给所有人发放武器 CoroutineTaskManager.Instance.WaitSecondTodo(() => { foreach (var item in NetworkServer.connections.Values) { Player player = item.identity.GetComponent(); if (player != null) { player.HideInvincible(); } } RpcShowSettle(); }, 1f); CoroutineTaskManager.Instance.WaitSecondTodo(() => { GameOver(); }, vistAllTime); } [Server] public void RegisterPlayer(Player p) { if (!allPlayers.Contains(p)) allPlayers.Add(p); } // ★ 玩家离开游戏时调用(在Player.OnStopServer里调用) [Server] public void UnRegisterPlayer(Player p) { if (allPlayers.Contains(p)) allPlayers.Remove(p); } // ★ 游戏开始时调用 → 自动分配队伍 [Server] public void AutoAssignTeams() { int redCount = 0; int blueCount = 0; // 计算已分配队伍的人数 foreach (var p in allPlayers) { if (p.teamType == TeamType.Red) redCount++; else if (p.teamType == TeamType.Blue) blueCount++; } // 遍历玩家 → 给没选队伍的自动分配 foreach (var p in allPlayers) { if (p.teamType != TeamType.None) continue; // 队伍数量对比 if (redCount < blueCount) { p.teamType = TeamType.Red; redCount++; } else if (blueCount < redCount) { p.teamType = TeamType.Blue; blueCount++; } else { // 一样多 → 随机 if (Random.value > 0.5f) { p.teamType = TeamType.Red; redCount++; } else { p.teamType = TeamType.Blue; blueCount++; } } GivePistol(p.index); } } [ClientRpc] public void RpcShowSettle() { GameLocal.Ins.Settle.SetActive(true); } [ClientRpc] public void GivePistol(int index) { Debug.Log("创建武器中..."); foreach (var item in NetworkServer.connections.Values) { Player player = item.identity.GetComponent(); if (player != null&&player.index == index) { player.GivePistol(); player.GiveArmor(); } } } [Server] public void SetGameState(GameState state) { gameState = state; } [Server] public void GameOver() { gameState = GameState.Settle; bool isBlue = GameLocal.Ins.self.teamType == TeamType.Blue; bool isWin; if (isBlue) { isWin = BlueScore > RedScore; } RpcShowWin(isBlue); // if (blueScore >= redScore) // { // RpcShowWin(true); // } // else // { // RpcShowWin(false); // } } [ClientRpc] public void RpcShowWin(bool isBlue) { GameLocal.Ins.Settle.SetActive(false); if (isBlue) { GameLocal.Ins.BlueWin.SetActive(true); } else { GameLocal.Ins.RedWin.SetActive(true); } } [ClientRpc] public void RpcShow() { SettlePanel.Show(); } [ClientRpc] public void ChangeBgmRpc(int i) { GameLocal.Ins.BGMState.StateChange(i); } [Server] public void CreateAirdropPlane(Vector3 startPos, Vector3 endPos) { GameObject airdropPlane = Instantiate(AirdropPlanePre,startPos,quaternion.identity); NetworkServer.Spawn(airdropPlane); AirdropPlane airdropPlaneScript = airdropPlane.GetComponent(); airdropPlaneScript.OnSpawn(endPos); } [Server] public void CreateAirDropItem(int id ,Vector3 startPos) { GameObject airdropItem = Instantiate(airdropItems[id],startPos,quaternion.identity); NetworkServer.Spawn(airdropItem); } /// /// 痛击场上所有敌方单位 /// [Command(requiresAuthority = false)] public void DamageAllEnemy() { } /// /// 更新配置表 /// public void UpdateConf() { string text = Resources.Load("Data").text; if (text != null) { ParseGameJson(text); } } public void ParseGameJson(string text) { DB = new JsonLiteDB(); DB.Load(text); TableReader infoReader = DB["GunsInfo"].GetReader(); while (infoReader.Read()) { GunInfo info = new GunInfo(infoReader); GunInfos.TryGetValue((GunType)info.Type, out Dictionary infoList); if (infoList == null) { Dictionary list = new Dictionary(); list.Add(info.Lvl, info); GunInfos.Add((GunType)info.Type, list); } else { infoList.Add(info.Lvl, info); } } Debug.Log("游戏数值更新 -> complete"); } [Server] public void CreateEnemyUI(Enemy enemy) { GameObject enemyUI = Instantiate(EnemyUIPre); NetworkServer.Spawn(enemyUI); PlayerUI enemyUIScript = enemyUI.GetComponent(); enemyUIScript.Init(enemy); EnemyUIList.Add(enemy.id, enemyUIScript); } [Server] public void DeleteEnemyUI(int id) { GameObject enemyUI = EnemyUIList[id].gameObject; EnemyUIList.Remove(id); NetworkServer.Destroy(enemyUI); } [ClientRpc] public void RpcShowHUD() { HUDPanel.Show(); } [Server] public void AddData(int playerIndex) { SettleInfos.Add(playerIndex.ToString(), new SettleInfo()); } #region 工具 public string GetLessTimeStr() { string res = ""; if (gameState == GameState.Playing) { res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds)); } return res; } public int GetLessTimeSeconds() { if (isServer) { return (int)(vistEnd - NetworkTime.time); } else { return (int)(vistEnd - NetworkClient.connection.remoteTimeStamp); } } // 时分秒 public string FormatTime(int totalSeconds) { //确保时间不为负 totalSeconds = Mathf.Max(0, totalSeconds); int hours = totalSeconds / 3600; // string hh = hours < 10 ? "0" + hours : hours.ToString(); int minutes = (totalSeconds - hours * 3600) / 60; string mm = minutes < 10f ? "0" + minutes : minutes.ToString(); int seconds = totalSeconds - hours * 3600 - minutes * 60; string ss = seconds < 10 ? "0" + seconds : seconds.ToString(); return string.Format("{0}:{1}", mm, ss); } #endregion [ClientRpc] public void PlaySound2DRPC(string sound) { MasterAudio.PlaySound(sound); } [SyncVar] private int syncRemainingTime; private float _airdropTime;//空投时间 private float _curAirdropTime;//当前空头时间 private bool _isStartAirdrop;//是否开始倒计时空投 public void StartAirDrop() { _isStartAirdrop = true; } public void StopAirDrop() { _isStartAirdrop = false; } void Update() { if (isServer&& gameState==GameState.Playing&&_isStartAirdrop) { //服务器计算剩余时间并同步 //syncRemainingTime = GetLessTimeSeconds(); _curAirdropTime+=Time.deltaTime; if (_curAirdropTime >= _airdropTime) { int airdropPosId = Random.Range(0, 4); int endAirdropPosId =0; if (airdropPosId == 0) endAirdropPosId = 1; if (airdropPosId == 1) endAirdropPosId = 0; if (airdropPosId == 2) endAirdropPosId = 3; if (airdropPosId == 3) endAirdropPosId = 2; CreateAirdropPlane(GameLocal.Ins.startPlanePos[airdropPosId].position,GameLocal.Ins.startPlanePos[endAirdropPosId].position); _curAirdropTime = 0; StopAirDrop(); } } } public void StartRound() { gameState = GameState.Playing; foreach (var item in allPlayers) { item.HideInvincible(); } } [Server] public void StopRound() { gameState = GameState.Waiting; foreach (var item in allPlayers) { item.ClearGun(); } if (BlueRoundScore > RedRoundScore) { BlueScore += 1; } if (BlueRoundScore < RedRoundScore) { RedScore += 1; } if (BlueRoundScore == RedRoundScore) { RedScore += 1; BlueScore += 1; } BlueRoundScore = 0; RedRoundScore = 0; } public Player GetPlayerByIndex(int index) { return allPlayers.FirstOrDefault(p => p.index == index); } #region 分数系统 /// /// 红色方加分 /// /// public void AddRedScore(int playerId,int score) { RedRoundScore+=score; } /// /// 蓝色方加分 /// /// public void AddBlueScore(int playerId,int score) { BlueRoundScore+=score; } #endregion }