Skip to content

Commit

Permalink
Merge pull request godotengine#175 from Ughuuu/add-reconnection-handler
Browse files Browse the repository at this point in the history
Add reconnection handler to Lobby Client
  • Loading branch information
Bioblaze authored Dec 5, 2024
2 parents 932319a + f9df54f commit 05b782b
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 30 deletions.
41 changes: 35 additions & 6 deletions modules/blazium_sdk/doc_classes/LobbyClient.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
<methods>
<method name="connect_to_lobby">
<return type="bool" />
<param index="0" name="game_id" type="String" />
<description>
Connect to a Blazium Lobby Server using the game_id and [member server_url].
</description>
</method>
<method name="create_lobby">
<return type="ViewLobbyResponse" />
<param index="0" name="title" type="String" />
<param index="1" name="max_players" type="int" default="4" />
<param index="2" name="password" type="String" default="&quot;&quot;" />
<param index="1" name="tags" type="String[]" default="[]" />
<param index="2" name="max_players" type="int" default="4" />
<param index="3" name="password" type="String" default="&quot;&quot;" />
<description>
Create a lobby and become host. If you are already in a lobby, you cannot create one. You need to leave first.
Generates [signal lobby_created] signal.
Expand Down Expand Up @@ -58,8 +58,11 @@
</method>
<method name="list_lobbies">
<return type="ListLobbyResponse" />
<param index="0" name="start" type="int" default="0" />
<param index="1" name="count" type="int" default="10" />
<param index="0" name="title" type="String" default="&quot;&quot;" />
<param index="1" name="max_players" type="int" default="-1" />
<param index="2" name="tags" type="String[]" default="[]" />
<param index="3" name="start" type="int" default="0" />
<param index="4" name="count" type="int" default="10" />
<description>
Lists all lobbies.
</description>
Expand Down Expand Up @@ -126,6 +129,8 @@
<member name="connected" type="bool" setter="" getter="get_connected" default="false">
True if the client is connected, else false.
</member>
<member name="game_id" type="String" setter="set_game_id" getter="get_game_id" default="&quot;&quot;">
</member>
<member name="lobby" type="LobbyInfo" setter="" getter="get_lobby">
The current lobby. Reflects changes to the lobby.
</member>
Expand All @@ -135,14 +140,25 @@
<member name="peers" type="LobbyPeer[]" setter="" getter="get_peers" default="[]">
The lobby peers. Reflects changes to all peers.
</member>
<member name="reconnection_token" type="String" setter="set_reconnection_token" getter="get_reconnection_token" default="&quot;&quot;">
Reconnection token.
</member>
<member name="server_url" type="String" setter="set_server_url" getter="get_server_url" default="&quot;wss://lobby.blazium.app/connect&quot;">
Set to what url this lobby should connect to.
</member>
</members>
<signals>
<signal name="connected_to_lobby">
<param index="0" name="peer" type="LobbyPeer" />
<param index="1" name="reconnection_token" type="String" />
<description>
Signal generated after you connect to the lobby.
</description>
</signal>
<signal name="disconnected_from_lobby">
<param index="0" name="reason" type="String" />
<description>
Disconnects from the lobby.
Signal generated after you disconnect from the lobby.
</description>
</signal>
<signal name="lobby_created">
Expand All @@ -160,6 +176,7 @@
</description>
</signal>
<signal name="lobby_left">
<param index="0" name="kicked" type="bool" />
<description>
Signal generated after you leave a lobby.
</description>
Expand All @@ -177,6 +194,12 @@
Signals a log from a command.
</description>
</signal>
<signal name="peer_disconnected">
<param index="0" name="peer" type="LobbyPeer" />
<description>
Signal generated after a peer disconnects. If they don't reconnect they will be removed.
</description>
</signal>
<signal name="peer_joined">
<param index="0" name="peer" type="LobbyPeer" />
<description>
Expand Down Expand Up @@ -210,6 +233,12 @@
Signal generated after a peer is ready.
</description>
</signal>
<signal name="peer_reconnected">
<param index="0" name="peer" type="LobbyPeer" />
<description>
Signal generated after a peer reconnects.
</description>
</signal>
<signal name="received_data">
<param index="0" name="data" type="Object" />
<param index="1" name="from_peer" type="LobbyPeer" />
Expand Down
5 changes: 4 additions & 1 deletion modules/blazium_sdk/doc_classes/LobbyInfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@
<member name="max_players" type="int" setter="" getter="get_max_players" default="0">
The maximum number of players allowed in the lobby.
</member>
<member name="password_protected" type="bool" setter="" getter="is_password_protected" default="true">
<member name="password_protected" type="bool" setter="" getter="is_password_protected" default="false">
</member>
<member name="players" type="int" setter="" getter="get_players" default="0">
The number of players currently in the lobby.
</member>
<member name="sealed" type="bool" setter="" getter="is_sealed" default="false">
Whether the lobby is sealed.
</member>
<member name="tags" type="String[]" setter="" getter="get_tags" default="[]">
The tags of the lobby. Used for listing lobbies to filter based on them.
</member>
</members>
</class>
87 changes: 74 additions & 13 deletions modules/blazium_sdk/lobby/lobby_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,20 @@ LobbyClient::~LobbyClient() {
void LobbyClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_server_url", "server_url"), &LobbyClient::set_server_url);
ClassDB::bind_method(D_METHOD("get_server_url"), &LobbyClient::get_server_url);
ClassDB::bind_method(D_METHOD("set_reconnection_token", "reconnection_token"), &LobbyClient::set_reconnection_token);
ClassDB::bind_method(D_METHOD("get_reconnection_token"), &LobbyClient::get_reconnection_token);
ClassDB::bind_method(D_METHOD("set_game_id", "game_id"), &LobbyClient::set_game_id);
ClassDB::bind_method(D_METHOD("get_game_id"), &LobbyClient::get_game_id);

ClassDB::bind_method(D_METHOD("is_host"), &LobbyClient::is_host);
ClassDB::bind_method(D_METHOD("get_connected"), &LobbyClient::get_connected);
ClassDB::bind_method(D_METHOD("get_lobby"), &LobbyClient::get_lobby);
ClassDB::bind_method(D_METHOD("get_peer"), &LobbyClient::get_peer);
ClassDB::bind_method(D_METHOD("get_peers"), &LobbyClient::get_peers);

ADD_PROPERTY(PropertyInfo(Variant::STRING, "server_url", PROPERTY_HINT_NONE, ""), "set_server_url", "get_server_url");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "reconnection_token", PROPERTY_HINT_NONE, ""), "set_reconnection_token", "get_reconnection_token");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "game_id", PROPERTY_HINT_NONE, ""), "set_game_id", "get_game_id");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "connected"), "", "get_connected");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "lobby", PROPERTY_HINT_RESOURCE_TYPE, "LobbyInfo"), "", "get_lobby");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer"), "", "get_peer");
Expand All @@ -60,12 +67,12 @@ void LobbyClient::_bind_methods() {
ADD_PROPERTY_DEFAULT("peer", Ref<LobbyPeer>());
ADD_PROPERTY_DEFAULT("lobby", Ref<LobbyInfo>());
// Register methods
ClassDB::bind_method(D_METHOD("connect_to_lobby", "game_id"), &LobbyClient::connect_to_lobby);
ClassDB::bind_method(D_METHOD("connect_to_lobby"), &LobbyClient::connect_to_lobby);
ClassDB::bind_method(D_METHOD("set_peer_name", "peer_name"), &LobbyClient::set_peer_name);
ClassDB::bind_method(D_METHOD("create_lobby", "title", "max_players", "password"), &LobbyClient::create_lobby, DEFVAL(4), DEFVAL(""));
ClassDB::bind_method(D_METHOD("create_lobby", "title", "tags", "max_players", "password"), &LobbyClient::create_lobby, DEFVAL(Array()), DEFVAL(4), DEFVAL(""));
ClassDB::bind_method(D_METHOD("join_lobby", "lobby_id", "password"), &LobbyClient::join_lobby, DEFVAL(""));
ClassDB::bind_method(D_METHOD("leave_lobby"), &LobbyClient::leave_lobby);
ClassDB::bind_method(D_METHOD("list_lobbies", "start", "count"), &LobbyClient::list_lobby, DEFVAL(0), DEFVAL(10));
ClassDB::bind_method(D_METHOD("list_lobbies", "title", "max_players", "tags", "start", "count"), &LobbyClient::list_lobby, DEFVAL(""), DEFVAL(-1), DEFVAL(Array()), DEFVAL(0), DEFVAL(10));
ClassDB::bind_method(D_METHOD("view_lobby", "lobby_id", "password"), &LobbyClient::view_lobby, DEFVAL(""), DEFVAL(""));
ClassDB::bind_method(D_METHOD("kick_peer", "peer_id"), &LobbyClient::kick_peer);
ClassDB::bind_method(D_METHOD("send_chat_message", "chat_message"), &LobbyClient::lobby_chat);
Expand All @@ -75,27 +82,34 @@ void LobbyClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("send_lobby_data_to", "data", "target_peer"), &LobbyClient::lobby_data_to);

