示例#1
0
        /// <summary>
        /// This method parses the commands received and calls a method to deserialize them.
        /// </summary>
        /// <param name="ss">Socket state to process the data from</param>
        private static void ProcessData(SocketState ss)
        {
            //Splits the string but keeps the '\n' characters
            string totalData = ss.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            lock (TheWorld)
            {
                string lastCommand = null;

                foreach (string p in parts)
                {
                    //This is to ignore empty strings
                    if (p.Length == 0)
                    {
                        continue;
                    }
                    //This is so it ignores the last string if it doesn't end in '\n'
                    if (p[p.Length - 1] != '\n')
                    {
                        break;
                    }

                    lastCommand = p;
                    ss.RemoveData(0, p.Length);
                }

                if (lastCommand != null)
                {
                    //Calls a method to deserialize the data and then removes the data from the buffer
                    UpdateObject(lastCommand, (int)ss.ID);
                }
            }
        }
        /// <summary>
        /// Process any buffered messages separated by '\n'
        /// Then inform the view
        /// </summary>
        /// <param name="state"></param>
        private void ProcessMessages(SocketState state)
        {
            string totalData = state.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            // Loop until we have processed all messages.
            foreach (string p in parts)
            {
                // Ignore empty strings added by the regex splitter
                if (p.Length == 0)
                {
                    continue;
                }

                // Ignore incomplete messages
                if (p[p.Length - 1] != '\n')
                {
                    break;
                }

                // If the string contains text, try to parse it as json
                ParseMessage(p);

                // Then remove it from the SocketState's growable buffer
                state.RemoveData(0, p.Length);
            }
        }
示例#3
0
        /// <summary>
        /// Process any buffered messages separated by '\n'
        /// Display them, then remove them from the buffer.
        /// </summary>
        /// <param name="state"></param>
        private void ProcessMessages(SocketState state)
        {
            string totalData = state.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            // Loop until we have processed all messages.
            // We may have received more than one.

            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;
                }

                // Display the message
                // "messages" is the big message text box in the form.
                // We must use a MethodInvoker, because only the thread
                // that created the GUI can modify it.
                this.Invoke(new MethodInvoker(
                                () => messages.AppendText(p + Environment.NewLine)));

                // Then remove it from the SocketState's growable buffer
                state.RemoveData(0, p.Length);
            }
        }
        /// <summary>
        /// Process any buffered messages separated by '\n'
        /// Display them, then remove them from the buffer.
        /// </summary>
        /// <param name="state"></param>
        private void ProcessMessages(SocketState state)
        {
            string totalData = state.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");
            // Loop until we have processed all messages.
            foreach (string p in parts)
            {
                // Ignore empty strings
                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;
                }

                // Then remove it from the SocketState's growable buffer
                state.RemoveData(0, p.Length);

                //checks JSONstring and determines if its a tank, wall, proj, or powerup
                UpdateArrived(p);
            }
            //display the new inputs
            InputArrived();
        }
示例#5
0
        /// <summary>
        /// Callback for ReceivePlayerName to handle incoming requests.
        /// Parses the JSON requests.  This method uses the same logic as ClientSide handshake
        /// of Processing Messages, but instead of loading in objects we use the given information to
        /// update our tank with the ControlCommand. For incorrect commands that did not parse, we
        /// ignore the request.
        /// </summary>
        /// <param name="state"></param>
        private void HandleRequests(SocketState state)
        {
            if (state.ErrorOccured)
            {
                lock (serverWorld)
                {
                    RemoveClient(state.ID);
                    serverWorld.GetTank(state.ID).disconnected = true;

                    return;
                }
            }

            lock (state)
            {
                string   totalData = state.GetData();
                string[] parts     = Regex.Split(totalData, @"(?<=[\n])");

                // Loop until we have processed all messages.
                foreach (string p in parts)
                {
                    // Ignore empty strings added by the regex splitter
                    if (p.Length == 0)
                    {
                        continue;
                    }

                    // Ignoring strings with no newline
                    if (p[p.Length - 1] != '\n')
                    {
                        break;
                    }

                    // Skipping incomplete JSONS
                    if (p[0] != '{' || !p.EndsWith("\n"))
                    {
                        continue;
                    }

                    // Process the command, update the tank w/ this client ID
                    try
                    {
                        ControlCommand command = JsonConvert.DeserializeObject <ControlCommand>(p);

                        serverWorld.SetMoveTank(command, state.ID);
                        serverWorld.RotateTurret(command, state.ID);
                        serverWorld.FireTurret(command, state.ID);
                    }

                    catch
                    { /*command did not parse correctly; ignore*/ }

                    //Remove data from the SocketState's growable buffer
                    state.RemoveData(0, p.Length);
                }

                Networking.GetData(state);
            }
        }
