Merge remote-tracking branch 'origin/network_improvements' into game_protocol
This commit is contained in:
commit
e7d3658a53
@ -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)
|
||||
|
@ -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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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()++;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -219,7 +219,6 @@ void NetworkKartSelectionScreen::playerSelected(uint8_t player_id,
|
||||
//WaitingForOthersScreen::getInstance()->push();
|
||||
//return;
|
||||
}
|
||||
TracksScreen::getInstance()->setOfficalTrack(true);
|
||||
TracksScreen::getInstance()->push();
|
||||
} // playerSelected
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user