Skip to content

Commit

Permalink
Added translation support for server orders.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mailaender committed Dec 21, 2021
1 parent ecdab48 commit f0729a1
Show file tree
Hide file tree
Showing 19 changed files with 792 additions and 146 deletions.
119 changes: 119 additions & 0 deletions OpenRA.Game/Network/LocalizedMessage.cs
@@ -0,0 +1,119 @@
#region Copyright & License Information
/*
* Copyright 2007-2021 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Fluent.Net;
using OpenRA.Widgets;

namespace OpenRA.Network
{
public class FluentArgument
{
[Flags]
public enum FluentArgumentType
{
String = 0,
Number = 1,
}

public readonly string Key;
public readonly string Value;
public readonly FluentArgumentType Type;

public FluentArgument() { }

public FluentArgument(string key, object value)
{
Key = key;
Value = value.ToString();
Type = value is sbyte || value is short || value is int || value is long ||
value is byte || value is ushort || value is uint || value is ulong ||
value is float || value is double || value is decimal ?
FluentArgumentType.Number : FluentArgumentType.String;
}
}

public class LocalizedMessage
{
public const int ProtocolVersion = 1;

public readonly string Key;

[FieldLoader.LoadUsing(nameof(LoadArguments))]
public readonly FluentArgument[] Arguments;

static object LoadArguments(MiniYaml yaml)
{
var arguments = new List<FluentArgument>();
var argumentsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Arguments");
if (argumentsNode != null)
{
var regex = new Regex(@"Argument@\d+");
foreach (var argument in argumentsNode.Value.Nodes)
if (regex.IsMatch(argument.Key))
arguments.Add(FieldLoader.Load<FluentArgument>(argument.Value));
}

return arguments.ToArray();
}

static readonly string[] SerializeFields = { "Key" };

public LocalizedMessage(MiniYaml yaml)
{
FieldLoader.Load(this, yaml);
}

public LocalizedMessage(string key, Dictionary<string, object> arguments = null)
{
Key = key;
Arguments = arguments?.Select(a => new FluentArgument(a.Key, a.Value)).ToArray();
}

public string Serialize()
{
var root = new List<MiniYamlNode>() { new MiniYamlNode("Protocol", ProtocolVersion.ToString()) };
foreach (var field in SerializeFields)
root.Add(FieldSaver.SaveField(this, field));

if (Arguments != null)
{
var argumentsNode = new MiniYaml("");
var i = 0;
foreach (var argument in Arguments)
argumentsNode.Nodes.Add(new MiniYamlNode("Argument@" + i++, FieldSaver.Save(argument)));

root.Add(new MiniYamlNode("Arguments", argumentsNode));
}

return new MiniYaml("", root)
.ToLines("LocalizedMessage")
.JoinWith("\n");
}

public string Translate()
{
var argumentDictionary = new Dictionary<string, object>();
foreach (var argument in Arguments)
{
if (argument.Type == FluentArgument.FluentArgumentType.Number)
argumentDictionary.Add(argument.Key, new FluentNumber(argument.Value));
else
argumentDictionary.Add(argument.Key, new FluentString(argument.Value));
}

return Ui.Translate(Key, argumentDictionary);
}
}
}
16 changes: 16 additions & 0 deletions OpenRA.Game/Network/UnitOrders.cs
Expand Up @@ -34,6 +34,22 @@ internal static void ProcessOrder(OrderManager orderManager, World world, int cl
TextNotificationsManager.AddSystemLine(order.TargetString);
break;

// Client side translated server message
case "LocalizedMessage":
{
if (string.IsNullOrEmpty(order.TargetString))
break;

var yaml = MiniYaml.FromString(order.TargetString);
foreach (var node in yaml)
{
var localizedMessage = new LocalizedMessage(node.Value);
TextNotificationsManager.AddSystemLine(localizedMessage.Translate());
}

break;
}

case "DisableChatEntry":
{
// Order must originate from the server
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/Server/Connection.cs
Expand Up @@ -171,7 +171,7 @@ void SendReceiveLoop(object s)
var sent = socket.Send(data, start, length - start, SocketFlags.None, out var error);
if (error == SocketError.WouldBlock)
{
Log.Write("server", "Non-blocking send of {0} bytes failed. Falling back to blocking send.", length - start);
Log.Write("server", $"Non-blocking send of {length - start} bytes failed. Falling back to blocking send.");
socket.Blocking = true;
sent = socket.Send(data, start, length - start, SocketFlags.None);
socket.Blocking = false;
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/Server/ProtocolVersion.cs
Expand Up @@ -77,6 +77,6 @@ public static class ProtocolVersion
// The protocol for server and world orders
// This applies after the handshake has completed, and is provided to support
// alternative server implementations that wish to support multiple versions in parallel
public const int Orders = 18;
public const int Orders = 19;
}
}

0 comments on commit f0729a1

Please sign in to comment.