Allow spectating linear race

This commit is contained in:
Benau
2019-01-06 13:43:19 +08:00
parent aeeb4afd63
commit 961c3957e2
10 changed files with 162 additions and 16 deletions

View File

@@ -32,6 +32,7 @@
#include "guiengine/modaldialog.hpp"
#include "physics/physics.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/server_config.hpp"
#include "race/history.hpp"
#include "states_screens/race_gui_base.hpp"
@@ -1075,3 +1076,61 @@ std::pair<uint32_t, uint32_t> LinearWorld::getGameStartedProgress() const
}
return progress;
} // getGameStartedProgress
// ----------------------------------------------------------------------------
void LinearWorld::KartInfo::saveCompleteState(BareNetworkString* bns)
{
bns->addUInt32(m_finished_laps);
bns->addUInt32(m_ticks_at_last_lap);
bns->addUInt32(m_lap_start_ticks);
bns->addFloat(m_estimated_finish);
bns->addFloat(m_overall_distance);
bns->addFloat(m_wrong_way_timer);
} // saveCompleteState
// ----------------------------------------------------------------------------
void LinearWorld::KartInfo::restoreCompleteState(const BareNetworkString& b)
{
m_finished_laps = b.getUInt32();
m_ticks_at_last_lap = b.getUInt32();
m_lap_start_ticks = b.getUInt32();
m_estimated_finish = b.getFloat();
m_overall_distance = b.getFloat();
m_wrong_way_timer = b.getFloat();
} // restoreCompleteState
// ----------------------------------------------------------------------------
void LinearWorld::saveCompleteState(BareNetworkString* bns)
{
bns->addUInt32(m_fastest_lap_ticks);
bns->addFloat(m_distance_increase);
for (auto& kart : m_karts)
{
bns->add(kart->getXYZ());
bns->add(kart->getRotation());
}
for (KartInfo& ki : m_kart_info)
ki.saveCompleteState(bns);
for (TrackSector* ts : m_kart_track_sector)
ts->saveCompleteState(bns);
} // saveCompleteState
// ----------------------------------------------------------------------------
void LinearWorld::restoreCompleteState(const BareNetworkString& b)
{
m_fastest_lap_ticks = b.getUInt32();
m_distance_increase = b.getFloat();
for (auto& kart : m_karts)
{
btTransform t;
t.setOrigin(b.getVec3());
t.setRotation(b.getQuat());
kart->setTrans(t);
}
for (KartInfo& ki : m_kart_info)
ki.restoreCompleteState(b);
for (TrackSector* ts : m_kart_track_sector)
ts->restoreCompleteState(b);
updateRacePosition();
} // restoreCompleteState

View File

@@ -112,6 +112,10 @@ private:
m_overall_distance = 0.0f;
m_wrong_way_timer = 0.0f;
} // reset
// --------------------------------------------------------------------
void saveCompleteState(BareNetworkString* bns);
// --------------------------------------------------------------------
void restoreCompleteState(const BareNetworkString& b);
};
// ------------------------------------------------------------------------
@@ -121,7 +125,7 @@ protected:
* This member is not strictly private but try not to use it directly outside
* tightly related classes (e.g. AI)
*/
AlignedArray<KartInfo> m_kart_info;
std::vector<KartInfo> m_kart_info;
virtual void checkForWrongDirection(unsigned int i, float dt);
virtual float estimateFinishTimeForKart(AbstractKart* kart) OVERRIDE;
@@ -204,6 +208,10 @@ public:
// ------------------------------------------------------------------------
virtual std::pair<uint32_t, uint32_t> getGameStartedProgress() const
OVERRIDE;
// ------------------------------------------------------------------------
virtual void saveCompleteState(BareNetworkString* bns) OVERRIDE;
// ------------------------------------------------------------------------
virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE;
}; // LinearWorld
#endif

View File

@@ -155,9 +155,7 @@ void GameSetup::addServerInfo(NetworkString* ns)
ns->encodeString16(m_message_of_today);
ns->addUInt8((uint8_t)ServerConfig::m_server_configurable);
ns->addUInt8(
ServerConfig::m_live_players && race_manager->supportsLiveJoining() ?
1 : 0);
ns->addUInt8(ServerConfig::m_live_players? 1 : 0);
} // addServerInfo
//-----------------------------------------------------------------------------

View File

