Implement network-warnings, fixes #3264.
Shows a notification if the local client or other players connections timeout or have bad latency. This was SVN commit r17730.
This commit is contained in:
parent
4d41bd9622
commit
22f5b00fce
@ -352,6 +352,7 @@ enabledmods = "mod public"
|
|||||||
[overlay]
|
[overlay]
|
||||||
fps = "false" ; Show frames per second in top right corner
|
fps = "false" ; Show frames per second in top right corner
|
||||||
realtime = "false" ; Show current system time in top right corner
|
realtime = "false" ; Show current system time in top right corner
|
||||||
|
netwarnings = "true" ; Show warnings if the network connection is bad
|
||||||
|
|
||||||
[profiler2]
|
[profiler2]
|
||||||
autoenable = false ; Enable HTTP server output at startup (default off for security/performance)
|
autoenable = false ; Enable HTTP server output at startup (default off for security/performance)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/*
|
/**
|
||||||
DESCRIPTION : Contains global GUI functions, which will later be accessible from every GUI script/file.
|
* Contains global GUI functions accessible from every GUI script/file.
|
||||||
NOTES : So far, only the message box-related functions are implemented.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
// *******************************************
|
// *******************************************
|
||||||
// messageBox
|
// messageBox
|
||||||
@ -139,4 +138,42 @@ function updateCounters()
|
|||||||
var dataCounter = Engine.GetGUIObjectByName("dataCounter");
|
var dataCounter = Engine.GetGUIObjectByName("dataCounter");
|
||||||
dataCounter.caption = caption;
|
dataCounter.caption = caption;
|
||||||
dataCounter.size = sprintf("100%%-100 40 100%%-5 %(bottom)s", { bottom: 40 + 14 * linesCount });
|
dataCounter.size = sprintf("100%%-100 40 100%%-5 %(bottom)s", { bottom: 40 + 14 * linesCount });
|
||||||
|
dataCounter.hidden = linesCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the overlay with the most recent network warning of each client.
|
||||||
|
*/
|
||||||
|
function displayGamestateNotifications()
|
||||||
|
{
|
||||||
|
let messages = [];
|
||||||
|
let maxTextWidth = 0;
|
||||||
|
|
||||||
|
// TODO: Players who paused the game should be added here
|
||||||
|
|
||||||
|
// Add network warnings
|
||||||
|
if (Engine.ConfigDB_GetValue("user", "overlay.netwarnings") == "true")
|
||||||
|
{
|
||||||
|
let netwarnings = getNetworkWarnings();
|
||||||
|
messages = messages.concat(netwarnings.messages);
|
||||||
|
maxTextWidth = Math.max(maxTextWidth, netwarnings.maxTextWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize textbox
|
||||||
|
let width = maxTextWidth + 20;
|
||||||
|
let height = 14 * messages.length;
|
||||||
|
|
||||||
|
// Position left of the dataCounter
|
||||||
|
let top = "40";
|
||||||
|
let right = Engine.GetGUIObjectByName("dataCounter").hidden ? "100%-15" : "100%-110";
|
||||||
|
|
||||||
|
let bottom = top + "+" + height;
|
||||||
|
let left = right + "-" + width;
|
||||||
|
|
||||||
|
let gameStateNotifications = Engine.GetGUIObjectByName("gameStateNotifications");
|
||||||
|
gameStateNotifications.caption = messages.join("\n");
|
||||||
|
gameStateNotifications.hidden = !messages.length;
|
||||||
|
gameStateNotifications.size = left + " " + top + " " + right + " " + bottom;
|
||||||
|
|
||||||
|
setTimeout(displayGamestateNotifications, 1000);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,24 @@
|
|||||||
|
|
||||||
<object>
|
<object>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
==========================================
|
||||||
|
- GAMESTATE NOTIFICATIONS
|
||||||
|
==========================================
|
||||||
|
-->
|
||||||
|
<object name="gameStateNotifications"
|
||||||
|
type="text"
|
||||||
|
ghost="true"
|
||||||
|
z="199"
|
||||||
|
size="100%-110 40 100%-110 40"
|
||||||
|
font="mono-stroke-10"
|
||||||
|
textcolor="255 219 77"
|
||||||
|
text_align="center"
|
||||||
|
text_valign="top"
|
||||||
|
sprite="color: 0 0 0 100"
|
||||||
|
>
|
||||||
|
</object>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
==========================================
|
==========================================
|
||||||
- FPS & REAL TIME & GAME TIME COUNTER
|
- FPS & REAL TIME & GAME TIME COUNTER
|
||||||
|
@ -1,3 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Number of milliseconds to display network warnings.
|
||||||
|
*/
|
||||||
|
const g_NetworkWarningTimeout = 3000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently displayed network warnings. At most one message per user.
|
||||||
|
*/
|
||||||
|
var g_NetworkWarnings = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message-types to be displayed.
|
||||||
|
*/
|
||||||
|
var g_NetworkWarningTexts = {
|
||||||
|
|
||||||
|
"server-timeout": (msg, username) =>
|
||||||
|
sprintf(translate("Losing connection to server (%(seconds)s)"), {
|
||||||
|
"seconds": Math.ceil(msg.lastReceivedTime / 1000)
|
||||||
|
}),
|
||||||
|
|
||||||
|
"client-timeout": (msg, username) =>
|
||||||
|
sprintf(translate("%(player)s losing connection (%(seconds)s)"), {
|
||||||
|
"player": username,
|
||||||
|
"seconds": Math.ceil(msg.lastReceivedTime / 1000)
|
||||||
|
}),
|
||||||
|
|
||||||
|
"server-latency": (msg, username) =>
|
||||||
|
sprintf(translate("Bad connection to server (%(milliseconds)sms)"), {
|
||||||
|
"milliseconds": msg.meanRTT
|
||||||
|
}),
|
||||||
|
|
||||||
|
"client-latency": (msg, username) =>
|
||||||
|
sprintf(translate("Bad connection to %(player)s (%(milliseconds)sms)"), {
|
||||||
|
"player": username,
|
||||||
|
"milliseconds": msg.meanRTT
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
var g_NetworkCommands = {
|
var g_NetworkCommands = {
|
||||||
"/kick": argument => kickPlayer(argument, false),
|
"/kick": argument => kickPlayer(argument, false),
|
||||||
"/ban": argument => kickPlayer(argument, true),
|
"/ban": argument => kickPlayer(argument, true),
|
||||||
@ -94,3 +132,69 @@ function executeNetworkCommand(input)
|
|||||||
|
|
||||||
return !!g_NetworkCommands[command];
|
return !!g_NetworkCommands[command];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remember this warning for a few seconds.
|
||||||
|
* Overwrite previous warnings for this user.
|
||||||
|
*
|
||||||
|
* @param msg - GUI message sent by NetServer or NetClient
|
||||||
|
*/
|
||||||
|
function addNetworkWarning(msg)
|
||||||
|
{
|
||||||
|
if (!g_NetworkWarningTexts[msg.warntype])
|
||||||
|
{
|
||||||
|
warn("Unknown network warning type received: " + uneval(msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Engine.ConfigDB_GetValue("user", "overlay.netwarnings") != "true")
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_NetworkWarnings[msg.guid || "server"] = {
|
||||||
|
"added": Date.now(),
|
||||||
|
"msg": msg
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Colorizes and concatenates all network warnings.
|
||||||
|
* Returns text and textWidth.
|
||||||
|
*/
|
||||||
|
function getNetworkWarnings()
|
||||||
|
{
|
||||||
|
// Remove outdated messages
|
||||||
|
for (let guid in g_NetworkWarnings)
|
||||||
|
{
|
||||||
|
if (Date.now() > g_NetworkWarnings[guid].added + g_NetworkWarningTimeout)
|
||||||
|
delete g_NetworkWarnings[guid];
|
||||||
|
|
||||||
|
if (guid != "server" && !g_PlayerAssignments[guid])
|
||||||
|
delete g_NetworkWarnings[guid];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show local messages first
|
||||||
|
let guids = Object.keys(g_NetworkWarnings).sort(guid => guid != "server");
|
||||||
|
|
||||||
|
let font = Engine.GetGUIObjectByName("gameStateNotifications").font;
|
||||||
|
|
||||||
|
let messages = [];
|
||||||
|
let maxTextWidth = 0;
|
||||||
|
|
||||||
|
for (let guid of guids)
|
||||||
|
{
|
||||||
|
let msg = g_NetworkWarnings[guid].msg;
|
||||||
|
|
||||||
|
// Add formatted text
|
||||||
|
messages.push(g_NetworkWarningTexts[msg.warntype](msg, colorizePlayernameByGUID(guid)));
|
||||||
|
|
||||||
|
// Add width of unformatted text
|
||||||
|
let username = guid != "server" && g_PlayerAssignments[guid].name;
|
||||||
|
let textWidth = Engine.GetTextWidth(font, g_NetworkWarningTexts[msg.warntype](msg, username));
|
||||||
|
maxTextWidth = Math.max(textWidth, maxTextWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"messages": messages,
|
||||||
|
"maxTextWidth": maxTextWidth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -28,6 +28,7 @@ const g_MapPath = {
|
|||||||
*/
|
*/
|
||||||
const g_NetMessageTypes = {
|
const g_NetMessageTypes = {
|
||||||
"netstatus": msg => handleNetStatusMessage(msg),
|
"netstatus": msg => handleNetStatusMessage(msg),
|
||||||
|
"netwarn": msg => addNetworkWarning(msg),
|
||||||
"gamesetup": msg => handleGamesetupMessage(msg),
|
"gamesetup": msg => handleGamesetupMessage(msg),
|
||||||
"players": msg => handlePlayerAssignmentMessage(msg),
|
"players": msg => handlePlayerAssignmentMessage(msg),
|
||||||
"ready": msg => handleReadyMessage(msg),
|
"ready": msg => handleReadyMessage(msg),
|
||||||
@ -211,6 +212,8 @@ function init(attribs)
|
|||||||
g_DefaultPlayerData.shift();
|
g_DefaultPlayerData.shift();
|
||||||
for (let i in g_DefaultPlayerData)
|
for (let i in g_DefaultPlayerData)
|
||||||
g_DefaultPlayerData[i].Civ = "random";
|
g_DefaultPlayerData[i].Civ = "random";
|
||||||
|
|
||||||
|
setTimeout(displayGamestateNotifications, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -946,6 +949,8 @@ function onTick()
|
|||||||
error("Unrecognised net message type " + message.type);
|
error("Unrecognised net message type " + message.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
<script file="gui/common/functions_utility.js"/>
|
<script file="gui/common/functions_utility.js"/>
|
||||||
<script file="gui/common/network.js"/>
|
<script file="gui/common/network.js"/>
|
||||||
<script file="gui/common/settings.js"/>
|
<script file="gui/common/settings.js"/>
|
||||||
|
<script file="gui/common/timer.js"/>
|
||||||
|
|
||||||
<!-- After settings.js, which defines g_Settings -->
|
<!-- After settings.js, which defines g_Settings -->
|
||||||
<script file="gui/gamesetup/gamesetup.js"/>
|
<script file="gui/gamesetup/gamesetup.js"/>
|
||||||
|
@ -126,7 +126,9 @@ function pollAndHandleNetworkClient()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "chat":
|
case "chat":
|
||||||
// Ignore, since we have nowhere to display chat messages
|
break;
|
||||||
|
|
||||||
|
case "netwarn":
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -169,6 +171,10 @@ function pollAndHandleNetworkClient()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "netwarn":
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error(sprintf("Unrecognised net message type %(messageType)s", { messageType: message.type }));
|
error(sprintf("Unrecognised net message type %(messageType)s", { messageType: message.type }));
|
||||||
break;
|
break;
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
"tooltip": "Show detailed tooltips for trainable units in unit-producing buildings.",
|
"tooltip": "Show detailed tooltips for trainable units in unit-producing buildings.",
|
||||||
"parameters": { "config": "showdetailedtooltips" }
|
"parameters": { "config": "showdetailedtooltips" }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Network Warnings",
|
||||||
|
"tooltip": "Show which player has a bad connection in multiplayer games.",
|
||||||
|
"parameters": { "config": "overlay.netwarnings" }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"label": "FPS Overlay",
|
"label": "FPS Overlay",
|
||||||
|
@ -29,6 +29,7 @@ var g_ChatTimers = [];
|
|||||||
*/
|
*/
|
||||||
var g_NetMessageTypes = {
|
var g_NetMessageTypes = {
|
||||||
"netstatus": msg => handleNetStatusMessage(msg),
|
"netstatus": msg => handleNetStatusMessage(msg),
|
||||||
|
"netwarn": msg => addNetworkWarning(msg),
|
||||||
"players": msg => handlePlayerAssignmentsMessage(msg),
|
"players": msg => handlePlayerAssignmentsMessage(msg),
|
||||||
"rejoined": msg => addChatMessage({ "type": "rejoined", "guid": msg.guid }),
|
"rejoined": msg => addChatMessage({ "type": "rejoined", "guid": msg.guid }),
|
||||||
"kicked": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been kicked"), { "username": msg.username }) }),
|
"kicked": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been kicked"), { "username": msg.username }) }),
|
||||||
|
@ -269,6 +269,8 @@ function init(initData, hotloadData)
|
|||||||
|
|
||||||
onSimulationUpdate();
|
onSimulationUpdate();
|
||||||
|
|
||||||
|
setTimeout(displayGamestateNotifications, 1000);
|
||||||
|
|
||||||
// Report the performance after 5 seconds (when we're still near
|
// Report the performance after 5 seconds (when we're still near
|
||||||
// the initial camera view) and a minute (when the profiler will
|
// the initial camera view) and a minute (when the profiler will
|
||||||
// have settled down if framerates as very low), to give some
|
// have settled down if framerates as very low), to give some
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "scriptinterface/ScriptInterface.h"
|
#include "scriptinterface/ScriptInterface.h"
|
||||||
|
|
||||||
#include "graphics/Camera.h"
|
#include "graphics/Camera.h"
|
||||||
|
#include "graphics/FontMetrics.h"
|
||||||
#include "graphics/GameView.h"
|
#include "graphics/GameView.h"
|
||||||
#include "graphics/MapReader.h"
|
#include "graphics/MapReader.h"
|
||||||
#include "graphics/scripting/JSInterface_GameView.h"
|
#include "graphics/scripting/JSInterface_GameView.h"
|
||||||
@ -875,6 +876,16 @@ CParamNode GetTemplate(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std
|
|||||||
return g_GUI->GetTemplate(templateName);
|
return g_GUI->GetTemplate(templateName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetTextWidth(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const CStr& fontName, const CStrW& text)
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
CStrIntern _fontName(fontName);
|
||||||
|
CFontMetrics fontMetrics(_fontName);
|
||||||
|
fontMetrics.CalculateStringSize(text.c_str(), width, height);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Timer
|
// Timer
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1049,6 +1060,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
|
|||||||
scriptInterface.RegisterFunction<void, std::wstring, JS::HandleValue, &WriteJSONFile>("WriteJSONFile");
|
scriptInterface.RegisterFunction<void, std::wstring, JS::HandleValue, &WriteJSONFile>("WriteJSONFile");
|
||||||
scriptInterface.RegisterFunction<bool, std::string, &TemplateExists>("TemplateExists");
|
scriptInterface.RegisterFunction<bool, std::string, &TemplateExists>("TemplateExists");
|
||||||
scriptInterface.RegisterFunction<CParamNode, std::string, &GetTemplate>("GetTemplate");
|
scriptInterface.RegisterFunction<CParamNode, std::string, &GetTemplate>("GetTemplate");
|
||||||
|
scriptInterface.RegisterFunction<int, CStr, CStrW, &GetTextWidth>("GetTextWidth");
|
||||||
|
|
||||||
// User report functions
|
// User report functions
|
||||||
scriptInterface.RegisterFunction<bool, &IsUserReportEnabled>("IsUserReportEnabled");
|
scriptInterface.RegisterFunction<bool, &IsUserReportEnabled>("IsUserReportEnabled");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -70,7 +70,8 @@ CNetClient::CNetClient(CGame* game) :
|
|||||||
m_Session(NULL),
|
m_Session(NULL),
|
||||||
m_UserName(L"anonymous"),
|
m_UserName(L"anonymous"),
|
||||||
m_GUID(ps_generate_guid()), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game),
|
m_GUID(ps_generate_guid()), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game),
|
||||||
m_GameAttributes(game->GetSimulation2()->GetScriptInterface().GetContext())
|
m_GameAttributes(game->GetSimulation2()->GetScriptInterface().GetContext()),
|
||||||
|
m_LastConnectionCheck(0)
|
||||||
{
|
{
|
||||||
m_Game->SetTurnManager(NULL); // delete the old local turn manager so we don't accidentally use it
|
m_Game->SetTurnManager(NULL); // delete the old local turn manager so we don't accidentally use it
|
||||||
|
|
||||||
@ -94,12 +95,16 @@ CNetClient::CNetClient(CGame* game) :
|
|||||||
AddTransition(NCS_PREGAME, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context);
|
AddTransition(NCS_PREGAME, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context);
|
||||||
AddTransition(NCS_PREGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_PREGAME, (void*)&OnPlayerAssignment, context);
|
AddTransition(NCS_PREGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_PREGAME, (void*)&OnPlayerAssignment, context);
|
||||||
AddTransition(NCS_PREGAME, (uint)NMT_KICKED, NCS_PREGAME, (void*)&OnKicked, context);
|
AddTransition(NCS_PREGAME, (uint)NMT_KICKED, NCS_PREGAME, (void*)&OnKicked, context);
|
||||||
|
AddTransition(NCS_PREGAME, (uint)NMT_CLIENT_TIMEOUT, NCS_PREGAME, (void*)&OnClientTimeout, context);
|
||||||
|
AddTransition(NCS_PREGAME, (uint)NMT_CLIENT_PERFORMANCE, NCS_PREGAME, (void*)&OnClientPerformance, context);
|
||||||
AddTransition(NCS_PREGAME, (uint)NMT_GAME_START, NCS_LOADING, (void*)&OnGameStart, context);
|
AddTransition(NCS_PREGAME, (uint)NMT_GAME_START, NCS_LOADING, (void*)&OnGameStart, context);
|
||||||
AddTransition(NCS_PREGAME, (uint)NMT_JOIN_SYNC_START, NCS_JOIN_SYNCING, (void*)&OnJoinSyncStart, context);
|
AddTransition(NCS_PREGAME, (uint)NMT_JOIN_SYNC_START, NCS_JOIN_SYNCING, (void*)&OnJoinSyncStart, context);
|
||||||
|
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_CHAT, NCS_JOIN_SYNCING, (void*)&OnChat, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_CHAT, NCS_JOIN_SYNCING, (void*)&OnChat, context);
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_GAME_SETUP, NCS_JOIN_SYNCING, (void*)&OnGameSetup, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_GAME_SETUP, NCS_JOIN_SYNCING, (void*)&OnGameSetup, context);
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_JOIN_SYNCING, (void*)&OnPlayerAssignment, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_JOIN_SYNCING, (void*)&OnPlayerAssignment, context);
|
||||||
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_CLIENT_TIMEOUT, NCS_JOIN_SYNCING, (void*)&OnClientTimeout, context);
|
||||||
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_CLIENT_PERFORMANCE, NCS_JOIN_SYNCING, (void*)&OnClientPerformance, context);
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_GAME_START, NCS_JOIN_SYNCING, (void*)&OnGameStart, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_GAME_START, NCS_JOIN_SYNCING, (void*)&OnGameStart, context);
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_SIMULATION_COMMAND, NCS_JOIN_SYNCING, (void*)&OnInGame, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_SIMULATION_COMMAND, NCS_JOIN_SYNCING, (void*)&OnInGame, context);
|
||||||
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_END_COMMAND_BATCH, NCS_JOIN_SYNCING, (void*)&OnJoinSyncEndCommandBatch, context);
|
AddTransition(NCS_JOIN_SYNCING, (uint)NMT_END_COMMAND_BATCH, NCS_JOIN_SYNCING, (void*)&OnJoinSyncEndCommandBatch, context);
|
||||||
@ -108,10 +113,14 @@ CNetClient::CNetClient(CGame* game) :
|
|||||||
AddTransition(NCS_LOADING, (uint)NMT_CHAT, NCS_LOADING, (void*)&OnChat, context);
|
AddTransition(NCS_LOADING, (uint)NMT_CHAT, NCS_LOADING, (void*)&OnChat, context);
|
||||||
AddTransition(NCS_LOADING, (uint)NMT_GAME_SETUP, NCS_LOADING, (void*)&OnGameSetup, context);
|
AddTransition(NCS_LOADING, (uint)NMT_GAME_SETUP, NCS_LOADING, (void*)&OnGameSetup, context);
|
||||||
AddTransition(NCS_LOADING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_LOADING, (void*)&OnPlayerAssignment, context);
|
AddTransition(NCS_LOADING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_LOADING, (void*)&OnPlayerAssignment, context);
|
||||||
|
AddTransition(NCS_LOADING, (uint)NMT_CLIENT_TIMEOUT, NCS_LOADING, (void*)&OnClientTimeout, context);
|
||||||
|
AddTransition(NCS_LOADING, (uint)NMT_CLIENT_PERFORMANCE, NCS_LOADING, (void*)&OnClientPerformance, context);
|
||||||
AddTransition(NCS_LOADING, (uint)NMT_LOADED_GAME, NCS_INGAME, (void*)&OnLoadedGame, context);
|
AddTransition(NCS_LOADING, (uint)NMT_LOADED_GAME, NCS_INGAME, (void*)&OnLoadedGame, context);
|
||||||
|
|
||||||
AddTransition(NCS_INGAME, (uint)NMT_REJOINED, NCS_INGAME, (void*)&OnRejoined, context);
|
AddTransition(NCS_INGAME, (uint)NMT_REJOINED, NCS_INGAME, (void*)&OnRejoined, context);
|
||||||
AddTransition(NCS_INGAME, (uint)NMT_KICKED, NCS_INGAME, (void*)&OnKicked, context);
|
AddTransition(NCS_INGAME, (uint)NMT_KICKED, NCS_INGAME, (void*)&OnKicked, context);
|
||||||
|
AddTransition(NCS_INGAME, (uint)NMT_CLIENT_TIMEOUT, NCS_INGAME, (void*)&OnClientTimeout, context);
|
||||||
|
AddTransition(NCS_INGAME, (uint)NMT_CLIENT_PERFORMANCE, NCS_INGAME, (void*)&OnClientPerformance, context);
|
||||||
AddTransition(NCS_INGAME, (uint)NMT_CHAT, NCS_INGAME, (void*)&OnChat, context);
|
AddTransition(NCS_INGAME, (uint)NMT_CHAT, NCS_INGAME, (void*)&OnChat, context);
|
||||||
AddTransition(NCS_INGAME, (uint)NMT_GAME_SETUP, NCS_INGAME, (void*)&OnGameSetup, context);
|
AddTransition(NCS_INGAME, (uint)NMT_GAME_SETUP, NCS_INGAME, (void*)&OnGameSetup, context);
|
||||||
AddTransition(NCS_INGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_INGAME, (void*)&OnPlayerAssignment, context);
|
AddTransition(NCS_INGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_INGAME, (void*)&OnPlayerAssignment, context);
|
||||||
@ -170,8 +179,45 @@ void CNetClient::DestroyConnection()
|
|||||||
|
|
||||||
void CNetClient::Poll()
|
void CNetClient::Poll()
|
||||||
{
|
{
|
||||||
if (m_Session)
|
if (!m_Session)
|
||||||
m_Session->Poll();
|
return;
|
||||||
|
|
||||||
|
CheckServerConnection();
|
||||||
|
m_Session->Poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNetClient::CheckServerConnection()
|
||||||
|
{
|
||||||
|
// Trigger local warnings if the connection to the server is bad.
|
||||||
|
// At most once per second.
|
||||||
|
std::time_t now = std::time(nullptr);
|
||||||
|
if (now <= m_LastConnectionCheck)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_LastConnectionCheck = now;
|
||||||
|
|
||||||
|
JSContext* cx = GetScriptInterface().GetContext();
|
||||||
|
|
||||||
|
// Report if we are losing the connection to the server
|
||||||
|
u32 lastReceived = m_Session->GetLastReceivedTime();
|
||||||
|
if (lastReceived > NETWORK_WARNING_TIMEOUT)
|
||||||
|
{
|
||||||
|
JS::RootedValue msg(cx);
|
||||||
|
GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'server-timeout' })", &msg);
|
||||||
|
GetScriptInterface().SetProperty(msg, "lastReceivedTime", lastReceived);
|
||||||
|
PushGuiMessage(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report if we have a bad ping to the server
|
||||||
|
u32 meanRTT = m_Session->GetMeanRTT();
|
||||||
|
if (meanRTT > DEFAULT_TURN_LENGTH_MP)
|
||||||
|
{
|
||||||
|
JS::RootedValue msg(cx);
|
||||||
|
GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'server-latency' })", &msg);
|
||||||
|
GetScriptInterface().SetProperty(msg, "meanRTT", meanRTT);
|
||||||
|
PushGuiMessage(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetClient::Flush()
|
void CNetClient::Flush()
|
||||||
@ -627,6 +673,60 @@ bool CNetClient::OnKicked(void *context, CFsmEvent* event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CNetClient::OnClientTimeout(void *context, CFsmEvent* event)
|
||||||
|
{
|
||||||
|
// Report the timeout of some other client
|
||||||
|
|
||||||
|
ENSURE(event->GetType() == (uint)NMT_CLIENT_TIMEOUT);
|
||||||
|
|
||||||
|
CNetClient* client = (CNetClient*)context;
|
||||||
|
JSContext* cx = client->GetScriptInterface().GetContext();
|
||||||
|
|
||||||
|
if (client->GetCurrState() == NCS_LOADING)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CClientTimeoutMessage* message = (CClientTimeoutMessage*)event->GetParamRef();
|
||||||
|
JS::RootedValue msg(cx);
|
||||||
|
|
||||||
|
client->GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'client-timeout' })", &msg);
|
||||||
|
client->GetScriptInterface().SetProperty(msg, "guid", std::string(message->m_GUID));
|
||||||
|
client->GetScriptInterface().SetProperty(msg, "lastReceivedTime", message->m_LastReceivedTime);
|
||||||
|
client->PushGuiMessage(msg);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CNetClient::OnClientPerformance(void *context, CFsmEvent* event)
|
||||||
|
{
|
||||||
|
// Performance statistics for one or multiple clients
|
||||||
|
|
||||||
|
ENSURE(event->GetType() == (uint)NMT_CLIENT_PERFORMANCE);
|
||||||
|
|
||||||
|
CNetClient* client = (CNetClient*)context;
|
||||||
|
JSContext* cx = client->GetScriptInterface().GetContext();
|
||||||
|
|
||||||
|
if (client->GetCurrState() == NCS_LOADING)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CClientPerformanceMessage* message = (CClientPerformanceMessage*)event->GetParamRef();
|
||||||
|
std::vector<CClientPerformanceMessage::S_m_Clients> &clients = message->m_Clients;
|
||||||
|
|
||||||
|
// Display warnings for other clients with bad ping
|
||||||
|
for (size_t i = 0; i < clients.size(); ++i)
|
||||||
|
{
|
||||||
|
if (clients[i].m_MeanRTT < DEFAULT_TURN_LENGTH_MP || clients[i].m_GUID == client->m_GUID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
JS::RootedValue msg(cx);
|
||||||
|
client->GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'client-latency' })", &msg);
|
||||||
|
client->GetScriptInterface().SetProperty(msg, "guid", clients[i].m_GUID);
|
||||||
|
client->GetScriptInterface().SetProperty(msg, "meanRTT", clients[i].m_MeanRTT);
|
||||||
|
client->PushGuiMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event)
|
bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event)
|
||||||
{
|
{
|
||||||
ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
|
ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -108,6 +108,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Poll();
|
void Poll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locally triggers a GUI message if the connection to the server is being lost or has bad latency.
|
||||||
|
*/
|
||||||
|
void CheckServerConnection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush any queued outgoing network messages.
|
* Flush any queued outgoing network messages.
|
||||||
* This should be called soon after sending a group of messages that may be batched together.
|
* This should be called soon after sending a group of messages that may be batched together.
|
||||||
@ -202,6 +207,8 @@ private:
|
|||||||
static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event);
|
static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event);
|
||||||
static bool OnRejoined(void* context, CFsmEvent* event);
|
static bool OnRejoined(void* context, CFsmEvent* event);
|
||||||
static bool OnKicked(void* context, CFsmEvent* event);
|
static bool OnKicked(void* context, CFsmEvent* event);
|
||||||
|
static bool OnClientTimeout(void* context, CFsmEvent* event);
|
||||||
|
static bool OnClientPerformance(void* context, CFsmEvent* event);
|
||||||
static bool OnLoadedGame(void* context, CFsmEvent* event);
|
static bool OnLoadedGame(void* context, CFsmEvent* event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -240,6 +247,9 @@ private:
|
|||||||
|
|
||||||
/// Serialized game state received when joining an in-progress game
|
/// Serialized game state received when joining an in-progress game
|
||||||
std::string m_JoinSyncBuffer;
|
std::string m_JoinSyncBuffer;
|
||||||
|
|
||||||
|
/// Time when the server was last checked for timeouts and bad latency
|
||||||
|
std::time_t m_LastConnectionCheck;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Global network client for the standard game
|
/// Global network client for the standard game
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -139,6 +139,14 @@ CNetMessage* CNetMessageFactory::CreateMessage(const void* pData,
|
|||||||
pNewMessage = new CKickedMessage;
|
pNewMessage = new CKickedMessage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NMT_CLIENT_TIMEOUT:
|
||||||
|
pNewMessage = new CClientTimeoutMessage;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_CLIENT_PERFORMANCE:
|
||||||
|
pNewMessage = new CClientPerformanceMessage;
|
||||||
|
break;
|
||||||
|
|
||||||
case NMT_LOADED_GAME:
|
case NMT_LOADED_GAME:
|
||||||
pNewMessage = new CLoadedGameMessage;
|
pNewMessage = new CLoadedGameMessage;
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?'
|
#define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?'
|
||||||
#define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!'
|
#define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!'
|
||||||
#define PS_PROTOCOL_VERSION 0x01010008 // Arbitrary protocol
|
#define PS_PROTOCOL_VERSION 0x01010009 // Arbitrary protocol
|
||||||
#define PS_DEFAULT_PORT 0x5073 // 'P', 's'
|
#define PS_DEFAULT_PORT 0x5073 // 'P', 's'
|
||||||
|
|
||||||
// Defines the list of message types. The order of the list must not change.
|
// Defines the list of message types. The order of the list must not change.
|
||||||
@ -60,6 +60,9 @@ enum NetMessageType
|
|||||||
NMT_REJOINED,
|
NMT_REJOINED,
|
||||||
NMT_KICKED,
|
NMT_KICKED,
|
||||||
|
|
||||||
|
NMT_CLIENT_TIMEOUT,
|
||||||
|
NMT_CLIENT_PERFORMANCE,
|
||||||
|
|
||||||
NMT_LOADED_GAME,
|
NMT_LOADED_GAME,
|
||||||
NMT_GAME_START,
|
NMT_GAME_START,
|
||||||
NMT_END_COMMAND_BATCH,
|
NMT_END_COMMAND_BATCH,
|
||||||
@ -167,6 +170,18 @@ START_NMT_CLASS_(Kicked, NMT_KICKED)
|
|||||||
NMT_FIELD_INT(m_Ban, u8, 1)
|
NMT_FIELD_INT(m_Ban, u8, 1)
|
||||||
END_NMT_CLASS()
|
END_NMT_CLASS()
|
||||||
|
|
||||||
|
START_NMT_CLASS_(ClientTimeout, NMT_CLIENT_TIMEOUT)
|
||||||
|
NMT_FIELD(CStr8, m_GUID)
|
||||||
|
NMT_FIELD_INT(m_LastReceivedTime, u32, 4)
|
||||||
|
END_NMT_CLASS()
|
||||||
|
|
||||||
|
START_NMT_CLASS_(ClientPerformance, NMT_CLIENT_PERFORMANCE)
|
||||||
|
NMT_START_ARRAY(m_Clients)
|
||||||
|
NMT_FIELD(CStr8, m_GUID)
|
||||||
|
NMT_FIELD_INT(m_MeanRTT, u32, 4)
|
||||||
|
NMT_END_ARRAY()
|
||||||
|
END_NMT_CLASS()
|
||||||
|
|
||||||
START_NMT_CLASS_(LoadedGame, NMT_LOADED_GAME)
|
START_NMT_CLASS_(LoadedGame, NMT_LOADED_GAME)
|
||||||
NMT_FIELD_INT(m_CurrentTurn, u32, 4)
|
NMT_FIELD_INT(m_CurrentTurn, u32, 4)
|
||||||
END_NMT_CLASS()
|
END_NMT_CLASS()
|
||||||
|
@ -121,7 +121,8 @@ CNetServerWorker::CNetServerWorker(int autostartPlayers) :
|
|||||||
m_AutostartPlayers(autostartPlayers),
|
m_AutostartPlayers(autostartPlayers),
|
||||||
m_Shutdown(false),
|
m_Shutdown(false),
|
||||||
m_ScriptInterface(NULL),
|
m_ScriptInterface(NULL),
|
||||||
m_NextHostID(1), m_Host(NULL), m_HostGUID(), m_Stats(NULL)
|
m_NextHostID(1), m_Host(NULL), m_HostGUID(), m_Stats(NULL),
|
||||||
|
m_LastConnectionCheck(0)
|
||||||
{
|
{
|
||||||
m_State = SERVER_STATE_UNCONNECTED;
|
m_State = SERVER_STATE_UNCONNECTED;
|
||||||
|
|
||||||
@ -451,6 +452,8 @@ bool CNetServerWorker::RunStep()
|
|||||||
for (size_t i = 0; i < m_Sessions.size(); ++i)
|
for (size_t i = 0; i < m_Sessions.size(); ++i)
|
||||||
m_Sessions[i]->GetFileTransferer().Poll();
|
m_Sessions[i]->GetFileTransferer().Poll();
|
||||||
|
|
||||||
|
CheckClientConnections();
|
||||||
|
|
||||||
// Process network events:
|
// Process network events:
|
||||||
|
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
@ -549,6 +552,55 @@ bool CNetServerWorker::RunStep()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNetServerWorker::CheckClientConnections()
|
||||||
|
{
|
||||||
|
if (m_State == SERVER_STATE_LOADING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Send messages at most once per second
|
||||||
|
std::time_t now = std::time(nullptr);
|
||||||
|
if (now <= m_LastConnectionCheck)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_LastConnectionCheck = now;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_Sessions.size(); ++i)
|
||||||
|
{
|
||||||
|
u32 lastReceived = m_Sessions[i]->GetLastReceivedTime();
|
||||||
|
u32 meanRTT = m_Sessions[i]->GetMeanRTT();
|
||||||
|
|
||||||
|
CNetMessage* message = nullptr;
|
||||||
|
|
||||||
|
// Report if we didn't hear from the client since few seconds
|
||||||
|
if (lastReceived > NETWORK_WARNING_TIMEOUT)
|
||||||
|
{
|
||||||
|
CClientTimeoutMessage* msg = new CClientTimeoutMessage();
|
||||||
|
msg->m_GUID = m_Sessions[i]->GetGUID();
|
||||||
|
msg->m_LastReceivedTime = lastReceived;
|
||||||
|
message = msg;
|
||||||
|
}
|
||||||
|
// Report if the client has bad ping
|
||||||
|
else if (meanRTT > DEFAULT_TURN_LENGTH_MP)
|
||||||
|
{
|
||||||
|
CClientPerformanceMessage* msg = new CClientPerformanceMessage();
|
||||||
|
CClientPerformanceMessage::S_m_Clients client;
|
||||||
|
client.m_GUID = m_Sessions[i]->GetGUID();
|
||||||
|
client.m_MeanRTT = meanRTT;
|
||||||
|
msg->m_Clients.push_back(client);
|
||||||
|
message = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to all clients except the affected one
|
||||||
|
// (since that will show the locally triggered warning instead)
|
||||||
|
if (message)
|
||||||
|
for (size_t j = 0; j < m_Sessions.size(); ++j)
|
||||||
|
if (i != j)
|
||||||
|
m_Sessions[j]->SendMessage(message);
|
||||||
|
|
||||||
|
SAFE_DELETE(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CNetServerWorker::HandleMessageReceive(const CNetMessage* message, CNetServerSession* session)
|
void CNetServerWorker::HandleMessageReceive(const CNetMessage* message, CNetServerSession* session)
|
||||||
{
|
{
|
||||||
// Handle non-FSM messages first
|
// Handle non-FSM messages first
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -281,6 +281,10 @@ private:
|
|||||||
|
|
||||||
void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session);
|
void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a network warning if the connection to a client is being lost or has bad latency.
|
||||||
|
*/
|
||||||
|
void CheckClientConnections();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal script context for (de)serializing script messages,
|
* Internal script context for (de)serializing script messages,
|
||||||
@ -331,6 +335,11 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::string m_JoinSyncFile;
|
std::string m_JoinSyncFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when the clients connections were last checked for timeouts and latency.
|
||||||
|
*/
|
||||||
|
std::time_t m_LastConnectionCheck;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Thread-related stuff:
|
// Thread-related stuff:
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "ps/CLogger.h"
|
#include "ps/CLogger.h"
|
||||||
#include "scriptinterface/ScriptInterface.h"
|
#include "scriptinterface/ScriptInterface.h"
|
||||||
|
|
||||||
|
const u32 NETWORK_WARNING_TIMEOUT = 4000;
|
||||||
|
|
||||||
static const int CHANNEL_COUNT = 1;
|
static const int CHANNEL_COUNT = 1;
|
||||||
|
|
||||||
CNetClientSession::CNetClientSession(CNetClient& client) :
|
CNetClientSession::CNetClientSession(CNetClient& client) :
|
||||||
@ -168,6 +170,22 @@ bool CNetClientSession::SendMessage(const CNetMessage* message)
|
|||||||
return CNetHost::SendMessage(message, m_Server, "server");
|
return CNetHost::SendMessage(message, m_Server, "server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CNetClientSession::GetLastReceivedTime() const
|
||||||
|
{
|
||||||
|
if (!m_Server)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return enet_time_get() - m_Server->lastReceiveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CNetClientSession::GetMeanRTT() const
|
||||||
|
{
|
||||||
|
if (!m_Server)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_Server->roundTripTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) :
|
CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) :
|
||||||
@ -184,6 +202,22 @@ CStr CNetServerSession::GetIPAddress() const
|
|||||||
return ipAddress;
|
return ipAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CNetServerSession::GetLastReceivedTime() const
|
||||||
|
{
|
||||||
|
if (!m_Peer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return enet_time_get() - m_Peer->lastReceiveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CNetServerSession::GetMeanRTT() const
|
||||||
|
{
|
||||||
|
if (!m_Peer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_Peer->roundTripTime;
|
||||||
|
}
|
||||||
|
|
||||||
void CNetServerSession::Disconnect(u32 reason)
|
void CNetServerSession::Disconnect(u32 reason)
|
||||||
{
|
{
|
||||||
Update((uint)NMT_CONNECTION_LOST, NULL);
|
Update((uint)NMT_CONNECTION_LOST, NULL);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -24,6 +24,11 @@
|
|||||||
#include "ps/CStr.h"
|
#include "ps/CStr.h"
|
||||||
#include "scriptinterface/ScriptVal.h"
|
#include "scriptinterface/ScriptVal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report the peer if we didn't receive a packet after this time (milliseconds).
|
||||||
|
*/
|
||||||
|
extern const u32 NETWORK_WARNING_TIMEOUT;
|
||||||
|
|
||||||
class CNetClient;
|
class CNetClient;
|
||||||
class CNetServerWorker;
|
class CNetServerWorker;
|
||||||
|
|
||||||
@ -83,6 +88,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool SendMessage(const CNetMessage* message);
|
virtual bool SendMessage(const CNetMessage* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of milliseconds since the most recent packet of the server was received.
|
||||||
|
*/
|
||||||
|
u32 GetLastReceivedTime() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Average round trip time to the server.
|
||||||
|
*/
|
||||||
|
u32 GetMeanRTT() const;
|
||||||
|
|
||||||
CNetFileTransferer& GetFileTransferer() { return m_FileTransferer; }
|
CNetFileTransferer& GetFileTransferer() { return m_FileTransferer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -124,6 +139,16 @@ public:
|
|||||||
|
|
||||||
CStr GetIPAddress() const;
|
CStr GetIPAddress() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of milliseconds since the latest packet of that client was received.
|
||||||
|
*/
|
||||||
|
u32 GetLastReceivedTime() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Average round trip time to the client.
|
||||||
|
*/
|
||||||
|
u32 GetMeanRTT() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a disconnection notification to the client,
|
* Sends a disconnection notification to the client,
|
||||||
* and sends a NMT_CONNECTION_LOST message to the session FSM.
|
* and sends a NMT_CONNECTION_LOST message to the session FSM.
|
||||||
|
@ -38,8 +38,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
static const int DEFAULT_TURN_LENGTH_MP = 500;
|
const u32 DEFAULT_TURN_LENGTH_MP = 500;
|
||||||
static const int DEFAULT_TURN_LENGTH_SP = 200;
|
const u32 DEFAULT_TURN_LENGTH_SP = 200;
|
||||||
|
|
||||||
static const int COMMAND_DELAY = 2;
|
static const int COMMAND_DELAY = 2;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015 Wildfire Games.
|
/* Copyright (C) 2016 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -26,6 +26,9 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
extern const u32 DEFAULT_TURN_LENGTH_MP;
|
||||||
|
extern const u32 DEFAULT_TURN_LENGTH_SP;
|
||||||
|
|
||||||
class CNetServerWorker;
|
class CNetServerWorker;
|
||||||
class CNetClient;
|
class CNetClient;
|
||||||
class CSimulationMessage;
|
class CSimulationMessage;
|
||||||
|
Loading…
Reference in New Issue
Block a user