void NetworkedMultiplayerENet::close_connection() { if (!active) return; _pop_current_packet(); bool peers_disconnected=false; for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (E->get()) { enet_peer_disconnect_now(E->get(),unique_id); peers_disconnected=true; } } if (peers_disconnected) { enet_host_flush(host); OS::get_singleton()->delay_usec(100); //wait 100ms for disconnection packets to send } enet_host_destroy(host); active=false; incoming_packets.clear(); unique_id=1; //server is 1 connection_status=CONNECTION_DISCONNECTED; }
void NetworkedMultiplayerENet::poll(){ ERR_FAIL_COND(!active); _pop_current_packet(); ENetEvent event; /* Wait up to 1000 milliseconds for an event. */ while (enet_host_service (host, & event, 1000) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { /* Store any relevant client information here. */ IP_Address ip; ip.host=event.peer -> address.host; StringName *new_id = memnew( StringName ); *new_id = String(ip) +":"+ itos(event.peer -> address.port); peer_map[*new_id]=event.peer; connection_status=CONNECTION_CONNECTED; //if connecting, this means it connected t something! emit_signal("peer_connected",*new_id); } break; case ENET_EVENT_TYPE_DISCONNECT: { /* Reset the peer's client information. */ StringName *id = (StringName*)event.peer -> data; emit_signal("peer_disconnected",*id); peer_map.erase(*id); memdelete( id ); } break; case ENET_EVENT_TYPE_RECEIVE: { Packet packet; packet.packet = event.packet; StringName *id = (StringName*)event.peer -> data; packet.from_channel=event.channelID; packet.from=*id; incoming_packets.push_back(packet); //destroy packet later.. }break; case ENET_EVENT_TYPE_NONE: { //do nothing } break; } } }
void NetworkedMultiplayerENet::close_connection() { ERR_FAIL_COND(!active); _pop_current_packet(); enet_host_destroy(host); active=false; incoming_packets.clear(); connection_status=CONNECTION_DISCONNECTED; }
Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ ERR_FAIL_COND_V(incoming_packets.size()==0,ERR_UNAVAILABLE); _pop_current_packet(); current_packet = incoming_packets.front()->get(); incoming_packets.pop_front(); r_buffer=(const uint8_t**)¤t_packet.packet->data; r_buffer_size=current_packet.packet->dataLength; return OK; }
void NetworkedMultiplayerENet::poll(){ ERR_FAIL_COND(!active); _pop_current_packet(); ENetEvent event; /* Wait up to 1000 milliseconds for an event. */ while (true) { if (!host || !active) //might have been disconnected while emitting a notification return; int ret = enet_host_service (host, & event, 1); if (ret<0) { //error, do something? break; } else if (ret==0) { break; } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { /* Store any relevant client information here. */ if (server && refuse_connections) { enet_peer_reset(event.peer); break; } IP_Address ip; ip.host=event.peer -> address.host; int *new_id = memnew( int ); *new_id = event.data; if (*new_id==0) { //data zero is sent by server (enet won't let you configure this). Server is always 1 *new_id=1; } event.peer->data=new_id; peer_map[*new_id]=event.peer; connection_status=CONNECTION_CONNECTED; //if connecting, this means it connected t something! emit_signal("peer_connected",*new_id); if (server) { //someone connected, let it know of all the peers available for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (E->key()==*new_id) continue; //send existing peers to new peer ENetPacket * packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(E->key(),&packet->data[4]); enet_peer_send(event.peer,1,packet); //send the new peer to existing peers packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER,&packet->data[0]); encode_uint32(*new_id,&packet->data[4]); enet_peer_send(E->get(),1,packet); } } else { emit_signal("connection_succeeded"); } } break; case ENET_EVENT_TYPE_DISCONNECT: { /* Reset the peer's client information. */ int *id = (int*)event.peer -> data; if (!id) { if (!server) { emit_signal("connection_failed"); } } else { if (server) { //someone disconnected, let it know to everyone else for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (E->key()==*id) continue; //send the new peer to existing peers ENetPacket* packet = enet_packet_create (NULL,8,ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_REMOVE_PEER,&packet->data[0]); encode_uint32(*id,&packet->data[4]); enet_peer_send(E->get(),1,packet); } } else if (!server) { emit_signal("server_disconnected"); close_connection(); return; } emit_signal("peer_disconnected",*id); peer_map.erase(*id); memdelete( id ); } } break; case ENET_EVENT_TYPE_RECEIVE: { if (event.channelID==1) { //some config message ERR_CONTINUE( event.packet->dataLength < 8); int msg = decode_uint32(&event.packet->data[0]); int id = decode_uint32(&event.packet->data[4]); switch(msg) { case SYSMSG_ADD_PEER: { peer_map[id]=NULL; emit_signal("peer_connected",id); } break; case SYSMSG_REMOVE_PEER: { peer_map.erase(id); emit_signal("peer_disconnected",id); } break; } enet_packet_destroy(event.packet); } else if (event.channelID==0){ Packet packet; packet.packet = event.packet; int *id = (int*)event.peer -> data; ERR_CONTINUE(event.packet->dataLength<12) uint32_t source = decode_uint32(&event.packet->data[0]); int target = decode_uint32(&event.packet->data[4]); uint32_t flags = decode_uint32(&event.packet->data[8]); packet.from=source; if (server) { packet.from=*id; if (target==0) { //re-send the everyone but sender :| incoming_packets.push_back(packet); //and make copies for sending for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (uint32_t(E->key())==source) //do not resend to self continue; ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); enet_peer_send(E->get(),0,packet2); } } else if (target<0) { //to all but one //and make copies for sending for (Map<int,ENetPeer*>::Element *E=peer_map.front();E;E=E->next()) { if (uint32_t(E->key())==source || E->key()==-target) //do not resend to self, also do not send to excluded continue; ENetPacket* packet2 = enet_packet_create (packet.packet->data,packet.packet->dataLength,flags); enet_peer_send(E->get(),0,packet2); } if (-target != 1) { //server is not excluded incoming_packets.push_back(packet); } else { //server is excluded, erase packet enet_packet_destroy(packet.packet); } } else if (target==1) { //to myself and only myself incoming_packets.push_back(packet); } else { //to someone else, specifically ERR_CONTINUE(!peer_map.has(target)); enet_peer_send(peer_map[target],0,packet.packet); } } else { incoming_packets.push_back(packet); } //destroy packet later.. } else { ERR_CONTINUE(true); } }break; case ENET_EVENT_TYPE_NONE: { //do nothing } break; } } }