mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Improve the "UDP port 20595" connection error dialog
Add a unique disconnect reason for timeouts of connection attempts. Rewrite the displayed error message and provide a link directly to the FAQ entry. (The old message was very misleading and only brought players on the wrong track during troubleshooting)
This commit is contained in:
parent
40762c257d
commit
78900842b1
5 changed files with 72 additions and 36 deletions
|
|
@ -58,35 +58,43 @@ function getValidPort(port)
|
|||
/**
|
||||
* Must be kept in sync with source/network/NetHost.h
|
||||
*/
|
||||
function getDisconnectReason(id, wasConnected)
|
||||
function getDisconnectReason(id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0: return wasConnected ? "" :
|
||||
translate("This is often caused by UDP port 20595 not being forwarded on the host side, by a firewall, or anti-virus software.");
|
||||
case 1: return translate("The host has ended the game.");
|
||||
case 2: return translate("Incorrect network protocol version.");
|
||||
case 3: return translate("Game is loading, please try again later.");
|
||||
case 4: return translate("Game has already started, no observers allowed.");
|
||||
case 5: return translate("You have been kicked.");
|
||||
case 6: return translate("You have been banned.");
|
||||
case 7: return translate("Player name in use. If you were disconnected, retry in few seconds.");
|
||||
case 8: return translate("Server full.");
|
||||
case 9: return translate("Secure lobby authentication failed. Join via lobby.");
|
||||
case 10: return translate("Error: Server failed to allocate a unique client identifier.");
|
||||
case 11: return translate("Error: Client commands were ready for an unexpected game turn.");
|
||||
case 12: return translate("Error: Client simulated an unexpected game turn.");
|
||||
case 13: return translate("Password is invalid.");
|
||||
case 14: return translate("Could not find an unused port for the enet STUN client.");
|
||||
case 15: return translate("Could not find the STUN endpoint.");
|
||||
case 16: return translate("Different game engine versions or different mods loaded.");
|
||||
case 0: return translate("An unknown error ocurred.");
|
||||
case 1: return translate("The connection request has timed out.");
|
||||
case 2: return translate("The host has ended the game.");
|
||||
case 3: return translate("Incorrect network protocol version.");
|
||||
case 4: return translate("Game is loading, please try again later.");
|
||||
case 5: return translate("Game has already started, no observers allowed.");
|
||||
case 6: return translate("You have been kicked.");
|
||||
case 7: return translate("You have been banned.");
|
||||
case 8: return translate("Player name in use. If you were disconnected, retry in few seconds.");
|
||||
case 9: return translate("Server full.");
|
||||
case 10: return translate("Secure lobby authentication failed. Join via lobby.");
|
||||
case 11: return translate("Error: Server failed to allocate a unique client identifier.");
|
||||
case 12: return translate("Error: Client commands were ready for an unexpected game turn.");
|
||||
case 13: return translate("Error: Client simulated an unexpected game turn.");
|
||||
case 14: return translate("Password is invalid.");
|
||||
case 15: return translate("Could not find an unused port for the enet STUN client.");
|
||||
case 16: return translate("Could not find the STUN endpoint.");
|
||||
case 17: return translate("Different game engine versions or different mods loaded.");
|
||||
|
||||
default:
|
||||
warn("Unknown disconnect-reason ID received: " + id);
|
||||
return sprintf(translate("\\[Invalid value %(id)s]"), { "id": id });
|
||||
}
|
||||
}
|
||||
|
||||
function getHandshakeDisconnectMessage(mismatchType, clientMismatchInfo, serverMismatchInfo)
|
||||
function getRequestTimeOutMessage()
|
||||
{
|
||||
return (Engine.HasXmppClient() ? "" : translate("Please ensure that you entered the correct server name or IP address, and port number.\n\n")) +
|
||||
translate("If you haven't yet, try to connect again and to different hosts." +
|
||||
"\nIf the issue persists or occurs regularly, visit the official FAQ for detailed guidance and troubleshooting steps.");
|
||||
}
|
||||
|
||||
function getMismatchMessage(mismatchType, clientMismatchInfo, serverMismatchInfo)
|
||||
{
|
||||
switch (mismatchType)
|
||||
{
|
||||
|
|
@ -107,26 +115,46 @@ function getHandshakeDisconnectMessage(mismatchType, clientMismatchInfo, serverM
|
|||
/**
|
||||
* Show the disconnect reason in a message box.
|
||||
*
|
||||
* @param {number} reason
|
||||
* @param {Object} message
|
||||
* @param {boolean} wasConnected
|
||||
*/
|
||||
function reportDisconnect(reason, wasConnected)
|
||||
function reportDisconnect(message, wasConnected)
|
||||
{
|
||||
messageBox(
|
||||
400, 200,
|
||||
(wasConnected ?
|
||||
translate("Lost connection to the server.") :
|
||||
translate("Failed to connect to the server.")
|
||||
) + "\n\n" + getDisconnectReason(reason, wasConnected),
|
||||
translate("Disconnected")
|
||||
);
|
||||
if (message.reason === 0)
|
||||
reportConnectionRequestTimeOut();
|
||||
else if (message.reason == 16)
|
||||
reportMismatchingSoftwareVersions(message.mismatch_type, message.client_mismatch, message.server_mismatch);
|
||||
else
|
||||
messageBox(
|
||||
400, 200,
|
||||
(wasConnected ?
|
||||
translate("Lost connection to the server.") :
|
||||
translate("Failed to connect to the server.")
|
||||
) + "\n\n" + getDisconnectReason(message.reason),
|
||||
translate("Disconnected")
|
||||
);
|
||||
}
|
||||
|
||||
function reportHandshakeDisconnect(mismatchType, clientMismatch, serverMismatch)
|
||||
async function reportConnectionRequestTimeOut()
|
||||
{
|
||||
const buttonIndex = await messageBox(
|
||||
600, 230,
|
||||
translate("Failed to connect to the server.") + " " + getDisconnectReason(1) + "\n\n" + getRequestTimeOutMessage(),
|
||||
translate("Connection Error"),
|
||||
[translate("Close"), translate("Open FAQ")]
|
||||
);
|
||||
if (buttonIndex === 1)
|
||||
openURL("https://gitea.wildfiregames.com/0ad/0ad/wiki/FAQ#what-shall-i-do-when-joining-multiplayer-matches-fails-with-an-error-message");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function reportMismatchingSoftwareVersions(mismatchType, clientMismatch, serverMismatch)
|
||||
{
|
||||
messageBox(
|
||||
400, 200,
|
||||
translate("Failed to connect to the server.")
|
||||
+ "\n\n" + getHandshakeDisconnectMessage(mismatchType, clientMismatch, serverMismatch),
|
||||
+ "\n\n" + getMismatchMessage(mismatchType, clientMismatch, serverMismatch),
|
||||
translate("Disconnected")
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -317,8 +317,8 @@ function pollAndHandleNetworkClient(loadSavedGame)
|
|||
if (message.reason === 16)
|
||||
reportHandshakeDisconnect(message.mismatch_type, message.client_mismatch_component, message.server_mismatch_component);
|
||||
else
|
||||
reportDisconnect(message.reason, false);
|
||||
return true;
|
||||
reportDisconnect(message, false);
|
||||
return;
|
||||
|
||||
default:
|
||||
error("Unrecognised netstatus type: " + message.status);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ typedef std::map<CStr, PlayerAssignment> PlayerAssignmentMap; // map from GUID -
|
|||
enum NetDisconnectReason
|
||||
{
|
||||
NDR_UNKNOWN = 0,
|
||||
NDR_CONNECTION_REQUEST_TIMED_OUT,
|
||||
NDR_SERVER_SHUTDOWN,
|
||||
NDR_INCORRECT_PROTOCOL_VERSION,
|
||||
NDR_SERVER_LOADING,
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ void CNetClientSession::Poll()
|
|||
enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname));
|
||||
LOGMESSAGE("Net client: Connected to %s:%u", hostname, (unsigned int)event.peer->address.port);
|
||||
m_Connected = true;
|
||||
m_WasConnected = true;
|
||||
|
||||
m_IncomingMessages.push(event);
|
||||
}
|
||||
|
|
@ -178,7 +179,10 @@ void CNetClientSession::ProcessPolledMessages()
|
|||
else if (event.type == ENET_EVENT_TYPE_DISCONNECT)
|
||||
{
|
||||
// This deletes the session, so we must break;
|
||||
m_Client.HandleDisconnect(event.data);
|
||||
if (event.data == 0 && !m_WasConnected)
|
||||
m_Client.HandleDisconnect(NDR_CONNECTION_REQUEST_TIMED_OUT);
|
||||
else
|
||||
m_Client.HandleDisconnect(event.data);
|
||||
break;
|
||||
}
|
||||
else if (event.type == ENET_EVENT_TYPE_RECEIVE)
|
||||
|
|
|
|||
|
|
@ -126,9 +126,12 @@ private:
|
|||
// Net messages to send on the next flush() call.
|
||||
boost::lockfree::queue<ENetPacket*> m_OutgoingMessages;
|
||||
|
||||
// Last know state. If false, flushing errors are silenced.
|
||||
// Last known state. If false, flushing errors are silenced.
|
||||
bool m_Connected = false;
|
||||
|
||||
// Whether this session was ever connected to the server.
|
||||
bool m_WasConnected = false;
|
||||
|
||||
// Wrapper around enet stats - those are atomic as the code is lock-free.
|
||||
std::atomic<u32> m_LastReceivedTime;
|
||||
std::atomic<u32> m_MeanRTT;
|
||||
|
|
|
|||
Loading…
Reference in a new issue