@@ -518,7 +518,7 @@ void ClientLobby::disconnectedPlayer(Event* event)
{
std::string name;
data.decodeString(&name);
if (!World::getWorld())
if (World::getWorld())
continue;
core::stringw player_name = StringUtils::utf8ToWide(name);
core::stringw msg = _("%s disconnected.", player_name);

View File

@@ -661,8 +661,34 @@ NetworkString* ServerLobby::getLoadWorldMessage(
*/
bool ServerLobby::canLiveJoinNow() const
{
return ServerConfig::m_live_players &&
race_manager->supportsLiveJoining() && worldIsActive();
bool live_join = ServerConfig::m_live_players && worldIsActive();
if (!live_join)
return false;
if (race_manager->modeHasLaps())
{
// No spectate when fastest kart is nearly finish, because if there
// is endcontroller the spectating remote may not be knowing this
// on time
LinearWorld* w = dynamic_cast<LinearWorld*>(World::getWorld());
if (!w)
return false;
AbstractKart* fastest_kart = NULL;
for (unsigned i = 0; i < w->getNumKarts(); i++)
{
fastest_kart = w->getKartAtPosition(i + 1);
if (fastest_kart && !fastest_kart->isEliminated())
break;
}
if (!fastest_kart)
return false;
float progress = w->getOverallDistance(
fastest_kart->getWorldKartId()) /
(Track::getCurrentTrack()->getTrackLength() *
(float)race_manager->getNumLaps());
if (progress > 0.9f)
return false;
}
return live_join;
} // canLiveJoinNow
//-----------------------------------------------------------------------------
@@ -712,6 +738,13 @@ void ServerLobby::liveJoinRequest(Event* event)
return;
}
bool spectator = data.getUInt8() == 1;
if (race_manager->modeHasLaps() && !spectator)
{
// No live join for linear race
rejectLiveJoin(peer, BLR_NO_GAME_FOR_LIVE_JOIN);
return;
}
peer->clearAvailableKartIDs();
if (!spectator)
{
@@ -761,10 +794,22 @@ void ServerLobby::liveJoinRequest(Event* event)
rki.getNetworkPlayerProfile().lock();
if (!player)
{
player = NetworkPlayerProfile::getReservedProfile(
race_manager->getMinorMode() ==
RaceManager::MINOR_MODE_FREE_FOR_ALL ?
KART_TEAM_NONE : rki.getKartTeam());
if (race_manager->modeHasLaps())
{
player = std::make_shared<NetworkPlayerProfile>(
nullptr, rki.getPlayerName(),
std::numeric_limits<uint32_t>::max(),
rki.getDefaultKartColor(),
rki.getOnlineId(), rki.getDifficulty(),
rki.getLocalPlayerId(), KART_TEAM_NONE);
}
else
{
player = NetworkPlayerProfile::getReservedProfile(
race_manager->getMinorMode() ==
RaceManager::MINOR_MODE_FREE_FOR_ALL ?
KART_TEAM_NONE : rki.getKartTeam());
}
}
players.push_back(player);
}

View File

@@ -592,8 +592,7 @@ void RaceManager::startNextRace()
// functions.
World::getWorld()->reset();
if (NetworkConfig::get()->isNetworking() &&
race_manager->supportsLiveJoining())
if (NetworkConfig::get()->isNetworking())
{
for (unsigned i = 0; i < race_manager->getNumPlayers(); i++)
{

View File

@@ -268,7 +268,7 @@ void RacePausedDialog::beforeAddingWidgets()
(choice_ribbon->findWidgetNamed("newrace"));
if (new_race)
{
//I18N show in race paused dialog in network to allow user to go
//I18N: show in race paused dialog in network to allow user to go
//back to lobby to end spectating (for example)
new_race->setText(_("Back to lobby"));
}

View File

@@ -374,8 +374,13 @@ void NetworkingLobby::onUpdate(float delta)
if (m_client_live_joinable)
{
m_start_button->setVisible(true);
m_start_button->setLabel(m_live_join_text);
if (race_manager->supportsLiveJoining())
{
m_start_button->setVisible(true);
m_start_button->setLabel(m_live_join_text);
}
else
m_start_button->setVisible(false);
m_config_button->setLabel(m_spectate_text);
m_config_button->setImage(m_spectate_texture);
m_config_button->setVisible(true);

View File

@@ -192,3 +192,31 @@ void TrackSector::rewindTo(BareNetworkString* buffer)
m_current_graph_node = node;
m_current_track_coords.setZ(buffer->getFloat());
} // rewindTo
// ----------------------------------------------------------------------------
/** Save completely for spectating in linear race
*/
void TrackSector::saveCompleteState(BareNetworkString* bns)
{
bns->addUInt32(m_current_graph_node);
bns->addUInt32(m_estimated_valid_graph_node);
bns->addUInt32(m_last_valid_graph_node);
bns->add(m_current_track_coords);
bns->add(m_estimated_valid_track_coords);
bns->add(m_latest_valid_track_coords);
bns->addUInt8(m_on_road ? 0 : 1);
bns->addUInt32(m_last_triggered_checkline);
} // saveCompleteState
// ----------------------------------------------------------------------------
void TrackSector::restoreCompleteState(const BareNetworkString& b)
{
m_current_graph_node = b.getUInt32();
m_estimated_valid_graph_node = b.getUInt32();
m_last_valid_graph_node = b.getUInt32();
m_current_track_coords = b.getVec3();
m_estimated_valid_track_coords = b.getVec3();
m_latest_valid_track_coords = b.getVec3();
m_on_road = b.getUInt8() == 1;
m_last_triggered_checkline = b.getUInt32();
} // restoreCompleteState

View File

@@ -95,6 +95,10 @@ public:
void saveState(BareNetworkString* buffer) const;
// ------------------------------------------------------------------------
void rewindTo(BareNetworkString* buffer);
// ------------------------------------------------------------------------
void saveCompleteState(BareNetworkString* bns);
// ------------------------------------------------------------------------
void restoreCompleteState(const BareNetworkString& b);
}; // TrackSector