diff --git a/src/Makefile.am b/src/Makefile.am
index 0cbe55df7..eb759792f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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 \
diff --git a/src/attachment.cpp b/src/attachment.cpp
index ffad2a687..42bf5aeeb 100644
--- a/src/attachment.cpp
+++ b/src/attachment.cpp
@@ -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
//-----------------------------------------------------------------------------
diff --git a/src/attachment.hpp b/src/attachment.hpp
index ca1437b73..8476830ed 100644
--- a/src/attachment.hpp
+++ b/src/attachment.hpp
@@ -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();
diff --git a/src/collectable.cpp b/src/collectable.cpp
index e3872efa0..e0ee2928c 100644
--- a/src/collectable.cpp
+++ b/src/collectable.cpp
@@ -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
diff --git a/src/collectable.hpp b/src/collectable.hpp
index 60a048708..ffea3478d 100644
--- a/src/collectable.hpp
+++ b/src/collectable.hpp
@@ -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;
diff --git a/src/game_manager.cpp b/src/game_manager.cpp
index 0c11427db..2d5e368b4 100644
--- a/src/game_manager.cpp
+++ b/src/game_manager.cpp
@@ -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);
diff --git a/src/gui/race_gui.cpp b/src/gui/race_gui.cpp
index e72e204e2..497eab556 100644
--- a/src/gui/race_gui.cpp
+++ b/src/gui/race_gui.cpp
@@ -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);
diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj
index d9809acd6..57a414dff 100644
--- a/src/ide/vc9/supertuxkart.vcproj
+++ b/src/ide/vc9/supertuxkart.vcproj
@@ -1,1582 +1,1678 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/kart.hpp b/src/kart.hpp
index 9d95fe875..4a1d52cae 100644
--- a/src/kart.hpp
+++ b/src/kart.hpp
@@ -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; }
diff --git a/src/network/character_info_message.hpp b/src/network/character_info_message.hpp
index d273986fc..3b532852b 100644
--- a/src/network/character_info_message.hpp
+++ b/src/network/character_info_message.hpp
@@ -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
diff --git a/src/network/kart_control_message.cpp b/src/network/kart_control_message.cpp
new file mode 100644
index 000000000..636c5609c
--- /dev/null
+++ b/src/network/kart_control_message.cpp
@@ -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; igetLocalPlayerKart(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; igetNetworkKart(i);
+ kart->setControl(kc);
+ }
+}; // KartControlMessage
+
diff --git a/src/network/kart_control_message.hpp b/src/network/kart_control_message.hpp
new file mode 100644
index 000000000..965ca4c5a
--- /dev/null
+++ b/src/network/kart_control_message.hpp
@@ -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
diff --git a/src/network/kart_update_message.cpp b/src/network/kart_update_message.cpp
new file mode 100644
index 000000000..6b4655bd2
--- /dev/null
+++ b/src/network/kart_update_message.cpp
@@ -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; igetKart(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; igetKart(i);
+ kart->setXYZ(xyz);
+ kart->setRotation(q);
+ } // for i
+}; // KartUpdateMessage
+
diff --git a/src/network/kart_update_message.hpp b/src/network/kart_update_message.hpp
new file mode 100644
index 000000000..0901ed53e
--- /dev/null
+++ b/src/network/kart_update_message.hpp
@@ -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
diff --git a/src/network/message.hpp b/src/network/message.hpp
index 6b82affd6..d8180dd44 100644
--- a/src/network/message.hpp
+++ b/src/network/message.hpp
@@ -23,11 +23,14 @@
#include
#include
#include
+#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& 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
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& vs);
#ifndef WIN32
int getLength(size_t n) { return sizeof(int); }
diff --git a/src/network/network_manager.cpp b/src/network/network_manager.cpp
index a48b00f55..8910fa5c7 100644
--- a/src/network/network_manager.cpp
+++ b/src/network/network_manager.cpp
@@ -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; isetNumPlayers(m_kart_info.size());
+
+ // Set the global player ID for each player
for(unsigned int i=0; isetPlayerKart(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 m_kart_info;
int m_host_id;
std::vector m_client_names;
std::vector m_num_local_players;
+ std::vector 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;
diff --git a/src/player_kart.cpp b/src/player_kart.cpp
index a6d383e3e..5753a6a16 100644
--- a/src/player_kart.cpp
+++ b/src/player_kart.cpp
@@ -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 ||
diff --git a/src/player_kart.hpp b/src/player_kart.hpp
index ad5db213f..ad440a95c 100644
--- a/src/player_kart.hpp
+++ b/src/player_kart.hpp
@@ -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;
diff --git a/src/race_manager.cpp b/src/race_manager.cpp
index ff76fd99f..a3b76123c 100644
--- a/src/race_manager.cpp
+++ b/src/race_manager.cpp
@@ -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_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;
diff --git a/src/user_config.cpp b/src/user_config.cpp
index 10108edf5..b8320047f 100644
--- a/src/user_config.cpp
+++ b/src/user_config.cpp
@@ -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;
diff --git a/src/utils/random_generator.cpp b/src/utils/random_generator.cpp
new file mode 100644
index 000000000..e1f531999
--- /dev/null
+++ b/src/utils/random_generator.cpp
@@ -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::m_all_random_generators;
+
+RandomGenerator::RandomGenerator()
+{
+ m_a = 1103515245;
+ m_c = 12345;
+ m_all_random_generators.push_back(this);
+} // RandomGenerator
+
+// ----------------------------------------------------------------------------
+std::vector RandomGenerator::generateAllSeeds()
+{
+ std::vector all_seeds;
+ for(unsigned int i=0; i all_seeds)
+{
+ for(unsigned int i=0; iseed(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
+
+// ----------------------------------------------------------------------------
+
diff --git a/src/utils/random_generator.hpp b/src/utils/random_generator.hpp
new file mode 100644
index 000000000..440eeb01f
--- /dev/null
+++ b/src/utils/random_generator.hpp
@@ -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
+
+/** 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 m_all_random_generators;
+public:
+ RandomGenerator();
+ static void seedAll(std::vector all_seeds);
+ std::vector generateAllSeeds();
+ void seed(int s);
+ /** Returns a pseudo random number between 0 and n-1 inclusive */
+ int get (int n);
+
+
+}; // RandomGenerator
+#endif
+
diff --git a/src/world.cpp b/src/world.cpp
index 743e575ee..373d6e83a 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -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; igetNumKarts(); 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(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; igetPosition()-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);
diff --git a/src/world.hpp b/src/world.hpp
index f52b00b29..eec1a5481 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -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 m_player_karts;
std::vector m_local_player_karts;
+ std::vector m_network_karts;
+ RandomGenerator m_random;
+
+ Karts m_kart;
Physics* m_physics;
float m_fastest_lap;
Kart* m_fastest_kart;