示例#6
0
        /// <summary>
        /// Callback to receive player name.
        /// </summary>
        /// <param name="state"></param>
        private void ReceivePlayerName(SocketState state)
        {
            // If a Socket disconnects, return.
            if (state.ErrorOccured)
            {
                return;
            }

            // Add tank to the world if it doesnt exist yet
            if (!clients.ContainsKey(state.ID))
            {
                lock (serverWorld)
                {
                    serverWorld.AddTank(state.ID, state.GetData());
                }
            }

            state.OnNetworkAction = HandleRequests;

            // Send start-up info; Lock the socket to avoid race conditions
            lock (state.TheSocket)
            {
                if (!clients.ContainsKey(state.ID))
                {
                    Networking.Send(state.TheSocket, $"{ state.ID }\n{ WORLD_SIZE }\n");
                    Networking.Send(state.TheSocket, serverWorld.GetWalls() + "\n");
                }
            }

            // Add client to clients list
            lock (clients)
            {
                if (!clients.ContainsKey(state.ID))
                {
                    clients.Add(state.ID, state);
                    Console.WriteLine($"Player({ state.ID }): { state.GetData().TrimEnd('\n') } Has Joined The Game!");
                }
            }

            Networking.GetData(state);
        }
示例#7
0
        private static void HandleClientRequests(SocketState state)
        {
            if (state.ErrorOccurred)
            {
                return;
            }
            string[] request = state.GetData().Split(' ')[1].Substring(1).Split(':');
            string   command = request[0];

            string[] args = request.Length == 2 ? request[1].Split(',') : new string[0];
            Execute(state.Socket, command, args);
        }
        private void HandleIDandWorldSize(SocketState state)
        {
            if (state.ErrorOccured)
            {
                // inform the view
                Error("Lost connection to server");
                return;
            }
            string totalData = state.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            // Checks to ensure both the userID and the worldSize have been received
            if (parts.Length < 3)
            {
                Networking.GetData(state);
                return;
            }

            //Removes the used data from the buffer
            state.RemoveData(0, parts[0].Length + parts[1].Length);

            // try to parse the first message as the user's ID
            string id = parts[0];

            if (!(Int32.TryParse(id, out userID)))
            {
                Error("First message sent be server was not the players ID");
                return;
            }

            // try to parse the second message as the world size
            string size      = parts[1];
            int    worldSize = -1;

            if (!(Int32.TryParse(size, out worldSize)))
            {
                worldSize = -1;
                Error("Failed to receive wallsize");
                return;
            }

            //creates a new world
            world = new World(worldSize);
            world.AddAnimation += HandleAnimation;

            // prepares to handle the next messages as walls
            state.OnNetworkAction = HandleWalls;

            Networking.GetData(state);
        }
示例#9
0
        protected void OnNetworkAction(SocketState state)
        {
            if (state.ErrorOccurred)
            {
                OnDisconnected?.Invoke(this);
                return;
            }

            string data = state.GetData();

            OnReceived?.Invoke(this, data);
            state.RemoveData(0, data.Length);
            Networking.GetData(state);
        }
示例#10
0
        /// <summary>
        /// This handles the HTTP request and makes the web page depending on the request
        /// </summary>
        /// <param name="ss">Socket state for the connection</param>
        public static void ServeHttpRequest(SocketState ss)
        {
            if (ss.ErrorOccured == true)
            {
                Console.WriteLine("Error occured while accepting: \"" + ss.ErrorMessage + "\"");
                return;
            }

            string request = ss.GetData();

            Console.WriteLine(request);

            //Player request
            if (request.Contains("GET /games?player="))
            {
                //Finds the player name with substring
                int    start  = request.IndexOf("=") + 1;
                int    length = request.IndexOf(" HTTP/1.1") - start;
                string name   = request.Substring(start, length);

                //Gets all of the players in the form of a dictionary
                Dictionary <uint, PlayerModel> playersDictionary = DatabaseController.GetAllPlayerGames(name);

                //Creates list of sessions that the player has been in by getting the game durations from the database
                List <SessionModel> SessionList = new List <SessionModel>();
                foreach (KeyValuePair <uint, PlayerModel> player in playersDictionary)
                {
                    SessionList.Add(new SessionModel(player.Key, DatabaseController.GetGameDuration(player.Key), player.Value.Score, player.Value.Accuracy));
                }

                //Sends the list so it can be formatted into a table
                Networking.SendAndClose(ss.TheSocket, WebViews.GetPlayerGames(name, SessionList));
            }
            //Games request
            else if (request.Contains("GET /games HTTP/1.1"))
            {
                //Creates a table with each of the games and all of their data
                Networking.SendAndClose(ss.TheSocket, WebViews.GetAllGames(DatabaseController.GetAllGames()));
            }
            //If there aren't any slashes it goes to the home page
            else if (request.Contains("GET / HTTP/1.1"))
            {
                Networking.SendAndClose(ss.TheSocket, WebViews.GetHomePage(0));
            }
            //Otherwise it throws a 404 error
            else
            {
                Networking.SendAndClose(ss.TheSocket, WebViews.Get404());
            }
        }
