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;