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.

325 lines
10 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 PlayerData[] playerDataAsArray { get { return playerData.Values.ToArray(); } }
  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. #region Unity Functions
  40. private void Start()
  41. {
  42. //Start Game
  43. StartCoroutine(GameRoutine());
  44. }
  45. private void Update()
  46. {
  47. //This is required so that the server can continue to recieve client messages
  48. //(it is a unity thing)
  49. server.ServerUpdate();
  50. }
  51. private void OnEnable()
  52. {
  53. //Let Server know we want to recieve some messages
  54. RegisterHandlers();
  55. }
  56. private void OnDisable()
  57. {
  58. //Let server know to not send messages this way
  59. UnRegisterHandlers();
  60. }
  61. #endregion Unity Functions
  62. #region Class Functions
  63. private IEnumerator GameRoutine()
  64. {
  65. //Allows game mode to instantiate anything it might need;
  66. gameMode.PreGameStart();
  67. //Spawn Characters and tell let the GameMode do anything with the characters it might want
  68. SpawnCharacters();
  69. playerDataAsArray.ForEach(p => p.client.SendLives());
  70. gameMode.GameStart(playerDataAsArray);
  71. //Loop until the GameMode lets us know the game is over
  72. while (!gameMode.isGameOver(playerDataAsArray))
  73. {
  74. //wait until we have recieved all player input
  75. yield return StartCoroutine(WaitForPlayerInput());
  76. //Routine for players movement
  77. yield return StartCoroutine(RoundRoutine()); //it's pretty long so it gets it's own coroutine;
  78. }
  79. //Let the gamemode know that the game is over
  80. gameMode.GameEnd(playerDataAsArray);
  81. }
  82. void removePlayer(PlayerData player)
  83. {
  84. player.client.ChangeScene("WaitScene");
  85. player.isDead = true;
  86. }
  87. private IEnumerator RoundRoutine()
  88. {
  89. //Tell the gamemode that we are starting a round
  90. gameMode.RoundStart(playerDataAsArray);
  91. //Loop until all players have finished moving
  92. while (playerDataAsArray.Any(p => !p.blockReader.Finished))
  93. {
  94. //Loop through all players
  95. foreach (PlayerData player in playerDataAsArray)
  96. {
  97. yield return StartCoroutine(MoveRoutine(player));//Move Player
  98. gameMode.PlayerMoved(player);//LetGameModeKnow
  99. }
  100. //Let Gamemode know all players have moved
  101. gameMode.AllPlayersMoved(playerDataAsArray.ToArray());
  102. //if Game is over break out of loop
  103. if (gameMode.isGameOver(playerDataAsArray))
  104. break;
  105. }
  106. //decrease lives here!!
  107. foreach (PlayerData player in playerDataAsArray)
  108. {
  109. gameMode.PlayerKilled(player);
  110. }
  111. playerDataAsArray.ForEach(p => p.client.SendLives()); //Update the players score
  112. //Let GameMode know that Round is Over
  113. gameMode.RoundEnd(playerDataAsArray.ToArray());
  114. //check is anyone has 0 lives remaining
  115. //remove them from the array
  116. //force them back to the waiting for players screen
  117. foreach (PlayerData player in playerDataAsArray)
  118. {
  119. if(player.client.Lives == 0)
  120. {
  121. Debug.Log("Remove: " + player.client.characterAnimal);
  122. removePlayer(player);
  123. }
  124. }
  125. //Reset some player Data
  126. foreach (PlayerData player in playerDataAsArray)
  127. {
  128. if(player.client.Lives > 0)
  129. {
  130. player.blockReader.Reset();
  131. player.client.SendInventory();
  132. }
  133. }
  134. }
  135. private IEnumerator WaitForPlayerInput()
  136. {
  137. //send round length to players
  138. //#TODO make this only happen after first input
  139. LogicProtocols.FloatMsg RoundTime = new LogicProtocols.FloatMsg(gameMode.GetRoundTime());
  140. //playerDataAsArray.ForEach(p => p.client.conn.Send(LogicProtocols.SendRoundTime, RoundTime));
  141. foreach (PlayerData player in playerDataAsArray)
  142. {
  143. if (player.client.Lives > 0)
  144. {
  145. player.client.conn.Send(LogicProtocols.SendRoundTime, RoundTime);
  146. }
  147. }
  148. //Send players to input Scene
  149. //ClientList.ForEach(p => p.ChangeScene("ClientScene"));
  150. foreach (ClientData client in ClientList)
  151. {
  152. if(client.Lives > 0){client.ChangeScene("ClientScene");}
  153. }
  154. //Let gamemode know clients are input-ing
  155. gameMode.InputStart(playerDataAsArray);
  156. //wait for all players to
  157. yield return new WaitUntil(() => playerData.All(p => p.Value.recievedList || p.Value.isDead));
  158. //reset
  159. //playerDataAsArray.ForEach(p => p.recievedList = false); //reset all players list
  160. foreach (PlayerData player in playerDataAsArray)
  161. {
  162. if (player.client.Lives > 0){player.recievedList = false;}
  163. }
  164. //Let gamemode know all inputs have been recieved
  165. gameMode.InputEnd(playerDataAsArray);
  166. }
  167. private IEnumerator MoveRoutine(PlayerData data)
  168. {
  169. bool blockFinished = false;
  170. float waitTime;
  171. //Loop until the current block indicates or the reader indicates it has finished
  172. while (!blockFinished && !data.blockReader.Finished)
  173. {
  174. //If the current block hasn't already been removed, remove it from the player inventory
  175. //We need to check if it has already been removed so loops don't eat an entire stack
  176. if (data.blockReader.CurrentBlock != null && !data.blockReader.CurrentBlock.hasBeenRemoved)
  177. {
  178. data.client.Inventory.Remove(data.blockReader.CurrentBlock);
  179. data.blockReader.CurrentBlock.hasBeenRemoved = true;
  180. }
  181. //Process the move
  182. blockFinished = data.blockReader.Read(data.character, AnimationTime, out waitTime);
  183. //Wait for the animation to finish
  184. yield return new WaitForSeconds(waitTime);
  185. }
  186. }
  187. private void SpawnCharacters()
  188. {
  189. playerData = new Dictionary<int, PlayerData>();
  190. Block[] SpawnBlocks = FindObjectsOfType<Block>().Where(p => p.isSpawnable).ToArray();
  191. int blockIndex = 0;
  192. foreach (Block block in SpawnBlocks)
  193. {
  194. Debug.Log("Block #" + blockIndex++ + " (" + block.transform.position.x + ", " + block.transform.position.y + ", " + block.transform.position.z + ")");
  195. }
  196. //int spawnIndex = 0;
  197. //If we have an odd number of players, then we start at spawn point 0 (in the middle)
  198. //If we have an even number, then we skip it
  199. //int spawnIndex = ((ClientList.Count() + 1) % 2);
  200. int spawnIndex = 0;
  201. foreach (ClientData client in ClientList)
  202. {
  203. //Debug.Log("spawnIndex = " + spawnIndex);
  204. Character newChar = Instantiate(characterPrefab);
  205. //Block startingBlock = SpawnBlocks[(spawnIndex++ % ClientList.ConnectedClients.Count)];
  206. Block startingBlock = SpawnBlocks[spawnIndex++];
  207. newChar.Initialise(startingBlock, client.Inventory, client.characterAnimal);
  208. newChar.transform.forward = startingBlock.SpawnDirection.ToVector();
  209. playerData.Add(client.ID, new PlayerData(newChar, client));
  210. newChar.ClientLink = client;
  211. client.playerCharacter = newChar;
  212. }
  213. }
  214. #endregion Class Functions
  215. #region Networking Functions
  216. /// <summary>
  217. /// Registers functions which should deal with incoming messages from clients
  218. /// </summary>
  219. private void RegisterHandlers()
  220. {
  221. server.server.RegisterHandler(LogicProtocols.SendLogicList, RecieveLogicList);
  222. }
  223. /// <summary>
  224. /// Clears any functions from server register which the manager would deal with
  225. /// </summary>
  226. private void UnRegisterHandlers()
  227. {
  228. server.server.UnregisterHandler(LogicProtocols.SendLogicList);
  229. }
  230. /// <summary>
  231. /// Called when server recieves moves from client
  232. /// </summary>
  233. /// <param name="msg">messages passed by server</param>
  234. private void RecieveLogicList(NetworkMessage msg)
  235. {
  236. //try to read base message as a logic message
  237. LogicProtocols.LogicMsg logicMsg;
  238. if (!msg.TryRead(out logicMsg))
  239. return;
  240. //Debug that we have recieved it
  241. Debug.Log("Recieved function from " + ClientList[msg.conn.connectionId].Name);
  242. //Update player Data with recieved list
  243. playerData[msg.conn.connectionId].blockReader.LogicChain = new List<LogicBlock>(logicMsg.elements);
  244. playerData[msg.conn.connectionId].recievedList = true;
  245. }
  246. #endregion Networking Functions
  247. }
  248. public class PlayerData
  249. {
  250. public Character character;
  251. public BlockReader blockReader;
  252. public ClientData client;
  253. public bool recievedList;
  254. public bool isDead = false;
  255. public PlayerData(Character character, ClientData client)
  256. {
  257. this.character = character;
  258. this.client = client;
  259. blockReader = new BlockReader();
  260. }
  261. }