示例#11
0
        public void TestNoEventLoop(bool clientSide)
        {
            SetupTestConnections(clientSide, out testListener, out testLocalSocketState, out testRemoteSocketState, 2115);

            int calledCount = 0;

            // This OnNetworkAction will not ask for more data after receiving one message,
            // so it should only ever receive one message
            testLocalSocketState.OnNetworkAction = (x) => calledCount++;

            Networking.Send(testRemoteSocketState.TheSocket, "a");
            Networking.GetData(testLocalSocketState);
            // Note that waiting for data like this is *NOT* how the networking library is
            // intended to be used. This is only for testing purposes.
            // Normally, you would provide an OnNetworkAction that handles the data.
            NetworkTestHelper.WaitForOrTimeout(() => testLocalSocketState.GetData().Length > 0, NetworkTestHelper.timeout);

            // Send a second message (which should not increment calledCount)
            Networking.Send(testRemoteSocketState.TheSocket, "a");
            NetworkTestHelper.WaitForOrTimeout(() => false, NetworkTestHelper.timeout);

            Assert.AreEqual(1, calledCount);
        }
示例#12
0
        private static void ServeHttpRequest(SocketState state)
        {
            StringBuilder sb   = new StringBuilder();
            string        data = state.GetData();

            state.ClearData();
            if (String.IsNullOrEmpty(data))
            {
                Networking.GetData(state);
                return;
            }

            if (data.Contains("GET"))
            {
                Networking.SendAndClose(state.TheSocket, DatabaseModel.GetHomePage(0) + DatabaseModel.GetAllGames(DatabaseModel.GetGamesFromDB()));
            }
        }
示例#13
0
        private void HandleWalls(SocketState state)
        {
            if (state.ErrorOccured)
            {
                // inform the view
                Error("Lost connection to server");
                return;
            }

            string totalData = state.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            // Add all wall json
            foreach (string s in parts)
            {
                if (s != "")
                {
                    if (s[s.Length - 1] != '\n')
                    {
                        break;
                    }

                    JObject obj = JObject.Parse(s);
                    JToken  token;

                    // if the json is a valid wall, set it
                    if ((token = obj["wall"]) != null)
                    {
                        lock (world) {
                            world.setWall(JsonConvert.DeserializeObject <Wall>(s));
                        }
                    }

                    // if all the walls have been sent and now a new object is sent (that is not a wall), the client can now send commands
                    else
                    {
                        commandControl = new CommandControl();
                        AllowInput();
                        state.OnNetworkAction = ReceiveMessage;
                    }
                }
            }
            Networking.GetData(state);
        }
示例#14
0
        /// <summary>
        /// Handles all client sent commands and updates their tank accordingly so that it can be processed on the next frame
        /// </summary>
        /// <param name="s"></param>
        private void HandleClientCommands(SocketState s)
        {
            // Handle errors
            if (s.ErrorOccured)
            {
                Console.WriteLine("Client: " + s.ID + " disconnected.");
                lock (world) {
                    world.Players[(int)s.ID].disconnected = true;
                }
                return;
            }

            string data = s.GetData();

            string[] parts = Regex.Split(data, @"(?<=[\n])");

            // Try to deserialize messages as valid commands
            if (parts.Length > 2)
            {
                try {
                    CommandControl cc = JsonConvert.DeserializeObject <CommandControl>(parts[parts.Length - 2]);

                    // Remove all processed data
                    for (int i = 0; i < parts.Length - 1; i++)
                    {
                        s.RemoveData(0, parts[i].Length);
                    }

                    // Update the client's command control object
                    clients[s].commandControl = cc;
                }
                // Disconnect client if invalid commands are received
                catch {
                    Console.WriteLine("Client: " + s.ID + " disconnected.");
                    lock (world) {
                        world.Players[(int)s.ID].disconnected = true;
                    }
                    return;
                }
            }
            // loop
            Networking.GetData(s);
        }
示例#15
0
        /// <summary>
        /// when data arrives from clients update the world
        /// </summary>
        /// <param name="state"></param>
        public void UpdateWorld(SocketState state)
        {
            string data = state.GetData();

            string[] parts = Regex.Split(data, @"(?<=[\n])");
            state.ClearData();
            foreach (string p in parts)
            {
                if (p.Length == 0)
                {
                    continue;
                }
                if (p[p.Length - 1] != '\n')
                {
                    break;
                }
                UpdateArrived(p, state);
            }
        }
