terom@5: #include "NetworkServer.hh" terom@22: #include "Engine.hh" terom@23: #include "Logger.hh" terom@5: terom@14: #include terom@5: terom@21: NetworkServer::NetworkServer (GameState &state, const std::string &listen_port) : terom@22: NetworkCore(state), pid_pool(0) { terom@5: terom@21: // connect slots terom@21: slots.connect(netsession.sig_computer_connected(), this, &NetworkServer::on_connect); terom@21: slots.connect(netsession.sig_computer_disconnected(), this, &NetworkServer::on_disconnect); terom@21: terom@21: // and then we listen terom@21: netsession.start_listen(listen_port); terom@23: terom@23: Engine::log(INFO, "server") << "running, listen_port=" << listen_port; terom@5: } terom@5: terom@21: void NetworkServer::on_connect (CL_NetComputer &computer) { terom@22: // assign a pid terom@22: uint16_t pid = ++pid_pool; terom@22: terom@23: // create the player object (it logs it) terom@22: NetworkServerPlayer *player = new NetworkServerPlayer(*this, computer, pid); terom@22: terom@22: // map computer to it terom@22: players[computer] = player; terom@22: terom@22: // add to GameState terom@22: state.newRemotePlayer(player); terom@5: } terom@5: terom@21: void NetworkServer::on_disconnect (CL_NetComputer &computer) { terom@22: NetworkServerPlayer *player = players[computer]; terom@22: terom@22: // remove from players terom@22: players.erase(computer); terom@22: terom@22: // remove from state terom@22: state.removePlayer(player); terom@22: terom@22: // remove from game terom@22: player->disconnected(); terom@22: terom@22: // delete terom@22: delete player; terom@5: } terom@5: terom@22: NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid) : terom@23: RemotePlayer(Coordinate(0, 0), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) { terom@5: terom@23: // log terom@23: Engine::log(INFO, "server_player.connected") << "computer=" << computer << ", obj=" << obj; terom@23: terom@22: // messages terom@23: slots.connect(obj.sig_received_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move); terom@22: terom@22: // the initial NETMSG_PLAYER_HELLO terom@22: CL_NetPacket hello_pkt; terom@22: hello_pkt.output.write_uint32(position.x); terom@22: hello_pkt.output.write_uint32(position.y); terom@22: terom@23: obj.send(computer, NETMSG_SERVER_HELLO, hello_pkt, true); terom@22: terom@22: // send other player objects terom@22: for (std::map::iterator it = server.players.begin(); it != server.players.end(); it++) { terom@22: NetworkServerPlayer *player = it->second; terom@22: CL_NetPacket player_pkt; terom@22: terom@22: // player is not in players list yet terom@22: assert(player != this); terom@22: terom@22: player_pkt.output.write_uint32(player->position.x); terom@22: player_pkt.output.write_uint32(player->position.y); terom@22: terom@23: player->obj.send(computer, NETMSG_PLAYER_INFO, player_pkt, true); terom@22: } terom@22: terom@22: terom@22: // broadcast NETMSG_PLAYER_JOIN to all clients terom@23: obj.send(server.netsession.get_all(), NETMSG_PLAYER_JOIN, hello_pkt, true); terom@5: } terom@5: terom@22: void NetworkServerPlayer::disconnected (void) { terom@22: CL_NetPacket pkt; terom@23: terom@23: Engine::log(INFO, "server_player.disconnected") << "computer=" << computer << ", obj=" << obj; terom@22: terom@23: obj.send(server.netsession.get_all(), NETMSG_PLAYER_QUIT, pkt, true); terom@22: } terom@22: terom@22: void NetworkServerPlayer::on_move (CL_NetComputer &from, CL_NetPacket &pkt) { terom@22: // sanity-check terom@22: if (!(from == computer)) terom@22: return; terom@22: terom@22: // read packet terom@22: uint32_t dx = pkt.input.read_uint32(); terom@22: uint32_t dy = pkt.input.read_uint32(); terom@22: terom@22: // movement delta terom@22: PositionDelta delta(dx, dy); terom@22: terom@23: Engine::log(INFO, "server_player.on_move") << "obj=" << obj << ", old_pos=" << position << ", delta=" << delta; terom@23: terom@22: // apply movement terom@22: position += delta; terom@22: terom@22: // send position update terom@22: send_position_update(); terom@22: } terom@22: terom@22: void NetworkServerPlayer::send_position_update (void) { terom@22: CL_NetPacket pkt; terom@22: pkt.output.write_uint32(position.x); terom@22: pkt.output.write_uint32(position.y); terom@22: terom@23: Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position; terom@23: terom@23: obj.send(server.netsession.get_all(), NETMSG_PLAYER_POSITION, pkt, false); terom@22: } terom@22: