Add initial live join handling for the one who does it
This commit is contained in:
parent
0431344886
commit
2f8da236e3
@ -193,7 +193,8 @@ bool LocalPlayerController::action(PlayerAction action, int value,
|
|||||||
// If this is a client, send the action to networking layer
|
// If this is a client, send the action to networking layer
|
||||||
if (NetworkConfig::get()->isNetworking() &&
|
if (NetworkConfig::get()->isNetworking() &&
|
||||||
NetworkConfig::get()->isClient() &&
|
NetworkConfig::get()->isClient() &&
|
||||||
!RewindManager::get()->isRewinding())
|
!RewindManager::get()->isRewinding() &&
|
||||||
|
World::getWorld() && !World::getWorld()->isLiveJoinWorld())
|
||||||
{
|
{
|
||||||
if (auto gp = GameProtocol::lock())
|
if (auto gp = GameProtocol::lock())
|
||||||
{
|
{
|
||||||
|
@ -1412,7 +1412,7 @@ void Kart::update(int ticks)
|
|||||||
|
|
||||||
// Hover the kart above reset position before entering the game
|
// Hover the kart above reset position before entering the game
|
||||||
if (m_live_join_util != 0 &&
|
if (m_live_join_util != 0 &&
|
||||||
(m_live_join_util < World::getWorld()->getTicksSinceStart() ||
|
(m_live_join_util > World::getWorld()->getTicksSinceStart() ||
|
||||||
World::getWorld()->isLiveJoinWorld()))
|
World::getWorld()->isLiveJoinWorld()))
|
||||||
{
|
{
|
||||||
btRigidBody *body = getBody();
|
btRigidBody *body = getBody();
|
||||||
|
@ -326,6 +326,8 @@ public:
|
|||||||
unsigned int getCurrentNumPlayers() const { return m_num_players -
|
unsigned int getCurrentNumPlayers() const { return m_num_players -
|
||||||
m_eliminated_players;}
|
m_eliminated_players;}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
virtual void addReservedKart(int kart_id) { m_eliminated_karts--; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** The code that draws the timer should call this first to know
|
/** The code that draws the timer should call this first to know
|
||||||
* whether the game mode wants a timer drawn. */
|
* whether the game mode wants a timer drawn. */
|
||||||
virtual bool shouldDrawTimer() const
|
virtual bool shouldDrawTimer() const
|
||||||
|
@ -275,7 +275,7 @@ void WorldStatus::updateTime(int ticks)
|
|||||||
// Add 3 seconds delay before telling server finish loading
|
// Add 3 seconds delay before telling server finish loading
|
||||||
// world, so previous (if any) disconnected player has left
|
// world, so previous (if any) disconnected player has left
|
||||||
// fully
|
// fully
|
||||||
if (m_auxiliary_ticks == 360)
|
if (m_auxiliary_ticks == stk_config->time2Ticks(3.0f))
|
||||||
{
|
{
|
||||||
auto lobby = LobbyProtocol::get<LobbyProtocol>();
|
auto lobby = LobbyProtocol::get<LobbyProtocol>();
|
||||||
assert(lobby);
|
assert(lobby);
|
||||||
@ -545,4 +545,8 @@ void WorldStatus::endLiveJoinWorld(int ticks_now)
|
|||||||
{
|
{
|
||||||
m_live_join_world = false;
|
m_live_join_world = false;
|
||||||
m_auxiliary_ticks = 0;
|
m_auxiliary_ticks = 0;
|
||||||
|
m_phase = RACE_PHASE;
|
||||||
|
startEngines();
|
||||||
|
music_manager->startMusic();
|
||||||
|
setTicksForRewind(ticks_now);
|
||||||
} // endLiveJoinWorld
|
} // endLiveJoinWorld
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "input/device_manager.hpp"
|
#include "input/device_manager.hpp"
|
||||||
#include "items/item_manager.hpp"
|
#include "items/item_manager.hpp"
|
||||||
#include "items/powerup_manager.hpp"
|
#include "items/powerup_manager.hpp"
|
||||||
|
#include "karts/abstract_kart.hpp"
|
||||||
|
#include "karts/controller/controller.hpp"
|
||||||
#include "karts/kart_properties_manager.hpp"
|
#include "karts/kart_properties_manager.hpp"
|
||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "network/crypto.hpp"
|
#include "network/crypto.hpp"
|
||||||
@ -109,6 +111,8 @@ ClientLobby::~ClientLobby()
|
|||||||
void ClientLobby::setup()
|
void ClientLobby::setup()
|
||||||
{
|
{
|
||||||
m_auto_back_to_lobby_time = std::numeric_limits<uint64_t>::max();
|
m_auto_back_to_lobby_time = std::numeric_limits<uint64_t>::max();
|
||||||
|
m_start_live_game_time = std::numeric_limits<uint64_t>::max();
|
||||||
|
m_live_join_ticks = -1;
|
||||||
m_received_server_result = false;
|
m_received_server_result = false;
|
||||||
TracksScreen::getInstance()->resetVote();
|
TracksScreen::getInstance()->resetVote();
|
||||||
LobbyProtocol::setup();
|
LobbyProtocol::setup();
|
||||||
@ -155,6 +159,7 @@ bool ClientLobby::notifyEvent(Event* event)
|
|||||||
case LE_SERVER_OWNERSHIP: becomingServerOwner(); break;
|
case LE_SERVER_OWNERSHIP: becomingServerOwner(); break;
|
||||||
case LE_BAD_TEAM: handleBadTeam(); break;
|
case LE_BAD_TEAM: handleBadTeam(); break;
|
||||||
case LE_BAD_CONNECTION: handleBadConnection(); break;
|
case LE_BAD_CONNECTION: handleBadConnection(); break;
|
||||||
|
case LE_LIVE_JOIN_ACK: liveJoinAcknowledged(event); break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@ -272,6 +277,22 @@ void ClientLobby::addAllPlayers(Event* event)
|
|||||||
// Disable until render gui during loading is bug free
|
// Disable until render gui during loading is bug free
|
||||||
//StateManager::get()->enterGameState();
|
//StateManager::get()->enterGameState();
|
||||||
|
|
||||||
|
// Live join if state is CONNECTED
|
||||||
|
if (m_state.load() == CONNECTED)
|
||||||
|
{
|
||||||
|
World* w = World::getWorld();
|
||||||
|
w->setLiveJoinWorld(true);
|
||||||
|
for (unsigned i = 0; i < w->getNumKarts(); i++)
|
||||||
|
{
|
||||||
|
AbstractKart* k = w->getKart(i);
|
||||||
|
// The final joining ticks will be set by server later
|
||||||
|
if (k->getController()->isLocalPlayerController())
|
||||||
|
k->setLiveJoinKart(-1);
|
||||||
|
else
|
||||||
|
k->getNode()->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to assign mode in case a player hasn't chosen any karts
|
// Switch to assign mode in case a player hasn't chosen any karts
|
||||||
input_manager->getDeviceManager()->setAssignMode(ASSIGN);
|
input_manager->getDeviceManager()->setAssignMode(ASSIGN);
|
||||||
} // addAllPlayers
|
} // addAllPlayers
|
||||||
@ -374,6 +395,11 @@ void ClientLobby::update(int ticks)
|
|||||||
break;
|
break;
|
||||||
case REQUESTING_CONNECTION:
|
case REQUESTING_CONNECTION:
|
||||||
case CONNECTED:
|
case CONNECTED:
|
||||||
|
if (m_start_live_game_time != std::numeric_limits<uint64_t>::max() &&
|
||||||
|
STKHost::get()->getNetworkTimer() >= m_start_live_game_time)
|
||||||
|
{
|
||||||
|
finishLiveJoin();
|
||||||
|
}
|
||||||
if (NetworkConfig::get()->isAutoConnect() && !m_auto_started)
|
if (NetworkConfig::get()->isAutoConnect() && !m_auto_started)
|
||||||
{
|
{
|
||||||
// Send a message to the server to start
|
// Send a message to the server to start
|
||||||
@ -931,7 +957,51 @@ void ClientLobby::exitResultScreen(Event *event)
|
|||||||
void ClientLobby::finishedLoadingWorld()
|
void ClientLobby::finishedLoadingWorld()
|
||||||
{
|
{
|
||||||
NetworkString* ns = getNetworkString(1);
|
NetworkString* ns = getNetworkString(1);
|
||||||
|
// Live join if state is CONNECTED
|
||||||
|
ns->setSynchronous(m_state.load() == CONNECTED);
|
||||||
ns->addUInt8(LE_CLIENT_LOADED_WORLD);
|
ns->addUInt8(LE_CLIENT_LOADED_WORLD);
|
||||||
sendToServer(ns, true);
|
sendToServer(ns, true);
|
||||||
delete ns;
|
delete ns;
|
||||||
} // finishedLoadingWorld
|
} // finishedLoadingWorld
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ClientLobby::liveJoinAcknowledged(Event* event)
|
||||||
|
{
|
||||||
|
World* w = World::getWorld();
|
||||||
|
if (!w)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const NetworkString& data = event->data();
|
||||||
|
m_start_live_game_time = data.getUInt64();
|
||||||
|
powerup_manager->setRandomSeed(m_start_live_game_time);
|
||||||
|
m_start_live_game_time = data.getUInt64();
|
||||||
|
m_live_join_ticks = data.getUInt32();
|
||||||
|
for (unsigned i = 0; i < w->getNumKarts(); i++)
|
||||||
|
{
|
||||||
|
AbstractKart* k = w->getKart(i);
|
||||||
|
if (k->getController()->isLocalPlayerController())
|
||||||
|
k->setLiveJoinKart(m_live_join_ticks);
|
||||||
|
}
|
||||||
|
} // liveJoinAcknowledged
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ClientLobby::finishLiveJoin()
|
||||||
|
{
|
||||||
|
m_start_live_game_time = std::numeric_limits<uint64_t>::max();
|
||||||
|
World* w = World::getWorld();
|
||||||
|
if (!w)
|
||||||
|
return;
|
||||||
|
Log::info("ClientLobby", "Live join started at %lf",
|
||||||
|
StkTime::getRealTime());
|
||||||
|
|
||||||
|
w->setLiveJoinWorld(false);
|
||||||
|
w->endLiveJoinWorld(m_live_join_ticks);
|
||||||
|
for (unsigned i = 0; i < w->getNumKarts(); i++)
|
||||||
|
{
|
||||||
|
AbstractKart* k = w->getKart(i);
|
||||||
|
if (!k->getController()->isLocalPlayerController() &&
|
||||||
|
!k->isEliminated())
|
||||||
|
k->getNode()->setVisible(true);
|
||||||
|
}
|
||||||
|
m_state.store(RACING);
|
||||||
|
} // finishLiveJoin
|
||||||
|
@ -81,6 +81,10 @@ private:
|
|||||||
|
|
||||||
uint64_t m_auto_back_to_lobby_time;
|
uint64_t m_auto_back_to_lobby_time;
|
||||||
|
|
||||||
|
uint64_t m_start_live_game_time;
|
||||||
|
|
||||||
|
int m_live_join_ticks;
|
||||||
|
|
||||||
/** The state of the finite state machine. */
|
/** The state of the finite state machine. */
|
||||||
std::atomic<ClientState> m_state;
|
std::atomic<ClientState> m_state;
|
||||||
|
|
||||||
@ -95,6 +99,8 @@ private:
|
|||||||
|
|
||||||
irr::core::stringw m_total_players;
|
irr::core::stringw m_total_players;
|
||||||
|
|
||||||
|
void liveJoinAcknowledged(Event* event);
|
||||||
|
void finishLiveJoin();
|
||||||
public:
|
public:
|
||||||
ClientLobby(const TransportAddress& a, std::shared_ptr<Server> s);
|
ClientLobby(const TransportAddress& a, std::shared_ptr<Server> s);
|
||||||
virtual ~ClientLobby();
|
virtual ~ClientLobby();
|
||||||
|
@ -173,6 +173,9 @@ void GameProtocol::controllerAction(int kart_id, PlayerAction action,
|
|||||||
*/
|
*/
|
||||||
void GameProtocol::handleControllerAction(Event *event)
|
void GameProtocol::handleControllerAction(Event *event)
|
||||||
{
|
{
|
||||||
|
STKPeer* peer = event->getPeer();
|
||||||
|
if (NetworkConfig::get()->isServer() && peer->isWaitingForGame())
|
||||||
|
return;
|
||||||
NetworkString &data = event->data();
|
NetworkString &data = event->data();
|
||||||
uint8_t count = data.getUInt8();
|
uint8_t count = data.getUInt8();
|
||||||
bool will_trigger_rewind = false;
|
bool will_trigger_rewind = false;
|
||||||
@ -193,10 +196,10 @@ void GameProtocol::handleControllerAction(Event *event)
|
|||||||
}
|
}
|
||||||
uint8_t kart_id = data.getUInt8();
|
uint8_t kart_id = data.getUInt8();
|
||||||
if (NetworkConfig::get()->isServer() &&
|
if (NetworkConfig::get()->isServer() &&
|
||||||
!event->getPeer()->availableKartID(kart_id))
|
!peer->availableKartID(kart_id))
|
||||||
{
|
{
|
||||||
Log::warn("GameProtocol", "Wrong kart id %d from %s.",
|
Log::warn("GameProtocol", "Wrong kart id %d from %s.",
|
||||||
kart_id, event->getPeer()->getAddress().toString().c_str());
|
kart_id, peer->getAddress().toString().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +230,9 @@ void GameProtocol::handleControllerAction(Event *event)
|
|||||||
{
|
{
|
||||||
// Send update to all clients except the original sender if the event
|
// Send update to all clients except the original sender if the event
|
||||||
// is after the server time
|
// is after the server time
|
||||||
event->getPeer()->updateLastActivity();
|
peer->updateLastActivity();
|
||||||
if (!will_trigger_rewind)
|
if (!will_trigger_rewind)
|
||||||
STKHost::get()->sendPacketExcept(event->getPeer(), &data, false);
|
STKHost::get()->sendPacketExcept(peer, &data, false);
|
||||||
|
|
||||||
// FIXME unless there is a network jitter more than 100ms (more than
|
// FIXME unless there is a network jitter more than 100ms (more than
|
||||||
// server delay), time adjust is not necessary
|
// server delay), time adjust is not necessary
|
||||||
|
@ -68,7 +68,8 @@ public:
|
|||||||
LE_BAD_CONNECTION,
|
LE_BAD_CONNECTION,
|
||||||
LE_CONFIG_SERVER,
|
LE_CONFIG_SERVER,
|
||||||
LE_CHANGE_HANDICAP,
|
LE_CHANGE_HANDICAP,
|
||||||
LE_LIVE_JOIN
|
LE_LIVE_JOIN,
|
||||||
|
LE_LIVE_JOIN_ACK
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RejectReason : uint8_t
|
enum RejectReason : uint8_t
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "config/user_config.hpp"
|
#include "config/user_config.hpp"
|
||||||
#include "items/item_manager.hpp"
|
#include "items/item_manager.hpp"
|
||||||
#include "items/powerup_manager.hpp"
|
#include "items/powerup_manager.hpp"
|
||||||
|
#include "graphics/render_info.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/controller/player_controller.hpp"
|
#include "karts/controller/player_controller.hpp"
|
||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
@ -298,6 +299,7 @@ bool ServerLobby::notifyEvent(Event* event)
|
|||||||
{
|
{
|
||||||
case LE_RACE_FINISHED_ACK: playerFinishedResult(event); break;
|
case LE_RACE_FINISHED_ACK: playerFinishedResult(event); break;
|
||||||
case LE_LIVE_JOIN: liveJoinRequest(event); break;
|
case LE_LIVE_JOIN: liveJoinRequest(event); break;
|
||||||
|
case LE_CLIENT_LOADED_WORLD: finishedLoadingLiveJoinClient(event); break;
|
||||||
default: Log::error("ServerLobby", "Unknown message type %d - ignored.",
|
default: Log::error("ServerLobby", "Unknown message type %d - ignored.",
|
||||||
message_type);
|
message_type);
|
||||||
break;
|
break;
|
||||||
@ -647,10 +649,230 @@ NetworkString* ServerLobby::getLoadWorldMessage(
|
|||||||
} // getLoadWorldMessage
|
} // getLoadWorldMessage
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
bool ServerLobby::canLiveJoinNow() const
|
||||||
|
{
|
||||||
|
return race_manager->supportsLiveJoining() &&
|
||||||
|
World::getWorld() && RaceEventManager::getInstance()->isRunning() &&
|
||||||
|
!RaceEventManager::getInstance()->isRaceOver() &&
|
||||||
|
(World::getWorld()->getPhase() == WorldStatus::RACE_PHASE ||
|
||||||
|
World::getWorld()->getPhase() == WorldStatus::GOAL_PHASE);
|
||||||
|
} // canLiveJoinNow
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** \ref peer will be reset back to the lobby.
|
||||||
|
*/
|
||||||
|
void ServerLobby::rejectLiveJoin(STKPeer* peer)
|
||||||
|
{
|
||||||
|
NetworkString* reset = getNetworkString(1);
|
||||||
|
reset->setSynchronous(true);
|
||||||
|
reset->addUInt8(LE_EXIT_RESULT);
|
||||||
|
peer->sendPacket(reset, /*reliable*/true);
|
||||||
|
delete reset;
|
||||||
|
updatePlayerList();
|
||||||
|
NetworkString* server_info = getNetworkString();
|
||||||
|
server_info->setSynchronous(true);
|
||||||
|
server_info->addUInt8(LE_SERVER_INFO);
|
||||||
|
m_game_setup->addServerInfo(server_info);
|
||||||
|
peer->sendPacket(server_info, /*reliable*/true);
|
||||||
|
delete server_info;
|
||||||
|
} // rejectLiveJoin
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** This message is like kartSelectionRequested, but it will send the peer
|
||||||
|
* load world message if he can join the current started game.
|
||||||
|
*/
|
||||||
void ServerLobby::liveJoinRequest(Event* event)
|
void ServerLobby::liveJoinRequest(Event* event)
|
||||||
{
|
{
|
||||||
|
STKPeer* peer = event->getPeer();
|
||||||
|
const NetworkString& data = event->data();
|
||||||
|
|
||||||
|
if (!canLiveJoinNow())
|
||||||
|
{
|
||||||
|
rejectLiveJoin(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setPlayerKarts(data, peer);
|
||||||
|
|
||||||
|
std::vector<int> used_id;
|
||||||
|
for (unsigned i = 0; i < peer->getPlayerProfiles().size(); i++)
|
||||||
|
{
|
||||||
|
int id = getReservedId(peer->getPlayerProfiles()[i], i);
|
||||||
|
if (id == -1)
|
||||||
|
break;
|
||||||
|
used_id.push_back(id);
|
||||||
|
}
|
||||||
|
if (used_id.size() != peer->getPlayerProfiles().size())
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < peer->getPlayerProfiles().size(); i++)
|
||||||
|
peer->getPlayerProfiles()[i]->setKartName("");
|
||||||
|
for (unsigned i = 0; i < used_id.size(); i++)
|
||||||
|
{
|
||||||
|
RemoteKartInfo& rki = race_manager->getKartInfo(used_id[i]);
|
||||||
|
rki.makeReserved();
|
||||||
|
}
|
||||||
|
Log::info("ServerLobby", "Too many players (%d) try to live join",
|
||||||
|
(int)peer->getPlayerProfiles().size());
|
||||||
|
rejectLiveJoin(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer->clearAvailableKartIDs();
|
||||||
|
for (int id : used_id)
|
||||||
|
{
|
||||||
|
Log::info("ServerLobby", "%s live joining with reserved kart id %d.",
|
||||||
|
peer->getAddress().toString().c_str(), id);
|
||||||
|
peer->addAvailableKartID(id);
|
||||||
|
}
|
||||||
|
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
|
||||||
|
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||||
|
{
|
||||||
|
const RemoteKartInfo& rki = race_manager->getKartInfo(i);
|
||||||
|
std::shared_ptr<NetworkPlayerProfile> player =
|
||||||
|
rki.getNetworkPlayerProfile().lock();
|
||||||
|
if (!player)
|
||||||
|
{
|
||||||
|
player = NetworkPlayerProfile::getReservedProfile(
|
||||||
|
race_manager->getMinorMode() ==
|
||||||
|
RaceManager::MINOR_MODE_FREE_FOR_ALL ?
|
||||||
|
KART_TEAM_NONE : rki.getKartTeam());
|
||||||
|
}
|
||||||
|
players.push_back(player);
|
||||||
|
}
|
||||||
|
NetworkString* load_world_message = getLoadWorldMessage(players);
|
||||||
|
peer->sendPacket(load_world_message, true/*reliable*/);
|
||||||
|
delete load_world_message;
|
||||||
|
peer->updateLastActivity();
|
||||||
} // liveJoinRequest
|
} // liveJoinRequest
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Decide where to put the live join player depends on his team and game mode.
|
||||||
|
*/
|
||||||
|
int ServerLobby::getReservedId(std::shared_ptr<NetworkPlayerProfile>& p,
|
||||||
|
unsigned local_id) const
|
||||||
|
{
|
||||||
|
const bool is_ffa =
|
||||||
|
race_manager->getMinorMode() == RaceManager::MINOR_MODE_FREE_FOR_ALL;
|
||||||
|
int red_count = 0;
|
||||||
|
int blue_count = 0;
|
||||||
|
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||||
|
{
|
||||||
|
RemoteKartInfo& rki = race_manager->getKartInfo(i);
|
||||||
|
if (rki.isReserved())
|
||||||
|
continue;
|
||||||
|
bool disconnected = rki.disconnected();
|
||||||
|
if (race_manager->getKartInfo(i).getKartTeam() == KART_TEAM_RED &&
|
||||||
|
!disconnected)
|
||||||
|
red_count++;
|
||||||
|
else if (race_manager->getKartInfo(i).getKartTeam() ==
|
||||||
|
KART_TEAM_BLUE && !disconnected)
|
||||||
|
blue_count++;
|
||||||
|
}
|
||||||
|
KartTeam target_team = red_count > blue_count ? KART_TEAM_BLUE :
|
||||||
|
KART_TEAM_RED;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||||
|
{
|
||||||
|
RemoteKartInfo& rki = race_manager->getKartInfo(i);
|
||||||
|
std::shared_ptr<NetworkPlayerProfile> player =
|
||||||
|
rki.getNetworkPlayerProfile().lock();
|
||||||
|
if (!player)
|
||||||
|
{
|
||||||
|
if (is_ffa)
|
||||||
|
{
|
||||||
|
rki.copyFrom(p, local_id);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (ServerConfig::m_team_choosing)
|
||||||
|
{
|
||||||
|
if ((p->getTeam() == KART_TEAM_RED &&
|
||||||
|
rki.getKartTeam() == KART_TEAM_RED) ||
|
||||||
|
(p->getTeam() == KART_TEAM_BLUE &&
|
||||||
|
rki.getKartTeam() == KART_TEAM_BLUE))
|
||||||
|
{
|
||||||
|
rki.copyFrom(p, local_id);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rki.getKartTeam() == target_team)
|
||||||
|
{
|
||||||
|
p->setTeam(target_team);
|
||||||
|
rki.copyFrom(p, local_id);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
} // getReservedId
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Finally put the kart in the world and inform client the current world
|
||||||
|
* status, (including current confirmed item state, kart scores...)
|
||||||
|
*/
|
||||||
|
void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
|
||||||
|
{
|
||||||
|
STKPeer* peer = event->getPeer();
|
||||||
|
if (!canLiveJoinNow())
|
||||||
|
{
|
||||||
|
rejectLiveJoin(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool live_joined_in_time = true;
|
||||||
|
for (const int id : peer->getAvailableKartIDs())
|
||||||
|
{
|
||||||
|
const RemoteKartInfo& rki = race_manager->getKartInfo(id);
|
||||||
|
if (rki.isReserved())
|
||||||
|
{
|
||||||
|
live_joined_in_time = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!live_joined_in_time)
|
||||||
|
{
|
||||||
|
Log::warn("ServerLobby", "%s can't live-join in time.",
|
||||||
|
peer->getAddress().toString().c_str());
|
||||||
|
rejectLiveJoin(peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
World* w = World::getWorld();
|
||||||
|
assert(w);
|
||||||
|
|
||||||
|
// Give 3 seconds for all peers to get new kart info
|
||||||
|
const int live_join_util_ticks = w->getTicksSinceStart() +
|
||||||
|
stk_config->time2Ticks(3.0f);
|
||||||
|
uint64_t live_join_start_time = STKHost::get()->getNetworkTimer();
|
||||||
|
live_join_start_time -= m_server_delay;
|
||||||
|
live_join_start_time += 3000;
|
||||||
|
|
||||||
|
for (const int id : peer->getAvailableKartIDs())
|
||||||
|
{
|
||||||
|
const RemoteKartInfo& rki = race_manager->getKartInfo(id);
|
||||||
|
AbstractKart* k = w->getKart(id);
|
||||||
|
k->changeKart(rki.getKartName(), rki.getDifficulty(),
|
||||||
|
rki.getKartTeam() == KART_TEAM_RED ?
|
||||||
|
std::make_shared<RenderInfo>(1.0f) :
|
||||||
|
rki.getKartTeam() == KART_TEAM_BLUE ?
|
||||||
|
std::make_shared<RenderInfo>(0.66f) :
|
||||||
|
std::make_shared<RenderInfo>(rki.getDefaultKartColor()));
|
||||||
|
k->setLiveJoinKart(live_join_util_ticks);
|
||||||
|
w->addReservedKart(id);
|
||||||
|
}
|
||||||
|
Log::info("ServerLobby", "%s live-joining succeeded.",
|
||||||
|
peer->getAddress().toString().c_str());
|
||||||
|
|
||||||
|
NetworkString* ns = getNetworkString(10);
|
||||||
|
ns->setSynchronous(true);
|
||||||
|
ns->addUInt8(LE_LIVE_JOIN_ACK).addUInt64(m_client_starting_time)
|
||||||
|
.addUInt64(live_join_start_time).addUInt32(live_join_util_ticks);
|
||||||
|
peer->setWaitingForGame(false);
|
||||||
|
peer->sendPacket(ns, true/*reliable*/);
|
||||||
|
delete ns;
|
||||||
|
updatePlayerList();
|
||||||
|
peer->updateLastActivity();
|
||||||
|
} // finishedLoadingLiveJoinClient
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Simple finite state machine. Once this
|
/** Simple finite state machine. Once this
|
||||||
* is known, register the server and its address with the stk server so that
|
* is known, register the server and its address with the stk server so that
|
||||||
@ -660,8 +882,7 @@ void ServerLobby::update(int ticks)
|
|||||||
{
|
{
|
||||||
World* w = World::getWorld();
|
World* w = World::getWorld();
|
||||||
int sec = ServerConfig::m_kick_idle_player_seconds;
|
int sec = ServerConfig::m_kick_idle_player_seconds;
|
||||||
if (NetworkConfig::get()->isWAN() &&
|
if (sec > 0 && m_state.load() >= WAIT_FOR_WORLD_LOADED &&
|
||||||
sec > 0 && m_state.load() >= WAIT_FOR_WORLD_LOADED &&
|
|
||||||
m_state.load() <= RACING && m_server_has_loaded_world.load() == true)
|
m_state.load() <= RACING && m_server_has_loaded_world.load() == true)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||||
@ -672,8 +893,19 @@ void ServerLobby::update(int ticks)
|
|||||||
if (!player)
|
if (!player)
|
||||||
continue;
|
continue;
|
||||||
auto peer = player->getPeer();
|
auto peer = player->getPeer();
|
||||||
if (peer && peer->idleForSeconds() > sec &&
|
if (peer && peer->idleForSeconds() > sec)
|
||||||
!peer->isDisconnected())
|
{
|
||||||
|
if (w && w->getKart(i)->isEliminated())
|
||||||
|
{
|
||||||
|
// Remove loading world too long live join peer
|
||||||
|
Log::info("ServerLobby", "%s hasn't live-joined within"
|
||||||
|
" %d seconds, remove it.",
|
||||||
|
peer->getAddress().toString().c_str(), sec);
|
||||||
|
RemoteKartInfo& rki = race_manager->getKartInfo(i);
|
||||||
|
rki.makeReserved();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!peer->isDisconnected() && NetworkConfig::get()->isWAN())
|
||||||
{
|
{
|
||||||
if (w && w->getKart(i)->hasFinishedRace())
|
if (w && w->getKart(i)->hasFinishedRace())
|
||||||
continue;
|
continue;
|
||||||
@ -684,6 +916,7 @@ void ServerLobby::update(int ticks)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (w)
|
if (w)
|
||||||
setGameStartedProgress(w->getGameStartedProgress());
|
setGameStartedProgress(w->getGameStartedProgress());
|
||||||
else
|
else
|
||||||
@ -2963,10 +3196,12 @@ void ServerLobby::handlePlayerDisconnection() const
|
|||||||
total++;
|
total++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
rki.makeReserved();
|
||||||
|
|
||||||
AbstractKart* k = World::getWorld()->getKart(i);
|
AbstractKart* k = World::getWorld()->getKart(i);
|
||||||
if (!k->isEliminated() && !k->hasFinishedRace())
|
if (!k->isEliminated() && !k->hasFinishedRace())
|
||||||
{
|
{
|
||||||
rki.makeReserved();
|
|
||||||
CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>
|
CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>
|
||||||
(World::getWorld());
|
(World::getWorld());
|
||||||
if (ctf)
|
if (ctf)
|
||||||
|
@ -183,6 +183,7 @@ private:
|
|||||||
void playerFinishedResult(Event *event);
|
void playerFinishedResult(Event *event);
|
||||||
bool registerServer(bool now);
|
bool registerServer(bool now);
|
||||||
void finishedLoadingWorldClient(Event *event);
|
void finishedLoadingWorldClient(Event *event);
|
||||||
|
void finishedLoadingLiveJoinClient(Event *event);
|
||||||
void kickHost(Event* event);
|
void kickHost(Event* event);
|
||||||
void changeTeam(Event* event);
|
void changeTeam(Event* event);
|
||||||
void handleChat(Event* event);
|
void handleChat(Event* event);
|
||||||
@ -276,6 +277,10 @@ private:
|
|||||||
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
|
std::vector<std::shared_ptr<NetworkPlayerProfile> >& players) const;
|
||||||
void setPlayerKarts(const NetworkString& ns, STKPeer* peer) const;
|
void setPlayerKarts(const NetworkString& ns, STKPeer* peer) const;
|
||||||
void liveJoinRequest(Event* event);
|
void liveJoinRequest(Event* event);
|
||||||
|
void rejectLiveJoin(STKPeer* peer);
|
||||||
|
bool canLiveJoinNow() const;
|
||||||
|
int getReservedId(std::shared_ptr<NetworkPlayerProfile>& p,
|
||||||
|
unsigned local_id) const;
|
||||||
public:
|
public:
|
||||||
ServerLobby();
|
ServerLobby();
|
||||||
virtual ~ServerLobby();
|
virtual ~ServerLobby();
|
||||||
|
@ -207,6 +207,9 @@ public:
|
|||||||
bool availableKartID(unsigned id)
|
bool availableKartID(unsigned id)
|
||||||
{ return m_available_kart_ids.find(id) != m_available_kart_ids.end(); }
|
{ return m_available_kart_ids.find(id) != m_available_kart_ids.end(); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
const std::set<unsigned>& getAvailableKartIDs() const
|
||||||
|
{ return m_available_kart_ids; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setUserVersion(const std::string& uv) { m_user_version = uv; }
|
void setUserVersion(const std::string& uv) { m_user_version = uv; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
const std::string& getUserVersion() const { return m_user_version; }
|
const std::string& getUserVersion() const { return m_user_version; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user