This patch is become useless with r6623 from yourself :)

Thanks,

Matt (gentildemon)


Florian Köberle a écrit :
> Why is it necessary?
>
> Extreme example: The game time is 59,9 seconds and the turn master orders the 
> character to jump in oder to save him from the water which will increase in 
> 0.1 seconds.
> It's important that the non turn master does not continue the game to the 
> 60th game second, if it hasn't received the jump action yet. Otherwise the 
> non turn master will see the character drown and no resurrection system can 
> bring him back as the water has already risen.
>
> How to detect that there are no further actions for the current physics frame?
>
> If there had been actions in a physics frame wormux will send now one "echo" 
> action at the end of the physics frame.
> The non turn masters knows when receiving it that they can render all physics 
> frames until that time.
> ---
>  lib/wormux/include/WORMUX_action.h |    2 +-
>  src/game/game.cpp                  |    1 +
>  src/game/time.cpp                  |   35 +++++++++++++++++++++--------------
>  src/game/time.h                    |    4 ++--
>  src/include/action_handler.cpp     |   30 ++++++++++++++++++++++++++++--
>  src/network/network.cpp            |   21 +++++++++++++++++----
>  src/network/network.h              |   11 ++++++-----
>  src/network/network_local.cpp      |    2 +-
>  src/network/network_local.h        |    2 +-
>  9 files changed, 78 insertions(+), 30 deletions(-)
>
> diff --git a/lib/wormux/include/WORMUX_action.h 
> b/lib/wormux/include/WORMUX_action.h
> index 14238c9..4f9dc21 100644
> --- a/lib/wormux/include/WORMUX_action.h
> +++ b/lib/wormux/include/WORMUX_action.h
> @@ -106,7 +106,7 @@ public:
>      ACTION_NETWORK_RANDOM_INIT,
>      ACTION_INFO_CLIENT_CONNECT,
>      ACTION_INFO_CLIENT_DISCONNECT,
> -
> +    ACTION_ECHO,
>      // ########################################################
>    } Action_t;
>  
> diff --git a/src/game/game.cpp b/src/game/game.cpp
> index d24bd99..70df1d8 100644
> --- a/src/game/game.cpp
> +++ b/src/game/game.cpp
> @@ -552,6 +552,7 @@ void Game::MainLoop()
>      }
>    }
>  #endif
> +  Network::GetInstance()->SendEcho();
>  
>    delay = time_of_next_phy_frame - Time::GetInstance()->ReadRealTime();
>    if (delay >= 0)
> diff --git a/src/game/time.cpp b/src/game/time.cpp
> index c345817..05ec829 100644
> --- a/src/game/time.cpp
> +++ b/src/game/time.cpp
> @@ -19,7 +19,11 @@
>   *  Handle the game time. The game can be paused.
>   
> *****************************************************************************/
>  
> +#include "game/game.h"
>  #include "game/time.h"
> +#include "network/network.h"
> +#include "team/team.h"
> +#include "team/teams_list.h"
>  #include <SDL.h>
>  #include <sstream>
>  #include <iomanip>
> @@ -34,7 +38,7 @@ Time::Time()
>    is_game_paused = false;
>    delta_t = 20;
>    current_time = 0;
> -  //max_time = 0;
> +  max_time_plus_one = 0;
>    real_time_game_start = 0;
>    real_time_pause_dt = 0;
>  }
> @@ -42,6 +46,7 @@ Time::Time()
>  void Time::Reset()
>  {
>    current_time = 0;
> +  max_time_plus_one = 0;
>    is_game_paused = false;
>    real_time_game_start = SDL_GetTicks();
>    real_time_pause_dt = 0;
> @@ -55,19 +60,21 @@ uint Time::ReadRealTime() const
>  
>  void Time::Refresh()
>  {
> -  /*
> -  TODO : Activate this condition later.
> -  Refresh time condition :
> -  - active team is Local
> -  - current node is server and game loop is not in Playing state
> -  - game don't use network
> -  if((ActiveTeam().IsLocal() || ActiveTeam().IsLocalAI()) ||
> -     (Network::GetInstance()->IsServer() && Game::GetInstance()->ReadState() 
> != Game::PLAYING) ||
> -     (!Network::GetInstance()->IsServer() && 
> !Network::GetInstance()->IsClient()) ||
> -     current_time < max_time)
> -  */
> -  current_time += delta_t;
> -  //RefreshMaxTime(current_time);
> +  uint newValue = current_time + delta_t;
> +  bool activeTeamLocal = ActiveTeam().IsLocal() || ActiveTeam().IsLocalAI();
> +  bool serverButNotPlaying = Network::GetInstance()->IsServer() && 
> Game::GetInstance()->ReadState() != Game::PLAYING;
> +  bool noNetworkGame = !Network::GetInstance()->IsServer() && 
> !Network::GetInstance()->IsClient();
> +  bool ignoreMaxTime = activeTeamLocal || serverButNotPlaying || 
> noNetworkGame;
> +  if (ignoreMaxTime || (newValue < max_time_plus_one))
> +    current_time = newValue;
> +  else
> +    real_time_pause_dt += delta_t;
> +}
> +
> +void Time::RefreshMaxTimePlusOne(uint updated_max_time_plus_one)
> +{
> +  if (updated_max_time_plus_one >= max_time_plus_one)
> +    max_time_plus_one = updated_max_time_plus_one;
>  }
>  
>  void Time::TogglePause()
> diff --git a/src/game/time.h b/src/game/time.h
> index 193c8e9..edb9109 100644
> --- a/src/game/time.h
> +++ b/src/game/time.h
> @@ -31,7 +31,7 @@ class Time : public Singleton<Time>
>  {
>  private:
>    uint        current_time;
> -  //uint        max_time;
> +  uint        max_time_plus_one;
>    uint        delta_t;
>    bool        is_game_paused;
>  
> @@ -59,7 +59,7 @@ public:
>    uint ReadMin() const { return ReadSec() / 60; };
>    void Refresh();
>    uint GetDelta() const { return delta_t; };
> -  //void RefreshMaxTime(uint updated_max_time);
> +  void RefreshMaxTimePlusOne(uint updated_max_time_plus_one);
>  
>    // Read the clock time
>    uint ClockSec() const { return ReadSec() % 60; };
> diff --git a/src/include/action_handler.cpp b/src/include/action_handler.cpp
> index df17a05..f22348d 100644
> --- a/src/include/action_handler.cpp
> +++ b/src/include/action_handler.cpp
> @@ -825,6 +825,11 @@ static void Action_Network_Ping(Action */*a*/)
>  {
>  }
>  
> +// Nothing to do here. The action handler will use the timestamp to set the 
> maximal time.
> +static void Action_Echo(Action */*a*/)
> +{
> +}
> +
>  // ########################################################
>  
>  static void _Info_ConnectHost(const std::string& hostname, const 
> std::string& nicknames)
> @@ -1084,7 +1089,7 @@ void Action_Handler_Init()
>    ActionHandler::GetInstance()->Register 
> (Action::ACTION_NETWORK_RANDOM_INIT, "NETWORK_random_init", 
> &Action_Network_RandomInit);
>    ActionHandler::GetInstance()->Register 
> (Action::ACTION_INFO_CLIENT_DISCONNECT, "INFO_client_disconnect", 
> &Action_Info_ClientDisconnect);
>    ActionHandler::GetInstance()->Register 
> (Action::ACTION_INFO_CLIENT_CONNECT, "INFO_client_connect", 
> &Action_Info_ClientConnect);
> -
> +  ActionHandler::GetInstance()->Register (Action::ACTION_ECHO, 
> "ACTION_echo", &Action_Echo);
>    // ########################################################
>    ActionHandler::GetInstance()->UnLock();
>  }
> @@ -1106,11 +1111,32 @@ void ActionHandler::ExecActions()
>  {
>    Action * a;
>    std::list<Action*>::iterator it;
> +  Time * time = Time::GetInstance();
> +
> +  // The game can continue until the point at which all actions are known.
> +  // If for example a non turn master receives:
> +  // 5s game time: jump
> +  // 6s game time: jump
> +  // then the game can continue until the game time is (6s - smallest time 
> unit).
> +  // The physics frame for the 6th game second must not be calculated
> +  // as more actions for the 6th game second might be received in future.
> +  for (it = queue.begin(); it != queue.end() ;it++)
> +  {
> +    Lock();
> +    a = (*it);
> +    // The action echo gets send at the end of a physics frame:
> +    // No more physic related actions are expected for the current frame.
> +    if (a->GetType() == Action::ACTION_ECHO)
> +      time->RefreshMaxTimePlusOne(a->GetTimestamp() + 1);
> +    else
> +      time->RefreshMaxTimePlusOne(a->GetTimestamp());
> +    UnLock();
> +  }
> +
>    for (it = queue.begin(); it != queue.end() ;)
>    {
>      Lock();
>      a = (*it);
> -    //Time::GetInstance()->RefreshMaxTime((*it)->GetTimestamp());
>      // If action is in the future, wait for next refresh
>      if (a->GetTimestamp() > Time::GetInstance()->Read()) {
>        UnLock();
> diff --git a/src/network/network.cpp b/src/network/network.cpp
> index da56cab..5652b5c 100644
> --- a/src/network/network.cpp
> +++ b/src/network/network.cpp
> @@ -340,7 +340,7 @@ void Network::DisconnectNetwork()
>  
> //-----------------------------------------------------------------------------
>  
>  // Send Messages
> -void Network::SendActionToAll(const Action& a) const
> +void Network::SendActionToAll(const Action& a)
>  {
>    MSG_DEBUG("network.traffic","Send action %s to all remote computers",
>              
> ActionHandler::GetInstance()->GetActionName(a.GetType()).c_str());
> @@ -348,7 +348,7 @@ void Network::SendActionToAll(const Action& a) const
>    SendAction(a, NULL, false);
>  }
>  
> -void Network::SendActionToOne(const Action& a, DistantComputer* client) const
> +void Network::SendActionToOne(const Action& a, DistantComputer* client)
>  {
>    MSG_DEBUG("network.traffic","Send action %s to %s (%s)",
>              ActionHandler::GetInstance()->GetActionName(a.GetType()).c_str(),
> @@ -357,7 +357,7 @@ void Network::SendActionToOne(const Action& a, 
> DistantComputer* client) const
>    SendAction(a, client, true);
>  }
>  
> -void Network::SendActionToAllExceptOne(const Action& a, DistantComputer* 
> client) const
> +void Network::SendActionToAllExceptOne(const Action& a, DistantComputer* 
> client)
>  {
>    MSG_DEBUG("network.traffic","Send action %s to all EXCEPT %s",
>              ActionHandler::GetInstance()->GetActionName(a.GetType()).c_str(),
> @@ -369,11 +369,13 @@ void Network::SendActionToAllExceptOne(const Action& a, 
> DistantComputer* client)
>  // if (client == NULL) sending to every clients
>  // if (clt_as_rcver) sending only to client 'client'
>  // if (!clt_as_rcver) sending to all EXCEPT client 'client'
> -void Network::SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver) const
> +void Network::SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver)
>  {
>    char* packet;
>    int size;
>  
> +  echo_outstanding = true;
> +
>    a.WriteToPacket(packet, size);
>    ASSERT(packet != NULL);
>  
> @@ -405,6 +407,17 @@ void Network::SendAction(const Action& a, 
> DistantComputer* client, bool clt_as_r
>    free(packet);
>  }
>  
> +void Network::SendEcho() {
> +  if (echo_outstanding)
> +  {
> +    Action a(Action::ACTION_ECHO);
> +    SendActionToAll(a);
> +
> +    // this must be set after SendActionToAll as SendActionToAll would set 
> it to true otherwise.
> +    echo_outstanding = false;
> +  }
> +}
> +
>  
> //-----------------------------------------------------------------------------
>  
>  // Static method
> diff --git a/src/network/network.h b/src/network/network.h
> index 1a1964b..a9bd1c2 100644
> --- a/src/network/network.h
> +++ b/src/network/network.h
> @@ -85,7 +85,7 @@ private:
>  
>    Player player;
>    bool turn_master_player;
> -
> +  bool echo_outstanding;
>  protected:
>    bool game_master_player;
>    WNet::net_game_state_t state;
> @@ -99,7 +99,7 @@ protected:
>    int fin;
>  #endif
>  
> -  virtual void SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver) const;
> +  virtual void SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver);
>  
>    void DisconnectNetwork();
>  
> @@ -150,9 +150,10 @@ public:
>    virtual void CloseConnection(std::list<DistantComputer*>::iterator closed) 
> = 0;
>  
>    // Action handling
> -  void SendActionToAll(const Action& action) const;
> -  void SendActionToOne(const Action& action, DistantComputer* client) const;
> -  void SendActionToAllExceptOne(const Action& action, DistantComputer* 
> client) const;
> +  void SendActionToAll(const Action& action);
> +  void SendActionToOne(const Action& action, DistantComputer* client);
> +  void SendActionToAllExceptOne(const Action& action, DistantComputer* 
> client);
> +  void SendEcho();
>  
>    // Manage network state
>    void SetState(WNet::net_game_state_t state);
> diff --git a/src/network/network_local.cpp b/src/network/network_local.cpp
> index 48c70e6..3e6cc14 100644
> --- a/src/network/network_local.cpp
> +++ b/src/network/network_local.cpp
> @@ -25,7 +25,7 @@ NetworkLocal::NetworkLocal() : Network("-", "") {}
>  
>  NetworkLocal::~NetworkLocal() {}
>  
> -void NetworkLocal::SendAction(const Action& /*a*/, DistantComputer* 
> /*client*/, bool /*clt_as_rcver*/) const {}
> +void NetworkLocal::SendAction(const Action& /*a*/, DistantComputer* 
> /*client*/, bool /*clt_as_rcver*/) {}
>  
>  void NetworkLocal::CloseConnection(std::list<DistantComputer*>::iterator 
> /*closed*/)
>  {
> diff --git a/src/network/network_local.h b/src/network/network_local.h
> index 6d29dbc..727a577 100644
> --- a/src/network/network_local.h
> +++ b/src/network/network_local.h
> @@ -30,7 +30,7 @@ class NetworkLocal : public Network
>  protected:
>    virtual void HandleAction(Action* /*a*/, DistantComputer* /*sender*/) { 
> ASSERT(false) };
>    virtual void WaitActionSleep() { ASSERT(false) };
> -  virtual void SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver) const;
> +  virtual void SendAction(const Action& a, DistantComputer* client, bool 
> clt_as_rcver);
>  
>  public:
>    NetworkLocal();
>   


_______________________________________________
Wormux-dev mailing list
Wormux-dev@gna.org
https://mail.gna.org/listinfo/wormux-dev

Répondre à