#include #include #include #include "game.h" #include "network/game_state_message.h" #include "network/player_input_message.h" #include "network/tcpsocket.h" #include "network/message.h" #include "network/udpsocket.h" Player* Game::add_player(BettolaLib::Network::TCPSocket* socket) { _players.push_back(new Player(socket)); return _players.back(); } void Game::remove_player(unsigned int player_id) { _players.erase( std::remove_if(_players.begin(), _players.end(), [player_id](Player* player) { if(player->get_id() == player_id) { delete player; return true; } return false; }), _players.end()); } void Game::process_udp_message(const char* buffer, size_t size, const sockaddr_in& from_addr) { if(size < sizeof(BettolaLib::Network::MessageHeader)) return; BettolaLib::Network::MessageHeader header; memcpy(&header, buffer, sizeof(header)); if(header.type == BettolaLib::Network::MessageType::PlayerInput) { if(size < sizeof(BettolaLib::Network::MessageHeader) + sizeof(BettolaLib::Network::PlayerInputMessage)) return; BettolaLib::Network::PlayerInputMessage msg; memcpy(&msg, buffer + sizeof(header), sizeof(msg)); Player* player = get_player_by_id(msg.player_id); if(player) { if(!player->has_udp_addr()) { printf("Bettola Server: Associated UDP address for player %u\n", msg.player_id); player->set_udp_addr(from_addr); } player->set_last_processed_sequence(msg.sequence_number); float dir_x = (msg.right ? 1.0f : 0.0f) - (msg.left ? 1.0f : 0.0f); float dir_y = (msg.down ? 1.0f : 0.0f) - (msg.up ? 1.0f : 0.0f); player->set_velocity_direction(dir_x, dir_y); player->update(msg.dt); } } } void Game::broadcast_game_state(BettolaLib::Network::UDPSocket& udp_socket) { BettolaLib::Network::GameStateMessage msg; msg.num_players = _players.size(); memset(msg.players, 0, sizeof(msg.players)); for(size_t i = 0; i < _players.size(); ++i) { msg.players[i].player_id = _players[i]->get_id(); msg.players[i].x = _players[i]->get_x(); msg.players[i].y = _players[i]->get_y(); msg.players[i].last_processed_sequence = _players[i]->get_last_processed_sequence(); } BettolaLib::Network::MessageHeader header; header.type = BettolaLib::Network::MessageType::GameState; header.size = sizeof(msg); for(const auto& player : _players) { if(player->has_udp_addr()) { char buffer[sizeof(header) + sizeof(msg)]; memcpy(buffer, &header, sizeof(header)); memcpy(buffer + sizeof(header), &msg, sizeof(msg)); udp_socket.send_to(buffer, sizeof(buffer), player->get_udp_addr()); } } } Player* Game::get_player_by_socket(const BettolaLib::Network::TCPSocket* socket) { auto it = std::find_if(_players.begin(), _players.end(), [socket](const Player* player) { return &player->get_socket() == socket; }); return(it != _players.end() ? *it : nullptr); } Player* Game::get_player_by_id(unsigned int id) { auto it = std::find_if(_players.begin(), _players.end(), [id](const Player* player) { return player->get_id() == id; }); return(it != _players.end() ? *it : nullptr); }