Reimplement pinging via the orders channel.

This commit is contained in:
Paul Chote
2013-04-22 20:36:36 +12:00
parent 9f4b323287
commit 9069d98365
10 changed files with 89 additions and 19 deletions

View File

@@ -199,7 +199,12 @@ namespace OpenRA
{
return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text };
}
public static Order Pong(string pingTime)
{
return new Order("Pong", null, false) { IsImmediate = true, TargetString = pingTime };
}
public static Order PauseGame(bool paused)
{
return new Order("PauseGame", null, false) { TargetString = paused ? "Pause" : "UnPause" };

View File

@@ -62,6 +62,8 @@ namespace OpenRA.Network
public bool IsReady { get { return State == ClientState.Ready; } }
public bool IsObserver { get { return Slot == null; } }
public int Ping = -1;
public int PingJitter = -1;
public int[] PingHistory = {};
}
public class Slot

View File

@@ -190,6 +190,11 @@ namespace OpenRA.Network
Game.Debug("{0} has reciprocated",targetPlayer.PlayerName);
}
break;
}
case "Ping":
{
orderManager.IssueOrder(Order.Pong(order.TargetString));
break;
}
default:

View File

@@ -290,8 +290,9 @@ namespace OpenRA.Server
SyncClientToPlayerReference(client, Map.Players[client.Slot]);
lobbyInfo.Clients.Add(client);
//Assume that first validated client is server admin
if(lobbyInfo.Clients.Where(c1 => c1.Bot == null).Count()==1)
// Assume that first validated client is server admin
if (lobbyInfo.Clients.Where(c1 => c1.Bot == null).Count() == 1)
client.IsAdmin=true;
OpenRA.Network.Session.Client clientAdmin = lobbyInfo.Clients.Where(c1 => c1.IsAdmin).Single();
@@ -305,6 +306,9 @@ namespace OpenRA.Server
SyncLobbyInfo();
SendChat(newConn, "has joined the game.");
// Send initial ping
SendOrderTo(newConn, "Ping", Environment.TickCount.ToString());
if (File.Exists("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0])))
{
var motd = System.IO.File.ReadAllText("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0]));
@@ -456,6 +460,31 @@ namespace OpenRA.Server
foreach (var c in conns.Except(conn).ToArray())
DispatchOrdersToClient(c, fromIndex, 0, so.Serialize());
break;
case "Pong":
{
int pingSent;
if (!int.TryParse(so.Data, out pingSent))
{
Log.Write("server", "Invalid order pong payload: {0}", so.Data);
break;
}
var history = fromClient.PingHistory.ToList();
history.Add(Environment.TickCount - pingSent);
// Cap ping history at 5 values (25 seconds)
if (history.Count > 5)
history.RemoveRange(0, history.Count - 5);
fromClient.Ping = history.Sum() / history.Count;
fromClient.PingJitter = (history.Max() - history.Min())/2;
fromClient.PingHistory = history.ToArray();
if (State == ServerState.WaitingPlayers)
SyncLobbyInfo();
break;
}
}
}

View File

@@ -429,6 +429,7 @@
<Compile Include="Activities\RepairBridge.cs" />
<Compile Include="BridgeHut.cs" />
<Compile Include="Lint\CheckSequences.cs" />
<Compile Include="ServerTraits\PlayerPinger.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">

View File

@@ -100,22 +100,6 @@ namespace OpenRA.Mods.RA.Server
server.StartGame();
return true;
}},
{ "lag",
s =>
{
int lag;
if (!int.TryParse(s, out lag))
{
Log.Write("server", "Invalid order lag: {0}", s);
return false;
}
Log.Write("server", "Order lag is now {0} frames.", lag);
server.lobbyInfo.GlobalSettings.OrderLatency = lag;
server.SyncLobbyInfo();
return true;
}},
{ "slot",
s =>
{

View File

@@ -0,0 +1,41 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using OpenRA.Server;
using OpenRA.Network;
using S = OpenRA.Server.Server;
namespace OpenRA.Mods.RA.Server
{
public class PlayerPinger : ServerTrait, ITick
{
int PingInterval = 5000; // Ping every 5 seconds
// TickTimeout is in microseconds
public int TickTimeout { get { return PingInterval * 100; } }
int lastPing = 0;
bool isInitialPing = true;
public void Tick(S server)
{
if ((Environment.TickCount - lastPing > PingInterval) || isInitialPing)
{
isInitialPing = false;
lastPing = Environment.TickCount;
foreach (var p in server.conns)
server.SendOrderTo(p, "Ping", Environment.TickCount.ToString());
}
}
}
}

View File

@@ -112,6 +112,7 @@ LoadScreen: CncLoadScreen
ServerTraits:
LobbyCommands
PlayerPinger
MasterServerPinger
ChromeMetrics:

View File

@@ -89,6 +89,7 @@ LoadScreen: D2kLoadScreen
ServerTraits:
LobbyCommands
PlayerPinger
MasterServerPinger
ChromeMetrics:

View File

@@ -103,6 +103,7 @@ LoadScreen: RALoadScreen
ServerTraits:
LobbyCommands
PlayerPinger
MasterServerPinger
ChromeMetrics: