1) Synchronised herrings.

2) Fixed no-network play.
3) Fixed display of 'loading'/'synchronising' message.
4) Added missing files from previous commit.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2243 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2008-09-07 14:45:43 +00:00
parent ecac04b1bc
commit 2455bdc32d
11 changed files with 334 additions and 64 deletions

View File

@@ -40,6 +40,8 @@ supertuxkart_SOURCES = main.cpp \
network/connect_message.hpp network/character_info_message.hpp \
network/kart_update_message.hpp network/kart_update_message.cpp \
network/kart_control_message.hpp network/kart_control_message.cpp \
network/flyable_info.hpp network/herring_info.hpp \
network/race_state.hpp network/race_state.cpp \
utils/random_genertaor.hpp utils/random_generator.cpp \
material_manager.cpp material_manager.hpp \
grand_prix_manager.cpp grand_prix_manager.hpp \

View File

@@ -19,6 +19,7 @@
#include <math.h>
#include "network/flyable_info.hpp"
#include "flyable.hpp"
#include "world.hpp"
#include "kart.hpp"

View File

@@ -25,23 +25,11 @@
#include "kart.hpp"
#include "terrain_info.hpp"
class FlyableInfo;
class Flyable : public Moveable, public TerrainInfo
{
public:
/** FlyableInfo stores information for updating flyables on the clients.
* It contains only the coordinates, rotation, and explosion state. */
// -----------------------------------------------------------------------
class FlyableInfo
{
public:
Vec3 m_xyz;
btQuaternion m_rotation;
bool m_exploded;
FlyableInfo(const Vec3& xyz, const btQuaternion &rotation, bool exploded) :
m_xyz(xyz), m_rotation(rotation), m_exploded(exploded)
{};
FlyableInfo() {};
};
private:
bool m_has_hit_something;
bool m_exploded;

View File

@@ -56,7 +56,12 @@ CharSel::CharSel(int whichPlayer)
{
// First time this is called --> switch client and server
// to character barrier mode
if(network_manager->getState()==NetworkManager::NS_NONE)
// FIXME: switchTo ... must be called to clean the kart_info
// in the server (even when NW_NONE). This if condition
// needs to be checked (otherwise ghost karts and
// a ghost camera will appear)
if(network_manager->getState()==NetworkManager::NS_NONE ||
network_manager->getMode()==NetworkManager::NW_NONE)
network_manager->switchToCharacterSelection();
// For some strange reasons plib calls makeCurrent() in ssgContext

View File

@@ -30,16 +30,19 @@ enum WidgetTokens
StartRaceFeedback::StartRaceFeedback()
{
m_is_first_frame = true;
//Add some feedback so people know they are going to start the race
widget_manager->reset();
widget_manager->addTextWgt( WTOK_MSG, 60, 7, "" );
m_loading_text = _("Loading race...");
m_synchronising_text = _("Synchronising network...");
widget_manager->setWgtText(WTOK_MSG, _("Synchronising network..."));
if(network_manager->getMode()==NetworkManager::NW_NONE)
widget_manager->setWgtText(WTOK_MSG, m_loading_text);
else // networking
// the state and mode are checked in update()
widget_manager->setWgtText(WTOK_MSG, m_synchronising_text);
{
// This copies the local player information to the global
// player information in the race manager.
network_manager->setupPlayerKartInfo();
}
widget_manager->layout(WGT_AREA_ALL);
}
@@ -54,6 +57,8 @@ StartRaceFeedback::~StartRaceFeedback()
//-----------------------------------------------------------------------------
void StartRaceFeedback::update(float delta)
{
// First test if we are still waiting
// ===================================
// If the server hasn't received all client information, keep on waiting
if(network_manager->getMode()==NetworkManager::NW_SERVER &&
@@ -70,27 +75,24 @@ void StartRaceFeedback::update(float delta)
return;
}
if(network_manager->getMode()==NetworkManager::NW_NONE)
{
// This copies the loca lplayer information to the global
// player information in the race manager
network_manager->setupPlayerKartInfo();
}
else if(network_manager->getMode()==NetworkManager::NW_SERVER)
{
network_manager->sendRaceInformationToClients();
widget_manager->setWgtText(WTOK_MSG, m_loading_text);
}
else if(network_manager->getMode()==NetworkManager::NW_CLIENT)
{
// Client received race information
widget_manager->setWgtText(WTOK_MSG, m_loading_text);
}
// Waiting is finished, switch to loading
// ======================================
widget_manager->setWgtText(WTOK_MSG, _("Loading race..."));
widget_manager->update(delta);
// Pops this menu
race_manager->startNew();
// We can't do the actual loading etc. in the first call here, since then
// the text 'loading' would not be displayed. So a simple state variable
// 'is_first_frame' is used to make sure that the text is displayed
// before initiating the loading of the race.
if(!m_is_first_frame)
{
if(network_manager->getMode()==NetworkManager::NW_SERVER)
{
network_manager->sendRaceInformationToClients();
}
race_manager->startNew();
}
m_is_first_frame = false;
} // update

View File

@@ -22,10 +22,8 @@
class StartRaceFeedback: public BaseGUI
{
private:
char *m_loading_text; // Used to have the actual text in only
char *m_synchronising_text; // one place (easier to change, avoids
// multiple translations in case of typos)
protected:
bool m_is_first_frame;
public:
StartRaceFeedback();
~StartRaceFeedback();

View File

@@ -1616,6 +1616,14 @@
RelativePath="..\..\network\connect_message.hpp"
>
</File>
<File
RelativePath="..\..\network\flyable_info.hpp"
>
</File>
<File
RelativePath="..\..\network\herring_info.hpp"
>
</File>
<File
RelativePath="..\..\network\kart_control_message.hpp"
>

View File

@@ -57,7 +57,7 @@ private:
unsigned int m_pos; // simple stack counter for constructing packet data
bool m_needs_destroy; // only received messages need to be destroyed
protected:
public:
void addInt(int data);
void addShort(short data);
void addString(const std::string &data);
@@ -107,18 +107,18 @@ protected:
q.setZ(getFloat());
q.setW(getFloat());
return q; }
int getIntLength() const { return sizeof(int); }
int getUIntLength() const { return sizeof(int); }
int getShortLength() const { return sizeof(short); }
int getCharLength() const { return sizeof(char); }
int getFloatLength() { return sizeof(float); }
int getStringLength(const std::string& s) { return s.size()+1; }
int getVec3Length() { return 3*sizeof(float); }
int getQuaternionLength() { return 4*sizeof(float); }
int getStringVectorLength(const std::vector<std::string>& vs);
static int getIntLength() { return sizeof(int); }
static int getUIntLength() { return sizeof(int); }
static int getShortLength() { return sizeof(short); }
static int getCharLength() { return sizeof(char); }
static int getBoolLength() { return sizeof(char); }
static int getFloatLength() { return sizeof(float); }
static int getStringLength(const std::string& s) { return s.size()+1;}
static int getVec3Length() { return 3*sizeof(float); }
static int getQuaternionLength() { return 4*sizeof(float); }
static int getStringVectorLength(const std::vector<std::string>& vs);
#ifndef WIN32
int getSizeTLength(size_t n) { return sizeof(int); }
static int getSizeTLength(size_t n) { return sizeof(int); }
#endif
public:

View File

@@ -343,16 +343,21 @@ void NetworkManager::switchToCharacterSelection()
// Change state to wait for list of characters from server
m_state = NS_WAIT_FOR_AVAILABLE_CHARACTERS;
}
else if(m_mode==NW_SERVER)
{ // server: create message with all valid characters
// ================================================
for(unsigned int i=1; i<=m_num_clients; i++)
else // Server or no network
{
if(m_mode==NW_SERVER)
{
CharacterInfoMessage m(i);
enet_peer_send(m_clients[i], 0, m.getPacket());
// server: create message with all valid characters
// ================================================
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);
}
enet_host_flush(m_host);
// For server and no network:
// ==========================
// Prepare the data structures to receive and
// store information from all clients.
m_num_local_players.clear();

181
src/network/race_state.cpp Normal file
View File

@@ -0,0 +1,181 @@
// $Id: race_state.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 "world.hpp"
#include "network/network_manager.hpp"
#include "network/race_state.hpp"
#include "projectile_manager.hpp"
RaceState *race_state=NULL;
// ----------------------------------------------------------------------------
void RaceState::serialise()
{
// First compute the overall size needed
// =====================================
int len = 0;
// 1. Add all kart information
// ---------------------------
unsigned int num_karts = world->getCurrentNumKarts();
KartControl c;
// Send the number of karts and for each kart the compressed
// control structure, xyz,hpr, and speed (which is necessary to
// display the speed, and e.g. to determine when a parachute is detached)
len += 1 + num_karts*(KartControl::getCompressedSize()
+ getVec3Length()+getQuaternionLength()
+ getFloatLength()) ;
// 2. Add information about eaten herrings
// ---------------------------------------
// We can't use sizeof() here, since the data structures might be padded
len += 1 + m_herring_info.size()* HerringInfo::getLength();
// 3. Add the data about new flyables
// ----------------------------------
len += 1 + m_new_flyable.size() * 2;
if(projectile_manager->getNumProjectiles()>0)
printf("rocket\n");
// 4. Add rocket positions
// -----------------------
len += 2+projectile_manager->getNumProjectiles()*FlyableInfo::getLength();
// Now add the data
// ================
allocate(len);
// 1. Kart positions
// -----------------
addChar(num_karts);
assert(KartControl::getCompressedSize()<=9);
for(unsigned int i=0; i<num_karts; i++)
{
const Kart* kart=world->getKart(i);
const KartControl& kc=kart->getControls();
char compressed[9]; // avoid the new/delete overhead
kc.compress(compressed);
addCharArray(compressed, KartControl::getCompressedSize());
addVec3(kart->getXYZ());
addQuaternion(kart->getRotation());
addFloat(kart->getSpeed());
} // for i
// 2. Eaten herrings
// -----------------
addChar(m_herring_info.size());
for(unsigned int i=0; i<m_herring_info.size(); i++)
{
m_herring_info[i].serialise(this);
}
// 3. New projectiles
// ------------------
addChar(m_new_flyable.size());
for(unsigned int i=0; i<m_new_flyable.size(); i++)
{
addChar(m_new_flyable[i].m_type);
addChar(m_new_flyable[i].m_kart_id);
}
// 4. Projectiles
// --------------
addShort(m_flyable_info.size());
// The exploded flag could be compressed by combining 8 bits into one byte
for(unsigned int i=0; i<m_flyable_info.size(); i++)
{
m_flyable_info[i].serialise(this);
}
} // serialise
// ----------------------------------------------------------------------------
void RaceState::clear()
{
m_herring_info.clear();
m_flyable_info.clear();
} // clear
// ----------------------------------------------------------------------------
/** Unserialises a race state message.
* This function unserialises the message, and updates the state of the race
* simulation appropriately.
*/
void RaceState::receive(ENetPacket *pkt)
{
Message::receive(pkt, MT_RACE_STATE);
// 1. Kart information
// -------------------
unsigned int num_karts = getChar();
for(unsigned int i=0; i<num_karts; i++)
{
assert(KartControl::getCompressedSize()<=9);
char compressed[9]; // avoid new/delete overhead
getCharArray(compressed, KartControl::getCompressedSize());
KartControl kc;
kc.uncompress(compressed);
// Currently not used!
Vec3 xyz = getVec3();
btQuaternion q = getQuaternion();
Kart *kart = world->getKart(i);
kart->setXYZ(xyz);
kart->setRotation(q);
kart->setSpeed(getFloat());
} // for i
// Eaten herrings
// --------------
unsigned short num_herrings=getChar();
for(unsigned int i=0; i<num_herrings; i++)
{
HerringInfo hi(this);
if(hi.m_herring_id==-1) // Rescue triggered
world->getKart(hi.m_kart_id)->forceRescue();
else
herring_manager->eatenHerring(hi.m_herring_id,
world->getKart(hi.m_kart_id),
hi.m_add_info);
}
// 3. New flyables
// ---------------
unsigned int new_fl = getChar();
for(unsigned int i=0; i<new_fl; i++)
{
char type = getChar();
char world_kart_id = getChar();
projectile_manager->newProjectile(world->getKart(world_kart_id),
(CollectableType)type);
}
// 4. Projectiles
// --------------
unsigned short num_flyables = getShort();
m_flyable_info.clear();
m_flyable_info.resize(num_flyables);
for(unsigned short i=0; i<projectile_manager->getNumProjectiles(); i++)
{
FlyableInfo f(this);
m_flyable_info[i] = f;
}
clear(); // free message bugger
} // receive
// ----------------------------------------------------------------------------

View File

@@ -0,0 +1,80 @@
// $Id: race_state.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_RACE_STATE_H
#define HEADER_RACE_STATE_H
#include <vector>
#include "network/message.hpp"
#include "network/herring_info.hpp"
#include "network/flyable_info.hpp"
#include "herring.hpp"
#include "flyable.hpp"
/** This class stores the state information of a (single) race, e.g. the
position and orientation of karts, collisions that have happened etc.
It is used for the network version to update the clients with the
'official' state information from the server.
*/
class RaceState : public Message
{
private:
/** Updates about collected herrings. */
std::vector<HerringInfo> m_herring_info;
/** Updates about existing flyables. */
std::vector<FlyableInfo> m_flyable_info;
/** List of new flyables. */
struct NewFlyable{
char m_type;
char m_kart_id;
};
std::vector<NewFlyable> m_new_flyable;
public:
RaceState() : Message(MT_RACE_STATE) {}
void herringCollected(int kartid, int herring_id, char add_info=-1)
{
m_herring_info.push_back(HerringInfo(kartid, herring_id, add_info));
}
void setNumFlyables(int n) { m_flyable_info.resize(n); }
void setFlyableInfo(int n, const FlyableInfo& fi)
{
m_flyable_info[n] = fi;
}
void newFlyable(char type, char kartid)
{
NewFlyable nf;
nf.m_type = type;
nf.m_kart_id = kartid;
m_new_flyable.push_back(nf);
}
void serialise();
void receive(ENetPacket *pkt);
void clear(); // Removes all currently stored information
unsigned int getNumFlyables() const {return m_flyable_info.size(); }
const FlyableInfo
&getFlyable(unsigned int i) const {return m_flyable_info[i];}
}; // RaceState
extern RaceState *race_state;
#endif