示例#16
0
        /// <summary>
        /// Callback method for after the server receives the name
        /// </summary>
        /// <param name="sock"></param>
        static void ReceiveName(SocketState sock)
        {
            //Create the players tank and assign its name and ID
            Tank mainPlayer = new Tank();

            mainPlayer.name = sock.GetData().Trim();
            mainPlayer.ID   = (int)sock.ID;

            //Add the tank to both tank classes
            lock (tanks)
            {
                allTanksEver.Add(mainPlayer.ID, mainPlayer);
                tanks.Add(mainPlayer.ID, mainPlayer);
            }

            //Assign the health of the tank and spawn the tank
            mainPlayer.hitPoints = StartingHitPoints;
            tankRespawn(mainPlayer);

            //Change the callback to CommandRequestHandler and clear the sock's data
            sock.OnNetworkAction = CommandRequestHandler;
            sock.ClearData();

            //Get the startup data, serialize it, and send it to the client
            string startupData = mainPlayer.ID + "\n" + serverWorld.worldSize + "\n";

            foreach (Wall w in walls.Values)
            {
                startupData += JsonConvert.SerializeObject(w) + "\n";
            }
            startupData += GetWorldData();
            Networking.Send(sock.TheSocket, startupData);

            //Add the client to the connectedClients list and ask for more data
            lock (connectedClients)
            {
                connectedClients.Add(sock.ID, sock);
            }
            Console.WriteLine(mainPlayer.name + " has Joined the Game");
            mainPlayer.joined = true;
            Networking.GetData(sock);
        }
示例#17
0
        // Helper to simualte "processing" a message by looking for a newline separator
        void ProcessMessage(SocketState state, StringBuilder clientReceived)
        {
            string[] objects = Regex.Split(state.GetData(), @"(?<=[\n])");

            foreach (string obj in objects)
            {
                if (obj.Length == 0)
                {
                    continue;
                }

                if (obj[obj.Length - 1] != '\n')
                {
                    continue;
                }

                clientReceived.Append(obj);
                state.RemoveData(0, obj.Length);
            }
        }
示例#18
0
        /// <summary>
        ///     Called when server sends all spreadsheet names.
        /// </summary>
        /// <param name="state"></param>
        private void ReceiveSpreadsheets(SocketState state)
        {
            if (state.ErrorOccured)
            {
                // inform the view
                Error?.Invoke(state.ErrorMessage, "Error Receiving Spreadsheets");
                Disconnect();
                return;
            }

            string data = state.GetData();

            if (!data.EndsWith("\n\n"))
            {
                Networking.GetData(state);
                return;
            }

            string[] spreadSheetNames = data.Substring(0, data.Length - 2).Split('\n');
            GetSpreadsheets?.Invoke(spreadSheetNames.Where(sheet => !string.IsNullOrEmpty(sheet)).ToArray());
        }
示例#19
0
        public void GetData_SocketIsAlreadyClosedSoBeginReceiveWillFail_ShouldSetErrorSocketStateAndInvokeToCallDelegate(bool clientSide)
        {
            bool isCalled       = false;
            int  numTimesCalled = 0;

            void saveClientState(SocketState x)
            {
                isCalled = true;
                numTimesCalled++;
                testLocalSocketState = x;
            }

            testLocalSocketState = new SocketState(saveClientState, null);

            Networking.GetData(testLocalSocketState);
            NetworkTestHelper.WaitForOrTimeout(() => isCalled, NetworkTestHelper.timeout);

            Assert.AreEqual(1, numTimesCalled);
            Assert.IsTrue(testLocalSocketState.ErrorOccured);
            Assert.AreEqual("", testLocalSocketState.GetData());
        }
示例#20
0
        /// <summary>
        /// Gets the player's name and sends startup info
        /// </summary>
        /// <param name="s"></param>
        private void HandlePlayerName(SocketState s)
        {
            string data = s.GetData();

            string[] parts = Regex.Split(data, @"(?<=[\n])");

            // Check if a full message has been received
            if (parts.Length > 1)
            {
                // Generate a new tank for the client
                Tank t = new Tank((int)s.ID, parts[0].Substring(0, parts[0].Length - 1), new TankWars.Vector2D(50, 50));
                spawnTank(t);

                lock (world) {
                    // Add the tank to the world
                    world.setTankData(t);
                    s.RemoveData(0, parts[0].Length);

                    //Send the player's id
                    Networking.Send(s.TheSocket, s.ID + "\n");

                    // Send world size
                    Networking.Send(s.TheSocket, world.UniverseSize + "\n");

                    // Send all the walls
                    foreach (Wall w in world.Walls.Values)
                    {
                        Networking.Send(s.TheSocket, JsonConvert.SerializeObject(w) + '\n');
                    }
                }

                // Add the tank to the dictionary so it can start receiving frames
                lock (clients) {
                    clients.Add(s, t);
                }
                s.OnNetworkAction = HandleClientCommands;
            }
            Networking.GetData(s);
        }
