(s, value))
+ {
+ fprintf(stderr, "[XMLNode] WARNING: Expected uint but found '%s' for attribute '%s' of node '%s' in file %s\n",
+ s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str());
+ return 0;
+ }
+
+ return 1;
+} // get(uint32_t)
+
// ----------------------------------------------------------------------------
int XMLNode::get(const std::string &attribute, uint32_t *value) const
{
diff --git a/src/io/xml_node.hpp b/src/io/xml_node.hpp
index 953d52f8a..37e4ade41 100644
--- a/src/io/xml_node.hpp
+++ b/src/io/xml_node.hpp
@@ -74,6 +74,7 @@ public:
int get(const std::string &attribute, std::string *value) const;
int get(const std::string &attribute, core::stringw *value) const;
int get(const std::string &attribute, int32_t *value) const;
+ int get(const std::string &attribute, uint16_t *value) const;
int get(const std::string &attribute, uint32_t *value) const;
int get(const std::string &attribute, int64_t *value) const;
int get(const std::string &attribute, float *value) const;
diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp
index 1bbbdf2cc..7d7fbb6a0 100644
--- a/src/items/attachment.cpp
+++ b/src/items/attachment.cpp
@@ -33,8 +33,6 @@
#include "karts/kart_properties.hpp"
#include "modes/three_strikes_battle.hpp"
#include "modes/world.hpp"
-#include "network/race_state.hpp"
-#include "network/network_manager.hpp"
#include "utils/constants.hpp"
/** Initialises the attachment each kart has.
@@ -258,15 +256,6 @@ void Attachment::hitBanana(Item *item, int new_attachment)
new_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->itemCollected(m_kart->getWorldKartId(),
- item->getItemId(),
- new_attachment);
- }
-
if (add_a_new_item)
{
switch (new_attachment)
diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp
index d0116415d..b1ee43129 100644
--- a/src/items/flyable.cpp
+++ b/src/items/flyable.cpp
@@ -38,7 +38,6 @@
#include "karts/abstract_kart.hpp"
#include "karts/explosion_animation.hpp"
#include "modes/world.hpp"
-#include "network/flyable_info.hpp"
#include "physics/physics.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@@ -410,19 +409,6 @@ bool Flyable::updateAndDelete(float dt)
return false;
} // updateAndDelete
-// ----------------------------------------------------------------------------
-/** Updates the position of a projectile based on information received frmo the
- * server.
- */
-void Flyable::updateFromServer(const FlyableInfo &f, float dt)
-{
- setXYZ(f.m_xyz);
- setRotation(f.m_rotation);
-
- // Update the graphical position
- Moveable::update(dt);
-} // updateFromServer
-
// ----------------------------------------------------------------------------
/** Returns true if the item hit the kart who shot it (to avoid that an item
* that's too close to the shoter hits the shoter).
diff --git a/src/items/flyable.hpp b/src/items/flyable.hpp
index bfd46835f..9030209f3 100644
--- a/src/items/flyable.hpp
+++ b/src/items/flyable.hpp
@@ -34,7 +34,6 @@ using namespace irr;
#include "tracks/terrain_info.hpp"
class AbstractKart;
-class FlyableInfo;
class HitEffect;
class PhysicalObject;
class XMLNode;
@@ -169,7 +168,6 @@ public:
virtual bool updateAndDelete(float);
virtual const core::stringw getHitString(const AbstractKart *kart) const = 0;
virtual HitEffect* getHitEffect() const;
- void updateFromServer(const FlyableInfo &f, float dt);
bool isOwnerImmunity(const AbstractKart *kart_hit) const;
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
void explode(AbstractKart* kart, PhysicalObject* obj=NULL,
diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp
index 4b7fc0ad1..a76db40fe 100644
--- a/src/items/item_manager.cpp
+++ b/src/items/item_manager.cpp
@@ -29,7 +29,6 @@
#include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/linear_world.hpp"
-#include "network/network_manager.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
@@ -289,9 +288,6 @@ void ItemManager::collectedItem(Item *item, AbstractKart *kart, int add_info)
*/
void ItemManager::checkItemHit(AbstractKart* kart)
{
- // Only do this on the server
- if(network_manager->getMode()==NetworkManager::NW_CLIENT) return;
-
// We could use m_items_in_quads to to check for item hits: take the quad
// of the graph node of the kart, and only check items in that quad. But
// then we also need to check for any adjacent quads (since an item just
diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp
index d6bd8022c..a4264b16a 100644
--- a/src/items/powerup.cpp
+++ b/src/items/powerup.cpp
@@ -29,8 +29,6 @@
#include "karts/controller/controller.hpp"
#include "karts/kart_properties.hpp"
#include "modes/world.hpp"
-#include "network/network_manager.hpp"
-#include "network/race_state.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp
index f7846b684..18e299560 100644
--- a/src/items/projectile_manager.cpp
+++ b/src/items/projectile_manager.cpp
@@ -26,8 +26,6 @@
#include "items/powerup_manager.hpp"
#include "items/powerup.hpp"
#include "items/rubber_ball.hpp"
-#include "network/network_manager.hpp"
-#include "network/race_state.hpp"
ProjectileManager *projectile_manager=0;
@@ -66,14 +64,7 @@ void ProjectileManager::cleanup()
/** General projectile update call. */
void ProjectileManager::update(float dt)
{
- if(network_manager->getMode()==NetworkManager::NW_CLIENT)
- {
- updateClient(dt);
- }
- else
- {
- updateServer(dt);
- }
+ updateServer(dt);
HitEffects::iterator he = m_active_hit_effects.begin();
while(he!=m_active_hit_effects.end())
@@ -100,23 +91,10 @@ void ProjectileManager::update(float dt)
/** 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());
- }
-
Projectiles::iterator p = m_active_projectiles.begin();
while(p!=m_active_projectiles.end())
{
bool can_be_deleted = (*p)->updateAndDelete(dt);
- if(network_manager->getMode()!=NetworkManager::NW_NONE)
- {
- race_state->setFlyableInfo(p-m_active_projectiles.begin(),
- FlyableInfo((*p)->getXYZ(),
- (*p)->getRotation(),
- can_be_deleted) );
- }
if(can_be_deleted)
{
HitEffect *he = (*p)->getHitEffect();
@@ -130,32 +108,9 @@ void ProjectileManager::updateServer(float dt)
else
p++;
} // while p!=m_active_projectiles.end()
+
} // updateServer
-// -----------------------------------------------------------------------------
-/** Updates all rockets and hit effects on the client.
- * updateClient takes the information in race_state and updates all rockets
- * (i.e. position, hit effects etc) */
-void ProjectileManager::updateClient(float dt)
-{
- unsigned int num_projectiles = race_state->getNumFlyables();
- if(num_projectiles != m_active_projectiles.size())
- fprintf(stderr, "Warning: num_projectiles %d active %d\n",
- num_projectiles, (int)m_active_projectiles.size());
-
- unsigned int indx=0;
- for(Projectiles::iterator i = m_active_projectiles.begin();
- i != m_active_projectiles.end(); ++i, ++indx)
- {
- const FlyableInfo &f = race_state->getFlyable(indx);
- (*i)->updateFromServer(f, dt);
- if(f.m_exploded)
- {
- (*i)->hit(NULL);
- }
- } // for i in m_active_projectiles
-
-} // updateClient
// -----------------------------------------------------------------------------
Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
PowerupManager::PowerupType type)
diff --git a/src/items/projectile_manager.hpp b/src/items/projectile_manager.hpp
index f0906ca6b..8fb513502 100644
--- a/src/items/projectile_manager.hpp
+++ b/src/items/projectile_manager.hpp
@@ -53,7 +53,6 @@ private:
* being shown or have a sfx playing. */
HitEffects m_active_hit_effects;
- void updateClient(float dt);
void updateServer(float dt);
public:
ProjectileManager() {}
diff --git a/src/items/rubber_ball.cpp b/src/items/rubber_ball.cpp
index 35361ae29..592a7f86d 100644
--- a/src/items/rubber_ball.cpp
+++ b/src/items/rubber_ball.cpp
@@ -419,6 +419,8 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
// at it directly, stop interpolating, instead fly straight
// towards it.
Vec3 diff = m_target->getXYZ()-getXYZ();
+ if(diff.length()==0)
+ printf("diff=0\n");
*next_xyz = getXYZ() + (dt*m_speed/diff.length())*diff;
Vec3 old_vec = getXYZ()-m_previous_xyz;
diff --git a/src/karts/controller/controller.hpp b/src/karts/controller/controller.hpp
index a981176d2..869d22f16 100644
--- a/src/karts/controller/controller.hpp
+++ b/src/karts/controller/controller.hpp
@@ -37,7 +37,7 @@ class Item;
class KartControl;
class Material;
-/** This is the base class for kart controller - that can be a player
+/** This is the base class for kart controller - that can be a player
* or a a robot.
* \ingroup controller
*/
@@ -58,7 +58,7 @@ protected:
/** The name of the controller, mainly used for debugging purposes. */
std::string m_controller_name;
public:
- Controller (AbstractKart *kart,
+ Controller (AbstractKart *kart,
StateManager::ActivePlayer *player=NULL);
virtual ~Controller () {};
virtual void reset () = 0;
@@ -74,20 +74,20 @@ public:
virtual bool disableSlipstreamBonus() const = 0;
// ---------------------------------------------------------------------------
/** Sets the controller name for this controller. */
- virtual void setControllerName(const std::string &name)
+ virtual void setControllerName(const std::string &name)
{ m_controller_name = name; }
// ---------------------------------------------------------------------------
/** Returns the name of this controller. */
const std::string &getControllerName() const { return m_controller_name; }
// ---------------------------------------------------------------------------
- /** Returns the active player for this controller (NULL
+ /** Returns the active player for this controller (NULL
* if this controller does not belong to a player. */
StateManager::ActivePlayer *getPlayer () {return m_player;}
-
+
// ---------------------------------------------------------------------------
/** Returns the player object (or NULL if it's a computer controller). */
const StateManager::ActivePlayer *getPlayer () const { return m_player; }
-
+
// ------------------------------------------------------------------------
/** Default: ignore actions. Only PlayerController get them. */
virtual void action(PlayerAction action, int value) = 0;
@@ -101,6 +101,9 @@ public:
/** Called whan this controller's kart finishes the last lap. */
virtual void finishedRace(float time) = 0;
// ------------------------------------------------------------------------
+ /** Get a pointer on the kart controls. */
+ virtual KartControl* getControls() { return m_controls; }
+ // ------------------------------------------------------------------------
}; // Controller
#endif
diff --git a/src/karts/controller/end_controller.cpp b/src/karts/controller/end_controller.cpp
index ccea9e9eb..8b72439c2 100644
--- a/src/karts/controller/end_controller.cpp
+++ b/src/karts/controller/end_controller.cpp
@@ -43,7 +43,6 @@
#include "karts/max_speed.hpp"
#include "karts/rescue_animation.hpp"
#include "modes/linear_world.hpp"
-#include "network/network_manager.hpp"
#include "race/race_manager.hpp"
#include "states_screens/race_result_gui.hpp"
#include "tracks/quad_graph.hpp"
diff --git a/src/karts/controller/kart_control.hpp b/src/karts/controller/kart_control.hpp
index 78f789e7c..ed330d820 100644
--- a/src/karts/controller/kart_control.hpp
+++ b/src/karts/controller/kart_control.hpp
@@ -19,9 +19,8 @@
#ifndef HEADER_KART_CONTROL_HPP
#define HEADER_KART_CONTROL_HPP
-#include "network/message.hpp"
-/**
+/**
* \ingroup controller
*/
class KartControl
@@ -52,15 +51,6 @@ public:
reset();
}
// ------------------------------------------------------------------------
- /** Construct kart control from a Message (i.e. unserialise) */
- KartControl(Message *m)
- {
- m_steer = m->getFloat();
- m_accel = m->getFloat();
- char c = m->getChar();
- setButtonsCompressed(c);
- } // KartControl(Message*)
- // ------------------------------------------------------------------------
/** Resets all controls. */
void reset()
{
@@ -74,17 +64,6 @@ public:
m_look_back = false;
} // reset
// ------------------------------------------------------------------------
- /** Return the serialised size in bytes. */
- static int getLength() { return 9; }
- // ------------------------------------------------------------------------
- /** Serialises the kart control into a message. */
- void serialise(Message *m) const
- {
- m->addFloat(m_steer);
- m->addFloat(m_accel);
- m->addChar(getButtonsCompressed());
- } // compress
- // ------------------------------------------------------------------------
void uncompress(char *c)
{
m_steer = ((float*)c)[0];
diff --git a/src/karts/controller/network_player_controller.cpp b/src/karts/controller/network_player_controller.cpp
new file mode 100644
index 000000000..b408727ec
--- /dev/null
+++ b/src/karts/controller/network_player_controller.cpp
@@ -0,0 +1,368 @@
+#include "karts/controller/network_player_controller.hpp"
+
+#include "config/player.hpp"
+#include "graphics/irr_driver.hpp"
+#include "graphics/post_processing.hpp"
+#include "input/input_manager.hpp"
+#include "items/attachment.hpp"
+#include "items/item.hpp"
+#include "items/powerup.hpp"
+#include "karts/abstract_kart.hpp"
+#include "karts/kart_properties.hpp"
+#include "karts/skidding.hpp"
+#include "karts/rescue_animation.hpp"
+#include "modes/world.hpp"
+#include "race/history.hpp"
+#include "states_screens/race_gui_base.hpp"
+#include "utils/constants.hpp"
+#include "utils/log.hpp"
+#include "utils/translation.hpp"
+
+NetworkPlayerController::NetworkPlayerController(AbstractKart *kart,
+ StateManager::ActivePlayer *player)
+ : Controller(kart)
+{
+ assert(player != NULL);
+ m_player = player;
+ m_player->setKart(kart);
+ m_penalty_time = 0.0f;
+
+ reset();
+
+ Log::info("NetworkPlayerController", "New network player controller.");
+} // NetworkPlayerController
+
+//-----------------------------------------------------------------------------
+/** Destructor for a player kart.
+ */
+NetworkPlayerController::~NetworkPlayerController()
+{
+} // ~NetworkPlayerController
+
+//-----------------------------------------------------------------------------
+/** Resets the player kart for a new or restarted race.
+ */
+void NetworkPlayerController::reset()
+{
+ m_steer_val_l = 0;
+ m_steer_val_r = 0;
+ m_steer_val = 0;
+ m_prev_brake = 0;
+ m_prev_accel = 0;
+ m_prev_nitro = false;
+ m_penalty_time = 0;
+} // reset
+
+// ----------------------------------------------------------------------------
+/** Resets the state of control keys. This is used after the in-game menu to
+ * avoid that any keys pressed at the time the menu is opened are still
+ * considered to be pressed.
+ */
+void NetworkPlayerController::resetInputState()
+{
+ m_steer_val_l = 0;
+ m_steer_val_r = 0;
+ m_steer_val = 0;
+ m_prev_brake = 0;
+ m_prev_accel = 0;
+ m_prev_nitro = false;
+ m_controls->reset();
+} // resetInputState
+
+// ----------------------------------------------------------------------------
+/** This function interprets a kart action and value, and set the corresponding
+ * entries in the kart control data structure. This function handles esp.
+ * cases like 'press left, press right, release right' - in this case after
+ * releasing right, the steering must switch to left again. Similarly it
+ * handles 'press left, press right, release left' (in which case still
+ * right must be selected). Similarly for braking and acceleration.
+ * \param action The action to be executed.
+ * \param value If 32768, it indicates a digital value of 'fully set'
+ * if between 1 and 32767, it indicates an analog value,
+ * and if it's 0 it indicates that the corresponding button
+ * was released.
+ */
+void NetworkPlayerController::action(PlayerAction action, int value)
+{
+ switch (action)
+ {
+ case PA_STEER_LEFT:
+ m_steer_val_l = value;
+ if (value)
+ {
+ m_steer_val = value;
+ if(m_controls->m_skid==KartControl::SC_NO_DIRECTION)
+ m_controls->m_skid = KartControl::SC_LEFT;
+ }
+ else
+ m_steer_val = m_steer_val_r;
+
+ break;
+ case PA_STEER_RIGHT:
+ m_steer_val_r = -value;
+ if (value)
+ {
+ m_steer_val = -value;
+ if(m_controls->m_skid==KartControl::SC_NO_DIRECTION)
+ m_controls->m_skid = KartControl::SC_RIGHT;
+ }
+ else
+ m_steer_val = m_steer_val_l;
+
+ break;
+ case PA_ACCEL:
+ m_prev_accel = value;
+ if (value && !(m_penalty_time > 0.0f))
+ {
+ m_controls->m_accel = value/32768.0f;
+ m_controls->m_brake = false;
+ m_controls->m_nitro = m_prev_nitro;
+ }
+ else
+ {
+ m_controls->m_accel = 0.0f;
+ m_controls->m_brake = m_prev_brake;
+ m_controls->m_nitro = false;
+ }
+ break;
+ case PA_BRAKE:
+ m_prev_brake = value!=0;
+ // let's consider below that to be a deadzone
+ if(value > 32768/2)
+ {
+ m_controls->m_brake = true;
+ m_controls->m_accel = 0.0f;
+ m_controls->m_nitro = false;
+ }
+ else
+ {
+ m_controls->m_brake = false;
+ m_controls->m_accel = m_prev_accel/32768.0f;
+ // Nitro still depends on whether we're accelerating
+ m_controls->m_nitro = (m_prev_nitro && m_prev_accel);
+ }
+ break;
+ case PA_NITRO:
+ // This basically keeps track whether the button still is being pressed
+ m_prev_nitro = (value != 0);
+ // Enable nitro only when also accelerating
+ m_controls->m_nitro = ((value!=0) && m_controls->m_accel);
+ break;
+ case PA_RESCUE:
+ m_controls->m_rescue = (value!=0);
+ break;
+ case PA_FIRE:
+ {
+ m_controls->m_fire = (value!=0);
+ break;
+ }
+ case PA_LOOK_BACK:
+ m_controls->m_look_back = (value!=0);
+ break;
+ case PA_DRIFT:
+ if(value==0)
+ m_controls->m_skid = KartControl::SC_NONE;
+ else
+ if(m_steer_val==0)
+ m_controls->m_skid = KartControl::SC_NO_DIRECTION;
+ else
+ m_controls->m_skid = m_steer_val<0
+ ? KartControl::SC_RIGHT
+ : KartControl::SC_LEFT;
+ break;
+ case PA_PAUSE_RACE:
+ if (value != 0) StateManager::get()->escapePressed();
+ break;
+ default:
+ break;
+ }
+
+} // action
+
+//-----------------------------------------------------------------------------
+/** Handles steering for a player kart.
+ */
+void NetworkPlayerController::steer(float dt, int steer_val)
+{
+ if(stk_config->m_disable_steer_while_unskid &&
+ m_controls->m_skid==KartControl::SC_NONE &&
+ m_kart->getSkidding()->getVisualSkidRotation()!=0)
+ {
+ m_controls->m_steer = 0;
+ }
+
+
+ // Amount the steering is changed for digital devices.
+ // If the steering is 'back to straight', a different steering
+ // change speed is used.
+ const float STEER_CHANGE = ( (steer_val<=0 && m_controls->m_steer<0) ||
+ (steer_val>=0 && m_controls->m_steer>0) )
+ ? dt/m_kart->getKartProperties()->getTimeResetSteer()
+ : dt/m_kart->getTimeFullSteer(fabsf(m_controls->m_steer));
+ if (steer_val < 0)
+ {
+ // If we got analog values do not cumulate.
+ if (steer_val > -32767)
+ m_controls->m_steer = -steer_val/32767.0f;
+ else
+ m_controls->m_steer += STEER_CHANGE;
+ }
+ else if(steer_val > 0)
+ {
+ // If we got analog values do not cumulate.
+ if (steer_val < 32767)
+ m_controls->m_steer = -steer_val/32767.0f;
+ else
+ m_controls->m_steer -= STEER_CHANGE;
+ }
+ else
+ { // no key is pressed
+ if(m_controls->m_steer>0.0f)
+ {
+ m_controls->m_steer -= STEER_CHANGE;
+ if(m_controls->m_steer<0.0f) m_controls->m_steer=0.0f;
+ }
+ else
+ { // m_controls->m_steer<=0.0f;
+ m_controls->m_steer += STEER_CHANGE;
+ if(m_controls->m_steer>0.0f) m_controls->m_steer=0.0f;
+ } // if m_controls->m_steer<=0.0f
+ } // no key is pressed
+ if(UserConfigParams::m_gamepad_debug)
+ {
+ Log::debug("PlayerController", " set to: %f\n", m_controls->m_steer);
+ }
+
+ m_controls->m_steer = std::min(1.0f, std::max(-1.0f, m_controls->m_steer));
+
+} // steer
+
+//-----------------------------------------------------------------------------
+/** Callback when the skidding bonus is triggered. The player controller
+ * resets the current steering to 0, which makes the kart easier to control.
+ */
+void NetworkPlayerController::skidBonusTriggered()
+{
+ m_controls->m_steer = 0;
+} // skidBonusTriggered
+
+//-----------------------------------------------------------------------------
+/** Updates the player kart, called once each timestep.
+ */
+void NetworkPlayerController::update(float dt)
+{
+ if (UserConfigParams::m_gamepad_debug)
+ {
+ // Print a dividing line so that it's easier to see which events
+ // get received in which order in the one frame.
+ Log::debug("PlayerController", "irr_driver", "-------------------------------------\n");
+ }
+
+ // Don't do steering if it's replay. In position only replay it doesn't
+ // matter, but if it's physics replay the gradual steering causes
+ // incorrect results, since the stored values are already adjusted.
+ if (!history->replayHistory())
+ steer(dt, m_steer_val);
+
+ if (World::getWorld()->isStartPhase())
+ {
+ if (m_controls->m_accel || m_controls->m_brake ||
+ m_controls->m_fire || m_controls->m_nitro)
+ {
+ // Only give penalty time in SET_PHASE.
+ // Penalty time check makes sure it doesn't get rendered on every
+ // update.
+ if (m_penalty_time == 0.0 &&
+ World::getWorld()->getPhase() == WorldStatus::SET_PHASE)
+ {
+ RaceGUIBase* m=World::getWorld()->getRaceGUI();
+ if (m)
+ {
+ m->addMessage(_("Penalty time!!"), m_kart, 2.0f,
+ video::SColor(255, 255, 128, 0));
+ m->addMessage(_("Don't accelerate before go"), m_kart, 2.0f,
+ video::SColor(255, 210, 100, 50));
+ }
+
+ m_penalty_time = stk_config->m_penalty_time;
+ } // if penalty_time = 0
+
+ m_controls->m_brake = false;
+ m_controls->m_accel = 0.0f;
+ } // if key pressed
+
+ return;
+ } // if isStartPhase
+
+ if (m_penalty_time>0.0)
+ {
+ m_penalty_time-=dt;
+ return;
+ }
+
+ // We can't restrict rescue to fulfil isOnGround() (which would be more like
+ // MK), since e.g. in the City track it is possible for the kart to end
+ // up sitting on a brick wall, with all wheels in the air :((
+ // Only accept rescue if there is no kart animation is already playing
+ // (e.g. if an explosion happens, wait till the explosion is over before
+ // starting any other animation).
+ if ( m_controls->m_rescue && !m_kart->getKartAnimation() )
+ {
+ new RescueAnimation(m_kart);
+ m_controls->m_rescue=false;
+ }
+} // update
+
+//-----------------------------------------------------------------------------
+/** Checks if the kart was overtaken, and if so plays a sound
+*/
+void NetworkPlayerController::setPosition(int p)
+{
+ if(m_kart->getPosition()getNumKarts(); i++ )
+ {
+ AbstractKart *kart = world->getKart(i);
+ if(kart->getPosition() == p + 1)
+ {
+ kart->beep();
+ break;
+ }
+ }
+ }
+} // setPosition
+
+//-----------------------------------------------------------------------------
+/** Called when a kart finishes race.
+ * /param time Finishing time for this kart.
+ d*/
+void NetworkPlayerController::finishedRace(float time)
+{
+
+} // finishedRace
+
+//-----------------------------------------------------------------------------
+/** Called when a kart hits or uses a zipper.
+ */
+void NetworkPlayerController::handleZipper(bool play_sound)
+{
+ m_kart->showZipperFire();
+} // handleZipper
+
+//-----------------------------------------------------------------------------
+/** Called when a kart hits an item.
+ * \param item Item that was collected.
+ * \param add_info Additional info to be used then handling the item. If
+ * this is -1 (default), the item type is selected
+ * randomly. Otherwise it contains the powerup or
+ * attachment for the kart. This is used in network mode to
+ * let the server determine the powerup/attachment for
+ * the clients.
+ */
+void NetworkPlayerController::collectedItem(const Item &item, int add_info, float old_energy)
+{
+
+} // collectedItem
diff --git a/src/karts/controller/network_player_controller.hpp b/src/karts/controller/network_player_controller.hpp
new file mode 100644
index 000000000..fba1f70ef
--- /dev/null
+++ b/src/karts/controller/network_player_controller.hpp
@@ -0,0 +1,48 @@
+#ifndef NETWORK_PLAYER_CONTROLLER_HPP
+#define NETWORK_PLAYER_CONTROLLER_HPP
+
+#include "karts/controller/controller.hpp"
+
+class AbstractKart;
+class Player;
+
+class NetworkPlayerController : public Controller
+{
+protected:
+ int m_steer_val, m_steer_val_l, m_steer_val_r;
+ int m_prev_accel;
+ bool m_prev_brake;
+ bool m_prev_nitro;
+
+ float m_penalty_time;
+
+ void steer(float, int);
+public:
+ NetworkPlayerController (AbstractKart *kart,
+ StateManager::ActivePlayer *_player);
+ virtual ~NetworkPlayerController ();
+ void update (float);
+ void action (PlayerAction action, int value);
+ void handleZipper (bool play_sound);
+ void collectedItem (const Item &item, int add_info=-1,
+ float previous_energy=0);
+ virtual void skidBonusTriggered();
+ virtual void setPosition (int p);
+ virtual bool isPlayerController() const { return false; }
+ virtual bool isNetworkController() const { return true; }
+ virtual void reset ();
+ void resetInputState ();
+ virtual void finishedRace (float time);
+ virtual void crashed (const AbstractKart *k) {}
+ virtual void crashed (const Material *m) {}
+ // ------------------------------------------------------------------------
+ /** Callback whenever a new lap is triggered. Used by the AI
+ * to trigger a recomputation of the way to use, not used for players. */
+ virtual void newLap(int lap) {}
+ // ------------------------------------------------------------------------
+ /** Player will always be able to get a slipstream bonus. */
+ virtual bool disableSlipstreamBonus() const { return false; }
+
+};
+
+#endif // NETWORK_PLAYER_CONTROLLER_HPP
diff --git a/src/karts/controller/player_controller.cpp b/src/karts/controller/player_controller.cpp
index f58b72902..258556b08 100644
--- a/src/karts/controller/player_controller.cpp
+++ b/src/karts/controller/player_controller.cpp
@@ -35,6 +35,7 @@
#include "karts/skidding.hpp"
#include "karts/rescue_animation.hpp"
#include "modes/world.hpp"
+#include "network/network_world.hpp"
#include "race/history.hpp"
#include "states_screens/race_gui_base.hpp"
#include "utils/constants.hpp"
@@ -218,6 +219,10 @@ void PlayerController::action(PlayerAction action, int value)
default:
break;
}
+ if (NetworkWorld::getInstance()->isRunning())
+ {
+ NetworkWorld::getInstance()->controllerAction(this, action, value);
+ }
} // action
diff --git a/src/karts/controller/skidding_ai.cpp b/src/karts/controller/skidding_ai.cpp
index ef3158c93..b75800b79 100644
--- a/src/karts/controller/skidding_ai.cpp
+++ b/src/karts/controller/skidding_ai.cpp
@@ -54,7 +54,6 @@
#include "items/powerup.hpp"
#include "modes/linear_world.hpp"
#include "modes/profile_world.hpp"
-#include "network/network_manager.hpp"
#include "race/race_manager.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
@@ -297,13 +296,6 @@ void SkiddingAI::update(float dt)
return;
#endif
- // The client does not do any AI computations.
- if(network_manager->getMode()==NetworkManager::NW_CLIENT)
- {
- AIBaseController::update(dt);
- return;
- }
-
// If the kart needs to be rescued, do it now (and nothing else)
if(isStuck() && !m_kart->getKartAnimation())
{
diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp
index aa2c9b0dd..62d3f0e69 100644
--- a/src/karts/kart.cpp
+++ b/src/karts/kart.cpp
@@ -57,8 +57,6 @@
#include "karts/max_speed.hpp"
#include "karts/skidding.hpp"
#include "modes/linear_world.hpp"
-#include "network/race_state.hpp"
-#include "network/network_manager.hpp"
#include "physics/btKart.hpp"
#include "physics/btKartRaycast.hpp"
#include "physics/btUprightConstraint.hpp"
@@ -878,15 +876,6 @@ void Kart::collectedItem(Item *item, int add_info)
default : break;
} // switch TYPE
- // Attachments and powerups are stored in the corresponding
- // functions (hit{Red,Green}Item), so only coins need to be
- // stored here.
- if(network_manager->getMode()==NetworkManager::NW_SERVER &&
- (type==Item::ITEM_NITRO_BIG || type==Item::ITEM_NITRO_SMALL) )
- {
- race_state->itemCollected(getWorldKartId(), item->getItemId());
- }
-
if ( m_collected_energy > m_kart_properties->getNitroMax())
m_collected_energy = m_kart_properties->getNitroMax();
m_controller->collectedItem(*item, add_info, old_energy);
@@ -1018,14 +1007,6 @@ void Kart::update(float dt)
m_slipstream->update(dt);
- // Store the actual kart controls at the start of update in the server
- // state. This makes it easier to reset some fields when they are not used
- // anymore (e.g. controls.fire).
- if(network_manager->getMode()==NetworkManager::NW_SERVER)
- {
- race_state->storeKartControls(*this);
- }
-
if (!m_flying)
{
// When really on air, free fly, when near ground, try to glide / adjust for landing
@@ -1884,10 +1865,8 @@ void Kart::updatePhysics(float dt)
updateSliding();
- // Only compute the current speed if this is not the client. On a client the
- // speed is actually received from the server.
- if(network_manager->getMode()!=NetworkManager::NW_CLIENT)
- m_speed = getVehicle()->getRigidBody()->getLinearVelocity().length();
+ // Compute the speed of the kart.
+ m_speed = getVehicle()->getRigidBody()->getLinearVelocity().length();
// calculate direction of m_speed
const btTransform& chassisTrans = getVehicle()->getChassisWorldTransform();
diff --git a/src/karts/moveable.hpp b/src/karts/moveable.hpp
index 4461620ee..d6bafea84 100644
--- a/src/karts/moveable.hpp
+++ b/src/karts/moveable.hpp
@@ -31,13 +31,14 @@ using namespace irr;
#include "physics/user_pointer.hpp"
#include "utils/no_copy.hpp"
#include "utils/vec3.hpp"
+#include "network/types.hpp"
class Material;
/**
* \ingroup karts
*/
-class Moveable: public NoCopy
+class Moveable: public NoCopy, public CallbackObject
{
private:
btVector3 m_velocityLC; /**setMode(NetworkManager::NW_SERVER);
UserConfigParams::m_server_port = n;
}
else if( !strcmp(argv[i], "--server") )
{
- network_manager->setMode(NetworkManager::NW_SERVER);
+ NetworkManager::getInstance();
+ Log::info("main", "Creating a server network manager.");
}
- else if( sscanf(argv[i], "--port=%d", &n) )
+ else if( sscanf(argv[i], "--max-players=%d", &n) )
{
- UserConfigParams::m_server_port=n;
+ UserConfigParams::m_server_max_players=n;
}
- else if( sscanf(argv[i], "--client=%1023s", s) )
+ else if( sscanf(argv[i], "--login=%1023s", s) )
{
- network_manager->setMode(NetworkManager::NW_CLIENT);
- UserConfigParams::m_server_address=s;
+ login = s;
+ try_login = true;
+ }
+ else if( sscanf(argv[i], "--password=%1023s", s) )
+ {
+ password = s;
}
else if ( sscanf(argv[i], "--gfx=%d", &n) )
{
@@ -981,6 +993,9 @@ int handleCmdLine(int argc, char **argv)
race_manager->setNumLaps(999999); // profile end depends on time
}
else if( !strcmp(argv[i], "--no-graphics") )
+ {
+ }
+ else if( !strcmp(argv[i], "--with-profile") )
{
// Set default profile mode of 1 lap if we haven't already set one
if (!ProfileWorld::isProfileMode()) {
@@ -1092,6 +1107,19 @@ int handleCmdLine(int argc, char **argv)
UserConfigParams::m_music = false;// and music when profiling
}
+ if (try_login)
+ {
+ irr::core::stringw s;
+ Online::CurrentUser::SignInRequest* request =
+ Online::CurrentUser::get()->requestSignIn(login, password, false, false);
+ Online::HTTPManager::get()->synchronousRequest(request);
+
+ if (request->isSuccess())
+ {
+ Log::info("Main", "Logged in from command line.");
+ }
+ }
+
return 1;
} // handleCmdLine
@@ -1173,7 +1201,6 @@ void initRest()
powerup_manager = new PowerupManager ();
attachment_manager = new AttachmentManager ();
highscore_manager = new HighscoreManager ();
- network_manager = new NetworkManager ();
KartPropertiesManager::addKartSearchDir(
file_manager->getAddonsFile("karts/"));
track_manager->addTrackSearchDir(
@@ -1215,6 +1242,7 @@ void cleanSuperTuxKart()
if(Online::HTTPManager::isRunning())
Online::HTTPManager::get()->stopNetworkThread();
//delete in reverse order of what they were created in.
+ //delete in reverse order of what they were created in.
//see InitTuxkart()
Referee::cleanup();
if(ReplayPlay::get()) ReplayPlay::destroy();
@@ -1222,7 +1250,8 @@ void cleanSuperTuxKart()
INetworkHttp::destroy();
if(news_manager) delete news_manager;
if(addons_manager) delete addons_manager;
- if(network_manager) delete network_manager;
+ NetworkManager::kill();
+
if(grand_prix_manager) delete grand_prix_manager;
if(highscore_manager) delete highscore_manager;
if(attachment_manager) delete attachment_manager;
@@ -1365,6 +1394,15 @@ int main(int argc, char *argv[] )
//handleCmdLine() needs InitTuxkart() so it can't be called first
if(!handleCmdLine(argc, argv)) exit(0);
+ // load the network manager
+ // If the server has been created (--server option), this will do nothing (just a warning):
+ NetworkManager::getInstance();
+ NetworkManager::getInstance()->run();
+ if (NetworkManager::getInstance()->isServer())
+ {
+ ProtocolManager::getInstance()->requestStart(new ServerLobbyRoomProtocol());
+ }
+
addons_manager->checkInstalledAddons();
// Load addons.xml to get info about addons even when not
@@ -1377,6 +1415,20 @@ int main(int argc, char *argv[] )
}
}
+ // no graphics, and no profile mode
+ if (ProfileWorld::isNoGraphics() && !ProfileWorld::isProfileMode())
+ {
+ // hack to have a running game slot :
+ PtrVector& players = UserConfigParams::m_all_players;
+ if (UserConfigParams::m_default_player.toString().size() > 0)
+ for (int n=0; nsetCurrentSlot(players[n].getUniqueID());
+
+ main_loop->run();
+ throw "salut";
+ }
+
if(!UserConfigParams::m_no_start_screen)
{
StateManager::get()->pushScreen(StoryModeLobbyScreen::getInstance());
@@ -1439,7 +1491,7 @@ int main(int argc, char *argv[] )
// Create player and associate player with keyboard
StateManager::get()->createActivePlayer(
- UserConfigParams::m_all_players.get(0), device );
+ UserConfigParams::m_all_players.get(0), device, NULL);
if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL)
{
@@ -1480,7 +1532,7 @@ int main(int argc, char *argv[] )
{
// This will setup the race manager etc.
history->Load();
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startNew(false);
main_loop->run();
// well, actually run() will never return, since
@@ -1489,20 +1541,6 @@ int main(int argc, char *argv[] )
exit(-3);
}
- // Initialise connection in case that a command line option was set
- // configuring a client or server. Otherwise this function does nothing
- // here (and will be called again from the network gui).
- if(!network_manager->initialiseConnections())
- {
- Log::error("main", "Problems initialising network connections,\n"
- "Running in non-network mode.");
- }
- // On the server start with the network information page for now
- if(network_manager->getMode()==NetworkManager::NW_SERVER)
- {
- // TODO - network menu
- //menu_manager->pushMenu(MENUID_NETWORK_GUI);
- }
// Not replaying
// =============
if(!ProfileWorld::isProfileMode())
@@ -1512,7 +1550,7 @@ int main(int argc, char *argv[] )
// Quickstart (-N)
// ===============
// all defaults are set in InitTuxkart()
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startNew(false);
}
}
@@ -1522,7 +1560,7 @@ int main(int argc, char *argv[] )
// =========
race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startNew(false);
}
main_loop->run();
diff --git a/src/main_loop.cpp b/src/main_loop.cpp
index 8524dbed0..c8ec85ee9 100644
--- a/src/main_loop.cpp
+++ b/src/main_loop.cpp
@@ -29,7 +29,8 @@
#include "input/wiimote_manager.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
-#include "network/network_manager.hpp"
+#include "network/protocol_manager.hpp"
+#include "network/network_world.hpp"
#include "race/race_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/profiler.hpp"
@@ -73,9 +74,9 @@ float MainLoop::getLimitedDt()
// Throttle fps if more than maximum, which can reduce
// the noise the fan on a graphics card makes.
// When in menus, reduce FPS much, it's not necessary to push to the maximum for plain menus
- const int max_fps = (StateManager::get()->throttleFPS() ? 35 : UserConfigParams::m_max_fps);
+ const int max_fps = 35;//(StateManager::get()->throttleFPS() ? 35 : UserConfigParams::m_max_fps);
const int current_fps = (int)(1000.0f/dt);
- if( current_fps > max_fps && !ProfileWorld::isNoGraphics())
+ if( current_fps > max_fps && !ProfileWorld::isProfileMode())
{
int wait_time = 1000/max_fps - 1000/current_fps;
if(wait_time < 1) wait_time = 1;
@@ -94,22 +95,12 @@ float MainLoop::getLimitedDt()
*/
void MainLoop::updateRace(float dt)
{
- // Server: Send the current position and previous controls to all clients
- // Client: send current controls to server
- // But don't do this if the race is in finish phase (otherwise
- // messages can be mixed up in the race manager)
- if(!World::getWorld()->isFinishPhase())
- network_manager->sendUpdates();
if(ProfileWorld::isProfileMode()) dt=1.0f/60.0f;
- // Again, only receive updates if the race isn't over - once the
- // race results are displayed (i.e. game is in finish phase)
- // messages must be handled by the normal update of the network
- // manager
- if(!World::getWorld()->isFinishPhase())
- network_manager->receiveUpdates();
-
- World::getWorld()->updateWorld(dt);
+ if (NetworkWorld::getInstance()->isRunning())
+ NetworkWorld::getInstance()->update(dt);
+ else
+ World::getWorld()->updateWorld(dt);
} // updateRace
//-----------------------------------------------------------------------------
@@ -127,13 +118,8 @@ void MainLoop::run()
m_prev_time = m_curr_time;
float dt = getLimitedDt();
- network_manager->update(dt);
-
if (World::getWorld()) // race is active if world exists
{
- // 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;
updateRace(dt);
} // if race is active
@@ -162,7 +148,20 @@ void MainLoop::run()
PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F);
irr_driver->update(dt);
PROFILER_POP_CPU_MARKER();
+
+ PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
+ ProtocolManager::getInstance()->update();
+ PROFILER_POP_CPU_MARKER();
+
+ PROFILER_SYNC_FRAME();
}
+ else if (!m_abort && ProfileWorld::isNoGraphics())
+ {
+ PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
+ ProtocolManager::getInstance()->update();
+ PROFILER_POP_CPU_MARKER();
+ }
+
PROFILER_SYNC_FRAME();
PROFILER_POP_CPU_MARKER();
} // while !m_exit
diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp
index ab56220d9..2646d3ea1 100644
--- a/src/modes/cutscene_world.cpp
+++ b/src/modes/cutscene_world.cpp
@@ -35,7 +35,7 @@
#include "physics/physics.hpp"
#include "states_screens/credits.hpp"
#include "states_screens/cutscene_gui.hpp"
-#include "states_screens/kart_selection.hpp"
+#include "states_screens/offline_kart_selection.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "tracks/track.hpp"
#include "tracks/track_object.hpp"
@@ -384,7 +384,7 @@ void CutsceneWorld::enterRaceOverState()
slot->setFirstTime(false);
unlock_manager->save();
- KartSelectionScreen* s = KartSelectionScreen::getInstance();
+ KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
s->setMultiplayer(false);
s->setGoToOverworldNext();
StateManager::get()->pushScreen( s );
diff --git a/src/modes/demo_world.cpp b/src/modes/demo_world.cpp
index 681382e7e..35a91def1 100644
--- a/src/modes/demo_world.cpp
+++ b/src/modes/demo_world.cpp
@@ -21,7 +21,6 @@
#include "guiengine/modaldialog.hpp"
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
-#include "network/network_manager.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@@ -141,7 +140,7 @@ bool DemoWorld::updateIdleTimeAndStartDemo(float dt)
// Use keyboard 0 by default in --no-start-screen
device = input_manager->getDeviceList()->getKeyboard(0);
StateManager::get()->createActivePlayer(
- UserConfigParams::m_all_players.get(0), device );
+ UserConfigParams::m_all_players.get(0), device , NULL);
// ASSIGN should make sure that only input from assigned devices
// is read.
input_manager->getDeviceList()->setAssignMode(ASSIGN);
@@ -149,7 +148,7 @@ bool DemoWorld::updateIdleTimeAndStartDemo(float dt)
m_do_demo = true;
race_manager->setNumKarts(m_num_karts);
race_manager->setLocalKartInfo(0, "tux");
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startSingleRace(m_demo_tracks[0], m_num_laps, false);
m_demo_tracks.push_back(m_demo_tracks[0]);
m_demo_tracks.erase(m_demo_tracks.begin());
diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp
index c519703c1..81cadfa95 100644
--- a/src/modes/linear_world.cpp
+++ b/src/modes/linear_world.cpp
@@ -25,7 +25,6 @@
#include "karts/abstract_kart.hpp"
#include "karts/controller/controller.hpp"
#include "karts/kart_properties.hpp"
-#include "network/network_manager.hpp"
#include "physics/physics.hpp"
#include "race/history.hpp"
#include "states_screens/race_gui_base.hpp"
@@ -319,13 +318,7 @@ void LinearWorld::newLap(unsigned int kart_index)
// Race finished
if(kart_info.m_race_lap >= race_manager->getNumLaps() && raceHasLaps())
{
- // A client does not detect race finished by itself, it will
- // receive a message from the server. So a client does not do
- // anything here.
- if(network_manager->getMode()!=NetworkManager::NW_CLIENT)
- {
- kart->finishedRace(getTime());
- }
+ kart->finishedRace(getTime());
}
float time_per_lap;
if (kart_info.m_race_lap == 1) // just completed first lap
diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp
index 65cdf8f10..f6d420c57 100644
--- a/src/modes/overworld.cpp
+++ b/src/modes/overworld.cpp
@@ -27,9 +27,8 @@
#include "karts/rescue_animation.hpp"
#include "modes/overworld.hpp"
#include "physics/physics.hpp"
-#include "network/network_manager.hpp"
#include "states_screens/dialogs/select_challenge.hpp"
-#include "states_screens/kart_selection.hpp"
+#include "states_screens/offline_kart_selection.hpp"
#include "states_screens/race_gui_overworld.hpp"
#include "tracks/track.hpp"
@@ -64,7 +63,7 @@ void OverWorld::enterOverWorld()
// Create player and associate player with keyboard
StateManager::get()->createActivePlayer(unlock_manager->getCurrentPlayer(),
- device);
+ device, NULL);
if (!kart_properties_manager->getKart(UserConfigParams::m_default_kart))
{
@@ -83,7 +82,7 @@ void OverWorld::enterOverWorld()
->setSinglePlayer( StateManager::get()->getActivePlayer(0) );
StateManager::get()->enterGameState();
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startNew(false);
if(race_manager->haveKartLastPositionOnOverworld()){
OverWorld *ow = (OverWorld*)World::getWorld();
@@ -129,7 +128,7 @@ void OverWorld::update(float dt)
m_return_to_garage = false;
delayedSelfDestruct();
race_manager->exitRace(false);
- KartSelectionScreen* s = KartSelectionScreen::getInstance();
+ KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
s->setMultiplayer(false);
s->setFromOverworld(true);
StateManager::get()->resetAndGoToScreen(s);
diff --git a/src/modes/world.cpp b/src/modes/world.cpp
index 92e76e05f..69862551b 100644
--- a/src/modes/world.cpp
+++ b/src/modes/world.cpp
@@ -38,12 +38,11 @@
#include "karts/controller/player_controller.hpp"
#include "karts/controller/end_controller.hpp"
#include "karts/controller/skidding_ai.hpp"
+#include "karts/controller/network_player_controller.hpp"
#include "karts/kart.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/overworld.hpp"
#include "modes/profile_world.hpp"
-#include "network/network_manager.hpp"
-#include "network/race_state.hpp"
#include "physics/btKart.hpp"
#include "physics/physics.hpp"
#include "physics/triangle_mesh.hpp"
@@ -79,8 +78,8 @@ World* World::m_world = NULL;
* of all karts is set (i.e. in a normal race the arrival time for karts
* will be estimated), highscore is updated, and the race result gui
* is being displayed.
- * Rescuing is handled via the three functions:
- * getNumberOfRescuePositions() - which returns the number of rescue
+ * Rescuing is handled via the three functions:
+ * getNumberOfRescuePositions() - which returns the number of rescue
* positions defined.
* getRescuePositionIndex(AbstractKart *kart) - which determines the
* index of the rescue position to be used for the given kart.
@@ -133,7 +132,6 @@ World::World() : WorldStatus(), m_clear_color(255,100,101,140)
*/
void World::init()
{
- race_state = new RaceState();
m_faster_music_active = false;
m_fastest_kart = 0;
m_eliminated_karts = 0;
@@ -189,8 +187,6 @@ void World::init()
if(ReplayPlay::get())
ReplayPlay::get()->Load();
- network_manager->worldLoaded();
-
powerup_manager->updateWeightsForRace(num_karts);
} // init
@@ -300,11 +296,10 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
m_num_players ++;
break;
case RaceManager::KT_NETWORK_PLAYER:
- break; // Avoid compiler warning about enum not handled.
- //controller = new NetworkController(kart_ident, position, init_pos,
- // global_player_id);
- //m_num_players++;
- //break;
+ controller = new NetworkPlayerController(new_kart,
+ StateManager::get()->getActivePlayer(local_player_id));
+ m_num_players++;
+ break;
case RaceManager::KT_AI:
controller = loadAIController(new_kart);
break;
@@ -375,7 +370,6 @@ World::~World()
// gui and this must be deleted.
delete m_race_gui;
}
- delete race_state;
for ( unsigned int i = 0 ; i < m_karts.size() ; i++ )
delete m_karts[i];
@@ -491,7 +485,7 @@ void World::resetAllKarts()
// Loop over all karts, in case that some karts are dfferent
for(unsigned int kart_id=0; kart_idgetBody()->setCenterOfMassTransform(pos);
// Project kart to surface of track
- // This will set the physics transform
+ // This will set the physics transform
m_track->findGround(kart);
} // moveKartTo
@@ -748,13 +742,12 @@ void World::updateWorld(float dt)
InputDevice* device = input_manager->getDeviceList()->getKeyboard(0);
// Create player and associate player with keyboard
- StateManager::get()
- ->createActivePlayer(unlock_manager->getCurrentPlayer(),
- device);
+ StateManager::get()->createActivePlayer(unlock_manager->getCurrentPlayer(),
+ device, NULL);
if (!kart_properties_manager->getKart(UserConfigParams::m_default_kart))
{
- Log::warn("World",
+ Log::warn("World",
"Cannot find kart '%s', will revert to default.",
UserConfigParams::m_default_kart.c_str());
UserConfigParams::m_default_kart.revertToDefaults();
@@ -768,7 +761,7 @@ void World::updateWorld(float dt)
->setSinglePlayer( StateManager::get()->getActivePlayer(0) );
StateManager::get()->enterGameState();
- network_manager->setupPlayerKartInfo();
+ race_manager->setupPlayerKartInfo();
race_manager->startNew(true);
}
else
@@ -821,11 +814,8 @@ void World::update(float dt)
if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
if(history->replayHistory()) dt=history->getNextDelta();
WorldStatus::update(dt);
- // Clear race state so that new information can be stored
- race_state->clear();
- if(network_manager->getMode()!=NetworkManager::NW_CLIENT &&
- !history->dontDoPhysics())
+ if (!history->dontDoPhysics())
{
m_physics->update(dt);
}
@@ -988,7 +978,8 @@ AbstractKart *World::getPlayerKart(unsigned int n) const
unsigned int count=-1;
for(unsigned int i=0; igetController()->isPlayerController())
+ if(m_karts[i]->getController()->isPlayerController() ||
+ m_karts[i]->getController()->isNetworkController())
{
count++;
if(count==n) return m_karts[i];
diff --git a/src/modes/world.hpp b/src/modes/world.hpp
index c981c960c..d6aaffd95 100644
--- a/src/modes/world.hpp
+++ b/src/modes/world.hpp
@@ -282,6 +282,9 @@ public:
assert(kartId >= 0 && kartId < int(m_karts.size()));
return m_karts[kartId]; }
// ------------------------------------------------------------------------
+ /** Returns all karts. */
+ KartList getKarts() const { return m_karts; }
+ // ------------------------------------------------------------------------
/** Returns the number of currently active (i.e.non-elikminated) karts. */
unsigned int getCurrentNumKarts() const { return (int)m_karts.size() -
m_eliminated_karts; }
diff --git a/src/modes/world_status.cpp b/src/modes/world_status.cpp
index 522d0e01e..294009f1e 100644
--- a/src/modes/world_status.cpp
+++ b/src/modes/world_status.cpp
@@ -26,7 +26,6 @@
#include "karts/abstract_kart.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
-#include "network/network_manager.hpp"
#include
@@ -112,8 +111,6 @@ void WorldStatus::enterRaceOverState()
*/
void WorldStatus::terminateRace()
{
- if(network_manager->getMode()==NetworkManager::NW_SERVER)
- network_manager->sendRaceResults();
} // terminateRace
//-----------------------------------------------------------------------------
diff --git a/src/network/character_confirm_message.hpp b/src/network/character_confirm_message.hpp
deleted file mode 100644
index 527794928..000000000
--- a/src/network/character_confirm_message.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// 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_CHARACTER_CONFIRM_MESSAGE_HPP
-#define HEADER_CHARACTER_CONFIRM_MESSAGE_HPP
-
-#include
-
-#include "network/message.hpp"
-
-
-/** This message is from the server to all clients to inform them about a
- * newly selected character. This means that this character is not available
- * anymore. The message contains the hostid of the client who selected this
- * character (0 in case of server), so that this message acts as a
- * confirmation for the corresponding client (or a reject if the message has
- * a different hostid, meaning that another client selected the character
- * earlier).
- */
-class CharacterConfirmMessage : public Message
-{
-private:
- /** The host id. */
- int m_host_id;
- /** Name of the selected kart. */
- std::string m_kart_name;
-public:
- /** Constructor, takes the name of the kart name and the host id.
- * \param kart_name Name of the kart.
- * \param host_id Id of the host who selected this character.
- */
- CharacterConfirmMessage(const std::string &kart_name, int host_id)
- : Message(Message::MT_CHARACTER_CONFIRM)
- {
- allocate(getStringLength(kart_name) + getCharLength());
- addString(kart_name);
- addChar(host_id);
- } // CharacterConfirmMessage
-
- // ------------------------------------------------------------------------
- /** Unpacks a character confirm message.
- * \param pkt Received enet packet.
- */
- CharacterConfirmMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_CONFIRM)
- {
- m_kart_name = getString();
- m_host_id = getChar();
- } // CharacterConfirmMessage(EnetPacket)
- // ------------------------------------------------------------------------
- /** Returns the kart name contained in a received message. */
- const std::string &getKartName() const { return m_kart_name; }
- /** Returns the host id contained in a received message. */
- int getHostId() const { return m_host_id; }
-
-}; // CharacterConfirmMessage
-#endif
diff --git a/src/network/character_info_message.hpp b/src/network/character_info_message.hpp
deleted file mode 100644
index 443a2d670..000000000
--- a/src/network/character_info_message.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// 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_CHARACTER_INFO_MESSAGE_HPP
-#define HEADER_CHARACTER_INFO_MESSAGE_HPP
-
-#include "karts/kart_properties_manager.hpp"
-#include "network/message.hpp"
-
-/** This message is sent from the server to the clients and contains the list
- * of available characters. Additionally, it contains the clients id.
- */
-class CharacterInfoMessage : public Message
-{
-// Add the remote host id to this message (to avoid sending this separately)
-public:
- CharacterInfoMessage(int hostid) : Message(Message::MT_CHARACTER_INFO)
- {
- std::vector all_karts =
- kart_properties_manager->getAllAvailableKarts();
- allocate(getCharLength()+getStringVectorLength(all_karts));
- addChar(hostid);
- addStringVector(all_karts);
- }
- // ------------------------------------------------------------------------
- CharacterInfoMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
- {
- int hostid=getChar();
- network_manager->setHostId(hostid);
- std::vector all_karts;
- all_karts = getStringVector();
- kart_properties_manager->setUnavailableKarts(all_karts);
- }
-}; // CharacterInfoMessage
-#endif
diff --git a/src/network/character_selected_message.hpp b/src/network/character_selected_message.hpp
deleted file mode 100644
index 9e8a61961..000000000
--- a/src/network/character_selected_message.hpp
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// 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_CHARACTER_SELECTED_MESSAGE_HPP
-#define HEADER_CHARACTER_SELECTED_MESSAGE_HPP
-
-#include "network/message.hpp"
-#include "network/remote_kart_info.hpp"
-#include "race/race_manager.hpp"
-
-/** This message is send contains information about selected karts. It is send
- * from the client to the server to indicate a selected kart, and from the
- * server to the clients to indicate that a kart was selected. In the latter
- * case it contains the hostid of the successful selecter. This way a client
- * selecting a kart can check if its selection was successful or not, and
- * other clients are informed that a certain kart is not available anymore.
- */
-class CharacterSelectedMessage : public Message
-{
-private:
- /** Number of local players on a host. If the message is send from the
- * server to the clients, this field instead contains the host id of
- * the host which selected the kart
- */
- int m_num_local_players;
- /** Stores information about the selected kart. */
- RemoteKartInfo m_kart_info;
-
-public:
- /** Contains information about a selected kart. When send from the client
- * to the server, it contains the number of local players (which
- * technically needs only to be sent once); when send from from the server
- * to the clients this field instead contains the host id of the host
- * selected the character. This allows the client to detect if a selected
- * kart was not confirmed by the server (i.e. another client or the server
- * has selected the kart first
- * \param player_id The local player id.
- * \param host_id If this value is specified (>-1), then this value is
- * used in the message instead of the number of local
- * players.
- */
- CharacterSelectedMessage(int player_id, int host_id=-1)
- : Message(Message::MT_CHARACTER_INFO)
- {
- m_kart_info = race_manager->getLocalKartInfo(player_id);
- m_num_local_players = race_manager->getNumLocalPlayers();
-
- allocate(getCharLength() // m_kart_info.getLocalPlayerId())
- +getStringLength(m_kart_info.getKartName())
- +m_kart_info.getPlayerName().size() + 1 // FIXME: encoding issues
- +getCharLength()); // m_num_local_players)
- addChar(m_kart_info.getLocalPlayerId());
- addString(m_kart_info.getKartName());
- addString(core::stringc(m_kart_info.getPlayerName().c_str()).c_str()); // FIXME: encoding issues
- // Piggy backing this information saves sending it as a separate
- // message. It is actually only required in the first message
- if(host_id>-1)
- addChar(host_id);
- else
- addChar(race_manager->getNumLocalPlayers());
- } // CharacterSelectedMessage
-
- // ------------------------------------------------------------------------
- /** Unpacks a character selected message. The additional field is either
- * the number of local players (when send from client to server), or the
- * hostid of the host selected the character.
- * \param pkt Received enet packet.
- */
- CharacterSelectedMessage(ENetPacket* pkt):Message(pkt, MT_CHARACTER_INFO)
- {
- m_kart_info.setLocalPlayerId(getChar());
- m_kart_info.setKartName(getString());
- m_kart_info.setPlayerName(core::stringw(getString().c_str())); // FIXME: encoding issues
- m_num_local_players = getChar();
- } // CharacterSelectedMessage(EnetPacket)
-
- // ------------------------------------------------------------------------
- /** Returns the remote kart info structure of the selected kart. */
- const RemoteKartInfo& getKartInfo () const { return m_kart_info; }
-
- /** Returns the number of local players. */
- int getNumPlayers() const { return m_num_local_players; }
-
- /** Returns the host id of the host who selected the kart successfully.
- * This information is actually stored in m_num_local_players field, which
- * is used when a client receives this message.
- */
- int getHostId () const { return m_num_local_players; }
-}; // CharacterSelectedMessage
-#endif
diff --git a/src/network/client_network_manager.cpp b/src/network/client_network_manager.cpp
new file mode 100644
index 000000000..22a22f186
--- /dev/null
+++ b/src/network/client_network_manager.cpp
@@ -0,0 +1,135 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 "network/client_network_manager.hpp"
+
+#include "network/protocols/get_public_address.hpp"
+#include "network/protocols/hide_public_address.hpp"
+#include "network/protocols/show_public_address.hpp"
+#include "network/protocols/get_peer_address.hpp"
+#include "network/protocols/connect_to_server.hpp"
+#include "network/protocols/client_lobby_room_protocol.hpp"
+#include "network/protocols/synchronization_protocol.hpp"
+
+#include "utils/log.hpp"
+
+#include
+#include
+#include
+
+void* waitInput(void* data)
+{
+ std::string str = "";
+ bool stop = false;
+ int n = 0;
+
+ while(!stop)
+ {
+ getline(std::cin, str);
+ if (str == "quit")
+ {
+ stop = true;
+ }
+ else if (str == "disconnect")
+ {
+ NetworkManager::getInstance()->getPeers()[0]->disconnect();
+ }
+ else if (str == "connect")
+ {
+ ProtocolManager::getInstance()->requestStart(new ConnectToServer());
+ }
+ else if (str == "select")
+ {
+ std::string str2;
+ getline(std::cin, str2);
+ Protocol* protocol = ProtocolManager::getInstance()->getProtocol(PROTOCOL_LOBBY_ROOM);
+ ClientLobbyRoomProtocol* clrp = static_cast(protocol);
+ clrp->requestKartSelection(str2);
+ }
+ else if (str == "synchronize")
+ {
+ ProtocolManager::getInstance()->requestStart(new SynchronizationProtocol());
+ }
+ else if (NetworkManager::getInstance()->getPeers().size() > 0)
+ {
+ NetworkString msg;
+ msg.ai8(0);
+ msg += str;
+ NetworkManager::getInstance()->getPeers()[0]->sendPacket(msg);
+ }
+ }
+
+ exit(0);
+
+ return NULL;
+}
+
+ClientNetworkManager::ClientNetworkManager()
+{
+ m_thread_keyboard = NULL;
+ m_connected = false;
+}
+
+ClientNetworkManager::~ClientNetworkManager()
+{
+}
+
+void ClientNetworkManager::run()
+{
+ if (enet_initialize() != 0)
+ {
+ Log::error("ClientNetworkManager", "Could not initialize enet.\n");
+ return;
+ }
+ m_localhost = new STKHost();
+ m_localhost->setupClient(1, 2, 0, 0);
+ m_localhost->startListening();
+
+ Log::info("ClientNetworkManager", "Host initialized.");
+
+ // listen keyboard console input
+ m_thread_keyboard = (pthread_t*)(malloc(sizeof(pthread_t)));
+ pthread_create(m_thread_keyboard, NULL, waitInput, NULL);
+
+ NetworkManager::run();
+
+ Log::info("ClientNetworkManager", "Ready !");
+}
+
+void ClientNetworkManager::reset()
+{
+ NetworkManager::reset();
+
+ m_connected = false;
+ m_localhost = new STKHost();
+ m_localhost->setupClient(1, 2, 0, 0);
+ m_localhost->startListening();
+
+}
+
+void ClientNetworkManager::sendPacket(const NetworkString& data, bool reliable)
+{
+ if (m_peers.size() > 1)
+ Log::warn("ClientNetworkManager", "Ambiguous send of data.\n");
+ m_peers[0]->sendPacket(data, reliable);
+}
+
+STKPeer* ClientNetworkManager::getPeer()
+{
+ return m_peers[0];
+}
diff --git a/src/network/client_network_manager.hpp b/src/network/client_network_manager.hpp
new file mode 100644
index 000000000..ba4101f8c
--- /dev/null
+++ b/src/network/client_network_manager.hpp
@@ -0,0 +1,50 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 CLIENT_NETWORK_MANAGER_HPP
+#define CLIENT_NETWORK_MANAGER_HPP
+
+#include "network/network_manager.hpp"
+
+class ClientNetworkManager : public NetworkManager
+{
+ friend class Singleton;
+ public:
+ static ClientNetworkManager* getInstance()
+ {
+ return Singleton::getInstance();
+ }
+
+ virtual void run();
+ virtual void reset();
+ virtual void sendPacket(const NetworkString& data, bool reliable = true);
+
+ STKPeer* getPeer();
+ virtual bool isServer() { return false; }
+ void setConnected(bool value) { m_connected = value; }
+ bool isConnected() { return m_connected; }
+
+ protected:
+ ClientNetworkManager();
+ virtual ~ClientNetworkManager();
+
+ bool m_connected; //!< Is the user connected to a server
+ pthread_t* m_thread_keyboard;
+};
+
+#endif // CLIENT_NETWORK_MANAGER_HPP
diff --git a/src/network/connect_message.cpp b/src/network/connect_message.cpp
deleted file mode 100644
index 03660c158..000000000
--- a/src/network/connect_message.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// 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 "network/connect_message.hpp"
-
-#include
-#include
-#include
-#ifndef WIN32
-# include
-#endif
-
-#include "config/player.hpp"
-#include "karts/kart_properties_manager.hpp"
-#include "states_screens/state_manager.hpp"
-#include "tracks/track_manager.hpp"
-
-// ----------------------------------------------------------------------------
-/** Creates the connect message. It includes the id of the client (currently
- * player name @ hostname), and the list of available tracks.
- */
-ConnectMessage::ConnectMessage() : Message(MT_CONNECT)
-{
- setId();
- const std::vector &all_tracks =
- track_manager->getAllTrackIdentifiers();
- std::vector all_karts =
- kart_properties_manager->getAllAvailableKarts();
- allocate(getStringLength(m_id) + getStringVectorLength(all_tracks)
- + getStringVectorLength(all_karts));
- addString(m_id);
- addStringVector(all_tracks);
- addStringVector(all_karts);
-} // ConnectMessage
-
-// ----------------------------------------------------------------------------
-/** Unpacks a connect message. The id of the client is stored in this object,
- * and the list of tracks is used to set tracks that are not available on
- * the client to be 'unavailable' on the server.
- * \param pkt Enet packet.
- */
-ConnectMessage::ConnectMessage(ENetPacket* pkt):Message(pkt, MT_CONNECT)
-{
- m_id = getString();
- std::vector all_tracks = getStringVector();
- std::vector all_karts = getStringVector();
- track_manager->setUnavailableTracks(all_tracks);
- kart_properties_manager->setUnavailableKarts(all_karts);
-} // ConnectMessage
-
-// ----------------------------------------------------------------------------
-/** Sets the id, i.e. player name @ hostname, of this client.
- */
-void ConnectMessage::setId()
-{
- char hostname[256];
- gethostname(hostname, 255);
- const std::string& id = core::stringc(StateManager::get()->getActivePlayerProfile(0)->getName()).c_str();
- std::ostringstream o;
- o << id << '@' << hostname;
- m_id = o.str();
-} // ConnectMessage
diff --git a/src/network/event.cpp b/src/network/event.cpp
new file mode 100644
index 000000000..0f4835e6d
--- /dev/null
+++ b/src/network/event.cpp
@@ -0,0 +1,99 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 "network/event.hpp"
+#include "network/network_manager.hpp"
+
+#include "utils/log.hpp"
+
+#include
+
+Event::Event(ENetEvent* event)
+{
+ switch (event->type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ type = EVENT_TYPE_CONNECTED;
+ break;
+ case ENET_EVENT_TYPE_DISCONNECT:
+ type = EVENT_TYPE_DISCONNECTED;
+ break;
+ case ENET_EVENT_TYPE_RECEIVE:
+ type = EVENT_TYPE_MESSAGE;
+ break;
+ case ENET_EVENT_TYPE_NONE:
+ return;
+ break;
+ }
+ if (type == EVENT_TYPE_MESSAGE)
+ {
+ data = NetworkString(std::string((char*)(event->packet->data), event->packet->dataLength-1));
+ }
+ else if (event->data)
+ {
+ }
+
+ m_packet = NULL;
+ if (event->packet)
+ m_packet = event->packet;
+
+ if (m_packet)
+ enet_packet_destroy(m_packet); // we got all we need, just remove the data.
+ m_packet = NULL;
+
+ std::vector peers = NetworkManager::getInstance()->getPeers();
+ peer = new STKPeer*;
+ *peer = NULL;
+ for (unsigned int i = 0; i < peers.size(); i++)
+ {
+ if (peers[i]->m_peer == event->peer)
+ {
+ *peer = peers[i];
+ Log::verbose("Event", "The peer you sought has been found on %lx", (long int)(peer));
+ return;
+ }
+ }
+ if (*peer == NULL) // peer does not exist, create him
+ {
+ STKPeer* new_peer = new STKPeer();
+ new_peer->m_peer = event->peer;
+ *peer = new_peer;
+ Log::debug("Event", "Creating a new peer, address are STKPeer:%lx, Peer:%lx", (long int)(new_peer), (long int)(event->peer));
+ }
+}
+
+Event::Event(const Event& event)
+{
+ m_packet = NULL;
+ data = event.data;
+ // copy the peer
+ peer = event.peer;
+ type = event.type;
+}
+
+Event::~Event()
+{
+ peer = NULL;
+ m_packet = NULL;
+}
+
+void Event::removeFront(int size)
+{
+ data.removeFront(size);
+}
+
diff --git a/src/network/event.hpp b/src/network/event.hpp
new file mode 100644
index 000000000..ce3a97629
--- /dev/null
+++ b/src/network/event.hpp
@@ -0,0 +1,76 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 EVENT_HPP
+#define EVENT_HPP
+
+#include "network/stk_peer.hpp"
+#include "network/network_string.hpp"
+#include "utils/types.hpp"
+
+/*!
+ * \enum EVENT_TYPE
+ * \brief Represents a network event type.
+ */
+enum EVENT_TYPE
+{
+ EVENT_TYPE_CONNECTED, //!< A peer is connected
+ EVENT_TYPE_DISCONNECTED,//!< A peer is disconnected
+ EVENT_TYPE_MESSAGE //!< A message between server and client protocols
+};
+
+/*!
+ * \class Event
+ * \brief Class representing an event that need to pass trough the system.
+ * This is used to remove ENet dependency in the network.
+ * It interfaces the ENetEvent structure.
+ * The user has to be extremely careful about the peer.
+ * Indeed, when packets are logged, the state of the peer cannot be stored at
+ * all times, and then the user of this class can rely only on the address/port
+ * of the peer, and not on values that might change over time.
+ */
+class Event
+{
+ public:
+ /*! \brief Constructor
+ * \param event : The event that needs to be translated.
+ */
+ Event(ENetEvent* event);
+ /*! \brief Constructor
+ * \param event : The event to copy.
+ */
+ Event(const Event& event);
+ /*! \brief Destructor
+ * frees the memory of the ENetPacket.
+ */
+ ~Event();
+
+ /*! \brief Remove bytes at the beginning of data.
+ * \param size : The number of bytes to remove.
+ */
+ void removeFront(int size);
+
+ EVENT_TYPE type; //!< Type of the event.
+ NetworkString data; //!< Copy of the data passed by the event.
+ STKPeer** peer; //!< Pointer to the peer that triggered that event.
+
+ private:
+ ENetPacket* m_packet; //!< A pointer on the ENetPacket to be deleted.
+};
+
+#endif // EVENT_HPP
diff --git a/src/network/flyable_info.hpp b/src/network/flyable_info.hpp
deleted file mode 100644
index eedc33585..000000000
--- a/src/network/flyable_info.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// 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_FLYABLE_INFO_HPP
-#define HEADER_FLYABLE_INFO_HPP
-
-#include "network/message.hpp"
-
-/** Class used to transfer information about projectiles from server to client.
- * It contains only the coordinates, rotation, and explosion state.
- */
-class FlyableInfo
-{
-public:
- Vec3 m_xyz; /** Position of object. */
- btQuaternion m_rotation; /** Orientation of object */
- bool m_exploded; /** If the object exploded in the current frame. */
-
- /** Constructor to initialise all fields.
- */
- FlyableInfo(const Vec3& xyz, const btQuaternion &rotation, bool exploded) :
- m_xyz(xyz), m_rotation(rotation), m_exploded(exploded)
- {};
- // ------------------------------------------------------------------------
- /** Allow this object to be stored in std::vector fields.
- */
- FlyableInfo() {};
- // ------------------------------------------------------------------------
- /** Construct a FlyableInfo from a message (which is unpacked).
- */
- FlyableInfo(Message *m)
- {
- m_xyz = m->getVec3();
- m_rotation = m->getQuaternion();
- m_exploded = m->getBool();
- } // FlyableInfo(Message)
- // ------------------------------------------------------------------------
- /** Returns the length of the serialised message. */
- static int getLength()
- {
- return Message::getVec3Length()
- + Message::getQuaternionLength()
- + Message::getBoolLength();
- } // getLength
- // ------------------------------------------------------------------------
- void serialise(Message *m)
- {
- m->addVec3(m_xyz);
- m->addQuaternion(m_rotation);
- m->addBool(m_exploded);
- } // serialise
-};
-
-#endif
-
diff --git a/src/network/game_setup.cpp b/src/network/game_setup.cpp
new file mode 100644
index 000000000..50f50c9cc
--- /dev/null
+++ b/src/network/game_setup.cpp
@@ -0,0 +1,145 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 "network/game_setup.hpp"
+
+#include "utils/log.hpp"
+
+//-----------------------------------------------------------------------------
+
+GameSetup::GameSetup()
+{
+}
+
+//-----------------------------------------------------------------------------
+
+GameSetup::~GameSetup()
+{
+ // remove all players
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ delete m_players[i];
+ };
+ m_players.clear();
+}
+
+//-----------------------------------------------------------------------------
+
+void GameSetup::addPlayer(NetworkPlayerProfile* profile)
+{
+ m_players.push_back(profile);
+ Log::verbose("GameSetup", "New player in the game setup. Global id : %u, "
+ "Race id : %d.", profile->user_profile->getUserID(), profile->race_id);
+}
+
+//-----------------------------------------------------------------------------
+
+bool GameSetup::removePlayer(uint32_t id)
+{
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->user_profile->getUserID() == id)
+ {
+ delete m_players[i];
+ m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
+ Log::verbose("GameSetup", "Removed a player from the game setup. "
+ "Remains %u.", m_players.size());
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+
+bool GameSetup::removePlayer(uint8_t id)
+{
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->race_id == id) // check the given id
+ {
+ delete m_players[i];
+ m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
+ Log::verbose("GameSetup", "Removed a player from the game setup. "
+ "Remains %u.", m_players.size());
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+
+void GameSetup::setPlayerKart(uint8_t id, std::string kart_name)
+{
+ bool found = false;
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->race_id == id)
+ {
+ m_players[i]->kart_name = kart_name;
+ Log::info("GameSetup::setPlayerKart", "Player %d took kart %s",
+ id, kart_name.c_str());
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ Log::info("GameSetup::setPlayerKart", "The player %d was unknown.", id);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+const NetworkPlayerProfile* GameSetup::getProfile(uint32_t id)
+{
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->user_profile->getUserID() == id)
+ {
+ return m_players[i];
+ }
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+
+const NetworkPlayerProfile* GameSetup::getProfile(uint8_t id)
+{
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->race_id == id)
+ {
+ return m_players[i];
+ }
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+
+bool GameSetup::isKartAvailable(std::string kart_name)
+{
+ for (unsigned int i = 0; i < m_players.size(); i++)
+ {
+ if (m_players[i]->kart_name == kart_name)
+ return false;
+ }
+ return true;
+}
diff --git a/src/network/game_setup.hpp b/src/network/game_setup.hpp
new file mode 100644
index 000000000..c7ab6cb3e
--- /dev/null
+++ b/src/network/game_setup.hpp
@@ -0,0 +1,72 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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.
+
+/*! \file game_setup.hpp
+ */
+
+#ifndef GAME_SETUP_HPP
+#define GAME_SETUP_HPP
+
+#include "online/user.hpp"
+
+#include
+#include
+
+/*! \class PlayerProfile
+ * \brief Contains the profile of a player.
+ */
+class NetworkPlayerProfile
+{
+ public:
+ NetworkPlayerProfile() { race_id = 0; user_profile = NULL; }
+ ~NetworkPlayerProfile() {}
+
+ uint8_t race_id; //!< The id of the player for the race
+ std::string kart_name; //!< The selected kart.
+ Online::User* user_profile; //!< Pointer to the lobby profile
+};
+
+/*! \class GameSetup
+ * \brief Used to store the needed data about the players that join a game.
+ * This class stores all the possible information about players in a lobby.
+ */
+class GameSetup
+{
+ public:
+ GameSetup();
+ virtual ~GameSetup();
+
+ void addPlayer(NetworkPlayerProfile* profile); //!< Add a player.
+ bool removePlayer(uint32_t id); //!< Remove a player by id.
+ bool removePlayer(uint8_t id); //!< Remove a player by local id.
+ void setPlayerKart(uint8_t id, std::string kart_name); //!< Set the kart of a player
+
+ std::vector getPlayers() { return m_players; }
+ int getPlayerCount() { return m_players.size(); }
+ const NetworkPlayerProfile* getProfile(uint32_t id); //!< Get a profile by database id
+ const NetworkPlayerProfile* getProfile(uint8_t id); //!< Get the profile by the lobby id
+
+ bool isKartAvailable(std::string kart_name);
+ bool isKartAllowed(std::string kart_name) {return true; }
+
+ protected:
+ std::vector m_players; //!< Information about players
+ NetworkPlayerProfile m_self_profile; //!< Information about self (client only)
+};
+
+#endif // GAME_SETUP_HPP
diff --git a/src/network/http_functions.cpp b/src/network/http_functions.cpp
new file mode 100644
index 000000000..8ff861a05
--- /dev/null
+++ b/src/network/http_functions.cpp
@@ -0,0 +1,67 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 SuperTuxKart-Team
+//
+// 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 "network/http_functions.hpp"
+
+#include "utils/log.hpp"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace HTTP
+{
+CURL *curl;
+CURLcode res;
+
+static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ ((std::string*)userp)->append((char*)contents, size * nmemb);
+ return size * nmemb;
+}
+
+void init()
+{
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if(!curl)
+ Log::error("HTTP", "Error while loading cURL library.\n");
+}
+
+std::string getPage(std::string url)
+{
+ std::string readBuffer;
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
+ res = curl_easy_perform(curl);
+ if(res != CURLE_OK)
+ Log::error("HTTP", "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+
+ return readBuffer;
+}
+
+void shutdown()
+{
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+}
+
+}
diff --git a/src/network/kart_update_message.hpp b/src/network/http_functions.hpp
similarity index 72%
rename from src/network/kart_update_message.hpp
rename to src/network/http_functions.hpp
index 7d3a38fc4..970b9c1dd 100644
--- a/src/network/kart_update_message.hpp
+++ b/src/network/http_functions.hpp
@@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs
+// Copyright (C) 2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -16,15 +16,20 @@
// 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_HPP
-#define HEADER_KART_UPDATE_MESSAGE_HPP
+#ifndef HTTP_FUNCTIONS_HPP
+#define HTTP_FUNCTIONS_HPP
-#include "network/message.hpp"
+#include
-class KartUpdateMessage : public Message
+namespace HTTP
{
-public:
- KartUpdateMessage();
- KartUpdateMessage(ENetPacket* pkt);
-}; // KartUpdateMessage
-#endif
+
+void init();
+void shutdown();
+
+std::string getPage(std::string url);
+
+
+}
+
+#endif // HTTP_FUNCTIONS_HPP
diff --git a/src/network/item_info.hpp b/src/network/item_info.hpp
deleted file mode 100644
index 0334e2ee0..000000000
--- a/src/network/item_info.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// 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_ITEM_INFO_HPP
-#define HEADER_ITEM_INFO_HPP
-/** Class used to transfer information about collected items from
-* server to client.
-*/
-class ItemInfo
-{
-public:
- /** Kart id (in world) of the kart collecting the item. */
- unsigned char m_kart_id;
- /** Index of the collected item. This is set to -1 if a kart
- * triggers a rescue (i.e. attaches the butterfly).]
- */
- short m_item_id;
- /** Additional info used, depending on item type. This is usually
- * the type of the collected item.
- */
- char m_add_info;
-
- /** Constructor to initialise all fields. */
- ItemInfo(int kart, int item, char add_info) :
- m_kart_id(kart), m_item_id(item),
- m_add_info(add_info)
- {}
- // -------------------------------------------------------------
- /** Construct ItemInfo from a message (which is unpacked). */
- ItemInfo(Message *m)
- {
- m_kart_id = m->getChar();
- m_item_id = m->getShort();
- m_add_info = m->getChar();
- }
- // -------------------------------------------------------------
- /*** Returns size in bytes necessary to store ItemInfo. */
- static int getLength() {return 2*Message::getCharLength()
- + Message::getShortLength();}
- // -------------------------------------------------------------
- /** Serialises this object into the message object */
- void serialise(Message *m)
- {
- m->addChar(m_kart_id);
- m->addShort(m_item_id);
- m->addChar(m_add_info);
- } // serialise
-}; // ItemInfo
-
-#endif
-
diff --git a/src/network/kart_control_message.cpp b/src/network/kart_control_message.cpp
deleted file mode 100644
index db6cea020..000000000
--- a/src/network/kart_control_message.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// 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 "network/kart_control_message.hpp"
-
-#include "karts/controller/controller.hpp"
-#include "modes/world.hpp"
-#include "network/network_kart.hpp"
-
-KartControlMessage::KartControlMessage()
- : Message(Message::MT_KART_CONTROL)
-{
- World *world=World::getWorld();
- unsigned int num_local_players = race_manager->getNumLocalPlayers();
- unsigned int control_size = KartControl::getLength();
- allocate(control_size*num_local_players);
- for(unsigned int i=0; igetLocalPlayerKart(i);
- const KartControl& controls = kart->getControls();
- controls.serialise(this);
- }
-} // KartControlMessage
-// ----------------------------------------------------------------------------
-/** Receives a kart control message.
- * \param 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)
-{
- // FIXME: This probably does not work anymore - it assume that
- // num_local_Players is the number of all local karts, while it might
- // only be the number of all network karts.
- for(int i=kart_id_offset; igetKart(i);
- if(kart->getController()->isNetworkController())
- {
- ((NetworkKart*)kart)->setControl(kc);
- }
- }
-}; // KartControlMessage
-
diff --git a/src/network/kart_update_message.cpp b/src/network/kart_update_message.cpp
deleted file mode 100644
index 2b16cc0e9..000000000
--- a/src/network/kart_update_message.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// 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 "network/kart_update_message.hpp"
-
-#include "karts/abstract_kart.hpp"
-#include "modes/world.hpp"
-
-KartUpdateMessage::KartUpdateMessage()
- : Message(Message::MT_KART_INFO)
-{
- World *world = World::getWorld();
- unsigned int num_karts = world->getNumKarts();
-
- // Send the number of karts and for each kart the compressed
- // control structure (3 ints) and xyz,hpr (4 floats: quaternion:
- allocate(getCharLength()+
- num_karts*(KartControl::getLength() + getVec3Length()
- +getQuaternionLength()) );
- addChar(num_karts);
- for(unsigned int i=0; igetKart(i);
- const KartControl& kc=kart->getControls();
- kc.serialise(this);
- addVec3(kart->getXYZ());
- addQuaternion(kart->getRotation());
- } // for i
-} // KartUpdateMessage
-// ----------------------------------------------------------------------------
-KartUpdateMessage::KartUpdateMessage(ENetPacket* pkt)
- : Message(pkt, MT_KART_INFO)
-{
- World *world = World::getWorld();
- 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/message.cpp b/src/network/message.cpp
deleted file mode 100644
index b1f754c02..000000000
--- a/src/network/message.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-//
-// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
-//
-// 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 "network/message.hpp"
-
-#include
-#include
-#include
-#include
-
-/** 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);
- m_type = type;
- m_pos = 0;
- m_data_size = -1;
- m_data = NULL;
- m_needs_destroy = 0; // enet destroys message after send
-} // 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;
- m_data_size = pkt->dataLength;
- m_data = (char*)pkt->data;
- m_type = (MessageType)m_data[0];
- if(m_type!=m)
- printf("type %d %d\n",m_type,m);
- assert(m_type==m);
- m_pos = 1;
- m_needs_destroy = true;
-} // Message
-
-// ----------------------------------------------------------------------------
-/** Frees the memory allocated for this message. */
-Message::~Message()
-{
- 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;
- m_pkt = enet_packet_create (NULL, m_data_size, ENET_PACKET_FLAG_RELIABLE);
- m_data = (char*)m_pkt->data;
- m_data[0] = m_type;
- m_pos = 1;
-} // allocate
-
-// ----------------------------------------------------------------------------
-/** Adds an integer value to the message.
- * \param data The integer value to add.
- */
-void Message::addInt(int data)
-{
- 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);
-} // 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
-
-// ----------------------------------------------------------------------------
-/** Adds a floating point value to the message.
- * \param data Floating point value to add.
- */
-void Message::addFloat(const float data)
-{
- // The simple approach of using addInt(*(int*)&data)
- // does not work (at least with optimisation on certain g++ versions,
- // see getFloat for more details)
- int n;
- memcpy(&n, &data, sizeof(float));
- addInt(n);
-} // addFloat
-// ----------------------------------------------------------------------------
-float Message::getFloat()
-{
- int i = getInt();
- float f;
- memcpy(&f, &i, sizeof(int));
- return f;
- // The 'obvious' way:
- // float *f = (float*) &i;
- // return *f;
- // does NOT work, see http://www.velocityreviews.com/forums/showthread.php?t=537336
- // for details
-} // getFloat
-
-// ----------------------------------------------------------------------------
-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;
-} // addString
-
-// ----------------------------------------------------------------------------
-std::string Message::getString()
-{
- char *str = (char*) &(m_data[m_pos]);
- int len = strlen(str)+1;
- m_pos += len;
- return std::string(str);
-} // getString
-
-// ----------------------------------------------------------------------------
-/** Returns the number of bytes necessary to store a string vector.
- * \param vs std::vector
- */
-int Message::getStringVectorLength(const std::vector& vs)
-{
- int len=getShortLength();
- for(unsigned int i=0; i to the message.
- */
-void Message::addStringVector(const std::vector& vs)
-{
- assert(vs.size()<32767);
- addShort(vs.size());
- for(unsigned short i=0; i Message::getStringVector()
-{
- std::vector vs;
- vs.resize(getShort());
- for(unsigned int i=0; i
-#include
-#include
-#include
-#include "btBulletDynamicsCommon.h"
-
-using std::memcpy;
-
-#include "enet/enet.h"
-
-#include "utils/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
-
-/** 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:
- /** Contains all tags used in identifying a message. */
- enum MessageType {MT_CONNECT=1, MT_CHARACTER_INFO, MT_CHARACTER_CONFIRM,
- MT_RACE_INFO, MT_RACE_START, MT_WORLD_LOADED,
- MT_KART_INFO, MT_KART_CONTROL, MT_RACE_STATE,
- MT_RACE_RESULT, MT_RACE_RESULT_ACK
- };
-private:
- ENetPacket *m_pkt;
- char *m_data;
- MessageType m_type;
- int m_data_size;
- unsigned int m_pos; // simple stack counter for constructing packet data
- bool m_needs_destroy; // only received messages need to be destroyed
-
-public:
- void addInt(int data);
- void addShort(short data);
- void addString(const std::string &data);
- void addStringVector(const std::vector& vs);
- void addUInt(unsigned int data) { addInt(*(int*)&data); }
- void addFloat(const float 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; }
-#ifndef WIN32 // on windows size_t is unsigned int
- void addSizeT(size_t data) { addInt((int)data); }
-#endif
- void addIntArray(int *d, unsigned int n)
- { for(unsigned int i=0;
- i
- getStringVector();
- 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;
- 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; }
- 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& vs);
-#ifndef WIN32
- static int getSizeTLength(size_t n) { return sizeof(int); }
-#endif
-
-public:
- 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 */
- static MessageType peekType(ENetPacket *pkt)
- { return (MessageType)pkt->data[0];}
-
-}; // Message
-
-
-#endif
-
diff --git a/src/network/kart_control_message.hpp b/src/network/network_interface.cpp
similarity index 68%
rename from src/network/kart_control_message.hpp
rename to src/network/network_interface.cpp
index 6127f62b9..262083330 100644
--- a/src/network/kart_control_message.hpp
+++ b/src/network/network_interface.cpp
@@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs
+// Copyright (C) 2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -16,16 +16,13 @@
// 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_HPP
-#define HEADER_KART_CONTROL_MESSAGE_HPP
+#include "network/network_interface.hpp"
-#include "network/message.hpp"
-class KartControlMessage : public Message
+NetworkInterface::NetworkInterface()
{
-public:
- KartControlMessage();
- KartControlMessage(ENetPacket* pkt, int kart_id_offset,
- int num_local_players);
-}; // KartUpdateMessage
-#endif
+}
+
+NetworkInterface::~NetworkInterface()
+{
+}
diff --git a/src/network/connect_message.hpp b/src/network/network_interface.hpp
similarity index 59%
rename from src/network/connect_message.hpp
rename to src/network/network_interface.hpp
index 1875b5718..65e5a4f4b 100644
--- a/src/network/connect_message.hpp
+++ b/src/network/network_interface.hpp
@@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs
+// Copyright (C) 2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -16,22 +16,29 @@
// 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_CONNECT_MESSAGE_HPP
-#define HEADER_CONNECT_MESSAGE_HPP
+#ifndef NETWORK_INTERFACE_H
+#define NETWORK_INTERFACE_H
+#include "network/singleton.hpp"
+#include "network/types.hpp"
+#include "network/network_manager.hpp"
+
+#include
#include
-#include "network/message.hpp"
-class ConnectMessage : public Message
+class NetworkInterface : public Singleton
{
-private:
- std::string m_id;
- void setId();
-public:
- ConnectMessage();
- ConnectMessage(ENetPacket* pkt);
- const std::string&
- getId() { return m_id; }
-}; // ConnectMessage
-#endif
+ friend class Singleton;
+ public:
+
+ void initNetwork(bool server);
+
+ protected:
+ // protected functions
+ NetworkInterface();
+ virtual ~NetworkInterface();
+
+};
+
+#endif // NETWORK_INTERFACE_H
diff --git a/src/network/network_kart.cpp b/src/network/network_kart.cpp
deleted file mode 100644
index 42cf8a3cc..000000000
--- a/src/network/network_kart.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2004-2005 Steve Baker
-// Copyright (C) 2006 SuperTuxKart-Team, Joerg Henrichs, Steve Baker
-//
-// 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 "network/network_manager.hpp"
-#include "network/network_kart.hpp"
-
-/** A network kart. On the server, it receives its control information (steering etc)
- from the network manager.
- */
-NetworkKart::NetworkKart(const std::string &kart_name,
- unsigned int world_kart_id, int position,
- const btTransform &init_transform,
- int global_player_id,
- RaceManager::KartType type)
- : Kart(kart_name, world_kart_id, position,
- init_transform)
-{
- m_global_player_id = global_player_id;
-} // NetworkKart
-
-// ----------------------------------------------------------------------------
-void NetworkKart::setControl(const KartControl& kc)
-{
- assert(network_manager->getMode()==NetworkManager::NW_SERVER);
- m_controls = kc;
-} // setControl
-
diff --git a/src/network/network_manager.cpp b/src/network/network_manager.cpp
index 2554e070d..5e44bac61 100644
--- a/src/network/network_manager.cpp
+++ b/src/network/network_manager.cpp
@@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
+// Copyright (C) 2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -18,723 +18,221 @@
#include "network/network_manager.hpp"
-#include "config/stk_config.hpp"
-#include "config/user_config.hpp"
-#include "karts/kart_properties_manager.hpp"
-#include "modes/world.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 "network/character_confirm_message.hpp"
-#include "network/race_result_message.hpp"
-#include "network/race_result_ack_message.hpp"
-#include "race/race_manager.hpp"
+#include "network/protocols/hide_public_address.hpp"
+#include "network/protocols/show_public_address.hpp"
+#include "network/protocols/get_public_address.hpp"
-NetworkManager* network_manager = 0;
+#include "network/protocol_manager.hpp"
+#include "network/client_network_manager.hpp"
+#include "network/server_network_manager.hpp"
+
+#include "utils/log.hpp"
+
+#include
+#include
+
+//-----------------------------------------------------------------------------
NetworkManager::NetworkManager()
{
- m_mode = NW_NONE;
- m_state = NS_ACCEPT_CONNECTIONS;
- m_host = NULL;
+ m_public_address.ip = 0;
+ m_public_address.port = 0;
+ m_localhost = NULL;
+ m_game_setup = NULL;
+}
- m_num_clients = 0;
- m_host_id = 0;
+//-----------------------------------------------------------------------------
- if (enet_initialize () != 0)
- {
- fprintf (stderr, "An error occurred while initializing ENet.\n");
- exit(-1);
- }
-} // NetworkManager
-
-// -----------------------------------------------------------------------------
-bool NetworkManager::initialiseConnections()
-{
- switch(m_mode)
- {
- case NW_NONE: return true;
- case NW_CLIENT: return initClient();
- case NW_SERVER: return initServer();
- }
- return true;
-} // NetworkManager
-
-// -----------------------------------------------------------------------------
NetworkManager::~NetworkManager()
{
- if(m_mode==NW_SERVER || m_mode==NW_CLIENT) enet_host_destroy(m_host);
- enet_deinitialize();
-} // ~NetworkManager
+ ProtocolManager::kill();
-// -----------------------------------------------------------------------------
-bool NetworkManager::initServer()
-{
- ENetAddress address;
- address.host = ENET_HOST_ANY;
- address.port = UserConfigParams::m_server_port;
-
- m_host = enet_host_create (& address /* the address to bind the server host to */,
- stk_config->m_max_karts /* number of connections */,
- 0 /* channel limit */,
- 0 /* incoming bandwidth */,
- 0 /* outgoing bandwidth */ );
- if (m_host == NULL)
+ if (m_localhost)
+ delete m_localhost;
+ while(!m_peers.empty())
{
- fprintf (stderr,
- "An error occurred while trying to create an ENet server host.\n"
- "Progressing in non-network mode\n");
- m_mode = NW_NONE;
- return false;
+ delete m_peers.back();
+ m_peers.pop_back();
}
+}
- m_server = NULL;
- m_clients.push_back(NULL); // server has host_id=0, so put a dummy entry at 0 in client array
+//-----------------------------------------------------------------------------
- m_client_names.push_back("server");
- return true;
-} // initServer
-
-// -----------------------------------------------------------------------------
-/** Initialises the client. This function tries to connect to the server.
- */
-bool NetworkManager::initClient()
+void NetworkManager::run()
{
- m_host = enet_host_create (NULL /* create a client host */,
- 1 /* only allow 1 outgoing connection */,
- 0 /* channel limit */,
- 0 /* downstream bandwidth unlimited */,
- 0 /* upstream bandwidth unlimited */ );
+ // create the protocol manager
+ ProtocolManager::getInstance();
+}
- if (m_host == NULL)
+void NetworkManager::reset()
+{
+ if (m_localhost)
+ delete m_localhost;
+ m_localhost = NULL;
+ while(!m_peers.empty())
{
- fprintf (stderr,
- "An error occurred while trying to create an ENet client host.\n");
- return false;
+ delete m_peers.back();
+ m_peers.pop_back();
}
+}
- ENetAddress address;
- ENetEvent event;
- ENetPeer *peer;
+//-----------------------------------------------------------------------------
- enet_address_set_host (& address, UserConfigParams::m_server_address.c_str());
- address.port = UserConfigParams::m_server_port;
-
- /* Initiate the connection, allocating the two channels 0 and 1. */
- peer = enet_host_connect (m_host, &address, 2, 0);
-
- if (peer == NULL)
- {
- fprintf(stderr,
- "No available peers for initiating an ENet connection.\n");
- return false;
- }
-
- /* Wait up to 5 seconds for the connection attempt to succeed. */
- if (enet_host_service (m_host, & event, 5000) <= 0 ||
- event.type != ENET_EVENT_TYPE_CONNECT)
- {
- /* Either the 5 seconds are up or a disconnect event was */
- /* received. Reset the peer in the event the 5 seconds */
- /* had run out without any significant event. */
- enet_peer_reset (peer);
-
- fprintf(stderr, "Connection to '%s:%d' failed.\n",
- UserConfigParams::m_server_address.c_str(), (int)UserConfigParams::m_server_port);
- return false;
- }
- m_server = peer;
- return true;
-} // initClient
-
-// ----------------------------------------------------------------------------
-/** Switches the network manager to client mode. This function sets the state
- * to waiting_for_chars (so that the message from the server containing all
- * available characters can be received).
- */
-void NetworkManager::becomeClient()
+bool NetworkManager::connect(TransportAddress peer)
{
- m_mode = NW_CLIENT;
- m_state = NS_WAIT_FOR_AVAILABLE_CHARACTERS;
-} // becomeClient
+ if (peerExists(peer))
+ return isConnectedTo(peer);
-// ----------------------------------------------------------------------------
-/** Switches the network manager to server mode. This function sets the state
- * to accepting connections.
- */
-void NetworkManager::becomeServer()
+ return STKPeer::connectToHost(m_localhost, peer, 2, 0);
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::setManualSocketsMode(bool manual)
{
- m_mode = NW_SERVER;
- m_state = NS_ACCEPT_CONNECTIONS;
-} // becomeServer
-
-// ----------------------------------------------------------------------------
-/** Called in case of an error, to switch back to non-networking mode.
-*/
-void NetworkManager::disableNetworking()
-{
- m_mode=NW_NONE;
- if (m_host != NULL)
- {
- enet_host_destroy(m_host);
- m_host = NULL;
- }
- // FIXME: what other enet data structures do we have to free/reset???
-
-} // disableNetworking
-
-// ----------------------------------------------------------------------------
-void NetworkManager::handleNewConnection(ENetEvent *event)
-{
- // Only accept while waiting for connections
- if(m_state!=NS_ACCEPT_CONNECTIONS) return;
-
- // The logical connection (from STK point of view) happens when
- // the connection message is received. But for now reserve the
- // space in the data structures (e.g. in case that two connects
- // happen before a connect message is received
- m_client_names.push_back("NOT SET YET");
- m_clients.push_back(event->peer);
- event->peer->data = (void*)int(m_clients.size()-1); // save hostid in peer data
-
-} // handleNewConnection
-
-// ----------------------------------------------------------------------------
-void NetworkManager::handleDisconnection(ENetEvent *event)
-{
- if(m_state!=NS_ACCEPT_CONNECTIONS)
- {
- fprintf(stderr, "Disconnect while in race - close your eyes and hope for the best.\n");
- return;
- }
- fprintf(stderr, "%x:%d disconnected (host id %d).\n", event->peer->address.host,
- event->peer->address.port, (int)(long)event->peer->data );
- m_num_clients--;
-} // handleDisconnection
-
-// ----------------------------------------------------------------------------
-void NetworkManager::handleMessageAtServer(ENetEvent *event)
-{ // handle message at server (from client)
-
- switch(m_state)
- {
- case NS_ACCEPT_CONNECTIONS:
- {
- ConnectMessage m(event->packet);
- m_client_names[(int)(long)event->peer->data] = m.getId();
- m_num_clients++;
- return;
- }
- case NS_KART_CONFIRMED: // Fall through
- case NS_CHARACTER_SELECT:
- {
- CharacterSelectedMessage m(event->packet);
- 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
- {
- m_num_local_players[hostid] = m.getNumPlayers();
- m_num_all_players += m.getNumPlayers();
- // count how many hosts have sent (at least) one message
- m_barrier_count ++;
- }
- RemoteKartInfo ki=m.getKartInfo();
- ki.setHostId(hostid);
- m_kart_info.push_back(ki);
-
- int kart_id = kart_properties_manager->getKartId(ki.getKartName());
- kart_properties_manager->testAndSetKart(kart_id);
- // TODO - character selection screen in networking
- /*
- CharSel *menu = dynamic_cast(menu_manager->getCurrentMenu());
- if(menu)
- menu->updateAvailableCharacters();
- */
-
- // Broadcast the information about a selected kart to all clients
- CharacterConfirmMessage ccm(ki.getKartName(), hostid);
- broadcastToClients(ccm);
- // See if this was the last message, i.e. we have received at least
- // 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 == (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
- // not yet have selected all characters!
- m_state = NS_ALL_REMOTE_CHARACTERS_DONE;
- }
- break;
- }
- case NS_READY_SET_GO_BARRIER:
- {
- m_barrier_count ++;
- if(m_barrier_count==(int)m_num_clients)
- {
- m_state = NS_RACING;
- RaceStartMessage m;
- broadcastToClients(m);
- }
- break;
- }
- case NS_RACE_RESULT_BARRIER:
- {
- // Other message, esp. kart control, are silently ignored.
- // FIXME: we might want to make sure that no such message actually arrives
- if(Message::peekType(event->packet)!=Message::MT_RACE_RESULT_ACK)
- {
- enet_packet_destroy(event->packet);
- return;
- }
- m_barrier_count++;
- if(m_barrier_count==(int)m_num_clients)
- {
- m_state = NS_MAIN_MENU;
- }
- break;
- }
- default: assert(0); // should not happen
- } // switch m_state
-} // handleMessageAtServer
-
-// ----------------------------------------------------------------------------
-void NetworkManager::handleMessageAtClient(ENetEvent *event)
-{ // handle message at client (from server)
- switch(m_state)
- {
- case NS_WAIT_FOR_AVAILABLE_CHARACTERS:
- {
- CharacterInfoMessage m(event->packet);
- // FIXME: handle list of available characters
- m_state = NS_CHARACTER_SELECT;
- break;
- }
- case NS_CHARACTER_SELECT:
- {
- CharacterConfirmMessage m(event->packet);
- kart_properties_manager->selectKartName(m.getKartName());
- // TODO - karts selection screen in networking
- /*
- CharSel *menu = dynamic_cast(menu_manager->getCurrentMenu());
- if(menu)
- menu->updateAvailableCharacters();
- */
- break;
- }
- case NS_WAIT_FOR_KART_CONFIRMATION:
- {
- CharacterConfirmMessage m(event->packet);
- kart_properties_manager->selectKartName(m.getKartName());
-
- // If the current menu is the character selection menu,
- // update the menu so that the newly taken character is removed.
- // TODO - kart selection screen and networking
- /*
- CharSel *menu = dynamic_cast(menu_manager->getCurrentMenu());
- if(menu)
- menu->updateAvailableCharacters();*/
- // Check if we received a message about the kart we just selected.
- // If so, the menu needs to progress, otherwise a different kart
- // must be selected by the current player.
- if(m.getKartName()==m_kart_to_confirm)
- {
- int host_id = m.getHostId();
- m_state = (host_id == getMyHostId()) ? NS_KART_CONFIRMED
- : NS_CHARACTER_SELECT;
- } // m.getkartName()==m_kart_to_confirm
- break;
- } // wait for kart confirmation
- case NS_WAIT_FOR_RACE_DATA:
- {
- // It is possible that character confirm messages arrive at the
- // client when it has already left the character selection screen.
- // In this case the messages can simply be ignored.
- if(Message::peekType(event->packet)==Message::MT_CHARACTER_CONFIRM)
- {
- // Receiving it will automatically free the memory.
- CharacterConfirmMessage m(event->packet);
- return;
- }
- RaceInfoMessage m(event->packet);
- // The constructor actually sets the information in the race manager
- m_state = NS_LOADING_WORLD;
- break;
- }
- case NS_READY_SET_GO_BARRIER:
- {
- // Not actually needed, but the destructor of RaceStartMessage
- // will free the memory of the event.
- RaceStartMessage m(event->packet);
- m_state = NS_RACING;
- break;
- }
- case NS_RACING:
- {
- assert(false); // should never be here while racing
- break;
- }
- case NS_RACE_RESULT_BARRIER:
- {
- RaceResultAckMessage message(event->packet);
- // TODO - race results menu in networking
- /*
- RaceResultsGUI *menu = dynamic_cast(menu_manager->getCurrentMenu());
- if(menu)
- menu->setSelectedWidget(message.getSelectedMenu());*/
- m_state = NS_RACE_RESULT_BARRIER_OVER;
- break;
- }
- default:
- {
- printf("received unknown message: type %d\n",
- Message::peekType(event->packet));
- // assert(0); // should not happen
- }
- } // switch m_state
-} // handleMessageAtClient
-
-// ----------------------------------------------------------------------------
-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;
- if(result<0)
- {
- fprintf(stderr, "Error while receiving messages -> ignored.\n");
- return;
- }
- switch (event.type)
- {
- case ENET_EVENT_TYPE_CONNECT: handleNewConnection(&event); break;
- case ENET_EVENT_TYPE_RECEIVE:
- if(m_mode==NW_SERVER)
- handleMessageAtServer(&event);
- else
- handleMessageAtClient(&event);
- break;
- case ENET_EVENT_TYPE_DISCONNECT: handleDisconnection(&event); break;
- case ENET_EVENT_TYPE_NONE: break;
- }
-} // update
-
-// ----------------------------------------------------------------------------
-void NetworkManager::broadcastToClients(Message &m)
-{
- enet_host_broadcast(m_host, 0, m.getPacket());
- enet_host_flush(m_host);
-} // broadcastToClients
-
-// ----------------------------------------------------------------------------
-void NetworkManager::sendToServer(Message &m)
-{
- enet_peer_send(m_server, 0, m.getPacket());
- enet_host_flush(m_host);
-} // sendToServer
-
-// ----------------------------------------------------------------------------
-/** Cleans up character related data structures. Must be called before any
- * character related data is set.
- */
-void NetworkManager::initCharacterDataStructures()
-{
- // This is called the first time the character selection menu is displayed
-
- if(m_mode==NW_CLIENT)
- {
- // Change state to wait for list of characters from server
- m_state = NS_WAIT_FOR_AVAILABLE_CHARACTERS;
- }
- else // Server or no network
- {
- if(m_mode==NW_SERVER)
- {
- // 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);
- }
- // For server and no network:
- // ==========================
- // Prepare the data structures to receive and
- // store information from all clients.
- m_num_local_players.clear();
- // Server (hostid 0) is not included in the num_clients count. So to
- // 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
- m_barrier_count = 0;
- m_state = NS_CHARACTER_SELECT;
- }
-
-} // switchTocharacterSelection
-
-// ----------------------------------------------------------------------------
-/** Called on the client to send the data about the selected kart to the
- * server and wait for confirmation.
- * \param player_id Local id of the player which selected the kart.
- * \param kart_id Identifier of the selected kart. this is used to wait till
- * a message about this kart is received back from the server.
- */
-void NetworkManager::sendCharacterSelected(int player_id,
- const std::string &kart_id)
-{
- if(m_mode==NW_SERVER)
- {
- CharacterConfirmMessage ccm(kart_id, getMyHostId());
- broadcastToClients(ccm);
- }
- else if(m_mode==NW_CLIENT)
- {
- CharacterSelectedMessage m(player_id);
- sendToServer(m);
- // Wait till we receive confirmation about the selected character.
- m_state = NS_WAIT_FOR_KART_CONFIRMATION;
- m_kart_to_confirm = kart_id;
- }
-} // sendCharacterSelected
-
-// ----------------------------------------------------------------------------
-void NetworkManager::waitForRaceInformation()
-{
- m_state = NS_WAIT_FOR_RACE_DATA;
-} // waitForRaceInformation
-
-// ----------------------------------------------------------------------------
-void NetworkManager::worldLoaded()
-{
- if(m_mode==NW_CLIENT)
- {
- WorldLoadedMessage m;
- sendToServer(m);
- m_state = NS_READY_SET_GO_BARRIER;
- }
-} // worldLoaded
-
-// ----------------------------------------------------------------------------
-/** Receive and store the information from sendKartsInformation()
-*/
-void NetworkManager::setupPlayerKartInfo()
-{
- // Not sure if this should be here, but without it extra uncontrolled
- // human players accumulate after each race.
- m_kart_info.clear();
-
- // Get the local kart info
- for(unsigned int i=0; igetNumLocalPlayers(); i++)
- m_kart_info.push_back(race_manager->getLocalKartInfo(i));
-
- // Now sort by (hostid, playerid)
- std::sort(m_kart_info.begin(), m_kart_info.end());
-
- // Set the player kart information
- race_manager->setNumPlayers(m_kart_info.size());
-
- // Set the global player ID for each player
- for(unsigned int i=0; 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
-
-// ----------------------------------------------------------------------------
-/** Sends the information from the race_manager to all clients.
-*/
-void NetworkManager::sendRaceInformationToClients()
-{
- if(m_mode==NW_SERVER)
- {
- setupPlayerKartInfo();
- RaceInfoMessage m(m_kart_info);
- broadcastToClients(m);
- }
- beginReadySetGoBarrier();
-} // sendRaceInformationToClients
-
-// ----------------------------------------------------------------------------
-void NetworkManager::beginReadySetGoBarrier()
-{
- m_state = NS_READY_SET_GO_BARRIER;
- m_barrier_count = 0;
- if(m_num_clients==0) m_state = NS_RACING;
-} // beginReadySetGoBarrier
-// ----------------------------------------------------------------------------
-void NetworkManager::sendConnectMessage()
-{
- ConnectMessage msg;
- sendToServer(msg);
-} // sendConnectMessage
-// ----------------------------------------------------------------------------
-/*** Send all kart controls and kart positions to all clients
-*/
-void NetworkManager::sendUpdates()
-{
- if(m_mode==NW_SERVER)
- {
- race_state->serialise();
- broadcastToClients(*race_state);
- }
- else if(m_mode==NW_CLIENT)
- {
- KartControlMessage m;
- sendToServer(m);
- }
-} // 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;
- bool correct=true;
-
- for(int i=0; ienterRaceOverState();
- return;
- }
- race_state->receive(event.packet);
- }
- } // for istopListening();
else
+ m_localhost->startListening();
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::notifyEvent(Event* event)
+{
+ Log::verbose("NetworkManager", "EVENT received of type %d", (int)(event->type));
+ STKPeer* peer = *event->peer;
+ if (event->type == EVENT_TYPE_CONNECTED)
{
- broadcastToClients(m);
+ Log::info("NetworkManager", "A client has just connected. There are now %lu peers.", m_peers.size() + 1);
+ Log::debug("NetworkManager", "Addresses are : %lx, %lx, %lx", event->peer, *event->peer, peer);
+ // create the new peer:
+ m_peers.push_back(peer);
}
-} // sendRaceResultAck
+ if (event->type == EVENT_TYPE_MESSAGE)
+ {
+ uint32_t addr = peer->getAddress();
+ Log::verbose("NetworkManager", "Message, Sender : %i.%i.%i.%i, message = \"%s\"",
+ ((addr>>24)&0xff),
+ ((addr>>16)&0xff),
+ ((addr>>8)&0xff),
+ (addr&0xff), event->data.c_str());
+
+ }
+
+ // notify for the event now.
+ ProtocolManager::getInstance()->notifyEvent(event);
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::sendPacket(STKPeer* peer, const NetworkString& data, bool reliable)
+{
+ if (peer)
+ peer->sendPacket(data, reliable);
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::sendPacketExcept(STKPeer* peer, const NetworkString& data, bool reliable)
+{
+ for (unsigned int i = 0; i < m_peers.size(); i++)
+ {
+ STKPeer* p = m_peers[i];
+ if (!p->isSamePeer(peer))
+ {
+ p->sendPacket(data, reliable);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+GameSetup* NetworkManager::setupNewGame()
+{
+ if (m_game_setup)
+ delete m_game_setup;
+ m_game_setup = NULL;
+ m_game_setup = new GameSetup();
+ return m_game_setup;
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::disconnected()
+{
+ // delete the game setup
+ if (m_game_setup)
+ delete m_game_setup;
+ m_game_setup = NULL;
+
+ // remove all peers
+ for (unsigned int i = 0; i < m_peers.size(); i++)
+ {
+ delete m_peers[i];
+ m_peers[i] = NULL;
+ }
+ m_peers.clear();
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::setLogin(std::string username, std::string password)
+{
+ m_player_login.username = username;
+ m_player_login.password = password;
+}
+
+//-----------------------------------------------------------------------------
+
+void NetworkManager::setPublicAddress(TransportAddress addr)
+{
+ m_public_address = addr;
+}
+//-----------------------------------------------------------------------------
+
+void NetworkManager::removePeer(STKPeer* peer)
+{
+ if (!peer || !peer->exists()) // peer does not exist (already removed)
+ return;
+ Log::debug("NetworkManager", "Disconnected host: %i.%i.%i.%i:%i",
+ peer->getAddress()>>24&0xff,
+ peer->getAddress()>>16&0xff,
+ peer->getAddress()>>8&0xff,
+ peer->getAddress()&0xff,
+ peer->getPort());
+ // remove the peer:
+ bool removed = false;
+ for (unsigned int i = 0; i < m_peers.size(); i++)
+ {
+ if (m_peers[i]->isSamePeer(peer) && !removed) // remove only one
+ {
+ delete m_peers[i];
+ m_peers.erase(m_peers.begin()+i, m_peers.begin()+i+1);
+ Log::verbose("NetworkManager", "The peer has been removed from the Network Manager.");
+ removed = true;
+ }
+ else if (m_peers[i]->isSamePeer(peer))
+ {
+ Log::fatal("NetworkManager", "Multiple peers match the disconnected one.");
+ }
+ }
+ if (!removed)
+ Log::warn("NetworkManager", "The peer that has been disconnected was not registered by the Network Manager.");
+
+ Log::info("NetworkManager", "Somebody is now disconnected. There are now %lu peers.", m_peers.size());
+}
+
+//-----------------------------------------------------------------------------
+
+bool NetworkManager::peerExists(TransportAddress peer)
+{
+ return m_localhost->peerExists(peer);
+}
+
+//-----------------------------------------------------------------------------
+
+bool NetworkManager::isConnectedTo(TransportAddress peer)
+{
+ return m_localhost->isConnectedTo(peer);
+}
diff --git a/src/network/network_manager.hpp b/src/network/network_manager.hpp
index 83d55f556..6d859151c 100644
--- a/src/network/network_manager.hpp
+++ b/src/network/network_manager.hpp
@@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
+// Copyright (C) 2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -16,107 +16,71 @@
// 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_NETWORK_MANAGER_HPP
-#define HEADER_NETWORK_MANAGER_HPP
+#ifndef NETWORKMANAGER_HPP
+#define NETWORKMANAGER_HPP
+
+#include "network/stk_peer.hpp"
+#include "network/stk_host.hpp"
+
+#include "network/protocol_manager.hpp"
+#include "network/singleton.hpp"
+#include "network/types.hpp"
+#include "network/event.hpp"
+#include "network/game_setup.hpp"
-#include
#include
-#include "enet/enet.h"
-
-#include "network/remote_kart_info.hpp"
-
-
-class Message;
-
-class NetworkManager
+class NetworkManager : public Singleton
{
-public:
- // The mode the network manager is operating in
- enum NetworkMode {NW_SERVER, NW_CLIENT, NW_NONE};
+ friend class Singleton;
+ public:
+ virtual void run();
+ virtual void reset();
- // States for the finite state machine. First for server:
- enum NetworkState {NS_MAIN_MENU, // before char sel gui
- NS_ACCEPT_CONNECTIONS, // server: accept connections
- NS_WAIT_FOR_AVAILABLE_CHARACTERS, // client: wait for list
- NS_ALL_REMOTE_CHARACTERS_DONE, // server: all client data received
- NS_WAIT_FOR_KART_CONFIRMATION, // client: wait for confirmation
- // if character selection was ok
- NS_KART_CONFIRMED, // Character was confirmed
- NS_WAIT_FOR_RACE_DATA, // client: wait for race info
- NS_READY_SET_GO_BARRIER, // c&s: barrier before r.s.g.
- NS_CHARACTER_SELECT, // c&s: character select in progress
- NS_LOADING_WORLD, // client: loading world
- NS_RACING,
- NS_WAIT_FOR_RACE_RESULT, // clients: waiting for race results
- NS_RACE_RESULT_BARRIER , // Wait till all ack results
- NS_RACE_RESULT_BARRIER_OVER // Barrier is over, goto next state
- };
-private:
+ // network management functions
+ virtual bool connect(TransportAddress peer);
+ virtual void setManualSocketsMode(bool manual);
- NetworkMode m_mode;
- NetworkState m_state;
- unsigned int m_num_clients;
- std::vector 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;
+ // message/packets related functions
+ virtual void notifyEvent(Event* event);
+ virtual void sendPacket(const NetworkString& data, bool reliable = true) = 0;
+ virtual void sendPacket(STKPeer* peer, const NetworkString& data, bool reliable = true);
+ virtual void sendPacketExcept(STKPeer* peer, const NetworkString& data, bool reliable = true);
- ENetHost *m_host; // me
- ENetPeer *m_server; // (clients only)
- std::vector m_clients; // (server only) pos in vector is client host_id
- /** Name of the kart that a client is waiting for confirmation for. */
- std::string m_kart_to_confirm;
+ // Game related functions
+ virtual GameSetup* setupNewGame(); //!< Creates a new game setup and returns it
+ virtual void disconnected(); //!< Called when you leave a server
- bool initServer();
- bool initClient();
- void handleNewConnection(ENetEvent *event);
- void handleMessageAtServer(ENetEvent *event);
- void handleMessageAtClient(ENetEvent *event);
- void handleDisconnection(ENetEvent *event);
- // the first cast to long avoid compiler errors on 64 bit systems
- // about lost precision, then cast long to int to get the right type
- unsigned int getHostId(ENetPeer *p) const {return (int)(long)p->data; }
+ // raw data management
+ void setLogin(std::string username, std::string password);
+ void setPublicAddress(TransportAddress addr);
+ void removePeer(STKPeer* peer);
- void sendToServer(Message &m);
- void broadcastToClients(Message &m);
-public:
- NetworkManager();
- ~NetworkManager();
- void setMode(NetworkMode m) {m_mode = m; }
- NetworkMode getMode() const {return m_mode; }
- void becomeServer();
- void becomeClient();
- void setState(NetworkState s) {m_state = s; }
- NetworkState getState() const {return m_state; }
- 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];}
- bool initialiseConnections();
- void update(float dt);
+ // getters
+ virtual bool peerExists(TransportAddress peer);
+ virtual bool isConnectedTo(TransportAddress peer);
- void disableNetworking();
- void sendConnectMessage(); // client send initial info to server
- void initCharacterDataStructures();
- void sendCharacterSelected(int player_id, const std::string &kartid);
- void waitForRaceInformation();
- void worldLoaded();
- void setupPlayerKartInfo();
- void beginReadySetGoBarrier();
- void sendRaceInformationToClients();
- void sendUpdates();
- void receiveUpdates();
- void waitForClientData();
- void sendRaceResults();
- void beginRaceResultBarrier();
- void sendRaceResultAck(char menu_selection=-1);
+ virtual bool isServer() = 0;
+ inline bool isClient() { return !isServer(); }
+ bool isPlayingOnline() { return m_playing_online; }
+ STKHost* getHost() { return m_localhost; }
+ std::vector getPeers() { return m_peers; }
+ unsigned int getPeerCount() { return m_peers.size(); }
+ TransportAddress getPublicAddress() { return m_public_address; }
+ GameSetup* getGameSetup() { return m_game_setup; }
+
+ protected:
+ NetworkManager();
+ virtual ~NetworkManager();
+
+ // protected members
+ std::vector m_peers;
+ STKHost* m_localhost;
+ bool m_playing_online;
+ GameSetup* m_game_setup;
+
+ TransportAddress m_public_address;
+ PlayerLogin m_player_login;
};
-extern NetworkManager *network_manager;
-
-#endif
+#endif // NETWORKMANAGER_HPP
diff --git a/src/network/network_string.cpp b/src/network/network_string.cpp
new file mode 100644
index 000000000..251c98fb5
--- /dev/null
+++ b/src/network/network_string.cpp
@@ -0,0 +1,8 @@
+#include "network/network_string.hpp"
+
+NetworkString operator+(NetworkString const& a, NetworkString const& b)
+{
+ NetworkString ns(a);
+ ns += b;
+ return ns;
+}
diff --git a/src/network/network_string.hpp b/src/network/network_string.hpp
new file mode 100644
index 000000000..83e3eb59a
--- /dev/null
+++ b/src/network/network_string.hpp
@@ -0,0 +1,230 @@
+#ifndef NETWORK_STRING_HPP
+#define NETWORK_STRING_HPP
+
+#include "utils/types.hpp"
+
+#include
+#include
+#include
+#include
+
+typedef unsigned char uchar;
+
+class NetworkString
+{
+ union {
+ float f;
+ uint8_t i[4];
+ } f_as_i; // float as integer
+ union {
+ double d;
+ uint8_t i[8];
+ } d_as_i; // double as integer
+ public:
+ NetworkString() { }
+ NetworkString(const uint8_t& value) { m_string.push_back(value); }
+ NetworkString(NetworkString const& copy) { m_string = copy.m_string; }
+ NetworkString(const std::string & value) { m_string = std::vector(value.begin(), value.end()); }
+
+ NetworkString& removeFront(int size)
+ {
+ m_string.erase(m_string.begin(), m_string.begin()+size);
+ return *this;
+ }
+ NetworkString& remove(int pos, int size)
+ {
+ m_string.erase(m_string.begin()+pos, m_string.begin()+pos+size);
+ return *this;
+ }
+
+ uint8_t operator[](const int& pos) const
+ {
+ return getUInt8(pos);
+ }
+
+ NetworkString& addUInt8(const uint8_t& value)
+ {
+ m_string.push_back(value);
+ return *this;
+ }
+ inline NetworkString& ai8(const uint8_t& value) { return addUInt8(value); }
+ NetworkString& addUInt16(const uint16_t& value)
+ {
+ m_string.push_back((value>>8)&0xff);
+ m_string.push_back(value&0xff);
+ return *this;
+ }
+ inline NetworkString& ai16(const uint16_t& value) { return addUInt16(value); }
+ NetworkString& addUInt32(const uint32_t& value)
+ {
+ m_string.push_back((value>>24)&0xff);
+ m_string.push_back((value>>16)&0xff);
+ m_string.push_back((value>>8)&0xff);
+ m_string.push_back(value&0xff);
+ return *this;
+ }
+ inline NetworkString& ai32(const uint32_t& value) { return addUInt32(value); }
+ NetworkString& addInt(const int& value)
+ {
+ m_string.push_back((value>>24)&0xff);
+ m_string.push_back((value>>16)&0xff);
+ m_string.push_back((value>>8)&0xff);
+ m_string.push_back(value&0xff);
+ return *this;
+ }
+ inline NetworkString& ai(const int& value) { return addInt(value); }
+ NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION
+ {
+ assert(sizeof(float)==4);
+ f_as_i.f = value;
+ m_string.push_back(f_as_i.i[0]);
+ m_string.push_back(f_as_i.i[1]);
+ m_string.push_back(f_as_i.i[2]);
+ m_string.push_back(f_as_i.i[3]);
+ return *this;
+ }
+ inline NetworkString& af(const float& value) { return addFloat(value); }
+ NetworkString& addDouble(const double& value) //!< BEWARE OF PRECISION
+ {
+ assert(sizeof(double)==8);
+ d_as_i.d = value;
+ m_string.push_back(d_as_i.i[0]);
+ m_string.push_back(d_as_i.i[1]);
+ m_string.push_back(d_as_i.i[2]);
+ m_string.push_back(d_as_i.i[3]);
+ m_string.push_back(d_as_i.i[4]);
+ m_string.push_back(d_as_i.i[5]);
+ m_string.push_back(d_as_i.i[6]);
+ m_string.push_back(d_as_i.i[7]);
+ return *this;
+ }
+ inline NetworkString& ad(const double& value) { return addDouble(value); }
+ NetworkString& addChar(const char& value)
+ {
+ m_string.push_back((uint8_t)(value));
+ return *this;
+ }
+ inline NetworkString& ac(const char& value) { return addChar(value); }
+
+ NetworkString& addString(const std::string& value)
+ {
+ for (unsigned int i = 0; i < value.size(); i++)
+ m_string.push_back((uint8_t)(value[i]));
+ return *this;
+ }
+ inline NetworkString& as(const std::string& value) { return addString(value); }
+
+ NetworkString& operator+=(NetworkString const& value)
+ {
+ m_string.insert( m_string.end(), value.m_string.begin(), value.m_string.end() );
+ return *this;
+ }
+
+ const char* c_str() const
+ {
+ std::string str(m_string.begin(), m_string.end());
+ return str.c_str();
+ }
+ int size() const
+ {
+ return m_string.size();
+ }
+
+ template
+ T get(int pos) const
+ {
+ int a = n;
+ T result = 0;
+ while(a--)
+ {
+ result <<= 8; // offset one byte
+ result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data to result
+ }
+ return result;
+ }
+
+ inline int getInt(int pos = 0) const { return get(pos); }
+ inline uint32_t getUInt(int pos = 0) const { return get(pos); }
+ inline uint32_t getUInt32(int pos = 0) const { return get(pos); }
+ inline uint16_t getUInt16(int pos = 0) const { return get(pos); }
+ inline uint8_t getUInt8(int pos = 0) const { return get(pos); }
+ inline char getChar(int pos = 0) const { return get(pos); }
+ inline unsigned char getUChar(int pos = 0) const { return get(pos); }
+ std::string getString(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); }
+
+ inline int gi(int pos = 0) const { return get(pos); }
+ inline uint32_t gui(int pos = 0) const { return get(pos); }
+ inline uint32_t gui32(int pos = 0) const { return get(pos); }
+ inline uint16_t gui16(int pos = 0) const { return get(pos); }
+ inline uint8_t gui8(int pos = 0) const { return get(pos); }
+ inline char gc(int pos = 0) const { return get(pos); }
+ inline unsigned char guc(int pos = 0) const { return get(pos); }
+ std::string gs(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); }
+
+ double getDouble(int pos = 0) //!< BEWARE OF PRECISION
+ {
+ for (int i = 0; i < 8; i++)
+ d_as_i.i[i] = m_string[pos+i];
+ return d_as_i.d;
+ }
+ float getFloat(int pos = 0) //!< BEWARE OF PRECISION
+ {
+ for (int i = 0; i < 4; i++)
+ f_as_i.i[i] = m_string[pos+i];
+ return f_as_i.f;
+ }
+
+ //! Functions to get while removing
+ template
+ T getAndRemove(int pos)
+ {
+ int a = n;
+ T result = 0;
+ while(a--)
+ {
+ result <<= 8; // offset one byte
+ result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data
+ }
+ remove(pos,n);
+ return result;
+ }
+
+ inline int getAndRemoveInt(int pos = 0) { return getAndRemove(pos); }
+ inline uint32_t getAndRemoveUInt(int pos = 0) { return getAndRemove(pos); }
+ inline uint32_t getAndRemoveUInt32(int pos = 0) { return getAndRemove(pos); }
+ inline uint16_t getAndRemoveUInt16(int pos = 0) { return getAndRemove(pos); }
+ inline uint8_t getAndRemoveUInt8(int pos = 0) { return getAndRemove(pos); }
+ inline char getAndRemoveChar(int pos = 0) { return getAndRemove(pos); }
+ inline unsigned char getAndRemoveUChar(int pos = 0) { return getAndRemove(pos); }
+ double getAndRemoveDouble(int pos = 0) //!< BEWARE OF PRECISION
+ {
+ for (int i = 0; i < 8; i++)
+ d_as_i.i[i] = m_string[pos+i];
+ return d_as_i.d;
+ remove(pos, 8);
+ }
+ float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION
+ {
+ for (int i = 0; i < 4; i++)
+ f_as_i.i[i] = m_string[pos+i];
+ return f_as_i.f;
+ remove(pos, 4);
+ }
+
+ inline NetworkString& gui8(uint8_t* dst) { *dst = getAndRemoveUInt8(0); return *this; }
+ inline NetworkString& gui16(uint16_t* dst) { *dst = getAndRemoveUInt16(0); return *this; }
+ inline NetworkString& gui32(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; }
+ inline NetworkString& gui(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; }
+ inline NetworkString& gi(int* dst) { *dst = getAndRemoveInt(0); return *this; }
+ inline NetworkString& gc(char* dst) { *dst = getAndRemoveChar(0); return *this; }
+ inline NetworkString& guc(uchar* dst) { *dst = getAndRemoveUChar(0); return *this; }
+ inline NetworkString& gd(double* dst) { *dst = getAndRemoveDouble(0); return *this; }
+ inline NetworkString& gf(float* dst) { *dst = getAndRemoveFloat(0); return *this; }
+
+ protected:
+ std::vector m_string;
+};
+
+NetworkString operator+(NetworkString const& a, NetworkString const& b);
+
+#endif // NETWORK_STRING_HPP
diff --git a/src/network/network_world.cpp b/src/network/network_world.cpp
new file mode 100644
index 000000000..ad7407eda
--- /dev/null
+++ b/src/network/network_world.cpp
@@ -0,0 +1,40 @@
+#include "network/network_world.hpp"
+
+#include "network/protocol_manager.hpp"
+#include "network/protocols/synchronization_protocol.hpp"
+#include "network/protocols/controller_events_protocol.hpp"
+#include "modes/world.hpp"
+
+#include "karts/controller/controller.hpp"
+
+NetworkWorld::NetworkWorld()
+{
+ m_running = false;
+}
+
+NetworkWorld::~NetworkWorld()
+{
+}
+
+void NetworkWorld::update(float dt)
+{
+ SynchronizationProtocol* protocol = static_cast(
+ ProtocolManager::getInstance()->getProtocol(PROTOCOL_SYNCHRONIZATION));
+ if (protocol) // if this protocol exists, that's that we play online
+ {
+ Log::debug("NetworkWorld", "Coutdown value is %f", protocol->getCountdown());
+ if (protocol->getCountdown() > 0.0)
+ {
+ return;
+ }
+ }
+ World::getWorld()->updateWorld(dt);
+}
+
+void NetworkWorld::controllerAction(Controller* controller, PlayerAction action, int value)
+{
+ ControllerEventsProtocol* protocol = static_cast(
+ ProtocolManager::getInstance()->getProtocol(PROTOCOL_CONTROLLER_EVENTS));
+ if (protocol)
+ protocol->controllerAction(controller, action, value);
+}
diff --git a/src/network/network_world.hpp b/src/network/network_world.hpp
new file mode 100644
index 000000000..bce5666f6
--- /dev/null
+++ b/src/network/network_world.hpp
@@ -0,0 +1,37 @@
+#ifndef NETWORK_WORLD_HPP
+#define NETWORK_WORLD_HPP
+
+#include "network/singleton.hpp"
+#include "input/input.hpp"
+#include