You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
7.9 KiB

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.Networking;
  6. using Networking.Server;
  7. using Networking;
  8. using UnityEngine.SceneManagement;
  9. public class GameManager : MonoBehaviour
  10. {
  11. #region Inspector Field
  12. [Header("Settings")]
  13. [SerializeField]
  14. private float AnimationTime;
  15. [SerializeField]
  16. private GameModeReference CurrentGameMode;
  17. [Header("References")]
  18. [SerializeField]
  19. [Tooltip("Prefab of character for players to play")]
  20. private Character characterPrefab;
  21. [SerializeField]
  22. private ServerObject server;
  23. [SerializeField]
  24. private ClientList ClientList;
  25. #endregion Inspector Field
  26. #region Private Variables
  27. private Dictionary<int, PlayerData> playerData;
  28. #endregion Private Variables
  29. #region Read Only
  30. /// <summary>
  31. /// Easy access to IEnumerable in playerData so we can Enumerate through it
  32. /// </summary>
  33. private IEnumerable<PlayerData> playerDataAsArray { get { return playerData.Values; } }
  34. /// <summary>
  35. /// Easy access to GameMode value in CurrentGameMode reference
  36. /// </summary>
  37. private GameMode gameMode {get { return CurrentGameMode.Value; } }
  38. #endregion Read Only
  39. public GameObject levelInfo;
  40. public blockSpawn bspawn;
  41. #region Unity Functions
  42. public void Awake()
  43. {
  44. RegisterHandlers();
  45. SpawnCharacters();
  46. ClientList.ForEach(p => p.ChangeScene("ClientScene"));
  47. }
  48. private void Start()
  49. {
  50. StartCoroutine(displayforSeconds(levelInfo, 5.0f));
  51. gameMode.GameStart(playerDataAsArray.ToArray());
  52. StartRound();
  53. }
  54. private void Update()
  55. {
  56. //This is required so that the server can continue to recieve client messages
  57. //(it is a unity thing)
  58. server.ServerUpdate();
  59. }
  60. private void OnDisable()
  61. {
  62. //Let server know to not send messages this way
  63. UnRegisterHandlers();
  64. }
  65. #endregion Unity Functions
  66. IEnumerator displayforSeconds(GameObject display, float time)
  67. {
  68. display.SetActive (true);
  69. yield return new WaitForSeconds(time);
  70. display.SetActive (false);
  71. }
  72. private void DoRoundRoutine()
  73. {
  74. Debug.Log("Starting Round");
  75. StartCoroutine(RoundRoutine());
  76. }
  77. private void StartRound()
  78. {
  79. gameMode.RoundStart(playerDataAsArray.ToArray());
  80. LogicProtocols.FloatMsg RoundTime = new LogicProtocols.FloatMsg( gameMode.GetRoundTime());
  81. bspawn.Spawn();
  82. playerDataAsArray.ForEach(p => p.client.conn.Send(LogicProtocols.SendRoundTime, RoundTime));
  83. }
  84. private IEnumerator RoundRoutine()
  85. {
  86. playerDataAsArray.ForEach(p => p.recievedList = false);
  87. //Debug.Log("Doing Round Routine");
  88. while (playerDataAsArray.Any(p => !p.blockReader.Finished))
  89. {
  90. //Debug.Log("One Move");
  91. foreach (PlayerData player in playerDataAsArray)
  92. {
  93. Debug.Log(player.client.Name);
  94. StartCoroutine(RunOnce(player));
  95. yield return new WaitUntil(() => player.waiting);
  96. }
  97. //wait until all players have finished
  98. //yield return new WaitUntil(() => playerArray.All(p => p.waiting));
  99. gameMode.FinishedMove(playerDataAsArray.ToArray());
  100. playerDataAsArray.ForEach(p => p.client.SendScore());
  101. }
  102. if (gameMode.isGameOver(playerDataAsArray.ToArray()))
  103. {
  104. Debug.Log("Game Over");
  105. SceneManager.LoadScene("ScoreBoards");
  106. }
  107. gameMode.RoundEnd(playerDataAsArray.ToArray());
  108. foreach (PlayerData player in playerDataAsArray)
  109. {
  110. player.blockReader.Reset();
  111. player.waiting = false;
  112. player.client.SendInventory();
  113. player.client.ChangeScene("ClientScene");
  114. }
  115. //Debug.Log("Finished Moving");
  116. StartRound();
  117. }
  118. private void SpawnCharacters()
  119. {
  120. playerData = new Dictionary<int, PlayerData>();
  121. Block[] SpawnBlocks = FindObjectsOfType<Block>().Where(p => p.isSpawnable).ToArray();
  122. int blockIndex = 0;
  123. foreach (Block block in SpawnBlocks)
  124. {
  125. Debug.Log("Block #" + blockIndex++ + " (" + block.transform.position.x + ", " + block.transform.position.y + ", " + block.transform.position.z + ")");
  126. }
  127. //int spawnIndex = 0;
  128. //If we have an odd number of players, then we start at spawn point 0 (in the middle)
  129. //If we have an even number, then we skip it
  130. int spawnIndex = ((ClientList.Count() + 1) % 2);
  131. //int spawnIndex = 0;
  132. foreach (ClientData client in ClientList)
  133. {
  134. Debug.Log("spawnIndex = " + spawnIndex);
  135. Character newChar = Instantiate(characterPrefab);
  136. //Block startingBlock = SpawnBlocks[(spawnIndex++ % ClientList.ConnectedClients.Count)];
  137. Block startingBlock = SpawnBlocks[spawnIndex++];
  138. newChar.Initialise(startingBlock, client.Inventory, client.characterAnimal);
  139. newChar.transform.forward = startingBlock.SpawnDirection.ToVector();
  140. playerData.Add(client.ID, new PlayerData(newChar,client));
  141. newChar.ClientLink = client;
  142. client.playerCharacter = newChar;
  143. }
  144. }
  145. #region Networking Functions
  146. /// <summary>
  147. /// Registers functions which should deal with incoming messages from clients
  148. /// </summary>
  149. private void RegisterHandlers()
  150. {
  151. server.server.RegisterHandler(LogicProtocols.SendLogicList, RecieveLogicList);
  152. }
  153. /// <summary>
  154. /// Clears any functions from server register which the manager would deal with
  155. /// </summary>
  156. private void UnRegisterHandlers()
  157. {
  158. server.server.UnregisterHandler(LogicProtocols.SendLogicList);
  159. }
  160. /// <summary>
  161. /// Called when server recieves moves from client
  162. /// </summary>
  163. /// <param name="msg">messages passed by server</param>
  164. private void RecieveLogicList(NetworkMessage msg)
  165. {
  166. //try to read base message as a logic message
  167. LogicProtocols.LogicMsg logicMsg;
  168. if (!msg.TryRead(out logicMsg))
  169. return;
  170. //Debug that we have recieved it
  171. Debug.Log("Recieved function from " + ClientList[msg.conn.connectionId].Name);
  172. //Update player Data with recieved list
  173. playerData[msg.conn.connectionId].blockReader.LogicChain = new List<LogicBlock>(logicMsg.elements);
  174. playerData[msg.conn.connectionId].recievedList = true;
  175. //if we have recieved all moves start round
  176. if (playerData.All(p => p.Value.recievedList))
  177. DoRoundRoutine();
  178. }
  179. #endregion Networking Functions
  180. private IEnumerator RunOnce(PlayerData data)
  181. {
  182. data.waiting = false;
  183. bool blockFinished = false;
  184. float waitTime;
  185. while (!blockFinished && !data.blockReader.Finished)
  186. {
  187. //Debug.Log(data.client + "Moving once");
  188. if (data.blockReader.CurrentBlock != null && !data.blockReader.CurrentBlock.hasBeenRemoved)
  189. {
  190. data.client.Inventory.Remove(data.blockReader.CurrentBlock);
  191. data.blockReader.CurrentBlock.hasBeenRemoved = true;
  192. }
  193. blockFinished = data.blockReader.Read(data.character, AnimationTime,out waitTime);
  194. //Debug.Log("Waiting: " + waitTime);
  195. yield return new WaitForSeconds(waitTime);
  196. gameMode.OnePlayerMoved(data);
  197. }
  198. data.waiting = true;
  199. }
  200. }
  201. public class PlayerData
  202. {
  203. public Character character;
  204. public BlockReader blockReader;
  205. public ClientData client;
  206. public bool recievedList;
  207. public bool waiting;
  208. public PlayerData(Character character, ClientData client)
  209. {
  210. this.character = character;
  211. this.client = client;
  212. blockReader = new BlockReader();
  213. }
  214. }