Log in

View Full Version : System of messages with localization


podvoxx
06-28-2012, 05:04 AM
Hi all.
I created a messaging system that allows you to easily use them to send a group of players and translate the text. Transfer is carried out with the help of xml-files. The path to a text file you specify in the host-mission script.

The system works in all game modes, and on a dedicated server and is intended for designers of mission does not require much knowledge of c# and scripts.

Advantages:
-do not write message-code in every script, you just connect dll-file
-localization file is loaded only once
-easy to use
-works in all game modes (multiplayer in the game, dedicated server, single, campaign)
-you can translate the menu items
-you can use the numerical parameters in your messages

Installation.
Put the file smpMessage.dll in a game-folder:
https://lh3.googleusercontent.com/-HIzg2kFf8bE/T-vghwXy6DI/AAAAAAAAAJc/_Rk_yQWT79A/s0-d/x.jpg

Now, you must connect dll-file to your script for using message methods. See this code:
Connecting the system in the script:

//$reference "smpMessage.dll"
using System;
using maddox.game;
using maddox.game.world;
using smpmessage;

public class Mission : AMission
{
// Path to localization xml-file if you want use translated text
private static string localizationFilePath = Environment.GetFolderPath(Environment.SpecialFolde r.Personal) + "\\1C SoftClub\\il-2 sturmovik cliffs of dover\\missions\\Single\\LocalizationExample\\loca lization.xml";

// Create dictionary for translate and send translated messages
private static Translate Dictionary = Translate.UseConfigFile(localizationFilePath);

public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;

Dictionary.ToAll("SendMessageSection", "SendToChatToALLtranslate", "Chat");
SendMessage.ToAll("Message to ALL - ENGLISH or ДРУГОЙ ЯЗЫК", "Chat");
}
}

Localization file it's xml-file. It is loaded only once. This saves server resources, access to the hard drive occurs only once
Name of loc.file: any name
Format of loc. file:

<?xml version="1.0" encoding="utf-8"?>
<!-- Language dictionary-->
<SMP>
<LanguageSection name="SendMessageSection">
<Text key="SendToChatToALLtranslate">
<en>Send To Chat To ALL translate ENGLISH</en>
<ru>Send To Chat To ALL translate РУССКИЙ</ru>
</Text>
<Text key="SendToChatToPlayertranslate">
<en>Send To Chat To Player translate ENGLISH</en>
<ru>Send To Chat To Player translate РУССКИЙ</ru>
</Text>
<Text key="SendToChatToArmytranslate">
<en>Send To Chat To Army translate ENGLISH</en>
<ru>Send To Chat To Army translate РУССКИЙ</ru>
</Text>
<Text key="SendToScreenToALLtranslate">
<en>Send To Screen To ALL translate ENGLISH</en>
<ru>Send To Screen To ALL translate РУССКИЙ</ru>
</Text>
<Text key="SendToScreenToPlayertranslate">
<en>Send To Screen To Player translate ENGLISH</en>
<ru>Send To Screen To Player translate РУССКИЙ</ru>
</Text>
<Text key="SendToScreenToArmytranslate">
<en>Send To Screen To Army translate ENGLISH</en>
<ru>Send To Screen To Army translate РУССКИЙ</ru>
</Text>
<Text key="SendToChatAndScreenToALLtranslate">
<en>Send To Chat And Screen To ALL translate ENGLISH</en>
<ru>Send To Chat And Screen To ALL translate РУССКИЙ</ru>
</Text>
<Text key="SendToChatAndScreenToPlayertranslate">
<en>Send To Chat And Screen To Player translate ENGLISH</en>
<ru>Send To Chat And Screen To Player translate РУССКИЙ</ru>
</Text>
<Text key="SendToChatAndScreenToArmytranslate">
<en>Send To Chat And Screen To Army translate ENGLISH</en>
<ru>Send To Chat And Screen To Army translate РУССКИЙ</ru>
</Text>
<Text key="GetTranslateText">
<en>Get Translate Text ENGLISH</en>
<ru>Get Translate Text РУССКИЙ</ru>
</Text>
<Text key="useParametersLabel">
<en>Number1: {0}, Number2: {1}</en>
<ru>Число 1: {0}, Число 2: {1}</ru>
</Text>
</LanguageSection>
<LanguageSection name="Parameters">
<Text key="useParametersLabel">
<en>Number1: {0}, Number2: {1}</en>
<ru>Число 1: {0}, Число 2: {1}</ru>
</Text>
</LanguageSection>
</SMP>

