Very first alpha version of network multiplayer.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2240 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-09-07 14:34:04 +00:00
parent 545a2703b5
commit da69106378
25 changed files with 2247 additions and 1690 deletions

View File

@ -32,12 +32,15 @@ supertuxkart_SOURCES = main.cpp \
material.cpp material.hpp \
network/network_manager.cpp network/network_manager.hpp \
network/network_kart.cpp network/network_kart.hpp \
network/message.cpp network/message.hpp \
network/race_info_message.hpp network/race_info_message.cpp \
network/remote_kart_info.hpp network/character_selected_message.hpp \
network/race_start_message.hpp network/connect_message.hpp \
network.num_players_message.hpp network/world_loaded_message.hpp \
network/connect_message.hpp network/character_info_message.hpp \
network/message.cpp network/message.hpp \
network/kart_update_message.hpp network/kart_update_message.cpp \
network/kart_control_message.hpp network/kart_control_message.cpp \
utils/random_genertaor.hpp utils/random_generator.cpp \
material_manager.cpp material_manager.hpp \
grand_prix_manager.cpp grand_prix_manager.hpp \
attachment.cpp attachment.hpp \
@ -49,7 +52,7 @@ supertuxkart_SOURCES = main.cpp \
music_information.cpp music_information.hpp \
sfx_openal.cpp sfx_openal.hpp \
smoke.cpp smoke.hpp \
input.hpp \
input.hpp kart_control.hpp \
isect.cpp isect.hpp \
track.cpp track.hpp \
herring.cpp herring.hpp \

View File

@ -72,7 +72,7 @@ void Attachment::hitGreenHerring()
case ATTACH_BOMB: projectile_manager->newExplosion(m_kart->getXYZ());
m_kart->handleExplosion(m_kart->getXYZ(), /*direct_hit*/ true);
clear();
random_attachment = rand()%3;
random_attachment = m_random.get(3);
break;
case ATTACH_ANVIL :// if the kart already has an anvil, attach a new anvil,
// and increase the overall time
@ -83,7 +83,7 @@ void Attachment::hitGreenHerring()
random_attachment = 2; // anvil
leftover_time = m_time_left;
break;
default: random_attachment = rand()%3;
default: random_attachment = m_random.get(3);
} // switch
switch (random_attachment)
@ -104,7 +104,7 @@ void Attachment::hitGreenHerring()
// handled in Kart::updatePhysics
m_kart->adjustSpeedWeight(stk_config->m_anvil_speed_factor);
break ;
} // switch rand()%3
} // switch
} // hitGreenHerring
//-----------------------------------------------------------------------------

View File

@ -21,6 +21,8 @@
#define HEADER_ATTACHMENT_H
#include "stk_config.hpp"
#include "utils/random_generator.hpp"
class Kart;
// Some loop in Attachment.cpp depend on PARACHUTE being the first element,
@ -42,6 +44,7 @@ private:
ssgSelector *m_holder; // where the attachment is put on the kart
Kart *m_previous_owner; // used by bombs so that it's not passed
// back to previous owner
RandomGenerator m_random;
public:
Attachment(Kart* _kart);
~Attachment();

View File

