Merge remote-tracking branch 'origin/network_improvements' into game_protocol

This commit is contained in:
Benau 2018-02-15 10:36:14 +08:00
commit e7d3658a53
15 changed files with 201 additions and 26 deletions

View File

@ -269,7 +269,13 @@ void Attachment::saveState(BareNetworkString *buffer) const
void Attachment::rewindTo(BareNetworkString *buffer)
{
uint8_t type = buffer->getUInt8();
AttachmentType new_type = AttachmentType(type & 0x7f); // mask out bit 7
// FIXME Sometimes type == 255 is returned, reason unknown
if (new_type > ATTACH_NOTHING)
{
return;
}
// If there is no attachment, clear the attachment if necessary and exit
if(new_type==ATTACH_NOTHING)

View File

@ -19,6 +19,7 @@
#include "network/protocols/client_lobby.hpp"
#include "config/player_manager.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/world_with_rank.hpp"
#include "network/event.hpp"
#include "network/network_config.hpp"
@ -33,6 +34,7 @@
#include "states_screens/network_kart_selection.hpp"
#include "states_screens/race_result_gui.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/track_manager.hpp"
#include "utils/log.hpp"
// ============================================================================
@ -321,6 +323,23 @@ void ClientLobby::update(float dt)
// 4 (size of id), global id
ns->addUInt8(LE_CONNECTION_REQUESTED).encodeString(name)
.encodeString(NetworkConfig::get()->getPassword());
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
all_k.resize(65535);
if (all_t.size() >= 65536)
all_t.resize(65535);
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
for (const std::string& kart : all_k)
{
ns->encodeString(kart);
}
for (const std::string& track : all_t)
{
ns->encodeString(track);
}
sendToServer(ns);
delete ns;
m_state = REQUESTING_CONNECTION;
@ -334,6 +353,7 @@ void ClientLobby::update(float dt)
{
NetworkKartSelectionScreen* screen =
NetworkKartSelectionScreen::getInstance();
screen->setAvailableKartsFromServer(m_available_karts);
screen->push();
m_state = SELECTING_KARTS;
@ -547,6 +567,9 @@ void ClientLobby::connectionRefused(Event* event)
case 2:
Log::info("ClientLobby", "Client busy.");
break;
case 3:
Log::info("ClientLobby", "Having incompatible karts / tracks.");
break;
default:
Log::info("ClientLobby", "Connection refused.");
break;
@ -658,6 +681,21 @@ void ClientLobby::startingRaceNow()
void ClientLobby::startSelection(Event* event)
{
m_state = KART_SELECTION;
const NetworkString& data = event->data();
const unsigned kart_num = data.getUInt16();
const unsigned track_num = data.getUInt16();
for (unsigned i = 0; i < kart_num; i++)
{
std::string kart;
data.decodeString(&kart);
m_available_karts.insert(kart);
}
for (unsigned i = 0; i < track_num; i++)
{
std::string track;
data.decodeString(&track);
m_available_tracks.insert(track);
}
Log::info("ClientLobby", "Kart selection starts now");
} // startSelection
@ -712,6 +750,10 @@ void ClientLobby::raceFinished(Event* event)
void ClientLobby::exitResultScreen(Event *event)
{
RaceResultGUI::getInstance()->backToLobby();
// Will be reset to linked if connected to server, see update(float dt)
m_game_setup = STKHost::get()->setupNewGame();
STKHost::get()->getServerPeerForClient()->unsetClientServerToken();
m_state = NONE;
} // exitResultScreen
//-----------------------------------------------------------------------------

View File

@ -4,6 +4,7 @@
#include "network/protocols/lobby_protocol.hpp"
#include "network/transport_address.hpp"
#include "utils/cpp2011.hpp"
#include <set>
class STKPeer;
@ -49,6 +50,9 @@ private:
/** The state of the finite state machine. */
STATE m_state;
std::set<std::string> m_available_karts;
std::set<std::string> m_available_tracks;
public:
ClientLobby();
virtual ~ClientLobby();
@ -67,6 +71,11 @@ public:
void startingRaceNow();
void leave();
const std::set<std::string>& getAvailableKarts() const
{ return m_available_karts; }
const std::set<std::string>& getAvailableTracks() const
{ return m_available_tracks; }
virtual bool notifyEvent(Event* event) OVERRIDE;
virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
virtual void finishedLoadingWorld() OVERRIDE;

View File

@ -305,7 +305,8 @@ void GameProtocol::rewind(BareNetworkString *buffer)
int value_r = buffer->getUInt32();
Controller *c = World::getWorld()->getKart(kart_id)->getController();
PlayerController *pc = dynamic_cast<PlayerController*>(c);
assert(pc);
// FIXME this can be endcontroller when finishing the race
//assert(pc);
if(pc)
pc->actionFromNetwork(action, value, value_l, value_r);
} // rewind

View File

@ -20,6 +20,7 @@
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/world.hpp"
#include "network/event.hpp"
#include "network/network_config.hpp"
@ -36,11 +37,11 @@
#include "states_screens/networking_lobby.hpp"
#include "states_screens/race_result_gui.hpp"
#include "states_screens/waiting_for_others.hpp"
#include "tracks/track_manager.hpp"
#include "utils/log.hpp"
#include "utils/random_generator.hpp"
#include "utils/time.hpp"
/** This is the central game setup protocol running in the server. It is
* mostly a finite state machine. Note that all nodes in ellipses and light
* grey background are actual states; nodes in boxes and white background
@ -48,9 +49,9 @@
* change.
\dot
digraph interaction {
node [shape=box]; "Server Constructor"; "playerTrackVote"; "connectionRequested";
"signalRaceStartToClients"; "startedRaceOnClient"; "loadWorld";
node [shape=ellipse,style=filled,color=lightgrey];
node [shape=box]; "Server Constructor"; "playerTrackVote"; "connectionRequested";
"signalRaceStartToClients"; "startedRaceOnClient"; "loadWorld";
node [shape=ellipse,style=filled,color=lightgrey];
"Server Constructor" -> "INIT_WAN" [label="If WAN game"]
"Server Constructor" -> "ACCEPTING_CLIENTS" [label="If LAN game"]
@ -83,6 +84,15 @@
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
{
setHandleDisconnections(true);
// We use maximum 16bit unsigned limit
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
if (all_k.size() >= 65536)
all_k.resize(65535);
if (all_t.size() >= 65536)
all_t.resize(65535);
m_available_kts.getData().first = { all_k.begin(), all_k.end() };
m_available_kts.getData().second = { all_t.begin(), all_t.end() };
} // ServerLobby
//-----------------------------------------------------------------------------
@ -283,6 +293,7 @@ void ServerLobby::update(float dt)
pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
pm->findAndTerminate(PROTOCOL_KART_UPDATE);
pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
setup();
}
break;
case DONE:
@ -386,6 +397,20 @@ void ServerLobby::startSelection(const Event *event)
// a new screen, which must be donefrom the main thread.
ns->setSynchronous(true);
ns->addUInt8(LE_START_SELECTION);
m_available_kts.lock();
const auto& all_k = m_available_kts.getData().first;
const auto& all_t = m_available_kts.getData().second;
ns->addUInt16((uint16_t)all_k.size()).addUInt16((uint16_t)all_t.size());
for (const std::string& kart : all_k)
{
ns->encodeString(kart);
}
for (const std::string& track : all_t)
{
ns->encodeString(track);
}
m_available_kts.unlock();
sendMessageToPeersChangingToken(ns, /*reliable*/true);
delete ns;
@ -563,12 +588,71 @@ void ServerLobby::connectionRequested(Event* event)
// Connection accepted.
// ====================
std::string name_u8;
int len = data.decodeString(&name_u8);
data.decodeString(&name_u8);
core::stringw name = StringUtils::utf8ToWide(name_u8);
std::string password;
data.decodeString(&password);
bool is_authorised = (password==NetworkConfig::get()->getPassword());
std::set<std::string> client_karts, client_tracks;
const unsigned kart_num = data.getUInt16();
const unsigned track_num = data.getUInt16();
for (unsigned i = 0; i < kart_num; i++)
{
std::string kart;
data.decodeString(&kart);
client_karts.insert(kart);
}
for (unsigned i = 0; i < track_num; i++)
{
std::string track;
data.decodeString(&track);
client_tracks.insert(track);
}
// Remove karts/tracks from server that are not supported on the new client
// so that in the end the server has a list of all karts/tracks available
// on all clients
std::set<std::string> karts_erase, tracks_erase;
for (const std::string& server_kart : m_available_kts.getData().first)
{
if (client_karts.find(server_kart) == client_karts.end())
{
karts_erase.insert(server_kart);
}
}
for (const std::string& server_track : m_available_kts.getData().second)
{
if (client_tracks.find(server_track) == client_tracks.end())
{
tracks_erase.insert(server_track);
}
}
// Drop this player if he doesn't have at least 1 kart / track the same
// from server
if (karts_erase.size() == m_available_kts.getData().first.size() ||
tracks_erase.size() == m_available_kts.getData().second.size())
{
NetworkString *message = getNetworkString(2);
message->addUInt8(LE_CONNECTION_REFUSED).addUInt8(3);
peer->sendPacket(message);
delete message;
Log::verbose("ServerLobby", "Player has incompatible karts / tracks");
m_available_kts.unlock();
return;
}
for (const std::string& kart_erase : karts_erase)
{
m_available_kts.getData().first.erase(kart_erase);
}
for (const std::string& track_erase : tracks_erase)
{
m_available_kts.getData().second.erase(track_erase);
}
m_available_kts.unlock();
// Get the unique global ID for this player.
m_next_player_id.lock();
m_next_player_id.getData()++;