If you do not translate message (only send) localization file and setting path to file are not needed. You must only adding dll-file unto your script


//$reference "smpMessage.dll"
using System;
using maddox.game;
using maddox.game.world;
using smpmessage;

public class Mission : AMission
{

public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;

SendMessage.ToAll("Message to ALL - ENGLISH or ДРУГОЙ ЯЗЫК", "Chat");
}
}


After create dictionary in host-mission you can add this dictionary in any submission script. To do this:

//$reference "smpMessage.dll"
using System;
using maddox.game;
using maddox.game.world;
using smpmessage;

public class Mission : AMission
{

// Get dictionary for translate and send messages
private static Translate Dictionary = Translate.GetInstance;

public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;

Dictionary.ToAll("SendMessageSection", "SendToChatToALLtranslate", "Chat");
}
}


You can use example mission in attache, put mission folder into "1C SoftClub\il-2 sturmovik cliffs of dover\missions\Single" in user-folder. Run mission and place enter aircraft. You see example messages
https://lh4.googleusercontent.com/-_-zxacyhtYY/T-vlpQW5sCI/AAAAAAAAAJo/XDts0yR4W_Y/s0-d/y.jpg
Example .cs-file:

//$reference "smpMessage.dll"
using System;
using maddox.game;
using maddox.game.world;
using smpmessage;
using System.Collections.Generic;

/* Available methods:
* -- Translate and send message
* public static void ToAll(string section, string key, string target, params object[] args)
* public static void ToArmy(string section, string key, int army, string target, params object[] args)
* public static void ToPlayers(string section, string key, Player[] players, string target, params object[] args)
*
* -- No translate, only send message
* public static void ToAll(string message, string target, params object[] args)
* public static void ToArmy(string message, int army, string target, params object[] args)
* public static void ToPlayers(string message, Player[] players, string target, params object[] args)
* public static void ToServer(string message, params object[] args)
*
* -- Only translate, no send message
* public string GetString(string section, string key, string language)
*
* Available languages in game: en ru de fr es cs it pl
*/

public class Mission : AMission
{
// Path to localization xml-file, if you want to use localization on your script
private static string localizationFilePath = Environment.GetFolderPath(Environment.SpecialFolde r.Personal) + "\\1C SoftClub\\il-2 sturmovik cliffs of dover\\missions\\Single\\LocalizationExample\\loca lization.xml";

// Create dictionary for translate and send messages
private static Translate Dictionary = Translate.UseConfigFile(localizationFilePath);

public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;
}