@ -153,7 +153,7 @@ void Collectable::hitRedHerring(int n)
{
const int SPECIAL_PROB = (int)(15.0 / ((float)world->getCurrentNumKarts() /
(float)m_owner->getPosition()));
const int RAND_NUM = rand()%100;
const int RAND_NUM = m_random.get(100);
if(RAND_NUM <= SPECIAL_PROB)
{
//If the driver in the first position has finished, give the driver
@ -170,7 +170,7 @@ void Collectable::hitRedHerring(int n)
}
}
m_type = rand()%(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE;
m_type = m_random.get(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE;
m_number = 1;
return;
}
@ -182,7 +182,7 @@ void Collectable::hitRedHerring(int n)
CollectableType newC;
if(!user_config->m_profile)
{
newC = (CollectableType)(rand()%(COLLECT_MAX - 1 - 2) + 1);
newC = (CollectableType)(m_random.get(COLLECT_MAX - 1 - 2) + 1);
}
else
{ // for now: no collectables when profiling

View File

@ -23,11 +23,14 @@
#define MAX_COLLECTABLES 5
#include "collectable_manager.hpp"
#include "utils/random_generator.hpp"
class Kart;
class Collectable
{
private:
RandomGenerator m_random;
protected:
Kart* m_owner;
CollectableType m_type;

View File

@ -105,16 +105,24 @@ void GameManager::run()
}
network_manager->update(dt);
if (race_manager->raceIsActive())
{
// Busy wait if race_manager is active (i.e. creating of world is done)
// till all clients have reached this state.
if(network_manager->getState()==NetworkManager::NS_READY_SET_GO_BARRIER) continue;
// Server: Send the current position and previous controls to all clients
// Client: send current controls to server
network_manager->sendUpdates();
music_on = false;
if(user_config->m_profile) dt=1.0f/60.0f;
// In the first call dt might be large (includes loading time),
// which can cause the camera to significantly tilt
scene->draw(world->getPhase()==World::SETUP_PHASE ? 0.0f : dt);
network_manager->receiveUpdates();
if ( world->getPhase() != World::LIMBO_PHASE)
{
world->update(dt);

View File

@ -157,7 +157,7 @@ RaceGUI::handle(GameAction ga, int value)
int playerNo = ka / KC_COUNT;
ka = ka % KC_COUNT;
world->getPlayerKart(playerNo)->action((KartAction) ka, value);
world->getLocalPlayerKart(playerNo)->action((KartAction) ka, value);
return;
}
@ -170,7 +170,7 @@ RaceGUI::handle(GameAction ga, int value)
case GA_DEBUG_ADD_BOWLING:
if (race_manager->getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
Kart* kart = world->getLocalPlayerKart(0);
kart->setCollectable(COLLECT_BOWLING, 10000);
}
break;
@ -787,7 +787,7 @@ void RaceGUI::drawLap(Kart* kart, int offset_x, int offset_y,
{
// Don't display laps in follow the leader mode
if(!race_manager->raceHasLaps()) return;
if(kart->getLap()<0) return; // don't display 'lap 0/...'
float maxRatio = std::max(ratio_x, ratio_y);
char str[256];
offset_x += (int)(120*ratio_x);

File diff suppressed because it is too large Load Diff

View File

@ -26,24 +26,11 @@
#include "moveable.hpp"
#include "kart_properties.hpp"
#include "kart_control.hpp"
#include "attachment.hpp"
#include "collectable.hpp"
#include "terrain_info.hpp"
struct KartControl
{
float lr;
float accel;
bool brake;
bool wheelie;
bool jump;
bool rescue;
bool fire;
KartControl() : lr(0.0f), accel(0.0f), brake(false),
wheelie(false), jump(false), rescue(false), fire(false){}
};
class SkidMark;
class Herring;
class Smoke;
@ -189,6 +176,8 @@ public:
float getWheelieSpeedBoost() const
{return m_kart_properties->getWheelieSpeedBoost(); }
float getSteerPercent () const {return m_controls.lr; }
const KartControl&
getControls () const {return m_controls; }
float getMaxSpeed () const {return m_max_speed; }
void setTimeAtLap (float t){m_time_at_last_lap=t; }
float getTimeAtLap () const {return m_time_at_last_lap; }

View File

@ -24,9 +24,18 @@
class CharacterInfoMessage : public Message
{
// For now this is an empty message
// Add the remote host id to this message (to avoid sending this separately)
public:
CharacterInfoMessage() :Message(Message::MT_CHARACTER_INFO) {allocate(0);}
CharacterInfoMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO) {}
CharacterInfoMessage(int hostid) :Message(Message::MT_CHARACTER_INFO)
{
allocate(getLength(hostid));
add(hostid);
}
// ------------------------------------------------------------------------
CharacterInfoMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
{
int hostid=getInt();
network_manager->setHostId(hostid);
}
}; // CharacterInfoMessage
#endif

View File

@ -0,0 +1,57 @@
// $Id:kart_control_message.cpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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 "kart_control_message.hpp"
#include "world.hpp"
#include "network/network_kart.hpp"
KartControlMessage::KartControlMessage()
: Message(Message::MT_KART_CONTROL)
{
unsigned int num_local_players = world->getCurrentNumLocalPlayers();
unsigned int control_size = KartControl::getCompressedSize();
assert(control_size<=9);
allocate(control_size*num_local_players);
for(unsigned int i=0; i<num_local_players; i++)
{
const Kart *kart = world->getLocalPlayerKart(i);
const KartControl& controls = kart->getControls();
char c[9];
controls.compress(c);
add(c, control_size);
}
} // KartControlMessage
// ----------------------------------------------------------------------------
// kart_id_offset is the global id of the first kart on the host from which
// this packet was received.
KartControlMessage::KartControlMessage(ENetPacket* pkt, int kart_id_offset,
int num_local_players)
: Message(pkt, MT_KART_CONTROL)
{
assert(KartControl::getCompressedSize()<=9);
for(int i=kart_id_offset; i<kart_id_offset+num_local_players; i++)
{
char c[9];
getChar(c, KartControl::getCompressedSize());
KartControl kc;
kc.uncompress(c);
NetworkKart *kart=world->getNetworkKart(i);
kart->setControl(kc);
}
}; // KartControlMessage

View File

@ -0,0 +1,32 @@
// $Id:kart_control_message.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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.
#ifndef HEADER_KART_CONTROL_MESSAGE_H
#define HEADER_KART_CONTROL_MESSAGE_H
#include "network/message.hpp"
class KartControlMessage : public Message
{
public:
KartControlMessage();
KartControlMessage(ENetPacket* pkt, int kart_id_offset,
int num_local_players);
}; // KartUpdateMessage
#endif

View File

@ -0,0 +1,64 @@
// $Id:kart_update_message.cpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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 "kart_update_message.hpp"
#include "world.hpp"
#include "kart.hpp"
KartUpdateMessage::KartUpdateMessage()
: Message(Message::MT_KART_INFO)
{
unsigned int num_karts = world->getCurrentNumKarts();
KartControl c;
// Send the number of karts and for each kart the compressed
// control structure (3 ints) and xyz,hpr (4 floats: quaternion:
allocate(getLength(num_karts)+
num_karts*(KartControl::getCompressedSize() + 7*getLength(1.0f)) );
add(num_karts);
for(unsigned int i=0; i<num_karts; i++)
{
const Kart* kart=world->getKart(i);
const KartControl& kc=kart->getControls();
assert(KartControl::getCompressedSize()<=9);
char compressed[9]; // avoid the new/delete overhead
kc.compress(compressed);
add(compressed, KartControl::getCompressedSize());
add(kart->getXYZ());
add(kart->getRotation());
} // for i
} // KartUpdateMessage
// ----------------------------------------------------------------------------
KartUpdateMessage::KartUpdateMessage(ENetPacket* pkt)
: Message(pkt, MT_KART_INFO)
{
unsigned int num_karts = getInt();
for(unsigned int i=0; i<num_karts; i++)
{
assert(KartControl::getCompressedSize()<=9);
char compressed[9]; // avoid new/delete overhead
getChar(compressed, KartControl::getCompressedSize());
KartControl kc;
kc.uncompress(compressed);
Vec3 xyz = getVec3();
btQuaternion q = getQuaternion();
Kart *kart = world->getKart(i);
kart->setXYZ(xyz);
kart->setRotation(q);
} // for i
}; // KartUpdateMessage

View File

@ -0,0 +1,31 @@
// $Id:kart_update_message.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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.
#ifndef HEADER_KART_UPDATE_MESSAGE_H
#define HEADER_KART_UPDATE_MESSAGE_H
#include "network/message.hpp"
class KartUpdateMessage : public Message
{
public:
KartUpdateMessage();
KartUpdateMessage(ENetPacket* pkt);
}; // KartUpdateMessage
#endif

View File

@ -23,11 +23,14 @@
#include <string>
#include <vector>
#include <assert.h>
#include "btBulletDynamicsCommon.h"
#ifdef HAVE_ENET
# include "enet/enet.h"
#endif
#include "vec3.hpp"
// sjl: when a message is received, need to work out what kind of message it
// is and therefore what to do with it
@ -36,33 +39,69 @@ class Message
{
public:
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO,
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED};
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
MT_KART_INFO, MT_KART_CONTROL};
private:
ENetPacket *m_pkt;
char *m_data;
MessageType m_type;
int m_data_size;
int m_pos; // simple stack counter for constructing packet data
unsigned int m_pos; // simple stack counter for constructing packet data
bool m_needs_destroy; // only received messages need to be destroyed
protected:
bool add(int data);
#ifndef WIN32 // on windows size_t is unsigned int
bool add(size_t data) { return add((int)data); }
#endif
bool add(unsigned int data) { return add((int)data); }
bool add(float data);
bool add(const std::string &data);
bool add(const std::vector<std::string>& vs);
bool add(float data) { return add(*(int*)&data); }
bool add(char *c, unsigned int n)
{ if((int)(m_pos+n)>m_data_size)
return false;
memcpy(m_data+m_pos,c,n);
m_pos+=n;
return true; }
#ifndef WIN32 // on windows size_t is unsigned int
bool add(size_t data) { return add((int)data); }
#endif
bool add(unsigned int data) { return add(*(int*)&data); }
bool add(int *d, unsigned int n)
{ for(unsigned int i=0;
i<n-1; i++)
add(d[i]);
return add(d[n-1]); }
bool add(const Vec3& v) { add(v.getX());
add(v.getY());
return add(v.getZ()); }
bool add(const btQuaternion& q) { add(q.getX());
add(q.getY());
add(q.getZ());
return add(q.getW()); }
int getInt();
float getFloat();
std::string getString();
std::vector<std::string>
getStringVector();
int getLength(int n) { return sizeof(int); }
int getLength(unsigned int n) { return sizeof(int); }
int getLength(float f) { return sizeof(float); }
int getLength(const std::string& s) { return s.size()+1; }
void getChar(char *c, int n) {memcpy(c,m_data+m_pos,n);
m_pos+=n;
return; }
Vec3 getVec3() { Vec3 v;
v.setX(getFloat());
v.setY(getFloat());
v.setZ(getFloat());
return v; }
btQuaternion getQuaternion() { btQuaternion q;
q.setX(getFloat());
q.setY(getFloat());
q.setZ(getFloat());
q.setW(getFloat());
return q; }
int getLength(int n) { return sizeof(int); }
int getLength(unsigned int n) { return sizeof(int); }
int getLength(float f) { return sizeof(float); }
int getLength(const std::string& s) { return s.size()+1; }
int getLength(const Vec3& v) { return 3*sizeof(float); }
int getLength(const btQuaternion &q){ return 4*sizeof(float); }
int getLength(const std::vector<std::string>& vs);
#ifndef WIN32
int getLength(size_t n) { return sizeof(int); }

View File

@ -24,6 +24,8 @@
#include "race_info_message.hpp"
#include "race_start_message.hpp"
#include "world_loaded_message.hpp"
#include "kart_update_message.hpp"
#include "kart_control_message.hpp"
#include "stk_config.hpp"
#include "user_config.hpp"
#include "race_manager.hpp"
@ -206,7 +208,7 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
case NS_CHARACTER_SELECT:
{
CharacterSelectedMessage m(event->packet);
int hostid=(int)(long)event->peer->data;
unsigned int hostid=(unsigned int)(long)event->peer->data;
assert(hostid>=1 && hostid<=m_num_clients);
if(m_num_local_players[hostid]==-1) // first package from that host
{
@ -222,7 +224,7 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
// one message from each client, and the size of the kart_info
// array is the same as the number of all players (which does not
// yet include the number of players on the host).
if(m_barrier_count == m_num_clients &&
if(m_barrier_count == (int)m_num_clients &&
m_num_all_players==(int)m_kart_info.size())
{
// we can't send the race info yet, since the server might
@ -234,7 +236,7 @@ void NetworkManager::handleMessageAtServer(ENetEvent *event)
case NS_READY_SET_GO_BARRIER:
{
m_barrier_count ++;
if(m_barrier_count==m_num_clients)
if(m_barrier_count==(int)m_num_clients)
{
m_state = NS_RACING;
RaceStartMessage m;
@ -273,7 +275,17 @@ void NetworkManager::handleMessageAtClient(ENetEvent *event)
m_state = NS_RACING;
break;
}
default: assert(0); // should not happen
case NS_RACING:
{
KartUpdateMessage k(event->packet);
break;
}
default:
{
printf("received unknown message: type %d\n",
Message::peekType(event->packet));
// assert(0); // should not happen
}
} // switch m_state
} // handleMessageAtClient
@ -281,6 +293,10 @@ void NetworkManager::handleMessageAtClient(ENetEvent *event)
void NetworkManager::update(float dt)
{
if(m_mode==NW_NONE) return;
// Messages during racing are handled in the sendUpdates/receiveUpdate
// calls, so don't do anything in this case.
if(m_state==NS_RACING) return;
ENetEvent event;
int result = enet_host_service (m_host, &event, 0);
if(result==0) return;
@ -311,9 +327,9 @@ void NetworkManager::broadcastToClients(Message &m)
} // broadcastToClients
// ----------------------------------------------------------------------------
void NetworkManager::sendToServer(Message* m)
void NetworkManager::sendToServer(Message &m)
{
enet_peer_send(m_server, 0, m->getPacket());
enet_peer_send(m_server, 0, m.getPacket());
enet_host_flush(m_host);
} // sendToServer
@ -330,8 +346,12 @@ void NetworkManager::switchToCharacterSelection()
else if(m_mode==NW_SERVER)
{ // server: create message with all valid characters
// ================================================
CharacterInfoMessage m;
broadcastToClients(m);
for(unsigned int i=1; i<=m_num_clients; i++)
{
CharacterInfoMessage m(i);
enet_peer_send(m_clients[i], 0, m.getPacket());
}
enet_host_flush(m_host);
// Prepare the data structures to receive and
// store information from all clients.
@ -340,6 +360,7 @@ void NetworkManager::switchToCharacterSelection()
// be able to use the hostid as index, we have to allocate one
// additional element.
m_num_local_players.resize(m_num_clients+1, -1);
m_num_local_players[0] = race_manager->getNumLocalPlayers();
m_kart_info.clear();
m_num_all_players = 0;
// use barrier count to see if we had at least one message from each host
@ -353,7 +374,7 @@ void NetworkManager::switchToCharacterSelection()
void NetworkManager::sendCharacterSelected(int player_id)
{
CharacterSelectedMessage m(player_id);
sendToServer(&m);
sendToServer(m);
} // sendCharacterSelected
// ----------------------------------------------------------------------------
@ -368,7 +389,7 @@ void NetworkManager::worldLoaded()
if(m_mode==NW_CLIENT)
{
WorldLoadedMessage m;
sendToServer(&m);
sendToServer(m);
m_state = NS_READY_SET_GO_BARRIER;
}
} // worldLoaded
@ -386,16 +407,21 @@ void NetworkManager::setupPlayerKartInfo()
// Now sort by (hostid, playerid)
std::sort(m_kart_info.begin(), m_kart_info.end());
// Set the global player ID for each player
for(unsigned int i=0; i<m_kart_info.size(); i++)
m_kart_info[i].setGlobalPlayerId(i);
// Set the player kart information
race_manager->setNumPlayers(m_kart_info.size());
// Set the global player ID for each player
for(unsigned int i=0; i<m_kart_info.size(); i++)
{
m_kart_info[i].setGlobalPlayerId(i);
race_manager->setPlayerKart(i, m_kart_info[i]);
}
// Compute the id of the first kart from each host
m_kart_id_offset.resize(m_num_clients+1);
m_kart_id_offset[0]=0;
for(unsigned int i=1; i<=m_num_clients; i++)
m_kart_id_offset[i]=m_kart_id_offset[i-1]+m_num_local_players[i-1];
race_manager->computeRandomKartList();
} // setupPlayerKartInfo
@ -406,6 +432,7 @@ void NetworkManager::sendRaceInformationToClients()
{
if(m_mode==NW_SERVER)
{
setupPlayerKartInfo();
RaceInfoMessage m(m_kart_info);
broadcastToClients(m);
}
@ -418,6 +445,96 @@ void NetworkManager::sendRaceInformationToClients()
void NetworkManager::sendConnectMessage()
{
ConnectMessage msg;
sendToServer(&msg);
sendToServer(msg);
} // sendConnectMessage
// ----------------------------------------------------------------------------
/*** Send all kart controls and kart positions to all clients
*/
void NetworkManager::sendUpdates()
{
if(m_mode==NW_SERVER)
{
KartUpdateMessage m;
broadcastToClients(m);
}
else
{
KartControlMessage m;
sendToServer(m);
}
} // sendUpdates
// ----------------------------------------------------------------------------
void NetworkManager::receiveUpdates()
{
// The server receives m_num_clients messages, each client one message
int num_messages = m_mode==NW_SERVER ? m_num_clients : 1;
ENetEvent event;
bool correct=true;
for(int i=0; i<num_messages; i++)
{
int result = enet_host_service (m_host, &event, 0);
if(result<0)
{
fprintf(stderr, m_mode==NW_SERVER
? "Error while waiting for client control - chaos will reign.\n"
: "Error while waiting for server update - chaos will reign.\n");
correct=false;
continue;
}
// if no message, busy wait
if(result==0 || event.type==ENET_EVENT_TYPE_NONE)
{
i--;
continue;
}
if(event.type!=ENET_EVENT_TYPE_RECEIVE)
{
fprintf(stderr, "unexpected message, ignored.\n");
i--;
continue;
}
if(m_mode==NW_SERVER)
{
int host_id = getHostId(event.peer);
KartControlMessage(event.packet, host_id, m_num_local_players[host_id]);
}
else
{
KartUpdateMessage(event.packet);
}
} // for i<num_messages
if(!correct)
fprintf(stderr, "Missing messages need to be handled!\n");
} // receiveUpdates
// ----------------------------------------------------------------------------
void NetworkManager::waitForClientData()
{
ENetEvent event;
bool correct=true;
for(unsigned int i=1; i<=m_num_clients; i++)
{
int result = enet_host_service (m_host, &event, 100);
if(result<=0)
{
fprintf(stderr, "Error while waiting for client control - chaos will reign.\n");
correct=false;
continue;
}
if(event.type!=ENET_EVENT_TYPE_RECEIVE)
{
fprintf(stderr, "received no message - chaos will reign.\n");
correct=false;
continue;
}
int host_id = getHostId(event.peer);
KartControlMessage(event.packet, host_id, m_num_local_players[host_id]);
}
if(!correct)
fprintf(stderr, "Missing messages need to be handled!\n");
} // waitForClientData
// ----------------------------------------------------------------------------

View File

@ -51,11 +51,12 @@ private:
NetworkMode m_mode;
NetworkState m_state;
int m_num_clients;
unsigned int m_num_clients;
std::vector<RemoteKartInfo> m_kart_info;
int m_host_id;
std::vector<std::string> m_client_names;
std::vector<int> m_num_local_players;
std::vector<int> m_kart_id_offset; // kart id of first kart on host i
int m_num_all_players;
int m_barrier_count;
@ -75,9 +76,8 @@ private:
// about lost precision, then cast long to int to get the right type
unsigned int getHostId(ENetPeer *p) const {return (int)(long)p->data; }
void sendToServer(Message *m);
void sendToServer(Message &m);
void broadcastToClients(Message &m);
void sendToClient(int id, const Message *m);
public:
NetworkManager();
~NetworkManager();
@ -85,12 +85,11 @@ public:
NetworkMode getMode() const {return m_mode; }
void setState(NetworkState s) {m_state = s; }
NetworkState getState() const {return m_state; }
int getHostId() const {return m_host_id; }
int getMyHostId() const {return m_host_id; }
void setHostId(int host_id) {m_host_id = host_id; }
unsigned int getNumClients() const {return m_num_clients; }
const std::string&
getClientName(int i) const {return m_client_names[i];}
void setKartInfo(int player_id, const std::string& kart,
const std::string& user="", int hostid=-1);
bool initialiseConnections();
void update(float dt);
@ -100,13 +99,11 @@ public:
void sendCharacterSelected(int player_id);
void waitForRaceInformation();
void worldLoaded();
// which one is actually necessary:
void setupPlayerKartInfo();
void sendRaceInformationToClients();
void switchToRaceDataSynchronisation();
void switchToReadySetGoBarrier();
void sendUpdates();
void receiveUpdates();
void waitForClientData();
};
extern NetworkManager *network_manager;

View File

@ -48,7 +48,6 @@ void PlayerKart::reset()
m_steer_val_l = 0;
m_steer_val_r = 0;
m_steer_val = 0;
m_accel_val = 0;
m_controls.accel = 0.0;
m_controls.brake =false;
m_controls.fire = false;
@ -82,11 +81,11 @@ void PlayerKart::action(KartAction action, int value)
break;
case KA_ACCEL:
m_accel_val = value;
m_controls.accel = value/32768.0f;
break;
case KA_BRAKE:
if (value)
m_accel_val = 0;
m_controls.accel = 0;
m_controls.brake = (value!=0); // This syntax avoid visual c++ warning (when brake=value)
break;
case KA_WHEELIE:
@ -150,8 +149,6 @@ void PlayerKart::update(float dt)
{
steer(dt, m_steer_val);
m_controls.accel = m_accel_val / 32768.0f;
if(world->isStartPhase())
{
if(m_controls.accel!=0.0 || m_controls.brake!=false ||

View File

@ -33,7 +33,7 @@ class Camera;
class PlayerKart : public Kart
{
private:
int m_steer_val, m_steer_val_l, m_steer_val_r, m_accel_val;
int m_steer_val, m_steer_val_l, m_steer_val_r;
Player *m_player;
float m_penalty_time;

View File

@ -44,7 +44,8 @@ RaceManager::RaceManager()
m_score_for_position = stk_config->m_scores;
m_coin_target = 0;
setTrack("race");
setLocalPlayerKart(0, "tuxkart");
setNumLocalPlayers(1);
setLocalKartInfo(0, "tuxkart");
} // RaceManager
//-----------------------------------------------------------------------------
@ -60,38 +61,31 @@ void RaceManager::reset()
} // reset
//-----------------------------------------------------------------------------
void RaceManager::setLocalPlayerKart(unsigned int player, const std::string& kart)
void RaceManager::setPlayerKart(unsigned int player_id, const RemoteKartInfo& ki)
{
if (player >= 0 && player < 4)
{
if (player >= getNumLocalPlayers())
setNumLocalPlayers(player+1);
m_local_player_karts[player].setPlayerId(player);
m_local_player_karts[player].setKartName(kart);
m_local_player_karts[player].setClientId(network_manager->getClientId());
}
else
{
fprintf(stderr, "Warning: player '%d' does not exists.\n", player);
}
} // setLocalPlayerKart
//-----------------------------------------------------------------------------
void RaceManager::setPlayerKart(unsigned int player, const std::string& kart,
const std::string& player_name, int host_id)
{
if (player >= getNumPlayers())
setNumPlayers(player+1);
m_player_karts[player] = kart;
m_player_karts[player_id] = ki;
} // setPlayerKart
// ----------------------------------------------------------------------------
void RaceManager::setLocalKartInfo(unsigned int player_id, const std::string& kart)
{
assert(0<=player_id && player_id <m_local_kart_info.size());
m_local_kart_info[player_id]=RemoteKartInfo(player_id, kart,
user_config->m_player[player_id].getName(),
network_manager->getMyHostId());
} // setLocalKartInfo
//-----------------------------------------------------------------------------
void RaceManager::setNumLocalPlayers(unsigned int n)
{
m_local_kart_info.resize(n);
} // setNumLocalPlayers
//-----------------------------------------------------------------------------
void RaceManager::setNumPlayers(int num)
{
m_player_karts.resize(num);
for(PlayerKarts::iterator i = m_player_karts.begin(); i != m_player_karts.end(); ++i)
if (i->empty()) *i = "tuxkart";
} // setNumPlayers
//-----------------------------------------------------------------------------
@ -170,7 +164,6 @@ void RaceManager::startNew()
//-----------------------------------------------------------------------------
void RaceManager::startNextRace()
{
m_num_finished_karts = 0;
m_num_finished_players = 0;

View File

@ -1025,7 +1025,7 @@ ActionMap *UserConfig::newIngameActionMap()
GameAction gaEnd = GA_NULL;
switch (race_manager->getNumPlayers())
switch (race_manager->getNumLocalPlayers())
{
case 1:
gaEnd = GA_P1_LOOK_BACK; break;

View File

@ -0,0 +1,67 @@
// $Id: randum_number.cpp 2163 2008-07-14 03:40:58Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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 "random_generator.hpp"
std::vector<RandomGenerator*> RandomGenerator::m_all_random_generators;
RandomGenerator::RandomGenerator()
{
m_a = 1103515245;
m_c = 12345;
m_all_random_generators.push_back(this);
} // RandomGenerator
// ----------------------------------------------------------------------------
std::vector<int> RandomGenerator::generateAllSeeds()
{
std::vector<int> all_seeds;
for(unsigned int i=0; i<m_all_random_generators.size(); i++)
{
int seed = rand();
all_seeds.push_back(seed);
}
seedAll(all_seeds);
return all_seeds;
} // generateAllSeeds
// ----------------------------------------------------------------------------
void RandomGenerator::seedAll(std::vector<int> all_seeds)
{
for(unsigned int i=0; i<all_seeds.size(); i++)
{
m_all_random_generators[i]->seed(all_seeds[i]);
}
} // seed
// -------------------q---------------------------------------------------------
void RandomGenerator::seed(int s)
{
m_random_value = s;
} // seed
// ----------------------------------------------------------------------------
int RandomGenerator::get(int n)
{
m_random_value = m_random_value*m_a+m_c;
return m_random_value % n;
} // get
// ----------------------------------------------------------------------------

View File

@ -0,0 +1,49 @@
// $Id: randum_number.hpp 2163 2008-07-14 03:40:58Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
//
// 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.
#ifndef HEADER_RANDOM_NUMBER_H
#define HEADER_RANDOM_NUMBER_H
#include <vector>
/** A random number generator. Each objects that needs a random number uses
its own number random generator. They are all seeded with number provided
by the server. This guarantees that in a network game all 'random' values
are actually identical among all machines.
The formula used is x(n+1)=(a*x(n)+c) % m, but m is assumed to be 2^32,
so the modulo operation can be skipped (for 4 byte integers).
*/
class RandomGenerator
{
private:
unsigned int m_random_value;
unsigned int m_a, m_c;
static std::vector<RandomGenerator*> m_all_random_generators;
public:
RandomGenerator();
static void seedAll(std::vector<int> all_seeds);
std::vector<int> generateAllSeeds();
void seed(int s);
/** Returns a pseudo random number between 0 and n-1 inclusive */
int get (int n);
}; // RandomGenerator
#endif

View File

@ -45,7 +45,6 @@
#include "camera.hpp"
#include "robots/default_robot.hpp"
#include "unlock_manager.hpp"
#include "network/network_kart.hpp"
#include "network/network_manager.hpp"
#ifdef HAVE_GHOST_REPLAY
# include "replay_player.hpp"
@ -98,6 +97,7 @@ World::World()
loadTrack() ;
m_player_karts.resize(race_manager->getNumPlayers());
m_network_karts.resize(race_manager->getNumPlayers());
m_local_player_karts.resize(race_manager->getNumLocalPlayers());
for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
@ -141,6 +141,7 @@ World::World()
newkart = new NetworkKart(kart_name, position, init_pos,
global_player_id);
}
m_network_karts[global_player_id] = static_cast<NetworkKart*>(newkart);
break;
case RaceManager::KT_AI:
newkart = loadRobot(kart_name, position, init_pos);
@ -347,10 +348,6 @@ void World::updateHighscores()
// again by a faster kart in the same race), which might be confusing
// if we ever decide to display a message (e.g. during a race)
unsigned int *index = new unsigned int[m_kart.size()];
#ifdef DEBUG
// FIXME begin: for debugging only: had a bug here once, couldn't reproduce it:
for(unsigned int i=0; i<m_kart.size(); i++) index[i]=-1;
#endif
for (unsigned int i=0; i<m_kart.size(); i++ )
{
index[m_kart[i]->getPosition()-1] = i;
@ -817,9 +814,7 @@ Kart* World::loadRobot(const std::string& kart_name, int position,
const int NUM_ROBOTS = 1;
srand((unsigned)std::time(0));
switch(rand() % NUM_ROBOTS)
switch(m_random.get(NUM_ROBOTS))
{
case 0:
currentRobot = new DefaultRobot(kart_name, position, init_pos);

View File

@ -28,6 +28,9 @@
#include "physics.hpp"
#include "kart.hpp"
#include "highscores.hpp"
#include "network/network_kart.hpp"
#include "utils/random_generator.hpp"
#ifdef HAVE_GHOST_REPLAY
# include "replay_recorder.hpp"
class ReplayPlayer;
@ -80,7 +83,9 @@ public:
void disableRace(); // Put race into limbo phase
PlayerKart *getPlayerKart(int player) const { return m_player_karts[player]; }
unsigned int getCurrentNumLocalPlayers() const {return m_local_player_karts.size();}
PlayerKart *getLocalPlayerKart(int n) const { return m_local_player_karts[n]; }
NetworkKart*getNetworkKart(int n) const {return m_network_karts[n]; }
Kart *getKart(int kartId) const { assert(kartId >= 0 &&
kartId < int(m_kart.size()));
return m_kart[kartId]; }
@ -103,9 +108,12 @@ public:
void unpause();
private:
Karts m_kart;
std::vector<PlayerKart*> m_player_karts;
std::vector<PlayerKart*> m_local_player_karts;
std::vector<NetworkKart*> m_network_karts;
RandomGenerator m_random;
Karts m_kart;
Physics* m_physics;
float m_fastest_lap;
Kart* m_fastest_kart;