View File

@ -5,6 +5,8 @@
#include "utils/cpp2011.hpp"
#include "utils/synchronised.hpp"
#include <set>
class ServerLobby : public LobbyProtocol
, public CallbackObject
{
@ -27,6 +29,11 @@ private:
EXITING
} m_state;
/** Available karts and tracks for all clients, this will be initialized
* with data in server first. */
Synchronised<std::pair<std::set<std::string>,
std::set<std::string> > > m_available_kts;
/** Next id to assign to a peer. */
Synchronised<int> m_next_player_id;

View File

@ -710,6 +710,18 @@ STKPeer* STKHost::getPeer(ENetPeer *enet_peer)
m_next_unique_host_id ++;
return peer;
} // getPeer
// ----------------------------------------------------------------------------
/** \brief Return the only server peer for client.
* \return STKPeer the STKPeer of server.
*/
STKPeer* STKHost::getServerPeerForClient() const
{
assert(m_peers.size() == 1);
assert(NetworkConfig::get()->isClient());
return m_peers[0];
} // getServerPeerForClient
// ----------------------------------------------------------------------------
/** \brief Tells if a peer is known and connected.
* \return True if the peer is known and connected, false elseway.

View File

@ -162,6 +162,7 @@ public:
void removePeer(const STKPeer* peer);
bool isConnectedTo(const TransportAddress& peer_address);
STKPeer *getPeer(ENetPeer *enet_peer);
STKPeer *getServerPeerForClient() const;
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
int mustStopListening();
uint16_t getPort() const;

View File

@ -163,7 +163,6 @@ void GhostReplaySelection::eventCallback(GUIEngine::Widget* widget,
else if (name == "record-ghost")
{
race_manager->setRecordRace(true);
TracksScreen::getInstance()->setOfficalTrack(false);
TracksScreen::getInstance()->push();
}
else if (name == "replay_difficulty_toggle")

View File

@ -1470,8 +1470,8 @@ void KartSelectionScreen::setKartsFromCurrentGroup()
{
const KartProperties* prop = kart_properties_manager->getKartById(i);
// Ignore karts that are not in the selected group
if(selected_kart_group != ALL_KART_GROUPS_ID &&
!prop->isInGroup(selected_kart_group))
if((selected_kart_group != ALL_KART_GROUPS_ID &&
!prop->isInGroup(selected_kart_group)) || isIgnored(prop->getIdent()))
continue;
karts.push_back(prop);
}

View File

@ -123,6 +123,8 @@ protected:
/** Remove the multiplayer message. */
void removeMultiplayerMessage();
virtual bool isIgnored(const std::string& ident) const { return false; }
/** Stores a pointer to the current selection screen */
static KartSelectionScreen* m_instance_ptr;
public:

