#include "NetworkClient.hh"
#include "Engine.hh"
#include "Logger.hh"
#include <cassert>
NetworkClient::NetworkClient (GameState &state, const CL_IPAddress &connect_to) :
NetworkCore(state), server(netsession.connect(connect_to)) {
// connect slots
slots.connect(netobjs.sig_create_object(), this, &NetworkClient::on_create_object);
// XXX: sig_disconnected
}
void NetworkClient::on_create_object (CL_NetObject_Client &obj, int msg_type, CL_NetPacket &pkt) {
switch (msg_type) {
case NETMSG_SERVER_HELLO:
on_server_hello(obj, pkt);
break;
case NETMSG_PLAYER_INFO:
on_player_info(obj, pkt);
break;
case NETMSG_PLAYER_JOIN:
on_player_join(obj, pkt);
break;
default:
Engine::log(WARN, "client.on_create_object") << "unknown msg_type=" << msg_type << " for obj=" << obj;
}
}
void NetworkClient::on_server_hello (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
uint32_t x = pkt.input.read_uint32();
uint32_t y = pkt.input.read_uint32();
Coordinate initial_position(x, y);
Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << initial_position;
// create the LocalPlayer object
NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, initial_position);
// inform state
state.newLocalPlayer(player);
}
void NetworkClient::on_player_info (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
uint32_t x = pkt.input.read_uint32();
uint32_t y = pkt.input.read_uint32();
Coordinate initial_position(x, y);
Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << initial_position;
// create the LocalPlayer object
NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, initial_position);
// inform state
state.newRemotePlayer(player);
}
void NetworkClient::on_player_join (CL_NetObject_Client &obj, CL_NetPacket &pkt) {
// read the packet
uint32_t x = pkt.input.read_uint32();
uint32_t y = pkt.input.read_uint32();
Coordinate initial_position(x, y);
Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << initial_position;
// create the RemotePlayer object
NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, initial_position);
// inform state
state.newRemotePlayer(player);
}
void NetworkClient::player_quit (NetworkClientRemotePlayer *player) {
// inform state
state.removePlayer(player);
// delete
// XXX: leak because deleting the slot while it's being called breaks ClanLib
// delete player;
}
NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position) :
LocalPlayer(client.state, initial_position, true), client(client), obj(obj) {
// receive messages
slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
}
bool NetworkClientLocalPlayer::move (PositionDelta d) {
// always send move, in all cases
CL_NetPacket pkt;
pkt.output.write_int32(d.dx);
pkt.output.write_int32(d.dy);
obj.send(NETMSG_CLIENT_MOVE, pkt, false);
// return validity
return LocalPlayer::move(d);
}
void NetworkClientLocalPlayer::on_position (CL_NetPacket &pkt) {
uint32_t x = pkt.input.read_uint32();
uint32_t y = pkt.input.read_uint32();
Coordinate pos (x, y);
Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
assert(updatePosition(pos));
}
NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, CL_NetObject_Client &obj, Coordinate initial_position) :
RemotePlayer(client.state, initial_position, true), client(client), obj(obj) {
// receive messages
slots.connect(obj.sig_received_message(NETMSG_PLAYER_POSITION), this, &NetworkClientRemotePlayer::on_position);
slots.connect(obj.sig_received_message(NETMSG_PLAYER_QUIT), this, &NetworkClientRemotePlayer::on_quit);
}
void NetworkClientRemotePlayer::on_position (CL_NetPacket &pkt) {
uint32_t x = pkt.input.read_uint32();
uint32_t y = pkt.input.read_uint32();
Coordinate pos (x, y);
Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", pos=" << pos;
assert(updatePosition(pos));
}
void NetworkClientRemotePlayer::on_quit (CL_NetPacket &pkt) {
// pkt is empty
(void) pkt;
Engine::log(INFO, "client_player.on_quit") << "obj=" << obj;
client.player_quit(this);
}