示例#21
0
        /// <summary>
        /// Second callback method for after the server has made a connection
        /// </summary>
        /// <param name="state"></param>
        private static void ServeHttpRequest(SocketState state)
        {
            string request = state.GetData();

            //If the request is for an individual player, create their table
            if (request.Contains("GET /games?player="))
            {
                String playerNameRequest = request.Substring(21, request.IndexOf("\n") - 34);
                String dataToSend        = mainDataControl.individualTableCreator(playerNameRequest);
                Networking.SendAndClose(state.TheSocket, dataToSend);
            }
            //If the request is for all games, generate all the tables
            else if (request.Contains("GET /games"))
            {
                String dataToSend = mainDataControl.allGamesTableCreator();
                Networking.SendAndClose(state.TheSocket, dataToSend);
            }
            //If the request is for anything else, send them to the homepage
            else
            {
                Networking.SendAndClose(state.TheSocket, mainDataControl.sendToHomePage());
            }
        }
示例#22
0
        public void SendAndClose_SendTinyMessage_ShouldPutDataInSocketStateAndCloseSocket(bool clientSide)
        {
            // assemble
            SetupTestConnections(clientSide, out testListener, out testLocalSocketState, out testRemoteSocketState);
            testLocalSocketState.OnNetworkAction  = x => { };
            testRemoteSocketState.OnNetworkAction = x => { };
            bool sendWasSuccessful;

            // act
            sendWasSuccessful = Networking.SendAndClose(testLocalSocketState.TheSocket, "abc");
            Networking.GetData(testRemoteSocketState);
            NetworkTestHelper.WaitForOrTimeout(() => testRemoteSocketState.GetData().Length > 0, NetworkTestHelper.timeout);

            // assert
            Assert.IsTrue(sendWasSuccessful);
            Assert.AreEqual("abc", testRemoteSocketState.GetData());
            Assert.IsFalse(testLocalSocketState.TheSocket.Connected);
        }
示例#23
0
        public void TestReceiveTinyMessage(bool clientSide)
        {
            SetupTestConnections(clientSide);

            testLocalSocketState.OnNetworkAction = (x) => { };

            Networking.Send(testRemoteSocketState.TheSocket, "a");

            Networking.GetData(testLocalSocketState);
            WaitForOrTimeout(() => testLocalSocketState.GetData().Length > 0, timeout);

            Assert.AreEqual("a", testLocalSocketState.GetData());
        }
