merging hilnius's branch
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/uni@13394 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
commit
ea2b52a663
32
data/gui/online/lobby_settings.stkgui
Normal file
32
data/gui/online/lobby_settings.stkgui
Normal file
@ -0,0 +1,32 @@
|
||||
<stkgui>
|
||||
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
|
||||
|
||||
<header text_align="center" width="80%" align="center" I18N="In the lobby settings screen" text="Lobby Settings"/>
|
||||
<spacer height="15" width="10"/>
|
||||
<box proportion="4" width="90%" layout="vertical-row" align="center">
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit" >
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the lobby settings screen" text="Name of the server"/>
|
||||
<textbox proportion="2" id="name" I18N="In the login dialog"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the lobby settings screen" text="Max. number of players"/>
|
||||
<gauge id="max_players" proportion="2" min_value="2" max_value="12"/>
|
||||
</div>
|
||||
</div>
|
||||
</box>
|
||||
|
||||
<spacer width="10" height="7%"/>
|
||||
|
||||
<bottombar x="2%" width="96%" height="10%" layout="horizontal-row">
|
||||
|
||||
</bottombar>
|
||||
|
||||
</div>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
</stkgui>
|
@ -2,25 +2,20 @@
|
||||
// Creates a cone lightbeam effect by smoothing edges
|
||||
// Original idea: http://udn.epicgames.com/Three/VolumetricLightbeamTutorial.html
|
||||
// TODO: Soft edges when it intesects geometry
|
||||
// Some artefacts are still visible
|
||||
|
||||
// Some artefacts are still visible
|
||||
|
||||
uniform sampler2D main_texture;
|
||||
uniform sampler2D tex;
|
||||
uniform float transparency;
|
||||
|
||||
varying vec2 uv;
|
||||
varying vec3 eyeVec;
|
||||
varying vec3 normal;
|
||||
|
||||
void main()
|
||||
{
|
||||
float inter = dot(normal, eyeVec);
|
||||
float m = texture2D(tex, vec2(0.5, uv.y)).r;
|
||||
float alpha = inter * inter * inter * inter * m;
|
||||
|
||||
|
||||
float inter = dot(normal, eyeVec);
|
||||
float m = texture2D(main_texture, vec2(0.5, uv.y)).r;
|
||||
|
||||
|
||||
gl_FragColor = vec4(1.0,1.0,0.8, 1.0);
|
||||
|
||||
|
||||
gl_FragColor.a = inter * inter * inter * inter * m;
|
||||
gl_FragColor = vec4(1.0, 1.0, 0.8, alpha);
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Jean-manuel clemencon supertuxkart
|
||||
// Creates a cone lightbeam effect by smoothing edges
|
||||
|
||||
|
||||
uniform float time;
|
||||
varying vec2 uv;
|
||||
varying vec3 eyeVec;
|
||||
varying vec3 normal;
|
||||
@ -10,13 +8,12 @@ varying vec3 normal;
|
||||
void main()
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 viewp = gl_ModelViewMatrix * gl_Vertex;
|
||||
|
||||
eyeVec = normalize(-viewp).xyz;
|
||||
normal = gl_NormalMatrix * gl_Normal;
|
||||
|
||||
eyeVec = normalize(-gl_Position).xyz;
|
||||
normal = gl_NormalMatrix * gl_Normal;
|
||||
gl_Position = ftransform();
|
||||
|
||||
gl_Position = ftransform();
|
||||
|
||||
uv = gl_TexCoord[0].st;
|
||||
uv = gl_TexCoord[0].st;
|
||||
}
|
||||
|
BIN
doc/protocols.xls
Normal file
BIN
doc/protocols.xls
Normal file
Binary file not shown.
@ -49,7 +49,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
|
||||
|
||||
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
|
||||
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
|
||||
if (host -> socket == ENET_SOCKET_NULL || (enet_socket_bind (host -> socket, address) < 0 && address != NULL))
|
||||
{
|
||||
if (host -> socket != ENET_SOCKET_NULL)
|
||||
enet_socket_destroy (host -> socket);
|
||||
|
@ -6,3 +6,4 @@ The following changes have been made:
|
||||
- materialtype override
|
||||
- skies respect Z
|
||||
- partial backport to expose setCurrentRendertime in the scene mgr
|
||||
- a workaround for every other RTTs flipping
|
||||
|
@ -987,7 +987,7 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri
|
||||
else
|
||||
{
|
||||
GLfloat glmat[16];
|
||||
if (isRTT)
|
||||
if (isRTT && CurrentTarget == ERT_FRAME_BUFFER)
|
||||
getGLTextureMatrix(glmat, mat * TextureFlipMatrix);
|
||||
else
|
||||
getGLTextureMatrix(glmat, mat);
|
||||
|
@ -105,6 +105,7 @@ src/karts/controller/ai_base_controller.cpp
|
||||
src/karts/controller/ai_properties.cpp
|
||||
src/karts/controller/controller.cpp
|
||||
src/karts/controller/end_controller.cpp
|
||||
src/karts/controller/network_player_controller.cpp
|
||||
src/karts/controller/player_controller.cpp
|
||||
src/karts/controller/skidding_ai.cpp
|
||||
src/karts/explosion_animation.cpp
|
||||
@ -136,15 +137,39 @@ src/modes/tutorial_world.cpp
|
||||
src/modes/world.cpp
|
||||
src/modes/world_status.cpp
|
||||
src/modes/world_with_rank.cpp
|
||||
src/network/connect_message.cpp
|
||||
src/network/kart_control_message.cpp
|
||||
src/network/kart_update_message.cpp
|
||||
src/network/message.cpp
|
||||
src/network/network_kart.cpp
|
||||
src/network/client_network_manager.cpp
|
||||
src/network/event.cpp
|
||||
src/network/game_setup.cpp
|
||||
src/network/http_functions.cpp
|
||||
src/network/network_interface.cpp
|
||||
src/network/network_manager.cpp
|
||||
src/network/race_info_message.cpp
|
||||
src/network/race_result_message.cpp
|
||||
src/network/race_state.cpp
|
||||
src/network/network_string.cpp
|
||||
src/network/network_world.cpp
|
||||
src/network/protocol.cpp
|
||||
src/network/protocol_manager.cpp
|
||||
src/network/protocols/client_lobby_room_protocol.cpp
|
||||
src/network/protocols/connect_to_peer.cpp
|
||||
src/network/protocols/connect_to_server.cpp
|
||||
src/network/protocols/controller_events_protocol.cpp
|
||||
src/network/protocols/game_events_protocol.cpp
|
||||
src/network/protocols/get_peer_address.cpp
|
||||
src/network/protocols/get_public_address.cpp
|
||||
src/network/protocols/hide_public_address.cpp
|
||||
src/network/protocols/kart_update_protocol.cpp
|
||||
src/network/protocols/lobby_room_protocol.cpp
|
||||
src/network/protocols/ping_protocol.cpp
|
||||
src/network/protocols/quick_join_protocol.cpp
|
||||
src/network/protocols/request_connection.cpp
|
||||
src/network/protocols/server_lobby_room_protocol.cpp
|
||||
src/network/protocols/show_public_address.cpp
|
||||
src/network/protocols/start_game_protocol.cpp
|
||||
src/network/protocols/start_server.cpp
|
||||
src/network/protocols/stop_server.cpp
|
||||
src/network/protocols/synchronization_protocol.cpp
|
||||
src/network/server_network_manager.cpp
|
||||
src/network/stk_host.cpp
|
||||
src/network/stk_peer.cpp
|
||||
src/network/types.cpp
|
||||
src/online/current_user.cpp
|
||||
src/online/http_manager.cpp
|
||||
src/online/messages.cpp
|
||||
@ -200,6 +225,9 @@ src/states_screens/help_screen_4.cpp
|
||||
src/states_screens/kart_selection.cpp
|
||||
src/states_screens/main_menu_screen.cpp
|
||||
src/states_screens/networking_lobby.cpp
|
||||
src/states_screens/networking_lobby_settings.cpp
|
||||
src/states_screens/network_kart_selection.cpp
|
||||
src/states_screens/offline_kart_selection.cpp
|
||||
src/states_screens/online_screen.cpp
|
||||
src/states_screens/options_screen_audio.cpp
|
||||
src/states_screens/options_screen_input2.cpp
|
||||
@ -368,6 +396,7 @@ src/karts/controller/ai_properties.hpp
|
||||
src/karts/controller/controller.hpp
|
||||
src/karts/controller/end_controller.hpp
|
||||
src/karts/controller/kart_control.hpp
|
||||
src/karts/controller/network_player_controller.hpp
|
||||
src/karts/controller/player_controller.hpp
|
||||
src/karts/controller/skidding_ai.hpp
|
||||
src/karts/explosion_animation.hpp
|
||||
@ -398,25 +427,41 @@ src/modes/tutorial_world.hpp
|
||||
src/modes/world.hpp
|
||||
src/modes/world_status.hpp
|
||||
src/modes/world_with_rank.hpp
|
||||
src/network/character_confirm_message.hpp
|
||||
src/network/character_info_message.hpp
|
||||
src/network/character_selected_message.hpp
|
||||
src/network/connect_message.hpp
|
||||
src/network/flyable_info.hpp
|
||||
src/network/item_info.hpp
|
||||
src/network/kart_control_message.hpp
|
||||
src/network/kart_update_message.hpp
|
||||
src/network/message.hpp
|
||||
src/network/network_kart.hpp
|
||||
src/network/client_network_manager.hpp
|
||||
src/network/event.hpp
|
||||
src/network/game_setup.hpp
|
||||
src/network/http_functions.hpp
|
||||
src/network/network_interface.hpp
|
||||
src/network/network_manager.hpp
|
||||
src/network/num_players_message.hpp
|
||||
src/network/race_info_message.hpp
|
||||
src/network/race_result_ack_message.hpp
|
||||
src/network/race_result_message.hpp
|
||||
src/network/race_start_message.hpp
|
||||
src/network/race_state.hpp
|
||||
src/network/network_string.hpp
|
||||
src/network/network_world.hpp
|
||||
src/network/protocol.hpp
|
||||
src/network/protocol_manager.hpp
|
||||
src/network/protocols/client_lobby_room_protocol.hpp
|
||||
src/network/protocols/connect_to_peer.hpp
|
||||
src/network/protocols/connect_to_server.hpp
|
||||
src/network/protocols/controller_events_protocol.hpp
|
||||
src/network/protocols/game_events_protocol.hpp
|
||||
src/network/protocols/get_peer_address.hpp
|
||||
src/network/protocols/get_public_address.hpp
|
||||
src/network/protocols/hide_public_address.hpp
|
||||
src/network/protocols/kart_update_protocol.hpp
|
||||
src/network/protocols/lobby_room_protocol.hpp
|
||||
src/network/protocols/ping_protocol.hpp
|
||||
src/network/protocols/quick_join_protocol.hpp
|
||||
src/network/protocols/request_connection.hpp
|
||||
src/network/protocols/server_lobby_room_protocol.hpp
|
||||
src/network/protocols/show_public_address.hpp
|
||||
src/network/protocols/start_game_protocol.hpp
|
||||
src/network/protocols/start_server.hpp
|
||||
src/network/protocols/stop_server.hpp
|
||||
src/network/protocols/synchronization_protocol.hpp
|
||||
src/network/remote_kart_info.hpp
|
||||
src/network/world_loaded_message.hpp
|
||||
src/network/server_network_manager.hpp
|
||||
src/network/singleton.hpp
|
||||
src/network/stk_host.hpp
|
||||
src/network/stk_peer.hpp
|
||||
src/network/types.hpp
|
||||
src/online/current_user.hpp
|
||||
src/online/http_manager.hpp
|
||||
src/online/messages.hpp
|
||||
@ -475,6 +520,9 @@ src/states_screens/help_screen_4.hpp
|
||||
src/states_screens/kart_selection.hpp
|
||||
src/states_screens/main_menu_screen.hpp
|
||||
src/states_screens/networking_lobby.hpp
|
||||
src/states_screens/networking_lobby_settings.hpp
|
||||
src/states_screens/network_kart_selection.hpp
|
||||
src/states_screens/offline_kart_selection.hpp
|
||||
src/states_screens/online_screen.hpp
|
||||
src/states_screens/options_screen_audio.hpp
|
||||
src/states_screens/options_screen_input2.hpp
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <WinSock2.h>
|
||||
#endif
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
@ -282,7 +282,7 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
// race_manager->getNumLocalPlayers(), buffer->isPositional());
|
||||
|
||||
#if HAVE_OGGVORBIS
|
||||
assert( alIsBuffer(buffer->getBufferID()) );
|
||||
//assert( alIsBuffer(buffer->getBufferID()) ); crashes on server
|
||||
SFXBase* sfx = new SFXOpenAL(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
#else
|
||||
SFXBase* sfx = new DummySFX(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
|
@ -487,13 +487,15 @@ namespace UserConfigParams
|
||||
// not saved to file
|
||||
|
||||
// ---- Networking
|
||||
PARAM_PREFIX StringUserConfigParam m_server_address
|
||||
PARAM_DEFAULT( StringUserConfigParam("localhost", "server_adress",
|
||||
"Information about last server used") );
|
||||
PARAM_PREFIX IntUserConfigParam m_server_port
|
||||
PARAM_DEFAULT( IntUserConfigParam(2305, "server_port",
|
||||
"Information about last server used") );
|
||||
|
||||
PARAM_DEFAULT( IntUserConfigParam(7321, "server_port",
|
||||
"Information about the port to listen on.") );
|
||||
|
||||
PARAM_PREFIX IntUserConfigParam m_server_max_players
|
||||
PARAM_DEFAULT( IntUserConfigParam(16, "server_max_players",
|
||||
"Maximum number of players on the server.") );
|
||||
|
||||
|
||||
// ---- Graphic Quality
|
||||
PARAM_PREFIX GroupUserConfigParam m_graphics_quality
|
||||
PARAM_DEFAULT( GroupUserConfigParam("GFX",
|
||||
|
@ -485,7 +485,7 @@ namespace GUIEngine
|
||||
|
||||
Used on divs, indicate by how many pixels to pad contents
|
||||
|
||||
|
||||
|
||||
\n
|
||||
<HR>
|
||||
\section code Using the engine in code
|
||||
@ -904,6 +904,25 @@ namespace GUIEngine
|
||||
g_loaded_screens.push_back(cutscene);
|
||||
} // addScreenToList
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void removeScreen(const char* name)
|
||||
{
|
||||
const int screen_amount = g_loaded_screens.size();
|
||||
for(int n=0; n<screen_amount; n++)
|
||||
{
|
||||
if (g_loaded_screens[n].getName() == name)
|
||||
{
|
||||
g_current_screen = g_loaded_screens.get(n);
|
||||
g_current_screen->unload();
|
||||
delete g_current_screen;
|
||||
g_current_screen = NULL;
|
||||
g_loaded_screens.remove(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void reshowCurrentScreen()
|
||||
{
|
||||
|
@ -195,6 +195,8 @@ namespace GUIEngine
|
||||
|
||||
/** \brief Add a screen to the list of screens known by the gui engine */
|
||||
void addScreenToList(Screen* screen);
|
||||
/** \brief Remove a screen from the list of screens known by the gui engine */
|
||||
void removeScreen(const char* name);
|
||||
|
||||
/** \brief Low-level mean to change current screen.
|
||||
* \note Do not use directly. Use a state manager instead to get higher-level functionnality.
|
||||
|
@ -61,6 +61,7 @@ namespace GUIEngine
|
||||
template<typename SCREEN>
|
||||
class ScreenSingleton
|
||||
{
|
||||
protected:
|
||||
static SCREEN* singleton;
|
||||
|
||||
public:
|
||||
|
@ -44,8 +44,8 @@ Global
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.debug|Win32.Build.0 = Debug|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.Release|Win32.Build.0 = Release|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-debug|Win32.ActiveCfg = Release|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-debug|Win32.Build.0 = Release|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-debug|Win32.Build.0 = Debug|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-release|Win32.ActiveCfg = wiiuse-release|Win32
|
||||
{B0E92B97-089A-4D5B-BF17-77F1BC5DAEEF}.wiiuse-release|Win32.Build.0 = wiiuse-release|Win32
|
||||
{E08E042A-6C45-411B-92BE-3CC31331019F}.debug|Win32.ActiveCfg = Static lib - Debug|Win32
|
||||
|
@ -164,12 +164,12 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
if (UserConfigParams::m_artist_debug_mode && world)
|
||||
{
|
||||
AbstractKart* kart = world->getLocalPlayerKart(0);
|
||||
|
||||
|
||||
if (control_is_pressed)
|
||||
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
|
||||
else
|
||||
kart->setPowerup(PowerupManager::POWERUP_RUBBERBALL, 10000);
|
||||
|
||||
|
||||
#ifdef FORCE_RESCUE_ON_FIRST_KART
|
||||
// Can be useful for debugging places where the AI gets into
|
||||
// a rescue loop: rescue, drive, crash, rescue to same place
|
||||
@ -181,7 +181,7 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
if (UserConfigParams::m_artist_debug_mode && world)
|
||||
{
|
||||
AbstractKart* kart = world->getLocalPlayerKart(0);
|
||||
|
||||
|
||||
kart->setPowerup(PowerupManager::POWERUP_PLUNGER, 10000);
|
||||
}
|
||||
break;
|
||||
@ -557,7 +557,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
action == PA_MENU_CANCEL ) )
|
||||
{
|
||||
// returns true if the event was handled
|
||||
if (KartSelectionScreen::getInstance()->playerQuit( player ))
|
||||
if (KartSelectionScreen::getRunningInstance()->playerQuit( player ))
|
||||
{
|
||||
return; // we're done here
|
||||
}
|
||||
@ -592,7 +592,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
|
||||
if (device != NULL)
|
||||
{
|
||||
KartSelectionScreen::getInstance()->playerJoin(device,
|
||||
KartSelectionScreen::getRunningInstance()->playerJoin(device,
|
||||
false );
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ XMLNode::XMLNode(const std::string &filename)
|
||||
m_file_name = filename;
|
||||
|
||||
io::IXMLReader *xml = file_manager->createXMLReader(filename);
|
||||
|
||||
|
||||
if (xml == NULL)
|
||||
{
|
||||
throw std::runtime_error("Cannot find file "+filename);
|
||||
@ -319,6 +319,22 @@ int XMLNode::get(const std::string &attribute, int64_t *value) const
|
||||
} // get(int64_t)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int XMLNode::get(const std::string &attribute, uint16_t *value) const
|
||||
{
|
||||
std::string s;
|
||||
if(!get(attribute, &s)) return 0;
|
||||
|
||||
if (!StringUtils::parseString<uint16_t>(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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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).
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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() {}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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];
|
||||
|
368
src/karts/controller/network_player_controller.cpp
Normal file
368
src/karts/controller/network_player_controller.cpp
Normal file
@ -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()<p)
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
//have the kart that did the passing beep.
|
||||
//I'm not sure if this method of finding the passing kart is fail-safe.
|
||||
for(unsigned int i = 0 ; i < world->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
|
48
src/karts/controller/network_player_controller.hpp
Normal file
48
src/karts/controller/network_player_controller.hpp
Normal file
@ -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
|
@ -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
|
||||
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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; /**<Velocity in kart coordinates. */
|
||||
|
108
src/main.cpp
108
src/main.cpp
@ -170,6 +170,12 @@
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/server_network_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/server_lobby_room_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
#include "race/highscore_manager.hpp"
|
||||
#include "race/history.hpp"
|
||||
@ -390,6 +396,7 @@ void cmdLineHelp (char* invocation)
|
||||
" --profile-time=n Enable automatic driven profile mode for n "
|
||||
"seconds.\n"
|
||||
" --no-graphics Do not display the actual race.\n"
|
||||
" --with-profile Enables the profile mode.\n"
|
||||
" --demo-mode t Enables demo mode after t seconds idle time in "
|
||||
"main menu.\n"
|
||||
" --demo-tracks t1,t2 List of tracks to be used in demo mode. No\n"
|
||||
@ -401,13 +408,11 @@ void cmdLineHelp (char* invocation)
|
||||
// " --history=n Replay history file 'history.dat' using:\n"
|
||||
// " n=1: recorded positions\n"
|
||||
// " n=2: recorded key strokes\n"
|
||||
//" --server[=port] This is the server (running on the specified "
|
||||
// "port).\n"
|
||||
//" --client=ip This is a client, connect to the specified ip"
|
||||
// " address.\n"
|
||||
//" --port=n Port number to use.\n"
|
||||
//" --numclients=n Number of clients to wait for (server "
|
||||
// "only).\n"
|
||||
" --server Start a server (not a playing client).\n"
|
||||
" --login=s Automatically sign in (set the login).\n"
|
||||
" --password=s Automatically sign in (set the password).\n"
|
||||
" --port=n Port number to use.\n"
|
||||
" --max-players=n Maximum number of clients (server only).\n"
|
||||
" --no-console Does not write messages in the console but to\n"
|
||||
" stdout.log.\n"
|
||||
" --console Write messages in the console and files\n"
|
||||
@ -604,6 +609,9 @@ int handleCmdLine(int argc, char **argv)
|
||||
int n;
|
||||
char s[1024];
|
||||
|
||||
bool try_login = false;
|
||||
irr::core::stringw login, password;
|
||||
|
||||
for(int i=1; i<argc; i++)
|
||||
{
|
||||
|
||||
@ -680,23 +688,27 @@ int handleCmdLine(int argc, char **argv)
|
||||
{
|
||||
AIBaseController::enableDebug();
|
||||
}
|
||||
else if(sscanf(argv[i], "--server=%d",&n)==1)
|
||||
else if(sscanf(argv[i], "--port=%d",&n))
|
||||
{
|
||||
network_manager->setMode(NetworkManager::NW_SERVER);
|
||||
UserConfigParams::m_server_port = n;
|
||||
}
|
||||
else if( !strcmp(argv[i], "--server") )
|
||||
{
|
||||
network_manager->setMode(NetworkManager::NW_SERVER);
|
||||
NetworkManager::getInstance<ServerNetworkManager>();
|
||||
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<ClientNetworkManager>();
|
||||
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<PlayerProfile>& players = UserConfigParams::m_all_players;
|
||||
if (UserConfigParams::m_default_player.toString().size() > 0)
|
||||
for (int n=0; n<players.size(); n++)
|
||||
if (players[n].getName() == UserConfigParams::m_default_player.toString())
|
||||
unlock_manager->setCurrentSlot(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();
|
||||
|
@ -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<NetworkWorld>()->isRunning())
|
||||
NetworkWorld::getInstance<NetworkWorld>()->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
|
||||
|
@ -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 );
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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_id<m_karts.size(); kart_id++)
|
||||
{
|
||||
for(unsigned int rescue_pos=0;
|
||||
for(unsigned int rescue_pos=0;
|
||||
rescue_pos<getNumberOfRescuePositions();
|
||||
rescue_pos++)
|
||||
{
|
||||
@ -650,7 +644,7 @@ void World::moveKartTo(AbstractKart* kart, const btTransform &transform)
|
||||
kart->getBody()->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; i<m_karts.size(); i++)
|
||||
if(m_karts[i]->getController()->isPlayerController())
|
||||
if(m_karts[i]->getController()->isPlayerController() ||
|
||||
m_karts[i]->getController()->isNetworkController())
|
||||
{
|
||||
count++;
|
||||
if(count==n) return m_karts[i];
|
||||
|
@ -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; }
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
#include <irrlicht.h>
|
||||
|
||||
@ -112,8 +111,6 @@ void WorldStatus::enterRaceOverState()
|
||||
*/
|
||||
void WorldStatus::terminateRace()
|
||||
{
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
network_manager->sendRaceResults();
|
||||
} // terminateRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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 <string>
|
||||
|
||||
#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
|
@ -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<std::string> 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<std::string> all_karts;
|
||||
all_karts = getStringVector();
|
||||
kart_properties_manager->setUnavailableKarts(all_karts);
|
||||
}
|
||||
}; // CharacterInfoMessage
|
||||
#endif
|
@ -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
|
135
src/network/client_network_manager.cpp
Normal file
135
src/network/client_network_manager.cpp
Normal file
@ -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 <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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<ClientLobbyRoomProtocol*>(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];
|
||||
}
|
50
src/network/client_network_manager.hpp
Normal file
50
src/network/client_network_manager.hpp
Normal file
@ -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<NetworkManager>;
|
||||
public:
|
||||
static ClientNetworkManager* getInstance()
|
||||
{
|
||||
return Singleton<NetworkManager>::getInstance<ClientNetworkManager>();
|
||||
}
|
||||
|
||||
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
|
@ -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 <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#ifndef WIN32
|
||||
# include <unistd.h>
|
||||
#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<std::string> &all_tracks =
|
||||
track_manager->getAllTrackIdentifiers();
|
||||
std::vector<std::string> 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<std::string> all_tracks = getStringVector();
|
||||
std::vector<std::string> 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
|
99
src/network/event.cpp
Normal file
99
src/network/event.cpp
Normal file
@ -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 <string.h>
|
||||
|
||||
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<STKPeer*> 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);
|
||||
}
|
||||
|
76
src/network/event.hpp
Normal file
76
src/network/event.hpp
Normal file
@ -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
|
@ -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
|
||||
|
145
src/network/game_setup.cpp
Normal file
145
src/network/game_setup.cpp
Normal file
@ -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;
|
||||
}
|
72
src/network/game_setup.hpp
Normal file
72
src/network/game_setup.hpp
Normal file
@ -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 <vector>
|
||||
#include <string>
|
||||
|
||||
/*! \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<NetworkPlayerProfile*> 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<NetworkPlayerProfile*> m_players; //!< Information about players
|
||||
NetworkPlayerProfile m_self_profile; //!< Information about self (client only)
|
||||
};
|
||||
|
||||
#endif // GAME_SETUP_HPP
|
67
src/network/http_functions.cpp
Normal file
67
src/network/http_functions.cpp
Normal file
@ -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 <string>
|
||||
#include <curl/curl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
@ -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 <string>
|
||||
|
||||
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
|
@ -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
|
||||
|
@ -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; i<num_local_players; i++)
|
||||
{
|
||||
const AbstractKart *kart = world->getLocalPlayerKart(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; i<kart_id_offset+num_local_players; i++)
|
||||
{
|
||||
KartControl kc(this);
|
||||
AbstractKart *kart = World::getWorld()->getKart(i);
|
||||
if(kart->getController()->isNetworkController())
|
||||
{
|
||||
((NetworkKart*)kart)->setControl(kc);
|
||||
}
|
||||
}
|
||||
}; // KartControlMessage
|
||||
|
@ -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; i<num_karts; i++)
|
||||
{
|
||||
const AbstractKart* kart = world->getKart(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; i<num_karts; i++)
|
||||
{
|
||||
// Currently not used
|
||||
KartControl kc(this);
|
||||
Vec3 xyz = getVec3();
|
||||
btQuaternion q = getQuaternion();
|
||||
AbstractKart *kart = world->getKart(i);
|
||||
kart->setXYZ(xyz);
|
||||
kart->setRotation(q);
|
||||
} // for i
|
||||
}; // KartUpdateMessage
|
||||
|
@ -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 <string>
|
||||
#include <math.h>
|
||||
#include <stdexcept>
|
||||
#include <assert.h>
|
||||
|
||||
/** Creates a message to be sent.
|
||||
* This only initialised the data structures, it does not reserve any memory.
|
||||
* A call to allocate() is therefore necessary.
|
||||
* \param type The type of the message
|
||||
*/
|
||||
Message::Message(MessageType type)
|
||||
{
|
||||
assert(sizeof(int)==4);
|
||||
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<std::string>
|
||||
*/
|
||||
int Message::getStringVectorLength(const std::vector<std::string>& vs)
|
||||
{
|
||||
int len=getShortLength();
|
||||
for(unsigned int i=0; i<vs.size(); i++)
|
||||
len += getStringLength(vs[i]);
|
||||
return len;
|
||||
} // getStringVectorLength
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a std::vector<std::string> to the message.
|
||||
*/
|
||||
void Message::addStringVector(const std::vector<std::string>& vs)
|
||||
{
|
||||
assert(vs.size()<32767);
|
||||
addShort(vs.size());
|
||||
for(unsigned short i=0; i<vs.size(); i++)
|
||||
addString(vs[i]);
|
||||
} // addStringVector
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::vector<std::string> Message::getStringVector()
|
||||
{
|
||||
std::vector<std::string> vs;
|
||||
vs.resize(getShort());
|
||||
for(unsigned int i=0; i<vs.size(); i++)
|
||||
vs[i]=getString();
|
||||
return vs;
|
||||
} // getStringVector
|
||||
// ----------------------------------------------------------------------------
|
@ -1,143 +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.
|
||||
|
||||
#ifndef HEADER_MESSAGE_HPP
|
||||
#define HEADER_MESSAGE_HPP
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#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<std::string>& 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<n; i++)
|
||||
addInt(d[i]); }
|
||||
void addVec3(const Vec3& v) { addFloat(v.getX());
|
||||
addFloat(v.getY());
|
||||
addFloat(v.getZ()); }
|
||||
void addQuaternion(const btQuaternion& q) { addFloat(q.getX());
|
||||
addFloat(q.getY());
|
||||
addFloat(q.getZ());
|
||||
addFloat(q.getW()); }
|
||||
int getInt();
|
||||
bool getBool() { return getChar()==1; }
|
||||
short getShort();
|
||||
float getFloat();
|
||||
std::string getString();
|
||||
std::vector<std::string>
|
||||
getStringVector();
|
||||
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<std::string>& 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
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
@ -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 <pthread.h>
|
||||
#include <string>
|
||||
|
||||
#include "network/message.hpp"
|
||||
|
||||
class ConnectMessage : public Message
|
||||
class NetworkInterface : public Singleton<NetworkInterface>
|
||||
{
|
||||
private:
|
||||
std::string m_id;
|
||||
void setId();
|
||||
public:
|
||||
ConnectMessage();
|
||||
ConnectMessage(ENetPacket* pkt);
|
||||
const std::string&
|
||||
getId() { return m_id; }
|
||||
}; // ConnectMessage
|
||||
#endif
|
||||
friend class Singleton<NetworkInterface>;
|
||||
public:
|
||||
|
||||
void initNetwork(bool server);
|
||||
|
||||
protected:
|
||||
// protected functions
|
||||
NetworkInterface();
|
||||
virtual ~NetworkInterface();
|
||||
|
||||
};
|
||||
|
||||
#endif // NETWORK_INTERFACE_H
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
|
||||
// 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
|
||||
|
@ -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 <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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<ProtocolManager>();
|
||||
}
|
||||
|
||||
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<CharSel*>(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<CharSel*>(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<CharSel*>(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<RaceResultsGUI*>(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; i<race_manager->getNumLocalPlayers(); 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; i<m_kart_info.size(); i++)
|
||||
{
|
||||
m_kart_info[i].setGlobalPlayerId(i);
|
||||
race_manager->setPlayerKart(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; i<num_messages; i++)
|
||||
{
|
||||
int result = enet_host_service (m_host, &event, 0);
|
||||
if(result<0)
|
||||
{
|
||||
fprintf(stderr, m_mode==NW_SERVER
|
||||
? "Error while waiting for client control - chaos will reign.\n"
|
||||
: "Error while waiting for server update - chaos will reign.\n");
|
||||
correct=false;
|
||||
continue;
|
||||
}
|
||||
// if no message, busy wait
|
||||
if(result==0 || event.type==ENET_EVENT_TYPE_NONE)
|
||||
{
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(event.type!=ENET_EVENT_TYPE_RECEIVE)
|
||||
{
|
||||
fprintf(stderr, "unexpected message, ignored.\n");
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(m_mode==NW_SERVER)
|
||||
{
|
||||
int host_id = getHostId(event.peer);
|
||||
KartControlMessage(event.packet, host_id, m_num_local_players[host_id]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test if it is a game over message:
|
||||
if(Message::peekType(event.packet)==Message::MT_RACE_RESULT)
|
||||
{
|
||||
RaceResultMessage m(event.packet);
|
||||
m_state = NS_WAIT_FOR_RACE_RESULT;
|
||||
World::getWorld()->enterRaceOverState();
|
||||
return;
|
||||
}
|
||||
race_state->receive(event.packet);
|
||||
}
|
||||
} // for i<num_messages
|
||||
if(!correct)
|
||||
fprintf(stderr, "Missing messages need to be handled!\n");
|
||||
|
||||
} // receiveUpdates
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::waitForClientData()
|
||||
{
|
||||
ENetEvent event;
|
||||
bool correct=true;
|
||||
for(unsigned int i=1; i<=m_num_clients; i++)
|
||||
{
|
||||
int result = enet_host_service (m_host, &event, 100);
|
||||
if(result<=0)
|
||||
{
|
||||
fprintf(stderr, "Error while waiting for client control - chaos will reign.\n");
|
||||
correct=false;
|
||||
continue;
|
||||
}
|
||||
if(event.type!=ENET_EVENT_TYPE_RECEIVE)
|
||||
{
|
||||
fprintf(stderr, "received no message - chaos will reign.\n");
|
||||
correct=false;
|
||||
continue;
|
||||
}
|
||||
int host_id = getHostId(event.peer);
|
||||
KartControlMessage(event.packet, host_id, m_num_local_players[host_id]);
|
||||
}
|
||||
if(!correct)
|
||||
fprintf(stderr, "Missing messages need to be handled!\n");
|
||||
|
||||
} // waitForClientData
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sends the race result (kart positions and finishing times) from the server
|
||||
* to all clients. Clients keep on racing till they receive this message, and
|
||||
* will then copy the server's race results to the race manager.
|
||||
*/
|
||||
void NetworkManager::sendRaceResults()
|
||||
{
|
||||
RaceResultMessage m;
|
||||
broadcastToClients(m);
|
||||
} // sendRaceResults
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Changes the mode to wait in a barrier for all clients and the server to
|
||||
* acknowledge the result screen. The server waits for a message from all
|
||||
* clients, upon which it sends a message to all clients. The clients wait
|
||||
* for this message before continuing.
|
||||
*/
|
||||
void NetworkManager::beginRaceResultBarrier()
|
||||
{
|
||||
m_state = NS_RACE_RESULT_BARRIER;
|
||||
|
||||
if(m_mode==NW_SERVER)
|
||||
{
|
||||
m_barrier_count = 0;
|
||||
// In case of no networking set the next state
|
||||
if(m_num_clients == 0) m_state = NS_MAIN_MENU;
|
||||
}
|
||||
} // beginRaceResultBarrier
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sends a race 'result acknowledge' message from the clients to the server,
|
||||
* or from the server to the clients (in this case it contains the selected
|
||||
* menu choice from the server).
|
||||
*/
|
||||
void NetworkManager::sendRaceResultAck(char menu_selection)
|
||||
{
|
||||
// Menu selection is actually not important for a client
|
||||
RaceResultAckMessage m(menu_selection);
|
||||
if (m_mode==NW_CLIENT)
|
||||
{
|
||||
sendToServer(m);
|
||||
}
|
||||
if (manual)
|
||||
m_localhost->stopListening();
|
||||
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);
|
||||
}
|
||||
|
@ -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 <string>
|
||||
#include <vector>
|
||||
|
||||
#include "enet/enet.h"
|
||||
|
||||
#include "network/remote_kart_info.hpp"
|
||||
|
||||
|
||||
class Message;
|
||||
|
||||
class NetworkManager
|
||||
class NetworkManager : public Singleton<NetworkManager>
|
||||
{
|
||||
public:
|
||||
// The mode the network manager is operating in
|
||||
enum NetworkMode {NW_SERVER, NW_CLIENT, NW_NONE};
|
||||
friend class Singleton<NetworkManager>;
|
||||
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<RemoteKartInfo> m_kart_info;
|
||||
int m_host_id;
|
||||
std::vector<std::string> m_client_names;
|
||||
std::vector<int> m_num_local_players;
|
||||
std::vector<int> 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<ENetPeer*> 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<STKPeer*> 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<STKPeer*> 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
|
||||
|
8
src/network/network_string.cpp
Normal file
8
src/network/network_string.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b)
|
||||
{
|
||||
NetworkString ns(a);
|
||||
ns += b;
|
||||
return ns;
|
||||
}
|
230
src/network/network_string.hpp
Normal file
230
src/network/network_string.hpp
Normal file
@ -0,0 +1,230 @@
|
||||
#ifndef NETWORK_STRING_HPP
|
||||
#define NETWORK_STRING_HPP
|
||||
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
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<uint8_t>(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<typename T, size_t n>
|
||||
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<int,4>(pos); }
|
||||
inline uint32_t getUInt(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint32_t getUInt32(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint16_t getUInt16(int pos = 0) const { return get<uint16_t,2>(pos); }
|
||||
inline uint8_t getUInt8(int pos = 0) const { return get<uint8_t,1>(pos); }
|
||||
inline char getChar(int pos = 0) const { return get<char,1>(pos); }
|
||||
inline unsigned char getUChar(int pos = 0) const { return get<unsigned char,1>(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<int,4>(pos); }
|
||||
inline uint32_t gui(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint32_t gui32(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint16_t gui16(int pos = 0) const { return get<uint16_t,2>(pos); }
|
||||
inline uint8_t gui8(int pos = 0) const { return get<uint8_t,1>(pos); }
|
||||
inline char gc(int pos = 0) const { return get<char,1>(pos); }
|
||||
inline unsigned char guc(int pos = 0) const { return get<unsigned char,1>(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<typename T, size_t n>
|
||||
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<int,4>(pos); }
|
||||
inline uint32_t getAndRemoveUInt(int pos = 0) { return getAndRemove<uint32_t,4>(pos); }
|
||||
inline uint32_t getAndRemoveUInt32(int pos = 0) { return getAndRemove<uint32_t,4>(pos); }
|
||||
inline uint16_t getAndRemoveUInt16(int pos = 0) { return getAndRemove<uint16_t,2>(pos); }
|
||||
inline uint8_t getAndRemoveUInt8(int pos = 0) { return getAndRemove<uint8_t,1>(pos); }
|
||||
inline char getAndRemoveChar(int pos = 0) { return getAndRemove<char,1>(pos); }
|
||||
inline unsigned char getAndRemoveUChar(int pos = 0) { return getAndRemove<unsigned char,1>(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<uint8_t> m_string;
|
||||
};
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b);
|
||||
|
||||
#endif // NETWORK_STRING_HPP
|
40
src/network/network_world.cpp
Normal file
40
src/network/network_world.cpp
Normal file
@ -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<SynchronizationProtocol*>(
|
||||
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<ControllerEventsProtocol*>(
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_CONTROLLER_EVENTS));
|
||||
if (protocol)
|
||||
protocol->controllerAction(controller, action, value);
|
||||
}
|
37
src/network/network_world.hpp
Normal file
37
src/network/network_world.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef NETWORK_WORLD_HPP
|
||||
#define NETWORK_WORLD_HPP
|
||||
|
||||
#include "network/singleton.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include <map>
|
||||
|
||||
class Controller;
|
||||
class KartUpdateProtocol;
|
||||
class AbstractKart;
|
||||
|
||||
/*! \brief Manages the world updates during an online game
|
||||
* This function's update is to be called instead of the normal World update
|
||||
*/
|
||||
class NetworkWorld : public Singleton<NetworkWorld>
|
||||
{
|
||||
friend class Singleton<NetworkWorld>;
|
||||
public:
|
||||
void update(float dt);
|
||||
|
||||
void start() { m_running = true; }
|
||||
void stop() { m_running = false; }
|
||||
bool isRunning() { return m_running; }
|
||||
|
||||
void controllerAction(Controller* controller, PlayerAction action, int value);
|
||||
|
||||
std::string m_self_kart;
|
||||
protected:
|
||||
bool m_running;
|
||||
float m_race_time;
|
||||
|
||||
private:
|
||||
NetworkWorld();
|
||||
virtual ~NetworkWorld();
|
||||
};
|
||||
|
||||
#endif // NETWORK_WORLD_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,25 +16,39 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_RACE_START_MESSAGE_HPP
|
||||
#define HEADER_RACE_START_MESSAGE_HPP
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/message.hpp"
|
||||
#include "network/remote_kart_info.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
|
||||
class RaceStartMessage : public Message
|
||||
Protocol::Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type)
|
||||
{
|
||||
private:
|
||||
// For now this is an empty message
|
||||
public:
|
||||
RaceStartMessage() : Message(Message::MT_RACE_START)
|
||||
{
|
||||
allocate(0);
|
||||
} // RaceStartMessage
|
||||
m_callback_object = callback_object;
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
RaceStartMessage(ENetPacket* pkt):Message(pkt, MT_RACE_START)
|
||||
{
|
||||
}
|
||||
}; // RaceStartMessage
|
||||
#endif
|
||||
Protocol::~Protocol()
|
||||
{
|
||||
}
|
||||
|
||||
void Protocol::pause()
|
||||
{
|
||||
m_listener->requestPause(this);
|
||||
}
|
||||
void Protocol::unpause()
|
||||
{
|
||||
m_listener->requestUnpause(this);
|
||||
}
|
||||
|
||||
void Protocol::kill()
|
||||
{
|
||||
}
|
||||
|
||||
void Protocol::setListener(ProtocolManager* listener)
|
||||
{
|
||||
m_listener = listener;
|
||||
}
|
||||
|
||||
PROTOCOL_TYPE Protocol::getProtocolType()
|
||||
{
|
||||
return m_type;
|
||||
}
|
119
src/network/protocol.hpp
Normal file
119
src/network/protocol.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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 PROTOCOL_HPP
|
||||
#define PROTOCOL_HPP
|
||||
|
||||
#include "network/event.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
class ProtocolManager;
|
||||
|
||||
/** \enum PROTOCOL_TYPE
|
||||
* \brief The types that protocols can have. This is used to select which protocol receives which event.
|
||||
* \ingroup network
|
||||
*/
|
||||
enum PROTOCOL_TYPE
|
||||
{
|
||||
PROTOCOL_NONE = 0, //!< No protocol type assigned.
|
||||
PROTOCOL_CONNECTION = 1, //!< Protocol that deals with client-server connection.
|
||||
PROTOCOL_LOBBY_ROOM = 2, //!< Protocol that is used during the lobby room phase.
|
||||
PROTOCOL_START_GAME = 3, //!< Protocol used when starting the game.
|
||||
PROTOCOL_SYNCHRONIZATION = 4,//!<Protocol used to synchronize clocks.
|
||||
PROTOCOL_KART_UPDATE = 5, //!< Protocol to update karts position, rotation etc...
|
||||
PROTOCOL_GAME_EVENTS = 6, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 7,//!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SILENT = 0xffff //!< Used for protocols that do not subscribe to any network event.
|
||||
};
|
||||
|
||||
/** \class Protocol
|
||||
* \brief Abstract class used to define the global protocol functions.
|
||||
* A protocol is an entity that is started at a point, and that is updated by a thread.
|
||||
* A protocol can be terminated by an other class, or it can terminate itself if has fulfilled its role.
|
||||
* This class must be inherited to make any network job.
|
||||
* \ingroup network
|
||||
*/
|
||||
class Protocol
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*
|
||||
* Sets the basic protocol parameters, as the callback object and the protocol type.
|
||||
*
|
||||
* \param callback_object The callback object that will be used by the protocol. Protocols that do not use callback objects must set it to NULL.
|
||||
* \param type The type of the protocol.
|
||||
*/
|
||||
Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type);
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~Protocol();
|
||||
|
||||
/*!
|
||||
* \brief Notify a protocol matching the Event type of that event.
|
||||
* \param event : Pointer to the event.
|
||||
*/
|
||||
virtual void notifyEvent(Event* event) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Set the protocol listener.
|
||||
* \param listener : Pointer to the listener.
|
||||
*/
|
||||
void setListener(ProtocolManager* listener);
|
||||
|
||||
/*!
|
||||
* \brief Called when the protocol is going to start. Must be re-defined by subclasses.
|
||||
*/
|
||||
virtual void setup() = 0;
|
||||
/*!
|
||||
* \brief Called when the protocol is paused (by an other entity or by itself).
|
||||
* This function must be called by the subclasse's pause function if re-defined.
|
||||
*/
|
||||
virtual void pause();
|
||||
/*!
|
||||
* \brief Called when the protocol is unpaused.
|
||||
* This function must be called by the subclasse's unpause function if re-defined.
|
||||
*/
|
||||
virtual void unpause();
|
||||
/*!
|
||||
* \brief Called by the protocol listener, synchronously with the main loop. Must be re-defined.
|
||||
*/
|
||||
virtual void update() = 0;
|
||||
/*!
|
||||
* \brief Called by the protocol listener as often as possible. Must be re-defined.
|
||||
*/
|
||||
virtual void asynchronousUpdate() = 0;
|
||||
/*!
|
||||
* \brief Called when the protocol is to be killed.
|
||||
*/
|
||||
virtual void kill();
|
||||
|
||||
/*!
|
||||
* \brief Method to get a protocol's type.
|
||||
* \return The protocol type.
|
||||
*/
|
||||
PROTOCOL_TYPE getProtocolType();
|
||||
protected:
|
||||
ProtocolManager* m_listener; //!< The protocol listener
|
||||
PROTOCOL_TYPE m_type; //!< The type of the protocol
|
||||
CallbackObject* m_callback_object; //!< The callback object, if needed
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_HPP
|
459
src/network/protocol_manager.cpp
Normal file
459
src/network/protocol_manager.cpp
Normal file
@ -0,0 +1,459 @@
|
||||
//
|
||||
// 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/protocol_manager.hpp"
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <errno.h>
|
||||
#include <typeinfo>
|
||||
|
||||
void* protocolManagerUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
{
|
||||
manager->update();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void* protocolManagerAsynchronousUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
{
|
||||
manager->asynchronousUpdate();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ProtocolManager::ProtocolManager()
|
||||
{
|
||||
pthread_mutex_init(&m_events_mutex, NULL);
|
||||
pthread_mutex_init(&m_protocols_mutex, NULL);
|
||||
pthread_mutex_init(&m_asynchronous_protocols_mutex, NULL);
|
||||
pthread_mutex_init(&m_requests_mutex, NULL);
|
||||
pthread_mutex_init(&m_id_mutex, NULL);
|
||||
pthread_mutex_init(&m_exit_mutex, NULL);
|
||||
m_next_protocol_id = 0;
|
||||
|
||||
|
||||
pthread_mutex_lock(&m_exit_mutex); // will let the update function run
|
||||
/// FIXME used on server because mainloop never running
|
||||
/*if (NetworkManager::getInstance()->isServer())
|
||||
{
|
||||
m_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_update_thread, NULL, protocolManagerUpdate, this);
|
||||
}*/
|
||||
// always run this one
|
||||
m_asynchronous_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_asynchronous_update_thread, NULL, protocolManagerAsynchronousUpdate, this);
|
||||
}
|
||||
|
||||
ProtocolManager::~ProtocolManager()
|
||||
{
|
||||
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function
|
||||
pthread_mutex_lock(&m_events_mutex);
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
pthread_mutex_lock(&m_id_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size() ; i++)
|
||||
delete m_protocols[i].protocol;
|
||||
for (unsigned int i = 0; i < m_events_to_process.size() ; i++)
|
||||
delete m_events_to_process[i];
|
||||
m_protocols.clear();
|
||||
m_requests.clear();
|
||||
m_events_to_process.clear();
|
||||
pthread_mutex_unlock(&m_events_mutex);
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
pthread_mutex_unlock(&m_id_mutex);
|
||||
|
||||
pthread_mutex_destroy(&m_events_mutex);
|
||||
pthread_mutex_destroy(&m_protocols_mutex);
|
||||
pthread_mutex_destroy(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_destroy(&m_requests_mutex);
|
||||
pthread_mutex_destroy(&m_id_mutex);
|
||||
pthread_mutex_destroy(&m_exit_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::notifyEvent(Event* event)
|
||||
{
|
||||
pthread_mutex_lock(&m_events_mutex);
|
||||
Event* event2 = new Event(*event);
|
||||
m_events_to_process.push_back(event2); // add the event to the queue
|
||||
pthread_mutex_unlock(&m_events_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacket(newMessage, reliable);
|
||||
}
|
||||
|
||||
void ProtocolManager::sendMessage(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacket(peer, newMessage, reliable);
|
||||
}
|
||||
void ProtocolManager::sendMessageExcept(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacketExcept(peer, newMessage, reliable);
|
||||
}
|
||||
|
||||
uint32_t ProtocolManager::requestStart(Protocol* protocol)
|
||||
{
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
ProtocolInfo info;
|
||||
info.protocol = protocol;
|
||||
info.state = PROTOCOL_STATE_RUNNING;
|
||||
assignProtocolId(&info); // assign a unique id to the protocol.
|
||||
req.protocol_info = info;
|
||||
req.type = PROTOCOL_REQUEST_START;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
|
||||
return info.id;
|
||||
}
|
||||
|
||||
void ProtocolManager::requestStop(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_STOP;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestPause(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_PAUSE;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestUnpause(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_UNPAUSE;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestTerminate(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_TERMINATE;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
// check that the request does not already exist :
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
if (m_requests[i].protocol_info.protocol == protocol)
|
||||
{
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::startProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
// add the protocol to the protocol vector so that it's updated
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
Log::info("ProtocolManager", "A %s protocol with id=%u has been started. There are %ld protocols running.", typeid(*protocol.protocol).name(), protocol.id, m_protocols.size()+1);
|
||||
m_protocols.push_back(protocol);
|
||||
// setup the protocol and notify it that it's started
|
||||
protocol.protocol->setListener(this);
|
||||
protocol.protocol->setup();
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
}
|
||||
void ProtocolManager::stopProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
|
||||
}
|
||||
void ProtocolManager::pauseProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol.protocol && m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
{
|
||||
m_protocols[i].state = PROTOCOL_STATE_PAUSED;
|
||||
m_protocols[i].protocol->pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
void ProtocolManager::unpauseProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol.protocol && m_protocols[i].state == PROTOCOL_STATE_PAUSED)
|
||||
{
|
||||
m_protocols[i].state = PROTOCOL_STATE_RUNNING;
|
||||
m_protocols[i].protocol->unpause();
|
||||
}
|
||||
}
|
||||
}
|
||||
void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
|
||||
{
|
||||
pthread_mutex_lock(&m_protocols_mutex); // be sure that noone accesses the protocols vector while we erase a protocol
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
int offset = 0;
|
||||
std::string protocol_type = typeid(*protocol.protocol).name();
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i-offset].protocol == protocol.protocol)
|
||||
{
|
||||
delete m_protocols[i].protocol;
|
||||
m_protocols.erase(m_protocols.begin()+(i-offset), m_protocols.begin()+(i-offset)+1);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
Log::info("ProtocolManager", "A %s protocol has been terminated. There are %ld protocols running.", protocol_type.c_str(), m_protocols.size());
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::propagateEvent(Event* event)
|
||||
{
|
||||
PROTOCOL_TYPE searchedProtocol = PROTOCOL_NONE;
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
if (event->data.size() > 0)
|
||||
searchedProtocol = (PROTOCOL_TYPE)(event->data.getAndRemoveUInt8());
|
||||
}
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
searchedProtocol = PROTOCOL_CONNECTION;
|
||||
}
|
||||
Log::verbose("ProtocolManager", "Received event for protocols of type %d", searchedProtocol);
|
||||
for (unsigned int i = 0; i < m_protocols.size() ; i++)
|
||||
{
|
||||
if (m_protocols[i].protocol->getProtocolType() == searchedProtocol || event->type == EVENT_TYPE_DISCONNECTED) // pass data to protocols even when paused
|
||||
m_protocols[i].protocol->notifyEvent(event);
|
||||
}
|
||||
if (searchedProtocol == PROTOCOL_NONE) // no protocol was aimed, show the msg to debug
|
||||
{
|
||||
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"", event->data.c_str());
|
||||
}
|
||||
|
||||
// because we made a copy of the event
|
||||
delete event->peer; // no more need of that
|
||||
delete event;
|
||||
}
|
||||
|
||||
void ProtocolManager::update()
|
||||
{
|
||||
// now update all protocols
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
m_protocols[i].protocol->update();
|
||||
}
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::asynchronousUpdate()
|
||||
{
|
||||
// before updating, notice protocols that they have received information
|
||||
int size = m_events_to_process.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
pthread_mutex_lock(&m_events_mutex); // secure threads
|
||||
Event* event = m_events_to_process.back();
|
||||
m_events_to_process.pop_back();
|
||||
pthread_mutex_unlock(&m_events_mutex); // release the mutex
|
||||
|
||||
propagateEvent(event);
|
||||
}
|
||||
|
||||
// now update all protocols that need to be updated in asynchronous mode
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
m_protocols[i].protocol->asynchronousUpdate();
|
||||
}
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
|
||||
// process queued events for protocols
|
||||
// these requests are asynchronous
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
switch (m_requests[i].type)
|
||||
{
|
||||
case PROTOCOL_REQUEST_START:
|
||||
startProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_STOP:
|
||||
stopProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_PAUSE:
|
||||
pauseProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_UNPAUSE:
|
||||
unpauseProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_TERMINATE:
|
||||
protocolTerminated(m_requests[i].protocol_info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_requests.clear();
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
int ProtocolManager::runningProtocolsCount()
|
||||
{
|
||||
return m_protocols.size();
|
||||
}
|
||||
|
||||
PROTOCOL_STATE ProtocolManager::getProtocolState(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].id == id) // we know a protocol with that id
|
||||
return m_protocols[i].state; // return its state
|
||||
}
|
||||
// the protocol isn't running right now
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
if (m_requests[i].protocol_info.id == id) // the protocol is going to be started
|
||||
return PROTOCOL_STATE_RUNNING; // we can say it's running
|
||||
}
|
||||
return PROTOCOL_STATE_TERMINATED; // else, it's already finished
|
||||
}
|
||||
|
||||
PROTOCOL_STATE ProtocolManager::getProtocolState(Protocol* protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol) // the protocol is known
|
||||
return m_protocols[i].state; // return its state
|
||||
}
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
if (m_requests[i].protocol_info.protocol == protocol) // the protocol is going to be started
|
||||
return PROTOCOL_STATE_RUNNING; // we can say it's running
|
||||
}
|
||||
return PROTOCOL_STATE_TERMINATED; // we don't know this protocol at all, it's finished
|
||||
}
|
||||
|
||||
uint32_t ProtocolManager::getProtocolID(Protocol* protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol)
|
||||
return m_protocols[i].id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Protocol* ProtocolManager::getProtocol(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].id == id)
|
||||
return m_protocols[i].protocol;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol* ProtocolManager::getProtocol(PROTOCOL_TYPE type)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol->getProtocolType() == type)
|
||||
return m_protocols[i].protocol;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ProtocolManager::isServer()
|
||||
{
|
||||
return NetworkManager::getInstance()->isServer();
|
||||
}
|
||||
|
||||
int ProtocolManager::exit()
|
||||
{
|
||||
switch(pthread_mutex_trylock(&m_exit_mutex)) {
|
||||
case 0: /* if we got the lock, unlock and return 1 (true) */
|
||||
pthread_mutex_unlock(&m_exit_mutex);
|
||||
return 1;
|
||||
case EBUSY: /* return 0 (false) if the mutex was locked */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ProtocolManager::assignProtocolId(ProtocolInfo* protocol_info)
|
||||
{
|
||||
pthread_mutex_lock(&m_id_mutex);
|
||||
protocol_info->id = m_next_protocol_id;
|
||||
m_next_protocol_id++;
|
||||
pthread_mutex_unlock(&m_id_mutex);
|
||||
}
|
||||
|
||||
|
317
src/network/protocol_manager.hpp
Normal file
317
src/network/protocol_manager.hpp
Normal file
@ -0,0 +1,317 @@
|
||||
//
|
||||
// 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 protocol_manager.hpp
|
||||
* \brief Contains structures and enumerations related to protocol management.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOL_MANAGER_HPP
|
||||
#define PROTOCOL_MANAGER_HPP
|
||||
|
||||
#include "network/singleton.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/protocol.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
* \enum PROTOCOL_STATE
|
||||
* \brief Defines the three states that a protocol can have.
|
||||
*/
|
||||
enum PROTOCOL_STATE
|
||||
{
|
||||
PROTOCOL_STATE_RUNNING, //!< The protocol is being updated everytime.
|
||||
PROTOCOL_STATE_PAUSED, //!< The protocol is paused.
|
||||
PROTOCOL_STATE_TERMINATED //!< The protocol is terminated/does not exist.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \enum PROTOCOL_REQUEST_TYPE
|
||||
* \brief Defines actions that can be done about protocols.
|
||||
* This enum is used essentially to keep the manager thread-safe and
|
||||
* to avoid protocols modifying directly their state.
|
||||
*/
|
||||
enum PROTOCOL_REQUEST_TYPE
|
||||
{
|
||||
PROTOCOL_REQUEST_START, //!< Start a protocol
|
||||
PROTOCOL_REQUEST_STOP, //!< Stop a protocol
|
||||
PROTOCOL_REQUEST_PAUSE, //!< Pause a protocol
|
||||
PROTOCOL_REQUEST_UNPAUSE, //!< Unpause a protocol
|
||||
PROTOCOL_REQUEST_TERMINATE //!< Terminate a protocol
|
||||
};
|
||||
|
||||
/*!
|
||||
* \struct ProtocolInfo
|
||||
* \brief Stores the information needed to manage protocols
|
||||
*/
|
||||
typedef struct ProtocolInfo
|
||||
{
|
||||
PROTOCOL_STATE state; //!< The state of the protocol
|
||||
Protocol* protocol; //!< A pointer to the protocol
|
||||
uint32_t id; //!< The unique id of the protocol
|
||||
} ProtocolInfo;
|
||||
|
||||
/*!
|
||||
* \struct ProtocolRequest
|
||||
* \brief Represents a request to do an action about a protocol.
|
||||
*/
|
||||
typedef struct ProtocolRequest
|
||||
{
|
||||
PROTOCOL_REQUEST_TYPE type; //!< The type of request
|
||||
ProtocolInfo protocol_info; //!< The concerned protocol information
|
||||
} ProtocolRequest;
|
||||
|
||||
/*!
|
||||
* \class ProtocolManager
|
||||
* \brief Manages the protocols at runtime.
|
||||
*
|
||||
* This class is in charge of storing and managing protocols.
|
||||
* It is a singleton as there can be only one protocol manager per game
|
||||
* instance. Any game object that wants to start a protocol must create a
|
||||
* protocol and give it to this singleton. The protocols are updated in a
|
||||
* special thread, to ensure that they are processed independently from the
|
||||
* frames per second. Then, the management of protocols is thread-safe: any
|
||||
* object can start/pause/stop protocols whithout problems.
|
||||
*/
|
||||
class ProtocolManager : public Singleton<ProtocolManager>
|
||||
{
|
||||
friend class Singleton<ProtocolManager>;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Function that processes incoming events.
|
||||
* This function is called by the network manager each time there is an
|
||||
* incoming packet.
|
||||
*/
|
||||
virtual void notifyEvent(Event* event);
|
||||
/*!
|
||||
* \brief WILL BE COMMENTED LATER
|
||||
*/
|
||||
virtual void sendMessage(Protocol* sender, const NetworkString& message, bool reliable = true);
|
||||
/*!
|
||||
* \brief WILL BE COMMENTED LATER
|
||||
*/
|
||||
virtual void sendMessage(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable = true);
|
||||
/*!
|
||||
* \brief WILL BE COMMENTED LATER
|
||||
*/
|
||||
virtual void sendMessageExcept(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable = true);
|
||||
|
||||
/*!
|
||||
* \brief Asks the manager to start a protocol.
|
||||
* This function will store the request, and process it at a time it is
|
||||
* thread-safe.
|
||||
* \param protocol : A pointer to the protocol to start
|
||||
* \return The unique id of the protocol that is being started.
|
||||
*/
|
||||
virtual uint32_t requestStart(Protocol* protocol);
|
||||
/*!
|
||||
* \brief Asks the manager to stop a protocol.
|
||||
* This function will store the request, and process it at a time it is
|
||||
* thread-safe.
|
||||
* \param protocol : A pointer to the protocol to stop
|
||||
*/
|
||||
virtual void requestStop(Protocol* protocol);
|
||||
/*!
|
||||
* \brief Asks the manager to pause a protocol.
|
||||
* This function will store the request, and process it at a time it is
|
||||
* thread-safe.
|
||||
* \param protocol : A pointer to the protocol to pause
|
||||
*/
|
||||
virtual void requestPause(Protocol* protocol);
|
||||
/*!
|
||||
* \brief Asks the manager to unpause a protocol.
|
||||
* This function will store the request, and process it at a time it is
|
||||
* thread-safe.
|
||||
* \param protocol : A pointer to the protocol to unpause
|
||||
*/
|
||||
virtual void requestUnpause(Protocol* protocol);
|
||||
/*!
|
||||
* \brief Notifies the manager that a protocol is terminated.
|
||||
* This function will store the request, and process it at a time it is
|
||||
* thread-safe.
|
||||
* \param protocol : A pointer to the protocol that is finished
|
||||
*/
|
||||
virtual void requestTerminate(Protocol* protocol);
|
||||
|
||||
/*!
|
||||
* \brief Updates the manager.
|
||||
*
|
||||
* This function processes the events queue, notifies the concerned
|
||||
* protocols that they have events to process. Then ask all protocols
|
||||
* to update themselves. Finally processes stored requests about
|
||||
* starting, stoping, pausing etc... protocols.
|
||||
* This function is called by the main loop.
|
||||
* This function IS FPS-dependant.
|
||||
*/
|
||||
virtual void update();
|
||||
/*!
|
||||
* \brief Updates the manager.
|
||||
*
|
||||
* This function processes the events queue, notifies the concerned
|
||||
* protocols that they have events to process. Then ask all protocols
|
||||
* to update themselves. Finally processes stored requests about
|
||||
* starting, stoping, pausing etc... protocols.
|
||||
* This function is called in a thread.
|
||||
* This function IS NOT FPS-dependant.
|
||||
*/
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
/*!
|
||||
* \brief Get the number of protocols running.
|
||||
* \return The number of protocols that are actually running.
|
||||
*/
|
||||
virtual int runningProtocolsCount();
|
||||
/*!
|
||||
* \brief Get the state of a protocol using its id.
|
||||
* \param id : The id of the protocol you seek the state.
|
||||
* \return The state of the protocol.
|
||||
*/
|
||||
virtual PROTOCOL_STATE getProtocolState(uint32_t id);
|
||||
/*!
|
||||
* \brief Get the state of a protocol using a pointer on it.
|
||||
* \param protocol : A pointer to the protocol you seek the state.
|
||||
* \return The state of the protocol.
|
||||
*/
|
||||
virtual PROTOCOL_STATE getProtocolState(Protocol* protocol);
|
||||
/*!
|
||||
* \brief Get the id of a protocol.
|
||||
* \param protocol : A pointer to the protocol you seek the id.
|
||||
* \return The id of the protocol pointed by the protocol parameter.
|
||||
*/
|
||||
virtual uint32_t getProtocolID(Protocol* protocol);
|
||||
|
||||
/*!
|
||||
* \brief Get a protocol using its id.
|
||||
* \param id : Unique ID of the seek protocol.
|
||||
* \return The protocol that has the ID id.
|
||||
*/
|
||||
virtual Protocol* getProtocol(uint32_t id);
|
||||
/*!
|
||||
* \brief Get a protocol using its type.
|
||||
* \param type : The type of the protocol.
|
||||
* \return The protocol that matches the given type.
|
||||
*/
|
||||
virtual Protocol* getProtocol(PROTOCOL_TYPE type);
|
||||
|
||||
/*! \brief Know whether the app is a server.
|
||||
* \return True if this application is in server mode, false elseway.
|
||||
*/
|
||||
bool isServer();
|
||||
|
||||
/*! \brief Tells if we need to stop the update thread. */
|
||||
int exit();
|
||||
|
||||
protected:
|
||||
// protected functions
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*/
|
||||
ProtocolManager();
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~ProtocolManager();
|
||||
/*!
|
||||
* \brief Assign an id to a protocol.
|
||||
* This function will assign m_next_protocol_id as the protocol id.
|
||||
* This id starts at 0 at the beginning and is increased by 1 each time
|
||||
* a protocol starts.
|
||||
* \param protocol_info : The protocol info that needs an id.
|
||||
*/
|
||||
void assignProtocolId(ProtocolInfo* protocol_info);
|
||||
|
||||
/*!
|
||||
* \brief Starts a protocol.
|
||||
* Add the protocol info to the m_protocols vector.
|
||||
* \param protocol : ProtocolInfo to start.
|
||||
*/
|
||||
virtual void startProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Stops a protocol.
|
||||
* Coes nothing. Noone can stop running protocols for now.
|
||||
* \param protocol : ProtocolInfo to stop.
|
||||
*/
|
||||
virtual void stopProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Pauses a protocol.
|
||||
* Pauses a protocol and tells it that it's being paused.
|
||||
* \param protocol : ProtocolInfo to pause.
|
||||
*/
|
||||
virtual void pauseProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Unpauses a protocol.
|
||||
* Unpauses a protocol and notifies it.
|
||||
* \param protocol : ProtocolInfo to unpause.
|
||||
*/
|
||||
virtual void unpauseProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Notes that a protocol is terminated.
|
||||
* Remove a protocol from the protocols vector.
|
||||
* \param protocol : ProtocolInfo concerned.
|
||||
*/
|
||||
virtual void protocolTerminated(ProtocolInfo protocol);
|
||||
|
||||
void propagateEvent(Event* event);
|
||||
|
||||
// protected members
|
||||
/*!
|
||||
* \brief Contains the running protocols.
|
||||
* This stores the protocols that are either running or paused, their
|
||||
* state and their unique id.
|
||||
*/
|
||||
std::vector<ProtocolInfo> m_protocols;
|
||||
/*!
|
||||
* \brief Contains the network events to pass to protocols.
|
||||
*/
|
||||
std::vector<Event*> m_events_to_process;
|
||||
/*!
|
||||
* \brief Contains the requests to start/stop etc... protocols.
|
||||
*/
|
||||
std::vector<ProtocolRequest> m_requests;
|
||||
/*! \brief The next id to assign to a protocol.
|
||||
* This value is incremented by 1 each time a protocol is started.
|
||||
* If a protocol has an id lower than this value, it means that it have
|
||||
* been formerly started.
|
||||
*/
|
||||
uint32_t m_next_protocol_id;
|
||||
|
||||
// mutexes:
|
||||
/*! Used to ensure that the event queue is used thread-safely. */
|
||||
pthread_mutex_t m_events_mutex;
|
||||
/*! Used to ensure that the protocol vector is used thread-safely. */
|
||||
pthread_mutex_t m_protocols_mutex;
|
||||
/*! Used to ensure that the protocol vector is used thread-safely. */
|
||||
pthread_mutex_t m_asynchronous_protocols_mutex;
|
||||
/*! Used to ensure that the request vector is used thread-safely. */
|
||||
pthread_mutex_t m_requests_mutex;
|
||||
/*! Used to ensure that the protocol id is used in a thread-safe way.*/
|
||||
pthread_mutex_t m_id_mutex;
|
||||
/*! Used when need to quit.*/
|
||||
pthread_mutex_t m_exit_mutex;
|
||||
|
||||
/*! Update thread.*/
|
||||
pthread_t* m_update_thread;
|
||||
/*! Asynchronous update thread.*/
|
||||
pthread_t* m_asynchronous_update_thread;
|
||||
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_MANAGER_HPP
|
457
src/network/protocols/client_lobby_room_protocol.cpp
Normal file
457
src/network/protocols/client_lobby_room_protocol.cpp
Normal file
@ -0,0 +1,457 @@
|
||||
//
|
||||
// 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/protocols/client_lobby_room_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/network_kart_selection.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
ClientLobbyRoomProtocol::ClientLobbyRoomProtocol(const TransportAddress& server_address)
|
||||
: LobbyRoomProtocol(NULL)
|
||||
{
|
||||
m_server_address = server_address;
|
||||
m_server = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ClientLobbyRoomProtocol::~ClientLobbyRoomProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::setup()
|
||||
{
|
||||
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::requestKartSelection(std::string kart_name)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0x02 : kart selection request, size_token (4), token, size kart name, kart name
|
||||
request.ai8(0x02).ai8(4).ai32(m_server->getClientServerToken()).ai8(kart_name.size()).as(kart_name);
|
||||
m_listener->sendMessage(this, request);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::leave()
|
||||
{
|
||||
m_server->disconnect();
|
||||
m_server_address.ip = 0;
|
||||
m_server_address.port = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
assert(event->data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = event->data.getAndRemoveUInt8();
|
||||
|
||||
Log::info("ClientLobbyRoomProtocol", "Message of type %d", message_type);
|
||||
if (message_type == 0x01) // new player connected
|
||||
newPlayer(event);
|
||||
else if (message_type == 0x02) // player disconnected
|
||||
disconnectedPlayer(event);
|
||||
else if (message_type == 0x03) // kart selection update
|
||||
kartSelectionUpdate(event);
|
||||
else if (message_type == 0x04) // start race
|
||||
startGame(event);
|
||||
else if (message_type == 0x05) // start selection phase
|
||||
startSelection(event);
|
||||
else if (message_type == 0x80) // connection refused
|
||||
connectionRefused(event);
|
||||
else if (message_type == 0x81) // connection accepted
|
||||
connectionAccepted(event);
|
||||
else if (message_type == 0x82) // kart selection refused
|
||||
kartSelectionRefused(event);
|
||||
|
||||
} // message
|
||||
else if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
} // connection
|
||||
else if (event->type == EVENT_TYPE_DISCONNECTED) // means we left essentially
|
||||
{
|
||||
NetworkManager::getInstance()->removePeer(m_server);
|
||||
m_server = NULL;
|
||||
NetworkManager::getInstance()->disconnected();
|
||||
m_listener->requestTerminate(this);
|
||||
NetworkManager::getInstance()->reset();
|
||||
NetworkManager::getInstance()->removePeer(*event->peer); // prolly the same as m_server
|
||||
} // disconnection
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::update()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case NONE:
|
||||
if (NetworkManager::getInstance()->isConnectedTo(m_server_address))
|
||||
{
|
||||
m_state = LINKED;
|
||||
}
|
||||
break;
|
||||
case LINKED:
|
||||
{
|
||||
NetworkString ns;
|
||||
// 1 (connection request), 4 (size of id), global id
|
||||
ns.ai8(1).ai8(4).ai32(Online::CurrentUser::get()->getUserID());
|
||||
m_listener->sendMessage(this, ns);
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
} break;
|
||||
case REQUESTING_CONNECTION:
|
||||
break;
|
||||
case CONNECTED:
|
||||
break;
|
||||
case KART_SELECTION:
|
||||
{
|
||||
NetworkKartSelectionScreen* screen = NetworkKartSelectionScreen::getInstance();
|
||||
StateManager::get()->pushScreen(screen);
|
||||
m_state = SELECTING_KARTS;
|
||||
} break;
|
||||
case SELECTING_KARTS:
|
||||
break;
|
||||
case PLAYING:
|
||||
break;
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a new player is connected to the server
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7
|
||||
* ------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 |
|
||||
* Data | 4 | player global id | 1 | 0 <= race id < 16 |
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::newPlayer(Event* event)
|
||||
{
|
||||
if (event->data.size() != 7 || event->data[0] != 4 || event->data[5] != 1) // 7 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t global_id = event->data.gui32(1);
|
||||
uint8_t race_id = event->data.gui8(6);
|
||||
|
||||
if (global_id == Online::CurrentUser::get()->getUserID())
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
|
||||
}
|
||||
else if (m_setup->getProfile(race_id) == NULL || m_setup->getProfile(global_id) == NULL)
|
||||
{
|
||||
Log::verbose("ClientLobbyRoomProtocol", "New player connected.");
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
|
||||
profile->kart_name = "";
|
||||
profile->race_id = race_id;
|
||||
profile->user_profile = new Online::User("", global_id);
|
||||
m_setup->addPlayer(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "One of the player notified in the list is myself.");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a new player is disconnected
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* -------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | 0 <= race id < 16 |
|
||||
* -------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t id = event->data[1];
|
||||
if (m_setup->removePlayer(id))
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "Peer removed successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The disconnected peer wasn't known.");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server accepts the connection.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 7 8 12
|
||||
* ----------------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | 4 | 1 | 4 |
|
||||
* Data | 1 | 0 <= race id < 16 | 4 | priv token | 4 | global id |
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
{
|
||||
if (event->data.size() < 12 || event->data[0] != 1 || event->data[2] != 4 || event->data[7] != 4) // 12 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
STKPeer* peer = *(event->peer);
|
||||
|
||||
uint32_t global_id = event->data.gui32(8);
|
||||
if (global_id == Online::CurrentUser::get()->getUserID())
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
|
||||
|
||||
// self profile
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
|
||||
profile->kart_name = "";
|
||||
profile->race_id = event->data.gui8(1);
|
||||
profile->user_profile = Online::CurrentUser::get();
|
||||
m_setup->addPlayer(profile);
|
||||
// connection token
|
||||
uint32_t token = event->data.gui32(3);
|
||||
peer->setClientServerToken(token);
|
||||
// add all players
|
||||
event->data.removeFront(12); // remove the 12 first bytes
|
||||
int remaining = event->data.size();
|
||||
if (remaining%7 != 0)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "ConnectionAccepted : Error in the server list");
|
||||
}
|
||||
remaining /= 7;
|
||||
for (int i = 0; i < remaining; i++)
|
||||
{
|
||||
if (event->data[0] != 1 || event->data[2] != 4)
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad format in players list.");
|
||||
uint8_t race_id = event->data[1];
|
||||
uint32_t global_id = event->data.gui32(3);
|
||||
Online::User* new_user = new Online::User("", global_id);
|
||||
NetworkPlayerProfile* profile2 = new NetworkPlayerProfile();
|
||||
profile2->race_id = race_id;
|
||||
profile2->user_profile = new_user;
|
||||
profile2->kart_name = "";
|
||||
m_setup->addPlayer(profile2);
|
||||
event->data.removeFront(7);
|
||||
}
|
||||
|
||||
// add self
|
||||
m_server = *(event->peer);
|
||||
m_state = CONNECTED;
|
||||
}
|
||||
else
|
||||
Log::info("ClientLobbyRoomProtocol", "Failure during the connection acceptation process.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server refuses the connection.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionRefused(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1) // 2 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->data[1]) // the second byte
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused : too many players.");
|
||||
break;
|
||||
case 1:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused : banned.");
|
||||
break;
|
||||
default:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server refuses the kart selection request.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused kart selection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->data[1]) // the error code
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused : already taken.");
|
||||
break;
|
||||
case 1:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused : not available.");
|
||||
break;
|
||||
default:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server tells to update a player's kart.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 N+3
|
||||
* ------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | N |
|
||||
* Data | 1 | race id | N (kart name size) | kart name |
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
|
||||
{
|
||||
if (event->data.size() < 3 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t player_id = event->data[1];
|
||||
uint8_t kart_name_length = event->data[2];
|
||||
std::string data = event->data.getString(3, kart_name_length);
|
||||
if (data.size() != kart_name_length)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Kart names sizes differ: told: %d, real: %d.", kart_name_length, data.size());
|
||||
return;
|
||||
}
|
||||
if (!m_setup->isKartAvailable(data))
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The updated kart is taken already.");
|
||||
}
|
||||
m_setup->setPlayerKart(player_id, data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the race needs to be started.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5
|
||||
* -------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | 4 | token |
|
||||
* -------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startGame(Event* event)
|
||||
{
|
||||
if (event->data.size() < 5 || event->data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t token = event->data.gui32(1);
|
||||
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = PLAYING;
|
||||
m_listener->requestStart(new StartGameProtocol(m_setup));
|
||||
Log::error("ClientLobbyRoomProtocol", "Starting new game");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token when starting game");
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the kart selection starts.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5
|
||||
* -------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | 4 | token |
|
||||
* -------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startSelection(Event* event)
|
||||
{
|
||||
if (event->data.size() < 5 || event->data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t token = event->data.gui32(1);
|
||||
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = KART_SELECTION;
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection starts now");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token");
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
49
src/network/protocols/client_lobby_room_protocol.hpp
Normal file
49
src/network/protocols/client_lobby_room_protocol.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
||||
#define CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocols/lobby_room_protocol.hpp"
|
||||
|
||||
class ClientLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
{
|
||||
public:
|
||||
ClientLobbyRoomProtocol(const TransportAddress& server_address);
|
||||
virtual ~ClientLobbyRoomProtocol();
|
||||
|
||||
void requestKartSelection(std::string kart_name);
|
||||
void sendMessage(std::string message);
|
||||
void leave();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
protected:
|
||||
void newPlayer(Event* event);
|
||||
void disconnectedPlayer(Event* event);
|
||||
void connectionAccepted(Event* event); //!< Callback function on connection acceptation
|
||||
void connectionRefused(Event* event); //!< Callback function on connection refusal
|
||||
void kartSelectionRefused(Event* event);
|
||||
void kartSelectionUpdate(Event* event);
|
||||
void startGame(Event* event);
|
||||
void startSelection(Event* event);
|
||||
|
||||
TransportAddress m_server_address;
|
||||
STKPeer* m_server;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
LINKED,
|
||||
REQUESTING_CONNECTION,
|
||||
CONNECTED, // means in the lobby room
|
||||
KART_SELECTION,
|
||||
SELECTING_KARTS, // in the network kart selection screen
|
||||
PLAYING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
115
src/network/protocols/connect_to_peer.cpp
Normal file
115
src/network/protocols/connect_to_peer.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// 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/protocols/connect_to_peer.hpp"
|
||||
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
#include "network/protocols/request_connection.hpp"
|
||||
#include "network/protocols/ping_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToPeer::ConnectToPeer(uint32_t peer_id) :
|
||||
Protocol(NULL, PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToPeer::~ConnectToPeer()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
Log::debug("ConnectToPeer", "Received event notifying peer connection.");
|
||||
m_state = CONNECTED; // we received a message, we are connected
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
m_public_address.ip = 0;
|
||||
m_public_address.port = 0;
|
||||
m_peer_address.ip = 0;
|
||||
m_peer_address.port = 0;
|
||||
m_current_protocol_id = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::asynchronousUpdate()
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_peer_id, &m_peer_address));
|
||||
m_state = WAITING_PEER_ADDRESS;
|
||||
break;
|
||||
}
|
||||
case WAITING_PEER_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we know the peer address
|
||||
{
|
||||
if (m_peer_address.ip != 0 && m_peer_address.port != 0)
|
||||
{
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ConnectToPeer", "The peer you want to connect to has hidden his address.");
|
||||
m_state = DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the peer to connect
|
||||
case CONNECTED:
|
||||
{
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
m_state = DONE;
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
55
src/network/protocols/connect_to_peer.hpp
Normal file
55
src/network/protocols/connect_to_peer.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
//
|
||||
// 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 CONNECT_TO_SERVER_HPP
|
||||
#define CONNECT_TO_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include <string>
|
||||
|
||||
class ConnectToPeer : public Protocol, public CallbackObject
|
||||
{
|
||||
public:
|
||||
ConnectToPeer(uint32_t peer_id);
|
||||
virtual ~ConnectToPeer();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_peer_address;
|
||||
TransportAddress m_public_address;
|
||||
uint32_t m_peer_id;
|
||||
uint32_t m_current_protocol_id;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
WAITING_PEER_ADDRESS,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
192
src/network/protocols/connect_to_server.cpp
Normal file
192
src/network/protocols/connect_to_server.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
//
|
||||
// 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/protocols/connect_to_server.hpp"
|
||||
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
#include "network/protocols/request_connection.hpp"
|
||||
#include "network/protocols/ping_protocol.hpp"
|
||||
#include "network/protocols/quick_join_protocol.hpp"
|
||||
#include "network/protocols/client_lobby_room_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::ConnectToServer() :
|
||||
Protocol(NULL, PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_server_id = 0;
|
||||
m_quick_join = true;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::ConnectToServer(uint32_t server_id, uint32_t host_id) :
|
||||
Protocol(NULL, PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_server_id = server_id;
|
||||
m_host_id = host_id;
|
||||
m_quick_join = false;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::~ConnectToServer()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
Log::info("ConnectToServer", "The Connect To Server protocol has "
|
||||
"received an event notifying that he's connected to the peer.");
|
||||
m_state = CONNECTED; // we received a message, we are connected
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::setup()
|
||||
{
|
||||
Log::info("ConnectToServer", "SETUPP");
|
||||
m_state = NONE;
|
||||
m_public_address.ip = 0;
|
||||
m_public_address.port = 0;
|
||||
m_server_address.ip = 0;
|
||||
m_server_address.port = 0;
|
||||
m_current_protocol_id = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::asynchronousUpdate()
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
Log::info("ConnectToServer", "Protocol starting");
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPublicAddress(&m_public_address));
|
||||
m_state = GETTING_SELF_ADDRESS;
|
||||
break;
|
||||
}
|
||||
case GETTING_SELF_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // now we know the public addr
|
||||
{
|
||||
m_state = SHOWING_SELF_ADDRESS;
|
||||
NetworkManager::getInstance()->setPublicAddress(m_public_address); // set our public address
|
||||
m_current_protocol_id = m_listener->requestStart(new ShowPublicAddress());
|
||||
Log::info("ConnectToServer", "Public address known");
|
||||
/*
|
||||
if (m_quick_join)
|
||||
m_current_protocol_id = m_listener->requestStart(new QuickJoinProtocol(&m_server_address, &m_server_id));
|
||||
else
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_server_id, &m_server_address));*/
|
||||
}
|
||||
break;
|
||||
case SHOWING_SELF_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // now our public address is in the database
|
||||
{
|
||||
Log::info("ConnectToServer", "Public address shown");
|
||||
if (m_quick_join)
|
||||
{
|
||||
m_current_protocol_id = m_listener->requestStart(new QuickJoinProtocol(&m_server_address, &m_server_id));
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_host_id, &m_server_address));
|
||||
m_state = GETTING_SERVER_ADDRESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GETTING_SERVER_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we know the server address
|
||||
{
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
m_current_protocol_id = m_listener->requestStart(new RequestConnection(m_server_id));
|
||||
Log::info("ConnectToServer", "Server's address known");
|
||||
}
|
||||
break;
|
||||
case REQUESTING_CONNECTION:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // server knows we wanna connect
|
||||
{
|
||||
Log::info("ConnectToServer", "Connection request made");
|
||||
if (m_server_address.ip == 0 || m_server_address.port == 0)
|
||||
{ // server data not correct, hide address and stop
|
||||
m_state = HIDING_ADDRESS;
|
||||
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
|
||||
return;
|
||||
}
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_server_address, 2.0));
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the server to answer our connection
|
||||
{
|
||||
static double timer = 0;
|
||||
if (Time::getRealTime() > timer+5.0) // every 5 seconds
|
||||
{
|
||||
timer = Time::getRealTime();
|
||||
NetworkManager::getInstance()->connect(m_server_address);
|
||||
Log::info("ConnectToServer", "Trying to connect");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONNECTED:
|
||||
{
|
||||
Log::info("ConnectToServer", "Connected");
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
|
||||
ClientNetworkManager::getInstance()->setConnected(true);
|
||||
m_state = HIDING_ADDRESS;
|
||||
break;
|
||||
}
|
||||
case HIDING_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we have hidden our address
|
||||
{
|
||||
Log::info("ConnectToServer", "Address hidden");
|
||||
m_state = DONE;
|
||||
if (ClientNetworkManager::getInstance()->isConnected()) // lobby room protocol if we're connected only
|
||||
m_listener->requestStart(new ClientLobbyRoomProtocol(m_server_address));
|
||||
}
|
||||
break;
|
||||
case DONE:
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
61
src/network/protocols/connect_to_server.hpp
Normal file
61
src/network/protocols/connect_to_server.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// 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 CONNECT_TO_SERVER_HPP
|
||||
#define CONNECT_TO_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include <string>
|
||||
|
||||
class ConnectToServer : public Protocol, public CallbackObject
|
||||
{
|
||||
public:
|
||||
ConnectToServer(); //!< Quick join
|
||||
ConnectToServer(uint32_t server_id, uint32_t host_id); //!< Specify server id
|
||||
virtual ~ConnectToServer();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_server_address;
|
||||
TransportAddress m_public_address;
|
||||
uint32_t m_server_id;
|
||||
uint32_t m_host_id;
|
||||
uint32_t m_current_protocol_id;
|
||||
bool m_quick_join;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
GETTING_SELF_ADDRESS,
|
||||
SHOWING_SELF_ADDRESS,
|
||||
GETTING_SERVER_ADDRESS,
|
||||
REQUESTING_CONNECTION,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
HIDING_ADDRESS,
|
||||
DONE
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
168
src/network/protocols/controller_events_protocol.cpp
Normal file
168
src/network/protocols/controller_events_protocol.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
|
||||
#include "modes/world.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ControllerEventsProtocol::ControllerEventsProtocol() :
|
||||
Protocol(NULL, PROTOCOL_CONTROLLER_EVENTS)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ControllerEventsProtocol::~ControllerEventsProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::setup()
|
||||
{
|
||||
m_self_controller_index = 0;
|
||||
std::vector<AbstractKart*> karts = World::getWorld()->getKarts();
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < karts.size(); i++)
|
||||
{
|
||||
if (karts[i]->getIdent() == NetworkWorld::getInstance()->m_self_kart)
|
||||
{
|
||||
Log::info("ControllerEventsProtocol", "My id is %d", i);
|
||||
m_self_controller_index = i;
|
||||
}
|
||||
STKPeer* peer = NULL;
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
for (unsigned int j = 0; j < peers.size(); j++)
|
||||
{
|
||||
if (peers[j]->getPlayerProfile()->kart_name == karts[i]->getIdent())
|
||||
{
|
||||
peer = peers[j];
|
||||
}
|
||||
Log::info("ControllerEventsProtocol", "Compared %s and %s",
|
||||
peers[j]->getPlayerProfile()->kart_name.c_str(), karts[i]->getIdent().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (peers.size() > 0)
|
||||
peer = peers[0];
|
||||
}
|
||||
if (peer == NULL)
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "Couldn't find the peer corresponding to the kart.");
|
||||
}
|
||||
m_controllers.push_back(std::pair<Controller*, STKPeer*>(karts[i]->getController(), peer));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->data.size() < 17)
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", event->data.size());
|
||||
return;
|
||||
}
|
||||
uint32_t token = event->data.gui32();
|
||||
NetworkString pure_message = event->data;
|
||||
pure_message.removeFront(4);
|
||||
if (token != (*event->peer)->getClientServerToken())
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "Bad token from peer.");
|
||||
return;
|
||||
}
|
||||
NetworkString ns = pure_message;
|
||||
float event_timestamp = ns.getFloat();
|
||||
ns.removeFront(4);
|
||||
uint8_t client_index = -1;
|
||||
while (ns.size() >= 9)
|
||||
{
|
||||
uint8_t controller_index = ns.gui8();
|
||||
client_index = controller_index;
|
||||
uint8_t serialized_1 = ns.gui8(1), serialized_2 = ns.gui8(2), serialized_3 = ns.gui8(3);
|
||||
PlayerAction action = (PlayerAction)(ns.gui8(4));
|
||||
int action_value = ns.gui32(5);
|
||||
|
||||
KartControl* controls = m_controllers[controller_index].first->getControls();
|
||||
controls->m_brake = (serialized_1 & 0x40)!=0;
|
||||
controls->m_nitro = (serialized_1 & 0x20)!=0;
|
||||
controls->m_rescue = (serialized_1 & 0x10)!=0;
|
||||
controls->m_fire = (serialized_1 & 0x08)!=0;
|
||||
controls->m_look_back = (serialized_1 & 0x04)!=0;
|
||||
controls->m_skid = KartControl::SkidControl(serialized_1 & 0x03);
|
||||
|
||||
m_controllers[controller_index].first->action(action, action_value);
|
||||
ns.removeFront(9);
|
||||
//Log::info("ControllerEventProtocol", "Registered one action.");
|
||||
}
|
||||
if (ns.size() > 0 && ns.size() != 9)
|
||||
{
|
||||
Log::warn("ControllerEventProtocol", "The data seems corrupted. Remains %d", ns.size());
|
||||
return;
|
||||
}
|
||||
if (client_index < 0)
|
||||
{
|
||||
Log::warn("ControllerEventProtocol", "Couldn't have a client id.");
|
||||
return;
|
||||
}
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
// notify everybody of the event :
|
||||
for (unsigned int i = 0; i < m_controllers.size(); i++)
|
||||
{
|
||||
if (i == client_index) // don't send that message to the sender
|
||||
continue;
|
||||
NetworkString ns2;
|
||||
ns2.ai32(m_controllers[i].second->getClientServerToken());
|
||||
ns2 += pure_message;
|
||||
m_listener->sendMessage(this, m_controllers[i].second, ns2, false);
|
||||
//Log::info("ControllerEventsProtocol", "Sizes are %d and %d", ns2.size(), pure_message.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::update()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::controllerAction(Controller* controller,
|
||||
PlayerAction action, int value)
|
||||
{
|
||||
assert(!m_listener->isServer());
|
||||
|
||||
KartControl* controls = controller->getControls();
|
||||
uint8_t serialized_1 = 0;
|
||||
serialized_1 |= (controls->m_brake==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_nitro==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_rescue==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_fire==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_look_back==true);
|
||||
serialized_1 <<= 2;
|
||||
serialized_1 += controls->m_skid;
|
||||
uint8_t serialized_2 = (uint8_t)(controls->m_accel*255.0);
|
||||
uint8_t serialized_3 = (uint8_t)(controls->m_steer*127.0);
|
||||
|
||||
NetworkString ns;
|
||||
ns.ai32(m_controllers[m_self_controller_index].second->getClientServerToken());
|
||||
ns.af(World::getWorld()->getTime());
|
||||
ns.ai8(m_self_controller_index);
|
||||
ns.ai8(serialized_1).ai8(serialized_2).ai8(serialized_3);
|
||||
ns.ai8((uint8_t)(action)).ai32(value);
|
||||
|
||||
m_listener->sendMessage(this, ns, false); // send message to server
|
||||
}
|
||||
|
||||
|
28
src/network/protocols/controller_events_protocol.hpp
Normal file
28
src/network/protocols/controller_events_protocol.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef CONTROLLER_EVENTS_PROTOCOL_HPP
|
||||
#define CONTROLLER_EVENTS_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "input/input.hpp"
|
||||
#include "karts/controller/controller.hpp"
|
||||
|
||||
class ControllerEventsProtocol : public Protocol
|
||||
{
|
||||
protected:
|
||||
std::vector<std::pair<Controller*, STKPeer*> > m_controllers;
|
||||
uint32_t m_self_controller_index;
|
||||
|
||||
public:
|
||||
ControllerEventsProtocol();
|
||||
virtual ~ControllerEventsProtocol();
|
||||
|
||||
virtual void setup();
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
void controllerAction(Controller* controller, PlayerAction action, int value);
|
||||
|
||||
};
|
||||
|
||||
#endif // CONTROLLER_EVENTS_PROTOCOL_HPP
|
21
src/network/protocols/game_events_protocol.cpp
Normal file
21
src/network/protocols/game_events_protocol.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
|
||||
GameEventsProtocol::GameEventsProtocol() : Protocol(NULL, PROTOCOL_GAME_EVENTS)
|
||||
{
|
||||
}
|
||||
|
||||
GameEventsProtocol::~GameEventsProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::setup()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::update()
|
||||
{
|
||||
}
|
21
src/network/protocols/game_events_protocol.hpp
Normal file
21
src/network/protocols/game_events_protocol.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef GAME_EVENTS_PROTOCOL_HPP
|
||||
#define GAME_EVENTS_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
|
||||
class GameEventsProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
GameEventsProtocol();
|
||||
virtual ~GameEventsProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // GAME_EVENTS_PROTOCOL_HPP
|
99
src/network/protocols/get_peer_address.cpp
Normal file
99
src/network/protocols/get_peer_address.cpp
Normal file
@ -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/protocols/get_peer_address.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/http_functions.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
GetPeerAddress::GetPeerAddress(uint32_t peer_id, CallbackObject* callback_object) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
}
|
||||
|
||||
GetPeerAddress::~GetPeerAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void GetPeerAddress::notifyEvent(Event* event)
|
||||
{
|
||||
// nothing there. If we receive events, they must be ignored
|
||||
}
|
||||
|
||||
void GetPeerAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
m_request = NULL;
|
||||
}
|
||||
|
||||
void GetPeerAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("peer_id",m_peer_id);
|
||||
m_request->setParameter("action","get");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if (rec_success == "yes")
|
||||
{
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
result->get("ip", &addr->ip);
|
||||
result->get("port", &addr->port);
|
||||
Log::debug("GetPeerAddress", "Address gotten successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("GetPeerAddress", "Fail to get address.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("GetPeerAddress", "Fail to get address.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPeerAddress::setPeerID(uint32_t peer_id)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
}
|
51
src/network/protocols/get_peer_address.hpp
Normal file
51
src/network/protocols/get_peer_address.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// 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 GET_PEER_ADDRESS_HPP
|
||||
#define GET_PEER_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
class GetPeerAddress : public Protocol
|
||||
{
|
||||
public:
|
||||
GetPeerAddress(uint32_t peer_id, CallbackObject* callback_object);
|
||||
virtual ~GetPeerAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
void setPeerID(uint32_t m_peer_id);
|
||||
protected:
|
||||
uint32_t m_peer_id;
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
|
||||
};
|
||||
|
||||
#endif // GET_PEER_ADDRESS_HPP
|
210
src/network/protocols/get_public_address.cpp
Normal file
210
src/network/protocols/get_public_address.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
//
|
||||
// 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/protocols/get_public_address.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/network_interface.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
int stunRand()
|
||||
{
|
||||
static bool init = false;
|
||||
if (!init)
|
||||
{
|
||||
srand((unsigned int)time(NULL));
|
||||
init = true;
|
||||
}
|
||||
return rand();
|
||||
}
|
||||
|
||||
GetPublicAddress::GetPublicAddress(CallbackObject* callback_object) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
GetPublicAddress::~GetPublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void GetPublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GetPublicAddress::setup()
|
||||
{
|
||||
m_state = NOTHING_DONE;
|
||||
}
|
||||
|
||||
void GetPublicAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NOTHING_DONE)
|
||||
{
|
||||
// format : 00MMMMMCMMMCMMMM (cf rfc 5389)
|
||||
uint16_t message_type = 0x0001; // binding request
|
||||
m_stun_tansaction_id[0] = stunRand();
|
||||
m_stun_tansaction_id[1] = stunRand();
|
||||
m_stun_tansaction_id[2] = stunRand();
|
||||
uint16_t message_length = 0x0000;
|
||||
|
||||
uint8_t bytes[21]; // the message to be sent
|
||||
// bytes 0-1 : the type of the message,
|
||||
bytes[0] = (uint8_t)(message_type>>8);
|
||||
bytes[1] = (uint8_t)(message_type);
|
||||
|
||||
// bytes 2-3 : message length added to header (attributes)
|
||||
bytes[2] = (uint8_t)(message_length>>8);
|
||||
bytes[3] = (uint8_t)(message_length);
|
||||
|
||||
// bytes 4-7 : magic cookie to recognize the stun protocol
|
||||
bytes[4] = (uint8_t)(m_stun_magic_cookie>>24);
|
||||
bytes[5] = (uint8_t)(m_stun_magic_cookie>>16);
|
||||
bytes[6] = (uint8_t)(m_stun_magic_cookie>>8);
|
||||
bytes[7] = (uint8_t)(m_stun_magic_cookie);
|
||||
|
||||
// bytes 8-19 : the transaction id
|
||||
bytes[8] = (uint8_t)(m_stun_tansaction_id[0]>>24);
|
||||
bytes[9] = (uint8_t)(m_stun_tansaction_id[0]>>16);
|
||||
bytes[10] = (uint8_t)(m_stun_tansaction_id[0]>>8);
|
||||
bytes[11] = (uint8_t)(m_stun_tansaction_id[0]);
|
||||
bytes[12] = (uint8_t)(m_stun_tansaction_id[1]>>24);
|
||||
bytes[13] = (uint8_t)(m_stun_tansaction_id[1]>>16);
|
||||
bytes[14] = (uint8_t)(m_stun_tansaction_id[1]>>8);
|
||||
bytes[15] = (uint8_t)(m_stun_tansaction_id[1]);
|
||||
bytes[16] = (uint8_t)(m_stun_tansaction_id[2]>>24);
|
||||
bytes[17] = (uint8_t)(m_stun_tansaction_id[2]>>16);
|
||||
bytes[18] = (uint8_t)(m_stun_tansaction_id[2]>>8);
|
||||
bytes[19] = (uint8_t)(m_stun_tansaction_id[2]);
|
||||
bytes[20] = '\0';
|
||||
|
||||
Log::verbose("GetPublicAddress", "Querrying STUN server 132.177.123.6");
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(dst, 3478));
|
||||
m_state = TEST_SENT;
|
||||
}
|
||||
if (m_state == TEST_SENT)
|
||||
{
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(dst, 3478));
|
||||
assert(data);
|
||||
|
||||
// check that the stun response is a response, contains the magic cookie and the transaction ID
|
||||
if ( data[0] == 0x01 &&
|
||||
data[1] == 0x01 &&
|
||||
data[4] == (uint8_t)(m_stun_magic_cookie>>24) &&
|
||||
data[5] == (uint8_t)(m_stun_magic_cookie>>16) &&
|
||||
data[6] == (uint8_t)(m_stun_magic_cookie>>8) &&
|
||||
data[7] == (uint8_t)(m_stun_magic_cookie) )
|
||||
{
|
||||
if(
|
||||
data[8] == (uint8_t)(m_stun_tansaction_id[0]>>24) &&
|
||||
data[9] == (uint8_t)(m_stun_tansaction_id[0]>>16) &&
|
||||
data[10] == (uint8_t)(m_stun_tansaction_id[0]>>8 ) &&
|
||||
data[11] == (uint8_t)(m_stun_tansaction_id[0] ) &&
|
||||
data[12] == (uint8_t)(m_stun_tansaction_id[1]>>24) &&
|
||||
data[13] == (uint8_t)(m_stun_tansaction_id[1]>>16) &&
|
||||
data[14] == (uint8_t)(m_stun_tansaction_id[1]>>8 ) &&
|
||||
data[15] == (uint8_t)(m_stun_tansaction_id[1] ) &&
|
||||
data[16] == (uint8_t)(m_stun_tansaction_id[2]>>24) &&
|
||||
data[17] == (uint8_t)(m_stun_tansaction_id[2]>>16) &&
|
||||
data[18] == (uint8_t)(m_stun_tansaction_id[2]>>8 ) &&
|
||||
data[19] == (uint8_t)(m_stun_tansaction_id[2] ))
|
||||
{
|
||||
Log::verbose("GetPublicAddress", "The STUN server responded with a valid answer");
|
||||
int message_size = data[2]*256+data[3];
|
||||
|
||||
// parse the stun message now:
|
||||
bool finish = false;
|
||||
uint8_t* attributes = data+20;
|
||||
if (message_size == 0)
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN answer does not contain any information.");
|
||||
finish = true;
|
||||
}
|
||||
if (message_size < 4) // cannot even read the size
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN message is not valid.");
|
||||
finish = true;
|
||||
}
|
||||
uint16_t port;
|
||||
uint32_t address;
|
||||
bool valid = false;
|
||||
while(!finish)
|
||||
{
|
||||
int type = attributes[0]*256+attributes[1];
|
||||
int size = attributes[2]*256+attributes[3];
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
assert(size == 8);
|
||||
assert(attributes[5] = 0x01); // IPv4 only
|
||||
port = attributes[6]*256+attributes[7];
|
||||
address = (attributes[8]<<24 & 0xFF000000)+(attributes[9]<<16 & 0x00FF0000)+(attributes[10]<<8 & 0x0000FF00)+(attributes[11] & 0x000000FF);
|
||||
finish = true;
|
||||
valid = true;
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
attributes = attributes + 4 + size;
|
||||
message_size -= 4 + size;
|
||||
if (message_size == 0)
|
||||
finish = true;
|
||||
if (message_size < 4) // cannot even read the size
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN message is not valid.");
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
// finished parsing, we know our public transport address
|
||||
if (valid)
|
||||
{
|
||||
Log::debug("GetPublicAddress", "The public address has been found : %i.%i.%i.%i:%i", address>>24&0xff, address>>16&0xff, address>>8&0xff, address&0xff, port);
|
||||
m_state = ADDRESS_KNOWN;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(false);
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
addr->ip = address;
|
||||
addr->port = port;
|
||||
}
|
||||
else
|
||||
m_state = NOTHING_DONE; // need to re-send the stun request
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = NOTHING_DONE; // need to re-send the stun request
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_state == ADDRESS_KNOWN)
|
||||
{
|
||||
m_state = EXITING;
|
||||
// terminate the protocol
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
if (m_state == EXITING)
|
||||
{
|
||||
}
|
||||
}
|
@ -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,30 +16,34 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_RACE_RESULT_MESSAGE_HPP
|
||||
#define HEADER_RACE_RESULT_MESSAGE_HPP
|
||||
#ifndef GET_PUBLIC_ADDRESS_HPP
|
||||
#define GET_PUBLIC_ADDRESS_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/message.hpp"
|
||||
|
||||
|
||||
/** This message is from the server to all clients to inform them about the
|
||||
* result of a race. The clients wait for this message before they finish
|
||||
* a race.
|
||||
*/
|
||||
class RaceResultMessage : public Message
|
||||
class GetPublicAddress : public Protocol
|
||||
{
|
||||
struct RaceResult {
|
||||
float m_time;
|
||||
int m_score;
|
||||
}; // RaceResult
|
||||
private:
|
||||
std::vector<RaceResult> m_all_results;
|
||||
public:
|
||||
RaceResultMessage();
|
||||
RaceResultMessage(ENetPacket* pkt);
|
||||
void addRaceResult(int kart_id, float time, int points);
|
||||
void getRaceResult(int kart_id, float &time, int &points);
|
||||
}; // RaceResultMessage
|
||||
#endif
|
||||
public:
|
||||
GetPublicAddress(CallbackObject* callback_object);
|
||||
virtual ~GetPublicAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
enum STATE
|
||||
{
|
||||
NOTHING_DONE,
|
||||
TEST_SENT,
|
||||
ADDRESS_KNOWN,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
uint32_t m_stun_tansaction_id[3];
|
||||
static const uint32_t m_stun_magic_cookie = 0x2112A442;
|
||||
};
|
||||
|
||||
#endif // GET_PUBLIC_ADDRESS_HPP
|
86
src/network/protocols/hide_public_address.cpp
Normal file
86
src/network/protocols/hide_public_address.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
//
|
||||
// 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/protocols/hide_public_address.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
HidePublicAddress::HidePublicAddress() : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
HidePublicAddress::~HidePublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void HidePublicAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("action","unset");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
Log::debug("ShowPublicAddress", "Address hidden successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to hide address.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to hide address.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
@ -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,27 +16,34 @@
|
||||
// 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_NUM_PLAYERS_MESSAGE_HPP
|
||||
#define HEADER_NUM_PLAYERS_MESSAGE_HPP
|
||||
#ifndef HIDE_PUBLIC_ADDRESS_HPP
|
||||
#define HIDE_PUBLIC_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#ifndef WIN32
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "network/message.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
|
||||
class NumPlayersMessage : public Message
|
||||
class HidePublicAddress : public Protocol
|
||||
{
|
||||
private:
|
||||
int m_num_players
|
||||
public:
|
||||
NumPlayersMessage():Message(Message::MT_CONNECT) { m_num_players=race }
|
||||
NumPlayersMessage(ENetPacket* pkt):Message(pkt)
|
||||
{ m_id=getString(); }
|
||||
const std::string&
|
||||
getNumPlayers() { return m_num_players; }
|
||||
}; // ConnectMessage
|
||||
#endif
|
||||
public:
|
||||
HidePublicAddress();
|
||||
virtual ~HidePublicAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // HIDE_PUBLIC_ADDRESS_HPP
|
135
src/network/protocols/kart_update_protocol.cpp
Normal file
135
src/network/protocols/kart_update_protocol.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
#include "network/protocols/kart_update_protocol.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
|
||||
KartUpdateProtocol::KartUpdateProtocol()
|
||||
: Protocol(NULL, PROTOCOL_KART_UPDATE)
|
||||
{
|
||||
m_karts = World::getWorld()->getKarts();
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
//if (m_karts[i]->getWorldKartId())
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "Kart %d has id %d and name %s", i, m_karts[i]->getWorldKartId(), m_karts[i]->getIdent().c_str());
|
||||
}
|
||||
if (m_karts[i]->getIdent() == NetworkWorld::getInstance()->m_self_kart)
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "My id is %d", i);
|
||||
m_self_kart_index = i;
|
||||
}
|
||||
}
|
||||
pthread_mutex_init(&m_positions_updates_mutex, NULL);
|
||||
}
|
||||
|
||||
KartUpdateProtocol::~KartUpdateProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type != EVENT_TYPE_MESSAGE)
|
||||
return;
|
||||
NetworkString ns = event->data;
|
||||
if (ns.size() < 36)
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "Message too short.");
|
||||
return;
|
||||
}
|
||||
float game_time = ns.getFloat(0);
|
||||
ns.removeFront(4);
|
||||
while(ns.size() >= 16)
|
||||
{
|
||||
uint32_t kart_id = ns.getUInt32(0);
|
||||
|
||||
float a,b,c;
|
||||
a = ns.getFloat(4);
|
||||
b = ns.getFloat(8);
|
||||
c = ns.getFloat(12);
|
||||
float d,e,f,g;
|
||||
d = ns.getFloat(16);
|
||||
e = ns.getFloat(20);
|
||||
f = ns.getFloat(24);
|
||||
g = ns.getFloat(28);
|
||||
pthread_mutex_trylock(&m_positions_updates_mutex);
|
||||
m_next_positions.push_back(Vec3(a,b,c));
|
||||
m_next_quaternions.push_back(btQuaternion(d,e,f,g));
|
||||
m_karts_ids.push_back(kart_id);
|
||||
pthread_mutex_unlock(&m_positions_updates_mutex);
|
||||
ns.removeFront(32);
|
||||
}
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::setup()
|
||||
{
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::update()
|
||||
{
|
||||
static double time = 0;
|
||||
double current_time = Time::getRealTime();
|
||||
if (current_time > time + 0.1) // 10 updates per second
|
||||
{
|
||||
time = current_time;
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.af( World::getWorld()->getTime());
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
Vec3 v = kart->getXYZ();
|
||||
btQuaternion quat = kart->getRotation();
|
||||
ns.ai32( kart->getWorldKartId());
|
||||
ns.af(v[0]).af(v[1]).af(v[2]); // add position
|
||||
ns.af(quat.x()).af(quat.y()).af(quat.z()).af(quat.w()); // add rotation
|
||||
Log::verbose("KartUpdateProtocol", "Sending %d's positions %f %f %f", kart->getWorldKartId(), v[0], v[1], v[2]);
|
||||
}
|
||||
m_listener->sendMessage(this, ns, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AbstractKart* kart = m_karts[m_self_kart_index];
|
||||
Vec3 v = kart->getXYZ();
|
||||
btQuaternion quat = kart->getRotation();
|
||||
NetworkString ns;
|
||||
ns.af( World::getWorld()->getTime());
|
||||
ns.ai32( kart->getWorldKartId());
|
||||
ns.af(v[0]).af(v[1]).af(v[2]); // add position
|
||||
ns.af(quat.x()).af(quat.y()).af(quat.z()).af(quat.w()); // add rotation
|
||||
Log::verbose("KartUpdateProtocol", "Sending %d's positions %f %f %f", kart->getWorldKartId(), v[0], v[1], v[2]);
|
||||
m_listener->sendMessage(this, ns, false);
|
||||
}
|
||||
}
|
||||
switch(pthread_mutex_trylock(&m_positions_updates_mutex))
|
||||
{
|
||||
case 0: /* if we got the lock */
|
||||
while (!m_next_positions.empty())
|
||||
{
|
||||
uint32_t id = m_karts_ids.back();
|
||||
if (id != m_self_kart_index || m_listener->isServer()) // server takes all updates
|
||||
{
|
||||
Vec3 pos = m_next_positions.back();
|
||||
btTransform transform = m_karts[id]->getBody()->getInterpolationWorldTransform();
|
||||
transform.setOrigin(pos);
|
||||
transform.setRotation(m_next_quaternions.back());
|
||||
m_karts[id]->getBody()->setCenterOfMassTransform(transform);
|
||||
//m_karts[id]->getBody()->setLinearVelocity(Vec3(0,0,0));
|
||||
Log::verbose("KartUpdateProtocol", "Update kart %i pos to %f %f %f", id, pos[0], pos[1], pos[2]);
|
||||
}
|
||||
m_next_positions.pop_back();
|
||||
m_next_quaternions.pop_back();
|
||||
m_karts_ids.pop_back();
|
||||
}
|
||||
pthread_mutex_unlock(&m_positions_updates_mutex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
33
src/network/protocols/kart_update_protocol.hpp
Normal file
33
src/network/protocols/kart_update_protocol.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef KART_UPDATE_PROTOCOL_HPP
|
||||
#define KART_UPDATE_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
#include <list>
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
class KartUpdateProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
KartUpdateProtocol();
|
||||
virtual ~KartUpdateProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {};
|
||||
|
||||
protected:
|
||||
std::vector<AbstractKart*> m_karts;
|
||||
uint32_t m_self_kart_index;
|
||||
|
||||
std::list<Vec3> m_next_positions;
|
||||
std::list<btQuaternion> m_next_quaternions;
|
||||
std::list<uint32_t> m_karts_ids;
|
||||
|
||||
pthread_mutex_t m_positions_updates_mutex;
|
||||
};
|
||||
|
||||
#endif // KART_UPDATE_PROTOCOL_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,18 +16,16 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_RACE_INFO_MESSAGE_HPP
|
||||
#define HEADER_RACE_INFO_MESSAGE_HPP
|
||||
#include "network/protocols/lobby_room_protocol.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "network/message.hpp"
|
||||
#include "network/remote_kart_info.hpp"
|
||||
|
||||
class RaceInfoMessage : public Message
|
||||
LobbyRoomProtocol::LobbyRoomProtocol(CallbackObject* callback_object) :
|
||||
Protocol(callback_object, PROTOCOL_LOBBY_ROOM)
|
||||
{
|
||||
public:
|
||||
RaceInfoMessage(const std::vector<RemoteKartInfo>& kart_info);
|
||||
RaceInfoMessage(ENetPacket* pkt);
|
||||
}; // RaceInfoMessage
|
||||
#endif
|
||||
m_setup = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LobbyRoomProtocol::~LobbyRoomProtocol()
|
||||
{
|
||||
}
|
47
src/network/protocols/lobby_room_protocol.hpp
Normal file
47
src/network/protocols/lobby_room_protocol.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// 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 LOBBY_ROOM_PROTOCOL_HPP
|
||||
#define LOBBY_ROOM_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
/*!
|
||||
* \class LobbyRoomProtocol
|
||||
* \brief Class used while the game is being prepared.
|
||||
* This protocol starts when a server opens a game, or when a client joins a game.
|
||||
* It is used to exchange data about the race settings, like kart selection.
|
||||
*/
|
||||
class LobbyRoomProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
LobbyRoomProtocol(CallbackObject* callback_object);
|
||||
virtual ~LobbyRoomProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event) = 0;
|
||||
virtual void setup() = 0;
|
||||
virtual void update() = 0;
|
||||
|
||||
protected:
|
||||
GameSetup* m_setup; //!< The game setup.
|
||||
};
|
||||
|
||||
#endif // LOBBY_ROOM_PROTOCOL_HPP
|
52
src/network/protocols/ping_protocol.cpp
Normal file
52
src/network/protocols/ping_protocol.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// 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/protocols/ping_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
PingProtocol::PingProtocol(const TransportAddress& ping_dst, double delay_between_pings) : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
m_ping_dst = ping_dst;
|
||||
m_delay_between_pings = delay_between_pings;
|
||||
}
|
||||
|
||||
PingProtocol::~PingProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::setup()
|
||||
{
|
||||
m_last_ping_time = 0;
|
||||
}
|
||||
|
||||
void PingProtocol::asynchronousUpdate()
|
||||
{
|
||||
if (Time::getRealTime() > m_last_ping_time+m_delay_between_pings)
|
||||
{
|
||||
m_last_ping_time = Time::getRealTime();
|
||||
uint8_t data = 0;
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(&data, 1, m_ping_dst);
|
||||
Log::info("PingProtocol", "Ping message sent");
|
||||
}
|
||||
}
|
24
src/network/protocols/ping_protocol.hpp
Normal file
24
src/network/protocols/ping_protocol.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef PING_PROTOCOL_HPP
|
||||
#define PING_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
|
||||
class PingProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
PingProtocol(const TransportAddress& ping_dst, double delay_between_pings);
|
||||
virtual ~PingProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_ping_dst;
|
||||
double m_delay_between_pings;
|
||||
double m_last_ping_time;
|
||||
};
|
||||
|
||||
#endif // PING_PROTOCOL_HPP
|
92
src/network/protocols/quick_join_protocol.cpp
Normal file
92
src/network/protocols/quick_join_protocol.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
//
|
||||
// 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 "quick_join_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
QuickJoinProtocol::QuickJoinProtocol(CallbackObject* callback_object, uint32_t* server_id) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
m_server_id = server_id;
|
||||
}
|
||||
|
||||
QuickJoinProtocol::~QuickJoinProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("action","quick-join");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
TransportAddress* res = static_cast<TransportAddress*>(m_callback_object);
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
result->get("ip", &res->ip);
|
||||
result->get("port", &res->port);
|
||||
result->get("hostid", m_server_id);
|
||||
Log::info("QuickJoinProtocol", "Quick joining %d:%d (server#%d).", res->ip, res->port, *m_server_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("QuickJoinProtocol", "Fail to quick join.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("QuickJoinProtocol", "Fail to quick join.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
31
src/network/protocols/quick_join_protocol.hpp
Normal file
31
src/network/protocols/quick_join_protocol.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef QUICK_JOIN_PROTOCOL_HPP
|
||||
#define QUICK_JOIN_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
class QuickJoinProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
QuickJoinProtocol(CallbackObject* callback_object, uint32_t* server_id);
|
||||
virtual ~QuickJoinProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
uint32_t* m_server_id;
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // QUICK_JOIN_PROTOCOL_HPP
|
97
src/network/protocols/request_connection.cpp
Normal file
97
src/network/protocols/request_connection.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// 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/protocols/request_connection.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
RequestConnection::RequestConnection(uint32_t server_id) : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
m_server_id = server_id;
|
||||
}
|
||||
|
||||
RequestConnection::~RequestConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void RequestConnection::asynchronousUpdate()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
m_request = new Online::CurrentUser::ServerJoinRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getUserID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("server_id",m_server_id);
|
||||
m_request->setParameter("action","request-connection");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
break;
|
||||
}
|
||||
case REQUEST_PENDING:
|
||||
{
|
||||
if (!m_request->isDone())
|
||||
return;
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if (rec_success == "yes")
|
||||
{
|
||||
Log::debug("RequestConnection", "Connection Request made successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("RequestConnection", "Fail to make a request to connecto to server %d", m_server_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("RequestConnection", "Fail to make a request.");
|
||||
}
|
||||
m_state = DONE;
|
||||
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user