diff --git a/Source/dvlnet/base_protocol.h b/Source/dvlnet/base_protocol.h
index 6e4f205c8..f441cd386 100644
--- a/Source/dvlnet/base_protocol.h
+++ b/Source/dvlnet/base_protocol.h
@@ -126,9 +126,9 @@ bool base_protocol
::wait_firstpeer()
template
bool base_protocol::send_info_request()
{
- tl::expected status = proto.network_online();
+ tl::expected status = proto.peers_ready();
if (!status.has_value()) {
- LogError("network_online: {}", status.error().what());
+ LogError("peers_ready: {}", status.error().what());
return false;
}
if (!*status)
diff --git a/Source/dvlnet/protocol_zt.cpp b/Source/dvlnet/protocol_zt.cpp
index b70974503..66f093687 100644
--- a/Source/dvlnet/protocol_zt.cpp
+++ b/Source/dvlnet/protocol_zt.cpp
@@ -90,6 +90,12 @@ tl::expected protocol_zt::network_online()
return true;
}
+tl::expected protocol_zt::peers_ready()
+{
+ return network_online()
+ .map([&](bool isOnline) { return isOnline && zerotier_peers_ready(); });
+}
+
tl::expected protocol_zt::send(const endpoint &peer, const buffer_t &data)
{
tl::expected frame = frame_queue::MakeFrame(data);
diff --git a/Source/dvlnet/protocol_zt.h b/Source/dvlnet/protocol_zt.h
index d6830f567..dbe7d0275 100644
--- a/Source/dvlnet/protocol_zt.h
+++ b/Source/dvlnet/protocol_zt.h
@@ -82,6 +82,7 @@ public:
bool recv(endpoint &peer, buffer_t &data);
bool get_disconnected(endpoint &peer);
tl::expected network_online();
+ tl::expected peers_ready();
bool is_peer_connected(endpoint &peer);
bool is_peer_relayed(const endpoint &peer) const;
static std::string make_default_gamename();
diff --git a/Source/dvlnet/zerotier_native.cpp b/Source/dvlnet/zerotier_native.cpp
index aead501bd..48c7fce36 100644
--- a/Source/dvlnet/zerotier_native.cpp
+++ b/Source/dvlnet/zerotier_native.cpp
@@ -46,6 +46,7 @@ constexpr uint64_t ZtNetwork = 0xa84ac5c10a7ebb5f;
std::atomic_bool zt_network_ready(false);
std::atomic_bool zt_node_online(false);
std::atomic_bool zt_joined(false);
+std::atomic_uint zt_peers_ready(0);
ankerl::unordered_dense::map ztPeerEvents;
@@ -142,6 +143,7 @@ void Callback(void *ptr)
Log("ZeroTier: ZTS_EVENT_NETWORK_READY_IP6, networkId={:x}", (unsigned long long)msg->network->net_id);
zt_ip6setup();
zt_network_ready = true;
+ zt_peers_ready = SDL_GetTicks();
break;
case ZTS_EVENT_ADDR_ADDED_IP6:
@@ -151,6 +153,8 @@ void Callback(void *ptr)
case ZTS_EVENT_PEER_DIRECT:
case ZTS_EVENT_PEER_RELAY:
ztPeerEvents[msg->peer->peer_id] = static_cast(msg->event_code);
+ if (!zerotier_peers_ready())
+ zt_peers_ready = SDL_GetTicks();
break;
case ZTS_EVENT_PEER_PATH_DEAD:
@@ -166,6 +170,11 @@ bool zerotier_network_ready()
return zt_network_ready && zt_node_online;
}
+bool zerotier_peers_ready()
+{
+ return SDL_GetTicks() - zt_peers_ready >= 5000;
+}
+
void zerotier_network_start()
{
std::string configPath = paths::ConfigPath();
diff --git a/Source/dvlnet/zerotier_native.h b/Source/dvlnet/zerotier_native.h
index 48149e16d..06a2fee30 100644
--- a/Source/dvlnet/zerotier_native.h
+++ b/Source/dvlnet/zerotier_native.h
@@ -6,6 +6,7 @@ namespace devilution {
namespace net {
bool zerotier_network_ready();
+bool zerotier_peers_ready();
void zerotier_network_start();
bool zerotier_is_relayed(uint64_t mac);