示例#24
0
        /// <summary>
        /// Callback method for any commands the player sends to the controller
        /// </summary>
        /// <param name="sock">The socketstate the connection is on</param>
        static void CommandRequestHandler(SocketState sock)
        {
            Tank main;

            //If the tank is not currently connected, don't listen to any commands from that client
            if (tanks.ContainsKey((int)sock.ID))
            {
                main = tanks[(int)sock.ID];
            }
            else
            {
                return;
            }

            // Split the command by its \n's
            string[] commands = Regex.Split(sock.GetData(), @"(?<=[\n])");
            if (commands.Length == 1)
            {
                return;
            }

            //Deserialize the command
            ControllerObject command = JsonConvert.DeserializeObject <ControllerObject>(commands[commands.Length - 2]);

            //If there is nothing in command then ignore it
            if (command == null)
            {
                return;
            }

            //If the tank is currently alive and has made it this far, listen to its commands
            if (main.hitPoints != 0)
            {
                //Process the fire status of the tank and either fire a projectile, beam, or do nothing
                switch (command.getFireStatus())
                {
                case "none":
                    break;

                case "main":
                    if (main.shotTimer > 0)
                    {
                        break;
                    }
                    Projectile shot = new Projectile();
                    main.tankTotalShots++;
                    shot.orientation = main.aiming;
                    shot.location    = main.location;
                    shot.tankID      = main.ID;
                    shot.ID          = shotCount;
                    shotCount++;
                    lock (projectiles)
                    {
                        projectiles.Add(shot.ID, shot);
                    }
                    main.shotTimer = FramesPerShot;
                    break;

                case "alt":
                    if (main.railgunShots > 0)
                    {
                        main.railgunShots--;
                        Beam railBeam = new Beam();
                        main.tankTotalShots++;
                        railBeam.direction = main.aiming;
                        railBeam.origin    = main.location;
                        railBeam.tankID    = main.ID;
                        railBeam.ID        = shotCount;
                        lock (beams)
                        {
                            beams.Add(railBeam.ID, railBeam);
                        }
                        shotCount++;
                    }

                    break;
                }

                //Variables used to track where the tank will be after the command is implemented
                double tankLocAfterMoveY;
                double tankLocAfterMoveX;

                //Process the tank's move command and update it's location based on the button that was pressed
                switch (command.getMoveDirection())
                {
                case "none":
                    main.tankVelocity = new Vector2D(0, 0);
                    break;

                case "up":
                    main.tankVelocity = new Vector2D(0, -EngineStrength);
                    tankLocAfterMoveY = main.location.GetY() + main.tankVelocity.GetY();
                    tankLocAfterMoveX = main.location.GetX() + main.tankVelocity.GetX();

                    //If the tank will hit a wall with this move, don't move it
                    if (collisionCheck(tankLocAfterMoveX, tankLocAfterMoveY))
                    {
                        main.tankVelocity = new Vector2D(0, 0);
                    }
                    //If the tank is at the edge of the world after this move, teleport it to the other side
                    else if (tankLocAfterMoveY < -serverWorld.worldSize / 2)
                    {
                        tankLocAfterMoveY = serverWorld.worldSize / 2 - 5;
                        main.location     = new Vector2D(main.location.GetX(), tankLocAfterMoveY);
                        main.orientation  = new Vector2D(0, -1);
                    }
                    //If the tank won't hit a wall or the edge, move it
                    else
                    {
                        main.location    = main.location + main.tankVelocity;
                        main.orientation = new Vector2D(0, -1);
                    }
                    break;

                case "down":
                    main.tankVelocity = new Vector2D(0, EngineStrength);
                    tankLocAfterMoveY = main.location.GetY() + main.tankVelocity.GetY();
                    tankLocAfterMoveX = main.location.GetX() + main.tankVelocity.GetX();

                    //If the tank will hit a wall with this move, don't move it
                    if (collisionCheck(tankLocAfterMoveX, tankLocAfterMoveY))
                    {
                        main.tankVelocity = new Vector2D(0, 0);
                    }
                    //If the tank is at the edge of the world after this move, teleport it to the other side
                    else if (tankLocAfterMoveY > serverWorld.worldSize / 2)
                    {
                        tankLocAfterMoveY = -serverWorld.worldSize / 2 + 5;
                        main.location     = new Vector2D(main.location.GetX(), tankLocAfterMoveY);
                        main.orientation  = new Vector2D(0, 1);
                    }
                    //If the tank won't hit a wall or the edge, move it
                    else
                    {
                        main.location    = main.location + main.tankVelocity;
                        main.orientation = new Vector2D(0, 1);
                    }
                    break;

                case "left":
                    main.tankVelocity = new Vector2D(-EngineStrength, 0);
                    tankLocAfterMoveY = main.location.GetY() + main.tankVelocity.GetY();
                    tankLocAfterMoveX = main.location.GetX() + main.tankVelocity.GetX();

                    //If the tank will hit a wall with this move, don't move it
                    if (collisionCheck(tankLocAfterMoveX, tankLocAfterMoveY))
                    {
                        main.tankVelocity = new Vector2D(0, 0);
                    }
                    //If the tank is at the edge of the world after this move, teleport it to the other side
                    else if (tankLocAfterMoveX < -serverWorld.worldSize / 2)
                    {
                        tankLocAfterMoveX = serverWorld.worldSize / 2 - 5;
                        main.location     = new Vector2D(tankLocAfterMoveX, main.location.GetY());
                        main.orientation  = new Vector2D(-1, 0);
                    }
                    //If the tank won't hit a wall or the edge, move it
                    else
                    {
                        main.location    = main.location + main.tankVelocity;
                        main.orientation = new Vector2D(-1, 0);
                    }
                    break;

                case "right":
                    main.tankVelocity = new Vector2D(EngineStrength, 0);
                    tankLocAfterMoveY = main.location.GetY() + main.tankVelocity.GetY();
                    tankLocAfterMoveX = main.location.GetX() + main.tankVelocity.GetX();

                    //If the tank will hit a wall with this move, don't move it
                    if (collisionCheck(tankLocAfterMoveX, tankLocAfterMoveY))
                    {
                        main.tankVelocity = new Vector2D(0, 0);
                    }
                    //If the tank is at the edge of the world after this move, teleport it to the other side
                    else if (tankLocAfterMoveX > serverWorld.worldSize / 2)
                    {
                        tankLocAfterMoveX = -serverWorld.worldSize / 2 + 5;
                        main.location     = new Vector2D(tankLocAfterMoveX, main.location.GetY());
                        main.orientation  = new Vector2D(1, 0);
                    }
                    //If the tank won't hit a wall or the edge, move it
                    else
                    {
                        main.location    = main.location + main.tankVelocity;
                        main.orientation = new Vector2D(1, 0);
                    }
                    break;
                }
                //Aim the turret the direction it should be facing
                main.aiming = command.getTurretDirection();
            }

            //Remove the data that has been processed and ask for more data
            sock.RemoveData(0, sock.GetData().Length);
            Networking.GetData(sock);
        }
