corrade-vassal

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 12  →  ?path2? @ 13
File deleted
/Vassal/Vassal/AssemblyInfo.cs
/Vassal/Vassal/App.config
@@ -1,6 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="libs" />
</assemblyBinding>
<!--
You can enable only one of these settings by commenting them out.
As a quick rule: server garbage collection uses up more memory
in favor of less CPU consuption and concurrent garbage collection
uses up more CPU in favour of memory consuption.
The default is to let the runtime pick a good choice for the machine.
-->
<!--
<gcConcurrent enabled="false"/>
<gcServer enabled="true"/>
-->
</runtime>
</configuration>
/Vassal/Vassal/Properties/AssemblyInfo.cs
@@ -5,6 +5,7 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
 
[assembly: AssemblyTitle("Vassal")]
[assembly: AssemblyDescription("Linden Virtual World Land Managing Tool")]
[assembly: AssemblyConfiguration("")]
@@ -17,9 +18,11 @@
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
 
[assembly: ComVisible(false)]
 
// The following GUID is for the ID of the typelib if this project is exposed to COM
 
[assembly: Guid("4419e938-ecd5-482f-ac8b-a3d20a5e6136")]
 
// Version information for an assembly consists of the following four values:
@@ -32,5 +35,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: NeutralResourcesLanguage("en-US")]
 
[assembly: AssemblyVersion("1.2.*")]
[assembly: NeutralResourcesLanguage("en-US")]
/Vassal/Vassal/Properties/Settings.Designer.cs
@@ -8,21 +8,17 @@
// </auto-generated>
//------------------------------------------------------------------------------
 
