had forgot to add new files

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13209 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-07-13 23:16:40 +00:00
parent c1534075d3
commit 2f08ee8902
9 changed files with 661 additions and 0 deletions

View File

@ -0,0 +1,366 @@
#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();
} // 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

View 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

View File

@ -24,6 +24,7 @@
#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"

View File

@ -0,0 +1,17 @@
#include "network/network_world.hpp"
#include "modes/world.hpp"
NetworkWorld::NetworkWorld()
{
m_running = false;
}
NetworkWorld::~NetworkWorld()
{
}
void NetworkWorld::update(float dt)
{
World::getWorld()->updateWorld(dt);
}

View File

@ -0,0 +1,28 @@
#ifndef NETWORK_WORLD_HPP
#define NETWORK_WORLD_HPP
#include "network/singleton.hpp"
/*! \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; }
protected:
bool m_running;
float m_race_time;
private:
NetworkWorld();
virtual ~NetworkWorld();
};
#endif // NETWORK_WORLD_HPP

View File

@ -0,0 +1,37 @@
#include "network/protocols/start_game_protocol.hpp"
#include "network/game_setup.hpp"
StartGameProtocol::StartGameProtocol(GameSetup* game_setup) :
Protocol(NULL, PROTOCOL_START_GAME)
{
m_game_setup = game_setup;
std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
for (unsigned int i = 0; i < players.size(); i++)
{
m_player_states.push_back(std::pair<NetworkPlayerProfile*, STATE>(players[i], LOADING));
}
}
StartGameProtocol::~StartGameProtocol()
{
}
void StartGameProtocol::notifyEvent(Event* event)
{
}
void StartGameProtocol::setup()
{
m_state = LOADING;
}
void StartGameProtocol::update()
{
if (m_state == LOADING)
{
}
else if (m_state == READY)
{
}
}

View File

@ -0,0 +1,29 @@
#ifndef START_GAME_PROTOCOL_HPP
#define START_GAME_PROTOCOL_HPP
#include "network/protocol.hpp"
class GameSetup;
class NetworkPlayerProfile;
class StartGameProtocol : public Protocol
{
protected:
enum STATE { LOADING, READY };
std::vector<std::pair<NetworkPlayerProfile*, STATE> > m_player_states;
GameSetup* m_game_setup;
STATE m_state;
public:
StartGameProtocol(GameSetup* game_setup);
virtual ~StartGameProtocol();
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
};
#endif // START_GAME_PROTOCOL_HPP

View File

@ -0,0 +1,107 @@
#include "network/protocols/synchronization_protocol.hpp"
#include "network/network_manager.hpp"
#include "utils/time.hpp"
//-----------------------------------------------------------------------------
SynchronizationProtocol::SynchronizationProtocol(uint32_t* ping, bool* successed) : Protocol(NULL, PROTOCOL_SYNCHRONIZATION)
{
m_average_ping = ping;
m_successed = successed;
m_pings.resize(NetworkManager::getInstance()->getPeerCount(), std::vector<std::pair<double,double> >(0));
m_pings_count = 0;
m_successed_pings = 0;
m_total_diff = 0;
}
//-----------------------------------------------------------------------------
SynchronizationProtocol::~SynchronizationProtocol()
{
}
//-----------------------------------------------------------------------------
void SynchronizationProtocol::notifyEvent(Event* event)
{
if (event->data.size() < 10)
{
Log::warn("SynchronizationProtocol", "Received a message too short.");
return;
}
uint8_t talk_id = event->data.gui8(0);
uint32_t token = event->data.gui32(1);
uint32_t request = event->data.gui8(5);
uint32_t sequence = event->data.gui32(6);
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
if (m_listener->isServer())
{
if (talk_id > peers.size())
{
Log::warn("SynchronizationProtocol", "The ID isn't known.");
return;
}
}
uint8_t peer_id = (m_listener->isServer() ? talk_id : 0); // on clients, peer index is 0
if (peers[peer_id]->getClientServerToken() != token)
{
Log::warn("SynchronizationProtocol", "Bad token from peer %d", talk_id);
return;
}
if (request)
{
NetworkString response;
response.ai8(event->data.gui8(talk_id)).ai32(token).ai8(0).ai32(sequence);
m_listener->sendMessage(this, peers[talk_id], response, false);
}
else // response
{
if (sequence < m_pings[peer_id].size())
{
Log::warn("SynchronizationProtocol", "The sequence isn't known.");
return;
}
m_pings[peer_id][sequence].second = Time::getRealTime();
m_total_diff += (m_pings[peer_id][sequence].second - m_pings[peer_id][sequence].first);
m_successed_pings++;
*m_average_ping = (int)((m_total_diff/m_successed_pings)*1000.0);
if ( *m_successed == false && m_successed_pings > 5)
{
*m_successed = true; // success after 5 pings (we have good idea of ping)
}
Log::info("SynchronizationProtocol", "Ping is %u", m_average_ping);
}
}
//-----------------------------------------------------------------------------
void SynchronizationProtocol::setup()
{
}
//-----------------------------------------------------------------------------
void SynchronizationProtocol::update()
{
static double timer = Time::getRealTime();
if (Time::getRealTime() > timer+100 && m_pings_count < 100) // max 100 pings (10 seconds)
{
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
for (unsigned int i = 0; i < peers.size(); i++)
{
NetworkString ns;
ns.ai8(i).addUInt32(peers[i]->getClientServerToken()).addUInt8(1).addUInt32(m_pings_count);
timer = Time::getRealTime();
m_pings[i].push_back(std::pair<double, double>(timer, 0.0));
m_listener->sendMessage(this, peers[i], ns, false);
}
m_pings_count++;
}
}
//-----------------------------------------------------------------------------

View File

@ -0,0 +1,28 @@
#ifndef SYNCHRONIZATION_PROTOCOL_HPP
#define SYNCHRONIZATION_PROTOCOL_HPP
#include "network/protocol.hpp"
#include <list>
#include <utility>
class SynchronizationProtocol : public Protocol
{
public:
SynchronizationProtocol(uint32_t* ping, bool* successed);
virtual ~SynchronizationProtocol();
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
protected:
//!< stores the start time / arrival time of packets for each peer
std::vector<std::vector<std::pair<double, double> > > m_pings;
uint32_t* m_average_ping;
uint32_t m_pings_count;
uint32_t m_successed_pings;
double m_total_diff;
bool* m_successed;
};
#endif // SYNCHRONIZATION_PROTOCOL_HPP