示例#25
0
        /// <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);
        }
示例#26
0
        public void TestMyOwn()
        {
            // List to represents connections
            List <SocketState> server = new List <SocketState>();

            void SaveServer(SocketState s)
            {
                lock (this)
                {
                    server.Add(s);
                }
            }

            //Two clients
            SocketState client_1 = null;

            void SaveClient_1(SocketState s)
            {
                client_1 = s;
            }

            SocketState client_2 = null;

            void SaveClient_2(SocketState s)
            {
                client_2 = s;
            }

            // Starting a server
            TcpListener listener = Networking.StartServer(SaveServer, 2112);

            // Client1 Connect to the server
            Networking.ConnectToServer(SaveClient_1, "localhost", 2112);

            // Client2 Connect to the server
            Networking.ConnectToServer(SaveClient_2, "localhost", 2112);

            // Make sure this line is what you want to it behave
            NetworkTestHelper.WaitForOrTimeout(() => (client_2 != null) && (client_1 != null) && (server.Count == 2), NetworkTestHelper.timeout);

            // Set the action to do nothing
            foreach (SocketState state in server)
            {
                state.OnNetworkAction = x => { };
            }

            client_1.OnNetworkAction = x => { };
            client_2.OnNetworkAction = x => { };

            foreach (SocketState state in server)
            {
                Networking.SendAndClose(state.TheSocket, "a");
            }

            Networking.GetData(client_1);
            Networking.GetData(client_2);


            // Note that waiting for data like this is *NOT* how the networking library is
            // intended to be used. This is only for testing purposes.
            // Normally, you would provide an OnNetworkAction that handles the data.
            NetworkTestHelper.WaitForOrTimeout(() => client_1.GetData().Length > 0 && client_2.GetData().Length > 0, NetworkTestHelper.timeout);

            Assert.AreEqual("a", client_1.GetData());
            Assert.AreEqual("a", client_2.GetData());

            //Make sure everything close and stop properly
            listener.Stop();
            foreach (SocketState state in server)
            {
                state.TheSocket.Close();
            }
            client_1.TheSocket.Close();
            client_2.TheSocket.Close();
        }
示例#27
0
        /// <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);
        }