namespace Vassal.Properties
{
 
 
namespace Vassal.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
 
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
 
public static Settings Default
{
get
{
public static Settings Default {
get {
return defaultInstance;
}
}
/Vassal/Vassal/Properties/Settings.settings
@@ -1,7 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
 
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
</SettingsFile>
/Vassal/Vassal/RegionEditForm.cs
@@ -13,6 +13,7 @@
using System.Threading;
using System.Windows.Forms;
using OpenMetaverse;
using wasSharp;
 
namespace Vassal
{
@@ -49,7 +50,7 @@
<KeyValuePair<string, Vector3>>(
File.ReadAllLines(file)
.AsParallel()
.Select(o => new List<string>(Vassal.wasCSVToEnumerable(o)))
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
@@ -136,7 +137,7 @@
.Select(o => (KeyValuePair<string, Vector3>) o.Tag))
{
streamWriter.Write(
Vassal.wasEnumerableToCSV(new[] {region.Key, region.Value.ToString()}));
CSV.FromEnumerable(new[] {region.Key, region.Value.ToString()}));
streamWriter.Write(Environment.NewLine);
}
}
@@ -165,7 +166,7 @@
Vector3 localPosition;
List<KeyValuePair<string, Vector3>> ConfiguredRegions = new List<KeyValuePair<string, Vector3>>(
File.ReadAllLines(Vassal.VASSAL_CONSTANTS.VASSAL_REGIONS)
.Select(o => new List<string>(Vassal.wasCSVToEnumerable(o)))
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
/Vassal/Vassal/SettingsForm.cs
@@ -450,9 +450,9 @@
{IsBackground = true}.Start();
 
// set parameters for Vassal
mainForm.Invoke((MethodInvoker)(() =>
mainForm.Invoke((MethodInvoker) (() =>
{
Vassal.vassalForm.Invoke((MethodInvoker)(() =>
Vassal.vassalForm.Invoke((MethodInvoker) (() =>
{
if (string.IsNullOrEmpty(Vassal.vassalForm.RegionRestartDelayBox.Text))
{
/Vassal/Vassal/Vassal.cs
@@ -5,20 +5,17 @@
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace Vassal
{
static class Program
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
@@ -25,4 +22,4 @@
Application.Run(new Vassal());
}
}
}
}
/Vassal/Vassal/Vassal.csproj
@@ -77,6 +77,9 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="wasSharp">
<HintPath>..\..\wasSharp\bin\Release\wasSharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="RegionEditForm.cs">
@@ -99,7 +102,7 @@
<DependentUpon>VassalForm.cs</DependentUpon>
</Compile>
<Compile Include="Vassal.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="RegionEditForm.resx">
<DependentUpon>RegionEditForm.cs</DependentUpon>
</EmbeddedResource>
/Vassal/Vassal/Vassal.exe.config
@@ -1,10 +1,10 @@
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="libs"/>
<probing privatePath="libs" />
</assemblyBinding>
<!--
You can enable only one of these settings by commenting them out.
/Vassal/Vassal/VassalConfiguration.cs
@@ -10,7 +10,6 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
 
namespace Vassal
@@ -20,27 +19,13 @@
/// </summary>
public enum Filter : uint
{
[XmlEnum(Name = "none")]
[Description("none")]
NONE = 0,
[XmlEnum(Name = "RFC1738")]
[Description("RFC1738")]
RFC1738,
[XmlEnum(Name = "RFC3986")]
[Description("RFC3986")]
RFC3986,
[XmlEnum(Name = "ENIGMA")]
[Description("ENIGMA")]
ENIGMA,
[XmlEnum(Name = "VIGENERE")]
[Description("VIGENERE")]
VIGENERE,
[XmlEnum(Name = "ATBASH")]
[Description("ATBASH")]
ATBASH,
[XmlEnum(Name = "BASE64")]
[Description("BASE64")]
BASE64
[XmlEnum(Name = "none")] [Description("none")] NONE = 0,
[XmlEnum(Name = "RFC1738")] [Description("RFC1738")] RFC1738,
[XmlEnum(Name = "RFC3986")] [Description("RFC3986")] RFC3986,
[XmlEnum(Name = "ENIGMA")] [Description("ENIGMA")] ENIGMA,
[XmlEnum(Name = "VIGENERE")] [Description("VIGENERE")] VIGENERE,
[XmlEnum(Name = "ATBASH")] [Description("ATBASH")] ATBASH,
[XmlEnum(Name = "BASE64")] [Description("BASE64")] BASE64
}
 
/// <summary>
@@ -52,28 +37,28 @@
public char reflector;
public char[] rotors;
}
 
[Serializable]
public class VassalConfiguration
{
private static readonly object VassalConfigurationLock = new object();
private uint _dataTimeout = 15000;
 
private string _HTTPServerURL = @"http://127.0.0.1:8080/";
private string _group = string.Empty;
private string _password = string.Empty;
 
private ENIGMA _enigma = new ENIGMA
{
rotors = new[] { '3', 'g', '1' },
plugs = new[] { 'z', 'p', 'q' },
rotors = new[] {'3', 'g', '1'},
plugs = new[] {'z', 'p', 'q'},
reflector = 'b'
};
 
private string _group = string.Empty;
private string _HTTPServerURL = @"http://127.0.0.1:8080/";
private List<Filter> _inputFilters = new List<Filter>();
private List<Filter> _outputFilters = new List<Filter>();
private string _password = string.Empty;
private uint _regionRestartDelay = 120;
private uint _teleportTimeout = 30000;
private string _vigenereSecret = string.Empty;
private uint _teleportTimeout = 30000;
private uint _dataTimeout = 15000;
private uint _regionRestartDelay = 120;
 
public string Group
{
@@ -153,7 +138,7 @@
{
lock (VassalConfigurationLock)
{
return !_inputFilters.Any() ? new List<Filter> { Filter.RFC1738 } : _inputFilters;
return !_inputFilters.Any() ? new List<Filter> {Filter.RFC1738} : _inputFilters;
}
}
set
@@ -171,7 +156,7 @@
{
lock (VassalConfigurationLock)
{
return !_outputFilters.Any() ? new List<Filter> { Filter.RFC1738 } : _outputFilters;
return !_outputFilters.Any() ? new List<Filter> {Filter.RFC1738} : _outputFilters;
}
}
set
@@ -261,7 +246,7 @@
{
using (StreamWriter writer = new StreamWriter(file, false, Encoding.UTF8))
{
XmlSerializer serializer = new XmlSerializer(typeof(VassalConfiguration));
XmlSerializer serializer = new XmlSerializer(typeof (VassalConfiguration));
serializer.Serialize(writer, configuration);
//writer.Flush();
}
@@ -275,10 +260,10 @@
using (StreamReader stream = new StreamReader(file, Encoding.UTF8))
{
XmlSerializer serializer =
new XmlSerializer(typeof(VassalConfiguration));
configuration = (VassalConfiguration)serializer.Deserialize(stream);
new XmlSerializer(typeof (VassalConfiguration));
configuration = (VassalConfiguration) serializer.Deserialize(stream);
}
}
}
}
}
}
/Vassal/Vassal/VassalForm.cs
@@ -17,9 +17,9 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using OpenMetaverse;
using wasSharp;
using Parallel = System.Threading.Tasks.Parallel;
using Timer = System.Timers.Timer;
 
@@ -52,21 +52,21 @@
switch (filter)
{
case Filter.RFC1738:
o = wasURLUnescapeDataString(o);
o = Web.URLUnescapeDataString(o);
break;
case Filter.RFC3986:
o = wasURIUnescapeDataString(o);
o = Web.URIUnescapeDataString(o);
break;
case Filter.ENIGMA:
o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
o = Cryptography.ENIGMA(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
vassalConfiguration.ENIGMA.plugs.ToArray(),
vassalConfiguration.ENIGMA.reflector);
break;
case Filter.VIGENERE:
o = wasDecryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
o = Cryptography.DecryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
break;
case Filter.ATBASH:
o = wasATBASH(o);
o = Cryptography.ATBASH(o);
break;
case Filter.BASE64:
o = Encoding.UTF8.GetString(Convert.FromBase64String(o));
@@ -88,21 +88,21 @@
switch (filter)
{
case Filter.RFC1738:
o = wasURLEscapeDataString(o);
o = Web.URLEscapeDataString(o);
break;
case Filter.RFC3986:
o = wasURIEscapeDataString(o);
o = Web.URIEscapeDataString(o);
break;
case Filter.ENIGMA:
o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
o = Cryptography.ENIGMA(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
vassalConfiguration.ENIGMA.plugs.ToArray(),
vassalConfiguration.ENIGMA.reflector);
break;
case Filter.VIGENERE:
o = wasEncryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
o = Cryptography.EncryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
break;
case Filter.ATBASH:
o = wasATBASH(o);
o = Cryptography.ATBASH(o);
break;
case Filter.BASE64:
o = Convert.ToBase64String(Encoding.UTF8.GetBytes(o));
@@ -117,16 +117,16 @@
try
{
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "Name"}
}), 60000);
}, wasOutput), 60000);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.BeginInvoke(
(MethodInvoker)
@@ -141,7 +141,7 @@
vassalForm.CurrentRegionAt.Visible = true;
vassalForm.CurrentRegionName.Visible = true;
vassalForm.CurrentRegionName.Text =
wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).Last();
CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).Last();
}));
break;
default:
@@ -150,7 +150,7 @@
vassalForm.CurrentRegionAt.Visible = false;
vassalForm.CurrentRegionName.Visible = false;
vassalForm.StatusText.Text = @"Error getting current region: " +
wasInput(wasKeyValueGet("error", result));
wasInput(KeyValue.Get("error", result));
}));
break;
}
@@ -173,227 +173,9 @@
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
private static double wasMapValueToRange(double value, double xMin, double xMax, double yMin, double yMax)
{
return yMin + (
(
yMax - yMin
)
*
(
value - xMin
)
/
(
xMax - xMin
)
);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC1738 URL Escapes a string</summary>
/// <param name="data">a string to escape</param>
/// <returns>an RFC1738 escaped string</returns>
private static string wasURLEscapeDataString(string data)
{
return HttpUtility.UrlEncode(data);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC1738 URL Unescape a string</summary>
/// <param name="data">a string to unescape</param>
/// <returns>an RFC1738 unescaped string</returns>
private static string wasURLUnescapeDataString(string data)
{
return HttpUtility.UrlDecode(data);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>URI unescapes an RFC3986 URI escaped string</summary>
/// <param name="data">a string to unescape</param>
/// <returns>the resulting string</returns>
private static string wasURIUnescapeDataString(string data)
{
// Uri.UnescapeDataString can only handle 32766 characters at a time
return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
.Select(o => Uri.UnescapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC3986 URI Escapes a string</summary>
/// <param name="data">a string to escape</param>
/// <returns>an RFC3986 escaped string</returns>
private static string wasURIEscapeDataString(string data)
{
// Uri.EscapeDataString can only handle 32766 characters at a time
return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
.Select(o => Uri.EscapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets an array element at a given modulo index.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="index">a positive or negative index of the element</param>
/// <param name="data">the array</param>
/// <return>an array element</return>
public static T wasGetElementAt<T>(T[] data, int index)
{
switch (index < 0)
{
case true:
return data[((index%data.Length) + data.Length)%data.Length];
default:
return data[index%data.Length];
}
}
 
#region KEY-VALUE DATA
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns the value of a key from a key-value data string.
/// </summary>
/// <param name="key">the key of the value</param>
/// <param name="data">the key-value data segment</param>
/// <returns>true if the key was found in data</returns>
private static string wasKeyValueGet(string key, string data)
{
return data.Split('&')
.AsParallel()
.Select(o => o.Split('=').ToList())
.Where(o => o.Count.Equals(2))
.Select(o => new
{
k = o.First(),
v = o.Last()
})
.Where(o => o.k.Equals(key))
.Select(o => o.v)
.FirstOrDefault();
}
 
#endregion
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>Escapes a dictionary's keys and values for sending as POST data.</summary>
/// <param name="data">A dictionary containing keys and values to be escaped</param>
private static Dictionary<string, string> wasKeyValueEscape(Dictionary<string, string> data)
{
return data.AsParallel().ToDictionary(o => wasOutput(o.Key), p => wasOutput(p.Value));
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Converts a list of string to a comma-separated values string.
/// </summary>
/// <param name="l">a list of strings</param>
/// <returns>a commma-separated list of values</returns>
/// <remarks>compliant with RFC 4180</remarks>
public static string wasEnumerableToCSV(IEnumerable<string> l)
{
string[] csv = l.Select(o => o.Clone() as string).ToArray();
Parallel.ForEach(csv.Select((v, i) => new {i, v}), o =>
{
string cell = o.v.Replace("\"", "\"\"");
switch (new[] {'"', ' ', ',', '\r', '\n'}.Any(p => cell.Contains(p)))
{
case true:
csv[o.i] = "\"" + cell + "\"";
break;
default:
csv[o.i] = cell;
break;
}
});
return string.Join(",", csv);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Converts a comma-separated list of values to a list of strings.
/// </summary>
/// <param name="csv">a comma-separated list of values</param>
/// <returns>a list of strings</returns>
/// <remarks>compliant with RFC 4180</remarks>
public static IEnumerable<string> wasCSVToEnumerable(string csv)
{
Stack<char> s = new Stack<char>();
StringBuilder m = new StringBuilder();
for (int i = 0; i < csv.Length; ++i)
{
switch (csv[i])
{
case ',':
if (!s.Any() || !s.Peek().Equals('"'))
{
yield return m.ToString();
m = new StringBuilder();
continue;
}
m.Append(csv[i]);
continue;
case '"':
if (i + 1 < csv.Length && csv[i].Equals(csv[i + 1]))
{
m.Append(csv[i]);
++i;
continue;
}
if (!s.Any() || !s.Peek().Equals(csv[i]))
{
s.Push(csv[i]);
continue;
}
s.Pop();
continue;
}
m.Append(csv[i]);
}
 
yield return m.ToString();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Serialises a dictionary to key-value data.
/// </summary>
/// <param name="data">a dictionary</param>
/// <returns>a key-value data encoded string</returns>
private static string wasKeyValueEncode(Dictionary<string, string> data)
{
return string.Join("&", data.AsParallel().Select(o => string.Join("=", o.Key, o.Value)));
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Sends a post request to an URL with set key-value pairs.
/// </summary>
/// <param name="URL">the url to send the message to</param>
@@ -429,7 +211,7 @@
{
using (StreamWriter dataStream = new StreamWriter(requestStream))
{
dataStream.Write(wasKeyValueEncode(message));
dataStream.Write(KeyValue.Encode(message));
}
}
// read response
@@ -523,7 +305,7 @@
new Thread(() =>
{
result = wasInput(wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
@@ -531,12 +313,12 @@
{"region", selectedRegionName},
{"position", selectedRegionPosition.ToString()},
{"fly", "True"}
}), vassalConfiguration.TeleportTimeout));
}, wasOutput), vassalConfiguration.TeleportTimeout));
receivedPOST.Set();
}) {IsBackground = true}.Start();
receivedPOST.WaitOne((int) vassalConfiguration.TeleportTimeout, false);
teleportTimer.Stop();
switch (!string.IsNullOrEmpty(result) && wasKeyValueGet("success", result) == "True")
switch (!string.IsNullOrEmpty(result) && KeyValue.Get("success", result) == "True")
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
@@ -553,7 +335,7 @@
{
vassalForm.StatusText.Text = @"Failed teleporting to " + selectedRegionName +
@": " +
wasKeyValueGet("error", result);
KeyValue.Get("error", result);
}));
break;
default:
@@ -693,7 +475,7 @@
Vector3 localPosition;
List<KeyValuePair<string, Vector3>> ConfiguredRegions = new List<KeyValuePair<string, Vector3>>(
File.ReadAllLines(VASSAL_CONSTANTS.VASSAL_REGIONS)
.Select(o => new List<string>(wasCSVToEnumerable(o)))
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
@@ -780,26 +562,26 @@
{
// Get the simulator name and if we are an estate manager.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{
"data", wasEnumerableToCSV(new[]
"data", CSV.FromEnumerable(new[]
{
"Name",
"IsEstateManager"
})
}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (data.Count.Equals(0))
throw new Exception();
 
@@ -887,13 +669,13 @@
stopWatch.Start();
// Get the statistics.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{
"data", wasEnumerableToCSV(new[]
"data", CSV.FromEnumerable(new[]
{
"Agents",
"LastLag",
@@ -910,15 +692,15 @@
"AvatarPositions"
})
}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
stopWatch.Stop();
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (data.Count.Equals(0))
throw new Exception();
 
@@ -973,23 +755,23 @@
 
// Get the map image.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getgridregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "MapImageID"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception();
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
@@ -997,11 +779,11 @@
{"item", data.Last()},
{"type", "Texture"},
{"format", "Jpeg"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
Image mapImage;
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
@@ -1063,7 +845,7 @@
 
// Get the region status.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getgridregiondata"},
{"group", vassalConfiguration.Group},
@@ -1070,14 +852,14 @@
{"password", vassalConfiguration.Password},
{"region", regionName},
{"data", "Access"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception();
 
@@ -1144,21 +926,21 @@
{
// Get the top scripts.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiontop"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", "scripts"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
HashSet<List<string>> data =
new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/5)
.Select(x => x.Select(v => v.Value).ToList()));
@@ -1204,19 +986,19 @@
 
// Get the top colliders.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiontop"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", "colliders"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
data = new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
data = new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/5)
.Select(x => x.Select(v => v.Value).ToList()));
@@ -1288,21 +1070,21 @@
{
// Get the avatar positions.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getavatarpositions"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"entity", "region"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
HashSet<List<string>> data =
new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/3)
.Select(x => x.Select(v => v.Value).ToList()));
@@ -1370,19 +1152,19 @@
{
// Get the region terrain texture UUIDs.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregionterraintextures"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
 
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(4))
throw new Exception();
 
@@ -1413,7 +1195,7 @@
Parallel.ForEach(Enumerable.Range(0, 4), i =>
{
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
@@ -1421,13 +1203,13 @@
{"item", data[i]},
{"type", "Texture"},
{"format", "Jpeg"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
return;
 
byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
groundTextureImages[i] = Image.FromStream(memoryStream);
@@ -1503,7 +1285,7 @@
{
foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows)
{
streamWriter.WriteLine(wasEnumerableToCSV(new[]
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
topScriptsRow.Cells["TopScriptsScore"].Value.ToString(),
topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString(),
@@ -1550,7 +1332,7 @@
{
foreach (DataGridViewRow topCollidersRow in TopCollidersGridView.Rows)
{
streamWriter.WriteLine(wasEnumerableToCSV(new[]
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
topCollidersRow.Cells["TopCollidersScore"].Value.ToString(),
topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString(),
@@ -1694,7 +1476,7 @@
 
// Teleport to the object.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
@@ -1702,7 +1484,7 @@
{"position", objectData.Value.ToString()},
{"region", currentRegionName},
{"fly", "True"}
}), vassalConfiguration.TeleportTimeout);
}, wasOutput), vassalConfiguration.TeleportTimeout);
 
if (string.IsNullOrEmpty(result))
{
@@ -1714,7 +1496,7 @@
 
// Return the object.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "derez"},
{"group", vassalConfiguration.Group},
@@ -1722,7 +1504,7 @@
{"item", objectData.Key.ToString()},
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half
{"type", "ReturnToOwner"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
{
@@ -1733,7 +1515,7 @@
}
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
@@ -1763,7 +1545,7 @@
{
vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
@": " +
wasInput(wasKeyValueGet("error", result));
wasInput(KeyValue.Get("error", result));
}));
break;
}
@@ -1856,7 +1638,7 @@
 
// Teleport to the object.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
@@ -1864,7 +1646,7 @@
{"position", objectData.Value.ToString()},
{"region", currentRegionName},
{"fly", "True"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
{
@@ -1876,7 +1658,7 @@
 
// Return the object.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "derez"},
{"group", vassalConfiguration.Group},
@@ -1884,7 +1666,7 @@
{"item", objectData.Key.ToString()},
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half
{"type", "ReturnToOwner"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
{
@@ -1895,7 +1677,7 @@
}
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
@@ -1925,7 +1707,7 @@
{
vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
@": " +
wasInput(wasKeyValueGet("error", result));
wasInput(KeyValue.Get("error", result));
}));
break;
}
@@ -2042,7 +1824,7 @@
 
// Teleport to the region.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
@@ -2050,7 +1832,7 @@
{"position", restartRegionData.Value.ToString()},
{"region", restartRegionData.Key},
{"fly", "True"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
{
@@ -2062,7 +1844,7 @@
}));
continue;
}
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
@@ -2084,7 +1866,7 @@
// then we are on the same region so no need to retry.
uint status; //37559
switch (
uint.TryParse(wasInput(wasKeyValueGet("status", result)), out status) &&
uint.TryParse(wasInput(KeyValue.Get("status", result)), out status) &&
status.Equals(37559))
{
case true: // We are on the region already!
@@ -2107,24 +1889,24 @@
throw new Exception("Failed to teleport to region.");
 
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "IsEstateManager"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
throw new Exception("Could not retrieve estate rights.");
 
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception("Could not retrieve estate rights.");
 
@@ -2135,7 +1917,7 @@
{
case true: // we are an estate manager
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "restartregion"},
{"group", vassalConfiguration.Group},
@@ -2145,12 +1927,12 @@
"delay",
vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture)
}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -2306,7 +2088,7 @@
 
// Ban the resident.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -2315,13 +2097,13 @@
{"action", "add"},
{"agent", agentUUID.ToString()},
{"all", alsoBan.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
switch (success)
@@ -2396,19 +2178,19 @@
{
// Get the map heights.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getterrainheight"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"entity", "region"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -2415,7 +2197,7 @@
throw new Exception("Could not get terrain heights.");
 
List<double> heights = new List<double>();
foreach (string map in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))))
foreach (string map in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))))
{
double height;
if (!double.TryParse(map, out height))
@@ -2434,7 +2216,8 @@
{
bitmap.SetPixel(x, 256 - y,
Color.FromArgb(
Math.Max((int) wasMapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0),
Math.Max(
(int) Numerics.MapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0),
0, 0));
}
}
@@ -2508,25 +2291,25 @@
{
// Download the terrain.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "terrain"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"action", "get"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
throw new Exception("Could not download terrain.");
 
byte[] data = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
byte[] data = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
 
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
@@ -2611,7 +2394,7 @@
 
// Upload the terrain.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "terrain"},
{"group", vassalConfiguration.Group},
@@ -2618,13 +2401,13 @@
{"password", vassalConfiguration.Password},
{"action", "set"},
{"data", Convert.ToBase64String(data)}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -2745,19 +2528,19 @@
 
// Get the selected estate list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -2764,7 +2547,7 @@
throw new Exception("Could not retrieve estate list.");
 
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
@@ -2875,7 +2658,7 @@
 
// Remove the agent or group from the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -2883,13 +2666,13 @@
{"type", selectedEstateListType},
{"action", "remove"},
{selectedEstateListType.Equals("group") ? "target" : "agent", memberUUID.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3003,7 +2786,7 @@
 
// Add the resident to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -3012,13 +2795,13 @@
{"action", "add"},
{"firstname", firstName},
{"lastname", lastName}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3026,18 +2809,18 @@
 
// Retrieve the estate list for updates.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -3044,7 +2827,7 @@
throw new Exception("Could not retrieve estate list.");
 
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
@@ -3129,7 +2912,7 @@
 
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -3137,13 +2920,13 @@
{"type", selectedEstateListType},
{"action", "add"},
{"target", target}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3151,18 +2934,18 @@
 
// Retrieve the estate list for updates.
result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -3169,7 +2952,7 @@
throw new Exception("Could not retrieve estate list.");
 
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
@@ -3224,7 +3007,7 @@
 
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregiondebug"},
{"group", vassalConfiguration.Group},
@@ -3232,13 +3015,13 @@
{"scripts", scripts.ToString()},
{"collisions", collisons.ToString()},
{"physics", physics.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3326,7 +3109,7 @@
 
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregioninfo"},
{"group", vassalConfiguration.Group},
@@ -3340,13 +3123,13 @@
{"mature", mature.ToString()},
{"limit", agentLimit.ToString(Utils.EnUsCulture)},
{"bonus", objectBonus.ToString(Utils.EnUsCulture)}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3439,19 +3222,19 @@
 
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregionterraintextures"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", wasEnumerableToCSV(groundTextureUUIDs.Select(o => o.ToString()))}
}), vassalConfiguration.DataTimeout);
{"data", CSV.FromEnumerable(groundTextureUUIDs.Select(o => o.ToString()))}
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3540,7 +3323,7 @@
Monitor.Enter(ClientInstanceTeleportLock);
 
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
@@ -3548,16 +3331,16 @@
{"item", textureUUID.ToString()},
{"type", "Texture"},
{"format", "Png"}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
Image mapImage;
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
@@ -3660,7 +3443,7 @@
foreach (KeyValuePair<string, UUID> target in
File.ReadAllLines(file)
.AsParallel()
.Select(o => new List<string>(wasCSVToEnumerable(o)))
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
@@ -3727,7 +3510,7 @@
{
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -3735,13 +3518,13 @@
{"type", selectedEstateListType},
{"action", "add"},
{"target", target.Value.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3759,19 +3542,19 @@
{
// Retrieve the estate list for updates.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -3778,7 +3561,7 @@
throw new Exception("Could not retrieve estate list.");
 
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
@@ -3853,7 +3636,7 @@
foreach (KeyValuePair<string, UUID> target in
File.ReadAllLines(file)
.AsParallel()
.Select(o => new List<string>(wasCSVToEnumerable(o)))
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
@@ -3920,7 +3703,7 @@
{
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
@@ -3928,13 +3711,13 @@
{"type", selectedEstateListType},
{"action", "add"},
{"agent", target.Value.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -3952,19 +3735,19 @@
{
// Retrieve the estate list for updates.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
if (!success)
@@ -3971,7 +3754,7 @@
throw new Exception("Could not retrieve estate list.");
 
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
@@ -4025,7 +3808,7 @@
{
foreach (DataGridViewRow estateListRow in EstateListGridView.Rows)
{
streamWriter.WriteLine(wasEnumerableToCSV(new[]
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
estateListRow.Cells["EstateListName"].Value.ToString(),
estateListRow.Cells["EstateListUUID"].Value.ToString()
@@ -4112,19 +3895,19 @@
{
// Teleport the user home.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "estateteleportusershome"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"avatars", agentUUID.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
 
switch (success)
@@ -4254,7 +4037,7 @@
 
// Set the terrain variables.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
wasKeyValueEscape(new Dictionary<string, string>
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregionterrainvariables"},
{"group", vassalConfiguration.Group},
@@ -4265,13 +4048,13 @@
{"useestatesun", useEstateSun.ToString()},
{"fixedsun", fixedSun.ToString()},
{"sunposition", sunPosition.ToString()}
}), vassalConfiguration.DataTimeout);
}, wasOutput), vassalConfiguration.DataTimeout);
 
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
 
bool success;
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
 
if (!success)
@@ -4562,489 +4345,6 @@
 
#region CRYPTOGRAPHY
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets a sub-array from an array.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array slice between start and stop</returns>
public static T[] wasGetSubArray<T>(T[] data, int start, int stop)
{
if (stop.Equals(-1))
stop = data.Length - 1;
T[] result = new T[stop - start + 1];
Array.Copy(data, start, result, 0, stop - start + 1);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Delete a sub-array and return the result.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array without elements between start and stop</returns>
public static T[] wasDeleteSubArray<T>(T[] data, int start, int stop)
{
if (stop.Equals(-1))
stop = data.Length - 1;
T[] result = new T[data.Length - (stop - start) - 1];
Array.Copy(data, 0, result, 0, start);
Array.Copy(data, stop + 1, result, start, data.Length - stop - 1);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Concatenate multiple arrays.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="arrays">multiple arrays</param>
/// <returns>a flat array with all arrays concatenated</returns>
public static T[] wasConcatenateArrays<T>(params T[][] arrays)
{
int resultLength = 0;
foreach (T[] o in arrays)
{
resultLength += o.Length;
}
T[] result = new T[resultLength];
int offset = 0;
for (int x = 0; x < arrays.Length; x++)
{
arrays[x].CopyTo(result, offset);
offset += arrays[x].Length;
}
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Permutes an array in reverse a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
private static T[] wasReversePermuteArrayElements<T>(T[] input, int times)
{
if (times.Equals(0)) return input;
T[] slice = new T[input.Length];
Array.Copy(input, 1, slice, 0, input.Length - 1);
Array.Copy(input, 0, slice, input.Length - 1, 1);
return wasReversePermuteArrayElements(slice, --times);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Permutes an array forward a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
private static T[] wasForwardPermuteArrayElements<T>(T[] input, int times)
{
if (times.Equals(0)) return input;
T[] slice = new T[input.Length];
Array.Copy(input, input.Length - 1, slice, 0, 1);
Array.Copy(input, 0, slice, 1, input.Length - 1);
return wasForwardPermuteArrayElements(slice, --times);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Encrypt or decrypt a message given a set of rotors, plugs and a reflector.
/// </summary>
/// <param name="message">the message to encyrpt or decrypt</param>
/// <param name="rotors">any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g</param>
/// <param name="plugs">the letter representing the start character for the rotor</param>
/// <param name="reflector">any one of: B, b, C, c</param>
/// <returns>either a decrypted or encrypted string</returns>
private static string wasEnigma(string message, char[] rotors, char[] plugs, char reflector)
{
Dictionary<char, char[]> def_rotors = new Dictionary<char, char[]>
{
{
'1', new[]
{
'e', 'k', 'm', 'f', 'l',
'g', 'd', 'q', 'v', 'z',
'n', 't', 'o', 'w', 'y',
'h', 'x', 'u', 's', 'p',
'a', 'i', 'b', 'r', 'c',
'j'
}
},
{
'2', new[]
{
'a', 'j', 'd', 'k', 's',
'i', 'r', 'u', 'x', 'b',
'l', 'h', 'w', 't', 'm',
'c', 'q', 'g', 'z', 'n',
'p', 'y', 'f', 'v', 'o',
'e'
}
},
{
'3', new[]
{
'b', 'd', 'f', 'h', 'j',
'l', 'c', 'p', 'r', 't',
'x', 'v', 'z', 'n', 'y',
'e', 'i', 'w', 'g', 'a',
'k', 'm', 'u', 's', 'q',
'o'
}
},
{
'4', new[]
{
'e', 's', 'o', 'v', 'p',
'z', 'j', 'a', 'y', 'q',
'u', 'i', 'r', 'h', 'x',
'l', 'n', 'f', 't', 'g',
'k', 'd', 'c', 'm', 'w',
'b'
}
},
{
'5', new[]
{
'v', 'z', 'b', 'r', 'g',
'i', 't', 'y', 'u', 'p',
's', 'd', 'n', 'h', 'l',
'x', 'a', 'w', 'm', 'j',
'q', 'o', 'f', 'e', 'c',
'k'
}
},
{
'6', new[]
{
'j', 'p', 'g', 'v', 'o',
'u', 'm', 'f', 'y', 'q',
'b', 'e', 'n', 'h', 'z',
'r', 'd', 'k', 'a', 's',
'x', 'l', 'i', 'c', 't',
'w'
}
},
{
'7', new[]
{
'n', 'z', 'j', 'h', 'g',
'r', 'c', 'x', 'm', 'y',
's', 'w', 'b', 'o', 'u',
'f', 'a', 'i', 'v', 'l',
'p', 'e', 'k', 'q', 'd',
't'
}
},
{
'8', new[]
{
'f', 'k', 'q', 'h', 't',
'l', 'x', 'o', 'c', 'b',
'j', 's', 'p', 'd', 'z',
'r', 'a', 'm', 'e', 'w',
'n', 'i', 'u', 'y', 'g',
'v'
}
},
{
'b', new[]
{
'l', 'e', 'y', 'j', 'v',
'c', 'n', 'i', 'x', 'w',
'p', 'b', 'q', 'm', 'd',
'r', 't', 'a', 'k', 'z',
'g', 'f', 'u', 'h', 'o',
's'
}
},
{
'g', new[]
{
'f', 's', 'o', 'k', 'a',
'n', 'u', 'e', 'r', 'h',
'm', 'b', 't', 'i', 'y',
'c', 'w', 'l', 'q', 'p',
'z', 'x', 'v', 'g', 'j',
'd'
}
}
};
 
Dictionary<char, char[]> def_reflectors = new Dictionary<char, char[]>
{
{
'B', new[]
{
'a', 'y', 'b', 'r', 'c', 'u', 'd', 'h',
'e', 'q', 'f', 's', 'g', 'l', 'i', 'p',
'j', 'x', 'k', 'n', 'm', 'o', 't', 'z',
'v', 'w'
}
},
{
'b', new[]
{
'a', 'e', 'b', 'n', 'c', 'k', 'd', 'q',
'f', 'u', 'g', 'y', 'h', 'w', 'i', 'j',
'l', 'o', 'm', 'p', 'r', 'x', 's', 'z',
't', 'v'
}
},
{
'C', new[]
{
'a', 'f', 'b', 'v', 'c', 'p', 'd', 'j',
'e', 'i', 'g', 'o', 'h', 'y', 'k', 'r',
'l', 'z', 'm', 'x', 'n', 'w', 't', 'q',
's', 'u'
}
},
{
'c', new[]
{
'a', 'r', 'b', 'd', 'c', 'o', 'e', 'j',
'f', 'n', 'g', 't', 'h', 'k', 'i', 'v',
'l', 'm', 'p', 'w', 'q', 'z', 's', 'x',
'u', 'y'
}
}
};
 
// Setup rotors from plugs.
foreach (char rotor in rotors)
{
char plug = plugs[Array.IndexOf(rotors, rotor)];
int i = Array.IndexOf(def_rotors[rotor], plug);
if (i.Equals(0)) continue;
def_rotors[rotor] = wasConcatenateArrays(new[] {plug},
wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i, i), i, -1),
wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i + 1, -1), 0, i - 1));
}
 
StringBuilder result = new StringBuilder();
foreach (char c in message)
{
if (!char.IsLetter(c))
{
result.Append(c);
continue;
}
 
// Normalize to lower.
char l = char.ToLower(c);
 
Action<char[]> rotate = o =>
{
int i = o.Length - 1;
do
{
def_rotors[o[0]] = wasForwardPermuteArrayElements(def_rotors[o[0]], 1);
if (i.Equals(0))
{
rotors = wasReversePermuteArrayElements(o, 1);
continue;
}
l = wasGetElementAt(def_rotors[o[1]], Array.IndexOf(def_rotors[o[0]], l) - 1);
o = wasReversePermuteArrayElements(o, 1);
} while (--i > -1);
};
 
// Forward pass through the Enigma's rotors.
rotate.Invoke(rotors);
 
// Reflect
int x = Array.IndexOf(def_reflectors[reflector], l);
l = (x + 1)%2 == 0 ? def_reflectors[reflector][x - 1] : def_reflectors[reflector][x + 1];
 
// Reverse the order of the rotors.
Array.Reverse(rotors);
 
// Reverse pass through the Enigma's rotors.
rotate.Invoke(rotors);
 
if (char.IsUpper(c))
{
l = char.ToUpper(l);
}
result.Append(l);
}
 
return result.ToString();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Expand the VIGENRE key to the length of the input.
/// </summary>
/// <param name="input">the input to expand to</param>
/// <param name="enc_key">the key to expand</param>
/// <returns>the expanded key</returns>
private static string wasVigenereExpandKey(string input, string enc_key)
{
string exp_key = string.Empty;
int i = 0, j = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
exp_key += p;
++i;
continue;
}
int m = j%enc_key.Length;
exp_key += enc_key[m];
++j;
++i;
} while (i < input.Length);
return exp_key;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Encrypt using VIGENERE.
/// </summary>
/// <param name="input">the input to encrypt</param>
/// <param name="enc_key">the key to encrypt with</param>
/// <returns>the encrypted input</returns>
private static string wasEncryptVIGENERE(string input, string enc_key)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
enc_key = wasVigenereExpandKey(input, enc_key);
string result = string.Empty;
int i = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
result += p;
++i;
continue;
}
char q =
wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i]))[
Array.IndexOf(a, char.ToLowerInvariant(p))];
if (char.IsUpper(p))
{
q = char.ToUpperInvariant(q);
}
result += q;
++i;
} while (i < input.Length);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Decrypt using VIGENERE.
/// </summary>
/// <param name="input">the input to decrypt</param>
/// <param name="enc_key">the key to decrypt with</param>
/// <returns>the decrypted input</returns>
private static string wasDecryptVIGENERE(string input, string enc_key)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
enc_key = wasVigenereExpandKey(input, enc_key);
string result = string.Empty;
int i = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
result += p;
++i;
continue;
}
char q =
a[
Array.IndexOf(wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i])),
char.ToLowerInvariant(p))];
if (char.IsUpper(p))
{
q = char.ToUpperInvariant(q);
}
result += q;
++i;
} while (i < input.Length);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// An implementation of the ATBASH cypher for latin alphabets.
/// </summary>
/// <param name="data">the data to encrypt or decrypt</param>
/// <returns>the encrypted or decrypted data</returns>
private static string wasATBASH(string data)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
char[] input = data.ToArray();
 
