void openHandler(int clientID){ json msg; // Our first message to the client // If Player 1 just connected... if (server.getClientIDs().size() == 1) { // Send msg: you've been assigned player 1 msg["MESSAGE_TYPE"] = "PLAYER_ASSIGNMENT"; msg["PLAYER_NUMBER"] = 1; msg["UPDATE_CYCLE_LENGTH"] = UPDATE_CYCLE_LENGTH_MS; send_message(clientID, msg); } // If Player 2 just connected... else if (server.getClientIDs().size() == 2) { // Send msg: you've been assigned player 2 msg["MESSAGE_TYPE"] = "PLAYER_ASSIGNMENT"; msg["PLAYER_NUMBER"] = 2; msg["UPDATE_CYCLE_LENGTH"] = UPDATE_CYCLE_LENGTH_MS; send_message(clientID, msg); } // Or if there are too many connections, reject it: else { msg["MESSAGE_TYPE"] = "CONNECTION_REJECTED"; send_message(clientID, msg); server.wsClose(clientID); } }
void InterpretCommand(int clientID, std::string message) { bool named = false; vector<int> clientIDs = server.getClientIDs(); ostringstream os; ostringstream os2; if (message.find("NewPlayer:") == 0) { if (message.length() > 10) { if (player1 == "") player1 = message.substr(10); else player2 = message.substr(10); } named = true; } if (!named) { vector<int> clientIDs = server.getClientIDs(); if (message.length() > 7) { if (clientID == clientIDs[0]) { snakeState.SetPlayerInput(0, message[8]); } else { snakeState.SetPlayerInput(1, message[8]); } } } }
/* called once per select() loop */ void periodicHandler() { vector<int> clientIDs = server.getClientIDs(); static time_t next = time(NULL)+1; time_t current = time(NULL); messageDelay(); if (gameStarted) { if (current >= next) { snakeState.UpdateBoardState(); ostringstream ss; ostringstream score1; ostringstream score2; ss << "GB:" << snakeState.GetBoardState(); score1 << "1:" << player1 + " score: " << snakeState.GetPlayerScore(0); score2 << "2:" << player2 + " score: " << snakeState.GetPlayerScore(1); for (int i = 0; i < clientIDs.size(); i++){ server.wsSend(clientIDs[i], ss.str()); server.wsSend(clientIDs[i], score1.str()); server.wsSend(clientIDs[i], score2.str()); } next = time(NULL) + 1; } } }
/* called when a client connects */ void openHandler(int clientID) { vector<int> clientIDs = server.getClientIDs(); server.wsSend(clientID, "Welcome!"); ostringstream game_width; ostringstream game_height; ostringstream game_board; game_width << "GW:" << snakeState.GetBoardWidth(); game_height << "GH:" << snakeState.GetBoardHeight(); game_board << "GB:" << snakeState.GetBoardState(); server.wsSend(clientID, game_width.str()); server.wsSend(clientID, game_height.str()); server.wsSend(clientID, game_board.str()); if (clientIDs.size() == 2) { gameStarted = true; snakeState.StartNewGame(); return; } else if (clientIDs.size() > 2) server.wsClose(clientID); else gameStarted = false; }
/* called when a client sends a message to the server */ void messageHandler(int clientID, string message){ ostringstream os; os << "Stranger " << clientID << " says: " << message; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID) server.wsSend(clientIDs[i], os.str()); } }
/* called when a client disconnects */ void closeHandler(int clientID){ ostringstream os; os << "Stranger " << clientID << " has leaved."; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID) server.wsSend(clientIDs[i], os.str()); } }
/* called when a client sends a message to the server */ void messageHandler(int clientID, string message) { vector<int> clientIDs = server.getClientIDs(); stringstream ss; ss << clientID << ":" << message; if(clientID == 0) message_queue[0].push(ss.str()); else message_queue[1].push(ss.str()); }
/* called when a client connects */ void openHandler(int clientID){ ostringstream os; os << "Stranger " << clientID << " has joined."; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID) server.wsSend(clientIDs[i], os.str()); } server.wsSend(clientID, "Welcome!"); }
/* called when a client disconnects */ void closeHandler(int clientID){ ostringstream os; os << "Stranger " << clientID << " has leaved."; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++){ server.wsSend(clientIDs[i], "Disconnected"); server.wsClose(clientIDs[i]); } ReceiveQueue.clear(); SendQueue.clear(); }
void closeHandler(int clientID){ // If game is ongoing, kill it and send out // an error to whomever is still connected: if (game_p != NULL && game_p->isActive()) { json errorMsg; errorMsg["MESSAGE_TYPE"] = "ERROR"; errorMsg["ERROR_MSG"] = "Other player disconnected"; // Send the message to whomever is connected vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) { server.wsSend(clientIDs[i], errorMsg.dump()); // Don't buffer } // Close all open connections (must be done separately) clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) { server.wsClose(i); } resetGame(); } }
//Checks for winners std::string check_winner(){ vector<int> clientIDs = server.getClientIDs(); std::string winner; if (clientSnakes[clientIDs[0]].score > clientSnakes[clientIDs[1]].score){ winner = "Winner: " + clientSnakes[clientIDs[0]].ID; } else if (clientSnakes[clientIDs[0]].score < clientSnakes[clientIDs[1]].score){ winner = "Winner: " + clientSnakes[clientIDs[1]].ID; } else if (clientSnakes[clientIDs[0]].score == clientSnakes[clientIDs[1]].score){ winner = "It's a tie"; } return winner; }
/* called once per select() loop */ void periodicHandler(){ static time_t next = time(NULL) + 10; time_t current = time(NULL); if (current >= next){ ostringstream os; string timestring = ctime(¤t); timestring = timestring.substr(0, timestring.size() - 1); os << timestring; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) server.wsSend(clientIDs[i], os.str()); next = time(NULL) + 10; } }
/* called when a client sends a message to the server */ void messageHandler(int clientID, string message){ bool scored = false; bool named = false; ostringstream os; ostringstream os2; if (message.find("Player1:")==0) { if(message.length()>8) player1 = message.substr(8); named = true; } if (message.find("Player2:")==0) { if (message.length()>8) player2 = message.substr(8); named = true; } if(!named){ if (message == "1: addScore") { score1++; scored = true; } else if (message == "2: addScore") { score2++; scored = true; } if(scored){ os << ("1:" + player1 + " Score: ")<<score1; os2 << ("2:" + player2 + " Score: " )<< score2; } vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) { server.wsSend(clientIDs[i], os.str()); server.wsSend(clientIDs[i], os2.str()); } } }
/* called when a client disconnects */ void closeHandler(int clientID) { vector<int> clientIDs = server.getClientIDs(); if (clientIDs.size() <= 2) gameStarted = false; ostringstream os; std::string player_name; if (clientID == 0) player_name = player1; else player_name = player2; os << player_name << " has left."; for (int i = 0; i < clientIDs.size(); i++) { if (clientIDs[i] != clientID) server.wsSend(clientIDs[i], os.str()); } }
/* called when a client connects */ void openHandler(int clientID) { vector<int> clientIDs = server.getClientIDs(); server.wsSend(clientID, "Welcome!"); ostringstream game_width; ostringstream game_height; ostringstream game_board; ostringstream ssMove; ostringstream playerID; game_width << "GW:" << snakeState.GetBoardWidth(); game_height << "GH:" << snakeState.GetBoardHeight(); game_board << "GB:" << snakeState.GetBoardState(); ssMove << "MOVE:" << snakeState.GetPlayerDirection(0) << snakeState.GetPlayerDirection(1); playerID << "ID:" << clientID; server.wsSend(clientID, playerID.str()); server.wsSend(clientID, game_width.str()); server.wsSend(clientID, game_height.str()); server.wsSend(clientID, game_board.str()); server.wsSend(clientID, ssMove.str()); if (clientIDs.size() == 2) { gameStarted = true; message_to_process[0] = ""; message_to_process[1] = ""; emptyQueue(); last_move[0] = 'D'; last_move[1] = 'A'; snakeState.StartNewGame(); return; } else if (clientIDs.size() > 2) server.wsClose(clientID); else gameStarted = false; }
//Provides info for current start of snake game and sends the notification to start the game to the client. void gameStartState(){ vector<int> clientIDs = server.getClientIDs(); std::vector<int> food = createFood(); Snake player1 = clientSnakes[clientIDs[0]]; Snake player2 = clientSnakes[clientIDs[1]]; player1.snake_array = createSnake(0); player2.snake_array = createSnake(34); player1.score = 0; player2.score = 0; clientSnakes[clientIDs[0]].score = 0; clientSnakes[clientIDs[1]].score = 0; clientSnakes[clientIDs[0]].snake_array = player1.snake_array; clientSnakes[clientIDs[1]].snake_array = player2.snake_array; std::vector<Snake> snakes = { player1, player2 }; SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[0], "st;" + snakeToString(player1.snake_array) + "; " + snakeToString(player2.snake_array) + "; " + std::to_string(player1.score) + "," + std::to_string(player2.score) + ";" + std::to_string(food[0]) + "," + std::to_string(food[1]))); SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[1], "st;" + snakeToString(player2.snake_array) + "; " + snakeToString(player1.snake_array) + "; " + std::to_string(player2.score) + "," + std::to_string(player1.score) + ";" + std::to_string(food[0]) + "," + std::to_string(food[1]))); }
/* called when a client connects */ void openHandler(int clientID){ ostringstream os; vector<int> clientIDs = server.getClientIDs(); std::cout << "in openhandler " << clientIDs.size() << std::endl; if (clientIDs.size() > 3){ server.wsClose(clientID); cout << "Connection rejected: Only two connection allowed at a time."; } else if (clientIDs.size() == 2) { std::cout << "size is 2" << std::endl; os << "Stranger " << clientID << " has joined."; for (int i = 0; i < clientIDs.size(); i++){ clientSnakes[clientIDs[i]].ID = clientID; server.wsSend(clientIDs[i], "Welcome!"); //SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "Welcome!")); } gameStartState(); } }
/* called when a client sends a message to the server */ void messageHandler(int clientID, string message){ std::vector<int> clientIDs = server.getClientIDs(); if (clientSnakes.find(clientID) != clientSnakes.end()){ std::string toSend; if (message == "GameOver"){ std::string winner = check_winner(); for (int i = 0; i < clientIDs.size(); i++){ //server.wsSend(clientIDs[i], "winner;" + winner); SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "winner;" + winner)); } gameStartState(); } else if (message.substr(0, 2) == "sn"){ clientSnakes[clientID].snake_array = stringToSnake(message.substr(2)); Snake player1 = clientSnakes[clientID]; Snake player2; for (int i = 0; i < clientIDs.size(); i++){ if (clientID != clientIDs[i]){ player2 = clientSnakes[clientIDs[i]]; } } if (check_collision(player1.snake_array[0][0], player1.snake_array[0][1], player2.snake_array)){ gameStartState(); } for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID){ SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "sn;" + message.substr(2))); } } } else if (message == "Food"){ clientSnakes[clientID].score++; std::vector<int> food = createFood(); for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID){ SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "fs;" + std::to_string(food[0]) + "," + std::to_string(food[1]) + ";" + std::to_string(clientSnakes[clientIDs[i]].score) + "," + std::to_string(clientSnakes[clientID].score))); } else if (clientIDs[i] == clientID){ std::string otherscore; for (auto key : clientIDs){ if (key != clientID){ otherscore = std::to_string(clientSnakes[key].score); } } SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "fs;" + std::to_string(food[0]) + "," + std::to_string(food[1]) + ";" + std::to_string(clientSnakes[clientIDs[i]].score) + "," + otherscore)); } } } else if (message.substr(0, 2) == "id"){ clientSnakes[clientID].ID = message.substr(2); for (int i = 0; i < clientIDs.size(); i++){ if (clientIDs[i] != clientID){ SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "id;" + clientSnakes[clientID].ID)); } } } else if (message == "Latency"){ std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); for (int i = 0; i < clientIDs.size(); i++){ SendQueue[std::chrono::steady_clock::now()].push_back(createMessage(clientIDs[i], "latency")); } serverDelayStart = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count(); } } }
/* called once per select() loop */ void periodicHandler() { vector<int> clientIDs = server.getClientIDs(); if (last_score1 != snakeState.GetPlayerScore(0) || last_score2 != snakeState.GetPlayerScore(1) || last_move[0] != snakeState.GetPlayerDirection(0) || last_move[1] != snakeState.GetPlayerDirection(1)) { if (last_score1 != snakeState.GetPlayerScore(0) || last_score2 != snakeState.GetPlayerScore(1)) { snakeState.SetPlayerInput(0, 'D'); snakeState.SetPlayerInput(1, 'A'); } emptyQueue(); message_to_process[0] = ""; message_to_process[1] = ""; last_score1 = snakeState.GetPlayerScore(0); last_score2 = snakeState.GetPlayerScore(1); last_move[0] = snakeState.GetPlayerDirection(0); last_move[1] = snakeState.GetPlayerDirection(1); snakeState.UpdateBoardState(); } messageDelay(); LARGE_INTEGER li; if (!QueryPerformanceFrequency(&li)) cout << "QueryPerformanceFrequency failed!\n"; static double freq = double(li.QuadPart) / 1000.0; QueryPerformanceCounter(&li); __int64 current = li.QuadPart; static __int64 interval = (double)500 * freq; // 500 ms static __int64 next = current + interval; if (gameStarted) { if (current >= next) { if (message_to_process[0] != "" && message_to_process[1] != "") { ProcessMessages(); message_to_process[0] = ""; message_to_process[1] = ""; ostringstream ss; ostringstream score1; ostringstream score2; ostringstream ssMove; ss << "GB:" << snakeState.GetBoardState(); score1 << "1:" << player1 + " score: " << snakeState.GetPlayerScore(0); score2 << "2:" << player2 + " score: " << snakeState.GetPlayerScore(1); ssMove << "MOVE:" << snakeState.GetPlayerDirection(0) << snakeState.GetPlayerDirection(1); for (int i = 0; i < clientIDs.size(); i++) { server.wsSend(clientIDs[i], ss.str()); server.wsSend(clientIDs[i], score1.str()); server.wsSend(clientIDs[i], score2.str()); server.wsSend(clientIDs[i], ssMove.str()); } snakeState.UpdateBoardState(); next = current + interval; } } } }
void periodicHandler(){ // Poll the incoming & outgoing message buffers. std::pair <int, std::string> message_pair; if (send_buffer.isMessageReady()) { message_pair = send_buffer.getMessage(); if (message_pair.first != -1) { json time_check = json::parse(message_pair.second); if (time_check["MESSAGE_TYPE"] == "TIME_STAMP_REPLY") { time_check["T3"] = chrono::system_clock::now().time_since_epoch() / chrono::milliseconds(1); message_pair.second = time_check.dump(); } server.wsSend(message_pair.first, message_pair.second); } } if (receive_buffer.isMessageReady()) { message_pair = receive_buffer.getMessage(); if (message_pair.first != -1) { read_message(message_pair.first, message_pair.second); } } // If the game is active, update the game state. // We want this to occur no sooner than UPDATE_CYCLE_LENGTH_MS. // WARNING: This sets the pace of the game, so Milestone 4 client features that // perform movement prediction MUST use the same clock speed. if (game_p != NULL && game_p->isActive()) { unsigned long long currentTime = chrono::system_clock::now().time_since_epoch() / chrono::milliseconds(1); if (currentTime - lastUpdateTime >= UPDATE_CYCLE_LENGTH_MS) { // Update the game json msg = game_p->update(); // Broadcast the update to all clients vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) { send_message(clientIDs[i], msg); } // Update the clock lastUpdateTime = chrono::system_clock::now().time_since_epoch() / chrono::milliseconds(1); } } // If there is a game object but the status is INACTIVE, // update the clients and then DESTROY the game object. if (game_p != NULL && !game_p->isActive()) { json msg = game_p->update(); resetGame(); // Broadcast the final update to all clients // and then disconnect clients cout << "GAME OVER BROADCASTING FINAL UPDATE" << endl; vector<int> clientIDs = server.getClientIDs(); for (int i = 0; i < clientIDs.size(); i++) { server.wsSend(clientIDs[i], msg.dump()); // Don't buffer } for (int i = 0; i < clientIDs.size(); i++) { server.wsClose(i); } } }