src/Network/Client.cc
changeset 274 c35307e8645c
parent 264 215de3d4de60
child 276 87434abc1ba1
equal deleted inserted replaced
273:eeb699e1d908 274:c35307e8645c
     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