6 #include "../Logger.hh" |
6 #include "../Logger.hh" |
7 |
7 |
8 #include <cassert> |
8 #include <cassert> |
9 |
9 |
10 NetworkClient::NetworkClient (GameState &state, const NetworkAddress &connect_to) : |
10 NetworkClient::NetworkClient (GameState &state, const NetworkAddress &connect_to) : |
11 state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), netobjs(netsession, NETCHAN_CORE, server) { |
11 state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), controller(*this) |
12 |
12 { |
13 // connect slots |
13 // connect slots |
14 slots.connect(netobjs.sig_create(NETMSG_SERVER_HELLO), this, &NetworkClient::on_server_hello); |
|
15 slots.connect(netobjs.sig_create(NETMSG_PLAYER_INFO), this, &NetworkClient::on_player_info); |
|
16 slots.connect(netobjs.sig_create(NETMSG_PLAYER_JOIN), this, &NetworkClient::on_player_join); |
|
17 slots.connect(netobjs.sig_create(NETMSG_PROJECTILE_CREATE), this, &NetworkClient::on_projectile_create); |
|
18 |
|
19 slots.connect(netsession.sig_chan_message(NETCHAN_TERRAIN_ARRAY), this, &NetworkClient::on_terrain_array); |
14 slots.connect(netsession.sig_chan_message(NETCHAN_TERRAIN_ARRAY), this, &NetworkClient::on_terrain_array); |
20 |
15 |
21 // XXX: sig_disconnected |
16 // XXX: sig_disconnected |
22 } |
|
23 |
|
24 void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacketInput &pkt) { |
|
25 // read the packet |
|
26 Vector position = pkt.read_vector(); |
|
27 |
|
28 Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << position; |
|
29 |
|
30 // create the LocalPlayer object |
|
31 NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, position); |
|
32 |
|
33 // inform state |
|
34 state.newLocalPlayer(player); |
|
35 } |
|
36 |
|
37 void NetworkClient::on_player_info (NetworkObject_Client *obj, NetworkPacketInput &pkt) { |
|
38 // read the packet |
|
39 Vector position = pkt.read_vector(); |
|
40 |
|
41 Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << position; |
|
42 |
|
43 // create the LocalPlayer object |
|
44 NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position); |
|
45 |
|
46 // inform state |
|
47 state.newPlayer(player); |
|
48 |
|
49 } |
|
50 |
|
51 void NetworkClient::on_player_join (NetworkObject_Client *obj, NetworkPacketInput &pkt) { |
|
52 // read the packet |
|
53 Vector position = pkt.read_vector(); |
|
54 |
|
55 Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << position; |
|
56 |
|
57 // create the RemotePlayer object |
|
58 NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position); |
|
59 |
|
60 // inform state |
|
61 state.newPlayer(player); |
|
62 } |
|
63 |
|
64 void NetworkClient::on_projectile_create (NetworkObject_Client *obj, NetworkPacketInput &pkt) { |
|
65 // read the packet |
|
66 Vector position = pkt.read_vector(); |
|
67 Vector velocity = pkt.read_vector(); |
|
68 float explosionRadius = pkt.read_float32(); |
|
69 float radius = pkt.read_float32(); |
|
70 |
|
71 Engine::log(INFO, "client.on_projectile_create") << "obj=" << obj << ", pos=" << position << ", velocity=" << velocity; |
|
72 |
|
73 // create the NetworkClientPorjectile object |
|
74 new NetworkClientProjectile(*this, obj, position, velocity, explosionRadius, radius); |
|
75 } |
17 } |
76 |
18 |
77 void NetworkClient::on_terrain_array (NetworkPacketInput &pkt, NetworkNode *node) { |
19 void NetworkClient::on_terrain_array (NetworkPacketInput &pkt, NetworkNode *node) { |
78 // ignore if not from server |
20 // ignore if not from server |
79 if (node != server) |
21 if (node != server) |
104 // XXX: leak because deleting the slot while it's being called breaks ClanLib |
46 // XXX: leak because deleting the slot while it's being called breaks ClanLib |
105 // delete player; |
47 // delete player; |
106 } |
48 } |
107 |
49 |
108 /* |
50 /* |
109 * NetworkClientObjectHelper |
51 * NetworkClientController |
110 */ |
52 */ |
111 NetworkClientObjectHelper::NetworkClientObjectHelper (NetworkClient &client, NetworkObject_Client *obj) : |
53 NetworkClientController::NetworkClientController (NetworkClient &client) : |
112 client(client), obj(obj) |
54 NetworkObject_ClientController(client.netsession, NETCHAN_CORE, client.server), client(client) |
113 { |
55 { |
114 |
56 |
115 } |
57 } |
116 |
58 |
117 /* |
59 void NetworkClientController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) { |
118 * NetworkClientPlayerHelper |
60 switch (msg_id) { |
119 */ |
61 case NETMSG_SERVER_HELLO: |
120 NetworkClientPlayerHelper::NetworkClientPlayerHelper (NetworkClient &client, Vector position, NetworkObject_Client *obj) : |
62 on_server_hello(obj_id, pkt); |
121 NetworkClientObjectHelper(client, obj), Player(client.state, position, true) |
63 break; |
122 { |
64 |
123 slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientPlayerHelper::on_position ); |
65 case NETMSG_PLAYER_INFO: |
124 slots.connect(obj->sig_message(NETMSG_PLAYER_DIG), this, &NetworkClientPlayerHelper::on_dig ); |
66 on_player_info(obj_id, pkt); |
125 slots.connect(obj->sig_message(NETMSG_PLAYER_WEAPON_CHANGE), this, &NetworkClientPlayerHelper::on_weapon_change ); |
67 break; |
126 slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_THROW), this, &NetworkClientPlayerHelper::on_rope_throw ); |
68 |
127 slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_FIXED), this, &NetworkClientPlayerHelper::on_rope_fixed ); |
69 case NETMSG_PLAYER_JOIN: |
128 slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_RELEASED), this, &NetworkClientPlayerHelper::on_rope_released ); |
70 on_player_join(obj_id, pkt); |
129 slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_LENGTH), this, &NetworkClientPlayerHelper::on_rope_length ); |
71 break; |
130 |
72 |
131 } |
73 case NETMSG_PROJECTILE_CREATE: |
132 |
74 on_projectile_create(obj_id, pkt); |
133 void NetworkClientPlayerHelper::on_position (NetworkPacketInput &pkt) { |
75 break; |
|
76 |
|
77 default: |
|
78 Engine::log(WARN, "client.handle_create") << "Unknown object create message: obj_id=" << obj_id << ", msg_id=" << msg_id; |
|
79 } |
|
80 } |
|
81 |
|
82 void NetworkClientController::on_server_hello (NetworkObjectID obj_id, NetworkPacketInput &pkt) { |
|
83 // read the packet |
|
84 Vector position = pkt.read_vector(); |
|
85 |
|
86 Engine::log(INFO, "client.on_server_hello") << this << ": pos=" << position; |
|
87 |
|
88 // create the LocalPlayer object |
|
89 new NetworkClientLocalPlayer(client, obj_id, position); |
|
90 } |
|
91 |
|
92 void NetworkClientController::on_player_info (NetworkObjectID obj_id, NetworkPacketInput &pkt) { |
|
93 // read the packet |
|
94 Vector position = pkt.read_vector(); |
|
95 |
|
96 Engine::log(INFO, "client.on_player_info") << this << ": pos=" << position; |
|
97 |
|
98 // create the LocalPlayer object |
|
99 new NetworkClientRemotePlayer(client, obj_id, position); |
|
100 } |
|
101 |
|
102 void NetworkClientController::on_player_join (NetworkObjectID obj_id, NetworkPacketInput &pkt) { |
|
103 // read the packet |
|
104 Vector position = pkt.read_vector(); |
|
105 |
|
106 Engine::log(INFO, "client.on_player_join") << this << ": pos=" << position; |
|
107 |
|
108 // create the RemotePlayer object |
|
109 new NetworkClientRemotePlayer(client, obj_id, position); |
|
110 } |
|
111 |
|
112 void NetworkClientController::on_projectile_create (NetworkObjectID obj_id, NetworkPacketInput &pkt) { |
|
113 // read the packet |
|
114 Vector position = pkt.read_vector(); |
|
115 Vector velocity = pkt.read_vector(); |
|
116 float explosionRadius = pkt.read_float32(); |
|
117 float radius = pkt.read_float32(); |
|
118 |
|
119 Engine::log(INFO, "client.on_projectile_create") << this << ": pos=" << position << ", velocity=" << velocity; |
|
120 |
|
121 // create the NetworkClientPorjectile object |
|
122 new NetworkClientProjectile(client, obj_id, position, velocity, explosionRadius, radius); |
|
123 } |
|
124 |
|
125 /* |
|
126 * NetworkClientObject |
|
127 */ |
|
128 NetworkClientObject::NetworkClientObject (NetworkClient &client, NetworkObjectID obj_id) : |
|
129 NetworkObject_Client(client.controller, obj_id), client(client) |
|
130 { |
|
131 |
|
132 } |
|
133 |
|
134 /* |
|
135 * NetworkClientPlayerBase |
|
136 */ |
|
137 NetworkClientPlayerBase::NetworkClientPlayerBase (NetworkClient &client, NetworkObjectID obj_id, Vector position) : |
|
138 NetworkClientObject(client, obj_id), Player(client.state, position, true) |
|
139 { |
|
140 slots.connect(sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientPlayerBase::on_position ); |
|
141 slots.connect(sig_message(NETMSG_PLAYER_DIG), this, &NetworkClientPlayerBase::on_dig ); |
|
142 slots.connect(sig_message(NETMSG_PLAYER_WEAPON_CHANGE), this, &NetworkClientPlayerBase::on_weapon_change ); |
|
143 slots.connect(sig_message(NETMSG_PLAYER_ROPE_THROW), this, &NetworkClientPlayerBase::on_rope_throw ); |
|
144 slots.connect(sig_message(NETMSG_PLAYER_ROPE_FIXED), this, &NetworkClientPlayerBase::on_rope_fixed ); |
|
145 slots.connect(sig_message(NETMSG_PLAYER_ROPE_RELEASED), this, &NetworkClientPlayerBase::on_rope_released ); |
|
146 slots.connect(sig_message(NETMSG_PLAYER_ROPE_LENGTH), this, &NetworkClientPlayerBase::on_rope_length ); |
|
147 } |
|
148 |
|
149 void NetworkClientPlayerBase::on_position (NetworkPacketInput &pkt) { |
134 Vector position = pkt.read_vector(); |
150 Vector position = pkt.read_vector(); |
135 Vector velocity = pkt.read_vector(); |
151 Vector velocity = pkt.read_vector(); |
136 int flags = pkt.read_uint8(); |
152 int flags = pkt.read_uint8(); |
137 float aim = pkt.read_float32(); |
153 float aim = pkt.read_float32(); |
138 |
154 |
144 flags & NETWORK_PHYSICS_FACE_RIGHT ? FACING_RIGHT : FACING_LEFT, |
160 flags & NETWORK_PHYSICS_FACE_RIGHT ? FACING_RIGHT : FACING_LEFT, |
145 aim |
161 aim |
146 ); |
162 ); |
147 } |
163 } |
148 |
164 |
149 void NetworkClientPlayerHelper::on_dig (NetworkPacketInput &pkt) { |
165 void NetworkClientPlayerBase::on_dig (NetworkPacketInput &pkt) { |
150 Vector position = pkt.read_vector(); |
166 Vector position = pkt.read_vector(); |
151 float radius = pkt.read_float32(); |
167 float radius = pkt.read_float32(); |
152 |
168 |
153 Engine::log(INFO, "client_player.on_dig") << "obj=" << obj << ", position=" << position << ", radius=" << radius; |
169 Engine::log(INFO, "client_player.on_dig") << this << ": position=" << position << ", radius=" << radius; |
154 |
170 |
155 // just update... |
171 // just update... |
156 handleDig(position, radius); |
172 handleDig(position, radius); |
157 } |
173 } |
158 |
174 |
159 void NetworkClientPlayerHelper::on_weapon_change (NetworkPacketInput &pkt) { |
175 void NetworkClientPlayerBase::on_weapon_change (NetworkPacketInput &pkt) { |
160 uint8_t weapon_index = pkt.read_uint8(); |
176 uint8_t weapon_index = pkt.read_uint8(); |
161 |
177 |
162 Engine::log(INFO, "client_player.on_weapon_change") << "obj=" << obj << ", weapon_index=" << weapon_index; |
178 Engine::log(INFO, "client_player.on_weapon_change") << this << ": weapon_index=" << weapon_index; |
163 |
179 |
164 handleChangeWeapon(weapon_index); |
180 handleChangeWeapon(weapon_index); |
165 } |
181 } |
166 |
182 |
167 void NetworkClientPlayerHelper::on_rope_throw (NetworkPacketInput &pkt) { |
183 void NetworkClientPlayerBase::on_rope_throw (NetworkPacketInput &pkt) { |
168 Vector position = pkt.read_vector(); |
184 Vector position = pkt.read_vector(); |
169 Vector velocity = pkt.read_vector(); |
185 Vector velocity = pkt.read_vector(); |
170 float length = pkt.read_float32(); |
186 float length = pkt.read_float32(); |
171 |
187 |
172 Engine::log(INFO, "client_player.on_rope_throw") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity << ", length=" << length; |
188 Engine::log(INFO, "client_player.on_rope_throw") << this << ": position=" << position << ", velocity=" << velocity << ", length=" << length; |
173 |
189 |
174 rope.updateState(ROPE_FLYING, position, velocity, length); |
190 rope.updateState(ROPE_FLYING, position, velocity, length); |
175 } |
191 } |
176 |
192 |
177 void NetworkClientPlayerHelper::on_rope_fixed (NetworkPacketInput &pkt) { |
193 void NetworkClientPlayerBase::on_rope_fixed (NetworkPacketInput &pkt) { |
178 Vector position = pkt.read_vector(); |
194 Vector position = pkt.read_vector(); |
179 float length = pkt.read_float32(); |
195 float length = pkt.read_float32(); |
180 |
196 |
181 Engine::log(INFO, "client_player.on_rope_fixed") << "obj=" << obj << ", position=" << position << ", length=" << length; |
197 Engine::log(INFO, "client_player.on_rope_fixed") << this << ": position=" << position << ", length=" << length; |
182 |
198 |
183 rope.updateState(ROPE_FIXED, position, Vector(0, 0), length); |
199 rope.updateState(ROPE_FIXED, position, Vector(0, 0), length); |
184 } |
200 } |
185 |
201 |
186 void NetworkClientPlayerHelper::on_rope_released (NetworkPacketInput &pkt) { |
202 void NetworkClientPlayerBase::on_rope_released (NetworkPacketInput &pkt) { |
187 Engine::log(INFO, "client_player.on_rope_released") << "obj=" << obj; |
203 Engine::log(INFO, "client_player.on_rope_released") << this; |
188 |
204 |
189 // use rope.getPosition() instead of e.g. Vector(0, 0) because it will collide there... |
205 // use rope.getPosition() instead of e.g. Vector(0, 0) because it will collide there... |
190 rope.updateState(ROPE_FOLDED, rope.getPosition(), Vector(0, 0), 0); |
206 rope.updateState(ROPE_FOLDED, rope.getPosition(), Vector(0, 0), 0); |
191 } |
207 } |
192 |
208 |
193 void NetworkClientPlayerHelper::on_rope_length (NetworkPacketInput &pkt) { |
209 void NetworkClientPlayerBase::on_rope_length (NetworkPacketInput &pkt) { |
194 float length = pkt.read_float32(); |
210 float length = pkt.read_float32(); |
195 |
211 |
196 Engine::log(INFO, "client_player.on_rope_length") << "obj=" << obj << ", length=" << length; |
212 Engine::log(INFO, "client_player.on_rope_length") << this << ": length=" << length; |
197 |
213 |
198 rope.updateLength(length); |
214 rope.updateLength(length); |
199 } |
215 } |
200 |
216 |
201 NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) : |
217 /* |
202 Player(client.state, position, true), NetworkClientPlayerHelper(client, position, obj) { |
218 * NetworkClientLocalPlayer |
203 |
219 */ |
|
220 NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObjectID obj_id, Vector position) : |
|
221 Player(client.state, position, true), NetworkClientPlayerBase(client, obj_id, position) |
|
222 { |
|
223 // set ourselves as the local player |
|
224 state.setLocalPlayer(this); |
204 } |
225 } |
205 |
226 |
206 void NetworkClientLocalPlayer::handleInput (PlayerInput input) { |
227 void NetworkClientLocalPlayer::handleInput (PlayerInput input) { |
207 // always send move, in all cases |
228 // always send move, in all cases |
208 NetworkPacket pkt; |
229 NetworkPacket pkt; |
209 pkt.write_uint16(input); |
230 pkt.write_uint16(input); |
210 |
231 |
211 obj->send(NETMSG_CLIENT_INPUT, pkt, false); |
232 send(NETMSG_CLIENT_INPUT, pkt, false); |
212 |
233 |
213 // do not handle locally |
234 // do not handle locally |
214 } |
235 } |
215 |
236 |
216 NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) : |
237 /* |
217 Player(client.state, position, true), NetworkClientPlayerHelper(client, position, obj) { |
238 * NetworkClientRemotePlayer |
|
239 */ |
|
240 NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, NetworkObjectID obj_id, Vector position) : |
|
241 Player(client.state, position, true), NetworkClientPlayerBase(client, obj_id, position) { |
218 |
242 |
219 // receive messages |
243 // receive messages |
220 slots.connect(obj->sig_message(NETMSG_PLAYER_QUIT), this, &NetworkClientRemotePlayer::on_quit); |
244 slots.connect(sig_message(NETMSG_PLAYER_QUIT), this, &NetworkClientRemotePlayer::on_quit); |
221 } |
245 } |
222 |
246 |
223 void NetworkClientRemotePlayer::on_quit (NetworkPacketInput &pkt) { |
247 void NetworkClientRemotePlayer::on_quit (NetworkPacketInput &pkt) { |
224 // pkt is empty |
248 // pkt is empty |
225 (void) pkt; |
249 (void) pkt; |
226 |
250 |
227 Engine::log(INFO, "client_player.on_quit") << "obj=" << obj; |
251 Engine::log(INFO, "client_player.on_quit") << this; |
228 |
252 |
229 client.player_quit(this); |
253 client.player_quit(this); |
230 } |
254 } |
231 |
255 |
232 NetworkClientProjectile::NetworkClientProjectile (NetworkClient &client, NetworkObject_Client *obj, Vector position, |
256 NetworkClientProjectile::NetworkClientProjectile (NetworkClient &client, NetworkObjectID obj_id, Vector position, |
233 Vector velocity, float explosionRadius, float radius) : |
257 Vector velocity, float explosionRadius, float radius) : |
234 NetworkClientObjectHelper(client, obj), Projectile(client.state, position, velocity, true, explosionRadius, radius) |
258 NetworkClientObject(client, obj_id), Projectile(client.state, position, velocity, explosionRadius, radius, 100 /* XXX */) |
235 { |
259 { |
236 // hook up signals |
260 // hook up signals |
237 slots.connect(obj->sig_message(NETMSG_PROJECTILE_DESTROY), this, &NetworkClientProjectile::on_destroy); |
261 slots.connect(sig_message(NETMSG_PROJECTILE_DESTROY), this, &NetworkClientProjectile::on_destroy); |
238 } |
262 } |
239 |
263 |
240 void NetworkClientProjectile::onDestroy (Vector position, bool removeGround) { |
264 void NetworkClientProjectile::onDestroy (Vector position, bool removeGround) { |
241 // ignore :> |
265 // ignore :> |
242 } |
266 } |
243 |
267 |
244 void NetworkClientProjectile::on_destroy (NetworkPacketInput &pkt) { |
268 void NetworkClientProjectile::on_destroy (NetworkPacketInput &pkt) { |
245 Vector position = pkt.read_vector(); |
269 Vector position = pkt.read_vector(); |
246 uint8_t flags = pkt.read_uint8(); |
270 uint8_t flags = pkt.read_uint8(); |
247 |
271 |
248 Engine::log(INFO, "client_projectile.on_destroy") << "obj=" << obj << ", position=" << position << ", flags=" << flags; |
272 Engine::log(INFO, "client_projectile.on_destroy") << this << ": position=" << position << ", flags=" << flags; |
249 |
273 |
250 // XXX: leak obj, not yet implemented: obj.destory(); |
274 // XXX: leak obj, not yet implemented: obj.destory(); |
251 |
275 |
252 // pass on to super |
276 // pass on to super |
253 Projectile::onDestroy(position, flags & NETWORK_PROJECTILE_REMOVE_GROUND); |
277 Projectile::onDestroy(position, flags & NETWORK_PROJECTILE_REMOVE_GROUND); |
254 } |
278 } |
|
279 |