예제 #1
0
        //async method for connecting to clients
        public static void connect(IAsyncResult ar)
        {
            //connection finished, allow others to connect
            connectionFound.Set();

            Console.WriteLine("\nPlayer connected");
            //hold data about the incoming request
            WaitConnection wait;

            byte[] guid = new byte[16];
            Guid   battleGUID;

            //tell player which spawn to use
            byte[] spawn = new byte[1];
            //stores items for communications
            BattleState state = new BattleState();

            //get socket for client
            Socket listener = (Socket)ar.AsyncState;
            Socket handler  = listener.EndAccept(ar);

            try
            {
                byte[] id = new byte[16];
                handler.Receive(id, 16, 0);
                state.ClientID = new Guid(id);
            }
            //separate try catches so second portion not hit until clientid set
            catch (Exception)
            {
                try
                {
                    //try to cleanly close connection
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
                catch (Exception) { }
            }

            try
            {
                //retrieve player level from the db and use to create player stats
                state.ClientStats = new PlayerStats(new DatabaseConnect().getPlayerLevel(state.ClientID));
                Console.WriteLine(new DatabaseConnect().getPlayerLevel(state.ClientID));

                ClientState addSocket;
                lock (ConnectedPlayers.DICTIONARY_LOCK)
                {
                    if (ConnectedPlayers.playerDetails.TryGetValue(state.ClientID, out addSocket))
                    {
                        addSocket.BattleSocket = handler;
                    }
                    else
                    {
                        addSocket = new ClientState(null, null, handler, null);
                        ConnectedPlayers.playerDetails.Add(state.ClientID, addSocket);
                    }
                }


                //read the battle guid from the client
                handler.Receive(guid, 16, 0);
                battleGUID = new Guid(guid);

                bool inDict;

                //get exclusive access to waiting
                lock (DICT_LOCK)
                {
                    //check if battle guid is already in disctionary, and save the value to wait if it is
                    //that is, check if this is the first client to connect to the battle
                    inDict = waiting.TryGetValue(battleGUID, out wait);
                    //if this is the first player, add the guid to the dictionary with a waitconnection object holding this client's socket
                    if (!inDict)
                    {
                        wait           = new WaitConnection(handler, state.ClientStats);
                        wait.WriteLock = new object();
                        wait.StatsLock = new object();
                        waiting.Add(battleGUID, wait);
                    }
                }
                //if this is the second client to connect
                if (inDict)
                {
                    //set second socket to this client's socket
                    wait.Socket2 = handler;
                    wait.P2      = state.ClientStats;
                    //set this client's opponent to the first client in wait
                    state.OpponentSocket = wait.Socket1;
                    state.OpponentStats  = wait.P1;
                    state.WriteLock      = wait.WriteLock;
                    state.StatsLock      = wait.StatsLock;
                    //set event indicating both clients are connected
                    wait.setWait();
                    //indicate to client to spawn at second location
                    spawn[0] = 1;
                }
                else
                {
                    //add some sort of timeout?
                    //wait until second client connects
                    if (!wait.Wait.Wait(5000))
                    {
                        //remove from waiting list, and throw exception so connection cleaned up
                        waiting.Remove(battleGUID);
                        throw new Exception("Timeout");
                    }
                    //pass lock to both clients for writing to each others socket
                    state.WriteLock = wait.WriteLock;
                    state.StatsLock = wait.StatsLock;
                    //set this client's opponent to the second client in wait
                    state.OpponentSocket = wait.Socket2;
                    state.OpponentStats  = wait.P2;
                    //both clients are connected, remove from waiting
                    //maybe move this later so players can reconnect
                    waiting.Remove(battleGUID);
                    //indicate to client to spawn at first location;
                    spawn[0] = 0;
                }

                //set client's socket in state object
                state.ClientSocket = handler;
                //initialize buffer
                state.Update = new byte[UPDATE_SIZE];
                //lock write operations on the socket
                lock (state.WriteLock)
                {
                    byte[] opponentLevel = new byte[1];
                    opponentLevel[0] = (byte)((state.OpponentStats.MaxHP - 100) / 21);
                    handler.Send(opponentLevel, 1, 0);
                    //tell the client where to spawn
                    handler.Send(spawn, 1, 0);
                }
                //start receiving client updates
                handler.BeginReceive(state.Update, 0, UPDATE_SIZE, 0, new AsyncCallback(readUpdate), state);
            }
            //catch connection errors
            catch (Exception)
            {
                lock (ConnectedPlayers.DICTIONARY_LOCK)
                {
                    ClientState removeSocket;
                    if (ConnectedPlayers.playerDetails.TryGetValue(state.ClientID, out removeSocket))
                    {
                        removeSocket.BattleSocket = null;
                        try
                        {
                            //if value not found then connection should already be closed by cleanup procedure
                            handler.Shutdown(SocketShutdown.Both);
                            handler.Close();
                        }
                        catch (Exception) { }
                    }
                }
                Console.WriteLine("\nPlayer disconnected");
            }
        }
예제 #2
0
        //read updates from clients
        public static void readUpdate(IAsyncResult ar)
        {
            //retreive the state object and socket
            BattleState state   = (BattleState)ar.AsyncState;
            Socket      handler = state.ClientSocket;

            try
            {
                //bool battleEnd;
                //bool win;

                //NEED TO DEAL WITH SIZES AND STUFF, MAYBE SEND A MESSAGE WITH THE SIZE
                //for now everything sent as 41 bytes
                ar.AsyncWaitHandle.WaitOne();
                if (handler.EndReceive(ar) == 0)
                {
                    //ANYTHING ELSE NEED TO BE DONE ON THE SIDE OF THE PERSON WHO DCED?
                    return;
                }


                byte flags = state.Update[0];

                //determine winner and if battle ended
                bool battleEnd = false;
                //currently treat loss and draw the same, so only indicate win
                bool win = false;

                byte clientWinLoseDraw = 0;

                //whichever update gets here first receives authority over end game, lock the other out until complete processing hits
                lock (state.StatsLock)
                {
                    //if battle over do not evaluate this round of damage
                    if (!(state.OpponentStats.HP <= 0 || state.ClientStats.HP <= 0))
                    {
                        if (((flags >> 5) & 1) == 1)
                        {
                            state.ClientStats.HP -= 75;

                            Console.WriteLine("mine");
                            Console.WriteLine("My life: " + state.ClientStats.HP.ToString());
                        }
                        if (((flags >> 6) & 1) == 1)
                        {
                            state.OpponentStats.HP -= Math.Max(state.ClientStats.Attack - state.OpponentStats.Defense, 1);
                            Console.WriteLine("shot");
                            Console.WriteLine("Opponent life: " + state.OpponentStats.HP.ToString());
                        }
                        if (((flags >> 7) & 1) == 1)
                        {
                            state.OpponentStats.HP -= 75;
                            Console.WriteLine("mine hit opponent");
                            Console.WriteLine("Opponent life: " + state.OpponentStats.HP.ToString());
                        }
                        if (((flags >> 3) & 1) == 1)
                        {
                            if (state.ClientStats.HP + 50 <= state.ClientStats.MaxHP)
                            {
                                state.ClientStats.HP += 50;
                            }
                            else
                            {
                                state.ClientStats.HP = state.ClientStats.MaxHP;
                            }
                            Console.WriteLine("health pot");
                            Console.WriteLine("My life: " + state.ClientStats.HP.ToString());
                        }
                    }
                }
                //if client has no hp indicate battle over and match lost
                if (state.ClientStats.HP <= 0 && state.OpponentStats.HP <= 0)
                {
                    battleEnd = true;
                    //draws are indicated by a 3, because apparently numbers go 0, 1, 3
                    clientWinLoseDraw = 3;
                }
                //if client has health and opponent doesnt indicate match over and battle won
                else if (state.ClientStats.HP <= 0)
                {
                    battleEnd = true;
                    //client lost, clientWinLoseDraw already initialized to 0
                }
                else if (state.OpponentStats.HP <= 0)
                {
                    battleEnd = true;
                    win       = true;
                    //client won
                    clientWinLoseDraw = 1;
                }



                //lock write operations and pass along and acknowledge update
                lock (state.WriteLock)
                {
                    send(state, battleEnd, clientWinLoseDraw);
                }

                //recursively read updates until the battle is over
                if (!battleEnd)
                {
                    handler.BeginReceive(state.Update, 0, UPDATE_SIZE, 0, new AsyncCallback(readUpdate), state);
                }
                else
                {
                    //handle winner stuff (DB stuff, etc)
                    if (win)
                    {
                        var dbCon = new DatabaseConnect();
                        dbCon.updatePlayerExpAfterBattle(state.ClientID);
                    }

                    //clean up
                    lock (ConnectedPlayers.DICTIONARY_LOCK)
                    {
                        ClientState removeSocket;
                        if (ConnectedPlayers.playerDetails.TryGetValue(state.ClientID, out removeSocket))
                        {
                            removeSocket.BattleSocket = null;
                            //if value not found then connection should already be closed
                            handler.Shutdown(SocketShutdown.Both);
                            handler.Close();
                        }
                    }

                    Console.WriteLine("\nPlayer disconnected");
                }
            }
            //end communications gracefully if player disconnects before battle ends
            catch (Exception)
            {
                lock (ConnectedPlayers.DICTIONARY_LOCK)
                {
                    ClientState removeSocket;
                    if (ConnectedPlayers.playerDetails.TryGetValue(state.ClientID, out removeSocket))
                    {
                        removeSocket.BattleSocket = null;
                        try
                        {
                            //if value not found then connection should already be closed
                            handler.Shutdown(SocketShutdown.Both);
                            handler.Close();
                        }
                        catch (Exception) { }
                    }
                }
                Console.WriteLine("\nPlayer disconnected");
            }
        }