private void OnReceive(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; clientSocket.EndReceive(ar); //Transform the array of bytes received from the user into an //intelligent form of object Data Data msgReceived = new Data(byteData); //We will send this object in response the users request Data msgToSend = new Data(); lock (globalLocker) { int clientId = findClient(clientList, clientSocket); byte[] message; if (clientId == -1) writeToLog2("Получено " + msgReceived.cmdCommand.ToString() + " от " + clientSocket.LocalEndPoint.ToString(), true); else if (clientList[clientId].roomId == -1) writeToLog2("Получено " + msgReceived.cmdCommand.ToString() + " от " + clientList[clientId].login, true); else writeToLog2("Получено " + msgReceived.cmdCommand.ToString() + "\t от " + clientList[clientId].login + " в \"" + rooms[clientList[clientId].roomId].roomName + "\"", true); switch (msgReceived.cmdCommand) { case Command.Connect: /////////проверка разрешения пользователя на доступ к игре //если разрешено ClientInfo clientInfo = new ClientInfo(); clientInfo.socket = clientSocket; clientInfo.ip = clientInfo.socket.RemoteEndPoint.ToString(); clientInfo.login = msgReceived.login; clientInfo.roomId = -1; if (msgReceived.cardID != VERSION) { writeToLog("Попытка подключиться (старый клиент): " + clientInfo.login); msgToSend.cmdCommand = Command.OldVersion; message = msgToSend.ToByte(); //writeToLog2("Отправлено к " + clientInfo.login + " " + msgToSend.cmdCommand.ToString(), true); clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(clientInfo.socket, Command.OldVersion, -1)); return; } if (isLoginOK(clientList, msgReceived.login)) { writeToLog("Подключился новый игрок: " + clientInfo.login); clientList.Add(clientInfo); msgToSend.cmdCommand = Command.Success; message = msgToSend.ToByte(); //writeToLog2("Отправлено к " + clientInfo.login + " " + msgToSend.cmdCommand.ToString(), true); clientInfo.acceptEvent.Reset(); clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(clientInfo.socket, Command.Success, -1)); clientInfo.acceptEvent.WaitOne(); if (playersChanged != null) playersChanged(false, null); } else { writeToLog("Попытка подключиться: " + clientInfo.login); msgToSend.cmdCommand = Command.Failed; message = msgToSend.ToByte(); //writeToLog2("Отправлено к " + clientInfo.login + " " + msgToSend.cmdCommand.ToString(), true); clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(clientInfo.socket, Command.Failed, -1)); } break; case Command.connectToGame: //найти и добавить в игру клиента if (clientId != -1) { clientList[clientId].roomId = findRoom(msgReceived.gameToConnectRoomName); rooms[clientList[clientId].roomId].gamersSend += clientList[clientId].login + " "; rooms[clientList[clientId].roomId].gamers += "; " + clientList[clientId].login; rooms[clientList[clientId].roomId].clientsInRoom.Add(clientList[clientId]); msgToSend.UsersInRoom = rooms[clientList[clientId].roomId].gamersSend; Send4All(clientId, Command.ListUsers, msgToSend); if (roomsChanged != null) roomsChanged(null, null); playersChanged(true, null); writeToLog(clientList[clientId].login + " присоединился в комнату " + rooms[clientList[clientId].roomId].roomName); } break; case Command.newGame: //создать новый стол if (clientId != -1 && clientList[clientId].roomId == -1) { Room r = new Room(); r.phase = 0; r.id = rooms.Count; r.roomName = msgReceived.gameToConnectRoomName; r.maxScores = msgReceived.cardID; r.gamers = clientList[clientId].login; r.password = msgReceived.login; r.gamersSend = r.gamers + " "; r.clientsInRoom = new List<ClientInfo>(); r.clientsInRoom.Add(clientList[clientId]); r.deckSize = Convert.ToInt32(msgReceived.UsersInRoom); r.Cards = new List<int>(); for (int i = 0; i < r.deckSize; i++) r.Cards.Add(i + 1); clientList[clientId].isAdmin = true; //первый создавший - админ, может запустить игру rooms.Add(r); clientList[clientId].roomId = r.id; writeToLog(clientList[clientId].login + " создал комнату: " + (r.roomName)); if (roomsChanged != null) roomsChanged(null, null); playersChanged(true, null); } break; #region GameLogic case Command.startGame: if (clientId != -1 && clientList[clientId].roomId != -1) { var r = rooms[clientList[clientId].roomId]; //активная комната r.status = 1; //идет игра r.phase = 1; if (roomsChanged != null) roomsChanged(null, null); r.gamersSend = r.gamersSend.Replace("# ", " "); r.gamersSend = r.gamersSend.Replace("? ", " "); r.gamersSend = r.gamersSend.Replace("* ", " "); writeToLog("В комнате " + r.roomName + " началась игра!"); //msgToSend.UsersInRoom = r.gamersSend; //Send4All(clientId, Command.ListUsers, msgToSend); //начинаем игру раздаем карты Random rnd = new Random(); r.sendCount = 0; r.acceptAllEvent.Reset(); for (int i = 0; i < r.clientsInRoom.Count; i++) { r.clientsInRoom[i].scores = 0; //очки в текущей партии r.clientsInRoom[i].voated = 0; r.clientsInRoom[i].discarded = 0; for (int j = 0; j < 5; j++) msgToSend.userCards[j] = NextCard(rnd, clientId); msgToSend.cardID = r.maxScores; msgToSend.cmdCommand = Command.startGame; message = msgToSend.ToByte(); if (r.clientsInRoom[i].socket.Connected) r.clientsInRoom[i].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendRoom), new PacketInfo(r.clientsInRoom[i].socket, Command.startGame, -2)); else connectionLost("Socket disconnected", r.clientsInRoom[i].socket); //r.clientsInRoom[i].acceptEvent.WaitOne(); //writeToLog2("Отправлено к " + r.clientsInRoom[i].login + " " + msgToSend.cmdCommand.ToString()); } r.acceptAllEvent.WaitOne(); roundBegin(r, clientId, rnd, true); } break; case Command.LeaderTurn: if (clientId != -1 && clientList[clientId].roomId != -1) { var r = rooms[clientList[clientId].roomId]; //активная комната int clientRoomId = findClient(r.clientsInRoom, clientSocket); r.clientsInRoom[clientRoomId].discarded = msgReceived.cardID; //занесли в память что скинул msgToSend.cmdCommand = Command.GamersTurn; //передает словесное задание msgToSend.gameToConnectRoomName = msgReceived.gameToConnectRoomName; message = msgToSend.ToByte(); if (r.clientsInRoom.Count > 1) { r.acceptAllEvent.Reset(); r.sendCount = 1; for (int i = 0; i < r.clientsInRoom.Count; i++) { if (i == findLeaderID(clientId)) continue; if (r.clientsInRoom[i].socket.Connected) r.clientsInRoom[i].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendRoom), new PacketInfo(r.clientsInRoom[i].socket, Command.GamersTurn, -2)); else connectionLost("Socket disconnected", r.clientsInRoom[i].socket); //writeToLog2("Отправлено к " + r.clientsInRoom[i].login + " " + msgToSend.cmdCommand.ToString()); } r.acceptAllEvent.WaitOne(); } //отчет в список r.gamersSend = r.gamersSend.Replace(clientList[clientId].login, clientList[clientId].login + "*"); msgToSend.UsersInRoom = rooms[clientList[clientId].roomId].gamersSend; Send4All(clientId, Command.ListUsers, msgToSend); r.phase = 4; //ассоциация пришла - отправили команду игрокам для сброса карт } break; case Command.GamersTurn: if (clientId != -1 && clientList[clientId].roomId != -1) { var r = rooms[clientList[clientId].roomId]; //активная комната int clientRoomId = findClient(r.clientsInRoom, clientSocket); r.clientsInRoom[clientRoomId].discarded = msgReceived.cardID; //занесли в память что скинул r.gamersSend = r.gamersSend.Replace(clientList[clientId].login, clientList[clientId].login + "#"); bool isReady = true; foreach (ClientInfo cl in r.clientsInRoom) if (cl.discarded <= 0) { isReady = false; break; } if (isReady) { Data msgToSendV = new Data(rooms[clientList[clientId].roomId].clientsInRoom.Count); msgToSendV.cmdCommand = Command.VoatingTurn; msgToSendV.userCards = ShuffleDiscarded(clientId); Send4All(clientId, Command.VoatingTurn, msgToSendV); r.phase = 5; //все сбросили карты - время для голосования! r.gamersSend = rooms[clientList[clientId].roomId].gamersSend.Replace("# ", " "); } msgToSend.UsersInRoom = rooms[clientList[clientId].roomId].gamersSend; Send4All(clientId, Command.ListUsers, msgToSend); } break; case Command.VoatingTurn: if (clientId != -1 && clientList[clientId].roomId != -1) { var r = rooms[clientList[clientId].roomId]; //активная комната int clientRoomId = findClient(r.clientsInRoom, clientSocket); r.clientsInRoom[clientRoomId].voated = msgReceived.cardID; //занесли в память что ответил r.gamersSend = r.gamersSend.Replace(clientList[clientId].login, clientList[clientId].login + "#"); bool isReady = true; foreach (ClientInfo cl in r.clientsInRoom) { if (cl.login == r.clientsInRoom[findLeaderID(clientId)].login) continue; if (cl.voated <= 0 && cl.ip != "LoggedOut") { isReady = false; break; } } if (isReady) calcResult(r, clientId, msgToSend); msgToSend.UsersInRoom = rooms[clientList[clientId].roomId].gamersSend; Send4All(clientId, Command.ListUsers, msgToSend); r.gamersSend = r.gamersSend.Replace("& ", " "); } break; case Command.Success: if (clientId != -1 && clientList[clientId].roomId != -1) { var r = rooms[clientList[clientId].roomId]; //активная комната int clientRoomId = findClient(r.clientsInRoom, clientSocket); r.clientsInRoom[clientRoomId].voated = 0; //сбрасываем сыгранные карты r.clientsInRoom[clientRoomId].discarded = 0; r.gamersSend = r.gamersSend.Replace(clientList[clientId].login, clientList[clientId].login + "#"); bool isReady = true; foreach (ClientInfo cl in r.clientsInRoom) if (cl.discarded > 0) { isReady = false; break; } if (isReady) roundBegin(r, clientId, new Random(), false); else { msgToSend.UsersInRoom = r.gamersSend; Send4All(clientId, Command.ListUsers, msgToSend); } } break; #endregion case Command.List: //сформировать список столов и вернуть назад msgToSend.cmdCommand = Command.List; msgToSend.list = rooms; message = msgToSend.ToByte(); //Send the message to all users if (clientSocket.Connected) clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(clientSocket, Command.List, -1)); else connectionLost("Socket disconnected", clientSocket); //writeToLog2("Отправлено к " + clientList[clientId].login + " " + msgToSend.cmdCommand.ToString()); playersChanged(true, null); break; case Command.chat: if (clientId != -1) { if (msgReceived.cardID == 1) //сообщение пришло для игровой комнаты { if (msgReceived.UsersInRoom.StartsWith("@kick")) //получена команда if (clientList[clientId].isAdmin) { string target = msgReceived.UsersInRoom.Remove(0, 6); for (int i=0; i< rooms[clientList[clientId].roomId].clientsInRoom.Count; i++) if (rooms[clientList[clientId].roomId].clientsInRoom[i].login == target) { msgToSend.cmdCommand = Command.Disconnect; message = msgToSend.ToByte(); rooms[clientList[clientId].roomId].clientsInRoom[i].acceptEvent.Reset(); rooms[clientList[clientId].roomId].clientsInRoom[i].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(rooms[clientList[clientId].roomId].clientsInRoom[i].socket, Command.Disconnect, -1)); rooms[clientList[clientId].roomId].clientsInRoom[i].acceptEvent.WaitOne(); } } msgToSend.gameToConnectRoomName = msgReceived.UsersInRoom; msgToSend.login = clientList[clientId].login; msgToSend.cardID = 1; Send4All(clientId, Command.chat, msgToSend); } else { msgToSend.gameToConnectRoomName = msgReceived.UsersInRoom; msgToSend.login = clientList[clientId].login; msgToSend.cmdCommand = Command.chat; msgToSend.cardID = 0; message = msgToSend.ToByte(); lock (removeLobbyLocker) { acceptLobbyEvent.Reset(); sendLobby = 0; int waiterNum = 0; for (int i = 0; i < clientList.Count; i++) if (clientList[i].roomId == -1) waiterNum++; if (waiterNum == 0) return; for (int i = 0; i < clientList.Count; i++) if (clientList[i].roomId == -1) if (clientList[i].socket.Connected) clientList[i].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendLobby), new PacketInfo(clientList[i].socket, Command.chat, waiterNum)); else connectionLost("Socket disconnected", clientList[i].socket); acceptLobbyEvent.WaitOne(); } } } break; case Command.logOut: if (clientId != -1) { writeToLog("Игрок " + clientList[clientId].login + " вышел из комнаты " + rooms[clientList[clientId].roomId].roomName); afterDisconnect(clientId, clientSocket, msgToSend); clientList[clientId].roomId = -1; roomsChanged(null, null); playersChanged(true, null); } break; case Command.Disconnect: if (clientId != -1) { if (clientList[clientId].roomId != -1) afterDisconnect(clientId, clientSocket, new Data()); writeToLog("Игрок " + clientList[clientId].login + " отключился"); lock (removeLobbyLocker) clientList.RemoveAt(clientId); roomsChanged(null, null); playersChanged(true, null); } break; } //If the user is logging out then we need not listen from her if (msgReceived.cmdCommand != Command.Disconnect && msgToSend.cmdCommand != Command.Failed) { //Start listening to the message send by the user clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } } log2Changed(log, null); } catch (Exception ex) { Socket clientSocket = (Socket)ar.AsyncState; connectionLost(ex.Message, clientSocket); } }
private bool calcResult(Room r, int clientId, Data msgToSend) { int[] roundScores = new int[r.clientsInRoom.Count]; string roundResult = ""; int LeaderId = findLeaderID(clientId); r.phase = 6; //финальная фаза - подсчет очков int loginLong = 0; for (int i = 0; i < r.clientsInRoom.Count; i++) if (r.clientsInRoom[i].login.Length > loginLong) loginLong = r.clientsInRoom[i].login.Length; for (int i = 0; i < r.clientsInRoom.Count; i++) { roundScores[i] = 0; if (LeaderId == i) { int count = 0; for (int j = 0; j < r.clientsInRoom.Count; j++) { if (i == j) continue; if (r.clientsInRoom[j].voated == r.clientsInRoom[i].discarded) count++; } if (count == 0 || count == (r.clientsInRoom.Count - 1)) roundScores[i] = -2; //все отгадали или никто -2 очка else roundScores[i] = 3; } else { if (r.clientsInRoom[i].voated == r.clientsInRoom[i].discarded) roundScores[i] += -2; //проголосовал за свою -1 очко // +1 за голос за свою if (r.clientsInRoom[i].voated == r.clientsInRoom[LeaderId].discarded) roundScores[i] += 3; //отгадал +3 очка for (int j = 0; j < r.clientsInRoom.Count; j++) if (r.clientsInRoom[j].voated == r.clientsInRoom[i].discarded) roundScores[i] ++; } r.clientsInRoom[i].scores += roundScores[i]; roundResult += " " + r.clientsInRoom[i].login; for (int k = r.clientsInRoom[i].login.Length; k <= loginLong; k++) roundResult += " "; roundResult += "\t\t" + roundScores[i].ToString() + "\n"; } Data msgToSendV = new Data(rooms[clientList[clientId].roomId].clientsInRoom.Count*3); for (int i = 0; i < r.clientsInRoom.Count; i++) msgToSendV.userCards[i] = r.clientsInRoom[i].scores; for (int i = r.clientsInRoom.Count; i < 2*r.clientsInRoom.Count; i++) msgToSendV.userCards[i] = r.clientsInRoom[i - r.clientsInRoom.Count].discarded; for (int i = 2*r.clientsInRoom.Count; i < 3 * r.clientsInRoom.Count; i++) msgToSendV.userCards[i] = r.clientsInRoom[i - 2*r.clientsInRoom.Count].voated; msgToSendV.gameToConnectRoomName = roundResult; Send4All(clientId, Command.Result, msgToSendV); //отправка результата r.gamersSend = r.gamersSend.Replace("# ", " "); r.gamersSend = r.gamersSend.Replace("* ", " "); bool winnerHere = defineWinner(r, clientId, msgToSend); for (int i = 0; i < r.clientsInRoom.Count; i++) //ищем все дампы if (r.clientsInRoom[i].ip == "LoggedOut") { if (r.clientsInRoom[i].isLeader) if (i == 0) r.clientsInRoom[r.clientsInRoom.Count - 1].isLeader = true; else r.clientsInRoom[i - 1].isLeader = true; r.gamersSend = r.gamersSend.Replace(r.clientsInRoom[i].login + "? ", " "); r.clientsInRoom.RemoveAt(i); //удаляем дамп ушедшего i = 0; } return winnerHere; }
private bool defineWinner(Room r, int clientId, Data msgToSend) { for (int i = 0; i < r.clientsInRoom.Count; i++) if (r.clientsInRoom[i].scores >= r.maxScores) //Вот он победитель! почти { bool flag = true; for (int j = 0; j < r.clientsInRoom.Count; j++) if (r.clientsInRoom[i].scores <= r.clientsInRoom[j].scores && i != j) flag = false; if (flag) { writeToLog("В комнате " + r.roomName + " победил игрок: " + r.clientsInRoom[i].login); msgToSend.login = r.clientsInRoom[i].login; Send4All(clientId, Command.win, msgToSend); //Thread.Sleep(2000); r.status = 0; r.gamersSend = r.gamersSend.Replace(r.clientsInRoom[i].login, r.clientsInRoom[i].login + "&"); r.clientsInRoom[findLeaderID(clientId)].isLeader = false; if (roomsChanged != null) roomsChanged(null, null); return true; } } return false; }
private void roundBegin(Room r, int clientId, Random rnd, bool IsGameStart) { //выбираем ведущего int leaderID = 0; if (IsGameStart) { for (int i = 0; i < r.clientsInRoom.Count; i++) r.clientsInRoom[i].isLeader = false; leaderID = rnd.Next(r.clientsInRoom.Count); } else { leaderID = findLeaderID(clientId); r.clientsInRoom[leaderID].isLeader = false; leaderID++; if (leaderID == r.clientsInRoom.Count) leaderID = 0; r.clientsInRoom[leaderID].isLeader = true; } playersChanged(false, null); Data msgToSend = new Data(); r.clientsInRoom[leaderID].isLeader = true; msgToSend.cmdCommand = Command.LeaderTurn; msgToSend.cardID = NextCard(new Random(), clientId); byte[] message = msgToSend.ToByte(); //while (r.clientsInRoom[leaderID].isBusy == true) Thread.Sleep(30); r.clientsInRoom[leaderID].acceptEvent.Reset(); if (r.clientsInRoom[leaderID].socket.Connected) r.clientsInRoom[leaderID].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendOne), new PacketInfo(r.clientsInRoom[leaderID].socket, Command.LeaderTurn, -1)); else { connectionLost("Socket disconnected", r.clientsInRoom[leaderID].socket); return; } r.clientsInRoom[leaderID].acceptEvent.WaitOne(); //r.clientsInRoom[leaderID].isBusy = true; //writeToLog2("Отправлено к " + r.clientsInRoom[leaderID].login + " " + msgToSend.cmdCommand.ToString()); //остальные ждут когда он загадает r.acceptAllEvent.Reset(); r.sendCount = 1; for (int i = 0; i < r.clientsInRoom.Count; i++) if (i != leaderID) { msgToSend.cmdCommand = Command.Waiting; msgToSend.login = r.clientsInRoom[leaderID].login; msgToSend.cardID = NextCard(new Random(), clientId); message = msgToSend.ToByte(); if (r.clientsInRoom[i].socket.Connected) r.clientsInRoom[i].socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSendRoom), new PacketInfo(r.clientsInRoom[i].socket, Command.Waiting, r.clientsInRoom.Count)); else { connectionLost("Socket disconnected", r.clientsInRoom[i].socket); if (i == r.clientsInRoom.Count - 1) r.acceptAllEvent.Set(); } //r.clientsInRoom[i].isBusy = true; //writeToLog2("Отправлено к " + r.clientsInRoom[i].login + " " + msgToSend.cmdCommand.ToString()); } r.acceptAllEvent.WaitOne(); r.phase = 2; r.gamersSend = r.gamersSend.Replace("# ", " "); r.gamersSend = r.gamersSend.Replace("? ", " "); }