Parallel.ForEach(Enumerable.Range(0, data.Length), i =>
{
char e = input[i];
if (!char.IsLetter(e)) return;
int x = 25 - Array.BinarySearch(a, char.ToLowerInvariant(e));
if (!char.IsUpper(e))
{
input[i] = a[x];
return;
}
input[i] = char.ToUpperInvariant(a[x]);
});
 
return new string(input);
}
 
#endregion
}
}
/Vassal/Vassal.sln
@@ -4,7 +4,12 @@
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vassal", "Vassal\Vassal.csproj", "{4419E938-ECD5-482F-AC8B-A3D20A5E6136}"
ProjectSection(ProjectDependencies) = postProject
{A971E1C9-776C-4CD2-88AC-71197C7B955E} = {A971E1C9-776C-4CD2-88AC-71197C7B955E}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wasSharp", "..\wasSharp\wasSharp.csproj", "{A971E1C9-776C-4CD2-88AC-71197C7B955E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +20,10 @@
{4419E938-ECD5-482F-AC8B-A3D20A5E6136}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4419E938-ECD5-482F-AC8B-A3D20A5E6136}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4419E938-ECD5-482F-AC8B-A3D20A5E6136}.Release|Any CPU.Build.0 = Release|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
/wasSharp/Arrays.cs
@@ -0,0 +1,139 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
 
