stk-code_catmod/src/network_manager.cpp
hikerstk d3b4fcf8e7 Started to introduce concept of 'local player', but commit
'in between' to move a few files.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2225 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-09-07 13:33:12 +00:00

272 lines
9.3 KiB
C++

// $Id: network_manager.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "network_manager.hpp"
#include "stk_config.hpp"
#include "user_config.hpp"
#include "race_manager.hpp"
NetworkManager* network_manager = 0;
NetworkManager::NetworkManager()
{
m_mode = NW_NONE;
m_state = NS_SYNCHRONISING;
m_port = 12345;
m_server_address = "172.31.41.53";
m_num_clients = 0;
m_host_id = 0;
#ifdef HAVE_ENET
if (enet_initialize () != 0)
{
fprintf (stderr, "An error occurred while initializing ENet.\n");
exit(-1);
}
// FIXME: debugging
m_kart_info.push_back(KartInfo("tuxkart","xx", 1));
m_kart_info.push_back(KartInfo("yeti", "yy", 1));
#endif
} // NetworkManager
// -----------------------------------------------------------------------------
bool NetworkManager::initialiseConnections()
{
switch(m_mode)
{
case NW_NONE: return true;
case NW_CLIENT: return initClient();
case NW_SERVER: return initServer();
}
return true;
} // NetworkManager
// -----------------------------------------------------------------------------
NetworkManager::~NetworkManager()
{
#ifdef HAVE_ENET
if(m_mode==NW_SERVER || m_mode==NW_CLIENT) enet_host_destroy(m_host);
enet_deinitialize();
#endif
} // ~NetworkManager
// -----------------------------------------------------------------------------
bool NetworkManager::initServer()
{
#ifdef HAVE_ENET
fprintf(stderr, "Initialising server, listening on %d\n", m_port);
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = m_port;
m_host = enet_host_create (& address /* the address to bind the server host to */,
stk_config->m_max_karts /* number of connections */,
0 /* incoming bandwidth */,
0 /* outgoing bandwidth */ );
if (m_host == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet server host.\n"
"Progressing in non-network mode\n");
m_mode = NW_NONE;
return false;
}
fprintf(stderr, "Server initialised, waiting for connections ...\n");
return true;
#endif
} // initServer
// -----------------------------------------------------------------------------
bool NetworkManager::initClient()
{
fprintf(stderr, "Initialising client\n");
#ifdef HAVE_ENET
m_host = enet_host_create (NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
0 /* downstream bandwidth unlimited */,
0 /* upstream bandwidth unlimited */ );
if (m_host == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet client host.\n");
return false;
}
ENetAddress address;
ENetEvent event;
ENetPeer *peer;
enet_address_set_host (& address, m_server_address.c_str());
address.port = m_port;
/* Initiate the connection, allocating the two channels 0 and 1. */
peer = enet_host_connect (m_host, &address, 2);
if (peer == NULL)
{
fprintf (stderr,
"No available peers for initiating an ENet connection.\n");
return false;
}
/* Wait up to 5 seconds for the connection attempt to succeed. */
if (enet_host_service (m_host, & event, 5000) <= 0 ||
event.type != ENET_EVENT_TYPE_CONNECT)
{
/* Either the 5 seconds are up or a disconnect event was */
/* received. Reset the peer in the event the 5 seconds */
/* had run out without any significant event. */
enet_peer_reset (peer);
fprintf(stderr, "Connection to '%s:%d' failed.\n",
m_server_address.c_str(), m_port);
return false;
}
fprintf(stderr, "Connection to %s:%d succeeded.\n",
m_server_address.c_str(), m_port);
enet_host_service(m_host, &event, 1000);
// FIXME Receive host id from server here!!
m_host_id = 1;
return true;
#endif
} // initServer
// ----------------------------------------------------------------------------
void NetworkManager::handleNewConnection(ENetEvent *event)
{
if(m_state!=NS_SYNCHRONISING)
{
// We don't accept connections atm
return;
}
m_num_clients++;
fprintf (stderr, "A new client connected from %x:%u. Connected: %d.\n",
event->peer -> address.host,
event->peer -> address.port, m_num_clients);
// FIXME: send m_num_clients as hostid back to new client.
} // handleNewConnection
// ----------------------------------------------------------------------------
void NetworkManager::handleDisconnection(ENetEvent *event)
{
if(m_state!=NS_SYNCHRONISING)
{
fprintf(stderr, "Disconnect while in race - close your eyes and hope for the best.\n");
return;
}
fprintf(stderr, "%x:%d disconected.\n", event->peer->address.host,
event->peer->address.port );
m_num_clients--;
} // handleDisconnection
// ----------------------------------------------------------------------------
void NetworkManager::handleNewMessage(ENetEvent *event)
{
if(m_state==NS_SYNCHRONISING)
{
fprintf(stderr, "Received a receive event while waiting for client - ignored.\n");
return;
}
} // handleNewMessage
// ----------------------------------------------------------------------------
void NetworkManager::update(float dt)
{
ENetEvent event;
int result = enet_host_service (m_host, &event, 1);
if(result==0) return;
if(result<0)
{
fprintf(stderr, "Error while receiving messages -> ignored.\n");
return;
}
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT: handleNewConnection(&event); break;
case ENET_EVENT_TYPE_RECEIVE: handleNewMessage(&event); break;
case ENET_EVENT_TYPE_DISCONNECT: handleDisconnection(&event); break;
case ENET_EVENT_TYPE_NONE: break;
}
} // update
// ----------------------------------------------------------------------------
/** Send race_manager->getNumPlayers(), the kart and the name of each
player to the server.
*/
void NetworkManager::sendKartsInformationToServer()
{
for(int i=0; i<(int)race_manager->getNumLocalPlayers(); i++)
{
fprintf(stderr, "Sending name '%s', ",user_config->m_player[i].getName().c_str());
fprintf(stderr, "kart name '%s'\n", race_manager->getLocalPlayerKart(i));
} // for i<getNumLocalPlayers
fprintf(stderr, "Client sending kart information to server\n");
} // sendKartsInformationToServer
// ----------------------------------------------------------------------------
/** Receive and store the information from sendKartsInformation()
*/
void NetworkManager::waitForKartsInformation()
{
fprintf(stderr, "Server receiving all kart information\n");
// First put the local karts into the race_manager:
for(unsigned int i=0; i<(int)race_manager->getNumLocalPlayers(); i++)
{
//FIXME race_manager->setPlayerKart(i, race_manager->getLocalPlayerKart(i),
// m_host_id);
}
int offset=race_manager->getNumLocalPlayers();
for(unsigned int i=0; i<m_kart_info.size(); i++)
{
// receive number of karts, kart name, and player name for each hosts,
// and put it into the race_manager data structure:
//FIXME race_manager->setPlayerKart(offset+i, m_kart_info[i].m_kart_name,
// m_kart_info[i].m_client_id);
} // for i
} // waitForKartsInformation
// ----------------------------------------------------------------------------
/** Sends the information from the race_manager to all clients.
*/
void NetworkManager::sendRaceInformationToClients()
{
fprintf(stderr, "server sending race_manager information to all clients\n");
for(unsigned i=0; i<race_manager->getNumPlayers(); i++)
{
// fprintf(stderr, "Sending kart '%s' host %d\n",
//FIXME race_manager->getKartName(i), race_manager->getHostId(i));
} // for i
} // sendRaceInformationToClients
// ----------------------------------------------------------------------------
/** Receives and sets the race_manager information.
*/
void NetworkManager::waitForRaceInformation()
{
fprintf(stderr, "Client waiting for race information\n");
} // waitForRaceInformation
// ----------------------------------------------------------------------------