/// <summary> /// This part sets up a tank with the player name and sends the startup info to the client including the world size, player ID, /// and walls. /// </summary> /// <param name="ss">Socket state for the connection</param> private static void SendStartupInfo(SocketState ss) { if (ss.ErrorOccured == true) { Console.WriteLine("Error occured while accepting: \"" + ss.ErrorMessage + "\""); return; } //Gets the name and ID from the socket and removes the name from the socket string tankName = ss.GetData(); int tankID = (int)ss.ID; ss.RemoveData(0, tankName.Length); lock (TheWorld) { /*This sets up the tank, sets the cooldown frames so it can fire, adds a filler command to the dictionary, and * spawns the tank at a random location.*/ Tank t = new Tank(tankName.Substring(0, tankName.Length - 1), tankID); TheWorld.UpdateTank(t); TheWorld.TankSetCooldownFrames(t.ID, FramesPerShot); TheWorld.UpdateCommand(tankID, new ControlCommands()); SpawnTank(t); Console.WriteLine("Player(" + tankID + ") " + "\"" + t.Name + "\" joined"); } //Changes the delegate ss.OnNetworkAction = ReceiveCommandData; //Sends the tank ID and the world size string message = tankID + "\n" + UniverseSize.ToString() + "\n"; if (!Networking.Send(ss.TheSocket, message)) { Console.WriteLine("Error occured while sending data"); } //Sends the walls to the client lock (TheWorld) { StringBuilder wallMessage = new StringBuilder(); foreach (Wall w in TheWorld.Walls.Values) { wallMessage.Append(JsonConvert.SerializeObject(w) + "\n"); } if (!Networking.Send(ss.TheSocket, wallMessage.ToString())) { Console.WriteLine("Error occured while sending data"); } } //Adds the socket state to the list of connections SocketConnections.Add(ss); Networking.GetData(ss); }
/// <summary> /// Starts the server and sets up the walls /// </summary> private void StartServer() { clients = new Dictionary <SocketState, Tank>(); // start accepting clients theServer = Networking.StartServer(HandleNewClient, 11000); }
/// <summary> /// Starts the server with Networking class. /// </summary> private void Start() { Networking.StartServer(HandleNewClient, 11000); Console.WriteLine("Server Is Running. Now Accepting New Clients."); }
/// <summary> /// Method for sending the data to the client sockets. It goes through the list of tanks, powerups, projectiles, and beams /// and appends them to a stringbuilder to send. It also handles sockets that have disconnected. /// </summary> private static void SendDataToSockets() { lock (TheWorld) { foreach (SocketState s in SocketConnections.ToList()) { if (!s.TheSocket.Connected) { int tankID = (int)s.ID; //Makes sure that the dictionary contains the right key. If not, the tank must have died and rage quit if (TheWorld.Tanks.ContainsKey(tankID)) { Console.WriteLine("Player(" + tankID + ") " + "\"" + TheWorld.Tanks[(int)s.ID].Name + "\" disconnected"); TheWorld.TankDisconnect(tankID); TheWorld.TankKill(tankID); } if (TheWorld.DeadTanks.ContainsKey(tankID)) { Console.WriteLine("Player(" + tankID + ") " + "\"" + TheWorld.DeadTanks[(int)s.ID].Name + "\" disconnected"); TheWorld.TankDeadRemove(tankID); } SocketConnections.Remove(s); } } foreach (SocketState s in SocketConnections.ToList()) { StringBuilder frameMessage = new StringBuilder(); lock (TheWorld) { foreach (Tank t in TheWorld.Tanks.Values) { frameMessage.Append(JsonConvert.SerializeObject(t) + "\n"); } foreach (PowerUp p in TheWorld.PowerUps.Values) { frameMessage.Append(JsonConvert.SerializeObject(p) + "\n"); } foreach (Projectile p in TheWorld.Projectiles.Values) { frameMessage.Append(JsonConvert.SerializeObject(p) + "\n"); } foreach (Beam b in TheWorld.Beams.Values) { frameMessage.Append(JsonConvert.SerializeObject(b) + "\n"); } } if (!Networking.Send(s.TheSocket, frameMessage.ToString())) { Console.WriteLine("Error occured while sending data"); } } } }
private static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.White; Console.Title = "ENVIUM DEDICATED SERVER"; Out.MsgC(ConsoleColor.Green, "Initializing the server ..."); _buffer = new byte[4096]; _boundEndPoint = new IPEndPoint(IPAddress.Any, 644); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); try { _socket.Bind(_boundEndPoint); } catch (SocketException ex) { Out.Error("Network: Cannot bound at address {0}: {1}", _boundEndPoint, ex.Message); Console.ReadLine(); return; } Out.Msg("Network: Socket bounded at {0}", _socket.LocalEndPoint as IPEndPoint); FrameSnapshotManager = new FrameSnapshotManager(); ServerPluginHandler = new ServerPlugin(); Server = new GameServer(_socket) { State = EServerState.Loading, TickInterval = GetTickInterval() }; Networking.Initialize(); new Thread(GameTick) { IsBackground = true }.Start(); Server.State = EServerState.Active; Out.Msg("Done loading."); var clientEp = (EndPoint) new IPEndPoint(IPAddress.Any, 0); _socket.BeginReceiveFrom(_buffer, 0, _buffer.Length, SocketFlags.None, ref clientEp, DoReceiveFrom, clientEp); string read; while ((read = Console.ReadLine()) != "exit") { if (read == "help") { continue; } if (read == "curtime") { var time = Utils.SysTime(); Console.WriteLine("Current server time: {0}", time); continue; } Console.WriteLine("Unknown command \"{0}\".", read); } }
public void Attach(Networking Networking) { this.Networking = Networking; Networking.HookPacket <HelloPacket>(HelloPacketRecieved); Networking.ClientConnected += Networking_ClientConnected; }
/// <summary> /// This method is called the first time a client connects /// </summary> /// <param name="state"></param> private static void RecieveStartupInfo(SocketState state) { controller.UpdateWorld(state); state.OnNetworkAction = ReceiveMessageFromClient; Networking.GetData(state); }
public static void HandleNewClients(SocketState s) { s.callMe = ReceiveName; Networking.GetData(s); }
/// <summary> /// starts the server on the specified port /// </summary> private static void StartServer() { Networking.StartServer(OnStart, 11000); }
private void SendData() { while (true) { List <SocketState> playerSocketCopy = new List <SocketState>(playerSockets.Values); StringBuilder sb = new StringBuilder(); List <long> listToRemove = new List <long>(); var prev = DateTime.Now; //For every socket connected to this server send a frame foreach (SocketState state in playerSocketCopy) { foreach (Tank t in world.GetTanks()) { t.projectileDelay += 1; } if (powerUpTracker < powerupCount) { timeSinceLastPowerUp += FPS; } if (timeSinceLastPowerUp > randPowerupTime) { SpawnPowerup(); randPowerupTime = rand.Next(0, maxPowerupSpawnTime); timeSinceLastPowerUp = 0; } //Seems innefficient to do this for every tank but.. TODO lock (world) { foreach (Tank t in world.GetTanks()) { sb.Append(JsonConvert.SerializeObject(t) + "\n"); if (t.IsDead()) { RespawnTank(t); } if (t.IsDisconnected()) { listToRemove.Add(t.GetID()); } } foreach (long ID in listToRemove) { world.RemoveTankByID((int)ID); } listToRemove.Clear(); foreach (Projectile p in world.GetProjectiles()) { MoveProjectile(p); sb.Append(JsonConvert.SerializeObject(p) + "\n"); if (p.IsDead()) { listToRemove.Add(p.GetID()); } } foreach (long ID in listToRemove) { world.RemoveProjectile(ID); } listToRemove.Clear(); foreach (Beam b in world.GetBeams()) { sb.Append(JsonConvert.SerializeObject(b) + "\n"); listToRemove.Add(b.GetID()); } foreach (long ID in listToRemove) { world.RemoveBeam(ID); } listToRemove.Clear(); foreach (Powerup up in world.GetPowerups()) { sb.Append(JsonConvert.SerializeObject(up) + "\n"); if (up.IsDead()) { listToRemove.Add(up.GetID()); } } if (!working) { foreach (long ID in listToRemove) { world.RemovePowerup(ID); powerUpTracker--; } } } listToRemove.Clear(); List <SocketState> mySockets = new List <SocketState>(playerSockets.Values); foreach (SocketState player in mySockets) { Networking.Send(player.TheSocket, sb.ToString()); } //Console.WriteLine(sb.ToString()); sb.Clear(); } //managing the framerate for when this loop repeats var now = DateTime.Now; if (now <= prev.AddMilliseconds(FPS)) { TimeSpan timeSpan = prev.AddMilliseconds(FPS) - now; System.Threading.Thread.Sleep((int)timeSpan.TotalMilliseconds); } prev = DateTime.Now; } }
/// <summary> /// Detects the incoming messages of new players when they connect then calls Get Data in order to create an event loop to continue listening for /// new incoming players /// </summary> /// <param name="state">Connection of incoming player.</param> private void ProcessMessage(SocketState state) { string data; long ID = state.ID; string[] movingCommands; if (state.ErrorOccured) { PlayerDisconnect(state); Networking.SendAndClose(state.TheSocket, "error"); //Networking.GetData(state); return; } data = state.GetData(); state.ClearData(); if (String.IsNullOrEmpty(data)) { Networking.GetData(state); return; } //checks to see if user is sending a user command or name if (data.StartsWith("{\"moving\"")) { movingCommands = data.Split(','); foreach (string s in movingCommands) { string[] command = s.Split(':'); foreach (string t in command) { string tempString = t.Replace("\"", String.Empty); string tempString2 = tempString.Replace("{", String.Empty); string stringToCompare = tempString2.Replace("}", String.Empty); switch (stringToCompare) { case "none": break; case "up": MoveTank(new Vector2D(0, playerSpeed * -1), new Vector2D(0, -1), players[ID]); break; case "down": MoveTank(new Vector2D(0, playerSpeed), new Vector2D(0, 1), players[ID]); break; case "left": MoveTank(new Vector2D(playerSpeed * -1, 0), new Vector2D(-1, 0), players[ID]); break; case "right": MoveTank(new Vector2D(playerSpeed, 0), new Vector2D(1, 0), players[ID]); break; case "main": FireProjectile(players[ID]); break; case "alt": FireBeam(players[ID]); break; case "x": if (double.TryParse(command[2], out double anglex)) { turretAimx = anglex; } break; case "y": if (command[1].Length > 4) { if (double.TryParse(command[1].Substring(0, command[1].Length - 5), out double angley)) { turretAimy = angley; } players[ID].SetAim(new Vector2D(turretAimx, turretAimy)); } break; } } } } else if (!players.ContainsKey(ID)) { Console.WriteLine("Player " + state.ID.ToString() + " Connected."); CreateTank(data, ID); Sendwalls(state); Networking.GetData(state); return; } Networking.GetData(state); }
/// <summary> /// Invoked every iteration through the frame loop. /// Update World, then sends it to each client. /// </summary> private static void Update() { // Updated world StringBuilder sb = new StringBuilder(); lock (World) { // For all Stars in World foreach (Star star in World.Stars.Values) { // Append each Star sb.Append(JsonConvert.SerializeObject(star) + "\n"); // Destroy all Ships colliding with Star foreach (Ship ship in World.Ships.Values) { Vector2D distance = star.loc - ship.loc; if (distance.Length() < StarSize) { ship.hp = 0; if (GAMEMODE_RandomDeadlyStar) { ship.score--; } ship.alive = false; DeadShips.Add(ship); } } // Destroy all Projectiles colliding with Star foreach (Projectile p in World.Projectiles.Values) { Vector2D distance = star.loc - p.loc; if (distance.Length() < StarSize) { p.alive = false; DeadProjectiles.Add(p.ID); } } } // For all Ships in World foreach (Ship ship in World.Ships.Values) { // Thrust Ship if (ship.up) { ship.thrust = true; ship.velocity += Acceleration(Thrust(ship.dir), Gravity(ship.loc)); ship.loc += ship.velocity; ship.up = false; } // Non-thrusting Ship else { ship.velocity += Gravity(ship.loc); ship.loc += ship.velocity; ship.thrust = false; } // Rotate Left if (ship.left) { ship.dir = RotateLeft(ship.dir); ship.left = false; } // Rotate right if (ship.right) { ship.dir = RotateRight(ship.dir); ship.right = false; } // Fire projectile if (ship.space && ship.alive) { // Begin spacing projectiles ship.projectileTimer++; if (ship.projectileTimer >= ProjectileFiringDelay) { Projectile p = new Projectile(); p.ID = ProjectileID; p.loc = ship.loc; p.dir = ship.dir; p.alive = true; p.owner = ship.ID; p.velocity = (p.dir * ProjectileSpeed) + ship.velocity; World.Projectiles.Add(p.ID, p); ship.projFired++; ship.projectileTimer = 0; ProjectileID++; } ship.space = false; } // If Ship exits World's bounds if (ship.loc.GetX() >= UniverseSize / 2 || ship.loc.GetX() <= -(UniverseSize / 2) || ship.loc.GetY() >= UniverseSize / 2 || ship.loc.GetY() <= -(UniverseSize / 2)) { // Wrap around Ship ship.loc = WrapAround(ship.loc); } // Destroy all Projectiles colliding with Ship and vise-versa foreach (Projectile p in World.Projectiles.Values) { Vector2D distance = ship.loc - p.loc; if (distance.Length() < ShipSize && ship.ID != p.owner && ship.alive) { p.alive = false; ship.hp--; ShipHits.Add(World.Ships[p.owner]); if (ship.hp <= 0) { ship.alive = false; DeadShips.Add(ship); ScoringShips.Add(p.owner); } DeadProjectiles.Add(p.ID); } } sb.Append(JsonConvert.SerializeObject(ship) + "\n"); } // For all Projectiles in World foreach (Projectile p in World.Projectiles.Values) { // Update projectile location with constant velocity p.loc += p.velocity; // If Projectile exits World's bounds if (p.loc.GetX() >= UniverseSize / 2 || p.loc.GetX() <= -(UniverseSize / 2) || p.loc.GetY() >= UniverseSize / 2 || p.loc.GetY() <= -(UniverseSize / 2)) { // Destroy Projectile p.alive = false; DeadProjectiles.Add(p.ID); } sb.Append(JsonConvert.SerializeObject(p) + "\n"); } // All Projectiles-to-destroy are removed from World foreach (int i in DeadProjectiles) { World.Projectiles.Remove(i); } DeadProjectiles.Clear(); // All Ships-to-score have score increased foreach (int i in ScoringShips) { Ship s = World.Ships.Values.ElementAt(i); s.score++; } ScoringShips.Clear(); // All Ships-to-destroy are removed from World and respawned foreach (Ship ship in DeadShips) { if (ship.hp <= 0) { // Incremental value has a further effect on respawn rate ship.respawnTimer += 20; } if (ship.respawnTimer >= RespawnDelay * TimePerFrame) { ship.respawnTimer = 0; ResetShip(ship); ResurrectedShips.Add(ship); } } // Respawn dead Ship foreach (Ship ship in ResurrectedShips) { DeadShips.Remove(ship); } ResurrectedShips.Clear(); // Add hit projectiles to Ship foreach (Ship ship in ShipHits) { World.Ships[ship.ID].projHit++; } ShipHits.Clear(); // Each client is updated with appended World information foreach (SocketState state in Clients) { Networking.Send(state.theSocket, sb.ToString()); } } }
/// <summary> /// Main method responsible for running all server processes. /// </summary> /// <param name="args"></param> static void Main(string[] args) { // Allowing the program to update the database when closed Program.SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true); // Program start time LastAccessedTime = DateTime.Now; // XML Settings are read and adjusted... ReadSettings("...//...//...//Resources/settings.xml"); World = new World(); Clients = new List <SocketState>(); ShipID = 0; ProjectileID = 0; // Initial Star Creation Star star = new Star(); // Game mode alteration if (GAMEMODE_RandomDeadlyStar) { Random rand = new Random(); star.loc = new Vector2D(rand.Next(-(UniverseSize / 2), UniverseSize / 2), rand.Next(-(UniverseSize / 2), UniverseSize / 2)); } else { star.loc = new Vector2D(StarX, StarY); } // Star added to World World.Stars.Add(0, star); // Temporary lists initialized DeadShips = new HashSet <Ship>(); ResurrectedShips = new List <Ship>(); DeadProjectiles = new List <int>(); ScoringShips = new HashSet <int>(); ShipHits = new List <Ship>(); Watch = new Stopwatch(); // Begin event-driven callback for handling new clients Networking.ServerAwaitingClientLoop(HandleNewClient); System.Console.Out.WriteLine("Server is running, awaiting first client..."); // Begin forever loop which handles client data and updates and sends World data based on // result while (true) { Watch.Start(); while (Watch.ElapsedMilliseconds < TimePerFrame) { } Watch.Reset(); Update(); } }