Add live join and spectate button to lobby
This commit is contained in:
parent
582ec771c0
commit
2950238d2b
@ -253,12 +253,15 @@ void World::init()
|
|||||||
|
|
||||||
if (Camera::getNumCameras() == 0)
|
if (Camera::getNumCameras() == 0)
|
||||||
{
|
{
|
||||||
|
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||||
if ( (NetworkConfig::get()->isServer() &&
|
if ( (NetworkConfig::get()->isServer() &&
|
||||||
!ProfileWorld::isNoGraphics() ) ||
|
!ProfileWorld::isNoGraphics() ) ||
|
||||||
race_manager->isWatchingReplay() )
|
race_manager->isWatchingReplay() ||
|
||||||
|
(cl && cl->isSpectator()))
|
||||||
{
|
{
|
||||||
// In case that the server is running with gui or watching replay,
|
// In case that the server is running with gui, watching replay or
|
||||||
// create a camera and attach it to the first kart.
|
// spectating the game, create a camera and attach it to the first
|
||||||
|
// kart.
|
||||||
Camera::createCamera(World::getWorld()->getKart(0), 0);
|
Camera::createCamera(World::getWorld()->getKart(0), 0);
|
||||||
|
|
||||||
} // if server with graphics of is watching replay
|
} // if server with graphics of is watching replay
|
||||||
|
@ -155,6 +155,7 @@ void GameSetup::addServerInfo(NetworkString* ns)
|
|||||||
|
|
||||||
ns->encodeString16(m_message_of_today);
|
ns->encodeString16(m_message_of_today);
|
||||||
ns->addUInt8((uint8_t)ServerConfig::m_server_configurable);
|
ns->addUInt8((uint8_t)ServerConfig::m_server_configurable);
|
||||||
|
ns->addUInt8(race_manager->supportsLiveJoining() ? 1 : 0);
|
||||||
} // addServerInfo
|
} // addServerInfo
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "items/powerup_manager.hpp"
|
#include "items/powerup_manager.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/controller/controller.hpp"
|
#include "karts/controller/controller.hpp"
|
||||||
|
#include "karts/kart_properties.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"
|
||||||
@ -91,6 +92,7 @@ ClientLobby::ClientLobby(const TransportAddress& a, std::shared_ptr<Server> s)
|
|||||||
m_disconnected_msg[PDI_BAD_CONNECTION] =
|
m_disconnected_msg[PDI_BAD_CONNECTION] =
|
||||||
_("Bad network connection is detected.");
|
_("Bad network connection is detected.");
|
||||||
m_first_connect = true;
|
m_first_connect = true;
|
||||||
|
m_spectator = false;
|
||||||
} // ClientLobby
|
} // ClientLobby
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -110,6 +112,7 @@ ClientLobby::~ClientLobby()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ClientLobby::setup()
|
void ClientLobby::setup()
|
||||||
{
|
{
|
||||||
|
m_spectator = false;
|
||||||
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_start_live_game_time = std::numeric_limits<uint64_t>::max();
|
||||||
m_received_server_result = false;
|
m_received_server_result = false;
|
||||||
@ -649,6 +652,9 @@ void ClientLobby::handleServerInfo(Event* event)
|
|||||||
}
|
}
|
||||||
bool server_config = data.getUInt8() == 1;
|
bool server_config = data.getUInt8() == 1;
|
||||||
NetworkingLobby::getInstance()->toggleServerConfigButton(server_config);
|
NetworkingLobby::getInstance()->toggleServerConfigButton(server_config);
|
||||||
|
bool live_join_spectator = data.getUInt8() == 1;
|
||||||
|
NetworkingLobby::getInstance()
|
||||||
|
->toggleServerLiveJoinable(live_join_spectator);
|
||||||
} // handleServerInfo
|
} // handleServerInfo
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1101,3 +1107,21 @@ void ClientLobby::handleKartInfo(Event* event)
|
|||||||
SFXManager::get()->quickSound("energy_bar_full");
|
SFXManager::get()->quickSound("energy_bar_full");
|
||||||
MessageQueue::add(MessageQueue::MT_FRIEND, msg);
|
MessageQueue::add(MessageQueue::MT_FRIEND, msg);
|
||||||
} // handleKartInfo
|
} // handleKartInfo
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ClientLobby::startLiveJoinKartSelection()
|
||||||
|
{
|
||||||
|
NetworkKartSelectionScreen::getInstance()->setLiveJoin(true);
|
||||||
|
std::vector<int> all_k =
|
||||||
|
kart_properties_manager->getKartsInGroup("standard");
|
||||||
|
std::set<std::string> karts;
|
||||||
|
for (int kart : all_k)
|
||||||
|
{
|
||||||
|
const KartProperties* kp = kart_properties_manager->getKartById(kart);
|
||||||
|
if (!kp->isAddon())
|
||||||
|
karts.insert(kp->getIdent());
|
||||||
|
}
|
||||||
|
NetworkKartSelectionScreen::getInstance()
|
||||||
|
->setAvailableKartsFromServer(karts);
|
||||||
|
NetworkKartSelectionScreen::getInstance()->push();
|
||||||
|
} // startLiveJoinKartSelection
|
||||||
|
@ -79,6 +79,8 @@ private:
|
|||||||
|
|
||||||
bool m_first_connect;
|
bool m_first_connect;
|
||||||
|
|
||||||
|
bool m_spectator;
|
||||||
|
|
||||||
uint64_t m_auto_back_to_lobby_time;
|
uint64_t m_auto_back_to_lobby_time;
|
||||||
|
|
||||||
uint64_t m_start_live_game_time;
|
uint64_t m_start_live_game_time;
|
||||||
@ -125,6 +127,9 @@ public:
|
|||||||
bool isServerAutoGameTime() const { return m_server_auto_game_time; }
|
bool isServerAutoGameTime() const { return m_server_auto_game_time; }
|
||||||
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
|
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
|
||||||
void requestKartInfo(uint8_t kart_id);
|
void requestKartInfo(uint8_t kart_id);
|
||||||
|
void setSpectator(bool val) { m_spectator = val; }
|
||||||
|
bool isSpectator() const { return m_spectator; }
|
||||||
|
void startLiveJoinKartSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENT_LOBBY_HPP
|
#endif // CLIENT_LOBBY_HPP
|
||||||
|
@ -174,7 +174,8 @@ void GameProtocol::controllerAction(int kart_id, PlayerAction action,
|
|||||||
void GameProtocol::handleControllerAction(Event *event)
|
void GameProtocol::handleControllerAction(Event *event)
|
||||||
{
|
{
|
||||||
STKPeer* peer = event->getPeer();
|
STKPeer* peer = event->getPeer();
|
||||||
if (NetworkConfig::get()->isServer() && peer->isWaitingForGame())
|
if (NetworkConfig::get()->isServer() && (peer->isWaitingForGame() ||
|
||||||
|
peer->getAvailableKartIDs().empty()))
|
||||||
return;
|
return;
|
||||||
NetworkString &data = event->data();
|
NetworkString &data = event->data();
|
||||||
uint8_t count = data.getUInt8();
|
uint8_t count = data.getUInt8();
|
||||||
|
@ -696,6 +696,9 @@ void ServerLobby::liveJoinRequest(Event* event)
|
|||||||
rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN);
|
rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool spectator = data.getUInt8() == 1;
|
||||||
|
if (!spectator)
|
||||||
|
{
|
||||||
setPlayerKarts(data, peer);
|
setPlayerKarts(data, peer);
|
||||||
|
|
||||||
std::vector<int> used_id;
|
std::vector<int> used_id;
|
||||||
@ -728,6 +731,13 @@ void ServerLobby::liveJoinRequest(Event* event)
|
|||||||
peer->getAddress().toString().c_str(), id);
|
peer->getAddress().toString().c_str(), id);
|
||||||
peer->addAvailableKartID(id);
|
peer->addAvailableKartID(id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::info("ServerLobby", "%s spectating now.",
|
||||||
|
peer->getAddress().toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
|
std::vector<std::shared_ptr<NetworkPlayerProfile> > players;
|
||||||
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
|
||||||
{
|
{
|
||||||
@ -856,9 +866,14 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
|
|||||||
World::getWorld()->addReservedKart(id);
|
World::getWorld()->addReservedKart(id);
|
||||||
const RemoteKartInfo& rki = race_manager->getKartInfo(id);
|
const RemoteKartInfo& rki = race_manager->getKartInfo(id);
|
||||||
addLiveJoiningKart(id, rki, m_last_live_join_util_ticks);
|
addLiveJoiningKart(id, rki, m_last_live_join_util_ticks);
|
||||||
|
Log::info("ServerLobby", "%s live-joining succeeded with kart id %d.",
|
||||||
|
peer->getAddress().toString().c_str(), id);
|
||||||
}
|
}
|
||||||
Log::info("ServerLobby", "%s live-joining succeeded.",
|
if (peer->getAvailableKartIDs().empty())
|
||||||
|
{
|
||||||
|
Log::info("ServerLobby", "%s spectating succeeded.",
|
||||||
peer->getAddress().toString().c_str());
|
peer->getAddress().toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
NetworkString* ns = getNetworkString(10);
|
NetworkString* ns = getNetworkString(10);
|
||||||
ns->setSynchronous(true);
|
ns->setSynchronous(true);
|
||||||
|
@ -104,7 +104,9 @@ void NetworkKartSelectionScreen::allPlayersDone()
|
|||||||
if (m_live_join)
|
if (m_live_join)
|
||||||
{
|
{
|
||||||
kart.setSynchronous(true);
|
kart.setSynchronous(true);
|
||||||
kart.addUInt8(LobbyProtocol::LE_LIVE_JOIN);
|
kart.addUInt8(LobbyProtocol::LE_LIVE_JOIN)
|
||||||
|
// not spectator
|
||||||
|
.addUInt8(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
kart.addUInt8(LobbyProtocol::LE_KART_SELECTION);
|
kart.addUInt8(LobbyProtocol::LE_KART_SELECTION);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "network/protocols/client_lobby.hpp"
|
#include "network/protocols/client_lobby.hpp"
|
||||||
#include "network/server.hpp"
|
#include "network/server.hpp"
|
||||||
#include "network/stk_host.hpp"
|
#include "network/stk_host.hpp"
|
||||||
|
#include "network/network_timer_synchronizer.hpp"
|
||||||
#include "states_screens/dialogs/splitscreen_player_dialog.hpp"
|
#include "states_screens/dialogs/splitscreen_player_dialog.hpp"
|
||||||
#include "states_screens/dialogs/network_user_dialog.hpp"
|
#include "states_screens/dialogs/network_user_dialog.hpp"
|
||||||
#include "states_screens/dialogs/server_configuration_dialog.hpp"
|
#include "states_screens/dialogs/server_configuration_dialog.hpp"
|
||||||
@ -122,6 +123,10 @@ void NetworkingLobby::loadedFromFile()
|
|||||||
(file_manager->getAsset(FileManager::GUI_ICON, "hourglass.png"));
|
(file_manager->getAsset(FileManager::GUI_ICON, "hourglass.png"));
|
||||||
video::ITexture* icon_5 = irr_driver->getTexture
|
video::ITexture* icon_5 = irr_driver->getTexture
|
||||||
(file_manager->getAsset(FileManager::GUI_ICON, "green_check.png"));
|
(file_manager->getAsset(FileManager::GUI_ICON, "green_check.png"));
|
||||||
|
m_config_texture = irr_driver->getTexture
|
||||||
|
(file_manager->getAsset(FileManager::GUI_ICON, "main_options.png"));
|
||||||
|
m_spectate_texture = irr_driver->getTexture
|
||||||
|
(file_manager->getAsset(FileManager::GUI_ICON, "screen_other.png"));
|
||||||
m_icon_bank->addTextureAsSprite(icon_1);
|
m_icon_bank->addTextureAsSprite(icon_1);
|
||||||
m_icon_bank->addTextureAsSprite(icon_2);
|
m_icon_bank->addTextureAsSprite(icon_2);
|
||||||
m_icon_bank->addTextureAsSprite(icon_3);
|
m_icon_bank->addTextureAsSprite(icon_3);
|
||||||
@ -161,6 +166,8 @@ void NetworkingLobby::init()
|
|||||||
m_player_names.clear();
|
m_player_names.clear();
|
||||||
m_allow_change_team = false;
|
m_allow_change_team = false;
|
||||||
m_has_auto_start_in_server = false;
|
m_has_auto_start_in_server = false;
|
||||||
|
m_server_live_joinable = false;
|
||||||
|
m_client_live_joinable = false;
|
||||||
m_ping_update_timer = 0.0f;
|
m_ping_update_timer = 0.0f;
|
||||||
m_start_timeout = std::numeric_limits<float>::max();
|
m_start_timeout = std::numeric_limits<float>::max();
|
||||||
m_cur_starting_timer = std::numeric_limits<int64_t>::max();
|
m_cur_starting_timer = std::numeric_limits<int64_t>::max();
|
||||||
@ -248,6 +255,11 @@ void NetworkingLobby::onUpdate(float delta)
|
|||||||
if (NetworkConfig::get()->isServer() || !STKHost::existHost())
|
if (NetworkConfig::get()->isServer() || !STKHost::existHost())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_start_button->setVisible(false);
|
||||||
|
m_config_button->setVisible(false);
|
||||||
|
m_config_button->setImage(m_config_texture);
|
||||||
|
m_client_live_joinable = false;
|
||||||
|
|
||||||
m_ping_update_timer += delta;
|
m_ping_update_timer += delta;
|
||||||
if (m_player_list && m_ping_update_timer > 2.0f)
|
if (m_player_list && m_ping_update_timer > 2.0f)
|
||||||
{
|
{
|
||||||
@ -317,6 +329,18 @@ void NetworkingLobby::onUpdate(float delta)
|
|||||||
//wait before the current game finish
|
//wait before the current game finish
|
||||||
msg = _("Please wait for the current game's end.");
|
msg = _("Please wait for the current game's end.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// You can live join or spectator if u have the current play track
|
||||||
|
// and network timer is synchronized
|
||||||
|
if (t &&
|
||||||
|
STKHost::get()->getNetworkTimerSynchronizer()->isSynchronised() &&
|
||||||
|
m_server_live_joinable)
|
||||||
|
{
|
||||||
|
m_client_live_joinable = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_client_live_joinable = false;
|
||||||
|
|
||||||
m_timeout_message->setText(msg, false);
|
m_timeout_message->setText(msg, false);
|
||||||
core::stringw total_msg;
|
core::stringw total_msg;
|
||||||
for (auto& string : m_server_info)
|
for (auto& string : m_server_info)
|
||||||
@ -326,6 +350,19 @@ void NetworkingLobby::onUpdate(float delta)
|
|||||||
}
|
}
|
||||||
m_text_bubble->setText(total_msg, true);
|
m_text_bubble->setText(total_msg, true);
|
||||||
m_cur_starting_timer = std::numeric_limits<int64_t>::max();
|
m_cur_starting_timer = std::numeric_limits<int64_t>::max();
|
||||||
|
|
||||||
|
if (m_client_live_joinable)
|
||||||
|
{
|
||||||
|
m_start_button->setVisible(true);
|
||||||
|
//I18N: Live join is displayed in networking lobby to allow players
|
||||||
|
//to join the current started in-progress game
|
||||||
|
m_start_button->setLabel(_("Live join"));
|
||||||
|
//I18N: Spectate is displayed in networking lobby to allow players
|
||||||
|
//to join the current started in-progress game
|
||||||
|
m_config_button->setLabel(_("Spectate"));
|
||||||
|
m_config_button->setImage(m_spectate_texture);
|
||||||
|
m_config_button->setVisible(true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,15 +545,35 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
|
|||||||
m_chat_box->setText("");
|
m_chat_box->setText("");
|
||||||
} // send chat message
|
} // send chat message
|
||||||
else if (name == m_start_button->m_properties[PROP_ID])
|
else if (name == m_start_button->m_properties[PROP_ID])
|
||||||
|
{
|
||||||
|
if (m_client_live_joinable)
|
||||||
|
{
|
||||||
|
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||||
|
if (cl)
|
||||||
|
cl->startLiveJoinKartSelection();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Send a message to the server to start
|
// Send a message to the server to start
|
||||||
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
||||||
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
|
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
|
||||||
STKHost::get()->sendToServer(&start, true);
|
STKHost::get()->sendToServer(&start, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (name == m_config_button->m_properties[PROP_ID])
|
else if (name == m_config_button->m_properties[PROP_ID])
|
||||||
{
|
{
|
||||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||||
|
if (m_client_live_joinable && cl)
|
||||||
|
{
|
||||||
|
cl->setSpectator(true);
|
||||||
|
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
||||||
|
start.setSynchronous(true);
|
||||||
|
start.addUInt8(LobbyProtocol::LE_LIVE_JOIN)
|
||||||
|
// is spectating
|
||||||
|
.addUInt8(1);
|
||||||
|
STKHost::get()->sendToServer(&start, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (cl)
|
if (cl)
|
||||||
{
|
{
|
||||||
new ServerConfigurationDialog(
|
new ServerConfigurationDialog(
|
||||||
|
@ -77,7 +77,11 @@ private:
|
|||||||
unsigned m_min_start_game_players;
|
unsigned m_min_start_game_players;
|
||||||
|
|
||||||
bool m_allow_change_team, m_has_auto_start_in_server,
|
bool m_allow_change_team, m_has_auto_start_in_server,
|
||||||
m_server_configurable;
|
m_server_configurable, m_server_live_joinable,
|
||||||
|
m_client_live_joinable;
|
||||||
|
|
||||||
|
video::ITexture* m_config_texture;
|
||||||
|
video::ITexture* m_spectate_texture;
|
||||||
|
|
||||||
GUIEngine::IconButtonWidget* m_back_widget;
|
GUIEngine::IconButtonWidget* m_back_widget;
|
||||||
GUIEngine::LabelWidget* m_header;
|
GUIEngine::LabelWidget* m_header;
|
||||||
@ -145,6 +149,7 @@ public:
|
|||||||
float start_timeout, unsigned server_max_player);
|
float start_timeout, unsigned server_max_player);
|
||||||
void setStartingTimerTo(float t);
|
void setStartingTimerTo(float t);
|
||||||
void toggleServerConfigButton(bool val) { m_server_configurable = val; }
|
void toggleServerConfigButton(bool val) { m_server_configurable = val; }
|
||||||
|
void toggleServerLiveJoinable(bool val) { m_server_live_joinable = val; }
|
||||||
}; // class NetworkingLobby
|
}; // class NetworkingLobby
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user