263 lines
6.7 KiB
C++
263 lines
6.7 KiB
C++
#include "networked_multiplayer_enet.h"
|
|
|
|
void NetworkedMultiplayerENet::set_transfer_mode(TransferMode p_mode) {
|
|
|
|
transfer_mode=p_mode;
|
|
}
|
|
|
|
void NetworkedMultiplayerENet::set_target_peer(const StringName &p_peer){
|
|
|
|
target_peer=p_peer;
|
|
}
|
|
void NetworkedMultiplayerENet::set_channel(int p_channel){
|
|
|
|
send_channel=p_channel;
|
|
}
|
|
|
|
|
|
StringName NetworkedMultiplayerENet::get_packet_peer() const{
|
|
|
|
ERR_FAIL_COND_V(!active,StringName());
|
|
ERR_FAIL_COND_V(incoming_packets.size()==0,StringName());
|
|
|
|
return incoming_packets.front()->get().from;
|
|
|
|
}
|
|
int NetworkedMultiplayerENet::get_packet_channel() const{
|
|
|
|
ERR_FAIL_COND_V(!active,0);
|
|
ERR_FAIL_COND_V(incoming_packets.size()==0,0);
|
|
return incoming_packets.front()->get().from_channel;
|
|
}
|
|
|
|
|
|
Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_max_channels, int p_in_bandwidth, int p_out_bandwidth){
|
|
|
|
ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE);
|
|
|
|
ENetAddress address;
|
|
address.host = ENET_HOST_ANY;
|
|
/* Bind the server to port 1234. */
|
|
address.port = 1234;
|
|
|
|
host = enet_host_create (& address /* the address to bind the server host to */,
|
|
p_max_clients /* allow up to 32 clients and/or outgoing connections */,
|
|
p_max_channels /* allow up to 2 channels to be used, 0 and 1 */,
|
|
p_in_bandwidth /* assume any amount of incoming bandwidth */,
|
|
p_out_bandwidth /* assume any amount of outgoing bandwidth */);
|
|
|
|
ERR_FAIL_COND_V(!host,ERR_CANT_CREATE);
|
|
|
|
active=true;
|
|
server=true;
|
|
connection_status=CONNECTION_CONNECTED;
|
|
return OK;
|
|
}
|
|
Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip,int p_port, int p_max_channels, int p_in_bandwidth, int p_out_bandwidth){
|
|
|
|
ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE);
|
|
|
|
host = enet_host_create (NULL /* create a client host */,
|
|
1 /* only allow 1 outgoing connection */,
|
|
p_max_channels /* allow up 2 channels to be used, 0 and 1 */,
|
|
p_in_bandwidth /* 56K modem with 56 Kbps downstream bandwidth */,
|
|
p_out_bandwidth /* 56K modem with 14 Kbps upstream bandwidth */);
|
|
|
|
ERR_FAIL_COND_V(!host,ERR_CANT_CREATE);
|
|
|
|
|
|
ENetAddress address;
|
|
address.host=p_ip.host;
|
|
address.port=p_port;
|
|
|
|
/* Initiate the connection, allocating the two channels 0 and 1. */
|
|
ENetPeer *peer = enet_host_connect (host, & address, p_max_channels, 0);
|
|
|
|
if (peer == NULL) {
|
|
enet_host_destroy(host);
|
|
ERR_FAIL_COND_V(!peer,ERR_CANT_CREATE);
|
|
}
|
|
|
|
//technically safe to ignore the peer or anything else.
|
|
|
|
connection_status=CONNECTION_CONNECTING;
|
|
|
|
return OK;
|
|
}
|
|
|
|
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::disconnect() {
|
|
|
|
ERR_FAIL_COND(!active);
|
|
|
|
_pop_current_packet();
|
|
|
|
enet_host_destroy(host);
|
|
active=false;
|
|
incoming_packets.clear();
|
|
|
|
connection_status=CONNECTION_DISCONNECTED;
|
|
}
|
|
|
|
int NetworkedMultiplayerENet::get_available_packet_count() const {
|
|
|
|
return incoming_packets.size();
|
|
}
|
|
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;
|
|
}
|
|
Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer,int p_buffer_size){
|
|
|
|
ERR_FAIL_COND_V(incoming_packets.size()==0,ERR_UNAVAILABLE);
|
|
|
|
Map<StringName,ENetPeer*>::Element *E=NULL;
|
|
|
|
if (target_peer!=StringName()) {
|
|
peer_map.find(target_peer);
|
|
if (!E) {
|
|
ERR_EXPLAIN("Invalid Target Peer: "+String(target_peer));
|
|
ERR_FAIL_V(ERR_INVALID_PARAMETER);
|
|
}
|
|
}
|
|
|
|
int packet_flags=0;
|
|
switch(transfer_mode) {
|
|
case TRANSFER_MODE_UNRELIABLE: {
|
|
packet_flags=ENET_PACKET_FLAG_UNSEQUENCED;
|
|
} break;
|
|
case TRANSFER_MODE_RELIABLE: {
|
|
packet_flags=ENET_PACKET_FLAG_RELIABLE;
|
|
} break;
|
|
case TRANSFER_MODE_ORDERED: {
|
|
packet_flags=ENET_PACKET_FLAG_RELIABLE;
|
|
} break;
|
|
}
|
|
|
|
/* Create a reliable packet of size 7 containing "packet\0" */
|
|
ENetPacket * packet = enet_packet_create (p_buffer,p_buffer_size,packet_flags);
|
|
|
|
if (target_peer==StringName()) {
|
|
enet_host_broadcast(host,send_channel,packet);
|
|
} else {
|
|
enet_peer_send (E->get(), send_channel, packet);
|
|
}
|
|
|
|
enet_host_flush(host);
|
|
|
|
return OK;
|
|
}
|
|
|
|
int NetworkedMultiplayerENet::get_max_packet_size() const {
|
|
|
|
return 1<<24; //anything is good
|
|
}
|
|
|
|
void NetworkedMultiplayerENet::_pop_current_packet() const {
|
|
|
|
if (current_packet.packet) {
|
|
enet_packet_destroy(current_packet.packet);
|
|
current_packet.packet=NULL;
|
|
current_packet.from=StringName();
|
|
}
|
|
|
|
}
|
|
|
|
NetworkedMultiplayerPeer::ConnectionStatus NetworkedMultiplayerENet::get_connection_status() const {
|
|
|
|
return connection_status;
|
|
}
|
|
|
|
void NetworkedMultiplayerENet::_bind_methods() {
|
|
|
|
ObjectTypeDB::bind_method(_MD("create_server","port","max_clients","max_channels","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_server,DEFVAL(32),DEFVAL(1),DEFVAL(0),DEFVAL(0));
|
|
ObjectTypeDB::bind_method(_MD("create_client","ip","port","max_channels","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_client,DEFVAL(1),DEFVAL(0),DEFVAL(0));
|
|
ObjectTypeDB::bind_method(_MD("disconnect"),&NetworkedMultiplayerENet::disconnect);
|
|
|
|
}
|
|
|
|
|
|
NetworkedMultiplayerENet::NetworkedMultiplayerENet(){
|
|
|
|
active=false;
|
|
server=false;
|
|
send_channel=0;
|
|
current_packet.packet=NULL;
|
|
transfer_mode=TRANSFER_MODE_ORDERED;
|
|
connection_status=CONNECTION_DISCONNECTED;
|
|
}
|
|
|
|
NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){
|
|
|
|
if (active) {
|
|
disconnect();
|
|
}
|
|
}
|