Open hach-que opened 4 years ago
Ok, so it's just the lobby-based networking that's broken. The low level networking API seems to work with this example:
#include <chrono>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <thread>
#include "sdk/core.h"
#define panic_check(res, ctx) \
{ \
discord::Result res_ = res; \
if (res_ != discord::Result::Ok) \
{ \
std::cout << "result check failed (" << (int)res_ << "): " << ctx << " on line " << __LINE__ << "!\n"; \
exit(1); \
} \
}
class LobbyManager
{
private:
discord::Core *Core;
std::string CurrentRoute;
discord::NetworkPeerId SelfNetworkPeerId;
discord::UserId SelfUserId;
std::map<discord::UserId, discord::NetworkPeerId> CurrentPeers;
std::set<discord::LobbyId> CurrentLobbies;
public:
LobbyManager(discord::Core *InCore, discord::NetworkPeerId InSelfNetworkPeerId)
{
this->Core = InCore;
this->SelfNetworkPeerId = InSelfNetworkPeerId;
this->SelfUserId = 0;
}
void SendMessage(std::int64_t UserId, uint8_t *Data, uint32_t DataLen)
{
if (this->CurrentPeers.find(UserId) == this->CurrentPeers.end())
{
std::cout << "can't sent to " << UserId << ", no peer ID\n";
return;
}
auto PeerId = this->CurrentPeers[UserId];
if (PeerId == this->SelfNetworkPeerId)
{
return;
}
panic_check(this->Core->NetworkManager().SendMessage(PeerId, 0, Data, DataLen), "SendMessage");
}
void MemberConnectOrUpdate(std::int64_t LobbyId, std::int64_t UserId)
{
char PeerId[4096];
char Route[4096];
auto Data1 = this->Core->LobbyManager().GetMemberMetadataValue(LobbyId, UserId, "$net.peer_id", PeerId);
auto Data2 = this->Core->LobbyManager().GetMemberMetadataValue(LobbyId, UserId, "$net.route", Route);
if (Data1 != discord::Result::Ok || Data2 != discord::Result::Ok)
{
std::cout << "member metadata not available for OpenPeer\n";
return;
}
std::cout << "user ID " << UserId << " = " << PeerId << "\n";
uint64_t PeerIdVal;
std::istringstream PeerIdConverter(PeerId);
PeerIdConverter >> PeerIdVal;
if (this->CurrentPeers.find(UserId) == this->CurrentPeers.end())
{
// not open
std::cout << "calling OpenPeer with peer ID " << PeerIdVal << " and route " << Route << "\n";
panic_check(this->Core->NetworkManager().OpenPeer(PeerIdVal, Route), "OpenPeer");
this->Core->NetworkManager().OpenChannel(PeerIdVal, 0, true);
this->CurrentPeers[UserId] = PeerIdVal;
}
else
{
// already open, update route
std::cout << "calling UpdatePeer with peer ID " << PeerIdVal << " and route " << Route << "\n";
panic_check(this->Core->NetworkManager().UpdatePeer(PeerIdVal, Route), "UpdatePeer");
}
}
void MemberDisconnect(std::int64_t LobbyId, std::int64_t UserId)
{
auto PeerId = this->CurrentPeers.find(UserId);
if (PeerId != this->CurrentPeers.end())
{
std::cout << "calling ClosePeer with peer ID " << PeerId->second << "\n";
panic_check(this->Core->NetworkManager().ClosePeer(PeerId->second), "ClosePeer");
}
}
void AddLobby(std::int64_t LobbyId)
{
this->CurrentLobbies.insert(LobbyId);
int32_t MemberCount;
panic_check(this->Core->LobbyManager().MemberCount(LobbyId, &MemberCount), "MemberCount");
for (auto i = 0; i < MemberCount; i++)
{
discord::UserId MemberUserId;
panic_check(this->Core->LobbyManager().GetMemberUserId(LobbyId, i, &MemberUserId), "GetMemberUserId");
this->MemberConnectOrUpdate(LobbyId, MemberUserId);
}
if (this->CurrentRoute != "" && this->SelfUserId != 0)
{
discord::LobbyMemberTransaction Txn;
this->Core->LobbyManager().GetMemberUpdateTransaction(LobbyId, this->SelfUserId, &Txn);
std::ostringstream o;
o << this->SelfNetworkPeerId;
Txn.SetMetadata("$net.peer_id", o.str().c_str());
Txn.SetMetadata("$net.route", this->CurrentRoute.c_str());
this->Core->LobbyManager().UpdateMember(LobbyId, this->SelfUserId, Txn, [](discord::Result result) {
panic_check(result, "SetPeerInformation");
});
}
}
void RemoveLobby(std::int64_t LobbyId)
{
this->CurrentLobbies.erase(LobbyId);
}
void SetUserId(discord::UserId InUserId)
{
auto NeedsRoutePush = this->SelfUserId == 0;
this->SelfUserId = InUserId;
// this->CurrentPeers[InUserId] = this->SelfNetworkPeerId;
if (this->CurrentRoute != "")
{
for (auto L : this->CurrentLobbies)
{
discord::LobbyMemberTransaction Txn;
this->Core->LobbyManager().GetMemberUpdateTransaction(L, this->SelfUserId, &Txn);
std::ostringstream o;
o << this->SelfNetworkPeerId;
Txn.SetMetadata("$net.peer_id", o.str().c_str());
Txn.SetMetadata("$net.route", this->CurrentRoute.c_str());
this->Core->LobbyManager().UpdateMember(L, this->SelfUserId, Txn, [](discord::Result result) {
panic_check(result, "SetPeerInformation");
});
}
}
}
void HandleRouteUpdate(const char *Route)
{
this->CurrentRoute = Route;
if (this->SelfUserId != 0)
{
for (auto L : this->CurrentLobbies)
{
discord::LobbyMemberTransaction Txn;
this->Core->LobbyManager().GetMemberUpdateTransaction(L, this->SelfUserId, &Txn);
std::ostringstream o;
o << this->SelfNetworkPeerId;
Txn.SetMetadata("$net.peer_id", o.str().c_str());
Txn.SetMetadata("$net.route", this->CurrentRoute.c_str());
this->Core->LobbyManager().UpdateMember(L, this->SelfUserId, Txn, [](discord::Result result) {
panic_check(result, "SetPeerInformation");
});
}
}
}
};
void main()
{
using namespace std::chrono_literals;
std::cout << "Starting Discord networking source...\n";
discord::Core *core;
auto result = discord::Core::Create(426958487654891521, DiscordCreateFlags_Default, &core);
if (result != discord::Result::Ok)
{
std::cout << "Failed to init Discord.\n";
return;
}
discord::NetworkPeerId SelfNetworkPeerId;
core->NetworkManager().GetPeerId(&SelfNetworkPeerId);
LobbyManager *LM = new LobbyManager(core, SelfNetworkPeerId);
core->UserManager().OnCurrentUserUpdate.Connect([=]() {
std::cout << "OnCurrentUserUpdate\n";
discord::User CurrentUser;
panic_check(core->UserManager().GetCurrentUser(&CurrentUser), "GetCurrentUser");
LM->SetUserId(CurrentUser.GetId());
});
core->NetworkManager().OnRouteUpdate.Connect([=](char const *Route) {
LM->HandleRouteUpdate(Route);
});
core->LobbyManager().OnMemberConnect.Connect([=](std::int64_t LobbyId, std::int64_t UserId) {
LM->MemberConnectOrUpdate(LobbyId, UserId);
});
core->LobbyManager().OnMemberUpdate.Connect([=](std::int64_t LobbyId, std::int64_t UserId) {
LM->MemberConnectOrUpdate(LobbyId, UserId);
});
core->LobbyManager().OnMemberDisconnect.Connect([=](std::int64_t LobbyId, std::int64_t UserId) {
LM->MemberDisconnect(LobbyId, UserId);
});
core->NetworkManager().OnMessage.Connect([](discord::NetworkPeerId PeerId,
discord::NetworkChannelId ChannelId,
std::uint8_t *Data,
std::uint32_t DataLen) {
std::cout << "peer " << PeerId << ", channel " << ChannelId << ", data len: " << DataLen << "\n";
});
bool shouldsendmessages = false;
int64_t messagelobby = 0;
auto followup = [=, &shouldsendmessages, &messagelobby](int64_t LobbyId) {
std::cout << "connected to lobby " << LobbyId << "\n";
LM->AddLobby(LobbyId);
shouldsendmessages = true;
messagelobby = LobbyId;
};
discord::LobbySearchQuery Q;
panic_check(core->LobbyManager().GetSearchQuery(&Q), "GetSearchQuery");
Q.Limit(1);
core->LobbyManager().Search(Q, [=](discord::Result result) {
panic_check(result, "SearchResult");
int32_t LobbyCount;
core->LobbyManager().LobbyCount(&LobbyCount);
if (LobbyCount == 0)
{
// no lobby, create one
discord::LobbyTransaction CreateTxn;
panic_check(core->LobbyManager().GetLobbyCreateTransaction(&CreateTxn), "GetLobbyCreateTransaction");
CreateTxn.SetLocked(false);
CreateTxn.SetType(discord::LobbyType::Public);
core->LobbyManager().CreateLobby(CreateTxn, [=](discord::Result result, const discord::Lobby &lobby) {
panic_check(result, "CreateLobby");
followup(lobby.GetId());
});
}
else
{
// existing lobby, connect to it
discord::LobbyId ConnectLobbyId;
discord::Lobby ConnectLobby;
panic_check(core->LobbyManager().GetLobbyId(0, &ConnectLobbyId), "GetLobbyId");
panic_check(core->LobbyManager().GetLobby(ConnectLobbyId, &ConnectLobby), "GetLobby");
core->LobbyManager().ConnectLobby(
ConnectLobbyId,
ConnectLobby.GetSecret(),
[=](discord::Result result, const discord::Lobby &lobby) {
panic_check(result, "ConnectLobbyResult");
followup(lobby.GetId());
});
}
});
// main loop
int m = 0;
while (true)
{
// run callbacks
core->RunCallbacks();
// send a message every second, to every other user
if (shouldsendmessages && m % 10 == 0)
{
int32_t membercount;
core->LobbyManager().MemberCount(messagelobby, &membercount);
for (int i = 0; i < membercount; i++)
{
int64_t memberid;
core->LobbyManager().GetMemberUserId(messagelobby, i, &memberid);
std::cout << "sent to lobby " << messagelobby << " user " << memberid << "\n";
LM->SendMessage(memberid, (uint8_t *)"hello", 5);
}
}
// flush network messages
core->NetworkManager().Flush();
m++;
std::this_thread::sleep_for(100ms);
}
}
core->NetworkManager().Flush(); Shouldn't that be
core->LobbyManager().FlushNetwork()
?
Describe the bug For some reason, the Discord Game SDK refuses to send or receive packets when using the lobby-based networking ("Networking The Easy Way").
Steps to reproduce Here is a C++ file that reproduces the issue. Build and link this against the Discord Game SDK, and run it on two different machines with two different accounts.
When you run this, you'll see something similar to this (note that the output that should come from
OnNetworkMessage
won't appear):Expected behavior The
OnNetworkMessage
callback should fire.Screenshots![image](https://user-images.githubusercontent.com/504826/80122242-9eac3880-85d0-11ea-825a-52f9c6ea83c3.png)
Implementation specifics
Additional context This is currently blocking a networking integration in Unreal Engine 4.