public override void OnPlaceEnter(Player player, AiActor actor, int placeIndex)
{
base.OnPlaceEnter(player, actor, placeIndex);
// TEST Messages
// Translate and send message
Dictionary.ToAll("SendMessageSection", "SendToChatToALLtranslate", "Chat");
Dictionary.ToPlayers("SendMessageSection", "SendToChatToPlayertranslate", new Player[] { player }, "Chat");
Dictionary.ToArmy("SendMessageSection", "SendToChatToArmytranslate", 1, "Chat");

Dictionary.ToAll("SendMessageSection", "SendToScreenToALLtranslate", "Screen");
Dictionary.ToPlayers("SendMessageSection", "SendToScreenToPlayertranslate", new Player[] { player }, "Screen");
Dictionary.ToArmy("SendMessageSection", "SendToScreenToArmytranslate", 1, "Screen");

Dictionary.ToAll("SendMessageSection", "SendToChatAndScreenToALLtranslate", "ChatAndScreen");
Dictionary.ToPlayers("SendMessageSection", "SendToChatAndScreenToPlayertranslate", new Player[] { player }, "ChatAndScreen");
Dictionary.ToArmy("SendMessageSection", "SendToChatAndScreenToArmytranslate", 1, "ChatAndScreen");

// No translate, only send message
SendMessage.ToAll("Message to ALL - ENGLISH or ДРУГОЙ ЯЗЫК", "Chat");
SendMessage.ToPlayers("Message to Players - ENGLISH or ДРУГОЙ ЯЗЫК", new Player[] { player }, "Chat");
SendMessage.ToArmy("Message to Army - ENGLISH or ДРУГОЙ ЯЗЫК", 1, "Chat");

SendMessage.ToAll("Message to ALL - ENGLISH or ДРУГОЙ ЯЗЫК", "Screen");
SendMessage.ToPlayers("Message to Players - ENGLISH or ДРУГОЙ ЯЗЫК", new Player[] { player }, "Screen");
SendMessage.ToArmy("Message to Army - ENGLISH or ДРУГОЙ ЯЗЫК", 1, "Screen");

SendMessage.ToAll("Message to ALL - ENGLISH or ДРУГОЙ ЯЗЫК", "ChatAndScreen");
SendMessage.ToPlayers("Message to Players - ENGLISH or ДРУГОЙ ЯЗЫК", new Player[] { player }, "ChatAndScreen");
SendMessage.ToArmy("Message to Army - ENGLISH or ДРУГОЙ ЯЗЫК", 1, "ChatAndScreen");

// Only translate, no send message
//initTranslate.GetString("SendMessageSection", "GetTranslateText", "en");
//initTranslate.GetString("SendMessageSection", "GetTranslateText", "ru");
//initTranslate.GetString("SendMessageSection", "GetTranslateText", player.LanguageName());
// Examples for using translated text:
SendMessage.ToAll(Dictionary.GetString("SendMessageSection", "GetTranslateText", "en"), "Chat");
SendMessage.ToAll(Dictionary.GetString("SendMessageSection", "GetTranslateText", player.LanguageName()), "Chat");
SendMessage.ToAll(Dictionary.GetString("SendMessageSection", "GetTranslateText", "de"), "Chat");

// Using parameters in messages
int number1 = 1000;
int number2 = 500;
SendMessage.ToAll("SendMessageSection", "============NO TRANSLATE LINE whith xml-file===========", "Chat");

SendMessage.ToAll("Parameters", "useParametersLabel", "Chat", number1, number2);
SendMessage.ToAll("Parameters", "useParametersLabel", "Screen", number1, number2);
SendMessage.ToAll("Parameters", "useParametersLabel", "ChatAndScreen", number1, number2);

SendMessage.ToAll("Number1 = {0}, Number2 = {1}", "Chat", number1, number2);
SendMessage.ToAll("Number1 = {0}, Number2 = {1}", "Screen", number1, number2);
SendMessage.ToAll("Number1 = {0}, Number2 = {1}", "ChatAndScreen", number1, number2);

SendMessage.ToServer("This message only for server. No translate. {0}", "Only for chat!");

SendMessage.ToAll("============NO TRANSLATE LINE whithout xml-file===========", "Chat");
}
}


Code of dll-file:

using System;
using System.Collections.Generic;
using maddox.game;
using maddox.game.world;
using System.Xml;