示例#28
0
        //Method used to process the messages
        public void ProcessMessages(SocketState sock)
        {
            //Get the data and split it around \n
            string totalData = sock.GetData();

            string[] parts = Regex.Split(totalData, @"(?<=[\n])");

            int i = 1;

            // For every string, find out what it is and then deserialize it.
            foreach (string s in parts)
            {
                totalData = totalData.Substring(s.Length, totalData.Length - s.Length);

                //If it doesn't end with\n, it is incomplete data
                if (!s.EndsWith("\n"))
                {
                    break;
                }
                //If this is the first frame, then the first thing being sent is the playerID
                else if (i == 1 && Constants.firstFrame)
                {
                    Constants.playerID = int.Parse(s);
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    i++;
                    Constants.firstFrame = false;
                }
                //If this is the second bit of data being processed, then this is the worldsize
                else if (i == 2)
                {
                    Constants.worldSize = int.Parse(s);
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    i++;
                }
                //If s contains a wall, then deserialize it and add it to the walls dictionary
                else if (s.Contains("wall"))
                {
                    Wall newWall = JsonConvert.DeserializeObject <Wall>(s);
                    Constants.walls.Add(newWall.ID, newWall);
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    Constants.wallsRec = true;
                }
                //If s is a beam, then deserialize it and add it to the beams dictionary or update it
                else if (s.Contains("beam"))
                {
                    Beam newBeam = JsonConvert.DeserializeObject <Beam>(s);
                    if (Constants.beams.ContainsKey(newBeam.ID))
                    {
                        Constants.beams.Remove(newBeam.ID);
                        Constants.beams.Add(newBeam.ID, newBeam);
                    }
                    else
                    {
                        Constants.beams.Add(newBeam.ID, newBeam);
                    }
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    continue;
                }
                //If s is a tank, then deserialize it and update all of the tank's data.
                //If this is a new tank, then determine its color as well
                else if (s.Contains("tank"))
                {
                    Tank newTank = JsonConvert.DeserializeObject <Tank>(s);
                    if (Constants.tanks.ContainsKey(newTank.ID))
                    {
                        Constants.tanks[newTank.ID].hitPoints   = newTank.hitPoints;
                        Constants.tanks[newTank.ID].died        = newTank.died;
                        Constants.tanks[newTank.ID].location    = newTank.location;
                        Constants.tanks[newTank.ID].orientation = newTank.orientation;
                        Constants.tanks[newTank.ID].aiming      = newTank.aiming;
                        Constants.tanks[newTank.ID].score       = newTank.score;
                    }
                    else
                    {
                        switch ((Constants.tanks.Keys.Count) % 8)
                        {
                        case 0:
                            newTank.color = "blue";
                            break;

                        case 1:
                            newTank.color = "dark";
                            break;

                        case 2:
                            newTank.color = "green";
                            break;

                        case 3:
                            newTank.color = "lightGreen";
                            break;

                        case 4:
                            newTank.color = "orange";
                            break;

                        case 5:
                            newTank.color = "purple";
                            break;

                        case 6:
                            newTank.color = "red";
                            break;

                        case 7:
                            newTank.color = "yellow";
                            break;
                        }
                        Constants.tanks.Add(newTank.ID, newTank);
                    }
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    continue;
                }
                //If s is a powerup, then deserialize it and add it to the powerups dictionary
                else if (s.Contains("power"))
                {
                    Powerup newPowerup = JsonConvert.DeserializeObject <Powerup>(s);
                    if (Constants.powerups.ContainsKey(newPowerup.ID))
                    {
                        Constants.powerups[newPowerup.ID].location = newPowerup.location;
                        Constants.powerups[newPowerup.ID].died     = newPowerup.died;
                    }
                    else
                    {
                        Constants.powerups.Add(newPowerup.ID, newPowerup);
                    }
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    continue;
                }
                //If s is a projectile, then deserialize it and add it to the projectiles dictionary
                else if (s.Contains("proj"))
                {
                    Projectile newProj = JsonConvert.DeserializeObject <Projectile>(s);
                    if (Constants.projectiles.ContainsKey(newProj.ID))
                    {
                        Constants.projectiles[newProj.ID].location = newProj.location;
                        Constants.projectiles[newProj.ID].died     = newProj.died;
                    }
                    else
                    {
                        Constants.projectiles.Add(newProj.ID, newProj);
                    }
                    sock.RemoveData(0, sock.GetData().Length - totalData.Length);
                    continue;
                }
            }
        }
示例#29
0
        /// <summary>
        ///     Receives messages from server and handles them
        /// </summary>
        /// <param name="state"></param>
        private void ReceiveUpdatesLoop(SocketState state)
        {
            if (state.ErrorOccured)
            {
                // inform the view
                Error?.Invoke(state.ErrorMessage, "Error In Event Loop");
                Disconnect();
                return;
            }

            string incomingMessages = state.GetData();

            string[] data = Regex.Split(incomingMessages, @"(?<=[\n])");

            foreach (string message in data.Where(message => message.Length != 0))
            {
                //Last Step of handshake if message is the id
                if (int.TryParse(message, out int i))
                {
                    IDReceive?.Invoke(i);
                    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 (message.Last() != '\n' || message[0] != '{')
                {
                    continue;
                }

                Console.WriteLine("Received:" + message);

                //Parse message as json object
                var x = JObject.Parse(message);
                switch (x["messageType"]?.ToString())
                {
                case "cellUpdated":
                {
                    if (EditCell is null)
                    {
                        continue;
                    }
                    var updated = JsonConvert.DeserializeObject <CellUpdated>(message);
                    EditCell.Invoke(updated);
                    break;
                }

                case "cellSelected":
                {
                    if (SelectCell is null)
                    {
                        continue;
                    }
                    var selected = JsonConvert.DeserializeObject <CellSelected>(message);
                    SelectCell.Invoke(selected);
                    break;
                }

                case "serverError":
                {
                    if (ServerShutdown is null)
                    {
                        continue;
                    }
                    var error = JsonConvert.DeserializeObject <ServerShutdownError>(message);
                    ServerShutdown.Invoke(error);
                    break;
                }

                case "requestError":
                {
                    if (RequestError is null)
                    {
                        continue;
                    }
                    var error = JsonConvert.DeserializeObject <RequestError>(message);
                    RequestError.Invoke(error);
                    break;
                }

                case "disconnected":
                {
                    var d = JsonConvert.DeserializeObject <Disconnected>(message);
                    ClientDisconnected?.Invoke(d);
                    break;
                }
                }

                state.RemoveData(0, message.Length);
            }

            Networking.GetData(state);
        }