Connection disconnects now working
This commit is contained in:
parent
f173281614
commit
efe25fe610
@ -15,8 +15,12 @@ Client::Client()
|
|||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
// Send disconnect message
|
// Send disconnect message
|
||||||
|
bool connection_closed = false;
|
||||||
|
double close_timer;
|
||||||
sf::Packet client_packet;
|
sf::Packet client_packet;
|
||||||
sf::Uint8 packet_type = PLAYER_DISCONNECT;
|
sf::Uint8 packet_type = PLAYER_DISCONNECT;
|
||||||
|
Timer client_timer;
|
||||||
|
client_timer.Init();
|
||||||
client_packet.clear();
|
client_packet.clear();
|
||||||
client_packet << packet_type;
|
client_packet << packet_type;
|
||||||
client_packet << current_player;
|
client_packet << current_player;
|
||||||
@ -25,16 +29,52 @@ Client::~Client()
|
|||||||
// No time out needed here, since the
|
// No time out needed here, since the
|
||||||
// message will timeout after a couple of attempts
|
// message will timeout after a couple of attempts
|
||||||
// then exit anyway.
|
// then exit anyway.
|
||||||
while(m_net_client->pendingMessages())
|
close_timer = Timer::GetTimeDouble();
|
||||||
|
while(!connection_closed)
|
||||||
{
|
{
|
||||||
|
// Time must be updated before any messages are sent
|
||||||
|
// Especially guaranteed messages, since the time needs to be
|
||||||
|
// non zero.
|
||||||
|
client_timer.Update();
|
||||||
|
|
||||||
m_net_client->Receive();
|
m_net_client->Receive();
|
||||||
|
|
||||||
|
while(m_net_client->getData(client_packet))
|
||||||
|
{
|
||||||
|
sf::Uint8 packet_type;
|
||||||
|
client_packet >> packet_type;
|
||||||
|
switch(packet_type)
|
||||||
|
{
|
||||||
|
case PLAYER_DISCONNECT:
|
||||||
|
{
|
||||||
|
sf::Uint8 player_index;
|
||||||
|
// This completely removes the player from the game
|
||||||
|
// Deletes member from the player list
|
||||||
|
client_packet >> player_index;
|
||||||
|
if(player_index == current_player)
|
||||||
|
{
|
||||||
|
connection_closed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_net_client->Transmit();
|
m_net_client->Transmit();
|
||||||
|
|
||||||
// temporary for now. otherwise this thread consumed way too processing
|
// temporary for now. otherwise this thread consumed way too processing
|
||||||
sf::sleep(sf::seconds(0.005)); // 5 milli-seconds
|
sf::sleep(sf::seconds(0.005)); // 5 milli-seconds
|
||||||
|
|
||||||
|
// If the server does not respond within one second just close
|
||||||
|
// and the server can deal with the problems.
|
||||||
|
if((Timer::GetTimeDouble() - close_timer) > 1.0)
|
||||||
|
{
|
||||||
|
connection_closed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_net_client->Destroy();
|
m_net_client->Destroy();
|
||||||
|
m_players.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,15 +160,16 @@ void Client::update(double elapsed_time)
|
|||||||
{
|
{
|
||||||
case PLAYER_CONNECT:
|
case PLAYER_CONNECT:
|
||||||
{
|
{
|
||||||
sf::Uint32 players_address = 0u;
|
sf::Uint16 players_port = sf::Socket::AnyPort;
|
||||||
sf::Uint8 pindex;
|
sf::Uint8 pindex;
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
client_packet >> pindex;
|
client_packet >> pindex;
|
||||||
client_packet >> name;
|
client_packet >> name;
|
||||||
client_packet >> players_address;
|
client_packet >> players_port;
|
||||||
// Should be a much better way of doing this.
|
// Should be a much better way of doing this.
|
||||||
// Perhaps generate a random number
|
// Perhaps generate a random number
|
||||||
if((sf::Uint32)((sf::Uint64)(&m_players)) == players_address)
|
if((name == current_player_name) &&
|
||||||
|
(m_net_client->getLocalPort() == players_port))
|
||||||
{
|
{
|
||||||
current_player = pindex;
|
current_player = pindex;
|
||||||
}
|
}
|
||||||
@ -245,16 +286,16 @@ void Client::update(double elapsed_time)
|
|||||||
else if(!registered_player)
|
else if(!registered_player)
|
||||||
{
|
{
|
||||||
// Needs to be 32 bit so that the packet << overload will work.
|
// Needs to be 32 bit so that the packet << overload will work.
|
||||||
sf::Uint32 players_address = (sf::Uint32)((sf::Uint64)(&m_players));
|
sf::Uint16 players_port = m_net_client->getLocalPort();
|
||||||
sf::Uint8 packet_type = PLAYER_CONNECT;
|
sf::Uint8 packet_type = PLAYER_CONNECT;
|
||||||
client_packet.clear();
|
client_packet.clear();
|
||||||
client_packet << packet_type;
|
client_packet << packet_type;
|
||||||
client_packet << current_player;
|
client_packet << current_player;
|
||||||
client_packet << current_player_name;
|
client_packet << current_player_name;
|
||||||
// Send the address of the players map. This will server as a unique
|
// Send the players port. This will server as a unique
|
||||||
// identifier and prevent users with the same name from controlling
|
// identifier and prevent users with the same name from controlling
|
||||||
// each other.
|
// each other.
|
||||||
client_packet << players_address;
|
client_packet << players_port;
|
||||||
m_net_client->sendData(client_packet, true);
|
m_net_client->sendData(client_packet, true);
|
||||||
registered_player = true;
|
registered_player = true;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ void Network::Create(sf::Uint16 port, sf::IpAddress address )
|
|||||||
{
|
{
|
||||||
tmpclient.addr = address;
|
tmpclient.addr = address;
|
||||||
tmpclient.port = port;
|
tmpclient.port = port;
|
||||||
|
tmpclient.disconnect = DISCONNECTED;
|
||||||
numclients = addClients(&tmpclient, ¤t_client);
|
numclients = addClients(&tmpclient, ¤t_client);
|
||||||
|
|
||||||
net_socket.bind( sf::Socket::AnyPort );
|
net_socket.bind( sf::Socket::AnyPort );
|
||||||
@ -48,10 +49,11 @@ void Network::Create(sf::Uint16 port, sf::IpAddress address )
|
|||||||
void Network::Destroy( void )
|
void Network::Destroy( void )
|
||||||
{
|
{
|
||||||
/* Clean and exit */
|
/* Clean and exit */
|
||||||
|
Reset();
|
||||||
net_socket.unbind();
|
net_socket.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Network::getData(sf::Packet& p)
|
bool Network::getData(sf::Packet& p, sf::Uint8* sending_client)
|
||||||
{
|
{
|
||||||
bool rtn = false;
|
bool rtn = false;
|
||||||
sf::Uint16 curcl;
|
sf::Uint16 curcl;
|
||||||
@ -64,6 +66,10 @@ bool Network::getData(sf::Packet& p)
|
|||||||
{
|
{
|
||||||
p = clients[curcl].receive.front();
|
p = clients[curcl].receive.front();
|
||||||
clients[curcl].receive.pop();
|
clients[curcl].receive.pop();
|
||||||
|
if(sending_client != NULL)
|
||||||
|
{
|
||||||
|
*sending_client = curcl;
|
||||||
|
}
|
||||||
rtn = true;
|
rtn = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -75,26 +81,33 @@ bool Network::getData(sf::Packet& p)
|
|||||||
|
|
||||||
bool Network::queueTransmitMessage(Network_Messages_T msg_type , sf::Packet p, Client_t * dest)
|
bool Network::queueTransmitMessage(Network_Messages_T msg_type , sf::Packet p, Client_t * dest)
|
||||||
{
|
{
|
||||||
sf::Packet packet;
|
bool added_message_to_queue = false;
|
||||||
sf::Uint8 type = (sf::Uint8)msg_type;
|
// Only queue a message if there are clients to receive it
|
||||||
sf::Uint32 uid = UNIQUE_ID;
|
if(numclients > 0)
|
||||||
sf::Uint32 msg_id = getUniqueMessageId();
|
{
|
||||||
Transmit_Message_t* message = new Transmit_Message_t();
|
sf::Packet packet;
|
||||||
|
sf::Uint8 type = (sf::Uint8)msg_type;
|
||||||
|
sf::Uint32 uid = UNIQUE_ID;
|
||||||
|
sf::Uint32 msg_id = getUniqueMessageId();
|
||||||
|
Transmit_Message_t* message = new Transmit_Message_t();
|
||||||
|
|
||||||
// Add this to the list of packets expecting a response
|
// Add this to the list of packets expecting a response
|
||||||
packet << uid;
|
packet << uid;
|
||||||
packet << type;
|
packet << type;
|
||||||
packet << msg_id;
|
packet << msg_id;
|
||||||
packet.append(p.getData(), p.getDataSize());
|
packet.append(p.getData(), p.getDataSize());
|
||||||
|
|
||||||
message->msg_type = msg_type;
|
message->msg_type = msg_type;
|
||||||
message->Data = packet;
|
message->Data = packet;
|
||||||
message->TimeStarted = 0.0;
|
message->TimeStarted = 0.0;
|
||||||
message->dest = dest;
|
message->dest = dest;
|
||||||
|
|
||||||
transmit_queue[msg_id] = message;
|
transmit_queue[msg_id] = message;
|
||||||
|
|
||||||
return true;
|
added_message_to_queue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return added_message_to_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Network::sendData(sf::Packet& p, bool guaranteed)
|
bool Network::sendData(sf::Packet& p, bool guaranteed)
|
||||||
@ -131,6 +144,8 @@ int Network::addClients(Client_t *client, sf::Uint16 *curcl)
|
|||||||
{
|
{
|
||||||
clients[i].addr = client->addr;
|
clients[i].addr = client->addr;
|
||||||
clients[i].port = client->port;
|
clients[i].port = client->port;
|
||||||
|
// Set that a client is now connected
|
||||||
|
clients[i].disconnect = CONNECTED;
|
||||||
*curcl = i;
|
*curcl = i;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -202,6 +217,11 @@ void Network::Receive()
|
|||||||
if(MAX_NUM_CLIENTS > client_id)
|
if(MAX_NUM_CLIENTS > client_id)
|
||||||
{
|
{
|
||||||
clients[client_id].ping = Timer::GetTimeDouble() - transmit_queue[msg_id]->TimeStarted;
|
clients[client_id].ping = Timer::GetTimeDouble() - transmit_queue[msg_id]->TimeStarted;
|
||||||
|
|
||||||
|
// Need to also register that a ping message was received.
|
||||||
|
transmit_queue[msg_id]->Responses[&clients[client_id]] = Timer::GetTimeDouble();
|
||||||
|
// Received a response, so reset send attempts.
|
||||||
|
clients[client_id].num_send_attempts = 0u;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -212,6 +232,9 @@ void Network::Receive()
|
|||||||
if(MAX_NUM_CLIENTS > client_id)
|
if(MAX_NUM_CLIENTS > client_id)
|
||||||
{
|
{
|
||||||
transmit_queue[msg_id]->Responses[&clients[client_id]] = Timer::GetTimeDouble();
|
transmit_queue[msg_id]->Responses[&clients[client_id]] = Timer::GetTimeDouble();
|
||||||
|
|
||||||
|
// Received a response, so reset send attempts.
|
||||||
|
clients[client_id].num_send_attempts = 0u;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -262,16 +285,31 @@ void Network::Transmit()
|
|||||||
// Broadcast the mesages to all clients
|
// Broadcast the mesages to all clients
|
||||||
sf::Uint32 msg_id = 0;
|
sf::Uint32 msg_id = 0;
|
||||||
static double ping_timer = Timer::GetTimeDouble();
|
static double ping_timer = Timer::GetTimeDouble();
|
||||||
|
double current_time = Timer::GetTimeDouble();
|
||||||
|
|
||||||
// Once per second, send ping messages ( just for fun )
|
// Every five seconds, send ping messages
|
||||||
if((Timer::GetTimeDouble() - ping_timer) > 1000.0)
|
// Note this time must be longer than the combined
|
||||||
|
// timeout and retry count, otherwise a client will never
|
||||||
|
// be removed.
|
||||||
|
if((current_time - ping_timer) > 1.0)
|
||||||
{
|
{
|
||||||
ping_timer = Timer::GetTimeDouble();
|
ping_timer = current_time;
|
||||||
sf::Packet response;
|
sf::Packet response;
|
||||||
response.clear();
|
response.clear();
|
||||||
queueTransmitMessage(NETWORK_PING, response);
|
queueTransmitMessage(NETWORK_PING, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set any clients waiting to be removed to the
|
||||||
|
// do removal state. This will get changed in the
|
||||||
|
// Transmit loop below if there are any pending messages
|
||||||
|
for(int client_ndx = 0; client_ndx < MAX_NUM_CLIENTS; client_ndx++)
|
||||||
|
{
|
||||||
|
if(clients[client_ndx].disconnect == WAIT_DISCONNECT)
|
||||||
|
{
|
||||||
|
clients[client_ndx].disconnect = DO_DISCONNECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send any pending messages
|
// Send any pending messages
|
||||||
while(transmit_queue.find(msg_id) != transmit_queue.end())
|
while(transmit_queue.find(msg_id) != transmit_queue.end())
|
||||||
{
|
{
|
||||||
@ -306,7 +344,7 @@ void Network::Transmit()
|
|||||||
for ( std::map<Client_t*, double>::iterator iter = message->ClientTimeSent.begin(); iter != message->ClientTimeSent.end(); ++iter )
|
for ( std::map<Client_t*, double>::iterator iter = message->ClientTimeSent.begin(); iter != message->ClientTimeSent.end(); ++iter )
|
||||||
{
|
{
|
||||||
// Determine if enough time has elapsed to try and re-send
|
// Determine if enough time has elapsed to try and re-send
|
||||||
if((curTime - iter->second) >= 0.5)
|
if((curTime - iter->second) >= NETWORK_TIMEOUT)
|
||||||
{
|
{
|
||||||
// Determine if a response was already received from this client
|
// Determine if a response was already received from this client
|
||||||
if(message->Responses.find(iter->first) == message->Responses.end())
|
if(message->Responses.find(iter->first) == message->Responses.end())
|
||||||
@ -314,8 +352,26 @@ void Network::Transmit()
|
|||||||
// Resend the message to the client
|
// Resend the message to the client
|
||||||
net_socket.send(message->Data, iter->first->addr, iter->first->port);
|
net_socket.send(message->Data, iter->first->addr, iter->first->port);
|
||||||
message->ClientTimeSent[iter->first] = curTime;
|
message->ClientTimeSent[iter->first] = curTime;
|
||||||
|
|
||||||
|
// Keep track of the number of attempts
|
||||||
|
// if the number of attempts is exceeded, fake a receive message
|
||||||
|
// and set a timeout disconnect state
|
||||||
|
iter->first->num_send_attempts++;
|
||||||
|
if(MAX_NUM_SEND_ATTEMPTS < iter->first->num_send_attempts)
|
||||||
|
{
|
||||||
|
// Fake a receive message so that it will complete and be removed from the queue
|
||||||
|
message->Responses[iter->first] = Timer::GetTimeDouble();
|
||||||
|
iter->first->disconnect = TIMEOUT_DISCONNECT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are still pending messages for this client
|
||||||
|
// Move back to wait state.
|
||||||
|
if(iter->first->disconnect == DO_DISCONNECT)
|
||||||
|
{
|
||||||
|
iter->first->disconnect = WAIT_DISCONNECT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -356,6 +412,28 @@ void Network::Transmit()
|
|||||||
}
|
}
|
||||||
msg_id++;
|
msg_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Any clients that still have the disconnect action
|
||||||
|
// are now safe to remove (i.e. no longer have pending messages)
|
||||||
|
for(int client_ndx = 0; client_ndx < MAX_NUM_CLIENTS; client_ndx++)
|
||||||
|
{
|
||||||
|
if(clients[client_ndx].disconnect == DO_DISCONNECT)
|
||||||
|
{
|
||||||
|
// Reset all client information.
|
||||||
|
clients[client_ndx].addr = sf::IpAddress();
|
||||||
|
clients[client_ndx].port = 0;
|
||||||
|
clients[client_ndx].disconnect = DISCONNECTED;
|
||||||
|
while(!clients[client_ndx].receive.empty())
|
||||||
|
{
|
||||||
|
clients[client_ndx].receive.pop();
|
||||||
|
}
|
||||||
|
// Decrement the number of connected clients.
|
||||||
|
if(numclients > 0)
|
||||||
|
{
|
||||||
|
numclients--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Network::getNumConnected( void )
|
int Network::getNumConnected( void )
|
||||||
@ -370,6 +448,7 @@ void Network::Reset()
|
|||||||
{
|
{
|
||||||
clients[i].addr = sf::IpAddress();
|
clients[i].addr = sf::IpAddress();
|
||||||
clients[i].port = 0;
|
clients[i].port = 0;
|
||||||
|
clients[i].disconnect = DISCONNECTED;
|
||||||
while(!clients[i].receive.empty())
|
while(!clients[i].receive.empty())
|
||||||
{
|
{
|
||||||
clients[i].receive.pop();
|
clients[i].receive.pop();
|
||||||
@ -393,6 +472,28 @@ bool Network::pendingMessages()
|
|||||||
return (transmit_queue.size() > 0);
|
return (transmit_queue.size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf::Uint16 Network::getLocalPort()
|
||||||
|
{
|
||||||
|
return net_socket.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::disconnectClient(Client_t* player_client)
|
||||||
|
{
|
||||||
|
clients[findClient(player_client)].disconnect = WAIT_DISCONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client_t* Network::getClient( sf::Uint8 client_ndx )
|
||||||
|
{
|
||||||
|
Client_t* tmp_client = NULL;
|
||||||
|
if(client_ndx < MAX_NUM_CLIENTS)
|
||||||
|
{
|
||||||
|
tmp_client = &clients[client_ndx];
|
||||||
|
}
|
||||||
|
return tmp_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sf::Packet& operator <<(sf::Packet& Packet, const Network_Messages_T& NMT)
|
sf::Packet& operator <<(sf::Packet& Packet, const Network_Messages_T& NMT)
|
||||||
{
|
{
|
||||||
sf::Uint8 net_msg_t = (sf::Uint8)NMT;
|
sf::Uint8 net_msg_t = (sf::Uint8)NMT;
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
#define UNIQUE_ID 0xDEADBEEF
|
#define UNIQUE_ID 0xDEADBEEF
|
||||||
#define RECEIVE_BUFFER_SIZE 1024
|
#define RECEIVE_BUFFER_SIZE 1024
|
||||||
|
|
||||||
// In milliseconds
|
// In seconds
|
||||||
#define NETWORK_TIMEOUT 5000
|
#define NETWORK_TIMEOUT 1
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_NUM_SEND_ATTEMPTS 3
|
||||||
|
|
||||||
// The bit indicating if the message requires a response
|
// The bit indicating if the message requires a response
|
||||||
#define MSG_REQUIRES_RESPONSE_BIT ((sf::Uint16)1 << 15)
|
#define MSG_REQUIRES_RESPONSE_BIT ((sf::Uint16)1 << 15)
|
||||||
@ -35,11 +35,20 @@ typedef enum{
|
|||||||
NETWORK_GUARANTEED
|
NETWORK_GUARANTEED
|
||||||
}Network_Messages_T;
|
}Network_Messages_T;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
DISCONNECTED,
|
||||||
|
CONNECTED,
|
||||||
|
TIMEOUT_DISCONNECT,
|
||||||
|
WAIT_DISCONNECT,
|
||||||
|
DO_DISCONNECT
|
||||||
|
}Disconnect_States_t;
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
sf::IpAddress addr;
|
sf::IpAddress addr;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
double ping;
|
double ping;
|
||||||
|
Disconnect_States_t disconnect;
|
||||||
|
sf::Uint8 num_send_attempts;
|
||||||
std::queue<sf::Packet> receive;
|
std::queue<sf::Packet> receive;
|
||||||
}Client_t;
|
}Client_t;
|
||||||
|
|
||||||
@ -72,22 +81,25 @@ class Network{
|
|||||||
static std::map<sf::Uint32, Transmit_Message_t*> transmit_queue;
|
static std::map<sf::Uint32, Transmit_Message_t*> transmit_queue;
|
||||||
static char rxbuff[RECEIVE_BUFFER_SIZE];
|
static char rxbuff[RECEIVE_BUFFER_SIZE];
|
||||||
static sf::Clock message_timer;
|
static sf::Clock message_timer;
|
||||||
static sf::Uint32 getUniqueMessageId( void );
|
static sf::Uint32 getUniqueMessageId();
|
||||||
static int addClients(Client_t *client, sf::Uint16 *curcl);
|
static int addClients(Client_t *client, sf::Uint16 *curcl);
|
||||||
static int findClient(Client_t *client);
|
static int findClient(Client_t *client);
|
||||||
static bool queueTransmitMessage(Network_Messages_T msg_type , sf::Packet p, Client_t * dest = NULL);
|
static bool queueTransmitMessage(Network_Messages_T msg_type , sf::Packet p, Client_t * dest = NULL);
|
||||||
|
static Client_t clients[MAX_NUM_CLIENTS];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Client_t clients[MAX_NUM_CLIENTS];
|
|
||||||
static void Create( sf::Uint16 port, sf::IpAddress address );
|
static void Create( sf::Uint16 port, sf::IpAddress address );
|
||||||
static void Destroy( void );
|
static void Destroy();
|
||||||
static bool getData(sf::Packet& p);
|
static bool getData(sf::Packet& p, sf::Uint8* sending_client = NULL);
|
||||||
static bool sendData(sf::Packet& p, bool guaranteed = false);
|
static bool sendData(sf::Packet& p, bool guaranteed = false);
|
||||||
static int getNumConnected( void );
|
static int getNumConnected();
|
||||||
static void Transmit();
|
static void Transmit();
|
||||||
static void Receive();
|
static void Receive();
|
||||||
static void Reset();
|
static void Reset();
|
||||||
static bool pendingMessages();
|
static bool pendingMessages();
|
||||||
|
static sf::Uint16 getLocalPort();
|
||||||
|
static void disconnectClient(Client_t* player_client);
|
||||||
|
static Client_t* getClient( sf::Uint8 client_ndx );
|
||||||
};
|
};
|
||||||
|
|
||||||
sf::Packet& operator <<(sf::Packet& Packet, const Network_Messages_T& NMT);
|
sf::Packet& operator <<(sf::Packet& Packet, const Network_Messages_T& NMT);
|
||||||
|
@ -14,4 +14,5 @@ Player::Player()
|
|||||||
d_pressed = KEY_NOT_PRESSED;
|
d_pressed = KEY_NOT_PRESSED;
|
||||||
rel_mouse_movement = 0;
|
rel_mouse_movement = 0;
|
||||||
updated = false;
|
updated = false;
|
||||||
|
m_client = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "SFML/Config.hpp"
|
#include "SFML/Config.hpp"
|
||||||
|
#include "Network.h"
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
@ -19,6 +20,7 @@ class Player
|
|||||||
sf::Uint8 d_pressed;
|
sf::Uint8 d_pressed;
|
||||||
sf::Int32 rel_mouse_movement;
|
sf::Int32 rel_mouse_movement;
|
||||||
bool updated;
|
bool updated;
|
||||||
|
Client_t* m_client;
|
||||||
|
|
||||||
Player();
|
Player();
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ void Timer::Init(void)
|
|||||||
myClock.restart();
|
myClock.restart();
|
||||||
|
|
||||||
// Set the time keepers to zero
|
// Set the time keepers to zero
|
||||||
myTotalElapsedTime = 0;
|
totalElapsedTime = 0;
|
||||||
|
|
||||||
// Reset the game speed
|
// Reset the game speed
|
||||||
gameSpeed = 1.0f;
|
gameSpeed = 1.0f;
|
||||||
@ -22,12 +22,11 @@ void Timer::Init(void)
|
|||||||
void Timer::Update(void)
|
void Timer::Update(void)
|
||||||
{
|
{
|
||||||
// Record the time step
|
// Record the time step
|
||||||
stepTime = ((myClock.getElapsedTime().asSeconds() / 1000.0f) * gameSpeed);
|
stepTime = (myClock.getElapsedTime().asSeconds() * gameSpeed);
|
||||||
myClock.restart();
|
myClock.restart();
|
||||||
|
|
||||||
// Add the time to the total time
|
// Add the time to the total time
|
||||||
myTotalElapsedTime += stepTime;
|
totalElapsedTime += stepTime;
|
||||||
totalElapsedTime = myTotalElapsedTime;
|
|
||||||
|
|
||||||
// Calculate the game step
|
// Calculate the game step
|
||||||
curTimeStep = (sf::Uint32)(totalElapsedTime * STEPS_PER_SECOND);
|
curTimeStep = (sf::Uint32)(totalElapsedTime * STEPS_PER_SECOND);
|
||||||
@ -45,7 +44,7 @@ float Timer::GetStepTime(void)
|
|||||||
|
|
||||||
sf::Uint32 Timer::GetTotalTime(void)
|
sf::Uint32 Timer::GetTotalTime(void)
|
||||||
{
|
{
|
||||||
return (sf::Uint32)(totalElapsedTime * 1000.0f);
|
return (sf::Uint32)(totalElapsedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Timer::GetTimeDouble(void)
|
double Timer::GetTimeDouble(void)
|
||||||
|
@ -35,9 +35,6 @@ private:
|
|||||||
// The game speed
|
// The game speed
|
||||||
float gameSpeed;
|
float gameSpeed;
|
||||||
|
|
||||||
// The total elapsed time since the start of the game
|
|
||||||
double myTotalElapsedTime;
|
|
||||||
|
|
||||||
// The total elapsed time since the start of the game
|
// The total elapsed time since the start of the game
|
||||||
static double totalElapsedTime;
|
static double totalElapsedTime;
|
||||||
|
|
||||||
|
@ -46,10 +46,11 @@ void Server::update( double elapsed_time )
|
|||||||
static Player player_prev;
|
static Player player_prev;
|
||||||
const double move_speed = 75.0;
|
const double move_speed = 75.0;
|
||||||
sf::Packet server_packet;
|
sf::Packet server_packet;
|
||||||
|
sf::Uint8 tmp_player_client;
|
||||||
|
|
||||||
m_net_server->Receive();
|
m_net_server->Receive();
|
||||||
// Handle all received data (only really want the latest)
|
// Handle all received data (only really want the latest)
|
||||||
while(m_net_server->getData(server_packet))
|
while(m_net_server->getData(server_packet, &tmp_player_client))
|
||||||
{
|
{
|
||||||
sf::Uint8 ptype;
|
sf::Uint8 ptype;
|
||||||
// Get packet type
|
// Get packet type
|
||||||
@ -58,14 +59,14 @@ void Server::update( double elapsed_time )
|
|||||||
{
|
{
|
||||||
case PLAYER_CONNECT:
|
case PLAYER_CONNECT:
|
||||||
{
|
{
|
||||||
sf::Uint32 players_address = 0u;
|
sf::Uint16 players_port = sf::Socket::AnyPort;
|
||||||
refptr<Player> p = new Player();
|
refptr<Player> p = new Player();
|
||||||
std::string pname;
|
std::string pname;
|
||||||
sf::Uint8 pindex;
|
sf::Uint8 pindex;
|
||||||
|
|
||||||
server_packet >> pindex;
|
server_packet >> pindex;
|
||||||
server_packet >> pname;
|
server_packet >> pname;
|
||||||
server_packet >> players_address;
|
server_packet >> players_port;
|
||||||
// When a player connects, we need to associate
|
// When a player connects, we need to associate
|
||||||
// that player with a new ID. find first unused id
|
// that player with a new ID. find first unused id
|
||||||
// player zero means a player does not exist.
|
// player zero means a player does not exist.
|
||||||
@ -79,17 +80,18 @@ void Server::update( double elapsed_time )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->name = pname;
|
p->name = pname;
|
||||||
|
p->m_client = m_net_server->getClient(tmp_player_client);
|
||||||
m_players[pindex] = p;
|
m_players[pindex] = p;
|
||||||
|
|
||||||
// Alert all connected clients of all the connected players.
|
// Alert all connected clients of all the connected players.
|
||||||
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
||||||
{
|
{
|
||||||
sf::Uint32 paddress = ((piter->first == pindex) ? players_address : 0u);
|
sf::Uint16 port = ((piter->first == pindex) ? players_port : 0u);
|
||||||
server_packet.clear();
|
server_packet.clear();
|
||||||
server_packet << ptype;
|
server_packet << ptype;
|
||||||
server_packet << piter->first;
|
server_packet << piter->first;
|
||||||
server_packet << piter->second->name;
|
server_packet << piter->second->name;
|
||||||
server_packet << paddress;
|
server_packet << port;
|
||||||
// Send correct starting locations so that they match
|
// Send correct starting locations so that they match
|
||||||
// the other players screens.
|
// the other players screens.
|
||||||
server_packet << piter->second->direction;
|
server_packet << piter->second->direction;
|
||||||
@ -106,7 +108,8 @@ void Server::update( double elapsed_time )
|
|||||||
// then update the stored contents.
|
// then update the stored contents.
|
||||||
sf::Uint8 pindex;
|
sf::Uint8 pindex;
|
||||||
server_packet >> pindex;
|
server_packet >> pindex;
|
||||||
if(m_players.end() != m_players.find(pindex))
|
if((m_players.end() != m_players.find(pindex)) &&
|
||||||
|
(m_net_server->getClient(tmp_player_client) == m_players[pindex]->m_client))
|
||||||
{
|
{
|
||||||
server_packet >> m_players[pindex]->w_pressed;
|
server_packet >> m_players[pindex]->w_pressed;
|
||||||
server_packet >> m_players[pindex]->a_pressed;
|
server_packet >> m_players[pindex]->a_pressed;
|
||||||
@ -123,16 +126,21 @@ void Server::update( double elapsed_time )
|
|||||||
// This completely removes the player from the game
|
// This completely removes the player from the game
|
||||||
// Deletes member from the player list
|
// Deletes member from the player list
|
||||||
server_packet >> pindex;
|
server_packet >> pindex;
|
||||||
num_erased = m_players.erase(pindex);
|
if((m_players.end() != m_players.find(pindex)) &&
|
||||||
if(1 == num_erased)
|
(m_net_server->getClient(tmp_player_client) == m_players[pindex]->m_client))
|
||||||
{
|
{
|
||||||
// Player existed, alert all connected clients.
|
// Tell networking code to remove the client.
|
||||||
server_packet.clear();
|
m_net_server->disconnectClient(m_players[pindex]->m_client);
|
||||||
server_packet << ptype;
|
num_erased = m_players.erase(pindex);
|
||||||
server_packet << pindex;
|
if(1 == num_erased)
|
||||||
m_net_server->sendData(server_packet, true);
|
{
|
||||||
|
// Player exited, alert all connected clients.
|
||||||
|
server_packet.clear();
|
||||||
|
server_packet << ptype;
|
||||||
|
server_packet << pindex;
|
||||||
|
m_net_server->sendData(server_packet, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PLAYER_DEATH:
|
case PLAYER_DEATH:
|
||||||
@ -149,57 +157,82 @@ void Server::update( double elapsed_time )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end();)
|
||||||
{
|
{
|
||||||
sf::Uint8 pindex = piter->first;
|
sf::Uint8 pindex = piter->first;
|
||||||
if (KEY_PRESSED == m_players[pindex]->a_pressed)
|
// Increment to the next element. This is done in loop so that the
|
||||||
{
|
// erasing of players will not cause issues
|
||||||
double direction = m_players[pindex]->direction + M_PI_2;
|
piter++;
|
||||||
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->updated = true;
|
|
||||||
}
|
|
||||||
if (KEY_PRESSED == m_players[pindex]->d_pressed)
|
|
||||||
{
|
|
||||||
double direction = m_players[pindex]->direction - M_PI_2;
|
|
||||||
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->updated = true;
|
|
||||||
}
|
|
||||||
if (KEY_PRESSED == m_players[pindex]->w_pressed)
|
|
||||||
{
|
|
||||||
double direction = m_players[pindex]->direction;
|
|
||||||
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->updated = true;
|
|
||||||
}
|
|
||||||
if (KEY_PRESSED == m_players[pindex]->s_pressed)
|
|
||||||
{
|
|
||||||
double direction = m_players[pindex]->direction + M_PI;
|
|
||||||
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
|
||||||
m_players[pindex]->updated = true;
|
|
||||||
}
|
|
||||||
if(0 != m_players[pindex]->rel_mouse_movement)
|
|
||||||
{
|
|
||||||
m_players[pindex]->direction -= M_PI * 0.5 * m_players[pindex]->rel_mouse_movement / 1000;
|
|
||||||
m_players[pindex]->updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
server_packet.clear();
|
if(m_players[pindex]->m_client->disconnect == CONNECTED)
|
||||||
|
|
||||||
// Send the player update if there were changes
|
|
||||||
if(m_players[pindex]->updated)
|
|
||||||
{
|
{
|
||||||
sf::Uint8 ptype = PLAYER_UPDATE;
|
if (KEY_PRESSED == m_players[pindex]->a_pressed)
|
||||||
server_packet << ptype;
|
{
|
||||||
server_packet << pindex;
|
double direction = m_players[pindex]->direction + M_PI_2;
|
||||||
server_packet << m_players[pindex]->direction;
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
server_packet << m_players[pindex]->x;
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
server_packet << m_players[pindex]->y;
|
m_players[pindex]->updated = true;
|
||||||
m_net_server->sendData(server_packet);
|
}
|
||||||
m_players[pindex]->updated = false;
|
if (KEY_PRESSED == m_players[pindex]->d_pressed)
|
||||||
}
|
{
|
||||||
|
double direction = m_players[pindex]->direction - M_PI_2;
|
||||||
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
if (KEY_PRESSED == m_players[pindex]->w_pressed)
|
||||||
|
{
|
||||||
|
double direction = m_players[pindex]->direction;
|
||||||
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
if (KEY_PRESSED == m_players[pindex]->s_pressed)
|
||||||
|
{
|
||||||
|
double direction = m_players[pindex]->direction + M_PI;
|
||||||
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
if(0 != m_players[pindex]->rel_mouse_movement)
|
||||||
|
{
|
||||||
|
m_players[pindex]->direction -= M_PI * 0.5 * m_players[pindex]->rel_mouse_movement / 1000;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_packet.clear();
|
||||||
|
|
||||||
|
// Send the player update if there were changes
|
||||||
|
if(m_players[pindex]->updated)
|
||||||
|
{
|
||||||
|
sf::Uint8 ptype = PLAYER_UPDATE;
|
||||||
|
server_packet << ptype;
|
||||||
|
server_packet << pindex;
|
||||||
|
server_packet << m_players[pindex]->direction;
|
||||||
|
server_packet << m_players[pindex]->x;
|
||||||
|
server_packet << m_players[pindex]->y;
|
||||||
|
m_net_server->sendData(server_packet);
|
||||||
|
m_players[pindex]->updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_players[pindex]->m_client->disconnect == TIMEOUT_DISCONNECT)
|
||||||
|
{
|
||||||
|
// Tell networking code to remove the client.
|
||||||
|
m_net_server->disconnectClient(m_players[pindex]->m_client);
|
||||||
|
|
||||||
|
if(m_players.erase(pindex))
|
||||||
|
{
|
||||||
|
sf::Uint8 ptype = PLAYER_DISCONNECT;
|
||||||
|
// Player exited, alert all connected clients.
|
||||||
|
server_packet.clear();
|
||||||
|
server_packet << ptype;
|
||||||
|
server_packet << pindex;
|
||||||
|
m_net_server->sendData(server_packet, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_net_server->Transmit();
|
m_net_server->Transmit();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user