namespace smpmessage
{
// ================================================== ==
// (based on Small_Bee and FG_Kodiak code)
// ================================================== ==
public sealed class Translate
{
#region Parameters
private static readonly Lazy<Translate> Lazy = new Lazy<Translate>(() => new Translate());
private static readonly Dictionary<string, Dictionary<string, Dictionary<string, string>>> _stringPool = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
static readonly IGamePlay GamePlay = Strategy.THIS.GamePlay;

const string XmlLanguagenode = "SMP/LanguageSection";
private const string DefaultLanguage = "en";
public static string setupServerLanguage = "off";
#endregion

#region Read File
public static Translate GetInstance
{
get { return Lazy.Value; }
}


private Translate()
{
}

public static Translate UseConfigFile(string fileName)
{
if (_stringPool.Count == 0)
LoadSettings(fileName);
return Lazy.Value;
}

private static XmlDocument LoadXMLFile(string file)
{
// Load the xml-file in a xml-document
XmlDocument xDoc = new XmlDocument();

try
{
xDoc.Load(file);
}
catch (System.IO.FileNotFoundException)
{
throw new Exception("Xml-File " + file + " not found");
}
catch (Exception ex)
{
throw new Exception("Error loading " + file + ": " + ex.Message);
}

return xDoc;
}

private static void LoadSettings(string languageFile)
{
XmlDocument xDoc = LoadXMLFile(languageFile);

var xmlNodeList = xDoc.SelectNodes(XmlLanguagenode);

if (xmlNodeList != null)
foreach (XmlNode sectionNode in xmlNodeList)
{

var strs = new Dictionary<string, Dictionary<string, string>>();

foreach (XmlNode textNode in sectionNode.ChildNodes)
{

var texts = new Dictionary<string, string>();

foreach (XmlNode txt in textNode.ChildNodes)
{
texts.Add(txt.Name, txt.InnerText);
}

if (textNode.Attributes != null) strs.Add(textNode.Attributes["key"].Value, texts);
}

if (sectionNode.Attributes != null) _stringPool.Add(sectionNode.Attributes["name"].Value, strs);
}

}

public string GetString(string section, string key, string language)
{
if (_stringPool.Count > 0)
{
Dictionary<string, Dictionary<string, string>> strs;

if (_stringPool.TryGetValue(section, out strs))
{
Dictionary<string, string> texts;

if (strs.TryGetValue(key, out texts))
{
string text;
if (setupServerLanguage == "off")
{
if (texts.TryGetValue(language, out text))
return text;
if (texts.TryGetValue(DefaultLanguage, out text))
return text;
}
else
{
if (texts.TryGetValue(setupServerLanguage, out text))
return text;
if (texts.TryGetValue(DefaultLanguage, out text))
return text;
}
}
}
}
return key; // if nothing is found return a empty string -> modify if a error message is needed.
}

public string GetString(string section, string key)
{
return GetString(section, key, DefaultLanguage);
}

#endregion

#region Send Translate Message to List
public void ToAll(string section, string key, string target, params object[] args)
{
switch (target)
{
case "ChatAndScreen":
{
Send(SendMessage.GetPlayerListChatAll(), section, key, "Chat", args);
Send(SendMessage.GetPlayerListScreenAll(), section, key, "Screen", args);
} break;
case "Chat":
{
Send(SendMessage.GetPlayerListChatAll(), section, key, target, args);
break;
}
case "Screen":
{
Send(SendMessage.GetPlayerListScreenAll(), section, key, target, args);
}
break;
}
}

public void ToArmy(string section, string key, int army, string target, params object[] args)
{
Send(SendMessage.GetPlayerListArmy(army), section, key, target, args);
}

public void ToPlayers(string section, string key, Player[] players, string target, params object[] args)
{
Send(players, section, key, target, args);
}
#endregion

#region Send
private void Send(Player[] playerList, string section, string key, string target, params object[] args)
{
Dictionary<string, List<Player>> playerLanguageDict = new Dictionary<string, List<Player>>();

foreach (Player player in playerList)
{
string languageName = player.LanguageName();
if (!playerLanguageDict.ContainsKey(languageName))
{
playerLanguageDict.Add(languageName, new List<Player>());
}
playerLanguageDict[languageName].Add(player);
}

if (playerList.Length > 0)
{
foreach (KeyValuePair<string, List<Player>> kvp in playerLanguageDict)
{
SendMessage.Send(kvp.Value.ToArray(), GetString(section, key, kvp.Key.ToString()), target, args);
}
}
}
#endregion
}

public static class SendMessage
{
#region Parameters
static readonly IGamePlay GamePlay = Strategy.THIS.GamePlay;
public static string hudON = "off";
#endregion

#region Send Message to List
public static void ToAll(string message, string target, params object[] args)
{
switch (target)
{
case "ChatAndScreen":
{
Send(GetPlayerListChatAll(), message, "Chat", args);
Send(GetPlayerListScreenAll(), message, "Screen", args);
} break;
case "Chat":
{
Send(GetPlayerListChatAll(), message, target, args);
break;
}
case "Screen":
{
Send(GetPlayerListScreenAll(), message, target, args);
}
break;
}
}

public static void ToArmy(string message, int army, string target, params object[] args)
{
Send(GetPlayerListArmy(army), message, target, args);
}

public static void ToPlayers(string message, Player[] players, string target, params object[] args)
{
Send(players, message, target, args);
}

public static void ToServer(string message, params object[] args)
{
Send(GetServer(), message, "Chat", args);
}
#endregion

#region Send
public static void Send(Player[] playerList, string message, string target, params object[] args)
{
if (playerList.Length > 0)
{
switch (target)
{
case "ChatAndScreen":
{
GamePlay.gpLogServer(playerList, message, args);
GamePlay.gpHUDLogCenter(playerList, message, args);
} break;
case "Chat":
{
GamePlay.gpLogServer(playerList, message, args);
break;
}
case "Screen":
{
GamePlay.gpHUDLogCenter(playerList, message, args);
if (hudON == "on")
{
GamePlay.gpLogServer(playerList, "[HUD]: " + message, args);
}
break;
}
}
}

}
#endregion

#region GetPlayerList
public static Player[] GetPlayerListScreenAll()
{
List<Player> players = new List<Player>();

if (GamePlay.gpPlayer() != null)
if (GamePlay.gpPlayer().Name().ToString() != "Server")
{
players.Add(GamePlay.gpPlayer());
}
if (GamePlay.gpRemotePlayers() != null)
players.AddRange(GamePlay.gpRemotePlayers());
return players.ToArray();
}

public static Player[] GetPlayerListChatAll()
{
List<Player> players = new List<Player>();

if (GamePlay.gpPlayer() != null)
players.Add(GamePlay.gpPlayer());
if (GamePlay.gpRemotePlayers() != null)
players.AddRange(GamePlay.gpRemotePlayers());
return players.ToArray();
}

public static Player[] GetPlayerListArmy(int army)
{
List<Player> players = new List<Player>();
List<Player> acceptedPlayers = new List<Player>();
if (GamePlay.gpPlayer() != null)
players.Add(GamePlay.gpPlayer());
if (GamePlay.gpRemotePlayers() != null)
players.AddRange(GamePlay.gpRemotePlayers());

if (players != null)
{
foreach (Player player in players)
{
if (player.Army() == army) acceptedPlayers.Add(player);
}
}
return acceptedPlayers.ToArray();
}

public static Player[] GetServer()
{
List<Player> players = new List<Player>();

if (GamePlay.gpPlayer() != null)
players.Add(GamePlay.gpPlayer());
/*
if (GamePlay.gpPlayer().Name().ToString() == "Server")
{
players.Add(GamePlay.gpPlayer());
}
*/
return players.ToArray();
}
#endregion
}
}

podvoxx
07-19-2012, 05:53 AM
Hello all! I made ​​a new version of the assembly, now it has become even more convenient and faster. You can use the code and files as you want and where you want to, I hope it will help you to work on missions and save your time. Good luck!

FG28_Kodiak
07-19-2012, 06:38 AM
Excellent work!

Ataros
07-19-2012, 08:51 AM
Very cool stuff! Tnx!

podvoxx
08-17-2012, 04:56 AM
I'm update dll and add new method ToServer. This method send message only for server and hoster, other players can't see this text. You can use this to test and debug your missions.

hc_wolf
08-17-2012, 05:20 AM
Nice work Podvoxx,

I will update this into my Channel Command. Great if it free's server a little

Top Job!

podvoxx
08-17-2012, 05:52 AM
Nice work Podvoxx,

I will update this into my Channel Command. Great if it free's server a little

Top Job!

Thanks to all! :)

_79_dev
08-17-2012, 10:09 PM
Nice work mate.

I have a question:
Is there a way to change colours of font while sending chat messages?

podvoxx
08-18-2012, 04:18 AM
I have a question:
Is there a way to change colours of font while sending chat messages?

No, it's impossible