/// <summary> /// Processes the message received from the server. If it is a json object, it updates the world accordingly. /// Otherwise, it is either the player id or world size, and thus sets those accordingly. /// </summary> private void ProcessMessage(SocketState state) { if (state.ErrorOccured) { return; } //Gets data and parts from data string totalData = state.GetData(); string[] parts = Regex.Split(totalData, @"(?<=[\n])"); foreach (string s in parts) { //If the part has a length of 0, then it is not a complete message if (s.Length <= 0) { continue; } //If the part does not end with newline, then the message is incomplete if (s[s.Length - 1] != '\n') { break; } //If the part is a json, deserialize if (s[0] == '{') { lock (world) { //Get the json object out of the part JObject obj = JObject.Parse(s); JToken type; //Commands type = obj["controlcommand"]; if (type != null) { ControlCommand c = JsonConvert.DeserializeObject <ControlCommand>(s); //do thing } } } //If it is not a json object, then it must be the player's name else { lock (world) { users.Add(state, userCount); //Change position to random world.UpdateTank(userCount++, new Vector2D(0, 0), new Vector2D(0, 0), new Vector2D(0, 0), s, 3, 0, false, false); } } lock (state) { //Remove the processed part state.RemoveData(0, s.Length); } } }
/// <summary> /// Processes the message received from the server. If it is a json object, it updates the world accordingly. /// Otherwise, it is either the player id or world size, and thus sets those accordingly. /// </summary> private void ProcessMessage(SocketState state) { if (state.ErrorOccured) { return; } //Gets data and parts from data string totalData = state.GetData(); string[] parts = Regex.Split(totalData, @"(?<=[\n])"); foreach (string s in parts) { //If the part has a length of 0, then it is not a complete message if (s.Length <= 0) { continue; } //If the part does not end with newline, then the message is incomplete if (s[s.Length - 1] != '\n') { break; } //If the part is a json, deserialize if (s[0] == '{') { lock (world) { //Get the json object out of the part JObject obj = JObject.Parse(s); JToken type; //Wall is not loaded if (!world.WallsLoaded) { type = obj["wall"]; if (type != null) { Wall w = JsonConvert.DeserializeObject <Wall>(s); world.AddWall(w.ID, w.p1, w.p2); } else { //As soon as we reach a JSON that isn't a wall, the walls are loaded world.LoadWalls(); WorldLoaded(); } } //If it a tank, update the world type = obj["tank"]; if (type != null) { Tank t = JsonConvert.DeserializeObject <Tank>(s); world.UpdateTank(t.ID, t.location, t.orientation, t.aiming, t.name, t.hitPoints, t.score, t.died, t.disconnected); } //Projectile type = obj["proj"]; if (type != null) { Projectile p = JsonConvert.DeserializeObject <Projectile>(s); world.UpdateProjectile(p.ID, p.location, p.orientation, p.owner, p.died); } //Powerup type = obj["power"]; if (type != null) { Powerup p = JsonConvert.DeserializeObject <Powerup>(s); world.UpdatePowerup(p.ID, p.location, p.died); } //Beam type = obj["beam"]; if (type != null) { Beam b = JsonConvert.DeserializeObject <Beam>(s); BeamFired(b); } } } //If it is not a json object, then it must be the world size or player id else { //If player id is not set, then the part is the player id if (PlayerID < 0) { PlayerID = Int32.Parse(s); IDLoaded(); } //Otherwise, the part must be the world else { world = new World(Int32.Parse(s)); } } lock (state) { //Remove the processed part state.RemoveData(0, s.Length); } //If OnUpdate is set, call it if (OnUpdate != null) { OnUpdate(); } } }
/// <summary> /// We will receive the player's name and assign an ID number /// At this time we will also send to the client world size, the ID number /// and the walls /// </summary> /// <param name="client"></param> private void GetPlayerInfo(SocketState client) { //Check if error occured and write message to console if (client.ErrorOccured) { Console.WriteLine(client.ErrorMessage); } //Set the new callback action client.OnNetworkAction = GetActionDataFromClient; //Get the player name string playerName = client.GetData().Trim('\n'); //Create a new tank representing the player at a random location Tank newPlayer = new Tank(playerNumber, playerName, RandomLocationGenerator()) { //Allows the tank to fire upon spawn FrameCount = framesBetweenShot + 1 }; //We don't spawn on walls or powerups while (CheckForCollision(newPlayer, 1)) { newPlayer.Location = new Vector2D(RandomLocationGenerator()); } //Add player to our connections lock (connections) { //Send ID and worldsize info Networking.Send(client.TheSocket, playerNumber.ToString() + "\n" + serverWorld.Size.ToString() + "\n"); //Add socket state to the collection of players with their ID number connections.Add(client, playerNumber); } Console.WriteLine("Player " + playerNumber.ToString() + ": " + playerName + " has connected."); //Add player to server world lock (serverWorld.Tanks) { serverWorld.Tanks.Add(newPlayer.GetID(), newPlayer); //Increase player ID number playerNumber++; } //Create a string builder info to serialize and send all the walls StringBuilder wallinfo = new StringBuilder(); foreach (Wall wall in serverWorld.Walls.Values) { wallinfo.Append(JsonConvert.SerializeObject(wall) + "\n"); } //Send walls to the client Networking.Send(client.TheSocket, wallinfo.ToString()); //Empty the socket state of data client.ClearData(); //Begin receive loop Networking.GetData(client); }
/// <summary> /// Process any buffered messages separated by '\n' /// Then inform the view /// </summary> /// <param name="state"></param> private void ReceiveWorld(SocketState state) { //Gets the data from the state and splits it by a new line string totalData = state.GetData(); string[] parts = Regex.Split(totalData, @"(?<=[\n])"); // Loop until we have processed all messages. // We may have received more than one. //Gets the player number, which should only be once int playerNumber = 0; havePlayerNum = int.TryParse(parts[0], out playerNumber); parts[0] = ""; if (playerNumber != 0) { playerNum = playerNumber; } //Gets the dimensions of the world that should only happen once int dim = 0; haveDimension = int.TryParse(parts[1], out dim); parts[1] = ""; if (dim != 0) { worldDimension = dim; world = new World(worldDimension); } //Iterates through all the data given by the server foreach (string p in parts) { // Ignore empty strings added by the regex splitter if (p.Length == 0) { continue; } // The regex splitter will include the last string even if it doesn't end with a '\n', // So we need to ignore it if this happens. if (p[p.Length - 1] != '\n') { break; } //Locks with a world so that we process information in a single thread lock (world) { //Parses the object with the JSON JObject jObject = JObject.Parse(p); //Converts the JSON object to a token based on the name of the string JToken projToken = jObject["proj"]; JToken beamToken = jObject["beam"]; JToken tankToken = jObject["tank"]; JToken wallToken = jObject["wall"]; JToken powerToken = jObject["power"]; //If the projToken is not null, i.e. if the JSON string passed was a projectile, then it goes in this condition if (projToken != null) { //Deserializes the string and converts it to a projectile Projectile proj = JsonConvert.DeserializeObject <Projectile>(p); //Adds the projectile to the world world.SetProjectile(proj.GetID(), proj); //If projectile is dead, removes the projectile from the world if (proj.GetDead() == true) { world.GetProjectile().Remove(proj.GetID()); } } //If the beamToken is not null, i.e. if the JSON string passed was a beam, then it goes in this condition if (beamToken != null) { //Deserializes the string and converts it to a beam Beams b = JsonConvert.DeserializeObject <Beams>(p); //Adds the beam in the world's beam dictionary world.SetBeams(b.GetBeamID(), b); } //If the tankToken is not null, i.e. if the JSON string passed was a tank, then it goes in this condition if (tankToken != null) { //Deserializes the string and converts it to a tank Tank t = JsonConvert.DeserializeObject <Tank>(p); //Sets the color of the tank based on the tank's ID t.SetColor(t.GetID()); //Adds the tank to the world's tank dictionary world.SetTanks(t.GetID(), t); //If the hitpoints of the tank are 0, then it remove it from the dictionary if (t.GetHitPoints() == 0) { world.GetTanks().Remove(t.GetID()); } //If the tank gets disconnected, then it remove it from the dictionary if (t.GetDisconnected()) { world.GetTanks().Remove(t.GetID()); } //If the tank is dead, then it remove it from the dictionary if (t.GetDead()) { world.GetTanks().Remove(t.GetID()); } } //If the wallToken is not null, i.e. if the JSON string passed was a wall, then it goes in this condition if (wallToken != null) { //Deserializes the string and converts it to a wall Wall w = JsonConvert.DeserializeObject <Wall>(p); //Adds the wall to the world's wall dictionary world.SetWalls(w.GetID(), w); } //If the powerToken is not null, i.e. if the JSON string passed was a powerup, then it goes in this condition if (powerToken != null) { //Deserializes the string and converts it to a powerup Powerups power = JsonConvert.DeserializeObject <Powerups>(p); //Adds the powerup to the world's powerup dictionary world.SetPowerups(power.GetID(), power); //If the powerup is dead, then it removes it from the dictionary if (power.GetDead()) { world.GetPowerups().Remove(power.GetID()); } } } // Then remove it from the SocketState's growable buffer state.RemoveData(0, p.Length); } if (UpdateArrived != null) { // inform the view to redraw UpdateArrived(); } //Inform the server Process(); }
//Send ControlCommand to server private void SendControlCommand(SocketState state) { string jsonData = JsonConvert.SerializeObject(command); Networking.Send(state.TheSocket, jsonData + "\n"); }
private void SendStartupInfo(SocketState state, int playerID, int worldSize) { string message = playerID + "\n" + worldSize + "\n"; Networking.Send(state.TheSocket, message); }
/// <summary> /// Processes the message received from the server. If it is a json object, it updates the world accordingly. /// Otherwise, it is either the player id or world size, and thus sets those accordingly. /// </summary> private void ProcessMessage(SocketState state) { if (state.ErrorOccured) { return; } //Gets data and parts from data string totalData = state.GetData(); string[] parts = Regex.Split(totalData, @"(?<=[\n])"); foreach (string s in parts) { //If the part has a length of 0, then it is not a complete message if (s.Length <= 0) { continue; } //If the part does not end with newline, then the message is incomplete if (s[s.Length - 1] != '\n') { break; } //If the part is a json, deserialize if (s[0] == '{') { lock (controls) { //Get the json object out of the part JObject obj = JObject.Parse(s); JToken type; //Commands type = obj["moving"]; if (type != null) { ControlCommand c = JsonConvert.DeserializeObject <ControlCommand>(s); if (!controls.ContainsKey(users[state])) { controls.Add(users[state], c); } else { controls[users[state]] = c; } } } } //If it is not a json object, then it must be the player's name else { lock (world) { Random r = new Random(); Vector2D RandLoc = new Vector2D(r.Next(-world.GetSize() / 2 + 16, world.GetSize() / 2 - 16), r.Next(-world.GetSize() / 2 + 16, world.GetSize() / 2 - 16)); while (CheckTankWallCollision(RandLoc)) { RandLoc = new Vector2D(r.Next(-world.GetSize() / 2 + 16, world.GetSize() / 2 - 16), r.Next(-world.GetSize() / 2 + 16, world.GetSize() / 2 - 16)); } world.UpdateTank((int)state.ID, RandLoc, new Vector2D(0, 1), new Vector2D(0, 1), s, 3, 0, false, false); } } lock (state) { //Remove the processed part state.RemoveData(0, s.Length); } } }