View File

@ -219,7 +219,6 @@ void NetworkKartSelectionScreen::playerSelected(uint8_t player_id,
//WaitingForOthersScreen::getInstance()->push();
//return;
}
TracksScreen::getInstance()->setOfficalTrack(true);
TracksScreen::getInstance()->push();
} // playerSelected

View File

@ -21,6 +21,8 @@
#include "states_screens/kart_selection.hpp"
#include "guiengine/screen.hpp"
#include <set>
class NetworkKartSelectionScreen : public KartSelectionScreen,
public GUIEngine::ScreenSingleton<NetworkKartSelectionScreen>
{
@ -33,7 +35,19 @@ protected:
virtual ~NetworkKartSelectionScreen();
virtual void playerConfirm(const int playerID) OVERRIDE;
private:
std::set<std::string> m_available_karts;
virtual bool isIgnored(const std::string& ident) const OVERRIDE
{
return m_available_karts.find(ident) == m_available_karts.end();
}
public:
void setAvailableKartsFromServer(const std::set<std::string>& k)
{
m_available_karts = k;
}
virtual void init() OVERRIDE;
virtual bool onEscapePressed() OVERRIDE;
virtual void playerSelected(uint8_t player_id,

View File

@ -195,19 +195,18 @@ void TracksScreen::buildTrackList()
m_random_track_list.clear();
const std::string& curr_group_name = tabs->getSelectionIDString(0);
if (!(curr_group_name == DEFAULT_GROUP_NAME ||
curr_group_name == ALL_TRACK_GROUPS_ID) && m_offical_track)
{
tracks_widget->setText(_("Only official tracks are supported."));
tracks_widget->updateItemDisplay();
return;
}
const int track_amount = (int)track_manager->getNumberOfTracks();
// First build a list of all tracks to be displayed
// (e.g. exclude arenas, ...)
bool is_network = (STKHost::existHost());
ClientLobby* clrp = NULL;
if (is_network)
{
Protocol* protocol = LobbyProtocol::get();
clrp = dynamic_cast<ClientLobby*>(protocol);
assert(clrp);
}
PtrVector<Track, REF> tracks;
for (int n = 0; n < track_amount; n++)
{
@ -216,14 +215,18 @@ void TracksScreen::buildTrackList()
&& !curr->hasEasterEggs())
continue;
if (curr->isArena() || curr->isSoccer()||curr->isInternal()) continue;
if (m_offical_track && !curr->isInGroup(DEFAULT_GROUP_NAME)) continue;
if (!curr->isInGroup(DEFAULT_GROUP_NAME)) continue;
if (curr_group_name != ALL_TRACK_GROUPS_ID &&
!curr->isInGroup(curr_group_name)) continue;
if (is_network &&
clrp->getAvailableTracks().find(curr->getIdent()) ==
clrp->getAvailableTracks().end())
{
continue;
}
tracks.push_back(curr);
} // for n<track_amount
bool is_network = (STKHost::existHost());
tracks.insertionSort();
for (unsigned int i = 0; i < tracks.size(); i++)
{

View File

@ -40,8 +40,6 @@ private:
std::deque<std::string> m_random_track_list;
bool m_offical_track;
public:
/** \brief implement callback from parent class GUIEngine::Screen */
@ -58,8 +56,6 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void beforeAddingWidget() OVERRIDE;
void setOfficalTrack(bool offical) { m_offical_track = offical; }
void setFocusOnTrack(const std::string& trackName);
};