// Register signals
ADD_SIGNAL(MethodInfo("disconnected_from_lobby"));
ADD_SIGNAL(MethodInfo("connected_to_lobby", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer"), PropertyInfo(Variant::STRING, "reconnection_token")));
ADD_SIGNAL(MethodInfo("disconnected_from_lobby", PropertyInfo(Variant::STRING, "reason")));
ADD_SIGNAL(MethodInfo("peer_named", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("received_data", PropertyInfo(Variant::OBJECT, "data"), PropertyInfo(Variant::OBJECT, "from_peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("received_data_to", PropertyInfo(Variant::OBJECT, "data"), PropertyInfo(Variant::OBJECT, "from_peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("lobby_created", PropertyInfo(Variant::OBJECT, "lobby", PROPERTY_HINT_RESOURCE_TYPE, "LobbyInfo"), PropertyInfo(Variant::ARRAY, "peers", PROPERTY_HINT_ARRAY_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("lobby_joined", PropertyInfo(Variant::OBJECT, "lobby", PROPERTY_HINT_RESOURCE_TYPE, "LobbyInfo"), PropertyInfo(Variant::ARRAY, "peers", PROPERTY_HINT_ARRAY_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("lobby_left"));
ADD_SIGNAL(MethodInfo("lobby_left", PropertyInfo(Variant::BOOL, "kicked")));
ADD_SIGNAL(MethodInfo("lobby_sealed", PropertyInfo(Variant::BOOL, "sealed")));
ADD_SIGNAL(MethodInfo("peer_joined", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("peer_reconnected", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("peer_left", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer"), PropertyInfo(Variant::BOOL, "kicked")));
ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer")));
ADD_SIGNAL(MethodInfo("peer_messaged", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer"), PropertyInfo(Variant::STRING, "chat_message")));
ADD_SIGNAL(MethodInfo("peer_ready", PropertyInfo(Variant::OBJECT, "peer", PROPERTY_HINT_RESOURCE_TYPE, "LobbyPeer"), PropertyInfo(Variant::BOOL, "ready")));
ADD_SIGNAL(MethodInfo("log_updated", PropertyInfo(Variant::STRING, "command"), PropertyInfo(Variant::STRING, "logs")));
}

bool LobbyClient::connect_to_lobby(const String &p_game_id) {
bool LobbyClient::connect_to_lobby() {
if (connected) {
return true;
}
String lobby_url = get_server_url();
String url = lobby_url + "?gameID=" + p_game_id;
String url = lobby_url;
Vector<String> headers;
headers.push_back("GAME_ID: " + game_id);
headers.push_back("RECONNECTION_TOKEN: " + reconnection_token);
_socket->set_handshake_headers(headers);
Error err = _socket->connect_to_url(url);
if (err != OK) {
set_process_internal(false);
Expand All @@ -109,11 +123,21 @@ bool LobbyClient::connect_to_lobby(const String &p_game_id) {
return true;
}

void LobbyClient::disconnect_from_lobby() {
if (connected) {
_socket->close();
connected = false;
set_process_internal(false);
emit_signal("disconnected_from_lobby", _socket->get_close_reason());
emit_signal("log_updated", "disconnect_from_lobby", "Disconnected from: " + get_server_url());
}
}

String LobbyClient::_increment_counter() {
return String::num(_counter++);
}

Ref<LobbyClient::ViewLobbyResponse> LobbyClient::create_lobby(const String &p_lobby_name, int p_max_players, const String &p_password) {
Ref<LobbyClient::ViewLobbyResponse> LobbyClient::create_lobby(const String &p_lobby_name, const TypedArray<String> &p_tags, int p_max_players, const String &p_password) {
String id = _increment_counter();
Dictionary command;
command["command"] = "create_lobby";
Expand All @@ -122,6 +146,7 @@ Ref<LobbyClient::ViewLobbyResponse> LobbyClient::create_lobby(const String &p_lo
data_dict["name"] = p_lobby_name;
data_dict["max_players"] = p_max_players;
data_dict["password"] = p_password;
data_dict["tags"] = p_tags;
data_dict["id"] = id;
Array command_array;
Ref<ViewLobbyResponse> response;
Expand Down Expand Up @@ -169,14 +194,25 @@ Ref<LobbyClient::LobbyResponse> LobbyClient::leave_lobby() {
return response;
}

Ref<LobbyClient::ListLobbyResponse> LobbyClient::list_lobby(int p_start, int p_count) {
Ref<LobbyClient::ListLobbyResponse> LobbyClient::list_lobby(const String &p_title, const int p_max_players, const TypedArray<String> &p_tags, int p_start, int p_count) {
String id = _increment_counter();
Dictionary command;
command["command"] = "list_lobby";
Dictionary data_dict;
data_dict["id"] = id;
data_dict["start"] = p_start;
data_dict["count"] = p_count;
Dictionary filter_dict;
data_dict["filter"] = filter_dict;
if (p_tags.size() != 0) {
filter_dict["tags"] = p_tags;
}
if (!p_title.is_empty()) {
filter_dict["name"] = p_title;
}
if (p_max_players != -1) {
filter_dict["max_players"] = int(p_max_players);
}
command["data"] = data_dict;
Array command_array;
Ref<ListLobbyResponse> response;
Expand Down Expand Up @@ -362,8 +398,8 @@ void LobbyClient::_notification(int p_what) {
_receive_data(JSON::parse_string(packet_string));
}
} else if (state == WebSocketPeer::STATE_CLOSED) {
emit_signal("log_updated", "error", "WebSocket closed unexpectedly.");
emit_signal("disconnected_from_lobby");
emit_signal("log_updated", "error", _socket->get_close_reason());
emit_signal("disconnected_from_lobby", _socket->get_close_reason());
set_process_internal(false);
connected = false;
}
Expand Down Expand Up @@ -456,7 +492,9 @@ void LobbyClient::_receive_data(const Dictionary &p_dict) {
}
if (command == "peer_state") {
Dictionary peer_dict = data_dict.get("peer", Dictionary());
peer->set_id(peer_dict.get("id", ""));
peer->set_dict(peer_dict);
reconnection_token = peer_dict.get("reconnection_token", "");
emit_signal("connected_to_lobby", peer, reconnection_token);
} else if (command == "lobby_created") {
lobby->set_dict(data_dict.get("lobby", Dictionary()));
update_peers(data_dict, peers);
Expand All @@ -470,7 +508,11 @@ void LobbyClient::_receive_data(const Dictionary &p_dict) {
} else if (command == "lobby_left") {
lobby->set_dict(Dictionary());
peers.clear();
emit_signal("lobby_left");
emit_signal("lobby_left", false);
} else if (command == "lobby_kicked") {
lobby->set_dict(Dictionary());
peers.clear();
emit_signal("lobby_left", true);
} else if (command == "lobby_sealed") {
Dictionary lobby_dict = data_dict.get("lobby", Dictionary());
lobby->set_sealed(true);
Expand Down Expand Up @@ -564,6 +606,14 @@ void LobbyClient::_receive_data(const Dictionary &p_dict) {
sort_peers_by_id(peers);
lobby->set_players(peers.size());
emit_signal("peer_joined", joining_peer);
} else if (command == "peer_reconnected") {
for (int i = 0; i < peers.size(); ++i) {
Ref<LobbyPeer> updated_peer = peers[i];
if (updated_peer->get_id() == String(data_dict.get("peer_id", ""))) {
emit_signal("peer_reconnected", updated_peer);
break;
}
}
} else if (command == "peer_left") {
for (int i = 0; i < peers.size(); ++i) {
Ref<LobbyPeer> leaving_peer = peers[i];
Expand All @@ -575,6 +625,17 @@ void LobbyClient::_receive_data(const Dictionary &p_dict) {
}
}
sort_peers_by_id(peers);
} else if (command == "peer_disconnected") {
for (int i = 0; i < peers.size(); ++i) {
Ref<LobbyPeer> leaving_peer = peers[i];
if (leaving_peer->get_id() == String(data_dict.get("peer_id", ""))) {
peers.remove_at(i);
lobby->set_players(peers.size());
emit_signal("peer_disconnected", leaving_peer);
break;
}
}
sort_peers_by_id(peers);
} else if (command == "lobby_data") {
String from_peer_id = data_dict.get("from_peer", "");
for (int i = 0; i < peers.size(); ++i) {
Expand Down
Loading

0 comments on commit 05b782b

Please sign in to comment.