2 #include "Engine.hh" |
2 #include "Engine.hh" |
3 #include "Logger.hh" |
3 #include "Logger.hh" |
4 |
4 |
5 #include <cassert> |
5 #include <cassert> |
6 |
6 |
7 NetworkServer::NetworkServer (GameState &state, const std::string &listen_port) : |
7 NetworkServer::NetworkServer (GameState &state, const NetworkAddress &listen_addr) : |
8 NetworkCore(state), pid_pool(0) { |
8 NetworkCore(state), netsession(NETWORK_MAGIC_ID), netobjs(netsession, NETCHAN_CORE) { |
9 |
9 |
10 // connect slots |
10 // connect slots |
11 slots.connect(netsession.sig_computer_connected(), this, &NetworkServer::on_connect); |
11 slots.connect(netsession.sig_node_connected(), this, &NetworkServer::on_node_connected); |
12 slots.connect(netsession.sig_computer_disconnected(), this, &NetworkServer::on_disconnect); |
|
13 |
12 |
14 // and then we listen |
13 // and then we listen |
15 netsession.start_listen(listen_port); |
14 netsession.listen(listen_addr); |
16 |
15 |
17 Engine::log(INFO, "server") << "running, listen_port=" << listen_port; |
16 Engine::log(INFO, "server") << "running, listen_addr=" << listen_addr; |
18 } |
17 } |
19 |
18 |
20 void NetworkServer::on_connect (CL_NetComputer &computer) { |
19 void NetworkServer::on_node_connected (NetworkNode *node) { |
21 // assign a pid |
20 // create the player object (it logs it) |
22 uint16_t pid = ++pid_pool; |
21 NetworkServerPlayer *player = new NetworkServerPlayer(*this, node); |
|
22 |
|
23 // add to players |
|
24 players.push_back(player); |
23 |
25 |
24 // create the player object (it logs it) |
|
25 NetworkServerPlayer *player = new NetworkServerPlayer(*this, computer, pid); |
|
26 |
|
27 // map computer to it |
|
28 players[computer] = player; |
|
29 |
|
30 // add to GameState |
26 // add to GameState |
31 state.newRemotePlayer(player); |
27 state.newRemotePlayer(player); |
32 } |
28 } |
33 |
29 |
34 void NetworkServer::on_disconnect (CL_NetComputer &computer) { |
30 void NetworkServer::handle_disconnect (NetworkServerPlayer *player) { |
35 NetworkServerPlayer *player = players[computer]; |
|
36 |
|
37 // remove from players |
|
38 players.erase(computer); |
|
39 |
|
40 // remove from state |
31 // remove from state |
41 state.removePlayer(player); |
32 state.removePlayer(player); |
42 |
33 |
43 // remove from game |
34 // remove from list |
44 player->disconnected(); |
35 players.remove(player); |
45 |
|
46 // delete |
|
47 delete player; |
|
48 } |
36 } |
49 |
37 |
50 NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid) : |
38 NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, NetworkNode *node) : |
51 RemotePlayer(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), server(server), computer(computer), obj(&server.netobjs), pid(pid) { |
39 RemotePlayer(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), server(server), obj(server.netobjs), node(node) { |
52 |
40 |
53 // log |
41 // log |
54 Engine::log(INFO, "server_player.connected") << "computer=" << computer << ", obj=" << obj; |
42 Engine::log(INFO, "server_player.connected") << "node=" << node << ", obj=" << obj; |
55 |
43 |
56 // messages |
44 // messages |
57 slots.connect(obj.sig_received_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move); |
45 slots.connect(node->sig_disconnected(), this, &NetworkServerPlayer::on_disconnected); |
|
46 slots.connect(obj.sig_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move); |
58 |
47 |
59 // the initial NETMSG_PLAYER_HELLO |
48 // the initial NETMSG_PLAYER_HELLO |
60 CL_NetPacket hello_pkt; |
49 NetworkPacket hello_pkt; |
61 writeVector(hello_pkt, position); |
50 hello_pkt.write_vector(position); |
62 |
51 |
63 obj.send(computer, NETMSG_SERVER_HELLO, hello_pkt, true); |
52 obj.send_to(node, NETMSG_SERVER_HELLO, hello_pkt, true); |
64 |
53 |
65 // send other player objects |
54 // send other player objects |
66 for (std::map<CL_NetComputer, NetworkServerPlayer*>::iterator it = server.players.begin(); it != server.players.end(); it++) { |
55 for (std::list<NetworkServerPlayer*>::iterator it = server.players.begin(); it != server.players.end(); it++) { |
67 NetworkServerPlayer *player = it->second; |
56 NetworkServerPlayer *player = *it; |
68 CL_NetPacket player_pkt; |
57 NetworkPacket player_pkt; |
69 |
58 |
70 // player is not in players list yet |
59 // player is not in players list yet |
71 assert(player != this); |
60 assert(player != this); |
|
61 |
|
62 player_pkt.write_vector(player->position); |
72 |
63 |
73 writeVector(player_pkt, player->position); |
64 player->obj.send_to(node, NETMSG_PLAYER_INFO, player_pkt, true); |
74 |
|
75 player->obj.send(computer, NETMSG_PLAYER_INFO, player_pkt, true); |
|
76 } |
65 } |
77 |
66 |
78 |
67 // broadcast NETMSG_PLAYER_JOIN to all clients except current |
79 // broadcast NETMSG_PLAYER_JOIN to all clients |
68 obj.send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true); |
80 obj.send(server.netsession.get_all(), NETMSG_PLAYER_JOIN, hello_pkt, true); |
|
81 } |
69 } |
82 |
70 |
83 void NetworkServerPlayer::disconnected (void) { |
71 void NetworkServerPlayer::on_disconnected (void) { |
84 CL_NetPacket pkt; |
72 NetworkPacket pkt; |
85 |
73 |
86 Engine::log(INFO, "server_player.disconnected") << "computer=" << computer << ", obj=" << obj; |
74 Engine::log(INFO, "server_player.disconnected") << "node=" << node << ", obj=" << obj; |
|
75 |
|
76 // remove from server |
|
77 server.handle_disconnect(this); |
|
78 |
|
79 // tell other clients |
|
80 obj.send_all(NETMSG_PLAYER_QUIT, pkt, true); |
87 |
81 |
88 obj.send(server.netsession.get_all(), NETMSG_PLAYER_QUIT, pkt, true); |
82 // free |
|
83 delete this; |
89 } |
84 } |
90 |
85 |
91 void NetworkServerPlayer::on_move (CL_NetComputer &from, CL_NetPacket &pkt) { |
86 void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacket &pkt) { |
92 // sanity-check |
87 // sanity-check |
93 if (!(from == computer)) |
88 if (src != node) |
94 return; |
89 return; |
95 |
90 |
96 Vector impulse_force = readVector(pkt); |
91 Vector impulse_force = pkt.read_vector(); |
97 uint16_t impulse_ms = pkt.input.read_uint16(); |
92 uint16_t impulse_ms = pkt.read_uint16(); |
98 |
93 |
99 Engine::log(INFO, "server_player.on_move") << "obj=" << obj << ", old_pos=" << position << ", impulse=" << impulse_force << "@" << impulse_ms << "ms"; |
94 Engine::log(INFO, "server_player.on_move") << "player=" << obj << ", old_pos=" << position << ", impulse=" << impulse_force << "@" << impulse_ms << "ms"; |
100 |
95 |
101 // apply force |
96 // apply force |
102 applyForce(impulse_force, impulse_ms); |
97 applyForce(impulse_force, impulse_ms); |
103 |
98 |
104 // send position update |
99 // send position update |
105 send_position_update(); |
100 send_position_update(); |
106 } |
101 } |
107 |
102 |
108 void NetworkServerPlayer::send_position_update (void) { |
103 void NetworkServerPlayer::send_position_update (void) { |
109 CL_NetPacket pkt; |
104 NetworkPacket pkt; |
110 writeVector(pkt, position); |
105 pkt.write_vector(position); |
111 writeVector(pkt, velocity); |
106 pkt.write_vector(velocity); |
112 |
107 |
113 Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity; |
108 Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity; |
114 |
109 |
115 obj.send(server.netsession.get_all(), NETMSG_PLAYER_POSITION, pkt, false); |
110 obj.send_all(NETMSG_PLAYER_POSITION, pkt, false); |
116 } |
111 } |
117 |
112 |