namespace wasSharp
{
public class Arrays
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets an array element at a given modulo index.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="index">a positive or negative index of the element</param>
/// <param name="data">the array</param>
/// <return>an array element</return>
public static T GetElementAt<T>(T[] data, int index)
{
switch (index < 0)
{
case true:
return data[((index%data.Length) + data.Length)%data.Length];
default:
return data[index%data.Length];
}
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets a sub-array from an array.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array slice between start and stop</returns>
public static T[] GetSubArray<T>(T[] data, int start, int stop)
{
if (stop.Equals(-1))
stop = data.Length - 1;
T[] result = new T[stop - start + 1];
Array.Copy(data, start, result, 0, stop - start + 1);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Delete a sub-array and return the result.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="data">the array</param>
/// <param name="start">the start index</param>
/// <param name="stop">the stop index (-1 denotes the end)</param>
/// <returns>the array without elements between start and stop</returns>
public static T[] DeleteSubArray<T>(T[] data, int start, int stop)
{
if (stop.Equals(-1))
stop = data.Length - 1;
T[] result = new T[data.Length - (stop - start) - 1];
Array.Copy(data, 0, result, 0, start);
Array.Copy(data, stop + 1, result, start, data.Length - stop - 1);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Concatenate multiple arrays.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="arrays">multiple arrays</param>
/// <returns>a flat array with all arrays concatenated</returns>
public static T[] ConcatenateArrays<T>(params T[][] arrays)
{
int resultLength = 0;
foreach (T[] o in arrays)
{
resultLength += o.Length;
}
T[] result = new T[resultLength];
int offset = 0;
for (int x = 0; x < arrays.Length; x++)
{
arrays[x].CopyTo(result, offset);
offset += arrays[x].Length;
}
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Permutes an array in reverse a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
public static T[] ReversePermuteArrayElements<T>(T[] input, int times)
{
if (times.Equals(0)) return input;
T[] slice = new T[input.Length];
Array.Copy(input, 1, slice, 0, input.Length - 1);
Array.Copy(input, 0, slice, input.Length - 1, 1);
return ReversePermuteArrayElements(slice, --times);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Permutes an array forward a given number of times.
/// </summary>
/// <typeparam name="T">the array type</typeparam>
/// <param name="input">the array</param>
/// <param name="times">the number of times to permute</param>
/// <returns>the array with the elements permuted</returns>
public static T[] ForwardPermuteArrayElements<T>(T[] input, int times)
{
if (times.Equals(0)) return input;
T[] slice = new T[input.Length];
Array.Copy(input, input.Length - 1, slice, 0, 1);
Array.Copy(input, 0, slice, 1, input.Length - 1);
return ForwardPermuteArrayElements(slice, --times);
}
}
}
/wasSharp/BitTwiddling.cs
@@ -0,0 +1,26 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
namespace wasSharp
{
public class BitTwiddling
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Swaps two integers passed by reference using XOR.
/// </summary>
/// <param name="q">first integer to swap</param>
/// <param name="p">second integer to swap</param>
public static void XORSwap(ref int q, ref int p)
{
q ^= p;
p ^= q;
q ^= p;
}
}
}
/wasSharp/CSV.cs
@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace wasSharp
{
public class CSV
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Converts a list of string to a comma-separated values string.
/// </summary>
/// <param name="l">a list of strings</param>
/// <returns>a commma-separated list of values</returns>
/// <remarks>compliant with RFC 4180</remarks>
public static string FromEnumerable(IEnumerable<string> l)
{
string[] csv = l.Select(o => o).ToArray();
char[] escapeCharacters = {'"', ' ', ',', '\r', '\n'};
Parallel.ForEach(csv.Select((v, i) => new {i, v}), o =>
{
string cell = o.v.Replace("\"", "\"\"");
 
switch (cell.IndexOfAny(escapeCharacters))
{
case -1:
csv[o.i] = cell;
break;
default:
csv[o.i] = "\"" + cell + "\"";
break;
}
});
return string.Join(",", csv);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Converts a comma-separated list of values to a list of strings.
/// </summary>
/// <param name="csv">a comma-separated list of values</param>
/// <returns>a list of strings</returns>
/// <remarks>compliant with RFC 4180</remarks>
public static IEnumerable<string> ToEnumerable(string csv)
{
Stack<char> s = new Stack<char>();
StringBuilder m = new StringBuilder();
for (int i = 0; i < csv.Length; ++i)
{
switch (csv[i])
{
case ',':
if (!s.Any() || !s.Peek().Equals('"'))
{
yield return m.ToString();
m = new StringBuilder();
continue;
}
m.Append(csv[i]);
continue;
case '"':
if (i + 1 < csv.Length && csv[i].Equals(csv[i + 1]))
{
m.Append(csv[i]);
++i;
continue;
}
if (!s.Any() || !s.Peek().Equals(csv[i]))
{
s.Push(csv[i]);
continue;
}
s.Pop();
continue;
}
m.Append(csv[i]);
}
 
yield return m.ToString();
}
}
}
/wasSharp/Collections.cs
@@ -0,0 +1,88 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
 
namespace wasSharp
{
public class Collections
{
/// <summary>
/// A serializable dictionary class.
/// </summary>
/// <typeparam name="TKey">the key</typeparam>
/// <typeparam name="TValue">the value</typeparam>
[XmlRoot("Dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
 
public XmlSchema GetSchema()
{
return null;
}
 
public void ReadXml(XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof (TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof (TValue));
 
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
 
if (wasEmpty)
return;
 
while (reader.NodeType != XmlNodeType.EndElement)
{
reader.ReadStartElement("Item");
 
reader.ReadStartElement("Key");
TKey key = (TKey) keySerializer.Deserialize(reader);
reader.ReadEndElement();
 
reader.ReadStartElement("Value");
TValue value = (TValue) valueSerializer.Deserialize(reader);
reader.ReadEndElement();
 
Add(key, value);
 
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
 
public void WriteXml(XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof (TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof (TValue));
 
foreach (TKey key in Keys)
{
writer.WriteStartElement("Item");
 
writer.WriteStartElement("Key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
 
writer.WriteStartElement("Value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
 
writer.WriteEndElement();
}
}
 
#endregion
}
}
}
/wasSharp/Cryptography.cs
@@ -0,0 +1,395 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace wasSharp
{
public class Cryptography
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Encrypt or decrypt a message given a set of rotors, plugs and a reflector.
/// </summary>
/// <param name="message">the message to encyrpt or decrypt</param>
/// <param name="rotors">any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g</param>
/// <param name="plugs">the letter representing the start character for the rotor</param>
/// <param name="reflector">any one of: B, b, C, c</param>
/// <returns>either a decrypted or encrypted string</returns>
public static string ENIGMA(string message, char[] rotors, char[] plugs, char reflector)
{
Dictionary<char, char[]> def_rotors = new Dictionary<char, char[]>
{
{
'1', new[]
{
'e', 'k', 'm', 'f', 'l',
'g', 'd', 'q', 'v', 'z',
'n', 't', 'o', 'w', 'y',
'h', 'x', 'u', 's', 'p',
'a', 'i', 'b', 'r', 'c',
'j'
}
},
{
'2', new[]
{
'a', 'j', 'd', 'k', 's',
'i', 'r', 'u', 'x', 'b',
'l', 'h', 'w', 't', 'm',
'c', 'q', 'g', 'z', 'n',
'p', 'y', 'f', 'v', 'o',
'e'
}
},
{
'3', new[]
{
'b', 'd', 'f', 'h', 'j',
'l', 'c', 'p', 'r', 't',
'x', 'v', 'z', 'n', 'y',
'e', 'i', 'w', 'g', 'a',
'k', 'm', 'u', 's', 'q',
'o'
}
},
{
'4', new[]
{
'e', 's', 'o', 'v', 'p',
'z', 'j', 'a', 'y', 'q',
'u', 'i', 'r', 'h', 'x',
'l', 'n', 'f', 't', 'g',
'k', 'd', 'c', 'm', 'w',
'b'
}
},
{
'5', new[]
{
'v', 'z', 'b', 'r', 'g',
'i', 't', 'y', 'u', 'p',
's', 'd', 'n', 'h', 'l',
'x', 'a', 'w', 'm', 'j',
'q', 'o', 'f', 'e', 'c',
'k'
}
},
{
'6', new[]
{
'j', 'p', 'g', 'v', 'o',
'u', 'm', 'f', 'y', 'q',
'b', 'e', 'n', 'h', 'z',
'r', 'd', 'k', 'a', 's',
'x', 'l', 'i', 'c', 't',
'w'
}
},
{
'7', new[]
{
'n', 'z', 'j', 'h', 'g',
'r', 'c', 'x', 'm', 'y',
's', 'w', 'b', 'o', 'u',
'f', 'a', 'i', 'v', 'l',
'p', 'e', 'k', 'q', 'd',
't'
}
},
{
'8', new[]
{
'f', 'k', 'q', 'h', 't',
'l', 'x', 'o', 'c', 'b',
'j', 's', 'p', 'd', 'z',
'r', 'a', 'm', 'e', 'w',
'n', 'i', 'u', 'y', 'g',
'v'
}
},
{
'b', new[]
{
'l', 'e', 'y', 'j', 'v',
'c', 'n', 'i', 'x', 'w',
'p', 'b', 'q', 'm', 'd',
'r', 't', 'a', 'k', 'z',
'g', 'f', 'u', 'h', 'o',
's'
}
},
{
'g', new[]
{
'f', 's', 'o', 'k', 'a',
'n', 'u', 'e', 'r', 'h',
'm', 'b', 't', 'i', 'y',
'c', 'w', 'l', 'q', 'p',
'z', 'x', 'v', 'g', 'j',
'd'
}
}
};
 
Dictionary<char, char[]> def_reflectors = new Dictionary<char, char[]>
{
{
'B', new[]
{
'a', 'y', 'b', 'r', 'c', 'u', 'd', 'h',
'e', 'q', 'f', 's', 'g', 'l', 'i', 'p',
'j', 'x', 'k', 'n', 'm', 'o', 't', 'z',
'v', 'w'
}
},
{
'b', new[]
{
'a', 'e', 'b', 'n', 'c', 'k', 'd', 'q',
'f', 'u', 'g', 'y', 'h', 'w', 'i', 'j',
'l', 'o', 'm', 'p', 'r', 'x', 's', 'z',
't', 'v'
}
},
{
'C', new[]
{
'a', 'f', 'b', 'v', 'c', 'p', 'd', 'j',
'e', 'i', 'g', 'o', 'h', 'y', 'k', 'r',
'l', 'z', 'm', 'x', 'n', 'w', 't', 'q',
's', 'u'
}
},
{
'c', new[]
{
'a', 'r', 'b', 'd', 'c', 'o', 'e', 'j',
'f', 'n', 'g', 't', 'h', 'k', 'i', 'v',
'l', 'm', 'p', 'w', 'q', 'z', 's', 'x',
'u', 'y'
}
}
};
 
// Setup rotors from plugs.
foreach (char rotor in rotors)
{
char plug = plugs[Array.IndexOf(rotors, rotor)];
int i = Array.IndexOf(def_rotors[rotor], plug);
if (i.Equals(0)) continue;
def_rotors[rotor] = Arrays.ConcatenateArrays(new[] {plug},
Arrays.GetSubArray(Arrays.DeleteSubArray(def_rotors[rotor], i, i), i, -1),
Arrays.GetSubArray(Arrays.DeleteSubArray(def_rotors[rotor], i + 1, -1), 0, i - 1));
}
 
StringBuilder result = new StringBuilder();
foreach (char c in message)
{
if (!char.IsLetter(c))
{
result.Append(c);
continue;
}
 
// Normalize to lower.
char l = char.ToLower(c);
 
Action<char[]> rotate = o =>
{
int i = o.Length - 1;
do
{
def_rotors[o[0]] = Arrays.ForwardPermuteArrayElements(def_rotors[o[0]], 1);
if (i.Equals(0))
{
rotors = Arrays.ReversePermuteArrayElements(o, 1);
continue;
}
l = Arrays.GetElementAt(def_rotors[o[1]], Array.IndexOf(def_rotors[o[0]], l) - 1);
o = Arrays.ReversePermuteArrayElements(o, 1);
} while (--i > -1);
};
 
// Forward pass through the Enigma's rotors.
rotate.Invoke(rotors);
 
// Reflect
int x = Array.IndexOf(def_reflectors[reflector], l);
l = (x + 1)%2 == 0 ? def_reflectors[reflector][x - 1] : def_reflectors[reflector][x + 1];
 
// Reverse the order of the rotors.
Array.Reverse(rotors);
 
// Reverse pass through the Enigma's rotors.
rotate.Invoke(rotors);
 
if (char.IsUpper(c))
{
l = char.ToUpper(l);
}
result.Append(l);
}
 
return result.ToString();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Expand the VIGENRE key to the length of the input.
/// </summary>
/// <param name="input">the input to expand to</param>
/// <param name="enc_key">the key to expand</param>
/// <returns>the expanded key</returns>
public static string VIGENEREExpandKey(string input, string enc_key)
{
string exp_key = string.Empty;
int i = 0, j = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
exp_key += p;
++i;
continue;
}
int m = j%enc_key.Length;
exp_key += enc_key[m];
++j;
++i;
} while (i < input.Length);
return exp_key;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Encrypt using VIGENERE.
/// </summary>
/// <param name="input">the input to encrypt</param>
/// <param name="enc_key">the key to encrypt with</param>
/// <returns>the encrypted input</returns>
public static string EncryptVIGENERE(string input, string enc_key)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
enc_key = VIGENEREExpandKey(input, enc_key);
string result = string.Empty;
int i = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
result += p;
++i;
continue;
}
char q =
Arrays.ReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i]))[
Array.IndexOf(a, char.ToLowerInvariant(p))];
if (char.IsUpper(p))
{
q = char.ToUpperInvariant(q);
}
result += q;
++i;
} while (i < input.Length);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Decrypt using VIGENERE.
/// </summary>
/// <param name="input">the input to decrypt</param>
/// <param name="enc_key">the key to decrypt with</param>
/// <returns>the decrypted input</returns>
public static string DecryptVIGENERE(string input, string enc_key)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
enc_key = VIGENEREExpandKey(input, enc_key);
string result = string.Empty;
int i = 0;
do
{
char p = input[i];
if (!char.IsLetter(p))
{
result += p;
++i;
continue;
}
char q =
a[
Array.IndexOf(Arrays.ReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i])),
char.ToLowerInvariant(p))];
if (char.IsUpper(p))
{
q = char.ToUpperInvariant(q);
}
result += q;
++i;
} while (i < input.Length);
return result;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// An implementation of the ATBASH cypher for latin alphabets.
/// </summary>
/// <param name="data">the data to encrypt or decrypt</param>
/// <returns>the encrypted or decrypted data</returns>
public static string ATBASH(string data)
{
char[] a =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
 
char[] input = data.ToCharArray();
 
Parallel.ForEach(Enumerable.Range(0, data.Length), i =>
{
char e = input[i];
if (!char.IsLetter(e)) return;
int x = 25 - Array.BinarySearch(a, char.ToLowerInvariant(e));
if (!char.IsUpper(e))
{
input[i] = a[x];
return;
}
input[i] = char.ToUpperInvariant(a[x]);
});
 
return new string(input);
}
}
}
/wasSharp/KeyValue.cs
@@ -0,0 +1,145 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace wasSharp
{
public class KeyValue
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns the value of a key from a key-value data string.
/// </summary>
/// <param name="key">the key of the value</param>
/// <param name="data">the key-value data segment</param>
/// <returns>true if the key was found in data</returns>
public static string Get(string key, string data)
{
return data.Split('&')
.AsParallel()
.Select(o => o.Split('=').ToList())
.Where(o => o.Count.Equals(2))
.Select(o => new
{
k = o.First(),
v = o.Last()
})
.Where(o => o.k.Equals(key))
.Select(o => o.v)
.FirstOrDefault();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns a key-value data string with a key set to a given value.
/// </summary>
/// <param name="key">the key of the value</param>
/// <param name="value">the value to set the key to</param>
/// <param name="data">the key-value data segment</param>
/// <returns>
/// a key-value data string or the empty string if either key or
/// value are empty
/// </returns>
public static string Set(string key, string value, string data)
{
HashSet<string> output = new HashSet<string>(data.Split('&')
.AsParallel()
.Select(o => o.Split('=').ToList())
.Where(o => o.Count.Equals(2))
.Select(o => new
{
k = o.First(),
v = !o.First().Equals(key) ? o.Last() : value
}).Select(o => string.Join("=", o.k, o.v)));
string append = string.Join("=", key, value);
if (!output.Contains(append))
{
output.Add(append);
}
return string.Join("&", output.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Deletes a key-value pair from a string referenced by a key.
/// </summary>
/// <param name="key">the key to search for</param>
/// <param name="data">the key-value data segment</param>
/// <returns>a key-value pair string</returns>
public static string Delete(string key, string data)
{
return string.Join("&", data.Split('&')
.AsParallel()
.Select(o => o.Split('=').ToList())
.Where(o => o.Count.Equals(2))
.Select(o => new
{
k = o.First(),
v = o.Last()
})
.Where(o => !o.k.Equals(key))
.Select(o => string.Join("=", o.k, o.v))
.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Decodes key-value pair data to a dictionary.
/// </summary>
/// <param name="data">the key-value pair data</param>
/// <returns>a dictionary containing the keys and values</returns>
public static Dictionary<string, string> Decode(string data)
{
return data.Split('&')
.AsParallel()
.Select(o => o.Split('=').ToList())
.Where(o => o.Count.Equals(2))
.Select(o => new
{
k = o.First(),
v = o.Last()
})
.GroupBy(o => o.k)
.ToDictionary(o => o.Key, p => p.First().v);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Serialises a dictionary to key-value data.
/// </summary>
/// <param name="data">a dictionary</param>
/// <returns>a key-value data encoded string</returns>
public static string Encode(Dictionary<string, string> data)
{
return string.Join("&", data.AsParallel().Select(o => string.Join("=", o.Key, o.Value)));
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>Escapes a dictionary's keys and values for sending as POST data.</summary>
/// <param name="data">A dictionary containing keys and values to be escaped</param>
/// <param name="func">The function to use to escape the keys and values in the dictionary.</param>
public static Dictionary<string, string> Escape(Dictionary<string, string> data,
Func<string, string> func)
{
return data.AsParallel().ToDictionary(o => func(o.Key), p => func(p.Value));
}
}
}
/wasSharp/Numerics.cs
@@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
namespace wasSharp
{
public class Numerics
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Given a value in a source value range and a target range, map
/// the value from the source range into the target range.
/// </summary>
/// <param name="value">the value to map</param>
/// <param name="xMin">the lower bound of the source range</param>
/// <param name="xMax">the upper bound of the source range</param>
/// <param name="yMin">the lower bound of the target range</param>
/// <param name="yMax">the upper bound of the target range</param>
public static double MapValueToRange(double value, double xMin, double xMax, double yMin, double yMax)
{
return yMin + (
(
yMax - yMin
)
*
(
value - xMin
)
/
(
xMax - xMin
)
);
}
}
}
/wasSharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
using System.Reflection;
using System.Resources;
 
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
 
[assembly: AssemblyTitle("wasSharp")]
[assembly: AssemblyDescription("Collections of C# Tools Created by Wizardry and Steamworks")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Wizardry and Steamworks")]
[assembly: AssemblyProduct("wasSharp")]
[assembly: AssemblyCopyright("© Copyright 2015, Wizardry and Steamworks")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
 
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
 
[assembly: AssemblyVersion("1.4.*")]
/wasSharp/Reflection.cs
@@ -0,0 +1,177 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
 
namespace wasSharp
{
public class Reflection
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Retrieves an attribute of type T from an enumeration.
/// </summary>
/// <returns>an attribute of type T</returns>
public static T GetAttributeFromEnumValue<T>(Enum value) where T : Attribute
{
return (T) value.GetType()
.GetRuntimeField(value.ToString())
.GetCustomAttributes(typeof (T), false)
.SingleOrDefault();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns all the attributes of type T of an enumeration.
/// </summary>
/// <typeparam name="T">the attribute to retrieve</typeparam>
/// <returns>a list of attributes</returns>
public static IEnumerable<T> GetEnumAttributes<T>(Enum e) where T : Attribute
{
return e.GetType().GetRuntimeFields()
.AsParallel()
.Select(o => GetAttributeFromEnumValue<T>((Enum) o.GetValue(Activator.CreateInstance<T>())));
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns all the field names of an enumeration.
/// </summary>
/// <returns>the field names</returns>
public static IEnumerable<string> GetEnumNames<T>()
{
return
typeof (T).GetRuntimeFields()
.AsParallel()
.Select(o => o.GetCustomAttribute(typeof (NameAttribute), false))
.Select(o => (o as NameAttribute)?.Name)
.Where(o => !string.IsNullOrEmpty(o))
.Select(o => o);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns all the values of an enumeration.
/// </summary>
/// <returns>the values of the enumeration</returns>
public static IEnumerable<T> GetEnumValues<T>()
{
return Enum.GetValues(typeof (T)).Cast<object>().Select(value => (T) value);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Get the description from an enumeration value.
/// </summary>
/// <param name="value">an enumeration value</param>
/// <returns>the description or the empty string</returns>
public static string GetNameFromEnumValue(Enum value)
{
NameAttribute attribute = value.GetType()
.GetRuntimeField(value.ToString())
.GetCustomAttributes(typeof (NameAttribute), false)
.SingleOrDefault() as NameAttribute;
return attribute?.Name;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Get the description from an enumeration value.
/// </summary>
/// <param name="value">an enumeration value</param>
/// <returns>the description or the empty string</returns>
public static string GetDescriptionFromEnumValue(Enum value)
{
DescriptionAttribute attribute = value.GetType()
.GetRuntimeField(value.ToString())
.GetCustomAttributes(typeof (DescriptionAttribute), false)
.SingleOrDefault() as DescriptionAttribute;
return attribute?.Description;
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Get enumeration value from its name attribute.
/// </summary>
/// <typeparam name="T">the enumeration type</typeparam>
/// <param name="name">the description of a member</param>
/// <returns>the value or the default of T if case no name attribute found</returns>
public static T GetEnumValueFromName<T>(string name)
{
var field = typeof (T).GetRuntimeFields()
.AsParallel().SelectMany(f => f.GetCustomAttributes(
typeof (NameAttribute), false), (
f, a) => new {Field = f, Att = a}).SingleOrDefault(a => ((NameAttribute) a.Att)
.Name.Equals(name));
return field != null ? (T) field.Field.GetValue(Activator.CreateInstance<T>()) : default(T);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Get the description of structure member.
/// </summary>
/// <typeparam name="T">the type of the structure to search</typeparam>
/// <param name="structure">the structure to search</param>
/// <param name="item">the value of the item to search</param>
/// <returns>the description or the empty string</returns>
public static string GetStructureMemberName<T>(T structure, object item) where T : struct
{
var field = typeof (T).GetRuntimeFields()
.AsParallel().SelectMany(f => f.GetCustomAttributes(typeof (NameAttribute), false),
(f, a) => new {Field = f, Att = a}).SingleOrDefault(f => f.Field.GetValue(structure).Equals(item));
return field != null ? ((NameAttribute) field.Att).Name : string.Empty;
}
 
/// <summary>
/// A generic name attribute.
/// </summary>
public class NameAttribute : Attribute
{
protected readonly string name;
 
public NameAttribute(string name)
{
this.name = name;
}
 
public string Name => name;
}
 
/// <summary>
/// A generic description attribute.
/// </summary>
public class DescriptionAttribute : Attribute
{
protected readonly string description;
 
public DescriptionAttribute(string description)
{
this.description = description;
}
 
public string Description => description;
}
}
}
/wasSharp/Time.cs
@@ -0,0 +1,279 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
 
namespace wasSharp
{
public class Time
{
public delegate void TimerCallback(object state);
 
public sealed class Timer : IDisposable
{
private static readonly Task CompletedTask = Task.FromResult(false);
private readonly TimerCallback Callback;
private readonly object State;
private Task Delay;
private bool Disposed;
private int Period;
private CancellationTokenSource TokenSource;
 
public Timer(TimerCallback callback, object state, int dueTime, int period)
{
Callback = callback;
State = state;
Period = period;
Reset(dueTime);
}
 
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
: this(callback, state, (int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds)
{
}
 
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
 
~Timer()
{
Dispose(false);
}
 
private void Dispose(bool cleanUpManagedObjects)
{
if (cleanUpManagedObjects)
Cancel();
Disposed = true;
}
 
public void Change(int dueTime, int period)
{
Period = period;
Reset(dueTime);
}
 
public void Change(TimeSpan dueTime, TimeSpan period)
{
Change((int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds);
}
 
private void Reset(int due)
{
Cancel();
if (due >= 0)
{
TokenSource = new CancellationTokenSource();
Action tick = null;
tick = () =>
{
Task.Run(() => Callback(State));
if (Disposed || Period < 0) return;
Delay = Period > 0 ? Task.Delay(Period, TokenSource.Token) : CompletedTask;
Delay.ContinueWith(t => tick(), TokenSource.Token);
};
Delay = due > 0 ? Task.Delay(due, TokenSource.Token) : CompletedTask;
Delay.ContinueWith(t => tick(), TokenSource.Token);
}
}
 
private void Cancel()
{
if (TokenSource != null)
{
TokenSource.Cancel();
TokenSource.Dispose();
TokenSource = null;
}
}
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Given a number of allowed events per seconds, this class allows you
/// to determine via the IsSafe property whether it is safe to trigger
/// another lined-up event. This is mostly used to check that throttles
/// are being respected.
/// </summary>
public class TimedThrottle : IDisposable
{
private readonly uint EventsAllowed;
private readonly object LockObject = new object();
private Timer timer;
private uint TriggeredEvents;
 
public TimedThrottle(uint events, uint seconds)
{
EventsAllowed = events;
if (timer == null)
{
timer = new Timer(o =>
{
lock (LockObject)
{
TriggeredEvents = 0;
}
}, null, (int) seconds, (int) seconds);
}
}
 
public bool IsSafe
{
get
{
lock (LockObject)
{
return ++TriggeredEvents <= EventsAllowed;
}
}
}
 
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
 
protected virtual void Dispose(bool dispose)
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
}
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// An alarm class similar to the UNIX alarm with the added benefit
/// of a decaying timer that tracks the time between rescheduling.
/// </summary>
/// <remarks>
/// (C) Wizardry and Steamworks 2013 - License: GNU GPLv3
/// </remarks>
public class DecayingAlarm : IDisposable
{
[Flags]
public enum DECAY_TYPE
{
[XmlEnum(Name = "none")] NONE = 0,
[XmlEnum(Name = "arithmetic")] ARITHMETIC = 1,
[XmlEnum(Name = "geometric")] GEOMETRIC = 2,
[XmlEnum(Name = "harmonic")] HARMONIC = 4,
[XmlEnum(Name = "weighted")] WEIGHTED = 5
}
 
private readonly DECAY_TYPE decay = DECAY_TYPE.NONE;
private readonly Stopwatch elapsed = new Stopwatch();
private readonly object LockObject = new object();
private readonly HashSet<double> times = new HashSet<double>();
private Timer alarm;
 
/// <summary>
/// The default constructor using no decay.
/// </summary>
public DecayingAlarm()
{
Signal = new ManualResetEvent(false);
}
 
/// <summary>
/// The constructor for the DecayingAlarm class taking as parameter a decay type.
/// </summary>
/// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param>
public DecayingAlarm(DECAY_TYPE decay)
{
Signal = new ManualResetEvent(false);
this.decay = decay;
}
 
public ManualResetEvent Signal { get; set; }
 
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
 
public void Alarm(double deadline)
{
lock (LockObject)
{
switch (alarm == null)
{
case true:
elapsed.Start();
alarm = new Timer(o =>
{
lock (LockObject)
{
Signal.Set();
elapsed.Stop();
times.Clear();
alarm.Dispose();
alarm = null;
}
}, null, (int) deadline, 0);
return;
case false:
elapsed.Stop();
times.Add(elapsed.ElapsedMilliseconds);
switch (decay)
{
case DECAY_TYPE.ARITHMETIC:
alarm?.Change(
(int) ((deadline + times.Aggregate((a, b) => b + a))/(1f + times.Count)), 0);
break;
case DECAY_TYPE.GEOMETRIC:
alarm?.Change((int) (Math.Pow(deadline*times.Aggregate((a, b) => b*a),
1f/(1f + times.Count))), 0);
break;
case DECAY_TYPE.HARMONIC:
alarm?.Change((int) ((1f + times.Count)/
(1f/deadline + times.Aggregate((a, b) => 1f/b + 1f/a))), 0);
break;
case DECAY_TYPE.WEIGHTED:
HashSet<double> d = new HashSet<double>(times) {deadline};
double total = d.Aggregate((a, b) => b + a);
alarm?.Change(
(int) (d.Aggregate((a, b) => Math.Pow(a, 2)/total + Math.Pow(b, 2)/total)), 0);
break;
default:
alarm?.Change((int) deadline, 0);
break;
}
elapsed.Reset();
elapsed.Start();
break;
}
}
}
 
protected virtual void Dispose(bool dispose)
{
if (alarm != null)
{
alarm.Dispose();
alarm = null;
}
}
}
}
}
/wasSharp/Web.cs
@@ -0,0 +1,65 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System;
using System.Linq;
using System.Net;
 
namespace wasSharp
{
public class Web
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC3986 URI Escapes a string</summary>
/// <param name="data">a string to escape</param>
/// <returns>an RFC3986 escaped string</returns>
public static string URIEscapeDataString(string data)
{
// Uri.EscapeDataString can only handle 32766 characters at a time
return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
.Select(o => Uri.EscapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>URI unescapes an RFC3986 URI escaped string</summary>
/// <param name="data">a string to unescape</param>
/// <returns>the resulting string</returns>
public static string URIUnescapeDataString(string data)
{
// Uri.UnescapeDataString can only handle 32766 characters at a time
return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
.Select(o => Uri.UnescapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
.ToArray());
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC1738 URL Escapes a string</summary>
/// <param name="data">a string to escape</param>
/// <returns>an RFC1738 escaped string</returns>
public static string URLEscapeDataString(string data)
{
return WebUtility.UrlEncode(data);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>RFC1738 URL Unescape a string</summary>
/// <param name="data">a string to unescape</param>
/// <returns>an RFC1738 unescaped string</returns>
public static string URLUnescapeDataString(string data)
{
return WebUtility.UrlDecode(data);
}
}
}
/wasSharp/XML.cs
@@ -0,0 +1,129 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace wasSharp
{
public class XML
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Unescapes a string used in XML.
/// </summary>
/// <param name="s">the string to unescape</param>
/// <returns>an XML unescaped string</returns>
public static string UnescapeXML(string s)
{
Queue<char> t = new Queue<char>();
StringBuilder m = new StringBuilder();
foreach (char c in s)
{
switch (c)
{
case '&':
if (!t.Count.Equals(0))
{
m.Append(string.Join("", t.ToArray()));
t.Clear();
}
t.Enqueue(c);
break;
case ';':
if (!t.Count.Equals(0))
{
t.Enqueue(c);
string special = string.Join("", t.ToArray());
switch (special)
{
case "&apos;":
m.Append('\'');
break;
case "&quot;":
m.Append('"');
break;
case "&gt;":
m.Append('>');
break;
case "&lt;":
m.Append('<');
break;
case "&amp;":
m.Append('&');
break;
default: // Unrecognized escape sequence
m.Append(special);
break;
}
t.Clear();
break;
}
m.Append(c);
break;
default:
if (!t.Count.Equals(0))
{
t.Enqueue(c);
if (t.Count >= 6)
{
m.Append(string.Join("", t.ToArray()));
t.Clear();
}
break;
}
m.Append(c);
break;
}
}
return m.ToString();
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Escapes a string to be used in XML.
/// </summary>
/// <param name="s">the string to escape</param>
/// <returns>an XML escaped string</returns>
public static string EscapeXML(string s)
{
if (string.IsNullOrEmpty(s)) return s;
 
string[] result = new string[s.Length];
Parallel.ForEach(Enumerable.Range(0, s.Length), o =>
{
switch (s[o])
{
case '&':
result[o] = @"&amp;";
break;
case '<':
result[o] = @"&lt;";
break;
case '>':
result[o] = @"&gt;";
break;
case '"':
result[o] = @"&quot;";
break;
case '\'':
result[o] = @"&apos;";
break;
default:
result[o] = s[o].ToString();
break;
}
});
return string.Join("", result);
}
}
}
/wasSharp/wasSharp.cs
@@ -0,0 +1,12 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
 
namespace wasSharp
{
public class wasSharp
{
}
}
/wasSharp/wasSharp.csproj
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A971E1C9-776C-4CD2-88AC-71197C7B955E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>wasSharp</RootNamespace>
<AssemblyName>wasSharp</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile151</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>
<ItemGroup>
<Compile Include="Arrays.cs" />
<Compile Include="BitTwiddling.cs" />
<Compile Include="Collections.cs" />
<Compile Include="Cryptography.cs" />
<Compile Include="CSV.cs" />
<Compile Include="KeyValue.cs" />
<Compile Include="Numerics.cs" />
<Compile Include="Reflection.cs" />
<Compile Include="Time.cs" />
<Compile Include="wasSharp.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Web.cs" />
<Compile Include="XML.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
/wasSharp/wasSharp.sln
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wasSharp", "wasSharp.csproj", "{A971E1C9-776C-4CD2-88AC-71197C7B955E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A971E1C9-776C-4CD2-88AC-71197C7B955E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal