/// <summary> /// This method begins preperations for the building of the game world by creating and filling the world and also creating the update timer /// for the server as well. /// </summary> static void Start() { // No players have added at this moment so set the member variable to false. noPlayersJoined = true; // Create the HashTable for the client sockets and thier respective player cube ids. ClientSockets = new Dictionary <Socket, int>(); socketsToRemove = new List <Socket>(); allWorldCubes = new StringBuilder(); DeadPlayersUIDs = new HashSet <int>(); // Create the game world. world = new World("C:\\Users\\weisched\\Source\\Repos\\JacksonRepo\\AgCubio\\Resources\\XMLWorldParameters.xml"); // Lock the world object, and create all the food that will be added to the world. lock (world) { // Populate the world with an initial amount of food world.CreateFood(world.INITIAL_FOOD_AMT, true); world.CreateVirus(world.MAX_VIRUSES, true); } // Create timer for calling Update() updateTimer = new Timer(1 / (world.UPDATES_PER_SECOND / (double)1000)); updateTimer.Elapsed += new ElapsedEventHandler(updateTimerEvent); updateTimer.Start(); // Call Sever_Awaiting_Client method and await the connection of the first client. Network.Server_Awaiting_Client(HandleNewClient, 11000); // Also have server listen for incoming web requests on Port 11100 Network.Server_Awaiting_Client(GetWebRequest, 11100); }
/// <summary> /// This method is the "heartbeat" of the server. It's executed several times per second, as specified by the UPDATES_PER_SECOND member variable. /// It creates new food and viruses, atrophies player cubes, and broadcasts to all clients the most recent state of the world. /// </summary> private static void Update() { // Lock the world so that we can update it. lock (world) { // Create more food, if needed. if (world.foodCountInWorld < world.MAX_FOOD) { world.CreateFood(world.NEW_FOOD_AMT_PER_UPDATE, false); } // Create more viruses, if needed. if (world.virusCountInWorld < world.MAX_VIRUSES) { int virusesNeeded = world.MAX_VIRUSES - world.virusCountInWorld; world.CreateVirus(virusesNeeded, false); } // if any cubes have recently been exploded by a virus, start timers for them to re-merge if (world.virusMergeTimersToStart.Count > 0) { lock (mergeTimerLocker) { foreach (int teamID in world.virusMergeTimersToStart) { StartMergeTimer(teamID); } } world.virusMergeTimersToStart.Clear(); } // Clear out any old data in the StringBuilder allWorldCubes.Clear(); //List<double> TeamMasses = new List<double>(); //int Rank = 1; //foreach (int teamid in world.TeamStatistics.Keys) //{ // if (world.TeamStatistics[teamid].CurrentMass > world.TeamStatistics[teamid].MaximumMass) // { // world.TeamStatistics[teamid].MaximumMass = world.TeamStatistics[teamid].CurrentMass; // } // TeamMasses.Add(world.TeamStatistics[teamid].CurrentMass); //double largestMass = world.TeamStatistics[teamid].MaximumMass; //int largestMassId = teamid; //foreach (int teamidRank in world.TeamStatistics.Keys) //{ // if (world.TeamStatistics[teamidRank].MaximumMass > largestMass) // { // largestMass = world.TeamStatistics[teamidRank].MaximumMass; // largestMassId = teamidRank; // } //} // TeamMasses.Sort(); //} //foreach (int teamID in world.TeamStatistics.Keys) //{ // PlayerSessionStats session = world.TeamStatistics[teamID]; // if (TeamMasses.Count > 0 && TeamMasses[TeamMasses.Count - 1] == session.CurrentMass) // session.HighestRankAchieved = 1; // else if (TeamMasses.Count > 1 && TeamMasses[TeamMasses.Count - 2] == session.CurrentMass) // session.HighestRankAchieved = 2; // else if (TeamMasses.Count > 2 && TeamMasses[TeamMasses.Count - 3] == session.CurrentMass) // session.HighestRankAchieved = 3; // else if (TeamMasses.Count > 3 && TeamMasses[TeamMasses.Count - 4] == session.CurrentMass) // session.HighestRankAchieved = 4; // else if (TeamMasses.Count > 4 && TeamMasses[TeamMasses.Count - 5] == session.CurrentMass) // session.HighestRankAchieved = 5; //} // Create a list of all the current teams that exist masses. List <double> teamMasses = new List <double>(); // Loop through the sessions and get all the teams masses. foreach (int teamid in world.TeamStatistics.Keys) { // Update their mazimum mass value if needed. if (world.TeamStatistics[teamid].CurrentMass > world.TeamStatistics[teamid].MaximumMass) { world.TeamStatistics[teamid].MaximumMass = world.TeamStatistics[teamid].CurrentMass; } // Add each teams current mass to the list. teamMasses.Add(world.TeamStatistics[teamid].CurrentMass); } // Sort all the teams masses. teamMasses.Sort(); // Loop through and compare all the the current team masses with each other to determine the top 5 players // The list is sorted in acsending order so the top 5 largest players are in the bottom of the list. foreach (int teamid in world.TeamStatistics.Keys) { // If the team's mass is equal to the mass of the last item in the list, its the largest cube and therefore in 1st place. if (world.TeamStatistics[teamid].CurrentMass == teamMasses[teamMasses.Count - 1]) { if (world.TeamStatistics[teamid].HighestRankAchieved > 1) { world.TeamStatistics[teamid].HighestRankAchieved = 1; } } // If the team's mass is equal to the mass of the second to last item in the list, its the largest cube and therefore in 2nd place. else if (world.TeamStatistics[teamid].CurrentMass == teamMasses[teamMasses.Count - 2]) { if (world.TeamStatistics[teamid].HighestRankAchieved > 2) { world.TeamStatistics[teamid].HighestRankAchieved = 2; } } // If the team's mass is equal to the mass of the third to last item in the list, its the largest cube and therefore in 3rd place. else if (world.TeamStatistics[teamid].CurrentMass == teamMasses[teamMasses.Count - 3]) { if (world.TeamStatistics[teamid].HighestRankAchieved > 3) { world.TeamStatistics[teamid].HighestRankAchieved = 3; } } // If the team's mass is equal to the mass of the fourth to last item in the list, its the largest cube and therefore in 4th place. else if (world.TeamStatistics[teamid].CurrentMass == teamMasses[teamMasses.Count - 4]) { if (world.TeamStatistics[teamid].HighestRankAchieved > 4) { world.TeamStatistics[teamid].HighestRankAchieved = 4; } } // If the team's mass is equal to the mass of the fifth to last item in the list, its the largest cube and therefore in 5th place. else if (world.TeamStatistics[teamid].CurrentMass == teamMasses[teamMasses.Count - 5]) { if (world.TeamStatistics[teamid].HighestRankAchieved > 5) { world.TeamStatistics[teamid].HighestRankAchieved = 5; } } } // Perform mass attrition on player cubes, update DB if any players have died, // and send a String of all the recently modified cubes to all clients. foreach (Cube cube in world.CubesChangedSinceLastUpdate) { if (cube.food == false) { // If any players have died, update the game Database with their session stats if (cube.uid == cube.team_id && cube.Mass == 0 && !DeadPlayersUIDs.Contains(cube.uid)) { DeadPlayersUIDs.Add(cube.uid); UpdateDbWithDeadPlayerStats(cube); } // Update the attrition value for the player cubes if they have grown or shrunk. if (cube.Mass > world.RAPID_ATTRITION_THRESHOLD) { cube.Mass -= world.HIGH_ATTRITION_PER_UPDATE; } else if (cube.Mass > world.ATTRITION_LOWER_MASS_LIMIT) { cube.Mass -= world.NORMAL_ATTRITION_PER_UPDATE; } } // Serialize the cube so that it can be sent as a string. allWorldCubes.Append(JsonConvert.SerializeObject(cube) + '\n'); } // Empty the set for the next update. world.CubesChangedSinceLastUpdate.Clear(); // Send the recently modified cubes to all connected clients. lock (clientSocketsLocker) { foreach (Socket socket in ClientSockets.Keys) { Network.Send(socket, allWorldCubes.ToString()); } } } }