Replaced kart update message with race_state (which gets send
from the server to the clients). Started to implement synchronising of herrings and projectiles. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2242 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define _WINSOCKAPI_
|
||||
#include <plib/ssg.h>
|
||||
|
||||
#include "attachment.hpp"
|
||||
@@ -28,6 +29,8 @@
|
||||
#include "sound_manager.hpp"
|
||||
#include "stk_config.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
Attachment::Attachment(Kart* _kart)
|
||||
{
|
||||
@@ -62,17 +65,18 @@ void Attachment::set(attachmentType _type, float time, Kart *current_kart)
|
||||
} // set
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void Attachment::hitGreenHerring()
|
||||
void Attachment::hitGreenHerring(const Herring &herring, int random_attachment)
|
||||
{
|
||||
if(user_config->m_profile) return;
|
||||
int random_attachment;
|
||||
float leftover_time = 0.0f;
|
||||
|
||||
switch(getType()) // If there already is an attachment, make it worse :)
|
||||
{
|
||||
case ATTACH_BOMB: projectile_manager->newExplosion(m_kart->getXYZ());
|
||||
m_kart->handleExplosion(m_kart->getXYZ(), /*direct_hit*/ true);
|
||||
clear();
|
||||
random_attachment = m_random.get(3);
|
||||
if(random_attachment==-1)
|
||||
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,9 +87,19 @@ void Attachment::hitGreenHerring()
|
||||
random_attachment = 2; // anvil
|
||||
leftover_time = m_time_left;
|
||||
break;
|
||||
default: random_attachment = m_random.get(3);
|
||||
default: if(random_attachment==-1)
|
||||
random_attachment = m_random.get(3);
|
||||
} // switch
|
||||
|
||||
// Save the information about the attachment in the race state
|
||||
// so that the clients can be updated.
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
{
|
||||
race_state->herringCollected(m_kart->getWorldKartId(),
|
||||
herring.getHerringId(),
|
||||
random_attachment);
|
||||
}
|
||||
|
||||
switch (random_attachment)
|
||||
{
|
||||
case 0: set( ATTACH_PARACHUTE, stk_config->m_parachute_time+leftover_time);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define HEADER_ATTACHMENT_H
|
||||
|
||||
#include "stk_config.hpp"
|
||||
#include "herring.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
class Kart;
|
||||
@@ -74,7 +75,13 @@ public:
|
||||
return m_type==ATTACH_ANVIL
|
||||
?stk_config->m_anvil_speed_factor:1.0f;
|
||||
}
|
||||
void hitGreenHerring();
|
||||
/** Randomly selects the new attachment. For a server process, the
|
||||
* attachment can be passed into this function.
|
||||
\param herring The herring that was collected.
|
||||
\param random_attachment Optional: only used on the clients, it
|
||||
specifies the new attachment to use
|
||||
*/
|
||||
void hitGreenHerring(const Herring &herring, int random_attachment=-1);
|
||||
void update (float dt);
|
||||
void moveBombFromTo(Kart *from, Kart *to);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
#include "collectable.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "race_manager.hpp"
|
||||
@@ -143,8 +145,25 @@ void Collectable::use()
|
||||
} // use
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Collectable::hitRedHerring(int n)
|
||||
void Collectable::hitRedHerring(int n, const Herring &herring, int add_info)
|
||||
{
|
||||
// On the client this is called when update information is received
|
||||
// from the server:
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
if(m_type==COLLECT_NOTHING)
|
||||
{
|
||||
m_type = (CollectableType)add_info;
|
||||
m_number = n;
|
||||
}
|
||||
else if((CollectableType)add_info==m_type)
|
||||
{
|
||||
m_number+=n;
|
||||
if(m_number > MAX_COLLECTABLES) m_number = MAX_COLLECTABLES;
|
||||
}
|
||||
// Ignore new collectable if it is different from the current one
|
||||
return;
|
||||
}
|
||||
//The probabilities of getting the anvil or the parachute increase
|
||||
//depending on how bad the owner's position is. For the first
|
||||
//driver the posibility is none, for the last player is 15 %.
|
||||
@@ -192,6 +211,15 @@ void Collectable::hitRedHerring(int n)
|
||||
simpleCounter++;
|
||||
newC = (CollectableType)(simpleCounter%(COLLECT_MAX - 1 - 2) + 1);
|
||||
}
|
||||
// Save the information about the collectable in the race state
|
||||
// so that the clients can be updated.
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
{
|
||||
race_state->herringCollected(m_owner->getWorldKartId(),
|
||||
herring.getHerringId(),
|
||||
newC);
|
||||
}
|
||||
|
||||
if(m_type==COLLECT_NOTHING)
|
||||
{
|
||||
m_type=newC;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
class Kart;
|
||||
class Herring;
|
||||
|
||||
class Collectable
|
||||
{
|
||||
@@ -42,7 +43,7 @@ public:
|
||||
void reset ();
|
||||
int getNum () const {return m_number;}
|
||||
CollectableType getType () const {return m_type; }
|
||||
void hitRedHerring(int n);
|
||||
void hitRedHerring(int n, const Herring &herring, int newC=-1);
|
||||
Material* getIcon ();
|
||||
void use ();
|
||||
};
|
||||
|
||||
@@ -49,7 +49,6 @@ Flyable::Flyable(Kart *kart, CollectableType type, float mass) : Moveable(false)
|
||||
|
||||
m_owner = kart;
|
||||
m_has_hit_something = false;
|
||||
m_last_radar_beep = -1;
|
||||
m_exploded = false;
|
||||
m_shape = NULL;
|
||||
m_mass = mass;
|
||||
@@ -185,6 +184,14 @@ void Flyable::update (float dt)
|
||||
Moveable::update(dt);
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void Flyable::updateFromServer(const FlyableInfo &f)
|
||||
{
|
||||
setXYZ(f.m_xyz);
|
||||
setRotation(f.m_rotation);
|
||||
m_exploded = f.m_exploded;
|
||||
} // updateFromServer
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void Flyable::explode(Kart *kart_hit, MovingPhysics* moving_physics)
|
||||
{
|
||||
|
||||
@@ -27,9 +27,23 @@
|
||||
|
||||
class Flyable : public Moveable, public TerrainInfo
|
||||
{
|
||||
sgCoord m_last_pos;
|
||||
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;
|
||||
int m_last_radar_beep;
|
||||
bool m_exploded;
|
||||
|
||||
protected:
|
||||
@@ -72,6 +86,7 @@ public:
|
||||
static void init (const lisp::Lisp* lisp, ssgEntity *model,
|
||||
CollectableType type);
|
||||
virtual void update (float);
|
||||
void updateFromServer(const FlyableInfo &f);
|
||||
|
||||
virtual void hitTrack () {};
|
||||
void explode (Kart* kart, MovingPhysics* moving_physics=NULL);
|
||||
|
||||
@@ -24,9 +24,11 @@
|
||||
#include "scene.hpp"
|
||||
#include "coord.hpp"
|
||||
|
||||
Herring::Herring(herringType type, const Vec3& xyz, ssgEntity* model)
|
||||
Herring::Herring(herringType type, const Vec3& xyz, ssgEntity* model,
|
||||
unsigned int herring_id)
|
||||
: m_coord(xyz, Vec3(0, 0, 0))
|
||||
{
|
||||
m_herring_id = herring_id;
|
||||
m_type = type;
|
||||
m_eaten = false;
|
||||
m_time_till_return = 0.0f; // not strictly necessary, see isEaten()
|
||||
|
||||
@@ -30,7 +30,7 @@ class ssgTransform;
|
||||
class ssgEntity;
|
||||
|
||||
// HE_RED must be the first, HE_SILVER the last entry. See HerringManager
|
||||
enum herringType { HE_RED, HE_GREEN, HE_GOLD, HE_SILVER };
|
||||
enum herringType { HE_RED, HE_GREEN, HE_GOLD, HE_SILVER, HE_NONE };
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
class Herring
|
||||
@@ -42,10 +42,12 @@ private:
|
||||
Coord m_coord; // Original coordinates, used mainly when
|
||||
// eaten herrings reappear.
|
||||
ssgTransform* m_root; // The actual root of the herring
|
||||
|
||||
unsigned int m_herring_id; // index in herring_manager field
|
||||
public:
|
||||
Herring (herringType type, const Vec3& xyz, ssgEntity* model);
|
||||
Herring (herringType type, const Vec3& xyz, ssgEntity* model,
|
||||
unsigned int herring_id);
|
||||
~Herring ();
|
||||
unsigned int getHerringId() const {return m_herring_id; }
|
||||
void update (float delta);
|
||||
void isEaten ();
|
||||
int hitKart (Kart* kart );
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "herring_manager.hpp"
|
||||
#include "file_manager.hpp"
|
||||
@@ -29,6 +31,7 @@
|
||||
#include "kart.hpp"
|
||||
#include "string_utils.hpp"
|
||||
#include "translation.hpp"
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
@@ -197,22 +200,36 @@ void HerringManager::setDefaultHerringStyle()
|
||||
//-----------------------------------------------------------------------------
|
||||
Herring* HerringManager::newHerring(herringType type, const Vec3& xyz)
|
||||
{
|
||||
Herring* h = new Herring(type, xyz, m_herring_model[type]);
|
||||
Herring* h = new Herring(type, xyz, m_herring_model[type], m_all_herrings.size());
|
||||
m_all_herrings.push_back(h);
|
||||
return h;
|
||||
} // newHerring
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Set a herring as eaten.
|
||||
* This function is called on the server when a herring is eaten, or on the
|
||||
* client upon receiving information about eaten herrings. */
|
||||
void HerringManager::eatenHerring(int herring_id, Kart *kart,
|
||||
int add_info)
|
||||
{
|
||||
Herring *herring=m_all_herrings[herring_id];
|
||||
herring->isEaten();
|
||||
kart->collectedHerring(*herring, add_info);
|
||||
} // eatenHerring
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HerringManager::hitHerring(Kart* kart)
|
||||
{
|
||||
// Only do this on the server
|
||||
if(network_manager->getMode()!=NetworkManager::NW_SERVER) return;
|
||||
|
||||
for(AllHerringType::iterator i =m_all_herrings.begin();
|
||||
i!=m_all_herrings.end(); i++)
|
||||
{
|
||||
if((*i)->wasEaten()) continue;
|
||||
if((*i)->hitKart(kart))
|
||||
{
|
||||
(*i)->isEaten();
|
||||
kart->collectedHerring(*i);
|
||||
eatenHerring(i-m_all_herrings.begin(), kart);
|
||||
} // if hit
|
||||
} // for m_all_herrings
|
||||
} // hitHerring
|
||||
|
||||
@@ -64,6 +64,8 @@ public:
|
||||
void reset ();
|
||||
void removeTextures ();
|
||||
void setUserFilename (char *s) {m_user_filename=s;}
|
||||
void eatenHerring (int herring_id, Kart *kart,
|
||||
int add_info=-1);
|
||||
ssgEntity* getHerringModel (herringType type)
|
||||
{return m_herring_model[type];}
|
||||
};
|
||||
|
||||
@@ -1090,10 +1090,6 @@
|
||||
RelativePath="..\..\network\kart_control_message.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network\kart_packet.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network\kart_update_message.cpp"
|
||||
>
|
||||
@@ -1114,6 +1110,10 @@
|
||||
RelativePath="..\..\network\race_info_message.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network\race_state.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="utils"
|
||||
@@ -1648,6 +1648,10 @@
|
||||
RelativePath="..\..\network\race_start_message.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network\race_state.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network\remote_kart_info.hpp"
|
||||
>
|
||||
|
||||
45
src/kart.cpp
45
src/kart.cpp
@@ -19,6 +19,8 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#define _WINSOCKAPI_
|
||||
#include "network/network_manager.hpp"
|
||||
#include <plib/ssg.h>
|
||||
#include "bullet/Demos/OpenGL/GL_ShapeDrawer.h"
|
||||
|
||||
@@ -42,6 +44,9 @@
|
||||
#include "translation.hpp"
|
||||
#include "smoke.hpp"
|
||||
#include "material_manager.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
|
||||
// num_players triggers 'already defined' messages without the WINSOCKAPI define. Don't ask me :(
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# define snprintf _snprintf
|
||||
@@ -329,6 +334,7 @@ void Kart::reset()
|
||||
m_num_herrings_gobbled = 0;
|
||||
m_wheel_rotation = 0;
|
||||
m_wheelie_angle = 0.0f;
|
||||
m_bounce_back_time = 0.0f;
|
||||
|
||||
m_controls.lr = 0.0f;
|
||||
m_controls.accel = 0.0f;
|
||||
@@ -464,20 +470,29 @@ void Kart::raceFinished(float time)
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Kart::collectedHerring(Herring* herring)
|
||||
void Kart::collectedHerring(const Herring &herring, int random_attachment)
|
||||
{
|
||||
const herringType TYPE = herring->getType();
|
||||
const herringType type = herring.getType();
|
||||
const int OLD_HERRING_GOBBLED = m_num_herrings_gobbled;
|
||||
|
||||
switch (TYPE)
|
||||
switch (type)
|
||||
{
|
||||
case HE_GREEN : m_attachment.hitGreenHerring(); break;
|
||||
case HE_SILVER : m_num_herrings_gobbled++ ; break;
|
||||
case HE_GOLD : m_num_herrings_gobbled += 3 ; break;
|
||||
case HE_GREEN : m_attachment.hitGreenHerring(herring); break;
|
||||
case HE_SILVER : m_num_herrings_gobbled++ ; break;
|
||||
case HE_GOLD : m_num_herrings_gobbled += 3 ; break;
|
||||
case HE_RED : int n=1 + 4*getNumHerring() / MAX_HERRING_EATEN;
|
||||
m_collectable.hitRedHerring(n); break;
|
||||
m_collectable.hitRedHerring(n, herring); break;
|
||||
} // switch TYPE
|
||||
|
||||
// Attachments and collectables are stored in the corresponding
|
||||
// functions (hit{Red,Green}Herring), so only coins need to be
|
||||
// stored here.
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER &&
|
||||
(type==HE_SILVER || type==HE_GOLD) )
|
||||
{
|
||||
race_state->herringCollected(getWorldKartId(), herring.getHerringId());
|
||||
}
|
||||
|
||||
if ( m_num_herrings_gobbled > MAX_HERRING_EATEN )
|
||||
m_num_herrings_gobbled = MAX_HERRING_EATEN;
|
||||
|
||||
@@ -567,6 +582,7 @@ void Kart::update(float dt)
|
||||
m_rescue_pitch = getHPR().getPitch();
|
||||
m_rescue_roll = getHPR().getRoll();
|
||||
world->getPhysics()->removeKart(this);
|
||||
race_state->herringCollected(getWorldKartId(), -1, -1);
|
||||
}
|
||||
btQuaternion q_roll (btVector3(0.f, 1.f, 0.f),
|
||||
-m_rescue_roll*dt/rescue_time*M_PI/180.0f);
|
||||
@@ -780,13 +796,24 @@ void Kart::resetBrakes()
|
||||
for(int i=0; i<4; i++) m_vehicle->setBrake(0.0f, i);
|
||||
} // resetBrakes
|
||||
// -----------------------------------------------------------------------------
|
||||
void Kart::crashed(Kart *k)
|
||||
{
|
||||
// After a collision disable the engine for a short time so that karts
|
||||
// can 'bounce back' a bit (without this the engine force will prevent
|
||||
// karts from bouncing back, they will instead stuck towards the obstable).
|
||||
m_bounce_back_time = 0.5f;
|
||||
} // crashed
|
||||
// -----------------------------------------------------------------------------
|
||||
void Kart::updatePhysics (float dt)
|
||||
{
|
||||
m_bounce_back_time-=dt;
|
||||
float engine_power = getActualWheelForce() + handleWheelie(dt);
|
||||
if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
|
||||
|
||||
if(m_controls.accel)
|
||||
{ // accelerating
|
||||
if(m_controls.accel) // accelerating
|
||||
{ // For a short time after a collision disable the engine,
|
||||
// so that the karts can bounce back a bit from the obstacle.
|
||||
if(m_bounce_back_time>0.0f) engine_power = 0.0f;
|
||||
m_vehicle->applyEngineForce(engine_power, 2);
|
||||
m_vehicle->applyEngineForce(engine_power, 3);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ private:
|
||||
btTransform m_reset_transform; // reset position
|
||||
Vec3 m_curr_track_coords;
|
||||
Vec3 m_last_track_coords;
|
||||
unsigned int m_world_kart_id; // index of kart in world
|
||||
|
||||
protected:
|
||||
bool m_on_road; // true if the kart is on top of the
|
||||
@@ -60,6 +61,8 @@ protected:
|
||||
float m_zipper_time_left; // zipper time left
|
||||
float m_lap_start_time; // Time at start of a new lap
|
||||
char m_fastest_lap_message[255];
|
||||
float m_bounce_back_time; // a short time after a collision acceleration
|
||||
// is disabled to allow the karts to bounce back
|
||||
|
||||
int m_shortcut_sector; // segment on which the shortcut was started
|
||||
|
||||
@@ -107,6 +110,8 @@ public:
|
||||
Kart(const std::string& kart_name, int position,
|
||||
const btTransform& init_transform);
|
||||
virtual ~Kart();
|
||||
unsigned int getWorldKartId() const { return m_world_kart_id; }
|
||||
void setWorldKartId(unsigned int n) { m_world_kart_id=n; }
|
||||
void loadData();
|
||||
virtual void updateGraphics (const Vec3& off_xyz, const Vec3& off_hpr);
|
||||
const KartProperties*
|
||||
@@ -207,10 +212,10 @@ public:
|
||||
virtual int isPlayerKart () const {return 0; }
|
||||
// addMessages gets called by world to add messages to the gui
|
||||
virtual void addMessages () {};
|
||||
virtual void collectedHerring (Herring* herring);
|
||||
virtual void collectedHerring (const Herring &herring, int random_attachment);
|
||||
virtual void reset ();
|
||||
virtual void handleZipper ();
|
||||
virtual void crashed (Kart *k) {};
|
||||
virtual void crashed (Kart *k);
|
||||
virtual void doLapCounting ();
|
||||
virtual void update (float dt);
|
||||
virtual void raceFinished (float time);
|
||||
|
||||
@@ -28,13 +28,13 @@ class CharacterInfoMessage : public Message
|
||||
public:
|
||||
CharacterInfoMessage(int hostid) :Message(Message::MT_CHARACTER_INFO)
|
||||
{
|
||||
allocate(getLength(hostid));
|
||||
add(hostid);
|
||||
allocate(getCharLength());
|
||||
addChar(hostid);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
CharacterInfoMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
|
||||
{
|
||||
int hostid=getInt();
|
||||
int hostid=getChar();
|
||||
network_manager->setHostId(hostid);
|
||||
}
|
||||
}; // CharacterInfoMessage
|
||||
|
||||
@@ -37,23 +37,23 @@ public:
|
||||
m_kart_info = race_manager->getLocalKartInfo(player_id);
|
||||
m_num_local_players = race_manager->getNumLocalPlayers();
|
||||
|
||||
allocate(getLength(m_kart_info.getLocalPlayerId())
|
||||
+getLength(m_kart_info.getKartName())
|
||||
+getLength(m_kart_info.getPlayerName())
|
||||
+getLength(m_num_local_players) );
|
||||
add(m_kart_info.getLocalPlayerId());
|
||||
add(m_kart_info.getKartName());
|
||||
add(m_kart_info.getPlayerName());
|
||||
allocate(getCharLength() // m_kart_info.getLocalPlayerId())
|
||||
+getStringLength(m_kart_info.getKartName())
|
||||
+getStringLength(m_kart_info.getPlayerName())
|
||||
+getCharLength()); // m_num_local_players)
|
||||
addChar(m_kart_info.getLocalPlayerId());
|
||||
addString(m_kart_info.getKartName());
|
||||
addString(m_kart_info.getPlayerName());
|
||||
// Piggy backing this information saves sending it as a separate
|
||||
// message. It is actually only required in the first message
|
||||
add(race_manager->getNumLocalPlayers());
|
||||
addChar(race_manager->getNumLocalPlayers());
|
||||
}
|
||||
CharacterSelectedMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
|
||||
{
|
||||
m_kart_info.setLocalPlayerId(getInt());
|
||||
m_kart_info.setLocalPlayerId(getChar());
|
||||
m_kart_info.setKartName(getString());
|
||||
m_kart_info.setPlayerName(getString());
|
||||
m_num_local_players = getInt();
|
||||
m_num_local_players = getChar();
|
||||
}
|
||||
const RemoteKartInfo& getKartInfo () const { return m_kart_info; }
|
||||
int getNumPlayers() const { return m_num_local_players; }
|
||||
|
||||
@@ -40,8 +40,8 @@ private:
|
||||
const std::string& id=user_config->m_player[0].getName();
|
||||
std::ostringstream o;
|
||||
o << id << '@' << hostname;
|
||||
allocate(getLength(o.str()));
|
||||
add(o.str());
|
||||
allocate(getStringLength(o.str()));
|
||||
addString(o.str());
|
||||
}
|
||||
public:
|
||||
ConnectMessage():Message(Message::MT_CONNECT) { setId(); }
|
||||
|
||||
@@ -33,7 +33,7 @@ KartControlMessage::KartControlMessage()
|
||||
const KartControl& controls = kart->getControls();
|
||||
char c[9];
|
||||
controls.compress(c);
|
||||
add(c, control_size);
|
||||
addCharArray(c, control_size);
|
||||
}
|
||||
} // KartControlMessage
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -47,7 +47,7 @@ KartControlMessage::KartControlMessage(ENetPacket* pkt, int kart_id_offset,
|
||||
for(int i=kart_id_offset; i<kart_id_offset+num_local_players; i++)
|
||||
{
|
||||
char c[9];
|
||||
getChar(c, KartControl::getCompressedSize());
|
||||
getCharArray(c, KartControl::getCompressedSize());
|
||||
KartControl kc;
|
||||
kc.uncompress(c);
|
||||
NetworkKart *kart=world->getNetworkKart(i);
|
||||
|
||||
@@ -27,9 +27,10 @@ KartUpdateMessage::KartUpdateMessage()
|
||||
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);
|
||||
allocate(getCharLength()+
|
||||
num_karts*(KartControl::getCompressedSize() + getVec3Length()
|
||||
+getQuaternionLength()) );
|
||||
addChar(num_karts);
|
||||
for(unsigned int i=0; i<num_karts; i++)
|
||||
{
|
||||
const Kart* kart=world->getKart(i);
|
||||
@@ -37,9 +38,9 @@ KartUpdateMessage::KartUpdateMessage()
|
||||
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());
|
||||
addCharArray(compressed, KartControl::getCompressedSize());
|
||||
addVec3(kart->getXYZ());
|
||||
addQuaternion(kart->getRotation());
|
||||
} // for i
|
||||
} // KartUpdateMessage
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -51,9 +52,10 @@ KartUpdateMessage::KartUpdateMessage(ENetPacket* pkt)
|
||||
{
|
||||
assert(KartControl::getCompressedSize()<=9);
|
||||
char compressed[9]; // avoid new/delete overhead
|
||||
getChar(compressed, KartControl::getCompressedSize());
|
||||
getCharArray(compressed, KartControl::getCompressedSize());
|
||||
KartControl kc;
|
||||
kc.uncompress(compressed);
|
||||
// Currently not used
|
||||
Vec3 xyz = getVec3();
|
||||
btQuaternion q = getQuaternion();
|
||||
Kart *kart = world->getKart(i);
|
||||
|
||||
@@ -21,15 +21,13 @@
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
// need a more elegant way of setting the data_size, esp when strings are being used
|
||||
|
||||
// also, looking at how the packets are actually used, we can probably serialise as
|
||||
// part of the constructor, it seems packets to be sent are always created in a
|
||||
// single line
|
||||
#include <assert.h>
|
||||
|
||||
/** Creates a message to be sent.
|
||||
* This only initialised the data structures, it does not reserve any memory.
|
||||
* A call to allocate() is therefore necessary.
|
||||
* \param type The type of the message
|
||||
*/
|
||||
Message::Message(MessageType type)
|
||||
{
|
||||
assert(sizeof(int)==4);
|
||||
@@ -41,7 +39,24 @@ Message::Message(MessageType type)
|
||||
} // Message
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Handles a received message.
|
||||
* The message in pkt is received, and the message type is checked.
|
||||
* \param pkt The ENetPacket
|
||||
* \param m The type of the message. The type is checked via an assert!
|
||||
*/
|
||||
|
||||
Message::Message(ENetPacket* pkt, MessageType m)
|
||||
{
|
||||
receive(pkt, m);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads the message in pkt, and checks for the correct message type.
|
||||
* Paramaters:
|
||||
* \param pkt The ENetPacket
|
||||
* \param m The type of the message. The type is checked via an assert!
|
||||
*/
|
||||
void Message::receive(ENetPacket* pkt, MessageType m)
|
||||
{
|
||||
assert(sizeof(int)==4);
|
||||
m_pkt = pkt;
|
||||
@@ -54,13 +69,27 @@ Message::Message(ENetPacket* pkt, MessageType m)
|
||||
} // Message
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Frees the memory allocated for this message. */
|
||||
Message::~Message()
|
||||
{
|
||||
if(m_needs_destroy)
|
||||
enet_packet_destroy(m_pkt);
|
||||
clear();
|
||||
} // ~Message
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Frees the memory for a received message.
|
||||
* Calls enet_packet_destroy if necessary (i.e. if the message was received).
|
||||
* The memory for a message created to be sent does not need to be freed, it
|
||||
* is handled by enet. */
|
||||
void Message::clear()
|
||||
{
|
||||
if(m_needs_destroy)
|
||||
enet_packet_destroy(m_pkt);
|
||||
} // clear
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Reserves the memory for a message.
|
||||
* \param size Number of bytes to reserve.
|
||||
*/
|
||||
void Message::allocate(int size)
|
||||
{
|
||||
m_data_size = size+1;
|
||||
@@ -71,23 +100,49 @@ void Message::allocate(int size)
|
||||
} // allocate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Message::add(int data)
|
||||
/** Adds an integer value to the message.
|
||||
* \param data The integer value to add.
|
||||
*/
|
||||
void Message::addInt(int data)
|
||||
{
|
||||
if ((int)(m_pos + sizeof(int)) > m_data_size)
|
||||
return false;
|
||||
assert((int)(m_pos + sizeof(int)) <= m_data_size);
|
||||
int l=htonl(data);
|
||||
memcpy(m_data+m_pos, &l, sizeof(int));
|
||||
m_pos+=sizeof(int);
|
||||
return true;
|
||||
} // add<int>
|
||||
} // addInt
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Extracts an integer value from a message.
|
||||
* \return The extracted integer.
|
||||
*/
|
||||
int Message::getInt()
|
||||
{
|
||||
m_pos+=sizeof(int);
|
||||
return ntohl(*(int*)(&m_data[m_pos-sizeof(int)]));
|
||||
} // getInt
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a short value to the message.
|
||||
* \param data The integer value to add.
|
||||
*/
|
||||
void Message::addShort(short data)
|
||||
{
|
||||
assert((int)(m_pos + sizeof(short)) <= m_data_size);
|
||||
int l=htons(data);
|
||||
memcpy(m_data+m_pos, &l, sizeof(short));
|
||||
m_pos+=sizeof(short);
|
||||
} // addShort
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Extracts a short value from a message.
|
||||
* \return The short value.
|
||||
*/
|
||||
short Message::getShort()
|
||||
{
|
||||
m_pos+=sizeof(short);
|
||||
return ntohs(*(short*)(&m_data[m_pos-sizeof(short)]));
|
||||
} // getShort
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float Message::getFloat()
|
||||
{
|
||||
@@ -103,14 +158,13 @@ float Message::getFloat()
|
||||
} // getFloat
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Message::add(const std::string &data)
|
||||
void Message::addString(const std::string &data)
|
||||
{
|
||||
int len = data.size()+1; // copy 0 end byte
|
||||
assert((int)(m_pos+len) <=m_data_size);
|
||||
memcpy (&(m_data[m_pos]), data.c_str(), len);
|
||||
m_pos += len;
|
||||
return true;
|
||||
} // add<string>
|
||||
} // addString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string Message::getString()
|
||||
@@ -122,28 +176,33 @@ std::string Message::getString()
|
||||
} // getString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int Message::getLength(const std::vector<std::string>& vs)
|
||||
/** Returns the number of bytes necessary to store a string vector.
|
||||
* \param vs std::vector<std::string>
|
||||
*/
|
||||
int Message::getStringVectorLength(const std::vector<std::string>& vs)
|
||||
{
|
||||
int len=getLength(vs.size());
|
||||
int len=getShortLength();
|
||||
for(unsigned int i=0; i<vs.size(); i++)
|
||||
len += getLength(vs[i]);
|
||||
len += getStringLength(vs[i]);
|
||||
return len;
|
||||
} // getLength(vector<string>)
|
||||
} // getStringVectorLength
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Message::add(const std::vector<std::string>& vs)
|
||||
/** Adds a std::vector<std::string> to the message.
|
||||
*/
|
||||
void Message::addStringVector(const std::vector<std::string>& vs)
|
||||
{
|
||||
bool result = add(vs.size());
|
||||
if(!result) return false;
|
||||
for(unsigned int i=0; i<vs.size(); i++)
|
||||
if(!add(vs[i])) return false;
|
||||
return true;
|
||||
} // add(vector<string>)
|
||||
assert(vs.size()<32767);
|
||||
addShort(vs.size());
|
||||
for(unsigned short i=0; i<vs.size(); i++)
|
||||
addString(vs[i]);
|
||||
} // addStringVector
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::vector<std::string> Message::getStringVector()
|
||||
{
|
||||
std::vector<std::string> vs;
|
||||
vs.resize(getInt());
|
||||
vs.resize(getShort());
|
||||
for(unsigned int i=0; i<vs.size(); i++)
|
||||
vs[i]=getString();
|
||||
return vs;
|
||||
|
||||
@@ -34,13 +34,21 @@
|
||||
// sjl: when a message is received, need to work out what kind of message it
|
||||
// is and therefore what to do with it
|
||||
|
||||
// Collects and serialises/deserialises kart info to send
|
||||
/** Base class to serialises/deserialises messages.
|
||||
* This is the base class for all messages being exchange between client
|
||||
* and server. It handles the interface to enet, and adds a message type
|
||||
* (which is checked via an assert to help finding bugs by receiving a
|
||||
* message of an incorrect type). It also takes care of endianess (though
|
||||
* floats are converted via a byte swap, too - so it must be guaranteed
|
||||
* that the float representation between all machines is identical).
|
||||
*/
|
||||
class Message
|
||||
{
|
||||
public:
|
||||
enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO,
|
||||
MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
|
||||
MT_KART_INFO, MT_KART_CONTROL};
|
||||
MT_KART_INFO, MT_KART_CONTROL,
|
||||
MT_RACE_STATE};
|
||||
private:
|
||||
ENetPacket *m_pkt;
|
||||
char *m_data;
|
||||
@@ -50,38 +58,42 @@ private:
|
||||
bool m_needs_destroy; // only received messages need to be destroyed
|
||||
|
||||
protected:
|
||||
bool add(int data);
|
||||
bool add(const std::string &data);
|
||||
bool add(const std::vector<std::string>& vs);
|
||||
bool add(float data) { return add(*(int*)&data); }
|
||||
bool add(char *c, unsigned int n)
|
||||
{ if((int)(m_pos+n)>m_data_size)
|
||||
return false;
|
||||
void addInt(int data);
|
||||
void addShort(short data);
|
||||
void addString(const std::string &data);
|
||||
void addStringVector(const std::vector<std::string>& vs);
|
||||
void addUInt(unsigned int data) { addInt(*(int*)&data); }
|
||||
void addFloat(float data) { addInt(*(int*)&data); }
|
||||
void addBool(bool data) { addChar(data?1:0); }
|
||||
void addChar(char data) { addCharArray((char*)&data,1);}
|
||||
void addCharArray(char *c, unsigned int n=1)
|
||||
{ assert((int)(m_pos+n)<=m_data_size);
|
||||
memcpy(m_data+m_pos,c,n);
|
||||
m_pos+=n;
|
||||
return true; }
|
||||
m_pos+=n; }
|
||||
#ifndef WIN32 // on windows size_t is unsigned int
|
||||
bool add(size_t data) { return add((int)data); }
|
||||
void addSizeT(size_t data) { addInt((int)data); }
|
||||
#endif
|
||||
bool add(unsigned int data) { return add(*(int*)&data); }
|
||||
bool add(int *d, unsigned int n)
|
||||
void addIntArray(int *d, unsigned int n)
|
||||
{ for(unsigned int i=0;
|
||||
i<n-1; i++)
|
||||
add(d[i]);
|
||||
return add(d[n-1]); }
|
||||
bool add(const Vec3& v) { add(v.getX());
|
||||
add(v.getY());
|
||||
return add(v.getZ()); }
|
||||
bool add(const btQuaternion& q) { add(q.getX());
|
||||
add(q.getY());
|
||||
add(q.getZ());
|
||||
return add(q.getW()); }
|
||||
i<n; i++)
|
||||
addInt(d[i]); }
|
||||
void addVec3(const Vec3& v) { addFloat(v.getX());
|
||||
addFloat(v.getY());
|
||||
addFloat(v.getZ()); }
|
||||
void addQuaternion(const btQuaternion& q) { addFloat(q.getX());
|
||||
addFloat(q.getY());
|
||||
addFloat(q.getZ());
|
||||
addFloat(q.getW()); }
|
||||
int getInt();
|
||||
bool getBool() { return getChar()==1; }
|
||||
short getShort();
|
||||
float getFloat();
|
||||
std::string getString();
|
||||
std::vector<std::string>
|
||||
getStringVector();
|
||||
void getChar(char *c, int n) {memcpy(c,m_data+m_pos,n);
|
||||
char getChar() {char c;getCharArray(&c,1);
|
||||
return c; }
|
||||
void getCharArray(char *c, int n=1) {memcpy(c,m_data+m_pos,n);
|
||||
m_pos+=n;
|
||||
return; }
|
||||
Vec3 getVec3() { Vec3 v;
|
||||
@@ -95,26 +107,30 @@ protected:
|
||||
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 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 getLength(const std::vector<std::string>& vs);
|
||||
int getStringVectorLength(const std::vector<std::string>& vs);
|
||||
#ifndef WIN32
|
||||
int getLength(size_t n) { return sizeof(int); }
|
||||
int getSizeTLength(size_t n) { return sizeof(int); }
|
||||
#endif
|
||||
|
||||
public:
|
||||
Message(MessageType m); // create from scratch (to send)
|
||||
Message(ENetPacket *pkt, MessageType m); // create from (received) packet
|
||||
Message(MessageType m);
|
||||
Message(ENetPacket *pkt, MessageType m);
|
||||
void receive(ENetPacket *pkt, MessageType m);
|
||||
~Message();
|
||||
void clear();
|
||||
void allocate(int size);
|
||||
MessageType getType() const { return m_type; }
|
||||
ENetPacket* getPacket() const { assert(m_data_size>-1); return m_pkt; }
|
||||
// Return the type of a message without unserialising the message
|
||||
/** Return the type of a message without unserialising the message */
|
||||
static MessageType peekType(ENetPacket *pkt)
|
||||
{ return (MessageType)pkt->data[0];}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class NetworkKart : public Kart
|
||||
private:
|
||||
int m_global_player_id; // to identify this kart to the network manager
|
||||
public:
|
||||
NetworkKart(const std::string& kart_name, int position,
|
||||
NetworkKart(const std::string& kart_name, int position,
|
||||
const btTransform& init_transform,
|
||||
int global_player_id);
|
||||
void setControl(const KartControl& kc);
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network_manager.hpp"
|
||||
#include "connect_message.hpp"
|
||||
#include "character_info_message.hpp"
|
||||
#include "character_selected_message.hpp"
|
||||
#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 "network/connect_message.hpp"
|
||||
#include "network/character_info_message.hpp"
|
||||
#include "network/character_selected_message.hpp"
|
||||
#include "network/race_info_message.hpp"
|
||||
#include "network/race_start_message.hpp"
|
||||
#include "network/world_loaded_message.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
#include "network/kart_control_message.hpp"
|
||||
#include "stk_config.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "race_manager.hpp"
|
||||
@@ -277,7 +277,7 @@ void NetworkManager::handleMessageAtClient(ENetEvent *event)
|
||||
}
|
||||
case NS_RACING:
|
||||
{
|
||||
KartUpdateMessage k(event->packet);
|
||||
assert(false); // should never be here while racing
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -454,10 +454,10 @@ void NetworkManager::sendUpdates()
|
||||
{
|
||||
if(m_mode==NW_SERVER)
|
||||
{
|
||||
KartUpdateMessage m;
|
||||
broadcastToClients(m);
|
||||
race_state->serialise();
|
||||
broadcastToClients(*race_state);
|
||||
}
|
||||
else
|
||||
else if(m_mode==NW_CLIENT)
|
||||
{
|
||||
KartControlMessage m;
|
||||
sendToServer(m);
|
||||
@@ -467,6 +467,7 @@ void NetworkManager::sendUpdates()
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::receiveUpdates()
|
||||
{
|
||||
if(m_mode==NW_NONE) return; // do nothing if not networking
|
||||
// The server receives m_num_clients messages, each client one message
|
||||
int num_messages = m_mode==NW_SERVER ? m_num_clients : 1;
|
||||
ENetEvent event;
|
||||
@@ -502,7 +503,7 @@ void NetworkManager::receiveUpdates()
|
||||
}
|
||||
else
|
||||
{
|
||||
KartUpdateMessage(event.packet);
|
||||
race_state->receive(event.packet);
|
||||
}
|
||||
} // for i<num_messages
|
||||
if(!correct)
|
||||
|
||||
@@ -25,64 +25,62 @@ RaceInfoMessage::RaceInfoMessage(const std::vector<RemoteKartInfo>& kart_info)
|
||||
: Message(Message::MT_RACE_INFO)
|
||||
{
|
||||
const GrandPrixData *cup=NULL;
|
||||
int len = getLength(race_manager->getMajorMode() )
|
||||
+ getLength(race_manager->getMinorMode() )
|
||||
+ getLength(race_manager->getDifficulty())
|
||||
+ getLength(race_manager->getNumKarts() );
|
||||
int len = 3*getCharLength() // major, minor, difficulty
|
||||
+ getCharLength(); // num karts
|
||||
if(race_manager->getMajorMode()==RaceManager::RM_GRAND_PRIX)
|
||||
{
|
||||
cup = race_manager->getGrandPrix();
|
||||
len += getLength(cup->getId());
|
||||
len += getStringLength(cup->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
len += getLength(race_manager->getTrackName());
|
||||
len += getLength(race_manager->getNumLaps());
|
||||
len += getStringLength(race_manager->getTrackName());
|
||||
len += getCharLength(); // num laps
|
||||
}
|
||||
len += getLength(kart_info.size());
|
||||
len += getCharLength(); // kart_info.size()
|
||||
for(unsigned int i=0; i<kart_info.size(); i++)
|
||||
{
|
||||
len += getLength(kart_info[i].getGlobalPlayerId())
|
||||
+ getLength(kart_info[i].getHostId())
|
||||
+ getLength(kart_info[i].getKartName())
|
||||
+ getLength(kart_info[i].getLocalPlayerId())
|
||||
+ getLength(kart_info[i].getPlayerName());
|
||||
len += getCharLength() // kart_info[i].getGlobalPlayerId())
|
||||
+ getCharLength() // kart_info[i].getHostId())
|
||||
+ getStringLength(kart_info[i].getKartName())
|
||||
+ getCharLength() // kart_info[i].getLocalPlayerId())
|
||||
+ getStringLength(kart_info[i].getPlayerName());
|
||||
}
|
||||
const std::vector<std::string>& rkl=race_manager->getRandomKartList();
|
||||
len += getLength(rkl);
|
||||
len += getStringVectorLength(rkl);
|
||||
|
||||
allocate(len);
|
||||
add(race_manager->getMajorMode() );
|
||||
add(race_manager->getMinorMode() );
|
||||
add(race_manager->getDifficulty());
|
||||
add(race_manager->getNumKarts() );
|
||||
addChar(race_manager->getMajorMode() );
|
||||
addChar(race_manager->getMinorMode() );
|
||||
addChar(race_manager->getDifficulty());
|
||||
addChar(race_manager->getNumKarts() );
|
||||
if(race_manager->getMajorMode()==RaceManager::RM_GRAND_PRIX)
|
||||
add(cup->getName());
|
||||
addString(cup->getName());
|
||||
else
|
||||
{
|
||||
add(race_manager->getTrackName());
|
||||
add(race_manager->getNumLaps());
|
||||
addString(race_manager->getTrackName());
|
||||
addChar(race_manager->getNumLaps());
|
||||
}
|
||||
|
||||
add(kart_info.size());
|
||||
addChar(kart_info.size());
|
||||
for(unsigned int i=0; i<kart_info.size(); i++)
|
||||
{
|
||||
add(kart_info[i].getGlobalPlayerId());
|
||||
add(kart_info[i].getHostId());
|
||||
add(kart_info[i].getKartName());
|
||||
add(kart_info[i].getLocalPlayerId());
|
||||
add(kart_info[i].getPlayerName());
|
||||
addChar(kart_info[i].getGlobalPlayerId());
|
||||
addChar(kart_info[i].getHostId());
|
||||
addString(kart_info[i].getKartName());
|
||||
addChar(kart_info[i].getLocalPlayerId());
|
||||
addString(kart_info[i].getPlayerName());
|
||||
}
|
||||
add(rkl);
|
||||
addStringVector(rkl);
|
||||
} // RaceInfoMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
RaceInfoMessage::RaceInfoMessage(ENetPacket* pkt):Message(pkt, MT_RACE_INFO)
|
||||
{
|
||||
race_manager->setMajorMode ( RaceManager::RaceModeType(getInt()) );
|
||||
race_manager->setMinorMode ( RaceManager::RaceModeType(getInt()) );
|
||||
race_manager->setDifficulty( RaceManager::Difficulty (getInt()) );
|
||||
race_manager->setNumKarts ( getInt() );
|
||||
race_manager->setMajorMode ( RaceManager::RaceModeType(getChar()) );
|
||||
race_manager->setMinorMode ( RaceManager::RaceModeType(getChar()) );
|
||||
race_manager->setDifficulty( RaceManager::Difficulty (getChar()) );
|
||||
race_manager->setNumKarts ( getChar() );
|
||||
if(race_manager->getMajorMode()==RaceManager::RM_GRAND_PRIX)
|
||||
{
|
||||
GrandPrixData cup;
|
||||
@@ -92,18 +90,18 @@ RaceInfoMessage::RaceInfoMessage(ENetPacket* pkt):Message(pkt, MT_RACE_INFO)
|
||||
else
|
||||
{
|
||||
race_manager->setTrack(getString());
|
||||
race_manager->setNumLaps(getInt());
|
||||
race_manager->setNumLaps(getChar());
|
||||
}
|
||||
|
||||
std::vector<RemoteKartInfo> kart_info;
|
||||
kart_info.resize(getInt());
|
||||
kart_info.resize(getChar());
|
||||
|
||||
for(unsigned int i=0; i<kart_info.size(); i++)
|
||||
{
|
||||
kart_info[i].setGlobalPlayerId(getInt());
|
||||
kart_info[i].setHostId(getInt());
|
||||
kart_info[i].setGlobalPlayerId(getChar());
|
||||
kart_info[i].setHostId(getChar());
|
||||
kart_info[i].setKartName(getString());
|
||||
kart_info[i].setLocalPlayerId(getInt());
|
||||
kart_info[i].setLocalPlayerId(getChar());
|
||||
kart_info[i].setPlayerName(getString());
|
||||
}
|
||||
|
||||
|
||||
@@ -246,10 +246,10 @@ void PlayerKart::handleZipper()
|
||||
} // handleZipper
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PlayerKart::collectedHerring(Herring* herring)
|
||||
void PlayerKart::collectedHerring(const Herring &herring, int add_info)
|
||||
{
|
||||
Kart::collectedHerring(herring);
|
||||
sound_manager->playSfx ( ( herring->getType()==HE_GREEN ) ? SOUND_UGH:SOUND_GRAB);
|
||||
Kart::collectedHerring(herring, add_info);
|
||||
sound_manager->playSfx ( ( herring.getType()==HE_GREEN ) ? SOUND_UGH:SOUND_GRAB);
|
||||
} // collectedHerring
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -42,27 +42,23 @@ private:
|
||||
|
||||
void steer(float, int);
|
||||
public:
|
||||
PlayerKart(const std::string& kart_name,
|
||||
int position, Player *_player,
|
||||
const btTransform& init_pos, int player_index);
|
||||
PlayerKart(const std::string& kart_name,
|
||||
int position, Player *_player,
|
||||
const btTransform& init_pos, int player_index);
|
||||
|
||||
int earlyStartPenalty () {return m_penalty_time>0; }
|
||||
Player* getPlayer () {return m_player; }
|
||||
void update (float);
|
||||
void addMessages ();
|
||||
void action (KartAction action, int value);
|
||||
void crashed (Kart *k);
|
||||
void handleZipper ();
|
||||
void collectedHerring (Herring* herring);
|
||||
int earlyStartPenalty () {return m_penalty_time>0; }
|
||||
Player *getPlayer () {return m_player; }
|
||||
void update (float);
|
||||
void addMessages ();
|
||||
void action (KartAction action, int value);
|
||||
void handleZipper ();
|
||||
void collectedHerring (const Herring &herring, int add_info=-1);
|
||||
virtual void crashed (Kart *k);
|
||||
virtual void setPosition (int p);
|
||||
virtual void raceFinished (float time);
|
||||
|
||||
int isPlayerKart () const {return 1;}
|
||||
Camera* getCamera () {return m_camera;}
|
||||
|
||||
void reset();
|
||||
int isPlayerKart () const {return 1;}
|
||||
Camera* getCamera () {return m_camera;}
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
#include "loader.hpp"
|
||||
#include "projectile_manager.hpp"
|
||||
#include "bowling.hpp"
|
||||
@@ -81,12 +83,15 @@ void ProjectileManager::cleanup()
|
||||
/** General projectile update call. */
|
||||
void ProjectileManager::update(float dt)
|
||||
{
|
||||
// First update all projectiles on the track
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); ++i)
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
(*i)->update(dt);
|
||||
updateClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateServer(dt);
|
||||
}
|
||||
|
||||
// Then check if any projectile hit something
|
||||
if(m_something_was_hit)
|
||||
{
|
||||
@@ -124,6 +129,50 @@ void ProjectileManager::update(float dt)
|
||||
m_something_was_hit=false;
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Updates all rockets on the server (or no networking). */
|
||||
void ProjectileManager::updateServer(float dt)
|
||||
{
|
||||
// First update all projectiles on the track
|
||||
if(network_manager->getMode()!=NetworkManager::NW_NONE)
|
||||
{
|
||||
race_state->setNumFlyables(m_active_projectiles.size());
|
||||
}
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); ++i)
|
||||
{
|
||||
(*i)->update(dt);
|
||||
// Store the state information on the server
|
||||
if(network_manager->getMode()!=NetworkManager::NW_NONE)
|
||||
{
|
||||
race_state->setFlyableInfo(i-m_active_projectiles.begin(),
|
||||
(*i)->getXYZ(), (*i)->getRotation(),
|
||||
(*i)->hasHit());
|
||||
}
|
||||
}
|
||||
} // updateServer
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Updates all rockets and explosions on the client.
|
||||
* updateClient takes the information in race_state and updates all rockets
|
||||
* (i.e. position, explosion etc) */
|
||||
void ProjectileManager::updateClient()
|
||||
{
|
||||
m_something_was_hit = false;
|
||||
unsigned int num_projectiles = race_state->getNumFlyables();
|
||||
// Race_state must contain at least as many entries as the current number
|
||||
// of projectiles. It can contain more if new projectiles have been added.
|
||||
assert(m_active_projectiles.size()<=num_projectiles);
|
||||
|
||||
int indx=0;
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); ++i, ++indx)
|
||||
{
|
||||
const Flyable::FlyableInfo &f = race_state->getFlyable(indx);
|
||||
(*i)->updateFromServer(f);
|
||||
if(f.m_exploded) m_something_was_hit = true;
|
||||
} // for i in m_active_projectiles
|
||||
} // updateClient
|
||||
// -----------------------------------------------------------------------------
|
||||
Flyable *ProjectileManager::newProjectile(Kart *kart, CollectableType type)
|
||||
{
|
||||
|
||||
@@ -32,8 +32,8 @@ class Flyable;
|
||||
class ProjectileManager
|
||||
{
|
||||
private:
|
||||
typedef std::vector<Flyable*> Projectiles;
|
||||
typedef std::vector<Explosion* > Explosions;
|
||||
typedef std::vector<Flyable*> Projectiles;
|
||||
typedef std::vector<Explosion*> Explosions;
|
||||
|
||||
// The list of all active projectiles, i.e. projectiles
|
||||
// which are currently moving on the track
|
||||
@@ -46,16 +46,18 @@ private:
|
||||
ssgSelector* m_explosion_model;
|
||||
bool m_something_was_hit;
|
||||
bool m_explosion_ended;
|
||||
|
||||
void updateClient();
|
||||
void updateServer(float dt);
|
||||
public:
|
||||
ProjectileManager() {m_something_was_hit=false;};
|
||||
~ProjectileManager() {};
|
||||
void explode () {m_something_was_hit=true;}
|
||||
void FinishedExplosion() {m_explosion_ended =true;}
|
||||
ProjectileManager() {m_something_was_hit=false;}
|
||||
~ProjectileManager() {}
|
||||
void explode () {m_something_was_hit=true; }
|
||||
void FinishedExplosion() {m_explosion_ended =true; }
|
||||
ssgSelector* getExplosionModel()
|
||||
{
|
||||
return (ssgSelector*)m_explosion_model->clone();
|
||||
}
|
||||
unsigned int getNumProjectiles() const {return m_active_explosions.size();}
|
||||
int getProjectileId (const std::string ident);
|
||||
void loadData ();
|
||||
void cleanup ();
|
||||
|
||||
@@ -58,6 +58,7 @@ void RaceManager::reset()
|
||||
{
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
m_player_karts.clear();
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "robots/default_robot.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
# include "replay_player.hpp"
|
||||
#endif
|
||||
@@ -63,6 +65,7 @@ World::World()
|
||||
{
|
||||
delete world;
|
||||
world = this;
|
||||
race_state = new RaceState();
|
||||
m_phase = SETUP_PHASE;
|
||||
m_previous_phase = SETUP_PHASE; // initialise it just in case
|
||||
m_track = NULL;
|
||||
@@ -131,16 +134,8 @@ World::World()
|
||||
m_local_player_karts[local_player_id] = static_cast<PlayerKart*>(newkart);
|
||||
break;
|
||||
case RaceManager::KT_NETWORK_PLAYER:
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
{
|
||||
newkart = new NetworkKart(kart_name, position, init_pos,
|
||||
global_player_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
newkart = new NetworkKart(kart_name, position, init_pos,
|
||||
global_player_id);
|
||||
}
|
||||
newkart = new NetworkKart(kart_name, position, init_pos,
|
||||
global_player_id);
|
||||
m_network_karts[global_player_id] = static_cast<NetworkKart*>(newkart);
|
||||
break;
|
||||
case RaceManager::KT_AI:
|
||||
@@ -160,6 +155,7 @@ World::World()
|
||||
|
||||
scene->add ( newkart -> getModelTransform() ) ;
|
||||
m_kart.push_back(newkart);
|
||||
newkart->setWorldKartId(m_kart.size()-1);
|
||||
} // for i
|
||||
|
||||
resetAllKarts();
|
||||
@@ -201,6 +197,7 @@ World::~World()
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
saveReplayHumanReadable( "test" );
|
||||
#endif
|
||||
delete race_state;
|
||||
m_track->cleanup();
|
||||
// Clear all callbacks
|
||||
callback_manager->clear(CB_TRACK);
|
||||
@@ -292,6 +289,8 @@ void World::resetAllKarts()
|
||||
//-----------------------------------------------------------------------------
|
||||
void World::update(float dt)
|
||||
{
|
||||
// Clear race state so that new information can be stored
|
||||
race_state->clear();
|
||||
if(user_config->m_replay_history) dt=history->GetNextDelta();
|
||||
updateRaceStatus(dt);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user