corrade-vassal – Diff between revs 7 and 8

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 7 Rev 8
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // 3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. // 4 // rights of fair usage, the disclaimer and warranty conditions. //
5 /////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////
6   6  
7 using System; 7 using System;
8 using System.Collections; -  
9 using System.Collections.Generic; 8 using System.Collections.Generic;
10 using System.ComponentModel; -  
11 using System.Data; -  
12 using System.Drawing; 9 using System.Drawing;
13 using System.Drawing.Imaging; 10 using System.Drawing.Imaging;
14 using System.IO; 11 using System.IO;
15 using System.Linq; 12 using System.Linq;
16 using System.Net; 13 using System.Net;
17 using System.Net.Sockets; 14 using System.Net.Sockets;
18 using System.Reflection; 15 using System.Reflection;
19 using System.Text; 16 using System.Text;
20 using System.Text.RegularExpressions; 17 using System.Text.RegularExpressions;
21 using System.Timers; -  
22 using System.Threading; 18 using System.Threading;
23 using System.Web; 19 using System.Web;
24 using System.Windows.Forms; 20 using System.Windows.Forms;
25 using OpenMetaverse; 21 using OpenMetaverse;
26 using Parallel = System.Threading.Tasks.Parallel; 22 using Parallel = System.Threading.Tasks.Parallel;
27 using Timer = System.Timers.Timer; 23 using Timer = System.Timers.Timer;
28   24  
29 namespace Vassal 25 namespace Vassal
30 { 26 {
31 public partial class Vassal : Form 27 public partial class Vassal : Form
32 { 28 {
-   29 public static Timer vassalTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
33 public static System.Timers.Timer overviewTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 30 public static Timer overviewTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
34 public static System.Timers.Timer residentListTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 31 public static Timer residentListTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
35 public static System.Timers.Timer topScriptsTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 32 public static Timer estateTopTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
36 public static System.Timers.Timer topCollidersTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 33 public static Timer regionsStateTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
37 public static System.Timers.Timer regionsStateTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 34 public static Timer estateTexturesTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
-   35 public static Image[] groundTextureImages = new Image[4];
38 public static volatile int regionsStateCheckIndex = 0; 36 public static volatile int regionsStateCheckIndex;
39 public static VassalConfiguration vassalConfiguration = new VassalConfiguration(); 37 public static VassalConfiguration vassalConfiguration = new VassalConfiguration();
40 public static Vassal vassalForm; 38 public static Vassal vassalForm;
41 public static readonly object ClientInstanceTeleportLock = new object(); 39 public static readonly object ClientInstanceTeleportLock = new object();
42 public static readonly object RegionsStateCheckLock = new object(); 40 public static readonly object RegionsStateCheckLock = new object();
43   41  
44 /// <summary> 42 /// <summary>
45 /// Linden constants. 43 /// Corrade's input filter function.
46 /// </summary> 44 /// </summary>
47 public struct LINDEN_CONSTANTS 45 private static readonly Func<string, string> wasInput = o =>
48 { 46 {
49 public struct ALERTS -  
50 { -  
51 public const string NO_ROOM_TO_SIT_HERE = @"No room to sit here, try another spot."; -  
52   -  
53 public const string UNABLE_TO_SET_HOME = -  
54 @"You can only set your 'Home Location' on your land or at a mainland Infohub."; -  
55   -  
56 public const string HOME_SET = @"Home position set."; 47 if (string.IsNullOrEmpty(o)) return string.Empty;
57 } -  
58   48  
59 public struct ASSETS 49 foreach (Filter filter in vassalConfiguration.InputFilters)
60 { 50 {
61 public struct NOTECARD 51 switch (filter)
-   52 {
62 { 53 case Filter.RFC1738:
-   54 o = wasURLUnescapeDataString(o);
-   55 break;
-   56 case Filter.RFC3986:
-   57 o = wasURIUnescapeDataString(o);
-   58 break;
-   59 case Filter.ENIGMA:
-   60 o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
63 public const string NEWLINE = "\n"; 61 vassalConfiguration.ENIGMA.plugs.ToArray(),
-   62 vassalConfiguration.ENIGMA.reflector);
-   63 break;
-   64 case Filter.VIGENERE:
-   65 o = wasDecryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
-   66 break;
-   67 case Filter.ATBASH:
-   68 o = wasATBASH(o);
-   69 break;
-   70 case Filter.BASE64:
-   71 o = Encoding.UTF8.GetString(Convert.FromBase64String(o));
64 public const uint MAXIMUM_BODY_LENTH = 65536; 72 break;
65 } 73 }
-   74 }
-   75 return o;
66 } -  
67   76 };
68 public struct AVATARS -  
69 { -  
70 public const uint SET_DISPLAY_NAME_SUCCESS = 200; -  
71 public const string LASTNAME_PLACEHOLDER = @"Resident"; -  
72 public const uint MAXIMUM_DISPLAY_NAME_CHARACTERS = 31; -  
73 public const uint MINIMUM_DISPLAY_NAME_CHARACTERS = 1; -  
74 public const uint MAXIMUM_NUMBER_OF_ATTACHMENTS = 38; 77  
75   78 /// <summary>
76 public struct PROFILE 79 /// Corrade's output filter function.
77 { -  
78 public const uint SECOND_LIFE_TEXT_SIZE = 510; -  
79 public const uint FIRST_LIFE_TEXT_SIZE = 253; -  
80 } -  
81   80 /// </summary>
82 public struct PICKS 81 private static readonly Func<string, string> wasOutput = o =>
83 { -  
84 public const uint MAXIMUM_PICKS = 10; -  
-   82 {
-   83 if (string.IsNullOrEmpty(o)) return string.Empty;
85 public const uint MAXIMUM_PICK_DESCRIPTION_SIZE = 1022; 84  
86 } 85 foreach (Filter filter in vassalConfiguration.OutputFilters)
-   86 {
-   87 switch (filter)
-   88 {
-   89 case Filter.RFC1738:
-   90 o = wasURLEscapeDataString(o);
-   91 break;
-   92 case Filter.RFC3986:
-   93 o = wasURIEscapeDataString(o);
-   94 break;
87   95 case Filter.ENIGMA:
-   96 o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
-   97 vassalConfiguration.ENIGMA.plugs.ToArray(),
-   98 vassalConfiguration.ENIGMA.reflector);
-   99 break;
-   100 case Filter.VIGENERE:
-   101 o = wasEncryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
-   102 break;
-   103 case Filter.ATBASH:
-   104 o = wasATBASH(o);
-   105 break;
88 public struct CLASSIFIEDS 106 case Filter.BASE64:
89 { 107 o = Convert.ToBase64String(Encoding.UTF8.GetBytes(o));
-   108 break;
-   109 }
90 public const uint MAXIMUM_CLASSIFIEDS = 100; -  
91 } -  
92 } -  
93   110 }
94 public struct PRIMITIVES -  
95 { -  
96 public const uint MAXIMUM_NAME_SIZE = 63; -  
97 public const uint MAXIMUM_DESCRIPTION_SIZE = 127; -  
98 public const double MAXIMUM_REZ_HEIGHT = 4096.0; -  
99 public const double MINIMUM_SIZE_X = 0.01; -  
100 public const double MINIMUM_SIZE_Y = 0.01; -  
101 public const double MINIMUM_SIZE_Z = 0.01; -  
102 public const double MAXIMUM_SIZE_X = 64.0; -  
103 public const double MAXIMUM_SIZE_Y = 64.0; -  
104 public const double MAXIMUM_SIZE_Z = 64.0; 111 return o;
105 } -  
106   112 };
107 public struct OBJECTS -  
108 { -  
109 public const uint MAXIMUM_PRIMITIVE_COUNT = 256; 113  
-   114 private static readonly Action updateCurrentRegionName = () =>
110 } 115 {
111   116 try
112 public struct DIRECTORY 117 {
113 { 118 string result = wasPOST(vassalConfiguration.HTTPServerURL,
114 public struct EVENT -  
115 { 119 wasKeyValueEscape(new Dictionary<string, string>
116 public const uint SEARCH_RESULTS_COUNT = 200; 120 {
117 } 121 {"command", "getregiondata"},
118   122 {"group", vassalConfiguration.Group},
119 public struct GROUP -  
120 { 123 {"password", vassalConfiguration.Password},
-   124 {"data", "Name"}
121 public const uint SEARCH_RESULTS_COUNT = 100; 125 }), 60000);
122 } 126 bool success;
-   127 if (string.IsNullOrEmpty(result) ||
-   128 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   129 {
123   130 vassalForm.BeginInvoke(
124 public struct LAND -  
125 { 131 (MethodInvoker)
126 public const uint SEARCH_RESULTS_COUNT = 100; 132 (() => { vassalForm.StatusText.Text = @"Failed to query Corrade for current region."; }));
-   133 return;
-   134 }
-   135 switch (success)
127 } 136 {
-   137 case true:
-   138 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   139 {
-   140 vassalForm.CurrentRegionAt.Visible = true;
-   141 vassalForm.CurrentRegionName.Visible = true;
-   142 vassalForm.CurrentRegionName.Text =
-   143 wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).Last();
-   144 }));
-   145 break;
-   146 default:
-   147 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   148 {
-   149 vassalForm.CurrentRegionAt.Visible = false;
-   150 vassalForm.CurrentRegionName.Visible = false;
128   151 vassalForm.StatusText.Text = @"Error getting current region: " +
129 public struct PEOPLE 152 wasInput(wasKeyValueGet("error", result));
130 { -  
131 public const uint SEARCH_RESULTS_COUNT = 100; 153 }));
132 } 154 break;
133 } -  
134   155 }
135 public struct ESTATE -  
136 { -  
137 public const uint REGION_RESTART_DELAY = 120; -  
138 public const uint MAXIMUM_BAN_LIST_LENGTH = 500; -  
139 public const uint MAXIMUM_GROUP_LIST_LENGTH = 63; -  
140 public const uint MAXIMUM_USER_LIST_LENGTH = 500; 156 }
141 public const uint MAXIMUM_MANAGER_LIST_LENGTH = 10; -  
142   -  
143 public struct MESSAGES -  
144 { -  
145 public const string REGION_RESTART_MESSAGE = @"restart"; -  
146 } -  
147 } -  
148   -  
149 public struct PARCELS 157 catch (Exception ex)
150 { -  
151 public const double MAXIMUM_AUTO_RETURN_TIME = 999999; -  
152 public const uint MINIMUM_AUTO_RETURN_TIME = 0; -  
153 public const uint MAXIMUM_NAME_LENGTH = 63; -  
154 public const uint MAXIMUM_DESCRIPTION_LENGTH = 255; -  
155 } -  
156   -  
157 public struct GRID -  
158 { -  
159 public const string SECOND_LIFE = @"Second Life"; -  
160 public const string TIME_ZONE = @"Pacific Standard Time"; -  
161 } -  
162   -  
163 public struct CHAT -  
164 { -  
165 public const uint MAXIMUM_MESSAGE_LENGTH = 1024; -  
166 } -  
167   -  
168 public struct GROUPS -  
169 { -  
170 public const uint MAXIMUM_NUMBER_OF_ROLES = 10; -  
171 public const string EVERYONE_ROLE_NAME = @"Everyone"; -  
172 public const uint MAXIMUM_GROUP_NAME_LENGTH = 35; -  
173 public const uint MAXIMUM_GROUP_TITLE_LENGTH = 20; -  
174 } -  
175   -  
176 public struct NOTICES -  
177 { -  
178 public const uint MAXIMUM_NOTICE_MESSAGE_LENGTH = 512; -  
179 } 158 {
180   -  
181 public struct LSL -  
182 { -  
183 public const string CSV_DELIMITER = @", "; -  
184 public const float SENSOR_RANGE = 96; 159 vassalForm.BeginInvoke((MethodInvoker) (() =>
185 public const string DATE_TIME_STAMP = @"yyy-MM-ddTHH:mm:ss.ffffffZ"; -  
186 } -  
187   -  
188 public struct REGION -  
189 { -  
190 public const float TELEPORT_MINIMUM_DISTANCE = 1; -  
191 public const float DEFAULT_AGENT_LIMIT = 40; -  
192 public const float DEFAULT_OBJECT_BONUS = 1; -  
193 public const bool DEFAULT_FIXED_SUN = false; -  
194 public const float DEFAULT_TERRAIN_LOWER_LIMIT = -4; -  
195 public const float DEFAULT_TERRAIN_RAISE_LIMIT = 4; 160 {
196 public const bool DEFAULT_USE_ESTATE_SUN = true; -  
197 public const float DEFAULT_WATER_HEIGHT = 20; -  
198 public const float SUNRISE = 6; -  
199 } -  
200   161 vassalForm.StatusText.Text =
-   162 @"Error getting current region: " +
201 public struct VIEWER 163 ex.Message;
202 { 164 }));
203 public const float MAXIMUM_DRAW_DISTANCE = 4096; 165 }
204 } 166 };
205   -  
206 public struct TELEPORTS -  
207 { -  
208 public struct THROTTLE -  
209 { 167  
210 public const uint MAX_TELEPORTS = 10; 168 public Vassal()
211 public const uint GRACE_SECONDS = 15; 169 {
212 } 170 InitializeComponent();
213 } 171 vassalForm = this;
214 } 172 }
215   173  
216 /////////////////////////////////////////////////////////////////////////// 174 ///////////////////////////////////////////////////////////////////////////
217 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // 175 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
218 /////////////////////////////////////////////////////////////////////////// 176 ///////////////////////////////////////////////////////////////////////////
219 private static double wasMapValueToRange(double value, double xMin, double xMax, double yMin, double yMax) 177 private static double wasMapValueToRange(double value, double xMin, double xMax, double yMin, double yMax)
220 { 178 {
221 return yMin + ( 179 return yMin + (
222 ( 180 (
223 yMax - yMin 181 yMax - yMin
224 ) 182 )
225 * 183 *
226 ( 184 (
227 value - xMin 185 value - xMin
228 ) 186 )
229 / 187 /
230 ( 188 (
231 xMax - xMin 189 xMax - xMin
232 ) 190 )
233 ); 191 );
234 } 192 }
235   193  
236 /////////////////////////////////////////////////////////////////////////// 194 ///////////////////////////////////////////////////////////////////////////
237 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // 195 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
238 /////////////////////////////////////////////////////////////////////////// 196 ///////////////////////////////////////////////////////////////////////////
239 /// <summary>RFC1738 URL Escapes a string</summary> 197 /// <summary>RFC1738 URL Escapes a string</summary>
240 /// <param name="data">a string to escape</param> 198 /// <param name="data">a string to escape</param>
241 /// <returns>an RFC1738 escaped string</returns> 199 /// <returns>an RFC1738 escaped string</returns>
242 private static string wasURLEscapeDataString(string data) 200 private static string wasURLEscapeDataString(string data)
243 { 201 {
244 return HttpUtility.UrlEncode(data); 202 return HttpUtility.UrlEncode(data);
245 } 203 }
246   204  
247 /////////////////////////////////////////////////////////////////////////// 205 ///////////////////////////////////////////////////////////////////////////
248 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // 206 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
249 /////////////////////////////////////////////////////////////////////////// 207 ///////////////////////////////////////////////////////////////////////////
250 /// <summary>RFC1738 URL Unescape a string</summary> 208 /// <summary>RFC1738 URL Unescape a string</summary>
251 /// <param name="data">a string to unescape</param> 209 /// <param name="data">a string to unescape</param>
252 /// <returns>an RFC1738 unescaped string</returns> 210 /// <returns>an RFC1738 unescaped string</returns>
253 private static string wasURLUnescapeDataString(string data) 211 private static string wasURLUnescapeDataString(string data)
254 { 212 {
255 return HttpUtility.UrlDecode(data); 213 return HttpUtility.UrlDecode(data);
256 } 214 }
257   215  
258 /////////////////////////////////////////////////////////////////////////// 216 ///////////////////////////////////////////////////////////////////////////
259 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 217 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
260 /////////////////////////////////////////////////////////////////////////// 218 ///////////////////////////////////////////////////////////////////////////
261 /// <summary>URI unescapes an RFC3986 URI escaped string</summary> 219 /// <summary>URI unescapes an RFC3986 URI escaped string</summary>
262 /// <param name="data">a string to unescape</param> 220 /// <param name="data">a string to unescape</param>
263 /// <returns>the resulting string</returns> 221 /// <returns>the resulting string</returns>
264 private static string wasURIUnescapeDataString(string data) 222 private static string wasURIUnescapeDataString(string data)
265 { 223 {
266 // Uri.UnescapeDataString can only handle 32766 characters at a time 224 // Uri.UnescapeDataString can only handle 32766 characters at a time
267 return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766) 225 return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
268 .Select(o => Uri.UnescapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766))))) 226 .Select(o => Uri.UnescapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
269 .ToArray()); 227 .ToArray());
270 } 228 }
271   229  
272 /////////////////////////////////////////////////////////////////////////// 230 ///////////////////////////////////////////////////////////////////////////
273 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 231 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
274 /////////////////////////////////////////////////////////////////////////// 232 ///////////////////////////////////////////////////////////////////////////
275 /// <summary>RFC3986 URI Escapes a string</summary> 233 /// <summary>RFC3986 URI Escapes a string</summary>
276 /// <param name="data">a string to escape</param> 234 /// <param name="data">a string to escape</param>
277 /// <returns>an RFC3986 escaped string</returns> 235 /// <returns>an RFC3986 escaped string</returns>
278 private static string wasURIEscapeDataString(string data) 236 private static string wasURIEscapeDataString(string data)
279 { 237 {
280 // Uri.EscapeDataString can only handle 32766 characters at a time 238 // Uri.EscapeDataString can only handle 32766 characters at a time
281 return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766) 239 return string.Join("", Enumerable.Range(0, (data.Length + 32765)/32766)
282 .Select(o => Uri.EscapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766))))) 240 .Select(o => Uri.EscapeDataString(data.Substring(o*32766, Math.Min(32766, data.Length - (o*32766)))))
283 .ToArray()); 241 .ToArray());
284 } 242 }
285   243  
286 /////////////////////////////////////////////////////////////////////////// 244 ///////////////////////////////////////////////////////////////////////////
287 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 245 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
288 /////////////////////////////////////////////////////////////////////////// 246 ///////////////////////////////////////////////////////////////////////////
289 /// <summary> 247 /// <summary>
290 /// Gets an array element at a given modulo index. 248 /// Gets an array element at a given modulo index.
291 /// </summary> 249 /// </summary>
292 /// <typeparam name="T">the array type</typeparam> 250 /// <typeparam name="T">the array type</typeparam>
293 /// <param name="index">a positive or negative index of the element</param> 251 /// <param name="index">a positive or negative index of the element</param>
294 /// <param name="data">the array</param> 252 /// <param name="data">the array</param>
295 /// <return>an array element</return> 253 /// <return>an array element</return>
296 public static T wasGetElementAt<T>(T[] data, int index) 254 public static T wasGetElementAt<T>(T[] data, int index)
297 { 255 {
298 switch (index < 0) 256 switch (index < 0)
299 { 257 {
300 case true: 258 case true:
301 return data[((index%data.Length) + data.Length)%data.Length]; 259 return data[((index%data.Length) + data.Length)%data.Length];
302 default: 260 default:
303 return data[index%data.Length]; 261 return data[index%data.Length];
304 } 262 }
305 } 263 }
306   264  
307 #region KEY-VALUE DATA 265 #region KEY-VALUE DATA
308   266  
309 /////////////////////////////////////////////////////////////////////////// 267 ///////////////////////////////////////////////////////////////////////////
310 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 268 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
311 /////////////////////////////////////////////////////////////////////////// 269 ///////////////////////////////////////////////////////////////////////////
312 /// <summary> 270 /// <summary>
313 /// Returns the value of a key from a key-value data string. 271 /// Returns the value of a key from a key-value data string.
314 /// </summary> 272 /// </summary>
315 /// <param name="key">the key of the value</param> 273 /// <param name="key">the key of the value</param>
316 /// <param name="data">the key-value data segment</param> 274 /// <param name="data">the key-value data segment</param>
317 /// <returns>true if the key was found in data</returns> 275 /// <returns>true if the key was found in data</returns>
318 private static string wasKeyValueGet(string key, string data) 276 private static string wasKeyValueGet(string key, string data)
319 { 277 {
320 return data.Split('&') 278 return data.Split('&')
321 .AsParallel() 279 .AsParallel()
322 .Select(o => o.Split('=').ToList()) 280 .Select(o => o.Split('=').ToList())
323 .Where(o => o.Count.Equals(2)) 281 .Where(o => o.Count.Equals(2))
324 .Select(o => new 282 .Select(o => new
325 { 283 {
326 k = o.First(), 284 k = o.First(),
327 v = o.Last() 285 v = o.Last()
328 }) 286 })
329 .Where(o => o.k.Equals(key)) 287 .Where(o => o.k.Equals(key))
330 .Select(o => o.v) 288 .Select(o => o.v)
331 .FirstOrDefault(); 289 .FirstOrDefault();
332 } 290 }
333   291  
334 #endregion 292 #endregion
335   -  
336 #region CRYPTOGRAPHY -  
337   -  
338 /////////////////////////////////////////////////////////////////////////// -  
339 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
340 /////////////////////////////////////////////////////////////////////////// -  
341 /// <summary> -  
342 /// Gets a sub-array from an array. -  
343 /// </summary> -  
344 /// <typeparam name="T">the array type</typeparam> -  
345 /// <param name="data">the array</param> -  
346 /// <param name="start">the start index</param> -  
347 /// <param name="stop">the stop index (-1 denotes the end)</param> -  
348 /// <returns>the array slice between start and stop</returns> -  
349 public static T[] wasGetSubArray<T>(T[] data, int start, int stop) -  
350 { -  
351 if (stop.Equals(-1)) -  
352 stop = data.Length - 1; -  
353 T[] result = new T[stop - start + 1]; -  
354 Array.Copy(data, start, result, 0, stop - start + 1); -  
355 return result; -  
356 } -  
357   -  
358 /////////////////////////////////////////////////////////////////////////// -  
359 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
360 /////////////////////////////////////////////////////////////////////////// -  
361 /// <summary> -  
362 /// Delete a sub-array and return the result. -  
363 /// </summary> -  
364 /// <typeparam name="T">the array type</typeparam> -  
365 /// <param name="data">the array</param> -  
366 /// <param name="start">the start index</param> -  
367 /// <param name="stop">the stop index (-1 denotes the end)</param> -  
368 /// <returns>the array without elements between start and stop</returns> -  
369 public static T[] wasDeleteSubArray<T>(T[] data, int start, int stop) -  
370 { -  
371 if (stop.Equals(-1)) -  
372 stop = data.Length - 1; -  
373 T[] result = new T[data.Length - (stop - start) - 1]; -  
374 Array.Copy(data, 0, result, 0, start); -  
375 Array.Copy(data, stop + 1, result, start, data.Length - stop - 1); -  
376 return result; -  
377 } -  
378   -  
379 /////////////////////////////////////////////////////////////////////////// -  
380 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
381 /////////////////////////////////////////////////////////////////////////// -  
382 /// <summary> -  
383 /// Concatenate multiple arrays. -  
384 /// </summary> -  
385 /// <typeparam name="T">the array type</typeparam> -  
386 /// <param name="arrays">multiple arrays</param> -  
387 /// <returns>a flat array with all arrays concatenated</returns> -  
388 public static T[] wasConcatenateArrays<T>(params T[][] arrays) -  
389 { -  
390 int resultLength = 0; -  
391 foreach (T[] o in arrays) -  
392 { -  
393 resultLength += o.Length; -  
394 } -  
395 T[] result = new T[resultLength]; -  
396 int offset = 0; -  
397 for (int x = 0; x < arrays.Length; x++) -  
398 { -  
399 arrays[x].CopyTo(result, offset); -  
400 offset += arrays[x].Length; -  
401 } -  
402 return result; -  
403 } -  
404   -  
405 /////////////////////////////////////////////////////////////////////////// -  
406 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
407 /////////////////////////////////////////////////////////////////////////// -  
408 /// <summary> -  
409 /// Permutes an array in reverse a given number of times. -  
410 /// </summary> -  
411 /// <typeparam name="T">the array type</typeparam> -  
412 /// <param name="input">the array</param> -  
413 /// <param name="times">the number of times to permute</param> -  
414 /// <returns>the array with the elements permuted</returns> -  
415 private static T[] wasReversePermuteArrayElements<T>(T[] input, int times) -  
416 { -  
417 if (times.Equals(0)) return input; -  
418 T[] slice = new T[input.Length]; -  
419 Array.Copy(input, 1, slice, 0, input.Length - 1); -  
420 Array.Copy(input, 0, slice, input.Length - 1, 1); -  
421 return wasReversePermuteArrayElements(slice, --times); -  
422 } -  
423   -  
424 /////////////////////////////////////////////////////////////////////////// -  
425 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
426 /////////////////////////////////////////////////////////////////////////// -  
427 /// <summary> -  
428 /// Permutes an array forward a given number of times. -  
429 /// </summary> -  
430 /// <typeparam name="T">the array type</typeparam> -  
431 /// <param name="input">the array</param> -  
432 /// <param name="times">the number of times to permute</param> -  
433 /// <returns>the array with the elements permuted</returns> -  
434 private static T[] wasForwardPermuteArrayElements<T>(T[] input, int times) -  
435 { -  
436 if (times.Equals(0)) return input; -  
437 T[] slice = new T[input.Length]; -  
438 Array.Copy(input, input.Length - 1, slice, 0, 1); -  
439 Array.Copy(input, 0, slice, 1, input.Length - 1); -  
440 return wasForwardPermuteArrayElements(slice, --times); -  
441 } -  
442   -  
443 /////////////////////////////////////////////////////////////////////////// -  
444 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
445 /////////////////////////////////////////////////////////////////////////// -  
446 /// <summary> -  
447 /// Encrypt or decrypt a message given a set of rotors, plugs and a reflector. -  
448 /// </summary> -  
449 /// <param name="message">the message to encyrpt or decrypt</param> -  
450 /// <param name="rotors">any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g</param> -  
451 /// <param name="plugs">the letter representing the start character for the rotor</param> -  
452 /// <param name="reflector">any one of: B, b, C, c</param> -  
453 /// <returns>either a decrypted or encrypted string</returns> -  
454 private static string wasEnigma(string message, char[] rotors, char[] plugs, char reflector) -  
455 { -  
456 Dictionary<char, char[]> def_rotors = new Dictionary<char, char[]> -  
457 { -  
458 { -  
459 '1', new[] -  
460 { -  
461 'e', 'k', 'm', 'f', 'l', -  
462 'g', 'd', 'q', 'v', 'z', -  
463 'n', 't', 'o', 'w', 'y', -  
464 'h', 'x', 'u', 's', 'p', -  
465 'a', 'i', 'b', 'r', 'c', -  
466 'j' -  
467 } -  
468 }, -  
469 { -  
470 '2', new[] -  
471 { -  
472 'a', 'j', 'd', 'k', 's', -  
473 'i', 'r', 'u', 'x', 'b', -  
474 'l', 'h', 'w', 't', 'm', -  
475 'c', 'q', 'g', 'z', 'n', -  
476 'p', 'y', 'f', 'v', 'o', -  
477 'e' -  
478 } -  
479 }, -  
480 { -  
481 '3', new[] -  
482 { -  
483 'b', 'd', 'f', 'h', 'j', -  
484 'l', 'c', 'p', 'r', 't', -  
485 'x', 'v', 'z', 'n', 'y', -  
486 'e', 'i', 'w', 'g', 'a', -  
487 'k', 'm', 'u', 's', 'q', -  
488 'o' -  
489 } -  
490 }, -  
491 { -  
492 '4', new[] -  
493 { -  
494 'e', 's', 'o', 'v', 'p', -  
495 'z', 'j', 'a', 'y', 'q', -  
496 'u', 'i', 'r', 'h', 'x', -  
497 'l', 'n', 'f', 't', 'g', -  
498 'k', 'd', 'c', 'm', 'w', -  
499 'b' -  
500 } -  
501 }, -  
502 { -  
503 '5', new[] -  
504 { -  
505 'v', 'z', 'b', 'r', 'g', -  
506 'i', 't', 'y', 'u', 'p', -  
507 's', 'd', 'n', 'h', 'l', -  
508 'x', 'a', 'w', 'm', 'j', -  
509 'q', 'o', 'f', 'e', 'c', -  
510 'k' -  
511 } -  
512 }, -  
513 { -  
514 '6', new[] -  
515 { -  
516 'j', 'p', 'g', 'v', 'o', -  
517 'u', 'm', 'f', 'y', 'q', -  
518 'b', 'e', 'n', 'h', 'z', -  
519 'r', 'd', 'k', 'a', 's', -  
520 'x', 'l', 'i', 'c', 't', -  
521 'w' -  
522 } -  
523 }, -  
524 { -  
525 '7', new[] -  
526 { -  
527 'n', 'z', 'j', 'h', 'g', -  
528 'r', 'c', 'x', 'm', 'y', -  
529 's', 'w', 'b', 'o', 'u', -  
530 'f', 'a', 'i', 'v', 'l', -  
531 'p', 'e', 'k', 'q', 'd', -  
532 't' -  
533 } -  
534 }, -  
535 { -  
536 '8', new[] -  
537 { -  
538 'f', 'k', 'q', 'h', 't', -  
539 'l', 'x', 'o', 'c', 'b', -  
540 'j', 's', 'p', 'd', 'z', -  
541 'r', 'a', 'm', 'e', 'w', -  
542 'n', 'i', 'u', 'y', 'g', -  
543 'v' -  
544 } -  
545 }, -  
546 { -  
547 'b', new[] -  
548 { -  
549 'l', 'e', 'y', 'j', 'v', -  
550 'c', 'n', 'i', 'x', 'w', -  
551 'p', 'b', 'q', 'm', 'd', -  
552 'r', 't', 'a', 'k', 'z', -  
553 'g', 'f', 'u', 'h', 'o', -  
554 's' -  
555 } -  
556 }, -  
557 { -  
558 'g', new[] -  
559 { -  
560 'f', 's', 'o', 'k', 'a', -  
561 'n', 'u', 'e', 'r', 'h', -  
562 'm', 'b', 't', 'i', 'y', -  
563 'c', 'w', 'l', 'q', 'p', -  
564 'z', 'x', 'v', 'g', 'j', -  
565 'd' -  
566 } -  
567 } -  
568 }; -  
569   -  
570 Dictionary<char, char[]> def_reflectors = new Dictionary<char, char[]> -  
571 { -  
572 { -  
573 'B', new[] -  
574 { -  
575 'a', 'y', 'b', 'r', 'c', 'u', 'd', 'h', -  
576 'e', 'q', 'f', 's', 'g', 'l', 'i', 'p', -  
577 'j', 'x', 'k', 'n', 'm', 'o', 't', 'z', -  
578 'v', 'w' -  
579 } -  
580 }, -  
581 { -  
582 'b', new[] -  
583 { -  
584 'a', 'e', 'b', 'n', 'c', 'k', 'd', 'q', -  
585 'f', 'u', 'g', 'y', 'h', 'w', 'i', 'j', -  
586 'l', 'o', 'm', 'p', 'r', 'x', 's', 'z', -  
587 't', 'v' -  
588 } -  
589 }, -  
590 { -  
591 'C', new[] -  
592 { -  
593 'a', 'f', 'b', 'v', 'c', 'p', 'd', 'j', -  
594 'e', 'i', 'g', 'o', 'h', 'y', 'k', 'r', -  
595 'l', 'z', 'm', 'x', 'n', 'w', 't', 'q', -  
596 's', 'u' -  
597 } -  
598 }, -  
599 { -  
600 'c', new[] -  
601 { -  
602 'a', 'r', 'b', 'd', 'c', 'o', 'e', 'j', -  
603 'f', 'n', 'g', 't', 'h', 'k', 'i', 'v', -  
604 'l', 'm', 'p', 'w', 'q', 'z', 's', 'x', -  
605 'u', 'y' -  
606 } -  
607 } -  
608 }; -  
609   -  
610 // Setup rotors from plugs. -  
611 foreach (char rotor in rotors) -  
612 { -  
613 char plug = plugs[Array.IndexOf(rotors, rotor)]; -  
614 int i = Array.IndexOf(def_rotors[rotor], plug); -  
615 if (i.Equals(0)) continue; -  
616 def_rotors[rotor] = wasConcatenateArrays(new[] {plug}, -  
617 wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i, i), i, -1), -  
618 wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i + 1, -1), 0, i - 1)); -  
619 } -  
620   -  
621 StringBuilder result = new StringBuilder(); -  
622 foreach (char c in message) -  
623 { -  
624 if (!char.IsLetter(c)) -  
625 { -  
626 result.Append(c); -  
627 continue; -  
628 } -  
629   -  
630 // Normalize to lower. -  
631 char l = char.ToLower(c); -  
632   -  
633 Action<char[]> rotate = o => -  
634 { -  
635 int i = o.Length - 1; -  
636 do -  
637 { -  
638 def_rotors[o[0]] = wasForwardPermuteArrayElements(def_rotors[o[0]], 1); -  
639 if (i.Equals(0)) -  
640 { -  
641 rotors = wasReversePermuteArrayElements(o, 1); -  
642 continue; -  
643 } -  
644 l = wasGetElementAt(def_rotors[o[1]], Array.IndexOf(def_rotors[o[0]], l) - 1); -  
645 o = wasReversePermuteArrayElements(o, 1); -  
646 } while (--i > -1); -  
647 }; -  
648   -  
649 // Forward pass through the Enigma's rotors. -  
650 rotate.Invoke(rotors); -  
651   -  
652 // Reflect -  
653 int x = Array.IndexOf(def_reflectors[reflector], l); -  
654 l = (x + 1)%2 == 0 ? def_reflectors[reflector][x - 1] : def_reflectors[reflector][x + 1]; -  
655   -  
656 // Reverse the order of the rotors. -  
657 Array.Reverse(rotors); -  
658   -  
659 // Reverse pass through the Enigma's rotors. -  
660 rotate.Invoke(rotors); -  
661   -  
662 if (char.IsUpper(c)) -  
663 { -  
664 l = char.ToUpper(l); -  
665 } -  
666 result.Append(l); -  
667 } -  
668   -  
669 return result.ToString(); -  
670 } -  
671   -  
672 /////////////////////////////////////////////////////////////////////////// -  
673 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
674 /////////////////////////////////////////////////////////////////////////// -  
675 /// <summary> -  
676 /// Expand the VIGENRE key to the length of the input. -  
677 /// </summary> -  
678 /// <param name="input">the input to expand to</param> -  
679 /// <param name="enc_key">the key to expand</param> -  
680 /// <returns>the expanded key</returns> -  
681 private static string wasVigenereExpandKey(string input, string enc_key) -  
682 { -  
683 string exp_key = string.Empty; -  
684 int i = 0, j = 0; -  
685 do -  
686 { -  
687 char p = input[i]; -  
688 if (!char.IsLetter(p)) -  
689 { -  
690 exp_key += p; -  
691 ++i; -  
692 continue; -  
693 } -  
694 int m = j%enc_key.Length; -  
695 exp_key += enc_key[m]; -  
696 ++j; -  
697 ++i; -  
698 } while (i < input.Length); -  
699 return exp_key; -  
700 } -  
701   -  
702 /////////////////////////////////////////////////////////////////////////// -  
703 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
704 /////////////////////////////////////////////////////////////////////////// -  
705 /// <summary> -  
706 /// Encrypt using VIGENERE. -  
707 /// </summary> -  
708 /// <param name="input">the input to encrypt</param> -  
709 /// <param name="enc_key">the key to encrypt with</param> -  
710 /// <returns>the encrypted input</returns> -  
711 private static string wasEncryptVIGENERE(string input, string enc_key) -  
712 { -  
713 char[] a = -  
714 { -  
715 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', -  
716 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' -  
717 }; -  
718   -  
719 enc_key = wasVigenereExpandKey(input, enc_key); -  
720 string result = string.Empty; -  
721 int i = 0; -  
722 do -  
723 { -  
724 char p = input[i]; -  
725 if (!char.IsLetter(p)) -  
726 { -  
727 result += p; -  
728 ++i; -  
729 continue; -  
730 } -  
731 char q = -  
732 wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i]))[ -  
733 Array.IndexOf(a, char.ToLowerInvariant(p))]; -  
734 if (char.IsUpper(p)) -  
735 { -  
736 q = char.ToUpperInvariant(q); -  
737 } -  
738 result += q; -  
739 ++i; -  
740 } while (i < input.Length); -  
741 return result; -  
742 } -  
743   -  
744 /////////////////////////////////////////////////////////////////////////// -  
745 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // -  
746 /////////////////////////////////////////////////////////////////////////// -  
747 /// <summary> -  
748 /// Decrypt using VIGENERE. -  
749 /// </summary> -  
750 /// <param name="input">the input to decrypt</param> -  
751 /// <param name="enc_key">the key to decrypt with</param> -  
752 /// <returns>the decrypted input</returns> -  
753 private static string wasDecryptVIGENERE(string input, string enc_key) -  
754 { -  
755 char[] a = -  
756 { -  
757 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', -  
758 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' -  
759 }; -  
760   -  
761 enc_key = wasVigenereExpandKey(input, enc_key); -  
762 string result = string.Empty; -  
763 int i = 0; -  
764 do -  
765 { -  
766 char p = input[i]; -  
767 if (!char.IsLetter(p)) -  
768 { -  
769 result += p; -  
770 ++i; -  
771 continue; -  
772 } -  
773 char q = -  
774 a[ -  
775 Array.IndexOf(wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i])), -  
776 char.ToLowerInvariant(p))]; -  
777 if (char.IsUpper(p)) -  
778 { -  
779 q = char.ToUpperInvariant(q); -  
780 } -  
781 result += q; -  
782 ++i; -  
783 } while (i < input.Length); -  
784 return result; -  
785 } -  
786   -  
787 /////////////////////////////////////////////////////////////////////////// -  
788 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // -  
789 /////////////////////////////////////////////////////////////////////////// -  
790 /// <summary> -  
791 /// An implementation of the ATBASH cypher for latin alphabets. -  
792 /// </summary> -  
793 /// <param name="data">the data to encrypt or decrypt</param> -  
794 /// <returns>the encrypted or decrypted data</returns> -  
795 private static string wasATBASH(string data) -  
796 { -  
797 char[] a = -  
798 { -  
799 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', -  
800 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' -  
801 }; -  
802   -  
803 char[] input = data.ToArray(); -  
804   -  
805 Parallel.ForEach(Enumerable.Range(0, data.Length), i => -  
806 { -  
807 char e = input[i]; -  
808 if (!char.IsLetter(e)) return; -  
809 int x = 25 - Array.BinarySearch(a, char.ToLowerInvariant(e)); -  
810 if (!char.IsUpper(e)) -  
811 { -  
812 input[i] = a[x]; -  
813 return; -  
814 } -  
815 input[i] = char.ToUpperInvariant(a[x]); -  
816 }); -  
817   -  
818 return new string(input); -  
819 } -  
820   -  
821 #endregion -  
822   -  
823 /// <summary> -  
824 /// Corrade's input filter function. -  
825 /// </summary> -  
826 private static readonly Func<string, string> wasInput = o => -  
827 { -  
828 if (string.IsNullOrEmpty(o)) return string.Empty; -  
829   -  
830 foreach (Filter filter in vassalConfiguration.InputFilters) -  
831 { -  
832 switch (filter) -  
833 { -  
834 case Filter.RFC1738: -  
835 o = wasURLUnescapeDataString(o); -  
836 break; -  
837 case Filter.RFC3986: -  
838 o = wasURIUnescapeDataString(o); -  
839 break; -  
840 case Filter.ENIGMA: -  
841 o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(), -  
842 vassalConfiguration.ENIGMA.plugs.ToArray(), -  
843 vassalConfiguration.ENIGMA.reflector); -  
844 break; -  
845 case Filter.VIGENERE: -  
846 o = wasDecryptVIGENERE(o, vassalConfiguration.VIGENERESecret); -  
847 break; -  
848 case Filter.ATBASH: -  
849 o = wasATBASH(o); -  
850 break; -  
851 case Filter.BASE64: -  
852 o = Encoding.UTF8.GetString(Convert.FromBase64String(o)); -  
853 break; -  
854 } -  
855 } -  
856 return o; -  
857 }; -  
858   -  
859 /// <summary> -  
860 /// Corrade's output filter function. -  
861 /// </summary> -  
862 private static readonly Func<string, string> wasOutput = o => -  
863 { -  
864 if (string.IsNullOrEmpty(o)) return string.Empty; -  
865   -  
866 foreach (Filter filter in vassalConfiguration.OutputFilters) -  
867 { -  
868 switch (filter) -  
869 { -  
870 case Filter.RFC1738: -  
871 o = wasURLEscapeDataString(o); -  
872 break; -  
873 case Filter.RFC3986: -  
874 o = wasURIEscapeDataString(o); -  
875 break; -  
876 case Filter.ENIGMA: -  
877 o = wasEnigma(o, vassalConfiguration.ENIGMA.rotors.ToArray(), -  
878 vassalConfiguration.ENIGMA.plugs.ToArray(), -  
879 vassalConfiguration.ENIGMA.reflector); -  
880 break; -  
881 case Filter.VIGENERE: -  
882 o = wasEncryptVIGENERE(o, vassalConfiguration.VIGENERESecret); -  
883 break; -  
884 case Filter.ATBASH: -  
885 o = wasATBASH(o); -  
886 break; -  
887 case Filter.BASE64: -  
888 o = Convert.ToBase64String(Encoding.UTF8.GetBytes(o)); -  
889 break; -  
890 } -  
891 } -  
892 return o; -  
893 }; -  
894   293  
895 /////////////////////////////////////////////////////////////////////////// 294 ///////////////////////////////////////////////////////////////////////////
896 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 295 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
897 /////////////////////////////////////////////////////////////////////////// 296 ///////////////////////////////////////////////////////////////////////////
898 /// <summary>Escapes a dictionary's keys and values for sending as POST data.</summary> 297 /// <summary>Escapes a dictionary's keys and values for sending as POST data.</summary>
899 /// <param name="data">A dictionary containing keys and values to be escaped</param> 298 /// <param name="data">A dictionary containing keys and values to be escaped</param>
900 private static Dictionary<string, string> wasKeyValueEscape(Dictionary<string, string> data) 299 private static Dictionary<string, string> wasKeyValueEscape(Dictionary<string, string> data)
901 { 300 {
902 return data.AsParallel().ToDictionary(o => wasOutput(o.Key), p => wasOutput(p.Value)); 301 return data.AsParallel().ToDictionary(o => wasOutput(o.Key), p => wasOutput(p.Value));
903 } 302 }
904   303  
905 /////////////////////////////////////////////////////////////////////////// 304 ///////////////////////////////////////////////////////////////////////////
906 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 305 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
907 /////////////////////////////////////////////////////////////////////////// 306 ///////////////////////////////////////////////////////////////////////////
908 /// <summary> 307 /// <summary>
909 /// Converts a list of string to a comma-separated values string. 308 /// Converts a list of string to a comma-separated values string.
910 /// </summary> 309 /// </summary>
911 /// <param name="l">a list of strings</param> 310 /// <param name="l">a list of strings</param>
912 /// <returns>a commma-separated list of values</returns> 311 /// <returns>a commma-separated list of values</returns>
913 /// <remarks>compliant with RFC 4180</remarks> 312 /// <remarks>compliant with RFC 4180</remarks>
914 public static string wasEnumerableToCSV(IEnumerable<string> l) 313 public static string wasEnumerableToCSV(IEnumerable<string> l)
915 { 314 {
916 string[] csv = l.Select(o => o.Clone() as string).ToArray(); 315 string[] csv = l.Select(o => o.Clone() as string).ToArray();
917 Parallel.ForEach(csv.Select((v, i) => new {i, v}), o => 316 Parallel.ForEach(csv.Select((v, i) => new {i, v}), o =>
918 { 317 {
919 string cell = o.v.Replace("\"", "\"\""); 318 string cell = o.v.Replace("\"", "\"\"");
920 switch (new[] {'"', ' ', ',', '\r', '\n'}.Any(p => cell.Contains(p))) 319 switch (new[] {'"', ' ', ',', '\r', '\n'}.Any(p => cell.Contains(p)))
921 { 320 {
922 case true: 321 case true:
923 csv[o.i] = "\"" + cell + "\""; 322 csv[o.i] = "\"" + cell + "\"";
924 break; 323 break;
925 default: 324 default:
926 csv[o.i] = cell; 325 csv[o.i] = cell;
927 break; 326 break;
928 } 327 }
929 }); 328 });
930 return String.Join(",", csv); 329 return string.Join(",", csv);
931 } 330 }
932   331  
933 /////////////////////////////////////////////////////////////////////////// 332 ///////////////////////////////////////////////////////////////////////////
934 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 333 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
935 /////////////////////////////////////////////////////////////////////////// 334 ///////////////////////////////////////////////////////////////////////////
936 /// <summary> 335 /// <summary>
937 /// Converts a comma-separated list of values to a list of strings. 336 /// Converts a comma-separated list of values to a list of strings.
938 /// </summary> 337 /// </summary>
939 /// <param name="csv">a comma-separated list of values</param> 338 /// <param name="csv">a comma-separated list of values</param>
940 /// <returns>a list of strings</returns> 339 /// <returns>a list of strings</returns>
941 /// <remarks>compliant with RFC 4180</remarks> 340 /// <remarks>compliant with RFC 4180</remarks>
942 public static IEnumerable<string> wasCSVToEnumerable(string csv) 341 public static IEnumerable<string> wasCSVToEnumerable(string csv)
943 { 342 {
944 Stack<char> s = new Stack<char>(); 343 Stack<char> s = new Stack<char>();
945 StringBuilder m = new StringBuilder(); 344 StringBuilder m = new StringBuilder();
946 for (int i = 0; i < csv.Length; ++i) 345 for (int i = 0; i < csv.Length; ++i)
947 { 346 {
948 switch (csv[i]) 347 switch (csv[i])
949 { 348 {
950 case ',': 349 case ',':
951 if (!s.Any() || !s.Peek().Equals('"')) 350 if (!s.Any() || !s.Peek().Equals('"'))
952 { 351 {
953 yield return m.ToString(); 352 yield return m.ToString();
954 m = new StringBuilder(); 353 m = new StringBuilder();
955 continue; 354 continue;
956 } 355 }
957 m.Append(csv[i]); 356 m.Append(csv[i]);
958 continue; 357 continue;
959 case '"': 358 case '"':
960 if (i + 1 < csv.Length && csv[i].Equals(csv[i + 1])) 359 if (i + 1 < csv.Length && csv[i].Equals(csv[i + 1]))
961 { 360 {
962 m.Append(csv[i]); 361 m.Append(csv[i]);
963 ++i; 362 ++i;
964 continue; 363 continue;
965 } 364 }
966 if (!s.Any() || !s.Peek().Equals(csv[i])) 365 if (!s.Any() || !s.Peek().Equals(csv[i]))
967 { 366 {
968 s.Push(csv[i]); 367 s.Push(csv[i]);
969 continue; 368 continue;
970 } 369 }
971 s.Pop(); 370 s.Pop();
972 continue; 371 continue;
973 } 372 }
974 m.Append(csv[i]); 373 m.Append(csv[i]);
975 } 374 }
976   375  
977 yield return m.ToString(); 376 yield return m.ToString();
978 } 377 }
979   378  
980 /////////////////////////////////////////////////////////////////////////// 379 ///////////////////////////////////////////////////////////////////////////
981 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 380 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
982 /////////////////////////////////////////////////////////////////////////// 381 ///////////////////////////////////////////////////////////////////////////
983 /// <summary> 382 /// <summary>
984 /// Serialises a dictionary to key-value data. 383 /// Serialises a dictionary to key-value data.
985 /// </summary> 384 /// </summary>
986 /// <param name="data">a dictionary</param> 385 /// <param name="data">a dictionary</param>
987 /// <returns>a key-value data encoded string</returns> 386 /// <returns>a key-value data encoded string</returns>
988 private static string wasKeyValueEncode(Dictionary<string, string> data) 387 private static string wasKeyValueEncode(Dictionary<string, string> data)
989 { 388 {
990 return String.Join("&", data.AsParallel().Select(o => String.Join("=", o.Key, o.Value))); 389 return string.Join("&", data.AsParallel().Select(o => string.Join("=", o.Key, o.Value)));
991 } 390 }
992   391  
993 /////////////////////////////////////////////////////////////////////////// 392 ///////////////////////////////////////////////////////////////////////////
994 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 393 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
995 /////////////////////////////////////////////////////////////////////////// 394 ///////////////////////////////////////////////////////////////////////////
996 /// <summary> 395 /// <summary>
997 /// Sends a post request to an URL with set key-value pairs. 396 /// Sends a post request to an URL with set key-value pairs.
998 /// </summary> 397 /// </summary>
999 /// <param name="URL">the url to send the message to</param> 398 /// <param name="URL">the url to send the message to</param>
1000 /// <param name="message">key-value pairs to send</param> 399 /// <param name="message">key-value pairs to send</param>
1001 /// <param name="millisecondsTimeout">the time in milliseconds for the request to timeout</param> 400 /// <param name="millisecondsTimeout">the time in milliseconds for the request to timeout</param>
1002 private static string wasPOST(string URL, Dictionary<string, string> message, uint millisecondsTimeout) 401 private static string wasPOST(string URL, Dictionary<string, string> message, uint millisecondsTimeout)
1003 { 402 {
1004 try 403 try
1005 { 404 {
1006 HttpWebRequest request = (HttpWebRequest) WebRequest.Create(URL); 405 HttpWebRequest request = (HttpWebRequest) WebRequest.Create(URL);
1007 request.UserAgent = VASSAL_CONSTANTS.USER_AGENT; 406 request.UserAgent = VASSAL_CONSTANTS.USER_AGENT;
1008 request.Proxy = WebRequest.DefaultWebProxy; 407 request.Proxy = WebRequest.DefaultWebProxy;
-   408 request.Pipelined = true;
-   409 request.KeepAlive = true;
1009 request.Timeout = (int) millisecondsTimeout; 410 request.Timeout = (int) millisecondsTimeout;
-   411 request.ReadWriteTimeout = (int) millisecondsTimeout;
1010 request.AllowAutoRedirect = true; 412 request.AllowAutoRedirect = true;
1011 request.AllowWriteStreamBuffering = true; 413 request.AllowWriteStreamBuffering = true;
1012 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 414 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
1013 request.Method = WebRequestMethods.Http.Post; 415 request.Method = WebRequestMethods.Http.Post;
1014 // set the content type based on chosen output filers 416 // set the content type based on chosen output filers
1015 switch (vassalConfiguration.OutputFilters.Last()) 417 switch (vassalConfiguration.OutputFilters.Last())
1016 { 418 {
1017 case Filter.RFC1738: 419 case Filter.RFC1738:
1018 request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.WWW_FORM_URLENCODED; 420 request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.WWW_FORM_URLENCODED;
1019 break; 421 break;
1020 default: 422 default:
1021 request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.TEXT_PLAIN; 423 request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.TEXT_PLAIN;
1022 break; 424 break;
1023 } 425 }
1024 // send request 426 // send request
1025 using (Stream requestStream = request.GetRequestStream()) 427 using (Stream requestStream = request.GetRequestStream())
1026 { 428 {
1027 using (StreamWriter dataStream = new StreamWriter(requestStream)) 429 using (StreamWriter dataStream = new StreamWriter(requestStream))
1028 { 430 {
1029 dataStream.Write(wasKeyValueEncode(message)); 431 dataStream.Write(wasKeyValueEncode(message));
1030 } 432 }
1031 } 433 }
1032 // read response 434 // read response
1033 using (HttpWebResponse response = (HttpWebResponse) request.GetResponse()) 435 using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
1034 { 436 {
1035 using (Stream responseStream = response.GetResponseStream()) 437 using (Stream responseStream = response.GetResponseStream())
1036 { 438 {
1037 if (responseStream != null) 439 if (responseStream != null)
1038 { 440 {
1039 using ( 441 using (
1040 StreamReader streamReader = new StreamReader(responseStream)) 442 StreamReader streamReader = new StreamReader(responseStream))
1041 { 443 {
1042 return streamReader.ReadToEnd(); 444 return streamReader.ReadToEnd();
1043 } 445 }
1044 } 446 }
1045 } 447 }
1046 } 448 }
1047 } 449 }
1048 catch (Exception) 450 catch (Exception)
1049 { 451 {
1050   -  
1051 } 452 }
1052   453  
1053 return null; 454 return null;
1054 } 455 }
1055   -  
1056 /// <summary> -  
1057 /// Constants used by Corrade. -  
1058 /// </summary> -  
1059 public struct VASSAL_CONSTANTS -  
1060 { -  
1061 /// <summary> -  
1062 /// Copyright. -  
1063 /// </summary> -  
1064 public const string COPYRIGHT = @"(c) Copyright 2013 Wizardry and Steamworks"; -  
1065   -  
1066 public const string WIZARDRY_AND_STEAMWORKS = @"Wizardry and Steamworks"; -  
1067 public const string VASSAL = @"Vassal"; -  
1068 public const string WIZARDRY_AND_STEAMWORKS_WEBSITE = @"http://grimore.org"; -  
1069   -  
1070 /// <summary> -  
1071 /// Vassal version. -  
1072 /// </summary> -  
1073 public static readonly string VASSAL_VERSION = Assembly.GetEntryAssembly().GetName().Version.ToString(); -  
1074   -  
1075 /// <summary> -  
1076 /// Corrade user agent. -  
1077 /// </summary> -  
1078 public static readonly string USER_AGENT = -  
1079 $"{VASSAL}/{VASSAL_VERSION} ({WIZARDRY_AND_STEAMWORKS_WEBSITE})"; -  
1080   -  
1081 /// <summary> -  
1082 /// Vassal compile date. -  
1083 /// </summary> -  
1084 public static readonly string VASSAL_COMPILE_DATE = new DateTime(2000, 1, 1).Add(new TimeSpan( -  
1085 TimeSpan.TicksPerDay*Assembly.GetEntryAssembly().GetName().Version.Build + // days since 1 January 2000 -  
1086 TimeSpan.TicksPerSecond*2*Assembly.GetEntryAssembly().GetName().Version.Revision)).ToLongDateString(); -  
1087   -  
1088 /// <summary> -  
1089 /// Vassal configuration file. -  
1090 /// </summary> -  
1091 public static readonly string VASSAL_CONFIGURATION_FILE = @"Vassal.ini"; -  
1092   -  
1093 /// <summary> -  
1094 /// Vassal regions file. -  
1095 /// </summary> -  
1096 public static readonly string VASSAL_REGIONS = @"Regions.csv"; -  
1097   -  
1098 /// <summary> -  
1099 /// Conten-types that Corrade can send and receive. -  
1100 /// </summary> -  
1101 public struct CONTENT_TYPE -  
1102 { -  
1103 public const string TEXT_PLAIN = @"text/plain"; -  
1104 public const string WWW_FORM_URLENCODED = @"application/x-www-form-urlencoded"; -  
1105 } -  
1106 } -  
1107   456  
1108 private static readonly System.Action updateCurrentRegionName = () => 457 private void RegionSelected(object sender, EventArgs e)
1109 { 458 {
1110 try 459 new Thread(() =>
1111 { -  
1112 string result = wasPOST(vassalConfiguration.HTTPServerURL, -  
1113 wasKeyValueEscape(new Dictionary<string, string> 460 {
1114 { -  
1115 {"command", "getregiondata"}, -  
1116 {"group", vassalConfiguration.Group}, -  
1117 {"password", vassalConfiguration.Password}, -  
1118 {"data", "Name"} -  
1119 }), 60000); -  
1120 bool success; -  
1121 if (string.IsNullOrEmpty(result) || -  
1122 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 461 try
-   462 {
-   463 // Stop timers.
-   464 vassalTimer.Stop();
-   465 overviewTabTimer.Stop();
-   466 regionsStateTabTimer.Stop();
-   467 residentListTabTimer.Stop();
-   468 estateTopTabTimer.Stop();
-   469 estateTexturesTabTimer.Stop();
-   470  
-   471 Monitor.Enter(ClientInstanceTeleportLock);
-   472  
-   473 string selectedRegionName = string.Empty;
-   474 Vector3 selectedRegionPosition = Vector3.Zero;
1123 { 475 bool startTeleport = false;
1124 vassalForm.BeginInvoke((MethodInvoker) (() => 476 vassalForm.Invoke((MethodInvoker) (() =>
1125 { 477 {
1126 vassalForm.StatusText.Text = @"Failed to query Corrade for current region."; -  
1127 })); -  
1128 return; -  
1129 } -  
1130 switch (success) -  
1131 { -  
1132 case true: 478 ListViewItem listViewItem = LoadedRegionsBox.SelectedItem as ListViewItem;
1133 vassalForm.BeginInvoke((MethodInvoker) (() => 479 switch (listViewItem != null && LoadedRegionsBox.SelectedIndex != -1)
1134 { -  
1135 vassalForm.CurrentRegionAt.Visible = true; -  
1136 vassalForm.CurrentRegionName.Visible = true; -  
1137 vassalForm.CurrentRegionName.Text = -  
1138 wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).Last(); -  
1139 })); -  
1140 break; -  
1141 default: -  
1142 vassalForm.BeginInvoke((MethodInvoker) (() => -  
1143 { -  
1144 vassalForm.CurrentRegionAt.Visible = false; -  
1145 vassalForm.CurrentRegionName.Visible = false; -  
1146 vassalForm.StatusText.Text = @"Error getting current region: " + -  
1147 wasInput(wasKeyValueGet("error", result)); -  
1148 })); -  
1149 break; -  
1150 } -  
1151 } -  
1152 catch (Exception ex) -  
1153 { -  
1154 vassalForm.BeginInvoke((MethodInvoker) (() => -  
1155 { -  
1156 vassalForm.StatusText.Text = -  
1157 @"Error getting current region: " + -  
1158 ex.Message; -  
1159 })); -  
1160 } -  
1161 }; -  
1162   -  
1163 public Vassal() -  
1164 { -  
1165 InitializeComponent(); -  
1166 vassalForm = this; -  
1167 } -  
1168   -  
1169 private void RegionSelected(object sender, EventArgs e) -  
1170 { -  
1171 string selectedRegionName = string.Empty; -  
1172 Vector3 selectedRegionPosition = Vector3.Zero; -  
1173 bool startTeleport = false; -  
1174 vassalForm.Invoke((MethodInvoker) (() => -  
1175 { -  
1176 ListViewItem listViewItem = LoadedRegions.SelectedItem as ListViewItem; -  
1177 switch (listViewItem != null && LoadedRegions.SelectedIndex != -1) -  
1178 { 480 {
1179 case true: 481 case true:
1180 selectedRegionName = listViewItem.Text; 482 selectedRegionName = listViewItem.Text;
1181 selectedRegionPosition = (Vector3) listViewItem.Tag; 483 selectedRegionPosition = (Vector3) listViewItem.Tag;
1182 startTeleport = true; 484 startTeleport = true;
1183 break; 485 break;
1184 default: 486 default:
1185 startTeleport = false; 487 startTeleport = false;
1186 break; 488 break;
1187 } 489 }
1188 })); -  
1189   -  
-   490 }));
1190 if (!startTeleport) return; 491  
1191   492 if (!startTeleport) throw new Exception();
1192   493  
1193 // Announce teleport. 494 // Announce teleport.
1194 vassalForm.Invoke((MethodInvoker) (() => 495 vassalForm.Invoke((MethodInvoker) (() =>
1195 { 496 {
1196 vassalForm.RegionTeleportGroup.Enabled = false; 497 vassalForm.RegionTeleportGroup.Enabled = false;
1197 vassalForm.StatusProgress.Value = 0; -  
1198 vassalForm.StatusText.Text = @"Teleporting to " + selectedRegionName; -  
1199 })); -  
1200   -  
1201 new Thread(() => -  
1202 { 498 vassalForm.StatusProgress.Value = 0;
1203 Monitor.Enter(ClientInstanceTeleportLock); 499 vassalForm.StatusText.Text = @"Teleporting to " + selectedRegionName;
1204 try 500 }));
1205 { 501  
1206 int elapsedSeconds = 0; 502 int elapsedSeconds = 0;
1207 System.Timers.Timer teleportTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 503 Timer teleportTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
1208 teleportTimer.Elapsed += (o, p) => 504 teleportTimer.Elapsed += (o, p) =>
1209 { 505 {
1210 vassalForm.Invoke((MethodInvoker) (() => 506 vassalForm.Invoke((MethodInvoker) (() =>
1211 { 507 {
1212 vassalForm.StatusProgress.Value = 508 vassalForm.StatusProgress.Value =
1213 Math.Min( 509 Math.Min(
1214 (int) 510 (int)
1215 (100d* 511 (100d*
1216 (TimeSpan.FromSeconds(++elapsedSeconds).TotalMilliseconds/ 512 (TimeSpan.FromSeconds(++elapsedSeconds).TotalMilliseconds/
1217 vassalConfiguration.TeleportTimeout)), 100); 513 vassalConfiguration.TeleportTimeout)), 100);
1218 })); 514 }));
1219 }; 515 };
1220 teleportTimer.Start(); 516 teleportTimer.Start();
1221 string result = null; 517 string result = null;
1222 ManualResetEvent receivedPOST = new ManualResetEvent(false); 518 ManualResetEvent receivedPOST = new ManualResetEvent(false);
1223 new Thread(() => 519 new Thread(() =>
1224 { 520 {
1225 result = wasInput(wasPOST(vassalConfiguration.HTTPServerURL, 521 result = wasInput(wasPOST(vassalConfiguration.HTTPServerURL,
1226 wasKeyValueEscape(new Dictionary<string, string> 522 wasKeyValueEscape(new Dictionary<string, string>
1227 { 523 {
1228 {"command", "teleport"}, 524 {"command", "teleport"},
1229 {"group", vassalConfiguration.Group}, 525 {"group", vassalConfiguration.Group},
1230 {"password", vassalConfiguration.Password}, 526 {"password", vassalConfiguration.Password},
1231 {"region", selectedRegionName}, 527 {"region", selectedRegionName},
1232 {"position", selectedRegionPosition.ToString()}, 528 {"position", selectedRegionPosition.ToString()},
1233 {"fly", "True"} 529 {"fly", "True"}
1234 }), vassalConfiguration.TeleportTimeout)); 530 }), vassalConfiguration.TeleportTimeout));
1235 receivedPOST.Set(); 531 receivedPOST.Set();
1236 }) {IsBackground = true}.Start(); 532 }) {IsBackground = true}.Start();
1237 receivedPOST.WaitOne((int) vassalConfiguration.TeleportTimeout, false); 533 receivedPOST.WaitOne((int) vassalConfiguration.TeleportTimeout, false);
1238 teleportTimer.Stop(); 534 teleportTimer.Stop();
1239 switch (!string.IsNullOrEmpty(result) && wasKeyValueGet("success", result) == "True") 535 switch (!string.IsNullOrEmpty(result) && wasKeyValueGet("success", result) == "True")
1240 { 536 {
1241 case true: 537 case true:
1242 vassalForm.Invoke((MethodInvoker) (() => 538 vassalForm.Invoke((MethodInvoker) (() =>
1243 { 539 {
1244 vassalForm.StatusText.Text = @"Now at " + selectedRegionName; 540 vassalForm.StatusText.Text = @"Now at " + selectedRegionName;
1245 vassalForm.CurrentRegionName.Text = selectedRegionName; 541 vassalForm.CurrentRegionName.Text = selectedRegionName;
1246 })); 542 }));
1247 break; 543 break;
1248 default: 544 default:
1249 switch (!string.IsNullOrEmpty(result)) 545 switch (!string.IsNullOrEmpty(result))
1250 { 546 {
1251 case true: 547 case true:
1252 vassalForm.Invoke((MethodInvoker) (() => 548 vassalForm.Invoke((MethodInvoker) (() =>
1253 { 549 {
1254 vassalForm.StatusText.Text = @"Failed teleporting to " + selectedRegionName + 550 vassalForm.StatusText.Text = @"Failed teleporting to " + selectedRegionName +
1255 @": " + 551 @": " +
1256 wasKeyValueGet("error", result); 552 wasKeyValueGet("error", result);
1257 })); 553 }));
1258 break; 554 break;
1259 default: 555 default:
1260 vassalForm.Invoke((MethodInvoker) (() => 556 vassalForm.Invoke(
-   557 (MethodInvoker)
-   558 (() =>
1261 { 559 {
1262 vassalForm.StatusText.Text = @"Failed teleporting to " + selectedRegionName; 560 vassalForm.StatusText.Text = @"Failed teleporting to " +
-   561 selectedRegionName;
1263 })); 562 }));
1264 break; 563 break;
1265 } 564 }
1266 break; 565 break;
1267 } 566 }
1268 } 567 }
1269 catch (Exception ex) 568 catch (Exception ex)
1270 { 569 {
1271 vassalForm.Invoke((MethodInvoker) (() => 570 vassalForm.Invoke(
1272 { 571 (MethodInvoker)
1273 vassalForm.StatusText.Text = @"Error communicating with Corrade: " + ex.Message; 572 (() => { vassalForm.StatusText.Text = @"Error communicating with Corrade: " + ex.Message; }));
1274 })); -  
1275 } 573 }
1276 finally 574 finally
1277 { 575 {
1278 Monitor.Exit(ClientInstanceTeleportLock); -  
1279 vassalForm.BeginInvoke((MethodInvoker) (() => 576 vassalForm.BeginInvoke((MethodInvoker) (() =>
1280 { 577 {
1281 vassalForm.StatusProgress.Value = 100; 578 vassalForm.StatusProgress.Value = 100;
1282 vassalForm.RegionTeleportGroup.Enabled = true; 579 vassalForm.RegionTeleportGroup.Enabled = true;
1283 // Set the map image to the loading spinner. 580 // Set the map image to the loading spinner.
1284 Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); 581 Assembly thisAssembly = Assembly.GetExecutingAssembly();
1285 System.IO.Stream file = 582 Stream file =
1286 thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif"); 583 thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif");
1287 switch (file != null) 584 switch (file != null)
1288 { 585 {
1289 case true: 586 case true:
1290 vassalForm.Invoke((MethodInvoker) (() => 587 vassalForm.Invoke((MethodInvoker) (() =>
1291 { 588 {
1292 RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage; 589 RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage;
1293 RegionAvatarsMap.Image = Image.FromStream(file); 590 RegionAvatarsMap.Image = Image.FromStream(file);
1294 RegionAvatarsMap.Refresh(); 591 RegionAvatarsMap.Refresh();
1295 })); 592 }));
1296 break; 593 break;
1297 } 594 }
1298 // Clear the resident list table. 595 // Clear the resident list table.
1299 ResidentListGridView.Rows.Clear(); 596 ResidentListGridView.Rows.Clear();
1300 // Clear the top scripts table. 597 // Clear the top scripts table.
1301 TopScriptsGridView.Rows.Clear(); 598 TopScriptsGridView.Rows.Clear();
1302 // Clear the top colliders table. 599 // Clear the top colliders table.
1303 TopCollidersGridView.Rows.Clear(); 600 TopCollidersGridView.Rows.Clear();
-   601 // Clear the estate list table.
-   602 EstateListGridView.Rows.Clear();
-   603 // Clear the estate list selection box.
-   604 EstateListSelectBox.SelectedIndex = -1;
1304 // Invalidate data for overview tab. 605 // Invalidate data for overview tab.
1305 vassalForm.CurrentRegionAt.Visible = false; 606 vassalForm.CurrentRegionAt.Visible = false;
1306 vassalForm.CurrentRegionName.Visible = false; 607 vassalForm.CurrentRegionName.Visible = false;
1307 Agents.Text = string.Empty; 608 Agents.Text = string.Empty;
1308 Agents.Enabled = false; 609 Agents.Enabled = false;
1309 LastLag.Text = string.Empty; 610 LastLag.Text = string.Empty;
1310 LastLag.Enabled = false; 611 LastLag.Enabled = false;
1311 Dilation.Text = string.Empty; 612 Dilation.Text = string.Empty;
1312 Dilation.Enabled = false; 613 Dilation.Enabled = false;
1313 FPS.Text = string.Empty; 614 FPS.Text = string.Empty;
1314 FPS.Enabled = false; 615 FPS.Enabled = false;
1315 PhysicsFPS.Text = string.Empty; 616 PhysicsFPS.Text = string.Empty;
1316 PhysicsFPS.Enabled = false; 617 PhysicsFPS.Enabled = false;
1317 ActiveScripts.Text = string.Empty; 618 ActiveScripts.Text = string.Empty;
1318 ActiveScripts.Enabled = false; 619 ActiveScripts.Enabled = false;
1319 ScriptTime.Text = string.Empty; 620 ScriptTime.Text = string.Empty;
1320 ScriptTime.Enabled = false; 621 ScriptTime.Enabled = false;
1321 Objects.Text = string.Empty; 622 Objects.Text = string.Empty;
1322 Objects.Enabled = false; 623 Objects.Enabled = false;
1323 })); 624 }));
-   625  
-   626 Monitor.Exit(ClientInstanceTeleportLock);
-   627  
-   628 // start timers
-   629 vassalTimer.Start();
-   630 overviewTabTimer.Start();
-   631 regionsStateTabTimer.Start();
-   632 residentListTabTimer.Start();
-   633 estateTopTabTimer.Start();
-   634 estateTexturesTabTimer.Start();
1324 } 635 }
1325 }) 636 })
1326 {IsBackground = true}.Start(); 637 {IsBackground = true}.Start();
1327 } 638 }
1328   639  
1329 private void SettingsRequested(object sender, EventArgs e) 640 private void SettingsRequested(object sender, EventArgs e)
1330 { 641 {
-   642 vassalForm.BeginInvoke((MethodInvoker) (() => { VassalStatusGroup.Enabled = false; }));
1331 SettingsForm settingsForm = new SettingsForm {TopMost = true}; 643 SettingsForm settingsForm = new SettingsForm {TopMost = true};
1332 settingsForm.Show(); 644 settingsForm.Show();
1333 } 645 }
1334   646  
1335 private void VassalShown(object sender, EventArgs e) 647 private void VassalShown(object sender, EventArgs e)
1336 { 648 {
1337 // Set the version 649 // Set the version
1338 vassalForm.Version.Text = @"v" + VASSAL_CONSTANTS.VASSAL_VERSION; 650 vassalForm.Version.Text = @"v" + VASSAL_CONSTANTS.VASSAL_VERSION;
1339   651  
1340 // Disable estate manager tabs since we will enable these dynamically. 652 // Disable estate manager tabs since we will enable these dynamically.
1341 TopScriptsTab.Enabled = false; 653 EstateTopTab.Enabled = false;
1342 TopCollidersTab.Enabled = false; 654 EstateListsTab.Enabled = false;
1343 ResidentListBanGroup.Enabled = false; 655 ResidentListBanGroup.Enabled = false;
-   656 EstateTerrainDownloadUploadGroup.Enabled = false;
-   657 // Estate textures
-   658 RegionTexturesLowUUIDApplyBox.Enabled = false;
-   659 RegionTexturesLowUUIDApplyButton.Enabled = false;
-   660 RegionTexturesMiddleLowUUIDApplyBox.Enabled = false;
-   661 RegionTexturesMiddleLowUUIDApplyButton.Enabled = false;
-   662 RegionTexturesMiddleHighUUIDApplyBox.Enabled = false;
-   663 RegionTexturesMiddleHighUUIDApplyButton.Enabled = false;
-   664 RegionTexturesHighUUIDApplyBox.Enabled = false;
-   665 RegionTexturesHighUUIDApplyButton.Enabled = false;
1344   666  
1345 // Get the configuration file settings if it exists. 667 // Get the configuration file settings if it exists.
1346 if (File.Exists(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE)) 668 if (File.Exists(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE))
1347 { 669 {
1348 // Load the configuration. 670 // Load the configuration.
1349 VassalConfiguration.Load(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE, ref vassalConfiguration); 671 VassalConfiguration.Load(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE, ref vassalConfiguration);
1350 // Apply settings 672 // Apply settings
1351 RegionRestartDelayBox.Text = vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture); 673 RegionRestartDelayBox.Text = vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture);
1352 } 674 }
1353   -  
1354 // Spawn a thread to check Corrade's connection status. -  
1355 new Thread(() => -  
1356 { -  
1357 TcpClient tcpClient = new TcpClient(); -  
1358 try -  
1359 { -  
1360 System.Uri uri = new System.Uri(vassalConfiguration.HTTPServerURL); -  
1361 tcpClient.Connect(uri.Host, uri.Port); -  
1362 // port open -  
1363 vassalForm.BeginInvoke((MethodInvoker) (() => { Tabs.Enabled = true; })); -  
1364 // set the loading spinner -  
1365 Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); -  
1366 System.IO.Stream file = -  
1367 thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif"); -  
1368 switch (file != null) -  
1369 { -  
1370 case true: -  
1371 vassalForm.BeginInvoke((MethodInvoker) (() => -  
1372 { -  
1373 RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage; -  
1374 RegionAvatarsMap.Image = Image.FromStream(file); -  
1375 RegionAvatarsMap.Refresh(); -  
1376 })); -  
1377 break; -  
1378 } -  
1379 } -  
1380 catch (Exception) -  
1381 { -  
1382 // port closed -  
1383 vassalForm.BeginInvoke((MethodInvoker) (() => { Tabs.Enabled = false; })); -  
1384 } -  
1385 }) -  
1386 {IsBackground = true}.Start(); -  
1387   675  
1388 // Get all the regions if they exist. 676 // Get all the regions if they exist.
1389 if (File.Exists(VASSAL_CONSTANTS.VASSAL_REGIONS)) 677 if (File.Exists(VASSAL_CONSTANTS.VASSAL_REGIONS))
1390 { 678 {
1391 Vector3 localPosition; 679 Vector3 localPosition;
1392 List<KeyValuePair<string, Vector3>> ConfiguredRegions = new List<KeyValuePair<string, Vector3>>( 680 List<KeyValuePair<string, Vector3>> ConfiguredRegions = new List<KeyValuePair<string, Vector3>>(
1393 File.ReadAllLines(VASSAL_CONSTANTS.VASSAL_REGIONS) 681 File.ReadAllLines(VASSAL_CONSTANTS.VASSAL_REGIONS)
1394 .Select(o => new List<string>(wasCSVToEnumerable(o))) 682 .Select(o => new List<string>(wasCSVToEnumerable(o)))
1395 .Where(o => o.Count == 2) 683 .Where(o => o.Count == 2)
1396 .ToDictionary(o => o.First(), 684 .ToDictionary(o => o.First(),
1397 p => 685 p =>
1398 Vector3.TryParse(p.Last(), out localPosition) 686 Vector3.TryParse(p.Last(), out localPosition)
1399 ? localPosition 687 ? localPosition
1400 : Vector3.Zero).OrderBy(o => o.Key).ToDictionary(o => o.Key, o => o.Value)); 688 : Vector3.Zero).OrderBy(o => o.Key).ToDictionary(o => o.Key, o => o.Value));
1401 // Populate the loaded regions. 689 // Populate the loaded regions.
1402 LoadedRegions.Items.Clear(); 690 LoadedRegionsBox.Items.Clear();
1403 LoadedRegions.Items.AddRange( 691 LoadedRegionsBox.Items.AddRange(
1404 ConfiguredRegions.Select(o => (object) new ListViewItem {Text = o.Key, Tag = o.Value}) 692 ConfiguredRegions.Select(o => (object) new ListViewItem {Text = o.Key, Tag = o.Value})
1405 .ToArray()); 693 .ToArray());
1406 // Populate the batch restart grid view. 694 // Populate the batch restart grid view.
1407 BatchRestartGridView.Rows.Clear(); 695 BatchRestartGridView.Rows.Clear();
1408 foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions) 696 foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions)
1409 { 697 {
1410 BatchRestartGridView.Rows.Add(data.Key, data.Value.ToString()); 698 BatchRestartGridView.Rows.Add(data.Key, data.Value.ToString());
1411 } 699 }
1412 // Populate the regions state grid view. 700 // Populate the regions state grid view.
1413 foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions) 701 foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions)
1414 { 702 {
1415 RegionsStateGridView.Rows.Add(data.Key, "Check pening..."); 703 RegionsStateGridView.Rows.Add(data.Key, "Check pening...");
1416 } 704 }
1417 } 705 }
1418   706  
1419 // Start the overview timer. 707 // Start the vassal timer.
1420 overviewTabTimer.Elapsed += (o, p) => 708 vassalTimer.Elapsed += (o, p) =>
1421 { 709 {
1422 if (!Monitor.TryEnter(ClientInstanceTeleportLock)) 710 if (!Monitor.TryEnter(ClientInstanceTeleportLock))
1423 return; 711 return;
1424   -  
1425 try 712 try
1426 { 713 {
1427 // Always run the overview regardless which tab is active. 714 // Check Corrade connection status.
-   715 TcpClient tcpClient = new TcpClient();
-   716 Uri uri = new Uri(vassalConfiguration.HTTPServerURL);
-   717 tcpClient.Connect(uri.Host, uri.Port);
-   718 // port open
-   719 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   720 {
-   721 vassalForm.CurrentRegionAt.Visible = true;
-   722 vassalForm.CurrentRegionName.Visible = true;
-   723 Assembly thisAssembly = Assembly.GetExecutingAssembly();
-   724 Stream file =
-   725 thisAssembly.GetManifestResourceStream("Vassal.img.online.png");
-   726 switch (file != null)
-   727 {
-   728 case true:
-   729 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   730 {
-   731 ConnectionStatusPictureBox.Image = Image.FromStream(file);
-   732 ConnectionStatusPictureBox.Refresh();
-   733 }));
-   734 break;
-   735 }
-   736 Tabs.Enabled = true;
-   737 }));
-   738 }
-   739 catch (Exception)
-   740 {
-   741 // port closed
-   742 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   743 {
-   744 vassalForm.CurrentRegionAt.Visible = false;
-   745 vassalForm.CurrentRegionName.Visible = false;
-   746 Assembly thisAssembly = Assembly.GetExecutingAssembly();
-   747 Stream file =
-   748 thisAssembly.GetManifestResourceStream("Vassal.img.offline.png");
-   749 switch (file != null)
-   750 {
-   751 case true:
-   752 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   753 {
-   754 ConnectionStatusPictureBox.Image = Image.FromStream(file);
-   755 ConnectionStatusPictureBox.Refresh();
-   756 }));
-   757 break;
-   758 }
-   759 Tabs.Enabled = false;
-   760 }));
-   761 }
-   762  
-   763 try
1428   764 {
1429 // Get the statistics. 765 // Get the simulator name and if we are an estate manager.
1430 string result = wasPOST(vassalConfiguration.HTTPServerURL, 766 string result = wasPOST(vassalConfiguration.HTTPServerURL,
1431 wasKeyValueEscape(new Dictionary<string, string> 767 wasKeyValueEscape(new Dictionary<string, string>
1432 { 768 {
1433 {"command", "getregiondata"}, 769 {"command", "getregiondata"},
1434 {"group", vassalConfiguration.Group}, 770 {"group", vassalConfiguration.Group},
1435 {"password", vassalConfiguration.Password}, 771 {"password", vassalConfiguration.Password},
1436 { 772 {
1437 "data", wasEnumerableToCSV(new[] 773 "data", wasEnumerableToCSV(new[]
1438 { 774 {
1439 "Agents", -  
1440 "LastLag", -  
1441 "Dilation", -  
1442 "FPS", -  
1443 "PhysicsFPS", -  
1444 "ActiveScripts", -  
1445 "ScriptTime", -  
1446 "Objects", -  
1447 "Name", 775 "Name",
1448 "IsEstateManager" 776 "IsEstateManager"
1449 }) 777 })
1450 } 778 }
1451 }), vassalConfiguration.DataTimeout); 779 }), vassalConfiguration.DataTimeout);
1452   780  
1453 bool success; 781 bool success;
1454 if (string.IsNullOrEmpty(result) || 782 if (string.IsNullOrEmpty(result) ||
1455 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 783 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1456 throw new Exception(); 784 throw new Exception();
1457   785  
1458 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList(); 786 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
1459 if (data.Count.Equals(0)) 787 if (data.Count.Equals(0))
1460 throw new Exception(); 788 throw new Exception();
1461   789  
1462 vassalForm.BeginInvoke((MethodInvoker) (() => 790 vassalForm.BeginInvoke((MethodInvoker) (() =>
1463 { 791 {
1464 // Drop access to features if we are not estate managers. 792 // Drop access to features if we are not estate managers.
1465 bool isEstateManager; 793 bool isEstateManager;
1466 switch ( 794 switch (
1467 bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) && 795 bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) &&
1468 isEstateManager) 796 isEstateManager)
1469 { 797 {
1470 case true: // we are an estate manager 798 case true: // we are an estate manager
1471 TopScriptsTab.Enabled = true; 799 EstateTopTab.Enabled = true;
1472 TopCollidersTab.Enabled = true; 800 EstateListsTab.Enabled = true;
1473 ResidentListBanGroup.Enabled = true; 801 ResidentListBanGroup.Enabled = true;
-   802 EstateTerrainDownloadUploadGroup.Enabled = true;
-   803 RegionToolsRegionDebugGroup.Enabled = true;
-   804 RegionToolsRegionInfoGroup.Enabled = true;
-   805 // Estate textures
-   806 RegionTexturesLowUUIDApplyBox.Enabled = true;
-   807 RegionTexturesLowUUIDApplyButton.Enabled = true;
-   808 RegionTexturesMiddleLowUUIDApplyBox.Enabled = true;
-   809 RegionTexturesMiddleLowUUIDApplyButton.Enabled = true;
-   810 RegionTexturesMiddleHighUUIDApplyBox.Enabled = true;
-   811 RegionTexturesMiddleHighUUIDApplyButton.Enabled = true;
-   812 RegionTexturesHighUUIDApplyBox.Enabled = true;
-   813 RegionTexturesHighUUIDApplyButton.Enabled = true;
1474 break; 814 break;
1475 default: 815 default:
1476 TopScriptsTab.Enabled = false; 816 EstateTopTab.Enabled = false;
1477 TopCollidersTab.Enabled = false; 817 EstateListsTab.Enabled = false;
1478 ResidentListBanGroup.Enabled = false; 818 ResidentListBanGroup.Enabled = false;
-   819 EstateTerrainDownloadUploadGroup.Enabled = false;
-   820 RegionToolsRegionDebugGroup.Enabled = false;
-   821 RegionToolsRegionInfoGroup.Enabled = false;
-   822 // Estate textures
-   823 RegionTexturesLowUUIDApplyBox.Enabled = false;
-   824 RegionTexturesLowUUIDApplyButton.Enabled = false;
-   825 RegionTexturesMiddleLowUUIDApplyBox.Enabled = false;
-   826 RegionTexturesMiddleLowUUIDApplyButton.Enabled = false;
-   827 RegionTexturesMiddleHighUUIDApplyBox.Enabled = false;
-   828 RegionTexturesMiddleHighUUIDApplyButton.Enabled = false;
-   829 RegionTexturesHighUUIDApplyBox.Enabled = false;
-   830 RegionTexturesHighUUIDApplyButton.Enabled = false;
1479 break; 831 break;
1480 } 832 }
1481   833  
1482 // Show the region name. 834 // Show the region name.
1483 vassalForm.CurrentRegionName.Text = data[data.IndexOf("Name") + 1]; 835 vassalForm.CurrentRegionName.Text = data[data.IndexOf("Name") + 1];
1484 vassalForm.CurrentRegionAt.Visible = true; 836 vassalForm.CurrentRegionAt.Visible = true;
1485 vassalForm.CurrentRegionName.Visible = true; 837 vassalForm.CurrentRegionName.Visible = true;
-   838 }));
-   839 }
-   840 catch (Exception)
-   841 {
-   842 }
-   843  
-   844 Monitor.Exit(ClientInstanceTeleportLock);
-   845 };
-   846 vassalTimer.Start();
-   847  
-   848 // Start the overview timer.
-   849 overviewTabTimer.Elapsed += (o, p) =>
-   850 {
-   851 // Do not do anything in case the tab is not selected.
-   852 bool run = false;
-   853 vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(OverviewTab); }));
-   854  
-   855 if (!run)
-   856 {
-   857 overviewTabTimer.Stop();
-   858 return;
-   859 }
-   860  
-   861 overviewTabTimer.Stop();
-   862  
-   863 try
-   864 {
-   865 // Get the statistics.
-   866 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   867 wasKeyValueEscape(new Dictionary<string, string>
-   868 {
-   869 {"command", "getregiondata"},
-   870 {"group", vassalConfiguration.Group},
-   871 {"password", vassalConfiguration.Password},
-   872 {
-   873 "data", wasEnumerableToCSV(new[]
-   874 {
-   875 "Agents",
-   876 "LastLag",
-   877 "Dilation",
-   878 "FPS",
-   879 "PhysicsFPS",
-   880 "ActiveScripts",
-   881 "ScriptTime",
-   882 "Objects",
-   883 "AvatarPositions"
-   884 })
-   885 }
-   886 }), vassalConfiguration.DataTimeout);
-   887  
-   888 bool success;
-   889 if (string.IsNullOrEmpty(result) ||
-   890 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   891 throw new Exception();
-   892  
-   893 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
-   894 if (data.Count.Equals(0))
-   895 throw new Exception();
-   896  
-   897 vassalForm.BeginInvoke((MethodInvoker) (() =>
1486   898 {
1487 // Populate the overview tab. 899 // Populate the overview tab.
1488 Agents.Text = data[data.IndexOf("Agents") + 1]; 900 Agents.Text = data[data.IndexOf("Agents") + 1];
1489 Agents.Enabled = true; 901 Agents.Enabled = true;
1490 LastLag.Text = data[data.IndexOf("LastLag") + 1]; 902 LastLag.Text = data[data.IndexOf("LastLag") + 1];
1491 LastLag.Enabled = true; 903 LastLag.Enabled = true;
1492 Dilation.Text = data[data.IndexOf("Dilation") + 1]; 904 Dilation.Text = data[data.IndexOf("Dilation") + 1];
1493 Dilation.Enabled = true; 905 Dilation.Enabled = true;
1494 FPS.Text = data[data.IndexOf("FPS") + 1]; 906 FPS.Text = data[data.IndexOf("FPS") + 1];
1495 FPS.Enabled = true; 907 FPS.Enabled = true;
1496 PhysicsFPS.Text = data[data.IndexOf("PhysicsFPS") + 1]; 908 PhysicsFPS.Text = data[data.IndexOf("PhysicsFPS") + 1];
1497 PhysicsFPS.Enabled = true; 909 PhysicsFPS.Enabled = true;
1498 ActiveScripts.Text = data[data.IndexOf("ActiveScripts") + 1]; 910 ActiveScripts.Text = data[data.IndexOf("ActiveScripts") + 1];
1499 ActiveScripts.Enabled = true; 911 ActiveScripts.Enabled = true;
1500 ScriptTime.Text = data[data.IndexOf("ScriptTime") + 1]; 912 ScriptTime.Text = data[data.IndexOf("ScriptTime") + 1];
1501 ScriptTime.Enabled = true; 913 ScriptTime.Enabled = true;
1502 Objects.Text = data[data.IndexOf("Objects") + 1]; 914 Objects.Text = data[data.IndexOf("Objects") + 1];
1503 Objects.Enabled = true; 915 Objects.Enabled = true;
1504 })); 916 }));
-   917  
-   918 // Get avatar positions.
-   919 // Pattern: [...], X, 10, Y, 63, Z, 200, [...], X, 52, Y, 73, Z, 55, [...[...]]
-   920 float X = 0, Y = 0, Z = 0;
-   921 List<Vector3> positions = data.Select((x, i) => new {Item = x, Index = i})
-   922 .Where(x => x.Item.Equals("X") || x.Item.Equals("Y") || x.Item.Equals("Z"))
-   923 .Select(z => data[z.Index + 1]).Select((x, i) => new {Value = x, Index = i})
-   924 .GroupBy(x => x.Index/3)
-   925 .Select(x => x.Select(v => v.Value).ToList())
-   926 .Where(
-   927 x =>
-   928 float.TryParse(x[0], out X) && float.TryParse(x[1], out Y) &&
-   929 float.TryParse(x[2], out Z))
-   930 .Select(x => new Vector3(X, Y, Z))
-   931 .ToList();
1505   932  
1506 // Get the map image. 933 // Get the map image.
1507 result = wasPOST(vassalConfiguration.HTTPServerURL, 934 result = wasPOST(vassalConfiguration.HTTPServerURL,
1508 wasKeyValueEscape(new Dictionary<string, string> 935 wasKeyValueEscape(new Dictionary<string, string>
1509 { 936 {
1510 {"command", "getgridregiondata"}, 937 {"command", "getgridregiondata"},
1511 {"group", vassalConfiguration.Group}, 938 {"group", vassalConfiguration.Group},
1512 {"password", vassalConfiguration.Password}, 939 {"password", vassalConfiguration.Password},
1513 {"data", "MapImageID"} 940 {"data", "MapImageID"}
1514 }), vassalConfiguration.DataTimeout); 941 }), vassalConfiguration.DataTimeout);
1515   942  
1516 if (string.IsNullOrEmpty(result) || 943 if (string.IsNullOrEmpty(result) ||
1517 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 944 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1518 throw new Exception(); 945 throw new Exception();
1519   946  
1520 data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList(); 947 data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
1521 if (!data.Count.Equals(2)) 948 if (!data.Count.Equals(2))
1522 throw new Exception(); 949 throw new Exception();
1523 result = wasPOST(vassalConfiguration.HTTPServerURL, 950 result = wasPOST(vassalConfiguration.HTTPServerURL,
1524 wasKeyValueEscape(new Dictionary<string, string> 951 wasKeyValueEscape(new Dictionary<string, string>
1525 { 952 {
1526 {"command", "download"}, 953 {"command", "download"},
1527 {"group", vassalConfiguration.Group}, 954 {"group", vassalConfiguration.Group},
1528 {"password", vassalConfiguration.Password}, 955 {"password", vassalConfiguration.Password},
1529 {"item", data.Last()}, 956 {"item", data.Last()},
1530 {"type", "Texture"}, 957 {"type", "Texture"},
1531 {"format", "Jpeg"}, 958 {"format", "Jpeg"}
1532 }), vassalConfiguration.DataTimeout); 959 }), vassalConfiguration.DataTimeout);
1533 if (string.IsNullOrEmpty(result) || 960 if (string.IsNullOrEmpty(result) ||
1534 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 961 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1535 throw new Exception(); 962 throw new Exception();
1536 byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result))); 963 byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
1537 Image mapImage; 964 Image mapImage;
1538 using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length)) 965 using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
1539 { 966 {
1540 mapImage = Image.FromStream(memoryStream); 967 mapImage = Image.FromStream(memoryStream);
1541 } 968 }
1542   -  
1543 // Get the avatar positions. -  
1544 result = wasPOST(vassalConfiguration.HTTPServerURL, -  
1545 wasKeyValueEscape(new Dictionary<string, string> -  
1546 { -  
1547 {"command", "getavatarpositions"}, -  
1548 {"group", vassalConfiguration.Group}, -  
1549 {"password", vassalConfiguration.Password}, -  
1550 {"entity", "region"} -  
1551 }), vassalConfiguration.DataTimeout); -  
1552   -  
1553 if (string.IsNullOrEmpty(result) || -  
1554 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) -  
1555 throw new Exception(); -  
1556   -  
1557 // Every thrid element represents a Vecto3 of the avatar position. -  
1558 data = -  
1559 wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))) -  
1560 .Skip(2) -  
1561 .Where((x, i) => i%3 == 0) -  
1562 .ToList(); -  
1563   969  
1564 // Draw the avatars onto the map. 970 // Draw the avatars onto the map.
1565 Graphics mapGraphics = Graphics.FromImage(mapImage); -  
1566 Vector3 position; 971 Graphics mapGraphics = Graphics.FromImage(mapImage);
1567 foreach (string vector in data) 972 foreach (Vector3 position in positions)
1568 { -  
1569 switch (Vector3.TryParse(vector, out position)) -  
1570 { -  
1571 case true: 973 {
1572 mapGraphics.FillEllipse(Brushes.Chartreuse, 974 mapGraphics.FillEllipse(Brushes.Chartreuse,
1573 new Rectangle((int) position.X, (int) position.Y, 4, 4)); -  
1574 break; -  
1575 } 975 new Rectangle((int) position.X, (int) position.Y, 4, 4));
1576 } 976 }
1577 mapGraphics.DrawImage(mapImage, new Point(0, 0)); 977 mapGraphics.DrawImage(mapImage, new Point(0, 0));
1578   978  
1579 vassalForm.BeginInvoke((MethodInvoker) (() => 979 vassalForm.BeginInvoke((MethodInvoker) (() =>
1580 { 980 {
1581 RegionAvatarsMap.SizeMode = PictureBoxSizeMode.StretchImage; 981 RegionAvatarsMap.SizeMode = PictureBoxSizeMode.StretchImage;
1582 RegionAvatarsMap.Image = mapImage; 982 RegionAvatarsMap.Image = mapImage;
1583 RegionAvatarsMap.Refresh(); 983 RegionAvatarsMap.Refresh();
1584 })); 984 }));
1585 } 985 }
1586 catch (Exception) 986 catch (Exception)
1587 { 987 {
1588   -  
1589 } -  
1590 finally -  
1591 { -  
1592 Monitor.Exit(ClientInstanceTeleportLock); -  
1593 } 988 }
-   989  
1594   990 overviewTabTimer.Start();
1595 }; 991 };
1596 overviewTabTimer.Start(); 992 overviewTabTimer.Start();
1597   993  
1598 regionsStateTabTimer.Elapsed += (o, p) => 994 regionsStateTabTimer.Elapsed += (o, p) =>
1599 { 995 {
1600 // Do not do anything in case the tab is not selected. 996 // Do not do anything in case the tab is not selected.
1601 bool run = false; 997 bool run = false;
1602 vassalForm.Invoke((MethodInvoker) (() => -  
1603 { -  
1604 run = Tabs.SelectedTab.Equals(RegionsStateTab); 998 vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(RegionsStateTab); }));
1605 })); -  
1606 if (!run) return; -  
-   999  
-   1000 if (!run)
1607   1001 {
1608 if (!Monitor.TryEnter(RegionsStateCheckLock)) 1002 regionsStateTabTimer.Stop();
-   1003 return;
-   1004 }
-   1005  
1609 return; 1006 regionsStateTabTimer.Stop();
1610   1007  
1611 try 1008 try
1612 { 1009 {
1613 string regionName = string.Empty; 1010 string regionName = string.Empty;
1614 vassalForm.Invoke((MethodInvoker) (() => 1011 vassalForm.Invoke((MethodInvoker) (() =>
1615 { 1012 {
1616 regionName = 1013 regionName =
1617 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateRegionName"].Value 1014 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateRegionName"].Value
1618 .ToString(); 1015 .ToString();
-   1016 RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
-   1017 Color.Gold;
1619 })); 1018 }));
1620   1019  
1621 if (string.IsNullOrEmpty(regionName)) 1020 if (string.IsNullOrEmpty(regionName))
1622 throw new Exception(); 1021 throw new Exception();
1623   1022  
1624 // Get the region status. 1023 // Get the region status.
1625 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1024 string result = wasPOST(vassalConfiguration.HTTPServerURL,
1626 wasKeyValueEscape(new Dictionary<string, string> 1025 wasKeyValueEscape(new Dictionary<string, string>
1627 { 1026 {
1628 {"command", "getgridregiondata"}, 1027 {"command", "getgridregiondata"},
1629 {"group", vassalConfiguration.Group}, 1028 {"group", vassalConfiguration.Group},
1630 {"password", vassalConfiguration.Password}, 1029 {"password", vassalConfiguration.Password},
1631 {"region", regionName}, 1030 {"region", regionName},
1632 {"data", "Access"} 1031 {"data", "Access"}
1633 }), vassalConfiguration.DataTimeout); 1032 }), vassalConfiguration.DataTimeout);
1634   1033  
1635 bool success; 1034 bool success;
1636 if (string.IsNullOrEmpty(result) || 1035 if (string.IsNullOrEmpty(result) ||
1637 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1036 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1638 throw new Exception(); 1037 throw new Exception();
1639   1038  
1640 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList(); 1039 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
1641 if (!data.Count.Equals(2)) 1040 if (!data.Count.Equals(2))
1642 throw new Exception(); 1041 throw new Exception();
1643   1042  
1644 string status = data.Last(); 1043 string status = data.Last();
1645 vassalForm.Invoke((MethodInvoker) (() => 1044 vassalForm.Invoke((MethodInvoker) (() =>
1646 { 1045 {
1647 switch (status) 1046 switch (status)
1648 { 1047 {
1649 case "Unknown": 1048 case "Unknown":
1650 case "Down": 1049 case "Down":
1651 case "NonExistent": 1050 case "NonExistent":
1652 RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor = 1051 RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
1653 Color.LightPink; 1052 Color.LightPink;
1654 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value = 1053 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value =
1655 status; 1054 status;
1656 break; 1055 break;
1657 default: 1056 default:
1658 RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor = 1057 RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
1659 Color.LightGreen; 1058 Color.LightGreen;
1660 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value = 1059 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value =
1661 "Up"; 1060 "Up";
1662 break; 1061 break;
1663 } 1062 }
1664 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastCheck"].Value = DateTime 1063 RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastCheck"].Value = DateTime
1665 .Now.ToUniversalTime() 1064 .Now.ToUniversalTime()
1666 .ToString(Vassal.LINDEN_CONSTANTS.LSL.DATE_TIME_STAMP); 1065 .ToString(LINDEN_CONSTANTS.LSL.DATE_TIME_STAMP);
1667   -  
1668 })); 1066 }));
1669 } 1067 }
1670 catch (Exception) 1068 catch (Exception)
1671 { 1069 {
1672   -  
1673 } 1070 }
1674 finally 1071 finally
1675 { 1072 {
1676 Monitor.Exit(RegionsStateCheckLock); -  
1677 ++regionsStateCheckIndex; 1073 ++regionsStateCheckIndex;
1678 vassalForm.Invoke((MethodInvoker) (() => 1074 vassalForm.Invoke((MethodInvoker) (() =>
1679 { 1075 {
1680 if (regionsStateCheckIndex >= RegionsStateGridView.Rows.Count) 1076 if (regionsStateCheckIndex >= RegionsStateGridView.Rows.Count)
1681 { 1077 {
1682 regionsStateCheckIndex = 0; 1078 regionsStateCheckIndex = 0;
1683 } 1079 }
1684 })); 1080 }));
1685 } 1081 }
-   1082  
-   1083 regionsStateTabTimer.Start();
1686 }; 1084 };
1687 regionsStateTabTimer.Start(); 1085 regionsStateTabTimer.Start();
1688   1086  
1689 // Start the top scores timer. 1087 // Start the top scores timer.
1690 topScriptsTabTimer.Elapsed += (o, p) => 1088 estateTopTabTimer.Elapsed += (o, p) =>
1691 { 1089 {
1692 // Do not do anything in case the tab is not selected. 1090 // Do not do anything in case the tab is not selected.
1693 bool run = false; 1091 bool run = false;
1694 vassalForm.Invoke((MethodInvoker) (() => -  
1695 { -  
1696 run = Tabs.SelectedTab.Equals(TopScriptsTab); 1092 vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(EstateTopTab); }));
1697 })); -  
1698 if (!run) return; -  
-   1093  
-   1094 if (!run)
1699   1095 {
1700 if (!Monitor.TryEnter(ClientInstanceTeleportLock)) 1096 estateTopTabTimer.Stop();
-   1097 return;
-   1098 }
-   1099  
1701 return; 1100 estateTopTabTimer.Stop();
1702   1101  
1703 try 1102 try
1704 { 1103 {
1705 // Get the statistics. 1104 // Get the top scripts.
1706 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1105 string result = wasPOST(vassalConfiguration.HTTPServerURL,
1707 wasKeyValueEscape(new Dictionary<string, string> 1106 wasKeyValueEscape(new Dictionary<string, string>
1708 { 1107 {
1709 {"command", "getregiontop"}, 1108 {"command", "getregiontop"},
1710 {"group", vassalConfiguration.Group}, 1109 {"group", vassalConfiguration.Group},
1711 {"password", vassalConfiguration.Password}, 1110 {"password", vassalConfiguration.Password},
1712 {"type", "scripts"} 1111 {"type", "scripts"}
1713 }), vassalConfiguration.DataTimeout); 1112 }), vassalConfiguration.DataTimeout);
1714   1113  
1715 bool success; 1114 bool success;
1716 if (string.IsNullOrEmpty(result) || 1115 if (string.IsNullOrEmpty(result) ||
1717 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1116 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1718 throw new Exception(); 1117 throw new Exception();
1719   1118  
1720 HashSet<List<string>> data = 1119 HashSet<List<string>> data =
1721 new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))) 1120 new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
1722 .Select((x, i) => new {Index = i, Value = x}) 1121 .Select((x, i) => new {Index = i, Value = x})
1723 .GroupBy(x => x.Index/5) 1122 .GroupBy(x => x.Index/5)
1724 .Select(x => x.Select(v => v.Value).ToList())); 1123 .Select(x => x.Select(v => v.Value).ToList()));
1725 if (data.Count.Equals(0)) 1124 if (data.Count.Equals(0))
1726 throw new Exception(); 1125 throw new Exception();
1727   1126  
1728 vassalForm.Invoke((MethodInvoker) (() => 1127 vassalForm.Invoke((MethodInvoker) (() =>
1729 { 1128 {
1730 // Remove rows that are not in the data update. 1129 // Remove rows that are not in the data update.
1731 foreach ( 1130 foreach (
1732 int index in 1131 int index in
1733 TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>() 1132 TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>()
1734 .Where( 1133 .Where(
1735 topScriptsRow => 1134 topScriptsRow =>
1736 !data.Any(q => q[2].Equals(topScriptsRow.Cells["TopScriptsUUID"].Value))) 1135 !data.Any(q => q[2].Equals(topScriptsRow.Cells["TopScriptsUUID"].Value)))
1737 .Select(q => q.Index)) 1136 .Select(q => q.Index))
1738 { 1137 {
1739 TopScriptsGridView.Rows.RemoveAt(index); 1138 TopScriptsGridView.Rows.RemoveAt(index);
1740 } 1139 }
1741 // Now update or add new data. 1140 // Now update or add new data.
1742 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5))) 1141 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5)))
1743 { 1142 {
1744 DataGridViewRow row = 1143 DataGridViewRow row =
1745 TopScriptsGridView.Rows.AsParallel() 1144 TopScriptsGridView.Rows.AsParallel()
1746 .Cast<DataGridViewRow>() 1145 .Cast<DataGridViewRow>()
1747 .FirstOrDefault(q => q.Cells["TopScriptsUUID"].Value.Equals(dataComponents[2])); 1146 .FirstOrDefault(q => q.Cells["TopScriptsUUID"].Value.Equals(dataComponents[2]));
1748 switch (row != null) 1147 switch (row != null)
1749 { 1148 {
1750 case true: // the row exists, so update it. 1149 case true: // the row exists, so update it.
1751 row.Cells["TopScriptsScore"].Value = dataComponents[0]; 1150 row.Cells["TopScriptsScore"].Value = dataComponents[0];
1752 row.Cells["TopScriptsTaskName"].Value = dataComponents[1]; 1151 row.Cells["TopScriptsTaskName"].Value = dataComponents[1];
1753 row.Cells["TopScriptsUUID"].Value = dataComponents[2]; 1152 row.Cells["TopScriptsUUID"].Value = dataComponents[2];
1754 row.Cells["TopScriptsOwner"].Value = dataComponents[3]; 1153 row.Cells["TopScriptsOwner"].Value = dataComponents[3];
1755 row.Cells["TopScriptsPosition"].Value = dataComponents[4]; 1154 row.Cells["TopScriptsPosition"].Value = dataComponents[4];
1756 break; 1155 break;
1757 case false: // the row dosn't exist, so add it. 1156 case false: // the row dosn't exist, so add it.
1758 TopScriptsGridView.Rows.Add(dataComponents[0], dataComponents[1], dataComponents[2], 1157 TopScriptsGridView.Rows.Add(dataComponents[0], dataComponents[1], dataComponents[2],
1759 dataComponents[3], dataComponents[4]); 1158 dataComponents[3], dataComponents[4]);
1760 break; 1159 break;
1761 } 1160 }
1762 } 1161 }
1763 })); 1162 }));
1764 } -  
1765 catch (Exception) -  
1766 { -  
1767   -  
1768 } -  
1769 finally -  
1770 { -  
1771 Monitor.Exit(ClientInstanceTeleportLock); -  
1772 } -  
1773 }; -  
1774 topScriptsTabTimer.Start(); -  
1775   -  
1776 // Start the top colliders timer. -  
1777 topCollidersTabTimer.Elapsed += (o, p) => -  
1778 { -  
1779 // Do not do anything in case the tab is not selected. -  
1780 bool run = false; -  
1781 vassalForm.Invoke((MethodInvoker) (() => -  
1782 { -  
1783 run = Tabs.SelectedTab.Equals(TopCollidersTab); -  
1784 })); -  
1785 if (!run) return; -  
1786   -  
1787 if (!Monitor.TryEnter(ClientInstanceTeleportLock)) -  
1788 return; -  
1789   -  
1790 try -  
1791 { 1163  
1792 // Get the statistics. 1164 // Get the top colliders.
1793 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1165 result = wasPOST(vassalConfiguration.HTTPServerURL,
1794 wasKeyValueEscape(new Dictionary<string, string> 1166 wasKeyValueEscape(new Dictionary<string, string>
1795 { 1167 {
1796 {"command", "getregiontop"}, 1168 {"command", "getregiontop"},
1797 {"group", vassalConfiguration.Group}, 1169 {"group", vassalConfiguration.Group},
1798 {"password", vassalConfiguration.Password}, 1170 {"password", vassalConfiguration.Password},
1799 {"type", "colliders"} 1171 {"type", "colliders"}
1800 }), vassalConfiguration.DataTimeout); 1172 }), vassalConfiguration.DataTimeout);
1801   -  
1802 bool success; 1173  
1803 if (string.IsNullOrEmpty(result) || 1174 if (string.IsNullOrEmpty(result) ||
1804 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1175 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1805 throw new Exception(); 1176 throw new Exception();
1806   -  
1807 HashSet<List<string>> data = 1177  
1808 new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))) 1178 data = new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
1809 .Select((x, i) => new {Index = i, Value = x}) 1179 .Select((x, i) => new {Index = i, Value = x})
1810 .GroupBy(x => x.Index/5) 1180 .GroupBy(x => x.Index/5)
1811 .Select(x => x.Select(v => v.Value).ToList())); 1181 .Select(x => x.Select(v => v.Value).ToList()));
1812 if (data.Count.Equals(0)) 1182 if (data.Count.Equals(0))
1813 throw new Exception(); 1183 throw new Exception();
1814   1184  
1815 vassalForm.Invoke((MethodInvoker) (() => 1185 vassalForm.Invoke((MethodInvoker) (() =>
1816 { 1186 {
1817 // Remove rows that are not in the data update. 1187 // Remove rows that are not in the data update.
1818 foreach ( 1188 foreach (
1819 int index in 1189 int index in
1820 TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>() 1190 TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>()
1821 .Where( 1191 .Where(
1822 topCollidersRow => 1192 topCollidersRow =>
1823 !data.Any(q => q[2].Equals(topCollidersRow.Cells["TopCollidersUUID"].Value))) 1193 !data.Any(q => q[2].Equals(topCollidersRow.Cells["TopCollidersUUID"].Value)))
1824 .Select(q => q.Index)) 1194 .Select(q => q.Index))
1825 { 1195 {
1826 TopCollidersGridView.Rows.RemoveAt(index); 1196 TopCollidersGridView.Rows.RemoveAt(index);
1827 } 1197 }
1828 // Now update or add new data. 1198 // Now update or add new data.
1829 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5))) 1199 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5)))
1830 { 1200 {
1831 DataGridViewRow row = 1201 DataGridViewRow row =
1832 TopCollidersGridView.Rows.AsParallel() 1202 TopCollidersGridView.Rows.AsParallel()
1833 .Cast<DataGridViewRow>() 1203 .Cast<DataGridViewRow>()
1834 .FirstOrDefault(q => q.Cells["TopCollidersUUID"].Value.Equals(dataComponents[2])); 1204 .FirstOrDefault(q => q.Cells["TopCollidersUUID"].Value.Equals(dataComponents[2]));
1835 switch (row != null) 1205 switch (row != null)
1836 { 1206 {
1837 case true: // the row exists, so update it. 1207 case true: // the row exists, so update it.
1838 row.Cells["TopCollidersScore"].Value = dataComponents[0]; 1208 row.Cells["TopCollidersScore"].Value = dataComponents[0];
1839 row.Cells["TopSCollidersTaskName"].Value = dataComponents[1]; 1209 row.Cells["TopSCollidersTaskName"].Value = dataComponents[1];
1840 row.Cells["TopCollidersUUID"].Value = dataComponents[2]; 1210 row.Cells["TopCollidersUUID"].Value = dataComponents[2];
1841 row.Cells["TopCollidersOwner"].Value = dataComponents[3]; 1211 row.Cells["TopCollidersOwner"].Value = dataComponents[3];
1842 row.Cells["TopCollidersPosition"].Value = dataComponents[4]; 1212 row.Cells["TopCollidersPosition"].Value = dataComponents[4];
1843 break; 1213 break;
1844 case false: // the row dosn't exist, so add it. 1214 case false: // the row dosn't exist, so add it.
1845 TopCollidersGridView.Rows.Add(dataComponents[0], dataComponents[1], 1215 TopCollidersGridView.Rows.Add(dataComponents[0], dataComponents[1],
1846 dataComponents[2], 1216 dataComponents[2],
1847 dataComponents[3], dataComponents[4]); 1217 dataComponents[3], dataComponents[4]);
1848 break; 1218 break;
1849 } 1219 }
1850 } 1220 }
1851   -  
1852 })); 1221 }));
1853 } 1222 }
1854 catch (Exception) 1223 catch (Exception)
1855 { 1224 {
1856   -  
1857 } -  
1858 finally -  
1859 { -  
1860 Monitor.Exit(ClientInstanceTeleportLock); -  
1861 } 1225 }
-   1226  
-   1227 estateTopTabTimer.Start();
1862 }; 1228 };
1863 topCollidersTabTimer.Start(); 1229 estateTopTabTimer.Start();
1864   1230  
1865 // Start the resident list timer. 1231 // Start the resident list timer.
1866 residentListTimer.Elapsed += (o, p) => 1232 residentListTabTimer.Elapsed += (o, p) =>
1867 { 1233 {
1868 // Do not do anything in case the tab is not selected. 1234 // Do not do anything in case the tab is not selected.
1869 bool run = false; 1235 bool run = false;
1870 vassalForm.Invoke((MethodInvoker) (() => -  
1871 { -  
1872 run = Tabs.SelectedTab.Equals(ResidentListTab); 1236 vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(ResidentListTab); }));
1873 })); -  
1874 if (!run) return; -  
-   1237  
-   1238 if (!run)
1875   1239 {
1876 if (!Monitor.TryEnter(ClientInstanceTeleportLock)) 1240 residentListTabTimer.Stop();
-   1241 return;
-   1242 }
-   1243  
1877 return; 1244 residentListTabTimer.Stop();
1878   1245  
1879 try 1246 try
1880 { 1247 {
1881 // Get the avatar positions. 1248 // Get the avatar positions.
1882 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1249 string result = wasPOST(vassalConfiguration.HTTPServerURL,
1883 wasKeyValueEscape(new Dictionary<string, string> 1250 wasKeyValueEscape(new Dictionary<string, string>
1884 { 1251 {
1885 {"command", "getavatarpositions"}, 1252 {"command", "getavatarpositions"},
1886 {"group", vassalConfiguration.Group}, 1253 {"group", vassalConfiguration.Group},
1887 {"password", vassalConfiguration.Password}, 1254 {"password", vassalConfiguration.Password},
1888 {"entity", "region"} 1255 {"entity", "region"}
1889 }), vassalConfiguration.DataTimeout); 1256 }), vassalConfiguration.DataTimeout);
1890   1257  
1891 bool success; 1258 bool success;
1892 if (string.IsNullOrEmpty(result) || 1259 if (string.IsNullOrEmpty(result) ||
1893 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1260 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
1894 throw new Exception(); 1261 throw new Exception();
1895   1262  
1896 HashSet<List<string>> data = 1263 HashSet<List<string>> data =
1897 new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))) 1264 new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
1898 .Select((x, i) => new {Index = i, Value = x}) 1265 .Select((x, i) => new {Index = i, Value = x})
1899 .GroupBy(x => x.Index/3) 1266 .GroupBy(x => x.Index/3)
1900 .Select(x => x.Select(v => v.Value).ToList())); 1267 .Select(x => x.Select(v => v.Value).ToList()));
1901 if (data.Count.Equals(0)) 1268 if (data.Count.Equals(0))
1902 throw new Exception(); 1269 throw new Exception();
1903   1270  
1904 vassalForm.Invoke((MethodInvoker) (() => 1271 vassalForm.Invoke((MethodInvoker) (() =>
1905 { 1272 {
1906 // Remove rows that are not in the data update. 1273 // Remove rows that are not in the data update.
1907 foreach ( 1274 foreach (
1908 int index in 1275 int index in
1909 ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>() 1276 ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>()
1910 .Where( 1277 .Where(
1911 residentListRow => 1278 residentListRow =>
1912 !data.Any(q => q[1].Equals(residentListRow.Cells["ResidentListUUID"].Value))) 1279 !data.Any(q => q[1].Equals(residentListRow.Cells["ResidentListUUID"].Value)))
1913 .Select(q => q.Index)) 1280 .Select(q => q.Index))
1914 { 1281 {
1915 ResidentListGridView.Rows.RemoveAt(index); 1282 ResidentListGridView.Rows.RemoveAt(index);
1916 } 1283 }
1917 // Now update or add new data. 1284 // Now update or add new data.
1918 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(3))) 1285 foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(3)))
1919 { 1286 {
1920 DataGridViewRow row = 1287 DataGridViewRow row =
1921 ResidentListGridView.Rows.AsParallel() 1288 ResidentListGridView.Rows.AsParallel()
1922 .Cast<DataGridViewRow>() 1289 .Cast<DataGridViewRow>()
1923 .FirstOrDefault(q => q.Cells["ResidentListUUID"].Value.Equals(dataComponents[1])); 1290 .FirstOrDefault(q => q.Cells["ResidentListUUID"].Value.Equals(dataComponents[1]));
1924 switch (row != null) 1291 switch (row != null)
1925 { 1292 {
1926 case true: // the row exists, so update it. 1293 case true: // the row exists, so update it.
1927 row.Cells["ResidentListName"].Value = dataComponents[0]; 1294 row.Cells["ResidentListName"].Value = dataComponents[0];
1928 row.Cells["ResidentListUUID"].Value = dataComponents[1]; 1295 row.Cells["ResidentListUUID"].Value = dataComponents[1];
1929 row.Cells["ResidentListPosition"].Value = dataComponents[2]; 1296 row.Cells["ResidentListPosition"].Value = dataComponents[2];
1930 break; 1297 break;
1931 case false: // the row dosn't exist, so add it. 1298 case false: // the row dosn't exist, so add it.
1932 ResidentListGridView.Rows.Add(dataComponents[0], dataComponents[1], 1299 ResidentListGridView.Rows.Add(dataComponents[0], dataComponents[1],
1933 dataComponents[2]); 1300 dataComponents[2]);
1934 break; 1301 break;
1935 } 1302 }
1936 } 1303 }
1937   -  
1938 })); 1304 }));
1939 } 1305 }
1940 catch (Exception) 1306 catch (Exception)
1941 { 1307 {
-   1308 }
-   1309  
-   1310 residentListTabTimer.Start();
-   1311 };
-   1312 residentListTabTimer.Start();
-   1313  
-   1314 estateTexturesTabTimer.Elapsed += (o, p) =>
-   1315 {
-   1316 // Do not do anything in case the tab is not selected.
-   1317 bool run = false;
-   1318 vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(EstateTexturesTab); }));
-   1319  
-   1320 if (!run)
-   1321 {
-   1322 estateTexturesTabTimer.Stop();
1942   1323 return;
-   1324 }
-   1325  
-   1326 estateTexturesTabTimer.Stop();
1943 } 1327  
-   1328 try
-   1329 {
-   1330 // Get the region terrain texture UUIDs.
-   1331 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   1332 wasKeyValueEscape(new Dictionary<string, string>
-   1333 {
-   1334 {"command", "getregionterraintextures"},
-   1335 {"group", vassalConfiguration.Group},
-   1336 {"password", vassalConfiguration.Password}
-   1337 }), vassalConfiguration.DataTimeout);
-   1338  
-   1339 bool success;
-   1340 if (string.IsNullOrEmpty(result) ||
-   1341 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   1342 throw new Exception();
-   1343  
-   1344 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
-   1345 if (!data.Count.Equals(4))
-   1346 throw new Exception();
-   1347  
-   1348 vassalForm.Invoke((MethodInvoker) (() =>
-   1349 {
-   1350 RegionTexturesLowUUIDBox.Text = data[0];
-   1351 if (string.IsNullOrEmpty(RegionTexturesLowUUIDApplyBox.Text))
-   1352 {
-   1353 RegionTexturesLowUUIDApplyBox.Text = data[0];
-   1354 }
-   1355 RegionTexturesMiddleLowUUIDBox.Text = data[1];
-   1356 if (string.IsNullOrEmpty(RegionTexturesMiddleLowUUIDApplyBox.Text))
-   1357 {
-   1358 RegionTexturesMiddleLowUUIDApplyBox.Text = data[1];
-   1359 }
-   1360 RegionTexturesMiddleHighUUIDBox.Text = data[2];
-   1361 if (string.IsNullOrEmpty(RegionTexturesMiddleHighUUIDApplyBox.Text))
-   1362 {
-   1363 RegionTexturesMiddleHighUUIDApplyBox.Text = data[2];
-   1364 }
-   1365 RegionTexturesHighUUIDBox.Text = data[3];
-   1366 if (string.IsNullOrEmpty(RegionTexturesHighUUIDApplyBox.Text))
-   1367 {
-   1368 RegionTexturesHighUUIDApplyBox.Text = data[1];
-   1369 }
-   1370 }));
-   1371  
-   1372 Parallel.ForEach(Enumerable.Range(0, 4), i =>
-   1373 {
-   1374 result = wasPOST(vassalConfiguration.HTTPServerURL,
-   1375 wasKeyValueEscape(new Dictionary<string, string>
-   1376 {
-   1377 {"command", "download"},
-   1378 {"group", vassalConfiguration.Group},
-   1379 {"password", vassalConfiguration.Password},
-   1380 {"item", data[i]},
-   1381 {"type", "Texture"},
-   1382 {"format", "Jpeg"}
-   1383 }), vassalConfiguration.DataTimeout);
-   1384  
-   1385 if (string.IsNullOrEmpty(result) ||
-   1386 !bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   1387 return;
-   1388  
-   1389 byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
-   1390 using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
-   1391 {
-   1392 groundTextureImages[i] = Image.FromStream(memoryStream);
-   1393 }
-   1394  
-   1395 switch (i)
-   1396 {
-   1397 case 0:
-   1398 vassalForm.BeginInvoke(
-   1399 (MethodInvoker)
-   1400 (() => { RegionTexturesLowPictureBox.Image = groundTextureImages[0]; }));
-   1401  
-   1402 break;
-   1403 case 1:
-   1404 vassalForm.BeginInvoke(
-   1405 (MethodInvoker)
-   1406 (() => { RegionTexturesMiddleLowPictureBox.Image = groundTextureImages[1]; }));
-   1407  
-   1408 break;
-   1409 case 2:
-   1410 vassalForm.BeginInvoke(
-   1411 (MethodInvoker)
-   1412 (() => { RegionTexturesMiddleHighPictureBox.Image = groundTextureImages[2]; }));
-   1413 break;
-   1414 case 3:
-   1415 vassalForm.BeginInvoke(
-   1416 (MethodInvoker)
-   1417 (() => { RegionTexturesHighPictureBox.Image = groundTextureImages[3]; }));
-   1418 break;
-   1419 }
-   1420 });
-   1421 }
1944 finally 1422 catch (Exception)
1945 { -  
1946 Monitor.Exit(ClientInstanceTeleportLock); 1423 {
-   1424 }
-   1425  
1947 } 1426 estateTexturesTabTimer.Start();
1948 }; 1427 };
1949 residentListTimer.Start(); 1428 estateTexturesTabTimer.Start();
1950 } 1429 }
1951   1430  
1952 private void RequestedEditRegions(object sender, EventArgs e) 1431 private void RequestedEditRegions(object sender, EventArgs e)
1953 { 1432 {
1954 // Clear any selection. 1433 // Clear any selection.
1955 LoadedRegions.SelectedIndex = -1; 1434 LoadedRegionsBox.SelectedIndex = -1;
1956 RegionEditForm regionEditForm = new RegionEditForm {TopMost = true}; 1435 RegionEditForm regionEditForm = new RegionEditForm {TopMost = true};
1957 regionEditForm.Show(); 1436 regionEditForm.Show();
1958 } 1437 }
1959   1438  
1960 private void RequestSelecting(object sender, TabControlCancelEventArgs e) 1439 private void RequestSelecting(object sender, TabControlCancelEventArgs e)
1961 { 1440 {
1962 e.Cancel = !e.TabPage.Enabled; 1441 e.Cancel = !e.TabPage.Enabled;
1963 } 1442 }
1964   1443  
1965 private void RequestExportTopScripts(object sender, EventArgs e) 1444 private void RequestExportTopScripts(object sender, EventArgs e)
1966 { 1445 {
1967 vassalForm.BeginInvoke((MethodInvoker) (() => 1446 vassalForm.BeginInvoke((MethodInvoker) (() =>
1968 { 1447 {
1969 switch (vassalForm.ExportCSVDialog.ShowDialog()) 1448 switch (vassalForm.ExportCSVDialog.ShowDialog())
1970 { 1449 {
1971 case DialogResult.OK: 1450 case DialogResult.OK:
1972 string file = vassalForm.ExportCSVDialog.FileName; 1451 string file = vassalForm.ExportCSVDialog.FileName;
1973 new Thread(() => 1452 new Thread(() =>
1974 { 1453 {
1975 vassalForm.BeginInvoke((MethodInvoker) (() => 1454 vassalForm.BeginInvoke((MethodInvoker) (() =>
1976 { 1455 {
1977 try 1456 try
1978 { 1457 {
1979 vassalForm.StatusText.Text = @"exporting..."; 1458 vassalForm.StatusText.Text = @"exporting...";
1980 vassalForm.StatusProgress.Value = 0; 1459 vassalForm.StatusProgress.Value = 0;
1981   1460  
1982 using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8)) 1461 using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
1983 { 1462 {
1984 foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows) 1463 foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows)
1985 { 1464 {
1986 streamWriter.WriteLine(wasEnumerableToCSV(new[] 1465 streamWriter.WriteLine(wasEnumerableToCSV(new[]
1987 { 1466 {
1988 topScriptsRow.Cells["TopScriptsScore"].Value.ToString(), 1467 topScriptsRow.Cells["TopScriptsScore"].Value.ToString(),
1989 topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString(), 1468 topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString(),
1990 topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(), 1469 topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(),
1991 topScriptsRow.Cells["TopScriptsOwner"].Value.ToString(), 1470 topScriptsRow.Cells["TopScriptsOwner"].Value.ToString(),
1992 topScriptsRow.Cells["TopScriptsPosition"].Value.ToString() 1471 topScriptsRow.Cells["TopScriptsPosition"].Value.ToString()
1993 })); 1472 }));
1994 } 1473 }
1995 } 1474 }
1996   1475  
1997 vassalForm.StatusText.Text = @"exported"; 1476 vassalForm.StatusText.Text = @"exported";
1998 vassalForm.StatusProgress.Value = 100; 1477 vassalForm.StatusProgress.Value = 100;
1999 } 1478 }
2000 catch (Exception ex) 1479 catch (Exception ex)
2001 { 1480 {
2002 vassalForm.StatusText.Text = ex.Message; 1481 vassalForm.StatusText.Text = ex.Message;
2003 } 1482 }
2004 })); 1483 }));
2005 }) 1484 })
2006 {IsBackground = true}.Start(); 1485 {IsBackground = true}.Start();
2007 break; 1486 break;
2008 } 1487 }
2009 })); 1488 }));
2010 } 1489 }
2011   1490  
2012 private void RequestExportTopColliders(object sender, EventArgs e) 1491 private void RequestExportTopColliders(object sender, EventArgs e)
2013 { 1492 {
2014 vassalForm.BeginInvoke((MethodInvoker) (() => 1493 vassalForm.BeginInvoke((MethodInvoker) (() =>
2015 { 1494 {
2016 switch (vassalForm.ExportCSVDialog.ShowDialog()) 1495 switch (vassalForm.ExportCSVDialog.ShowDialog())
2017 { 1496 {
2018 case DialogResult.OK: 1497 case DialogResult.OK:
2019 string file = vassalForm.ExportCSVDialog.FileName; 1498 string file = vassalForm.ExportCSVDialog.FileName;
2020 new Thread(() => 1499 new Thread(() =>
2021 { 1500 {
2022 vassalForm.BeginInvoke((MethodInvoker) (() => 1501 vassalForm.BeginInvoke((MethodInvoker) (() =>
2023 { 1502 {
2024 try 1503 try
2025 { 1504 {
2026 vassalForm.StatusText.Text = @"exporting..."; 1505 vassalForm.StatusText.Text = @"exporting...";
2027 vassalForm.StatusProgress.Value = 0; 1506 vassalForm.StatusProgress.Value = 0;
2028   1507  
2029 using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8)) 1508 using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
2030 { 1509 {
2031 foreach (DataGridViewRow topCollidersRow in TopCollidersGridView.Rows) 1510 foreach (DataGridViewRow topCollidersRow in TopCollidersGridView.Rows)
2032 { 1511 {
2033 streamWriter.WriteLine(wasEnumerableToCSV(new[] 1512 streamWriter.WriteLine(wasEnumerableToCSV(new[]
2034 { 1513 {
2035 topCollidersRow.Cells["TopCollidersScore"].Value.ToString(), 1514 topCollidersRow.Cells["TopCollidersScore"].Value.ToString(),
2036 topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString(), 1515 topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString(),
2037 topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(), 1516 topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(),
2038 topCollidersRow.Cells["TopCollidersOwner"].Value.ToString(), 1517 topCollidersRow.Cells["TopCollidersOwner"].Value.ToString(),
2039 topCollidersRow.Cells["TopCollidersPosition"].Value.ToString() 1518 topCollidersRow.Cells["TopCollidersPosition"].Value.ToString()
2040 })); 1519 }));
2041 } 1520 }
2042 } 1521 }
2043   1522  
2044 vassalForm.StatusText.Text = @"exported"; 1523 vassalForm.StatusText.Text = @"exported";
2045 vassalForm.StatusProgress.Value = 100; 1524 vassalForm.StatusProgress.Value = 100;
2046 } 1525 }
2047 catch (Exception ex) 1526 catch (Exception ex)
2048 { 1527 {
2049 vassalForm.StatusText.Text = ex.Message; 1528 vassalForm.StatusText.Text = ex.Message;
2050 } 1529 }
2051 })); 1530 }));
2052 }) 1531 })
2053 {IsBackground = true}.Start(); 1532 {IsBackground = true}.Start();
2054 break; 1533 break;
2055 } 1534 }
2056 })); 1535 }));
2057 } 1536 }
2058   1537  
2059 private void RequestFilterTopScripts(object sender, EventArgs e) 1538 private void RequestFilterTopScripts(object sender, EventArgs e)
2060 { 1539 {
2061 vassalForm.BeginInvoke((MethodInvoker) (() => 1540 vassalForm.BeginInvoke((MethodInvoker) (() =>
2062 { 1541 {
2063 Regex topScriptsRowRegex; 1542 Regex topScriptsRowRegex;
2064 switch (!string.IsNullOrEmpty(TopScriptsFilter.Text)) 1543 switch (!string.IsNullOrEmpty(TopScriptsFilter.Text))
2065 { 1544 {
2066 case true: 1545 case true:
2067 topScriptsRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled); 1546 topScriptsRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled);
2068 break; 1547 break;
2069 default: 1548 default:
2070 topScriptsRowRegex = new Regex(@".+?", RegexOptions.Compiled); 1549 topScriptsRowRegex = new Regex(@".+?", RegexOptions.Compiled);
2071 break; 1550 break;
2072 } 1551 }
2073 foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>()) 1552 foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>())
2074 { 1553 {
2075 topScriptsRow.Visible = 1554 topScriptsRow.Visible =
2076 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsScore"].Value.ToString()) || 1555 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsScore"].Value.ToString()) ||
2077 topScriptsRowRegex.IsMatch( 1556 topScriptsRowRegex.IsMatch(
2078 topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString()) || 1557 topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString()) ||
2079 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString()) || 1558 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString()) ||
2080 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsOwner"].Value.ToString()) || 1559 topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsOwner"].Value.ToString()) ||
2081 topScriptsRowRegex.IsMatch( 1560 topScriptsRowRegex.IsMatch(
2082 topScriptsRow.Cells["TopScriptsPosition"].Value.ToString()); 1561 topScriptsRow.Cells["TopScriptsPosition"].Value.ToString());
2083 } 1562 }
2084 })); 1563 }));
2085 } 1564 }
2086   1565  
2087 private void RequestFilterTopColliders(object sender, EventArgs e) 1566 private void RequestFilterTopColliders(object sender, EventArgs e)
2088 { 1567 {
2089 vassalForm.BeginInvoke((MethodInvoker) (() => 1568 vassalForm.BeginInvoke((MethodInvoker) (() =>
2090 { 1569 {
2091 Regex topCollidersRowRegex; 1570 Regex topCollidersRowRegex;
2092 switch (!string.IsNullOrEmpty(TopScriptsFilter.Text)) 1571 switch (!string.IsNullOrEmpty(TopScriptsFilter.Text))
2093 { 1572 {
2094 case true: 1573 case true:
2095 topCollidersRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled); 1574 topCollidersRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled);
2096 break; 1575 break;
2097 default: 1576 default:
2098 topCollidersRowRegex = new Regex(@".+?", RegexOptions.Compiled); 1577 topCollidersRowRegex = new Regex(@".+?", RegexOptions.Compiled);
2099 break; 1578 break;
2100 } 1579 }
2101 foreach ( 1580 foreach (
2102 DataGridViewRow topCollidersRow in TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>()) 1581 DataGridViewRow topCollidersRow in TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>())
2103 { 1582 {
2104 topCollidersRow.Visible = 1583 topCollidersRow.Visible =
2105 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersScore"].Value.ToString()) || 1584 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersScore"].Value.ToString()) ||
2106 topCollidersRowRegex.IsMatch( 1585 topCollidersRowRegex.IsMatch(
2107 topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString()) || 1586 topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString()) ||
2108 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString()) || 1587 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString()) ||
2109 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersOwner"].Value.ToString()) || 1588 topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersOwner"].Value.ToString()) ||
2110 topCollidersRowRegex.IsMatch( 1589 topCollidersRowRegex.IsMatch(
2111 topCollidersRow.Cells["TopCollidersPosition"].Value.ToString()); 1590 topCollidersRow.Cells["TopCollidersPosition"].Value.ToString());
2112 } 1591 }
2113 })); 1592 }));
2114 } 1593 }
2115   1594  
2116 private void RequestReturnTopScriptsObjects(object sender, EventArgs e) 1595 private void RequestReturnTopScriptsObjects(object sender, EventArgs e)
2117 { 1596 {
2118 // Block teleports and disable button. 1597 // Block teleports and disable button.
2119 vassalForm.Invoke((MethodInvoker) (() => 1598 vassalForm.Invoke((MethodInvoker) (() =>
2120 { 1599 {
2121 vassalForm.ReturnTopScriptsButton.Enabled = false; 1600 vassalForm.ReturnTopScriptsButton.Enabled = false;
2122 RegionTeleportGroup.Enabled = false; 1601 RegionTeleportGroup.Enabled = false;
2123 })); 1602 }));
2124   1603  
2125 // Enqueue all the UUIDs to return. 1604 // Enqueue all the UUIDs to return.
2126 Queue<KeyValuePair<UUID, Vector3>> returnUUIDs = new Queue<KeyValuePair<UUID, Vector3>>(); 1605 Queue<KeyValuePair<UUID, Vector3>> returnUUIDs = new Queue<KeyValuePair<UUID, Vector3>>();
2127 vassalForm.Invoke((MethodInvoker) (() => 1606 vassalForm.Invoke((MethodInvoker) (() =>
2128 { 1607 {
2129 foreach ( 1608 foreach (
2130 DataGridViewRow topScriptsRow in 1609 DataGridViewRow topScriptsRow in
2131 TopScriptsGridView.Rows.AsParallel() 1610 TopScriptsGridView.Rows.AsParallel()
2132 .Cast<DataGridViewRow>() 1611 .Cast<DataGridViewRow>()
2133 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected))) 1612 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
2134 { 1613 {
2135 Vector3 objectPosition; 1614 Vector3 objectPosition;
2136 UUID returnUUID; 1615 UUID returnUUID;
2137 if (!UUID.TryParse(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(), out returnUUID) || 1616 if (!UUID.TryParse(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(), out returnUUID) ||
2138 !Vector3.TryParse(topScriptsRow.Cells["TopScriptsPosition"].Value.ToString(), out objectPosition)) 1617 !Vector3.TryParse(topScriptsRow.Cells["TopScriptsPosition"].Value.ToString(), out objectPosition))
2139 continue; 1618 continue;
2140 returnUUIDs.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition)); 1619 returnUUIDs.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition));
2141 } 1620 }
2142 })); 1621 }));
2143   1622  
2144 // If no rows were selected, enable teleports, the return button and return. 1623 // If no rows were selected, enable teleports, the return button and return.
2145 if (returnUUIDs.Count.Equals(0)) 1624 if (returnUUIDs.Count.Equals(0))
2146 { 1625 {
2147 vassalForm.Invoke((MethodInvoker) (() => 1626 vassalForm.Invoke((MethodInvoker) (() =>
2148 { 1627 {
2149 vassalForm.ReturnTopScriptsButton.Enabled = true; 1628 vassalForm.ReturnTopScriptsButton.Enabled = true;
2150 RegionTeleportGroup.Enabled = true; 1629 RegionTeleportGroup.Enabled = true;
2151 })); 1630 }));
2152 return; 1631 return;
2153 } 1632 }
2154   1633  
2155 new Thread(() => 1634 new Thread(() =>
2156 { 1635 {
2157 Monitor.Enter(ClientInstanceTeleportLock); 1636 Monitor.Enter(ClientInstanceTeleportLock);
2158   1637  
2159 try 1638 try
2160 { 1639 {
2161 vassalForm.Invoke((MethodInvoker) (() => -  
2162 { -  
2163 vassalForm.StatusProgress.Value = 0; 1640 vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 0; }));
2164 })); -  
2165 int totalObjects = returnUUIDs.Count; 1641 int totalObjects = returnUUIDs.Count;
2166 do 1642 do
2167 { 1643 {
2168 // Dequeue the first object. 1644 // Dequeue the first object.
2169 KeyValuePair<UUID, Vector3> objectData = returnUUIDs.Dequeue(); 1645 KeyValuePair<UUID, Vector3> objectData = returnUUIDs.Dequeue();
2170   1646  
2171 vassalForm.Invoke((MethodInvoker) (() => 1647 vassalForm.Invoke(
2172 { 1648 (MethodInvoker)
2173 vassalForm.StatusText.Text = @"Returning object UUID: " + objectData.Key.ToString(); -  
2174 })); 1649 (() => { vassalForm.StatusText.Text = @"Returning object UUID: " + objectData.Key; }));
2175   -  
2176 string currentRegionName = string.Empty; -  
2177 vassalForm.Invoke((MethodInvoker) (() => 1650  
2178 { -  
2179 currentRegionName = CurrentRegionName.Text; 1651 string currentRegionName = string.Empty;
2180 })); 1652 vassalForm.Invoke((MethodInvoker) (() => { currentRegionName = CurrentRegionName.Text; }));
2181   1653  
2182 // Teleport to the object. 1654 // Teleport to the object.
2183 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1655 string result = wasPOST(vassalConfiguration.HTTPServerURL,
2184 wasKeyValueEscape(new Dictionary<string, string> 1656 wasKeyValueEscape(new Dictionary<string, string>
2185 { 1657 {
2186 {"command", "teleport"}, 1658 {"command", "teleport"},
2187 {"group", vassalConfiguration.Group}, 1659 {"group", vassalConfiguration.Group},
2188 {"password", vassalConfiguration.Password}, 1660 {"password", vassalConfiguration.Password},
2189 {"position", objectData.Value.ToString()}, 1661 {"position", objectData.Value.ToString()},
2190 {"region", currentRegionName}, 1662 {"region", currentRegionName},
2191 {"fly", "True"} 1663 {"fly", "True"}
2192 }), vassalConfiguration.TeleportTimeout); 1664 }), vassalConfiguration.TeleportTimeout);
2193   1665  
2194 if (string.IsNullOrEmpty(result)) 1666 if (string.IsNullOrEmpty(result))
2195 { 1667 {
2196 vassalForm.Invoke((MethodInvoker) (() => 1668 vassalForm.Invoke(
2197 { 1669 (MethodInvoker)
2198 vassalForm.StatusText.Text = @"Error communicating with Corrade."; 1670 (() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
2199 })); -  
2200 continue; 1671 continue;
2201 } 1672 }
2202   1673  
2203 // Return the object. 1674 // Return the object.
2204 result = wasPOST(vassalConfiguration.HTTPServerURL, 1675 result = wasPOST(vassalConfiguration.HTTPServerURL,
2205 wasKeyValueEscape(new Dictionary<string, string> 1676 wasKeyValueEscape(new Dictionary<string, string>
2206 { 1677 {
2207 {"command", "derez"}, 1678 {"command", "derez"},
2208 {"group", vassalConfiguration.Group}, 1679 {"group", vassalConfiguration.Group},
2209 {"password", vassalConfiguration.Password}, 1680 {"password", vassalConfiguration.Password},
2210 {"item", objectData.Key.ToString()}, 1681 {"item", objectData.Key.ToString()},
2211 {"range", "32"}, // maximal prim size = 64 - middle bounding box at half 1682 {"range", "32"}, // maximal prim size = 64 - middle bounding box at half
2212 {"type", "ReturnToOwner"} 1683 {"type", "ReturnToOwner"}
2213 }), vassalConfiguration.DataTimeout); 1684 }), vassalConfiguration.DataTimeout);
2214   1685  
2215 if (string.IsNullOrEmpty(result)) 1686 if (string.IsNullOrEmpty(result))
2216 { 1687 {
2217 vassalForm.Invoke((MethodInvoker) (() => 1688 vassalForm.Invoke(
2218 { 1689 (MethodInvoker)
2219 vassalForm.StatusText.Text = @"Error communicating with Corrade."; 1690 (() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
2220 })); -  
2221 continue; 1691 continue;
2222 } 1692 }
2223   1693  
2224 bool success; 1694 bool success;
2225 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1695 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2226 { 1696 {
2227 vassalForm.Invoke((MethodInvoker) (() => 1697 vassalForm.Invoke(
2228 { 1698 (MethodInvoker)
2229 vassalForm.StatusText.Text = @"No success status could be retrieved. "; 1699 (() => { vassalForm.StatusText.Text = @"No success status could be retrieved. "; }));
2230 })); -  
2231 continue; 1700 continue;
2232 } 1701 }
2233   1702  
2234 switch (success) 1703 switch (success)
2235 { 1704 {
2236 case true: 1705 case true:
2237 vassalForm.Invoke((MethodInvoker) (() => 1706 vassalForm.Invoke((MethodInvoker) (() =>
2238 { 1707 {
2239 vassalForm.StatusText.Text = @"Returned object: " + objectData.Key.ToString(); 1708 vassalForm.StatusText.Text = @"Returned object: " + objectData.Key;
2240 // Remove the row from the grid view. 1709 // Remove the row from the grid view.
2241 DataGridViewRow row = 1710 DataGridViewRow row =
2242 TopScriptsGridView.Rows.AsParallel() 1711 TopScriptsGridView.Rows.AsParallel()
2243 .Cast<DataGridViewRow>() 1712 .Cast<DataGridViewRow>()
2244 .FirstOrDefault( 1713 .FirstOrDefault(
2245 o => o.Cells["TopScriptsUUID"].Value.Equals(objectData.Key.ToString())); 1714 o => o.Cells["TopScriptsUUID"].Value.Equals(objectData.Key.ToString()));
2246 if (row == null) return; 1715 if (row == null) return;
2247 int i = row.Index; 1716 int i = row.Index;
2248 TopScriptsGridView.Rows.RemoveAt(i); 1717 TopScriptsGridView.Rows.RemoveAt(i);
2249 })); 1718 }));
2250 break; 1719 break;
2251 case false: 1720 case false:
2252 vassalForm.Invoke((MethodInvoker) (() => 1721 vassalForm.Invoke((MethodInvoker) (() =>
2253 { 1722 {
2254 vassalForm.StatusText.Text = @"Could not return object " + objectData.Key.ToString() + 1723 vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
2255 @": " + 1724 @": " +
2256 wasInput(wasKeyValueGet("error", result)); 1725 wasInput(wasKeyValueGet("error", result));
2257 })); 1726 }));
2258 break; 1727 break;
2259 } 1728 }
2260   -  
2261 vassalForm.Invoke((MethodInvoker) (() => 1729 vassalForm.Invoke((MethodInvoker) (() =>
2262 { 1730 {
2263 vassalForm.StatusProgress.Value = 1731 vassalForm.StatusProgress.Value =
2264 Math.Min((int) (Math.Abs(returnUUIDs.Count - totalObjects)/ 1732 Math.Min((int) (100d*Math.Abs(returnUUIDs.Count - totalObjects)/totalObjects), 100);
2265 (double) totalObjects), 100); -  
2266 })); 1733 }));
2267 } while (!returnUUIDs.Count.Equals(0)); 1734 } while (!returnUUIDs.Count.Equals(0));
2268 vassalForm.Invoke((MethodInvoker) (() => -  
2269 { -  
2270 vassalForm.StatusProgress.Value = 100; 1735 vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 100; }));
2271 })); -  
2272 } 1736 }
2273 catch (Exception ex) 1737 catch (Exception ex)
2274 { 1738 {
2275 vassalForm.Invoke((MethodInvoker) (() => 1739 vassalForm.Invoke(
2276 { -  
2277 vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; 1740 (MethodInvoker) (() => { vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; }));
2278 })); -  
2279 } 1741 }
2280 finally 1742 finally
2281 { 1743 {
2282 Monitor.Exit(ClientInstanceTeleportLock); 1744 Monitor.Exit(ClientInstanceTeleportLock);
2283 // Allow teleports and enable button. 1745 // Allow teleports and enable button.
2284 vassalForm.BeginInvoke((MethodInvoker) (() => 1746 vassalForm.BeginInvoke((MethodInvoker) (() =>
2285 { 1747 {
2286 vassalForm.ReturnTopScriptsButton.Enabled = true; 1748 vassalForm.ReturnTopScriptsButton.Enabled = true;
2287 RegionTeleportGroup.Enabled = true; 1749 RegionTeleportGroup.Enabled = true;
2288 })); 1750 }));
2289 } 1751 }
2290 }) 1752 })
2291 {IsBackground = true}.Start(); 1753 {IsBackground = true}.Start();
2292 } 1754 }
2293   1755  
2294 private void RequestReturnTopCollidersObjects(object sender, EventArgs e) 1756 private void RequestReturnTopCollidersObjects(object sender, EventArgs e)
2295 { 1757 {
2296 // Block teleports and disable button. 1758 // Block teleports and disable button.
2297 vassalForm.Invoke((MethodInvoker) (() => 1759 vassalForm.Invoke((MethodInvoker) (() =>
2298 { 1760 {
2299 vassalForm.ReturnTopCollidersButton.Enabled = false; 1761 vassalForm.ReturnTopCollidersButton.Enabled = false;
2300 RegionTeleportGroup.Enabled = false; 1762 RegionTeleportGroup.Enabled = false;
2301 })); 1763 }));
2302   1764  
2303 // Enqueue all the UUIDs to return. 1765 // Enqueue all the UUIDs to return.
2304 Queue<KeyValuePair<UUID, Vector3>> returnObjectUUIDQueue = new Queue<KeyValuePair<UUID, Vector3>>(); 1766 Queue<KeyValuePair<UUID, Vector3>> returnObjectUUIDQueue = new Queue<KeyValuePair<UUID, Vector3>>();
2305 vassalForm.Invoke((MethodInvoker) (() => 1767 vassalForm.Invoke((MethodInvoker) (() =>
2306 { 1768 {
2307 foreach ( 1769 foreach (
2308 DataGridViewRow topCollidersRow in 1770 DataGridViewRow topCollidersRow in
2309 TopCollidersGridView.Rows.AsParallel() 1771 TopCollidersGridView.Rows.AsParallel()
2310 .Cast<DataGridViewRow>() 1772 .Cast<DataGridViewRow>()
2311 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected))) 1773 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
2312 { 1774 {
2313 Vector3 objectPosition; 1775 Vector3 objectPosition;
2314 UUID returnUUID; 1776 UUID returnUUID;
2315 if (!UUID.TryParse(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(), out returnUUID) || 1777 if (!UUID.TryParse(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(), out returnUUID) ||
2316 !Vector3.TryParse(topCollidersRow.Cells["TopCollidersPosition"].Value.ToString(), 1778 !Vector3.TryParse(topCollidersRow.Cells["TopCollidersPosition"].Value.ToString(),
2317 out objectPosition)) 1779 out objectPosition))
2318 continue; 1780 continue;
2319 returnObjectUUIDQueue.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition)); 1781 returnObjectUUIDQueue.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition));
2320 } 1782 }
2321 })); 1783 }));
2322   1784  
2323 // If no rows were selected, enable teleports, the return button and return. 1785 // If no rows were selected, enable teleports, the return button and return.
2324 if (returnObjectUUIDQueue.Count.Equals(0)) 1786 if (returnObjectUUIDQueue.Count.Equals(0))
2325 { 1787 {
2326 vassalForm.Invoke((MethodInvoker) (() => 1788 vassalForm.Invoke((MethodInvoker) (() =>
2327 { 1789 {
2328 vassalForm.ReturnTopCollidersButton.Enabled = true; 1790 vassalForm.ReturnTopCollidersButton.Enabled = true;
2329 RegionTeleportGroup.Enabled = true; 1791 RegionTeleportGroup.Enabled = true;
2330 })); 1792 }));
2331 return; 1793 return;
2332 } 1794 }
2333   1795  
2334 new Thread(() => 1796 new Thread(() =>
2335 { 1797 {
2336 Monitor.Enter(ClientInstanceTeleportLock); 1798 Monitor.Enter(ClientInstanceTeleportLock);
2337   1799  
2338 try 1800 try
2339 { 1801 {
2340 vassalForm.Invoke((MethodInvoker) (() => -  
2341 { -  
2342 vassalForm.StatusProgress.Value = 0; 1802 vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 0; }));
2343 })); -  
2344 int totalObjects = returnObjectUUIDQueue.Count; 1803 int totalObjects = returnObjectUUIDQueue.Count;
2345 do 1804 do
2346 { 1805 {
2347 // Dequeue the first object. 1806 // Dequeue the first object.
2348 KeyValuePair<UUID, Vector3> objectData = returnObjectUUIDQueue.Dequeue(); 1807 KeyValuePair<UUID, Vector3> objectData = returnObjectUUIDQueue.Dequeue();
2349   1808  
2350 vassalForm.Invoke((MethodInvoker) (() => 1809 vassalForm.Invoke(
2351 { 1810 (MethodInvoker)
2352 vassalForm.StatusText.Text = @"Returning UUID: " + objectData.Key.ToString(); -  
2353 })); 1811 (() => { vassalForm.StatusText.Text = @"Returning UUID: " + objectData.Key; }));
2354   -  
2355 string currentRegionName = string.Empty; -  
2356 vassalForm.Invoke((MethodInvoker) (() => 1812  
2357 { -  
2358 currentRegionName = CurrentRegionName.Text; 1813 string currentRegionName = string.Empty;
2359 })); 1814 vassalForm.Invoke((MethodInvoker) (() => { currentRegionName = CurrentRegionName.Text; }));
2360   1815  
2361 // Teleport to the object. 1816 // Teleport to the object.
2362 string result = wasPOST(vassalConfiguration.HTTPServerURL, 1817 string result = wasPOST(vassalConfiguration.HTTPServerURL,
2363 wasKeyValueEscape(new Dictionary<string, string> 1818 wasKeyValueEscape(new Dictionary<string, string>
2364 { 1819 {
2365 {"command", "teleport"}, 1820 {"command", "teleport"},
2366 {"group", vassalConfiguration.Group}, 1821 {"group", vassalConfiguration.Group},
2367 {"password", vassalConfiguration.Password}, 1822 {"password", vassalConfiguration.Password},
2368 {"position", objectData.Value.ToString()}, 1823 {"position", objectData.Value.ToString()},
2369 {"region", currentRegionName}, 1824 {"region", currentRegionName},
2370 {"fly", "True"} 1825 {"fly", "True"}
2371 }), vassalConfiguration.DataTimeout); 1826 }), vassalConfiguration.DataTimeout);
2372   1827  
2373 if (string.IsNullOrEmpty(result)) 1828 if (string.IsNullOrEmpty(result))
2374 { 1829 {
2375 vassalForm.Invoke((MethodInvoker) (() => 1830 vassalForm.Invoke(
2376 { 1831 (MethodInvoker)
2377 vassalForm.StatusText.Text = @"Error communicating with Corrade."; 1832 (() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
2378 })); -  
2379 continue; 1833 continue;
2380 } 1834 }
2381   1835  
2382 // Return the object. 1836 // Return the object.
2383 result = wasPOST(vassalConfiguration.HTTPServerURL, 1837 result = wasPOST(vassalConfiguration.HTTPServerURL,
2384 wasKeyValueEscape(new Dictionary<string, string> 1838 wasKeyValueEscape(new Dictionary<string, string>
2385 { 1839 {
2386 {"command", "derez"}, 1840 {"command", "derez"},
2387 {"group", vassalConfiguration.Group}, 1841 {"group", vassalConfiguration.Group},
2388 {"password", vassalConfiguration.Password}, 1842 {"password", vassalConfiguration.Password},
2389 {"item", objectData.Key.ToString()}, 1843 {"item", objectData.Key.ToString()},
2390 {"range", "32"}, // maximal prim size = 64 - middle bounding box at half 1844 {"range", "32"}, // maximal prim size = 64 - middle bounding box at half
2391 {"type", "ReturnToOwner"} 1845 {"type", "ReturnToOwner"}
2392 }), vassalConfiguration.DataTimeout); 1846 }), vassalConfiguration.DataTimeout);
2393   1847  
2394 if (string.IsNullOrEmpty(result)) 1848 if (string.IsNullOrEmpty(result))
2395 { 1849 {
2396 vassalForm.Invoke((MethodInvoker) (() => 1850 vassalForm.Invoke(
2397 { 1851 (MethodInvoker)
2398 vassalForm.StatusText.Text = @"Error communicating with Corrade."; 1852 (() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
2399 })); -  
2400 continue; 1853 continue;
2401 } 1854 }
2402   1855  
2403 bool success; 1856 bool success;
2404 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 1857 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2405 { 1858 {
2406 vassalForm.Invoke((MethodInvoker) (() => 1859 vassalForm.Invoke(
2407 { 1860 (MethodInvoker)
2408 vassalForm.StatusText.Text = @"No success status could be retrieved. "; 1861 (() => { vassalForm.StatusText.Text = @"No success status could be retrieved. "; }));
2409 })); -  
2410 continue; 1862 continue;
2411 } 1863 }
2412   1864  
2413 switch (success) 1865 switch (success)
2414 { 1866 {
2415 case true: 1867 case true:
2416 vassalForm.Invoke((MethodInvoker) (() => 1868 vassalForm.Invoke((MethodInvoker) (() =>
2417 { 1869 {
2418 vassalForm.StatusText.Text = @"Returned object: " + objectData.Key.ToString(); 1870 vassalForm.StatusText.Text = @"Returned object: " + objectData.Key;
2419 // Remove the row from the grid view. 1871 // Remove the row from the grid view.
2420 DataGridViewRow row = 1872 DataGridViewRow row =
2421 TopCollidersGridView.Rows.AsParallel() 1873 TopCollidersGridView.Rows.AsParallel()
2422 .Cast<DataGridViewRow>() 1874 .Cast<DataGridViewRow>()
2423 .FirstOrDefault( 1875 .FirstOrDefault(
2424 o => o.Cells["TopCollidersUUID"].Value.Equals(objectData.Key.ToString())); 1876 o => o.Cells["TopCollidersUUID"].Value.Equals(objectData.Key.ToString()));
2425 if (row == null) return; 1877 if (row == null) return;
2426 int i = row.Index; 1878 int i = row.Index;
2427 TopCollidersGridView.Rows.RemoveAt(i); 1879 TopCollidersGridView.Rows.RemoveAt(i);
2428 })); 1880 }));
2429 break; 1881 break;
2430 case false: 1882 case false:
2431 vassalForm.Invoke((MethodInvoker) (() => 1883 vassalForm.Invoke((MethodInvoker) (() =>
2432 { 1884 {
2433 vassalForm.StatusText.Text = @"Could not return object " + objectData.Key.ToString() + 1885 vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
2434 @": " + 1886 @": " +
2435 wasInput(wasKeyValueGet("error", result)); 1887 wasInput(wasKeyValueGet("error", result));
2436 })); 1888 }));
2437 break; 1889 break;
2438 } 1890 }
2439   -  
2440 vassalForm.Invoke((MethodInvoker) (() => 1891 vassalForm.Invoke((MethodInvoker) (() =>
2441 { 1892 {
2442 vassalForm.StatusProgress.Value = 1893 vassalForm.StatusProgress.Value =
2443 Math.Min((int) (Math.Abs(returnObjectUUIDQueue.Count - totalObjects)/ 1894 Math.Min(
2444 (double) totalObjects), 100); 1895 (int) (100d*Math.Abs(returnObjectUUIDQueue.Count - totalObjects)/totalObjects), 100);
2445 })); 1896 }));
2446 } while (!returnObjectUUIDQueue.Count.Equals(0)); 1897 } while (!returnObjectUUIDQueue.Count.Equals(0));
2447 vassalForm.Invoke((MethodInvoker) (() => -  
2448 { -  
2449 vassalForm.StatusProgress.Value = 100; 1898 vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 100; }));
2450 })); -  
2451 } 1899 }
2452 catch (Exception ex) 1900 catch (Exception ex)
2453 { 1901 {
2454 vassalForm.Invoke((MethodInvoker) (() => 1902 vassalForm.Invoke(
2455 { -  
2456 vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; 1903 (MethodInvoker) (() => { vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; }));
2457 })); -  
2458 } 1904 }
2459 finally 1905 finally
2460 { 1906 {
2461 Monitor.Exit(ClientInstanceTeleportLock); 1907 Monitor.Exit(ClientInstanceTeleportLock);
2462 // Allow teleports and enable button. 1908 // Allow teleports and enable button.
2463 vassalForm.BeginInvoke((MethodInvoker) (() => 1909 vassalForm.BeginInvoke((MethodInvoker) (() =>
2464 { 1910 {
2465 vassalForm.ReturnTopScriptsButton.Enabled = true; 1911 vassalForm.ReturnTopScriptsButton.Enabled = true;
2466 RegionTeleportGroup.Enabled = true; 1912 RegionTeleportGroup.Enabled = true;
2467 })); 1913 }));
2468 } 1914 }
2469 }) 1915 })
2470 {IsBackground = true}.Start(); 1916 {IsBackground = true}.Start();
2471 } 1917 }
2472   1918  
2473 private void RequestBatchRestart(object sender, EventArgs e) 1919 private void RequestBatchRestart(object sender, EventArgs e)
2474 { 1920 {
2475 // Block teleports and disable button. 1921 // Block teleports and disable button.
2476 vassalForm.Invoke((MethodInvoker) (() => 1922 vassalForm.Invoke((MethodInvoker) (() =>
2477 { 1923 {
2478 vassalForm.BatchRestartButton.Enabled = false; 1924 vassalForm.BatchRestartButton.Enabled = false;
2479 RegionTeleportGroup.Enabled = false; 1925 RegionTeleportGroup.Enabled = false;
2480 })); 1926 }));
2481   1927  
2482 // Enqueue all the regions to restart. 1928 // Enqueue all the regions to restart.
2483 Queue<KeyValuePair<string, Vector3>> restartRegionQueue = new Queue<KeyValuePair<string, Vector3>>(); 1929 Queue<KeyValuePair<string, Vector3>> restartRegionQueue = new Queue<KeyValuePair<string, Vector3>>();
2484 vassalForm.Invoke((MethodInvoker) (() => 1930 vassalForm.Invoke((MethodInvoker) (() =>
2485 { 1931 {
2486 foreach ( 1932 foreach (
2487 DataGridViewRow topCollidersRow in 1933 DataGridViewRow topCollidersRow in
2488 BatchRestartGridView.Rows.AsParallel() 1934 BatchRestartGridView.Rows.AsParallel()
2489 .Cast<DataGridViewRow>() 1935 .Cast<DataGridViewRow>()
2490 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected))) 1936 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
2491 { 1937 {
2492 Vector3 objectPosition; 1938 Vector3 objectPosition;
2493 string regionName = topCollidersRow.Cells["BatchRestartRegionName"].Value.ToString(); 1939 string regionName = topCollidersRow.Cells["BatchRestartRegionName"].Value.ToString();
2494 if (string.IsNullOrEmpty(regionName) || 1940 if (string.IsNullOrEmpty(regionName) ||
2495 !Vector3.TryParse(topCollidersRow.Cells["BatchRestartPosition"].Value.ToString(), 1941 !Vector3.TryParse(topCollidersRow.Cells["BatchRestartPosition"].Value.ToString(),
2496 out objectPosition)) 1942 out objectPosition))
2497 continue; 1943 continue;
2498 restartRegionQueue.Enqueue(new KeyValuePair<string, Vector3>(regionName, objectPosition)); 1944 restartRegionQueue.Enqueue(new KeyValuePair<string, Vector3>(regionName, objectPosition));
2499 } 1945 }
2500 })); 1946 }));
2501   1947  
2502 // If no rows were selected, enable teleports, the return button and return. 1948 // If no rows were selected, enable teleports, the return button and return.
2503 if (restartRegionQueue.Count.Equals(0)) 1949 if (restartRegionQueue.Count.Equals(0))
2504 { 1950 {
2505 vassalForm.Invoke((MethodInvoker) (() => 1951 vassalForm.Invoke((MethodInvoker) (() =>
2506 { 1952 {
2507 vassalForm.BatchRestartButton.Enabled = true; 1953 vassalForm.BatchRestartButton.Enabled = true;
2508 RegionTeleportGroup.Enabled = true; 1954 RegionTeleportGroup.Enabled = true;
2509 })); 1955 }));
2510 return; 1956 return;
2511 } 1957 }
2512   1958  
2513 new Thread(() => 1959 new Thread(() =>
2514 { 1960 {
2515 Monitor.Enter(ClientInstanceTeleportLock); 1961 Monitor.Enter(ClientInstanceTeleportLock);
2516   1962  
2517 try 1963 try
2518 { 1964 {
2519 do 1965 do
2520 { 1966 {
2521 // Dequeue the first object. 1967 // Dequeue the first object.
2522 KeyValuePair<string, Vector3> restartRegionData = restartRegionQueue.Dequeue(); 1968 KeyValuePair<string, Vector3> restartRegionData = restartRegionQueue.Dequeue();
2523 DataGridViewRow currentDataGridViewRow = null; 1969 DataGridViewRow currentDataGridViewRow = null;
2524 vassalForm.Invoke((MethodInvoker) (() => 1970 vassalForm.Invoke((MethodInvoker) (() =>
2525 { 1971 {
2526 currentDataGridViewRow = vassalForm.BatchRestartGridView.Rows.AsParallel() 1972 currentDataGridViewRow = vassalForm.BatchRestartGridView.Rows.AsParallel()
2527 .Cast<DataGridViewRow>() 1973 .Cast<DataGridViewRow>()
2528 .FirstOrDefault( 1974 .FirstOrDefault(
2529 o => 1975 o =>
2530 o.Cells["BatchRestartRegionName"].Value.ToString() 1976 o.Cells["BatchRestartRegionName"].Value.ToString()
2531 .Equals(restartRegionData.Key, StringComparison.OrdinalIgnoreCase) && 1977 .Equals(restartRegionData.Key, StringComparison.OrdinalIgnoreCase) &&
2532 o.Cells["BatchRestartPosition"].Value.ToString() 1978 o.Cells["BatchRestartPosition"].Value.ToString()
2533 .Equals(restartRegionData.Value.ToString(), 1979 .Equals(restartRegionData.Value.ToString(),
2534 StringComparison.OrdinalIgnoreCase)); 1980 StringComparison.OrdinalIgnoreCase));
2535 })); 1981 }));
2536   1982  
2537 if (currentDataGridViewRow == null) continue; 1983 if (currentDataGridViewRow == null) continue;
2538   1984  
2539 try 1985 try
2540 { 1986 {
2541 bool success = false; 1987 bool success = false;
2542 string result; 1988 string result;
2543   1989  
2544 // Retry to teleport to each region a few times. 1990 // Retry to teleport to each region a few times.
2545 int teleportRetries = 3; 1991 int teleportRetries = 3;
2546 do 1992 do
2547 { 1993 {
2548 vassalForm.Invoke((MethodInvoker) (() => 1994 vassalForm.Invoke((MethodInvoker) (() =>
2549 { 1995 {
2550 vassalForm.StatusText.Text = @"Attempting to teleport to " + restartRegionData.Key + 1996 vassalForm.StatusText.Text = @"Attempting to teleport to " + restartRegionData.Key +
2551 @" " + @"(" + 1997 @" " + @"(" +
2552 teleportRetries.ToString(Utils.EnUsCulture) + 1998 teleportRetries.ToString(Utils.EnUsCulture) +
2553 @")"; 1999 @")";
2554 })); 2000 }));
2555   2001  
2556 // Teleport to the region. 2002 // Teleport to the region.
2557 result = wasPOST(vassalConfiguration.HTTPServerURL, 2003 result = wasPOST(vassalConfiguration.HTTPServerURL,
2558 wasKeyValueEscape(new Dictionary<string, string> 2004 wasKeyValueEscape(new Dictionary<string, string>
2559 { 2005 {
2560 {"command", "teleport"}, 2006 {"command", "teleport"},
2561 {"group", vassalConfiguration.Group}, 2007 {"group", vassalConfiguration.Group},
2562 {"password", vassalConfiguration.Password}, 2008 {"password", vassalConfiguration.Password},
2563 {"position", restartRegionData.Value.ToString()}, 2009 {"position", restartRegionData.Value.ToString()},
2564 {"region", restartRegionData.Key}, 2010 {"region", restartRegionData.Key},
2565 {"fly", "True"} 2011 {"fly", "True"}
2566 }), vassalConfiguration.DataTimeout); 2012 }), vassalConfiguration.DataTimeout);
2567   2013  
2568 if (string.IsNullOrEmpty(result)) 2014 if (string.IsNullOrEmpty(result))
2569 { 2015 {
2570 vassalForm.Invoke((MethodInvoker) (() => 2016 vassalForm.Invoke(
-   2017 (MethodInvoker)
-   2018 (() =>
2571 { 2019 {
2572 vassalForm.StatusText.Text = @"Error communicating with Corrade."; 2020 vassalForm.StatusText.Text = @"Error communicating with Corrade.";
2573 })); 2021 }));
2574 continue; 2022 continue;
2575 } 2023 }
2576 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 2024 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2577 { 2025 {
2578 vassalForm.Invoke((MethodInvoker) (() => 2026 vassalForm.Invoke(
-   2027 (MethodInvoker)
-   2028 (() =>
2579 { 2029 {
2580 vassalForm.StatusText.Text = @"No success status could be retrieved. "; 2030 vassalForm.StatusText.Text = @"No success status could be retrieved. ";
2581 })); 2031 }));
2582 continue; 2032 continue;
2583 } 2033 }
2584 switch (success) 2034 switch (success)
2585 { 2035 {
2586 case true: 2036 case true:
2587 vassalForm.Invoke((MethodInvoker) (() => 2037 vassalForm.Invoke(
2588 { 2038 (MethodInvoker)
2589 vassalForm.StatusText.Text = @"Teleport succeeded."; 2039 (() => { vassalForm.StatusText.Text = @"Teleport succeeded."; }));
2590 })); -  
2591 Thread.Sleep(TimeSpan.FromSeconds(1).Milliseconds); 2040 Thread.Sleep(TimeSpan.FromSeconds(1).Milliseconds);
2592 break; 2041 break;
2593 default: 2042 default:
2594 // In case the destination is to close (Corrade status code 37559), 2043 // In case the destination is to close (Corrade status code 37559),
2595 // then we are on the same region so no need to retry. 2044 // then we are on the same region so no need to retry.
2596 uint status; //37559 2045 uint status; //37559
2597 switch ( 2046 switch (
2598 uint.TryParse(wasInput(wasKeyValueGet("status", result)), out status) && 2047 uint.TryParse(wasInput(wasKeyValueGet("status", result)), out status) &&
2599 status.Equals(37559)) 2048 status.Equals(37559))
2600 { 2049 {
2601 case true: // We are on the region already! 2050 case true: // We are on the region already!
2602 success = true; 2051 success = true;
2603 break; 2052 break;
2604 default: 2053 default:
2605 vassalForm.Invoke((MethodInvoker) (() => 2054 vassalForm.Invoke(
2606 { 2055 (MethodInvoker)
2607 vassalForm.StatusText.Text = @"Teleport failed."; 2056 (() => { vassalForm.StatusText.Text = @"Teleport failed."; }));
2608 })); -  
2609 Thread.Sleep(10000); 2057 Thread.Sleep(10000);
2610 break; 2058 break;
2611 } 2059 }
2612 break; 2060 break;
2613 } 2061 }
2614 } while (!success && !(--teleportRetries).Equals(0)); 2062 } while (!success && !(--teleportRetries).Equals(0));
2615   2063  
2616 if (!success) 2064 if (!success)
2617 throw new Exception("Failed to teleport to region."); 2065 throw new Exception("Failed to teleport to region.");
2618   2066  
2619 result = wasPOST(vassalConfiguration.HTTPServerURL, 2067 result = wasPOST(vassalConfiguration.HTTPServerURL,
2620 wasKeyValueEscape(new Dictionary<string, string> 2068 wasKeyValueEscape(new Dictionary<string, string>
2621 { 2069 {
2622 {"command", "getregiondata"}, 2070 {"command", "getregiondata"},
2623 {"group", vassalConfiguration.Group}, 2071 {"group", vassalConfiguration.Group},
2624 {"password", vassalConfiguration.Password}, 2072 {"password", vassalConfiguration.Password},
2625 {"data", "IsEstateManager"} 2073 {"data", "IsEstateManager"}
2626 }), vassalConfiguration.DataTimeout); 2074 }), vassalConfiguration.DataTimeout);
2627   2075  
2628 if (string.IsNullOrEmpty(result)) 2076 if (string.IsNullOrEmpty(result))
2629 throw new Exception("Error communicating with Corrade."); 2077 throw new Exception("Error communicating with Corrade.");
2630   2078  
2631 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 2079 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2632 throw new Exception("No success status could be retrieved."); 2080 throw new Exception("No success status could be retrieved.");
2633   2081  
2634 if (!success) 2082 if (!success)
2635 throw new Exception("Could not retrieve estate rights."); 2083 throw new Exception("Could not retrieve estate rights.");
2636   2084  
2637 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList(); 2085 List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))).ToList();
2638 if (!data.Count.Equals(2)) 2086 if (!data.Count.Equals(2))
2639 throw new Exception("Could not retrieve estate rights."); 2087 throw new Exception("Could not retrieve estate rights.");
2640   2088  
2641 bool isEstateManager; 2089 bool isEstateManager;
2642 switch ( 2090 switch (
2643 bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) && 2091 bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) &&
2644 isEstateManager) 2092 isEstateManager)
2645 { 2093 {
2646 case true: // we are an estate manager 2094 case true: // we are an estate manager
2647 result = wasPOST(vassalConfiguration.HTTPServerURL, 2095 result = wasPOST(vassalConfiguration.HTTPServerURL,
2648 wasKeyValueEscape(new Dictionary<string, string> 2096 wasKeyValueEscape(new Dictionary<string, string>
2649 { 2097 {
2650 {"command", "restartregion"}, 2098 {"command", "restartregion"},
2651 {"group", vassalConfiguration.Group}, 2099 {"group", vassalConfiguration.Group},
2652 {"password", vassalConfiguration.Password}, 2100 {"password", vassalConfiguration.Password},
2653 {"action", "restart"}, 2101 {"action", "restart"},
2654 { 2102 {
-   2103 "delay",
2655 "delay", vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture) 2104 vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture)
2656 } 2105 }
2657 }), vassalConfiguration.DataTimeout); 2106 }), vassalConfiguration.DataTimeout);
2658   2107  
2659 if (string.IsNullOrEmpty(result)) 2108 if (string.IsNullOrEmpty(result))
2660 throw new Exception("Error communicating with Corrade."); 2109 throw new Exception("Error communicating with Corrade.");
2661   2110  
2662 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 2111 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2663 throw new Exception("No success status could be retrieved."); 2112 throw new Exception("No success status could be retrieved.");
2664   2113  
2665 if (!success) 2114 if (!success)
2666 throw new Exception("Could not schedule a region restart."); 2115 throw new Exception("Could not schedule a region restart.");
2667   2116  
2668 vassalForm.Invoke((MethodInvoker) (() => 2117 vassalForm.Invoke((MethodInvoker) (() =>
2669 { 2118 {
2670 vassalForm.StatusText.Text = @"Region scheduled for restart."; 2119 vassalForm.StatusText.Text = @"Region scheduled for restart.";
2671 currentDataGridViewRow.Selected = false; 2120 currentDataGridViewRow.Selected = false;
2672 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen; 2121 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen;
2673 foreach ( 2122 foreach (
2674 DataGridViewCell cell in 2123 DataGridViewCell cell in
2675 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>()) 2124 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
2676 { 2125 {
2677 cell.ToolTipText = @"Region scheduled for restart."; 2126 cell.ToolTipText = @"Region scheduled for restart.";
2678 } 2127 }
2679 })); 2128 }));
2680 break; 2129 break;
2681 default: 2130 default:
2682 throw new Exception("No estate manager rights for region restart."); 2131 throw new Exception("No estate manager rights for region restart.");
2683 } 2132 }
2684 } 2133 }
2685 catch (Exception ex) 2134 catch (Exception ex)
2686 { 2135 {
2687 vassalForm.Invoke((MethodInvoker) (() => 2136 vassalForm.Invoke((MethodInvoker) (() =>
2688 { 2137 {
2689 vassalForm.StatusText.Text = ex.Message; 2138 vassalForm.StatusText.Text = ex.Message;
2690 currentDataGridViewRow.Selected = false; 2139 currentDataGridViewRow.Selected = false;
2691 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink; 2140 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink;
2692 foreach ( 2141 foreach (
2693 DataGridViewCell cell in 2142 DataGridViewCell cell in
2694 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>()) 2143 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
2695 { 2144 {
2696 cell.ToolTipText = ex.Message; 2145 cell.ToolTipText = ex.Message;
2697 } 2146 }
2698 })); 2147 }));
2699 } 2148 }
2700 } while (!restartRegionQueue.Count.Equals(0)); 2149 } while (!restartRegionQueue.Count.Equals(0));
2701 } 2150 }
2702 catch (Exception) 2151 catch (Exception)
2703 { 2152 {
2704   -  
2705 } 2153 }
2706 finally 2154 finally
2707 { 2155 {
2708 Monitor.Exit(ClientInstanceTeleportLock); 2156 Monitor.Exit(ClientInstanceTeleportLock);
2709 // Allow teleports and enable button. 2157 // Allow teleports and enable button.
2710 vassalForm.BeginInvoke((MethodInvoker) (() => 2158 vassalForm.BeginInvoke((MethodInvoker) (() =>
2711 { 2159 {
2712 vassalForm.BatchRestartButton.Enabled = true; 2160 vassalForm.BatchRestartButton.Enabled = true;
2713 RegionTeleportGroup.Enabled = true; 2161 RegionTeleportGroup.Enabled = true;
2714 })); 2162 }));
2715 } 2163 }
2716 }) 2164 })
2717 {IsBackground = true}.Start(); 2165 {IsBackground = true}.Start();
2718   -  
2719 } 2166 }
2720   2167  
2721 private void RequestFilterResidentList(object sender, EventArgs e) 2168 private void RequestFilterResidentList(object sender, EventArgs e)
2722 { 2169 {
2723 vassalForm.BeginInvoke((MethodInvoker) (() => 2170 vassalForm.BeginInvoke((MethodInvoker) (() =>
2724 { 2171 {
2725 Regex residentListRowRegex; 2172 Regex residentListRowRegex;
2726 switch (!string.IsNullOrEmpty(ResidentListFilter.Text)) 2173 switch (!string.IsNullOrEmpty(ResidentListFilter.Text))
2727 { 2174 {
2728 case true: 2175 case true:
2729 residentListRowRegex = new Regex(ResidentListFilter.Text, RegexOptions.Compiled); 2176 residentListRowRegex = new Regex(ResidentListFilter.Text, RegexOptions.Compiled);
2730 break; 2177 break;
2731 default: 2178 default:
2732 residentListRowRegex = new Regex(@".+?", RegexOptions.Compiled); 2179 residentListRowRegex = new Regex(@".+?", RegexOptions.Compiled);
2733 break; 2180 break;
2734 } 2181 }
2735 foreach ( 2182 foreach (
2736 DataGridViewRow residentListRow in ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>()) 2183 DataGridViewRow residentListRow in ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>())
2737 { 2184 {
2738 residentListRow.Visible = 2185 residentListRow.Visible =
2739 residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListName"].Value.ToString()) || 2186 residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListName"].Value.ToString()) ||
2740 residentListRowRegex.IsMatch( 2187 residentListRowRegex.IsMatch(
2741 residentListRow.Cells["ResidentListUUID"].Value.ToString()) || 2188 residentListRow.Cells["ResidentListUUID"].Value.ToString()) ||
2742 residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListPosition"].Value.ToString()); 2189 residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListPosition"].Value.ToString());
2743 } 2190 }
2744 })); 2191 }));
2745 } 2192 }
2746   2193  
2747 private void RequestBanAgents(object sender, EventArgs e) 2194 private void RequestBanAgents(object sender, EventArgs e)
2748 { 2195 {
2749 // Block teleports and disable button. 2196 // Block teleports and disable button.
2750 vassalForm.Invoke((MethodInvoker) (() => 2197 vassalForm.Invoke((MethodInvoker) (() =>
2751 { 2198 {
2752 ResidentListBanGroup.Enabled = false; 2199 ResidentListBanGroup.Enabled = false;
2753 RegionTeleportGroup.Enabled = false; 2200 RegionTeleportGroup.Enabled = false;
2754 })); 2201 }));
2755   2202  
2756 // Enqueue all the regions to restart. 2203 // Enqueue all the regions to restart.
2757 Queue<UUID> agentsQueue = new Queue<UUID>(); 2204 Queue<UUID> agentsQueue = new Queue<UUID>();
2758 vassalForm.Invoke((MethodInvoker) (() => 2205 vassalForm.Invoke((MethodInvoker) (() =>
2759 { 2206 {
2760 foreach ( 2207 foreach (
2761 DataGridViewRow residentListRow in 2208 DataGridViewRow residentListRow in
2762 ResidentListGridView.Rows.AsParallel() 2209 ResidentListGridView.Rows.AsParallel()
2763 .Cast<DataGridViewRow>() 2210 .Cast<DataGridViewRow>()
2764 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected))) 2211 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
2765 { 2212 {
2766 UUID agentUUID; 2213 UUID agentUUID;
2767 if (!UUID.TryParse(residentListRow.Cells["ResidentListUUID"].Value.ToString(), out agentUUID)) 2214 if (!UUID.TryParse(residentListRow.Cells["ResidentListUUID"].Value.ToString(), out agentUUID))
2768 continue; 2215 continue;
2769 agentsQueue.Enqueue(agentUUID); 2216 agentsQueue.Enqueue(agentUUID);
2770 } 2217 }
2771 })); 2218 }));
2772   2219  
2773 // If no rows were selected, enable teleports, the return button and return. 2220 // If no rows were selected, enable teleports, the return button and return.
2774 if (agentsQueue.Count.Equals(0)) 2221 if (agentsQueue.Count.Equals(0))
2775 { 2222 {
2776 vassalForm.Invoke((MethodInvoker) (() => 2223 vassalForm.Invoke((MethodInvoker) (() =>
2777 { 2224 {
2778 ResidentListBanGroup.Enabled = true; 2225 ResidentListBanGroup.Enabled = true;
2779 RegionTeleportGroup.Enabled = true; 2226 RegionTeleportGroup.Enabled = true;
2780 })); 2227 }));
2781 return; 2228 return;
2782 } 2229 }
2783   2230  
2784 new Thread(() => 2231 new Thread(() =>
2785 { 2232 {
2786 Monitor.Enter(ClientInstanceTeleportLock); 2233 Monitor.Enter(ClientInstanceTeleportLock);
2787 try 2234 try
2788 { 2235 {
2789 do 2236 do
2790 { 2237 {
2791 // Dequeue the first object. 2238 // Dequeue the first object.
2792 UUID agentUUID = agentsQueue.Dequeue(); 2239 UUID agentUUID = agentsQueue.Dequeue();
2793 DataGridViewRow currentDataGridViewRow = null; 2240 DataGridViewRow currentDataGridViewRow = null;
2794 vassalForm.Invoke((MethodInvoker) (() => 2241 vassalForm.Invoke((MethodInvoker) (() =>
2795 { 2242 {
2796 currentDataGridViewRow = vassalForm.ResidentListGridView.Rows.AsParallel() 2243 currentDataGridViewRow = vassalForm.ResidentListGridView.Rows.AsParallel()
2797 .Cast<DataGridViewRow>() 2244 .Cast<DataGridViewRow>()
2798 .FirstOrDefault( 2245 .FirstOrDefault(
2799 o => 2246 o =>
2800 o.Cells["ResidentListUUID"].Value.ToString() 2247 o.Cells["ResidentListUUID"].Value.ToString()
2801 .Equals(agentUUID.ToString(), StringComparison.OrdinalIgnoreCase)); 2248 .Equals(agentUUID.ToString(), StringComparison.OrdinalIgnoreCase));
2802 })); 2249 }));
2803   2250  
2804 if (currentDataGridViewRow == null) continue; 2251 if (currentDataGridViewRow == null) continue;
2805   2252  
2806 try 2253 try
2807 { 2254 {
2808 bool alsoBan = false; 2255 bool alsoBan = false;
2809 vassalForm.Invoke((MethodInvoker) (() => 2256 vassalForm.Invoke(
2810 { -  
2811 alsoBan = vassalForm.ResidentBanAllEstatesBox.Checked; 2257 (MethodInvoker) (() => { alsoBan = vassalForm.ResidentBanAllEstatesBox.Checked; }));
2812 })); -  
2813   2258  
2814 // Teleport to the region. 2259 // Teleport to the region.
2815 string result = wasPOST(vassalConfiguration.HTTPServerURL, 2260 string result = wasPOST(vassalConfiguration.HTTPServerURL,
2816 wasKeyValueEscape(new Dictionary<string, string> 2261 wasKeyValueEscape(new Dictionary<string, string>
2817 { 2262 {
2818 {"command", "setestatelist"}, 2263 {"command", "setestatelist"},
2819 {"group", vassalConfiguration.Group}, 2264 {"group", vassalConfiguration.Group},
2820 {"password", vassalConfiguration.Password}, 2265 {"password", vassalConfiguration.Password},
2821 {"type", "ban"}, 2266 {"type", "ban"},
2822 {"action", "add"}, 2267 {"action", "add"},
2823 {"agent", agentUUID.ToString()}, 2268 {"agent", agentUUID.ToString()},
2824 {"all", alsoBan.ToString()} 2269 {"all", alsoBan.ToString()}
2825 }), vassalConfiguration.DataTimeout); 2270 }), vassalConfiguration.DataTimeout);
2826   2271  
2827 if (string.IsNullOrEmpty(result)) 2272 if (string.IsNullOrEmpty(result))
2828 throw new Exception("Error communicating with Corrade."); 2273 throw new Exception("Error communicating with Corrade.");
2829   2274  
2830 bool success; 2275 bool success;
2831 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 2276 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2832 throw new Exception("No success status could be retrieved."); 2277 throw new Exception("No success status could be retrieved.");
2833   2278  
2834 switch (success) 2279 switch (success)
2835 { 2280 {
2836 case true: 2281 case true:
2837 vassalForm.Invoke((MethodInvoker) (() => 2282 vassalForm.Invoke((MethodInvoker) (() =>
2838 { 2283 {
2839 vassalForm.StatusText.Text = @"Resident banned."; 2284 vassalForm.StatusText.Text = @"Resident banned.";
2840 currentDataGridViewRow.Selected = false; 2285 currentDataGridViewRow.Selected = false;
2841 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen; 2286 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen;
2842 foreach ( 2287 foreach (
2843 DataGridViewCell cell in 2288 DataGridViewCell cell in
2844 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>()) 2289 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
2845 { 2290 {
2846 cell.ToolTipText = @"Resident banned."; 2291 cell.ToolTipText = @"Resident banned.";
2847 } 2292 }
2848 })); 2293 }));
2849 break; 2294 break;
2850 default: 2295 default:
2851 throw new Exception("Unable to ban resident."); 2296 throw new Exception("Unable to ban resident.");
2852 } 2297 }
2853 } 2298 }
2854 catch (Exception ex) 2299 catch (Exception ex)
2855 { 2300 {
2856 vassalForm.Invoke((MethodInvoker) (() => 2301 vassalForm.Invoke((MethodInvoker) (() =>
2857 { 2302 {
2858 vassalForm.StatusText.Text = ex.Message; 2303 vassalForm.StatusText.Text = ex.Message;
2859 currentDataGridViewRow.Selected = false; 2304 currentDataGridViewRow.Selected = false;
2860 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink; 2305 currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink;
2861 foreach ( 2306 foreach (
2862 DataGridViewCell cell in 2307 DataGridViewCell cell in
2863 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>()) 2308 currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
2864 { 2309 {
2865 cell.ToolTipText = ex.Message; 2310 cell.ToolTipText = ex.Message;
2866 } 2311 }
2867 })); 2312 }));
2868 } 2313 }
2869   -  
2870 } while (agentsQueue.Count.Equals(0)); 2314 } while (agentsQueue.Count.Equals(0));
2871 } 2315 }
2872 catch (Exception) 2316 catch (Exception)
2873 { 2317 {
2874   -  
2875 } 2318 }
2876 finally 2319 finally
2877 { 2320 {
2878 Monitor.Exit(ClientInstanceTeleportLock); 2321 Monitor.Exit(ClientInstanceTeleportLock);
2879 // Allow teleports and enable button. 2322 // Allow teleports and enable button.
2880 vassalForm.BeginInvoke((MethodInvoker) (() => 2323 vassalForm.BeginInvoke((MethodInvoker) (() =>
2881 { 2324 {
2882 ResidentListBanGroup.Enabled = true; 2325 ResidentListBanGroup.Enabled = true;
2883 RegionTeleportGroup.Enabled = true; 2326 RegionTeleportGroup.Enabled = true;
2884 })); 2327 }));
2885 } 2328 }
2886 }) 2329 })
2887 {IsBackground = true}.Start(); 2330 {IsBackground = true}.Start();
2888 } 2331 }
2889   2332  
2890 private void RequestRipTerrain(object sender, EventArgs e) 2333 private void RequestRipTerrain(object sender, EventArgs e)
2891 { 2334 {
2892 // Block teleports and disable button. 2335 // Block teleports and disable button.
2893 vassalForm.Invoke((MethodInvoker) (() => 2336 vassalForm.Invoke((MethodInvoker) (() =>
2894 { 2337 {
2895 RegionTeleportGroup.Enabled = false; 2338 RegionTeleportGroup.Enabled = false;
2896 RipTerrainButton.Enabled = false; 2339 RipTerrainButton.Enabled = false;
2897 })); 2340 }));
2898   2341  
2899 new Thread(() => 2342 new Thread(() =>
2900 { 2343 {
2901 Monitor.Enter(ClientInstanceTeleportLock); 2344 Monitor.Enter(ClientInstanceTeleportLock);
2902   2345  
2903 try 2346 try
2904 { 2347 {
2905 // Get the statistics. 2348 // Get the map heights.
2906 string result = wasPOST(vassalConfiguration.HTTPServerURL, 2349 string result = wasPOST(vassalConfiguration.HTTPServerURL,
2907 wasKeyValueEscape(new Dictionary<string, string> 2350 wasKeyValueEscape(new Dictionary<string, string>
2908 { 2351 {
2909 {"command", "getterrainheight"}, 2352 {"command", "getterrainheight"},
2910 {"group", vassalConfiguration.Group}, 2353 {"group", vassalConfiguration.Group},
2911 {"password", vassalConfiguration.Password}, 2354 {"password", vassalConfiguration.Password},
2912 {"entity", "region"} 2355 {"entity", "region"}
2913 }), vassalConfiguration.DataTimeout); 2356 }), vassalConfiguration.DataTimeout);
2914   2357  
2915 if (string.IsNullOrEmpty(result)) 2358 if (string.IsNullOrEmpty(result))
2916 throw new Exception("Error communicating with Corrade."); 2359 throw new Exception("Error communicating with Corrade.");
2917   2360  
2918 bool success; 2361 bool success;
2919 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) 2362 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
2920 throw new Exception("No success status could be retrieved."); 2363 throw new Exception("No success status could be retrieved.");
2921   2364  
2922 if (!success) 2365 if (!success)
2923 throw new Exception("Could not get terrain heights."); 2366 throw new Exception("Could not get terrain heights.");
2924   2367  
2925 List<double> heights = new List<double>(); 2368 List<double> heights = new List<double>();
2926 foreach (string map in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))) 2369 foreach (string map in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result))))
2927 { 2370 {
2928 double height; 2371 double height;
2929 if (!double.TryParse(map, out height)) 2372 if (!double.TryParse(map, out height))
2930 continue; 2373 continue;
2931 heights.Add(height); 2374 heights.Add(height);
2932 } 2375 }
2933 if (heights.Count.Equals(0)) 2376 if (heights.Count.Equals(0))
2934 throw new Exception("Could not get terrain heights."); 2377 throw new Exception("Could not get terrain heights.");
2935   2378  
2936 double maxHeight = heights.Max(); 2379 double maxHeight = heights.Max();
2937 using (Bitmap bitmap = new Bitmap(256, 256)) 2380 using (Bitmap bitmap = new Bitmap(256, 256))
2938 { 2381 {
2939 foreach (int x in Enumerable.Range(1, 255)) 2382 foreach (int x in Enumerable.Range(1, 255))
2940 { 2383 {
2941 foreach (int y in Enumerable.Range(1, 255)) 2384 foreach (int y in Enumerable.Range(1, 255))
2942 { 2385 {
2943 bitmap.SetPixel(x, 256 - y, 2386 bitmap.SetPixel(x, 256 - y,
-   2387 Color.FromArgb(
2944 Color.FromArgb((int) wasMapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0, 0)); 2388 Math.Max((int) wasMapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0),
-   2389 0, 0));
2945 } 2390 }
2946 } 2391 }
2947 Bitmap closureBitmap = (Bitmap)bitmap.Clone(); 2392 Bitmap closureBitmap = (Bitmap) bitmap.Clone();
2948 vassalForm.BeginInvoke((MethodInvoker) (() => 2393 vassalForm.BeginInvoke((MethodInvoker) (() =>
2949 { 2394 {
2950 switch (vassalForm.SaveTerrainFileDialog.ShowDialog()) 2395 switch (vassalForm.SavePNGFileDialog.ShowDialog())
2951 { 2396 {
2952 case DialogResult.OK: 2397 case DialogResult.OK:
2953 string file = vassalForm.SaveTerrainFileDialog.FileName; 2398 string file = vassalForm.SavePNGFileDialog.FileName;
2954 new Thread(() => 2399 new Thread(() =>
2955 { 2400 {
2956 vassalForm.BeginInvoke((MethodInvoker) (() => 2401 vassalForm.BeginInvoke((MethodInvoker) (() =>
2957 { 2402 {
2958 try 2403 try
2959 { 2404 {
2960 vassalForm.StatusText.Text = @"saving terrain..."; 2405 vassalForm.StatusText.Text = @"saving terrain...";
2961 vassalForm.StatusProgress.Value = 0; 2406 vassalForm.StatusProgress.Value = 0;
2962   2407  
2963 closureBitmap.Save(file, ImageFormat.Png); 2408 closureBitmap.Save(file, ImageFormat.Png);
2964   2409  
2965 vassalForm.StatusText.Text = @"terrain saved"; 2410 vassalForm.StatusText.Text = @"terrain saved";
2966 vassalForm.StatusProgress.Value = 100; 2411 vassalForm.StatusProgress.Value = 100;
2967 } 2412 }
2968 catch (Exception ex) 2413 catch (Exception ex)
2969 { 2414 {
2970 vassalForm.StatusText.Text = ex.Message; 2415 vassalForm.StatusText.Text = ex.Message;
2971 } 2416 }
2972 finally 2417 finally
2973 { 2418 {
2974 closureBitmap.Dispose(); 2419 closureBitmap.Dispose();
2975 } 2420 }
2976 })); 2421 }));
2977 }) 2422 })
2978 {IsBackground = true, Priority = ThreadPriority.Normal}.Start(); 2423 {IsBackground = true}.Start();
2979 break; 2424 break;
2980 } 2425 }
2981 })); 2426 }));
2982 } 2427 }
2983 -  
2984 } 2428 }
2985 catch (Exception ex) 2429 catch (Exception ex)
2986 { 2430 {
-   2431 vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   2432 }
-   2433 finally
-   2434 {
-   2435 Monitor.Exit(ClientInstanceTeleportLock);
-   2436 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   2437 {
-   2438 RegionTeleportGroup.Enabled = true;
-   2439 RipTerrainButton.Enabled = true;
-   2440 }));
-   2441 }
-   2442 }) {IsBackground = true}.Start();
-   2443 }
-   2444  
-   2445 private void RequestDownloadTerrain(object sender, EventArgs e)
-   2446 {
-   2447 // Block teleports and disable button.
-   2448 vassalForm.Invoke((MethodInvoker) (() =>
-   2449 {
-   2450 RegionTeleportGroup.Enabled = false;
-   2451 DownloadTerrainButton.Enabled = false;
-   2452 }));
-   2453  
-   2454 new Thread(() =>
-   2455 {
-   2456 Monitor.Enter(ClientInstanceTeleportLock);
-   2457  
-   2458 try
-   2459 {
-   2460 // Download the terrain.
-   2461 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2462 wasKeyValueEscape(new Dictionary<string, string>
-   2463 {
-   2464 {"command", "terrain"},
-   2465 {"group", vassalConfiguration.Group},
-   2466 {"password", vassalConfiguration.Password},
-   2467 {"action", "get"}
-   2468 }), vassalConfiguration.DataTimeout);
-   2469  
-   2470 if (string.IsNullOrEmpty(result))
-   2471 throw new Exception("Error communicating with Corrade.");
-   2472  
-   2473 bool success;
-   2474 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2475 throw new Exception("No success status could be retrieved.");
-   2476  
-   2477 if (!success)
-   2478 throw new Exception("Could not download terrain.");
-   2479  
-   2480 byte[] data = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
-   2481  
-   2482 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   2483 {
-   2484 switch (vassalForm.SaveRawFileDialog.ShowDialog())
-   2485 {
-   2486 case DialogResult.OK:
-   2487 string file = vassalForm.SaveRawFileDialog.FileName;
-   2488 new Thread(() =>
-   2489 {
-   2490 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   2491 {
-   2492 try
-   2493 {
-   2494 vassalForm.StatusText.Text = @"saving terrain...";
-   2495 vassalForm.StatusProgress.Value = 0;
-   2496  
-   2497 File.WriteAllBytes(file, data);
-   2498  
-   2499 vassalForm.StatusText.Text = @"terrain saved";
-   2500 vassalForm.StatusProgress.Value = 100;
-   2501 }
-   2502 catch (Exception ex)
-   2503 {
-   2504 vassalForm.StatusText.Text = ex.Message;
-   2505 }
-   2506 }));
-   2507 })
-   2508 {IsBackground = true}.Start();
-   2509 break;
-   2510 }
-   2511 }));
-   2512 }
-   2513 catch (Exception ex)
-   2514 {
-   2515 vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   2516 }
-   2517 finally
-   2518 {
-   2519 Monitor.Exit(ClientInstanceTeleportLock);
2987 vassalForm.BeginInvoke((MethodInvoker)(() => 2520 vassalForm.BeginInvoke((MethodInvoker) (() =>
2988 { 2521 {
-   2522 DownloadTerrainButton.Enabled = true;
2989 StatusText.Text = ex.Message; 2523 RegionTeleportGroup.Enabled = true;
2990 })); 2524 }));
2991 } 2525 }
-   2526 })
-   2527 {IsBackground = true}.Start();
-   2528 }
-   2529  
-   2530 private void RequestUploadTerrain(object sender, EventArgs e)
-   2531 {
-   2532 // Block teleports and disable button.
-   2533 vassalForm.Invoke((MethodInvoker) (() =>
-   2534 {
-   2535 RegionTeleportGroup.Enabled = false;
-   2536 UploadTerrainButton.Enabled = false;
-   2537 }));
-   2538  
-   2539 new Thread(() =>
-   2540 {
-   2541 Monitor.Enter(ClientInstanceTeleportLock);
-   2542  
-   2543 try
-   2544 {
-   2545 byte[] data = null;
-   2546 vassalForm.Invoke((MethodInvoker) (() =>
-   2547 {
-   2548 switch (vassalForm.LoadRawFileDialog.ShowDialog())
-   2549 {
-   2550 case DialogResult.OK:
-   2551 string file = vassalForm.LoadRawFileDialog.FileName;
-   2552 vassalForm.StatusText.Text = @"loading terrain...";
-   2553 vassalForm.StatusProgress.Value = 0;
-   2554  
-   2555 data = File.ReadAllBytes(file);
-   2556  
-   2557 vassalForm.StatusText.Text = @"terrain loaded";
-   2558 vassalForm.StatusProgress.Value = 100;
-   2559 break;
-   2560 }
-   2561 }));
-   2562  
-   2563 // Upload the terrain.
-   2564 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2565 wasKeyValueEscape(new Dictionary<string, string>
-   2566 {
-   2567 {"command", "terrain"},
-   2568 {"group", vassalConfiguration.Group},
-   2569 {"password", vassalConfiguration.Password},
-   2570 {"action", "set"},
-   2571 {"data", Convert.ToBase64String(data)}
-   2572 }), vassalConfiguration.DataTimeout);
-   2573  
-   2574 if (string.IsNullOrEmpty(result))
-   2575 throw new Exception("Error communicating with Corrade.");
-   2576  
-   2577 bool success;
-   2578 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2579 throw new Exception("No success status could be retrieved.");
-   2580  
-   2581 if (!success)
-   2582 throw new Exception("Could not upload terrain.");
-   2583 }
-   2584 catch (Exception ex)
-   2585 {
-   2586 vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   2587 }
2992 finally 2588 finally
2993 { 2589 {
2994 Monitor.Exit(ClientInstanceTeleportLock); 2590 Monitor.Exit(ClientInstanceTeleportLock);
2995 vassalForm.BeginInvoke((MethodInvoker)(() => 2591 vassalForm.BeginInvoke((MethodInvoker) (() =>
2996 { 2592 {
-   2593 UploadTerrainButton.Enabled = true;
2997 RegionTeleportGroup.Enabled = true; 2594 RegionTeleportGroup.Enabled = true;
2998 RipTerrainButton.Enabled = true; -  
2999 })); 2595 }));
3000 } 2596 }
-   2597 })
-   2598 {IsBackground = true}.Start();
-   2599 }
-   2600  
-   2601 private void RequestTabsChanged(object sender, EventArgs e)
-   2602 {
-   2603 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   2604 {
-   2605 overviewTabTimer.Stop();
-   2606 regionsStateTabTimer.Stop();
-   2607 residentListTabTimer.Stop();
-   2608 estateTopTabTimer.Stop();
-   2609  
-   2610 if (Tabs.SelectedTab.Equals(OverviewTab))
3001   2611 {
-   2612 overviewTabTimer.Start();
-   2613 return;
-   2614 }
-   2615 if (Tabs.SelectedTab.Equals(RegionsStateTab))
-   2616 {
-   2617 regionsStateTabTimer.Start();
-   2618 return;
-   2619 }
-   2620 if (Tabs.SelectedTab.Equals(ResidentListTab))
-   2621 {
-   2622 residentListTabTimer.Start();
-   2623 return;
-   2624 }
-   2625 if (Tabs.SelectedTab.Equals(EstateTopTab))
-   2626 {
-   2627 estateTopTabTimer.Start();
-   2628 return;
-   2629 }
-   2630 if (Tabs.SelectedTab.Equals(EstateTexturesTab))
-   2631 {
-   2632 estateTexturesTabTimer.Start();
-   2633 }
3002 }) {IsBackground = true}.Start(); 2634 }));
-   2635 }
-   2636  
-   2637 private void RequestFilterEstateList(object sender, EventArgs e)
-   2638 {
-   2639 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   2640 {
-   2641 Regex estateListRowRegex;
-   2642 switch (!string.IsNullOrEmpty(EstateListFilter.Text))
-   2643 {
-   2644 case true:
-   2645 estateListRowRegex = new Regex(EstateListFilter.Text, RegexOptions.Compiled);
-   2646 break;
-   2647 default:
-   2648 estateListRowRegex = new Regex(@".+?", RegexOptions.Compiled);
-   2649 break;
-   2650 }
-   2651 foreach (DataGridViewRow estateListRow in EstateListGridView.Rows.AsParallel().Cast<DataGridViewRow>())
-   2652 {
-   2653 estateListRow.Visible =
-   2654 estateListRowRegex.IsMatch(estateListRow.Cells["EstateListName"].Value.ToString());
-   2655 }
-   2656 }));
-   2657 }
-   2658  
-   2659 private void EstateListSelected(object sender, EventArgs e)
-   2660 {
-   2661 string selectedEstateListType = string.Empty;
-   2662 bool queryEstateList = false;
-   2663 vassalForm.Invoke((MethodInvoker) (() =>
-   2664 {
-   2665 if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
-   2666 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   2667 switch (
-   2668 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   2669 {
-   2670 case true:
-   2671 queryEstateList = true;
-   2672 break;
-   2673 default:
-   2674 EstateListsResidentsGroup.Enabled = false;
-   2675 EstateListsGroupsGroup.Enabled = false;
-   2676 queryEstateList = false;
-   2677 break;
-   2678 }
-   2679 }));
-   2680  
-   2681 if (!queryEstateList) return;
-   2682  
-   2683 new Thread(() =>
-   2684 {
-   2685 try
-   2686 {
-   2687 Monitor.Enter(ClientInstanceTeleportLock);
-   2688  
-   2689 // Disable controls.
-   2690 vassalForm.Invoke((MethodInvoker) (() =>
-   2691 {
-   2692 RegionTeleportGroup.Enabled = false;
-   2693 EstateListsResidentsGroup.Enabled = false;
-   2694 EstateListsGroupsGroup.Enabled = false;
-   2695 }));
-   2696  
-   2697 // Get the selected estate list.
-   2698 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2699 wasKeyValueEscape(new Dictionary<string, string>
-   2700 {
-   2701 {"command", "getestatelist"},
-   2702 {"group", vassalConfiguration.Group},
-   2703 {"password", vassalConfiguration.Password},
-   2704 {"type", selectedEstateListType}
-   2705 }), vassalConfiguration.DataTimeout);
-   2706  
-   2707 if (string.IsNullOrEmpty(result))
-   2708 throw new Exception("Error communicating with Corrade.");
-   2709  
-   2710 bool success;
-   2711 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2712 throw new Exception("No success status could be retrieved.");
-   2713  
-   2714 if (!success)
-   2715 throw new Exception("Could not retrieve estate list.");
-   2716  
-   2717 vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
-   2718 foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
-   2719 .Where(x => !string.IsNullOrEmpty(x))
-   2720 .Select((x, i) => new {Index = i, Value = x})
-   2721 .GroupBy(x => x.Index/2)
-   2722 .Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
-   2723 {
-   2724 vassalForm.Invoke(
-   2725 (MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
-   2726 }
-   2727 }
-   2728 catch (Exception ex)
-   2729 {
-   2730 vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusText.Text = ex.Message; }));
-   2731 }
-   2732 finally
-   2733 {
-   2734 Monitor.Exit(ClientInstanceTeleportLock);
-   2735 // Enable controls
-   2736 vassalForm.Invoke((MethodInvoker) (() =>
-   2737 {
-   2738 vassalForm.RegionTeleportGroup.Enabled = true;
-   2739  
-   2740 switch (selectedEstateListType)
-   2741 {
-   2742 case "ban":
-   2743 case "manager":
-   2744 case "user":
-   2745 EstateListsResidentsGroup.Enabled = true;
-   2746 EstateListsGroupsGroup.Enabled = false;
-   2747 break;
-   2748 case "group":
-   2749 EstateListsResidentsGroup.Enabled = false;
-   2750 EstateListsGroupsGroup.Enabled = true;
-   2751 break;
-   2752 }
-   2753 }));
-   2754 }
-   2755 })
-   2756 {IsBackground = true}.Start();
-   2757 }
-   2758  
-   2759 private void RequestRemoveEstateListMember(object sender, EventArgs e)
-   2760 {
-   2761 // Get the estate list type.
-   2762 string selectedEstateListType = string.Empty;
-   2763 bool queryEstateList = false;
-   2764 vassalForm.Invoke((MethodInvoker) (() =>
-   2765 {
-   2766 if (vassalForm.EstateListSelectBox.SelectedItem == null)
-   2767 {
-   2768 queryEstateList = false;
-   2769 return;
-   2770 }
-   2771 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   2772 switch (
-   2773 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   2774 {
-   2775 case true:
-   2776 queryEstateList = true;
-   2777 break;
-   2778 default:
-   2779 queryEstateList = false;
-   2780 break;
-   2781 }
-   2782 }));
-   2783  
-   2784 // If not estate list type is selected then return.
-   2785 if (!queryEstateList) return;
-   2786  
-   2787 // Enqueue all the regions to restart.
-   2788 Queue<UUID> estateListMembersQueue = new Queue<UUID>();
-   2789 vassalForm.Invoke((MethodInvoker) (() =>
-   2790 {
-   2791 foreach (
-   2792 DataGridViewRow estateListRow in
-   2793 EstateListGridView.Rows.AsParallel()
-   2794 .Cast<DataGridViewRow>()
-   2795 .Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
-   2796 {
-   2797 UUID estateListMemberUUID;
-   2798 if (!UUID.TryParse(estateListRow.Cells["EstateListUUID"].Value.ToString(),
-   2799 out estateListMemberUUID))
-   2800 continue;
-   2801 estateListMembersQueue.Enqueue(estateListMemberUUID);
-   2802 }
-   2803 }));
-   2804  
-   2805 // If no rows were selected, enable teleports, the return button and return.
-   2806 if (estateListMembersQueue.Count.Equals(0)) return;
-   2807  
-   2808 // Block teleports and disable button.
-   2809 vassalForm.Invoke((MethodInvoker) (() =>
-   2810 {
-   2811 RegionTeleportGroup.Enabled = false;
-   2812 RemoveEstateListMemberButton.Enabled = false;
-   2813 }));
-   2814  
-   2815 new Thread(() =>
-   2816 {
-   2817 try
-   2818 {
-   2819 Monitor.Enter(ClientInstanceTeleportLock);
-   2820 UUID memberUUID = UUID.Zero;
-   2821 do
-   2822 {
-   2823 try
-   2824 {
-   2825 memberUUID = estateListMembersQueue.Dequeue();
-   2826  
-   2827 // Remove the agent or group from the list.
-   2828 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2829 wasKeyValueEscape(new Dictionary<string, string>
-   2830 {
-   2831 {"command", "setestatelist"},
-   2832 {"group", vassalConfiguration.Group},
-   2833 {"password", vassalConfiguration.Password},
-   2834 {"type", selectedEstateListType},
-   2835 {"action", "remove"},
-   2836 {selectedEstateListType.Equals("group") ? "target" : "agent", memberUUID.ToString()}
-   2837 }), vassalConfiguration.DataTimeout);
-   2838  
-   2839 if (string.IsNullOrEmpty(result))
-   2840 throw new Exception("Error communicating with Corrade");
-   2841  
-   2842 bool success;
-   2843 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2844 throw new Exception("No success status could be retrieved");
-   2845  
-   2846 if (!success)
-   2847 throw new Exception("Unable to remove member");
-   2848  
-   2849 vassalForm.Invoke((MethodInvoker) (() =>
-   2850 {
-   2851 foreach (
-   2852 int i in
-   2853 EstateListGridView.Rows.AsParallel()
-   2854 .Cast<DataGridViewRow>()
-   2855 .Where(
-   2856 o =>
-   2857 o.Cells["EstateListUUID"].Value.ToString()
-   2858 .Equals(memberUUID.ToString(),
-   2859 StringComparison.OrdinalIgnoreCase)).Select(o => o.Index)
-   2860 )
-   2861 {
-   2862 EstateListGridView.Rows.RemoveAt(i);
-   2863 }
-   2864 }));
-   2865 }
-   2866 catch (Exception ex)
-   2867 {
-   2868 vassalForm.Invoke(
-   2869 (MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + memberUUID; }));
-   2870 }
-   2871 } while (!estateListMembersQueue.Count.Equals(0));
-   2872 }
-   2873 catch (Exception)
-   2874 {
-   2875 }
-   2876 finally
-   2877 {
-   2878 Monitor.Exit(ClientInstanceTeleportLock);
-   2879 // Enable teleports and enable button.
-   2880 vassalForm.Invoke((MethodInvoker) (() =>
-   2881 {
-   2882 RegionTeleportGroup.Enabled = true;
-   2883 RemoveEstateListMemberButton.Enabled = true;
-   2884 }));
-   2885 }
-   2886 })
-   2887 {IsBackground = true}.Start();
-   2888 }
-   2889  
-   2890 private void RequestEstateListsAddResident(object sender, EventArgs e)
-   2891 {
-   2892 // Get the estate list type.
-   2893 string selectedEstateListType = string.Empty;
-   2894 bool queryEstateList = false;
-   2895 vassalForm.Invoke((MethodInvoker) (() =>
-   2896 {
-   2897 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   2898 switch (
-   2899 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   2900 {
-   2901 case true:
-   2902 queryEstateList = true;
-   2903 break;
-   2904 default:
-   2905 queryEstateList = false;
-   2906 break;
-   2907 }
-   2908 }));
-   2909  
-   2910 // If not estate list type is selected then return.
-   2911 if (!queryEstateList) return;
-   2912  
-   2913 string firstName = string.Empty;
-   2914 string lastName = string.Empty;
-   2915  
-   2916 vassalForm.Invoke((MethodInvoker) (() =>
-   2917 {
-   2918 switch (string.IsNullOrEmpty(EstateListsResidentFirstName.Text))
-   2919 {
-   2920 case true:
-   2921 EstateListsResidentFirstName.BackColor = Color.MistyRose;
-   2922 return;
-   2923 default:
-   2924 EstateListsResidentFirstName.BackColor = Color.Empty;
-   2925 break;
-   2926 }
-   2927 firstName = EstateListsResidentFirstName.Text;
-   2928 switch (string.IsNullOrEmpty(EstateListsResidentLastName.Text))
-   2929 {
-   2930 case true:
-   2931 EstateListsResidentLastName.BackColor = Color.MistyRose;
-   2932 return;
-   2933 default:
-   2934 EstateListsResidentLastName.BackColor = Color.Empty;
-   2935 break;
-   2936 }
-   2937 lastName = EstateListsResidentLastName.Text;
-   2938 }));
-   2939  
-   2940 if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName)) return;
-   2941  
-   2942 // Block teleports and disable button.
-   2943 vassalForm.Invoke((MethodInvoker) (() =>
-   2944 {
-   2945 RegionTeleportGroup.Enabled = false;
-   2946 EstateListsResidentsGroup.Enabled = false;
-   2947 }));
-   2948  
-   2949 new Thread(() =>
-   2950 {
-   2951 try
-   2952 {
-   2953 Monitor.Enter(ClientInstanceTeleportLock);
-   2954  
-   2955 // Add the resident to the list.
-   2956 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2957 wasKeyValueEscape(new Dictionary<string, string>
-   2958 {
-   2959 {"command", "setestatelist"},
-   2960 {"group", vassalConfiguration.Group},
-   2961 {"password", vassalConfiguration.Password},
-   2962 {"type", selectedEstateListType},
-   2963 {"action", "add"},
-   2964 {"firstname", firstName},
-   2965 {"lastname", lastName}
-   2966 }), vassalConfiguration.DataTimeout);
-   2967  
-   2968 if (string.IsNullOrEmpty(result))
-   2969 throw new Exception("Error communicating with Corrade");
-   2970  
-   2971 bool success;
-   2972 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2973 throw new Exception("No success status could be retrieved");
-   2974  
-   2975 if (!success)
-   2976 throw new Exception("Unable to add resident");
-   2977  
-   2978 // Retrieve the estate list for updates.
-   2979 result = wasPOST(vassalConfiguration.HTTPServerURL,
-   2980 wasKeyValueEscape(new Dictionary<string, string>
-   2981 {
-   2982 {"command", "getestatelist"},
-   2983 {"group", vassalConfiguration.Group},
-   2984 {"password", vassalConfiguration.Password},
-   2985 {"type", selectedEstateListType}
-   2986 }), vassalConfiguration.DataTimeout);
-   2987  
-   2988 if (string.IsNullOrEmpty(result))
-   2989 throw new Exception("Error communicating with Corrade.");
-   2990  
-   2991 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   2992 throw new Exception("No success status could be retrieved.");
-   2993  
-   2994 if (!success)
-   2995 throw new Exception("Could not retrieve estate list.");
-   2996  
-   2997 vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
-   2998 foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
-   2999 .Where(x => !string.IsNullOrEmpty(x))
-   3000 .Select((x, i) => new {Index = i, Value = x})
-   3001 .GroupBy(x => x.Index/2)
-   3002 .Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
-   3003 {
-   3004 vassalForm.Invoke(
-   3005 (MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
-   3006 }
-   3007 }
-   3008 catch (Exception ex)
-   3009 {
-   3010 vassalForm.Invoke(
-   3011 (MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + firstName + @" " + lastName; }));
-   3012 }
-   3013 finally
-   3014 {
-   3015 Monitor.Exit(ClientInstanceTeleportLock);
-   3016 // Enable teleports and enable button.
-   3017 vassalForm.Invoke((MethodInvoker) (() =>
-   3018 {
-   3019 RegionTeleportGroup.Enabled = true;
-   3020 EstateListsResidentsGroup.Enabled = true;
-   3021 }));
-   3022 }
-   3023 })
-   3024 {IsBackground = true}.Start();
-   3025 }
-   3026  
-   3027 private void RequestEstateListsAddGroup(object sender, EventArgs e)
-   3028 {
-   3029 // Get the estate list type.
-   3030 string selectedEstateListType = string.Empty;
-   3031 bool queryEstateList = false;
-   3032 vassalForm.Invoke((MethodInvoker) (() =>
-   3033 {
-   3034 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   3035 switch (
-   3036 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   3037 {
-   3038 case true:
-   3039 queryEstateList = true;
-   3040 break;
-   3041 default:
-   3042 queryEstateList = false;
-   3043 break;
-   3044 }
-   3045 }));
-   3046  
-   3047 // If not estate list type is selected then return.
-   3048 if (!queryEstateList) return;
-   3049  
-   3050 string target = string.Empty;
-   3051  
-   3052 vassalForm.Invoke((MethodInvoker) (() =>
-   3053 {
-   3054 switch (string.IsNullOrEmpty(EstateListsAddGroupBox.Text))
-   3055 {
-   3056 case true:
-   3057 EstateListsAddGroupBox.BackColor = Color.MistyRose;
-   3058 return;
-   3059 default:
-   3060 EstateListsAddGroupBox.BackColor = Color.Empty;
-   3061 break;
-   3062 }
-   3063 target = EstateListsAddGroupBox.Text;
-   3064 }));
-   3065  
-   3066 if (string.IsNullOrEmpty(target)) return;
-   3067  
-   3068 // Block teleports and disable button.
-   3069 vassalForm.Invoke((MethodInvoker) (() =>
-   3070 {
-   3071 RegionTeleportGroup.Enabled = false;
-   3072 EstateListsGroupsGroup.Enabled = false;
-   3073 }));
-   3074  
-   3075 new Thread(() =>
-   3076 {
-   3077 try
-   3078 {
-   3079 Monitor.Enter(ClientInstanceTeleportLock);
-   3080  
-   3081 // Add the group to the list.
-   3082 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3083 wasKeyValueEscape(new Dictionary<string, string>
-   3084 {
-   3085 {"command", "setestatelist"},
-   3086 {"group", vassalConfiguration.Group},
-   3087 {"password", vassalConfiguration.Password},
-   3088 {"type", selectedEstateListType},
-   3089 {"action", "add"},
-   3090 {"target", target}
-   3091 }), vassalConfiguration.DataTimeout);
-   3092  
-   3093 if (string.IsNullOrEmpty(result))
-   3094 throw new Exception("Error communicating with Corrade");
-   3095  
-   3096 bool success;
-   3097 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3098 throw new Exception("No success status could be retrieved");
-   3099  
-   3100 if (!success)
-   3101 throw new Exception("Unable to add group");
-   3102  
-   3103 // Retrieve the estate list for updates.
-   3104 result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3105 wasKeyValueEscape(new Dictionary<string, string>
-   3106 {
-   3107 {"command", "getestatelist"},
-   3108 {"group", vassalConfiguration.Group},
-   3109 {"password", vassalConfiguration.Password},
-   3110 {"type", selectedEstateListType}
-   3111 }), vassalConfiguration.DataTimeout);
-   3112  
-   3113 if (string.IsNullOrEmpty(result))
-   3114 throw new Exception("Error communicating with Corrade.");
-   3115  
-   3116 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3117 throw new Exception("No success status could be retrieved.");
-   3118  
-   3119 if (!success)
-   3120 throw new Exception("Could not retrieve estate list.");
-   3121  
-   3122 vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
-   3123 foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
-   3124 .Where(x => !string.IsNullOrEmpty(x))
-   3125 .Select((x, i) => new {Index = i, Value = x})
-   3126 .GroupBy(x => x.Index/2)
-   3127 .Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
-   3128 {
-   3129 vassalForm.Invoke(
-   3130 (MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
-   3131 }
-   3132 }
-   3133 catch (Exception ex)
-   3134 {
-   3135 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target; }));
-   3136 }
-   3137 finally
-   3138 {
-   3139 Monitor.Exit(ClientInstanceTeleportLock);
-   3140 // Enable teleports and enable button.
-   3141 vassalForm.Invoke((MethodInvoker) (() =>
-   3142 {
-   3143 RegionTeleportGroup.Enabled = true;
-   3144 EstateListsGroupsGroup.Enabled = true;
-   3145 }));
-   3146 }
-   3147 })
-   3148 {IsBackground = true}.Start();
-   3149 }
-   3150  
-   3151 private void RequestRegionDebugApply(object sender, EventArgs e)
-   3152 {
-   3153 // Block teleports and disable button.
-   3154 vassalForm.Invoke((MethodInvoker) (() =>
-   3155 {
-   3156 RegionTeleportGroup.Enabled = false;
-   3157 ApplyRegionDebugButton.Enabled = false;
-   3158 }));
-   3159  
-   3160 new Thread(() =>
-   3161 {
-   3162 try
-   3163 {
-   3164 Monitor.Enter(ClientInstanceTeleportLock);
-   3165  
-   3166 bool scripts = false;
-   3167 bool collisons = false;
-   3168 bool physics = false;
-   3169 vassalForm.Invoke((MethodInvoker) (() =>
-   3170 {
-   3171 scripts = RegionDebugScriptsBox.Checked;
-   3172 collisons = RegionDebugCollisionsBox.Checked;
-   3173 physics = RegionDebugPhysicsBox.Checked;
-   3174 }));
-   3175  
-   3176 // Set the debug settings.
-   3177 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3178 wasKeyValueEscape(new Dictionary<string, string>
-   3179 {
-   3180 {"command", "setregiondebug"},
-   3181 {"group", vassalConfiguration.Group},
-   3182 {"password", vassalConfiguration.Password},
-   3183 {"scripts", scripts.ToString()},
-   3184 {"collisions", collisons.ToString()},
-   3185 {"physics", physics.ToString()}
-   3186 }), vassalConfiguration.DataTimeout);
-   3187  
-   3188 if (string.IsNullOrEmpty(result))
-   3189 throw new Exception("Error communicating with Corrade");
-   3190  
-   3191 bool success;
-   3192 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3193 throw new Exception("No success status could be retrieved");
-   3194  
-   3195 if (!success)
-   3196 throw new Exception("Unable to set region debug");
-   3197 }
-   3198 catch (Exception ex)
-   3199 {
-   3200 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3201 }
-   3202 finally
-   3203 {
-   3204 Monitor.Exit(ClientInstanceTeleportLock);
-   3205 }
-   3206  
-   3207 // Block teleports and disable button.
-   3208 vassalForm.Invoke((MethodInvoker) (() =>
-   3209 {
-   3210 RegionTeleportGroup.Enabled = true;
-   3211 ApplyRegionDebugButton.Enabled = true;
-   3212 }));
-   3213 })
-   3214 {IsBackground = true}.Start();
-   3215 }
-   3216  
-   3217 private void RequestApplyRegionInfo(object sender, EventArgs e)
-   3218 {
-   3219 // Block teleports and disable button.
-   3220 vassalForm.Invoke((MethodInvoker) (() =>
-   3221 {
-   3222 RegionTeleportGroup.Enabled = false;
-   3223 ApplyRegionInfoButton.Enabled = false;
-   3224 }));
-   3225  
-   3226 new Thread(() =>
-   3227 {
-   3228 try
-   3229 {
-   3230 Monitor.Enter(ClientInstanceTeleportLock);
-   3231  
-   3232 bool terraform = false;
-   3233 bool fly = false;
-   3234 bool damage = false;
-   3235 bool resell = false;
-   3236 bool push = false;
-   3237 bool parcel = false;
-   3238 bool mature = false;
-   3239 uint agentLimit = 20;
-   3240 double objectBonus = 2.0;
-   3241  
-   3242 bool run = false;
-   3243  
-   3244 vassalForm.Invoke((MethodInvoker) (() =>
-   3245 {
-   3246 terraform = RegionInfoTerraformBox.Checked;
-   3247 fly = RegionInfoFlyBox.Checked;
-   3248 damage = RegionInfoDamageBox.Checked;
-   3249 resell = RegioninfoResellBox.Checked;
-   3250 push = RegionInfoPushBox.Checked;
-   3251 parcel = RegionInfoParcelBox.Checked;
-   3252 mature = RegionInfoMatureBox.Checked;
-   3253 switch (!uint.TryParse(RegionInfoAgentLimitBox.Text, out agentLimit))
-   3254 {
-   3255 case true:
-   3256 RegionInfoAgentLimitBox.BackColor = Color.MistyRose;
-   3257 return;
-   3258 default:
-   3259 RegionInfoAgentLimitBox.BackColor = Color.Empty;
-   3260 run = true;
-   3261 break;
-   3262 }
-   3263 switch (!double.TryParse(RegionInfoObjectBonusBox.Text, out objectBonus))
-   3264 {
-   3265 case true:
-   3266 RegionInfoObjectBonusBox.BackColor = Color.MistyRose;
-   3267 return;
-   3268 default:
-   3269 RegionInfoAgentLimitBox.BackColor = Color.Empty;
-   3270 break;
-   3271 }
-   3272  
-   3273 run = true;
-   3274 }));
-   3275  
-   3276 if (!run) return;
-   3277  
-   3278 // Set the debug settings.
-   3279 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3280 wasKeyValueEscape(new Dictionary<string, string>
-   3281 {
-   3282 {"command", "setregioninfo"},
-   3283 {"group", vassalConfiguration.Group},
-   3284 {"password", vassalConfiguration.Password},
-   3285 {"terraform", terraform.ToString()},
-   3286 {"fly", fly.ToString()},
-   3287 {"damage", damage.ToString()},
-   3288 {"resell", resell.ToString()},
-   3289 {"push", push.ToString()},
-   3290 {"parcel", parcel.ToString()},
-   3291 {"mature", mature.ToString()},
-   3292 {"limit", agentLimit.ToString(Utils.EnUsCulture)},
-   3293 {"bonus", objectBonus.ToString(Utils.EnUsCulture)}
-   3294 }), vassalConfiguration.DataTimeout);
-   3295  
-   3296 if (string.IsNullOrEmpty(result))
-   3297 throw new Exception("Error communicating with Corrade");
-   3298  
-   3299 bool success;
-   3300 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3301 throw new Exception("No success status could be retrieved");
-   3302  
-   3303 if (!success)
-   3304 throw new Exception("Unable to set region info");
-   3305 }
-   3306 catch (Exception ex)
-   3307 {
-   3308 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3309 }
-   3310 finally
-   3311 {
-   3312 Monitor.Exit(ClientInstanceTeleportLock);
-   3313 }
-   3314  
-   3315 // Block teleports and disable button.
-   3316 vassalForm.Invoke((MethodInvoker) (() =>
-   3317 {
-   3318 RegionTeleportGroup.Enabled = true;
-   3319 ApplyRegionInfoButton.Enabled = true;
-   3320 }));
-   3321 })
-   3322 {IsBackground = true}.Start();
-   3323 }
-   3324  
-   3325 private void RequestEstateTexturesApply(object sender, EventArgs e)
-   3326 {
-   3327 List<UUID> groundTextureUUIDs = new List<UUID>();
-   3328 vassalForm.Invoke((MethodInvoker) (() =>
-   3329 {
-   3330 UUID textureUUID;
-   3331 switch (!UUID.TryParse(RegionTexturesLowUUIDApplyBox.Text, out textureUUID))
-   3332 {
-   3333 case true:
-   3334 RegionTexturesLowUUIDApplyBox.BackColor = Color.MistyRose;
-   3335 return;
-   3336 default:
-   3337 RegionTexturesLowUUIDApplyBox.BackColor = Color.Empty;
-   3338 break;
-   3339 }
-   3340 groundTextureUUIDs.Add(textureUUID);
-   3341  
-   3342 switch (!UUID.TryParse(RegionTexturesMiddleLowUUIDApplyBox.Text, out textureUUID))
-   3343 {
-   3344 case true:
-   3345 RegionTexturesMiddleLowUUIDApplyBox.BackColor = Color.MistyRose;
-   3346 return;
-   3347 default:
-   3348 RegionTexturesMiddleLowUUIDApplyBox.BackColor = Color.Empty;
-   3349 break;
-   3350 }
-   3351 groundTextureUUIDs.Add(textureUUID);
-   3352  
-   3353 switch (!UUID.TryParse(RegionTexturesMiddleHighUUIDApplyBox.Text, out textureUUID))
-   3354 {
-   3355 case true:
-   3356 RegionTexturesMiddleHighUUIDApplyBox.BackColor = Color.MistyRose;
-   3357 return;
-   3358 default:
-   3359 RegionTexturesMiddleHighUUIDApplyBox.BackColor = Color.Empty;
-   3360 break;
-   3361 }
-   3362 groundTextureUUIDs.Add(textureUUID);
-   3363  
-   3364 switch (!UUID.TryParse(RegionTexturesHighUUIDApplyBox.Text, out textureUUID))
-   3365 {
-   3366 case true:
-   3367 RegionTexturesHighUUIDApplyBox.BackColor = Color.MistyRose;
-   3368 return;
-   3369 default:
-   3370 RegionTexturesHighUUIDApplyBox.BackColor = Color.Empty;
-   3371 break;
-   3372 }
-   3373 groundTextureUUIDs.Add(textureUUID);
-   3374 }));
-   3375  
-   3376 if (!groundTextureUUIDs.Count.Equals(4)) return;
-   3377  
-   3378 // Block teleports and disable button.
-   3379 vassalForm.Invoke((MethodInvoker) (() =>
-   3380 {
-   3381 RegionTeleportGroup.Enabled = false;
-   3382 GroundTexturesGroup.Enabled = false;
-   3383 }));
-   3384  
-   3385 new Thread(() =>
-   3386 {
-   3387 try
-   3388 {
-   3389 Monitor.Enter(ClientInstanceTeleportLock);
-   3390  
-   3391 // Set the debug settings.
-   3392 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3393 wasKeyValueEscape(new Dictionary<string, string>
-   3394 {
-   3395 {"command", "setregionterraintextures"},
-   3396 {"group", vassalConfiguration.Group},
-   3397 {"password", vassalConfiguration.Password},
-   3398 {"data", wasEnumerableToCSV(groundTextureUUIDs.Select(o => o.ToString()))}
-   3399 }), vassalConfiguration.DataTimeout);
-   3400  
-   3401 if (string.IsNullOrEmpty(result))
-   3402 throw new Exception("Error communicating with Corrade");
-   3403  
-   3404 bool success;
-   3405 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3406 throw new Exception("No success status could be retrieved");
-   3407  
-   3408 if (!success)
-   3409 throw new Exception("Unable to apply estate ground textures");
-   3410 }
-   3411 catch (Exception ex)
-   3412 {
-   3413 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3414 }
-   3415 finally
-   3416 {
-   3417 Monitor.Exit(ClientInstanceTeleportLock);
-   3418 }
-   3419  
-   3420 // Block teleports and disable button.
-   3421 vassalForm.Invoke((MethodInvoker) (() =>
-   3422 {
-   3423 RegionTeleportGroup.Enabled = true;
-   3424 GroundTexturesGroup.Enabled = true;
-   3425 }));
-   3426 })
-   3427 {IsBackground = true};
-   3428 }
-   3429  
-   3430 private void RequestDownloadRegionTexture(object sender, EventArgs e)
-   3431 {
-   3432 string textureName = string.Empty;
-   3433 UUID textureUUID = UUID.Zero;
-   3434 bool run = false;
-   3435 vassalForm.Invoke((MethodInvoker) (() =>
-   3436 {
-   3437 Button button = sender as Button;
-   3438 if (button == null)
-   3439 {
-   3440 run = false;
-   3441 return;
-   3442 }
-   3443 textureName = button.Tag.ToString();
-   3444 switch (textureName)
-   3445 {
-   3446 case "Low":
-   3447 if (!UUID.TryParse(RegionTexturesLowUUIDBox.Text, out textureUUID))
-   3448 {
-   3449 run = false;
-   3450 return;
-   3451 }
-   3452 goto case "MiddleLow";
-   3453 case "MiddleLow":
-   3454 if (!UUID.TryParse(RegionTexturesMiddleLowUUIDBox.Text, out textureUUID))
-   3455 {
-   3456 run = false;
-   3457 return;
-   3458 }
-   3459 goto case "MiddleHigh";
-   3460 case "MiddleHigh":
-   3461 if (!UUID.TryParse(RegionTexturesMiddleHighUUIDBox.Text, out textureUUID))
-   3462 {
-   3463 run = false;
-   3464 return;
-   3465 }
-   3466 goto case "High";
-   3467 case "High":
-   3468 if (!UUID.TryParse(RegionTexturesHighUUIDBox.Text, out textureUUID))
-   3469 {
-   3470 run = false;
-   3471 return;
-   3472 }
-   3473 run = true;
-   3474 break;
-   3475 }
-   3476 }));
-   3477  
-   3478 if (!run) return;
-   3479  
-   3480 // Block teleports and disable button.
-   3481 vassalForm.Invoke((MethodInvoker) (() =>
-   3482 {
-   3483 RegionTeleportGroup.Enabled = false;
-   3484 GroundTexturesGroup.Enabled = false;
-   3485 }));
-   3486  
-   3487 new Thread(() =>
-   3488 {
-   3489 try
-   3490 {
-   3491 Monitor.Enter(ClientInstanceTeleportLock);
-   3492  
-   3493 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3494 wasKeyValueEscape(new Dictionary<string, string>
-   3495 {
-   3496 {"command", "download"},
-   3497 {"group", vassalConfiguration.Group},
-   3498 {"password", vassalConfiguration.Password},
-   3499 {"item", textureUUID.ToString()},
-   3500 {"type", "Texture"},
-   3501 {"format", "Png"}
-   3502 }), vassalConfiguration.DataTimeout);
-   3503  
-   3504 if (string.IsNullOrEmpty(result))
-   3505 throw new Exception("Error communicating with Corrade");
-   3506  
-   3507 bool success;
-   3508 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3509 throw new Exception("No success status could be retrieved");
-   3510  
-   3511 byte[] mapImageBytes = Convert.FromBase64String(wasInput(wasKeyValueGet("data", result)));
-   3512 Image mapImage;
-   3513 using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
-   3514 {
-   3515 mapImage = Image.FromStream(memoryStream);
-   3516 }
-   3517  
-   3518 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   3519 {
-   3520 switch (vassalForm.SavePNGFileDialog.ShowDialog())
-   3521 {
-   3522 case DialogResult.OK:
-   3523 string file = vassalForm.SavePNGFileDialog.FileName;
-   3524 new Thread(() =>
-   3525 {
-   3526 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   3527 {
-   3528 try
-   3529 {
-   3530 vassalForm.StatusText.Text = @"saving texture...";
-   3531 vassalForm.StatusProgress.Value = 0;
-   3532  
-   3533 mapImage.Save(file, ImageFormat.Png);
-   3534  
-   3535 vassalForm.StatusText.Text = @"texture saved";
-   3536 vassalForm.StatusProgress.Value = 100;
-   3537 }
-   3538 catch (Exception ex)
-   3539 {
-   3540 vassalForm.StatusText.Text = ex.Message;
-   3541 }
-   3542 finally
-   3543 {
-   3544 mapImage.Dispose();
-   3545 }
-   3546 }));
-   3547 })
-   3548 {IsBackground = true}.Start();
-   3549 break;
-   3550 }
-   3551 }));
-   3552 }
-   3553 catch (Exception ex)
-   3554 {
-   3555 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3556 }
-   3557 finally
-   3558 {
-   3559 Monitor.Exit(ClientInstanceTeleportLock);
-   3560 }
-   3561  
-   3562 // Block teleports and disable button.
-   3563 vassalForm.Invoke((MethodInvoker) (() =>
-   3564 {
-   3565 RegionTeleportGroup.Enabled = true;
-   3566 GroundTexturesGroup.Enabled = true;
-   3567 }));
-   3568 })
-   3569 {IsBackground = true}.Start();
-   3570 }
-   3571  
-   3572 private void RequestEstateListsAddGroupsFromCSV(object sender, EventArgs e)
-   3573 {
-   3574 // Get the estate list type.
-   3575 string selectedEstateListType = string.Empty;
-   3576 bool queryEstateList = false;
-   3577 vassalForm.Invoke((MethodInvoker) (() =>
-   3578 {
-   3579 if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
-   3580 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   3581 switch (
-   3582 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   3583 {
-   3584 case true:
-   3585 queryEstateList = true;
-   3586 break;
-   3587 default:
-   3588 queryEstateList = false;
-   3589 break;
-   3590 }
-   3591 }));
-   3592  
-   3593 // If not estate list type is selected then return.
-   3594 if (!queryEstateList) return;
-   3595  
-   3596 Queue<KeyValuePair<string, UUID>> targets = new Queue<KeyValuePair<string, UUID>>();
-   3597  
-   3598 vassalForm.Invoke((MethodInvoker) (() =>
-   3599 {
-   3600 switch (vassalForm.LoadCSVFile.ShowDialog())
-   3601 {
-   3602 case DialogResult.OK:
-   3603 string file = vassalForm.LoadCSVFile.FileName;
-   3604 try
-   3605 {
-   3606 vassalForm.StatusText.Text = @"loading group list...";
-   3607 vassalForm.StatusProgress.Value = 0;
-   3608  
-   3609 // import groups
-   3610 UUID targetUUID;
-   3611 foreach (KeyValuePair<string, UUID> target in
-   3612 File.ReadAllLines(file)
-   3613 .AsParallel()
-   3614 .Select(o => new List<string>(wasCSVToEnumerable(o)))
-   3615 .Where(o => o.Count == 2)
-   3616 .ToDictionary(o => o.First(),
-   3617 p =>
-   3618 UUID.TryParse(p.Last(), out targetUUID)
-   3619 ? targetUUID
-   3620 : UUID.Zero))
-   3621 {
-   3622 targets.Enqueue(target);
-   3623 }
-   3624  
-   3625 vassalForm.StatusText.Text = @"group list loaded";
-   3626 vassalForm.StatusProgress.Value = 100;
-   3627 }
-   3628 catch (Exception ex)
-   3629 {
-   3630 vassalForm.StatusText.Text = ex.Message;
-   3631 }
-   3632 break;
-   3633 }
-   3634 }));
-   3635  
-   3636 if (targets.Count.Equals(0)) return;
-   3637 int initialQueueSize = targets.Count;
-   3638  
-   3639 // Block teleports and disable button.
-   3640 vassalForm.Invoke((MethodInvoker) (() =>
-   3641 {
-   3642 RegionTeleportGroup.Enabled = false;
-   3643 EstateListsGroupsGroup.Enabled = false;
-   3644 }));
-   3645  
-   3646 new Thread(() =>
-   3647 {
-   3648 try
-   3649 {
-   3650 Monitor.Enter(ClientInstanceTeleportLock);
-   3651  
-   3652 do
-   3653 {
-   3654 KeyValuePair<string, UUID> target = targets.Dequeue();
-   3655  
-   3656 vassalForm.Invoke((MethodInvoker) (() =>
-   3657 {
-   3658 StatusText.Text = @"Adding to estate list: " + target.Key;
-   3659 vassalForm.StatusProgress.Value =
-   3660 Math.Min((int) (100d*Math.Abs(targets.Count - initialQueueSize)/initialQueueSize), 100);
-   3661 }));
-   3662  
-   3663 // Skip any items that already exist.
-   3664 bool run = false;
-   3665 vassalForm.Invoke((MethodInvoker) (() =>
-   3666 {
-   3667 run =
-   3668 !EstateListGridView.Rows.AsParallel()
-   3669 .Cast<DataGridViewRow>()
-   3670 .Any(o => o.Cells["EstateListUUID"].Value.ToString().Equals(target.Value.ToString()));
-   3671 }));
-   3672 if (!run) continue;
-   3673  
-   3674 // Skip broken UUIDs.
-   3675 if (target.Value.Equals(UUID.Zero)) continue;
-   3676  
-   3677 try
-   3678 {
-   3679 // Add the group to the list.
-   3680 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3681 wasKeyValueEscape(new Dictionary<string, string>
-   3682 {
-   3683 {"command", "setestatelist"},
-   3684 {"group", vassalConfiguration.Group},
-   3685 {"password", vassalConfiguration.Password},
-   3686 {"type", selectedEstateListType},
-   3687 {"action", "add"},
-   3688 {"target", target.Value.ToString()}
-   3689 }), vassalConfiguration.DataTimeout);
-   3690  
-   3691 if (string.IsNullOrEmpty(result))
-   3692 throw new Exception("Error communicating with Corrade");
-   3693  
-   3694 bool success;
-   3695 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3696 throw new Exception("No success status could be retrieved");
-   3697  
-   3698 if (!success)
-   3699 throw new Exception("Unable to add group");
-   3700 }
-   3701 catch (Exception ex)
-   3702 {
-   3703 vassalForm.Invoke(
-   3704 (MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target.Value; }));
-   3705 }
-   3706 } while (!targets.Count.Equals(0));
-   3707  
-   3708 // Retrieve the estate list.
-   3709 try
-   3710 {
-   3711 // Retrieve the estate list for updates.
-   3712 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3713 wasKeyValueEscape(new Dictionary<string, string>
-   3714 {
-   3715 {"command", "getestatelist"},
-   3716 {"group", vassalConfiguration.Group},
-   3717 {"password", vassalConfiguration.Password},
-   3718 {"type", selectedEstateListType}
-   3719 }), vassalConfiguration.DataTimeout);
-   3720  
-   3721 if (string.IsNullOrEmpty(result))
-   3722 throw new Exception("Error communicating with Corrade.");
-   3723  
-   3724 bool success;
-   3725 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3726 throw new Exception("No success status could be retrieved.");
-   3727  
-   3728 if (!success)
-   3729 throw new Exception("Could not retrieve estate list.");
-   3730  
-   3731 vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
-   3732 foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
-   3733 .Where(x => !string.IsNullOrEmpty(x))
-   3734 .Select((x, i) => new {Index = i, Value = x})
-   3735 .GroupBy(x => x.Index/2)
-   3736 .Select(x => x.Select(v => v.Value).ToList()))
-   3737 {
-   3738 vassalForm.BeginInvoke(
-   3739 (MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
-   3740 }
-   3741 }
-   3742 catch (Exception ex)
-   3743 {
-   3744 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3745 }
-   3746 }
-   3747 catch (Exception ex)
-   3748 {
-   3749 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3750 }
-   3751 finally
-   3752 {
-   3753 Monitor.Exit(ClientInstanceTeleportLock);
-   3754 // Enable teleports and enable button.
-   3755 vassalForm.Invoke((MethodInvoker) (() =>
-   3756 {
-   3757 RegionTeleportGroup.Enabled = true;
-   3758 EstateListsGroupsGroup.Enabled = true;
-   3759 }));
-   3760 }
-   3761 })
-   3762 {IsBackground = true}.Start();
-   3763 }
-   3764  
-   3765 private void RequestEstateListsAddResidentsFromCSV(object sender, EventArgs e)
-   3766 {
-   3767 // Get the estate list type.
-   3768 string selectedEstateListType = string.Empty;
-   3769 bool queryEstateList = false;
-   3770 vassalForm.Invoke((MethodInvoker) (() =>
-   3771 {
-   3772 if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
-   3773 selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
-   3774 switch (
-   3775 !string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
-   3776 {
-   3777 case true:
-   3778 queryEstateList = true;
-   3779 break;
-   3780 default:
-   3781 queryEstateList = false;
-   3782 break;
-   3783 }
-   3784 }));
-   3785  
-   3786 // If not estate list type is selected then return.
-   3787 if (!queryEstateList) return;
-   3788  
-   3789 Queue<KeyValuePair<string, UUID>> targets = new Queue<KeyValuePair<string, UUID>>();
-   3790  
-   3791 vassalForm.Invoke((MethodInvoker) (() =>
-   3792 {
-   3793 switch (vassalForm.LoadCSVFile.ShowDialog())
-   3794 {
-   3795 case DialogResult.OK:
-   3796 string file = vassalForm.LoadCSVFile.FileName;
-   3797 try
-   3798 {
-   3799 vassalForm.StatusText.Text = @"loading residents list...";
-   3800 vassalForm.StatusProgress.Value = 0;
-   3801  
-   3802 // import groups
-   3803 UUID targetUUID;
-   3804 foreach (KeyValuePair<string, UUID> target in
-   3805 File.ReadAllLines(file)
-   3806 .AsParallel()
-   3807 .Select(o => new List<string>(wasCSVToEnumerable(o)))
-   3808 .Where(o => o.Count == 2)
-   3809 .ToDictionary(o => o.First(),
-   3810 p =>
-   3811 UUID.TryParse(p.Last(), out targetUUID)
-   3812 ? targetUUID
-   3813 : UUID.Zero))
-   3814 {
-   3815 targets.Enqueue(target);
-   3816 }
-   3817  
-   3818 vassalForm.StatusText.Text = @"residents list loaded";
-   3819 vassalForm.StatusProgress.Value = 100;
-   3820 }
-   3821 catch (Exception ex)
-   3822 {
-   3823 vassalForm.StatusText.Text = ex.Message;
-   3824 }
-   3825 break;
-   3826 }
-   3827 }));
-   3828  
-   3829 if (targets.Count.Equals(0)) return;
-   3830 int initialQueueSize = targets.Count;
-   3831  
-   3832 // Block teleports and disable button.
-   3833 vassalForm.Invoke((MethodInvoker) (() =>
-   3834 {
-   3835 RegionTeleportGroup.Enabled = false;
-   3836 EstateListsResidentsGroup.Enabled = false;
-   3837 }));
-   3838  
-   3839 new Thread(() =>
-   3840 {
-   3841 try
-   3842 {
-   3843 Monitor.Enter(ClientInstanceTeleportLock);
-   3844  
-   3845 do
-   3846 {
-   3847 KeyValuePair<string, UUID> target = targets.Dequeue();
-   3848  
-   3849 vassalForm.Invoke((MethodInvoker) (() =>
-   3850 {
-   3851 StatusText.Text = @"Adding to estate list: " + target.Key;
-   3852 vassalForm.StatusProgress.Value =
-   3853 Math.Min((int) (100d*Math.Abs(targets.Count - initialQueueSize)/initialQueueSize), 100);
-   3854 }));
-   3855  
-   3856 // Skip any items that already exist.
-   3857 bool run = false;
-   3858 vassalForm.Invoke((MethodInvoker) (() =>
-   3859 {
-   3860 run =
-   3861 !EstateListGridView.Rows.AsParallel()
-   3862 .Cast<DataGridViewRow>()
-   3863 .Any(o => o.Cells["EstateListUUID"].Value.ToString().Equals(target.Value.ToString()));
-   3864 }));
-   3865 if (!run) continue;
-   3866  
-   3867 // Skip broken UUIDs.
-   3868 if (target.Value.Equals(UUID.Zero)) continue;
-   3869  
-   3870 try
-   3871 {
-   3872 // Add the group to the list.
-   3873 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3874 wasKeyValueEscape(new Dictionary<string, string>
-   3875 {
-   3876 {"command", "setestatelist"},
-   3877 {"group", vassalConfiguration.Group},
-   3878 {"password", vassalConfiguration.Password},
-   3879 {"type", selectedEstateListType},
-   3880 {"action", "add"},
-   3881 {"agent", target.Value.ToString()}
-   3882 }), vassalConfiguration.DataTimeout);
-   3883  
-   3884 if (string.IsNullOrEmpty(result))
-   3885 throw new Exception("Error communicating with Corrade");
-   3886  
-   3887 bool success;
-   3888 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3889 throw new Exception("No success status could be retrieved");
-   3890  
-   3891 if (!success)
-   3892 throw new Exception("Unable to add resident");
-   3893 }
-   3894 catch (Exception ex)
-   3895 {
-   3896 vassalForm.Invoke(
-   3897 (MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target.Value; }));
-   3898 }
-   3899 } while (!targets.Count.Equals(0));
-   3900  
-   3901 // Retrieve the estate list.
-   3902 try
-   3903 {
-   3904 // Retrieve the estate list for updates.
-   3905 string result = wasPOST(vassalConfiguration.HTTPServerURL,
-   3906 wasKeyValueEscape(new Dictionary<string, string>
-   3907 {
-   3908 {"command", "getestatelist"},
-   3909 {"group", vassalConfiguration.Group},
-   3910 {"password", vassalConfiguration.Password},
-   3911 {"type", selectedEstateListType}
-   3912 }), vassalConfiguration.DataTimeout);
-   3913  
-   3914 if (string.IsNullOrEmpty(result))
-   3915 throw new Exception("Error communicating with Corrade.");
-   3916  
-   3917 bool success;
-   3918 if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success))
-   3919 throw new Exception("No success status could be retrieved.");
-   3920  
-   3921 if (!success)
-   3922 throw new Exception("Could not retrieve estate list.");
-   3923  
-   3924 vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
-   3925 foreach (List<string> data in wasCSVToEnumerable(wasInput(wasKeyValueGet("data", result)))
-   3926 .Where(x => !string.IsNullOrEmpty(x))
-   3927 .Select((x, i) => new {Index = i, Value = x})
-   3928 .GroupBy(x => x.Index/2)
-   3929 .Select(x => x.Select(v => v.Value).ToList()))
-   3930 {
-   3931 vassalForm.BeginInvoke(
-   3932 (MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
-   3933 }
-   3934 }
-   3935 catch (Exception ex)
-   3936 {
-   3937 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3938 }
-   3939 }
-   3940 catch (Exception ex)
-   3941 {
-   3942 vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
-   3943 }
-   3944 finally
-   3945 {
-   3946 Monitor.Exit(ClientInstanceTeleportLock);
-   3947 // Enable teleports and enable button.
-   3948 vassalForm.Invoke((MethodInvoker) (() =>
-   3949 {
-   3950 RegionTeleportGroup.Enabled = true;
-   3951 EstateListsResidentsGroup.Enabled = true;
-   3952 }));
-   3953 }
-   3954 })
-   3955 {IsBackground = true}.Start();
-   3956 }
-   3957  
-   3958 private void RequestExportEstateList(object sender, EventArgs e)
-   3959 {
-   3960 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   3961 {
-   3962 switch (vassalForm.ExportCSVDialog.ShowDialog())
-   3963 {
-   3964 case DialogResult.OK:
-   3965 string file = vassalForm.ExportCSVDialog.FileName;
-   3966 new Thread(() =>
-   3967 {
-   3968 vassalForm.BeginInvoke((MethodInvoker) (() =>
-   3969 {
-   3970 try
-   3971 {
-   3972 vassalForm.StatusText.Text = @"exporting...";
-   3973 vassalForm.StatusProgress.Value = 0;
-   3974  
-   3975 using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
-   3976 {
-   3977 foreach (DataGridViewRow estateListRow in EstateListGridView.Rows)
-   3978 {
-   3979 streamWriter.WriteLine(wasEnumerableToCSV(new[]
-   3980 {
-   3981 estateListRow.Cells["EstateListName"].Value.ToString(),
-   3982 estateListRow.Cells["EstateListUUID"].Value.ToString()
-   3983 }));
-   3984 }
-   3985 }
-   3986  
-   3987 vassalForm.StatusText.Text = @"exported";
-   3988 vassalForm.StatusProgress.Value = 100;
-   3989 }
-   3990 catch (Exception ex)
-   3991 {
-   3992 vassalForm.StatusText.Text = ex.Message;
-   3993 }
-   3994 }));
-   3995 })
-   3996 {IsBackground = true}.Start();
-   3997 break;
-   3998 }
-   3999 }));
-   4000 }
-   4001  
-   4002 /// <summary>
-   4003 /// Linden constants.
-   4004 /// </summary>
-   4005 public struct LINDEN_CONSTANTS
-   4006 {
-   4007 public struct ALERTS
-   4008 {
-   4009 public const string NO_ROOM_TO_SIT_HERE = @"No room to sit here, try another spot.";
-   4010  
-   4011 public const string UNABLE_TO_SET_HOME =
-   4012 @"You can only set your 'Home Location' on your land or at a mainland Infohub.";
-   4013  
-   4014 public const string HOME_SET = @"Home position set.";
-   4015 }
-   4016  
-   4017 public struct ASSETS
-   4018 {
-   4019 public struct NOTECARD
-   4020 {
-   4021 public const string NEWLINE = "\n";
-   4022 public const uint MAXIMUM_BODY_LENTH = 65536;
-   4023 }
-   4024 }
-   4025  
-   4026 public struct AVATARS
-   4027 {
-   4028 public const uint SET_DISPLAY_NAME_SUCCESS = 200;
-   4029 public const string LASTNAME_PLACEHOLDER = @"Resident";
-   4030 public const uint MAXIMUM_DISPLAY_NAME_CHARACTERS = 31;
-   4031 public const uint MINIMUM_DISPLAY_NAME_CHARACTERS = 1;
-   4032 public const uint MAXIMUM_NUMBER_OF_ATTACHMENTS = 38;
-   4033  
-   4034 public struct PROFILE
-   4035 {
-   4036 public const uint SECOND_LIFE_TEXT_SIZE = 510;
-   4037 public const uint FIRST_LIFE_TEXT_SIZE = 253;
-   4038 }
-   4039  
-   4040 public struct PICKS
-   4041 {
-   4042 public const uint MAXIMUM_PICKS = 10;
-   4043 public const uint MAXIMUM_PICK_DESCRIPTION_SIZE = 1022;
-   4044 }
-   4045  
-   4046 public struct CLASSIFIEDS
-   4047 {
-   4048 public const uint MAXIMUM_CLASSIFIEDS = 100;
-   4049 }
-   4050 }
-   4051  
-   4052 public struct PRIMITIVES
-   4053 {
-   4054 public const uint MAXIMUM_NAME_SIZE = 63;
-   4055 public const uint MAXIMUM_DESCRIPTION_SIZE = 127;
-   4056 public const double MAXIMUM_REZ_HEIGHT = 4096.0;
-   4057 public const double MINIMUM_SIZE_X = 0.01;
-   4058 public const double MINIMUM_SIZE_Y = 0.01;
-   4059 public const double MINIMUM_SIZE_Z = 0.01;
-   4060 public const double MAXIMUM_SIZE_X = 64.0;
-   4061 public const double MAXIMUM_SIZE_Y = 64.0;
-   4062 public const double MAXIMUM_SIZE_Z = 64.0;
-   4063 }
-   4064  
-   4065 public struct OBJECTS
-   4066 {
-   4067 public const uint MAXIMUM_PRIMITIVE_COUNT = 256;
-   4068 }
-   4069  
-   4070 public struct DIRECTORY
-   4071 {
-   4072 public struct EVENT
-   4073 {
-   4074 public const uint SEARCH_RESULTS_COUNT = 200;
-   4075 }
-   4076  
-   4077 public struct GROUP
-   4078 {
-   4079 public const uint SEARCH_RESULTS_COUNT = 100;
-   4080 }
-   4081  
-   4082 public struct LAND
-   4083 {
-   4084 public const uint SEARCH_RESULTS_COUNT = 100;
-   4085 }
-   4086  
-   4087 public struct PEOPLE
-   4088 {
-   4089 public const uint SEARCH_RESULTS_COUNT = 100;
-   4090 }
-   4091 }
-   4092  
-   4093 public struct ESTATE
-   4094 {
-   4095 public const uint REGION_RESTART_DELAY = 120;
-   4096 public const uint MAXIMUM_BAN_LIST_LENGTH = 500;
-   4097 public const uint MAXIMUM_GROUP_LIST_LENGTH = 63;
-   4098 public const uint MAXIMUM_USER_LIST_LENGTH = 500;
-   4099 public const uint MAXIMUM_MANAGER_LIST_LENGTH = 10;
-   4100  
-   4101 public struct MESSAGES
-   4102 {
-   4103 public const string REGION_RESTART_MESSAGE = @"restart";
-   4104 }
-   4105 }
-   4106  
-   4107 public struct PARCELS
-   4108 {
-   4109 public const double MAXIMUM_AUTO_RETURN_TIME = 999999;
-   4110 public const uint MINIMUM_AUTO_RETURN_TIME = 0;
-   4111 public const uint MAXIMUM_NAME_LENGTH = 63;
-   4112 public const uint MAXIMUM_DESCRIPTION_LENGTH = 255;
-   4113 }
-   4114  
-   4115 public struct GRID
-   4116 {
-   4117 public const string SECOND_LIFE = @"Second Life";
-   4118 public const string TIME_ZONE = @"Pacific Standard Time";
-   4119 }
-   4120  
-   4121 public struct CHAT
-   4122 {
-   4123 public const uint MAXIMUM_MESSAGE_LENGTH = 1024;
-   4124 }
-   4125  
-   4126 public struct GROUPS
-   4127 {
-   4128 public const uint MAXIMUM_NUMBER_OF_ROLES = 10;
-   4129 public const string EVERYONE_ROLE_NAME = @"Everyone";
-   4130 public const uint MAXIMUM_GROUP_NAME_LENGTH = 35;
-   4131 public const uint MAXIMUM_GROUP_TITLE_LENGTH = 20;
-   4132 }
-   4133  
-   4134 public struct NOTICES
-   4135 {
-   4136 public const uint MAXIMUM_NOTICE_MESSAGE_LENGTH = 512;
-   4137 }
-   4138  
-   4139 public struct LSL
-   4140 {
-   4141 public const string CSV_DELIMITER = @", ";
-   4142 public const float SENSOR_RANGE = 96;
-   4143 public const string DATE_TIME_STAMP = @"yyy-MM-ddTHH:mm:ss.ffffffZ";
-   4144 }
-   4145  
-   4146 public struct REGION
-   4147 {
-   4148 public const float TELEPORT_MINIMUM_DISTANCE = 1;
-   4149 public const float DEFAULT_AGENT_LIMIT = 40;
-   4150 public const float DEFAULT_OBJECT_BONUS = 1;
-   4151 public const bool DEFAULT_FIXED_SUN = false;
-   4152 public const float DEFAULT_TERRAIN_LOWER_LIMIT = -4;
-   4153 public const float DEFAULT_TERRAIN_RAISE_LIMIT = 4;
-   4154 public const bool DEFAULT_USE_ESTATE_SUN = true;
-   4155 public const float DEFAULT_WATER_HEIGHT = 20;
-   4156 public const float SUNRISE = 6;
-   4157 }
-   4158  
-   4159 public struct VIEWER
-   4160 {
-   4161 public const float MAXIMUM_DRAW_DISTANCE = 4096;
-   4162 }
-   4163  
-   4164 public struct TELEPORTS
-   4165 {
-   4166 public struct THROTTLE
-   4167 {
-   4168 public const uint MAX_TELEPORTS = 10;
-   4169 public const uint GRACE_SECONDS = 15;
-   4170 }
-   4171 }
-   4172 }
-   4173  
-   4174 /// <summary>
-   4175 /// Constants used by Corrade.
-   4176 /// </summary>
-   4177 public struct VASSAL_CONSTANTS
-   4178 {
-   4179 /// <summary>
-   4180 /// Copyright.
-   4181 /// </summary>
-   4182 public const string COPYRIGHT = @"(c) Copyright 2013 Wizardry and Steamworks";
-   4183  
-   4184 public const string WIZARDRY_AND_STEAMWORKS = @"Wizardry and Steamworks";
-   4185 public const string VASSAL = @"Vassal";
-   4186 public const string WIZARDRY_AND_STEAMWORKS_WEBSITE = @"http://grimore.org";
-   4187  
-   4188 /// <summary>
-   4189 /// Vassal version.
-   4190 /// </summary>
-   4191 public static readonly string VASSAL_VERSION = Assembly.GetEntryAssembly().GetName().Version.ToString();
-   4192  
-   4193 /// <summary>
-   4194 /// Corrade user agent.
-   4195 /// </summary>
-   4196 public static readonly string USER_AGENT =
-   4197 $"{VASSAL}/{VASSAL_VERSION} ({WIZARDRY_AND_STEAMWORKS_WEBSITE})";
-   4198  
-   4199 /// <summary>
-   4200 /// Vassal compile date.
-   4201 /// </summary>
-   4202 public static readonly string VASSAL_COMPILE_DATE = new DateTime(2000, 1, 1).Add(new TimeSpan(
-   4203 TimeSpan.TicksPerDay*Assembly.GetEntryAssembly().GetName().Version.Build + // days since 1 January 2000
-   4204 TimeSpan.TicksPerSecond*2*Assembly.GetEntryAssembly().GetName().Version.Revision)).ToLongDateString();
-   4205  
-   4206 /// <summary>
-   4207 /// Vassal configuration file.
-   4208 /// </summary>
-   4209 public static readonly string VASSAL_CONFIGURATION_FILE = @"Vassal.ini";
-   4210  
-   4211 /// <summary>
-   4212 /// Vassal regions file.
-   4213 /// </summary>
-   4214 public static readonly string VASSAL_REGIONS = @"Regions.csv";
-   4215  
-   4216 /// <summary>
-   4217 /// Conten-types that Corrade can send and receive.
-   4218 /// </summary>
-   4219 public struct CONTENT_TYPE
-   4220 {
-   4221 public const string TEXT_PLAIN = @"text/plain";
-   4222 public const string WWW_FORM_URLENCODED = @"application/x-www-form-urlencoded";
-   4223 }
-   4224 }
-   4225  
-   4226 #region CRYPTOGRAPHY
-   4227  
-   4228 ///////////////////////////////////////////////////////////////////////////
-   4229 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4230 ///////////////////////////////////////////////////////////////////////////
-   4231 /// <summary>
-   4232 /// Gets a sub-array from an array.
-   4233 /// </summary>
-   4234 /// <typeparam name="T">the array type</typeparam>
-   4235 /// <param name="data">the array</param>
-   4236 /// <param name="start">the start index</param>
-   4237 /// <param name="stop">the stop index (-1 denotes the end)</param>
-   4238 /// <returns>the array slice between start and stop</returns>
-   4239 public static T[] wasGetSubArray<T>(T[] data, int start, int stop)
-   4240 {
-   4241 if (stop.Equals(-1))
-   4242 stop = data.Length - 1;
-   4243 T[] result = new T[stop - start + 1];
-   4244 Array.Copy(data, start, result, 0, stop - start + 1);
-   4245 return result;
-   4246 }
-   4247  
-   4248 ///////////////////////////////////////////////////////////////////////////
-   4249 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4250 ///////////////////////////////////////////////////////////////////////////
-   4251 /// <summary>
-   4252 /// Delete a sub-array and return the result.
-   4253 /// </summary>
-   4254 /// <typeparam name="T">the array type</typeparam>
-   4255 /// <param name="data">the array</param>
-   4256 /// <param name="start">the start index</param>
-   4257 /// <param name="stop">the stop index (-1 denotes the end)</param>
-   4258 /// <returns>the array without elements between start and stop</returns>
-   4259 public static T[] wasDeleteSubArray<T>(T[] data, int start, int stop)
-   4260 {
-   4261 if (stop.Equals(-1))
-   4262 stop = data.Length - 1;
-   4263 T[] result = new T[data.Length - (stop - start) - 1];
-   4264 Array.Copy(data, 0, result, 0, start);
-   4265 Array.Copy(data, stop + 1, result, start, data.Length - stop - 1);
-   4266 return result;
-   4267 }
-   4268  
-   4269 ///////////////////////////////////////////////////////////////////////////
-   4270 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4271 ///////////////////////////////////////////////////////////////////////////
-   4272 /// <summary>
-   4273 /// Concatenate multiple arrays.
-   4274 /// </summary>
-   4275 /// <typeparam name="T">the array type</typeparam>
-   4276 /// <param name="arrays">multiple arrays</param>
-   4277 /// <returns>a flat array with all arrays concatenated</returns>
-   4278 public static T[] wasConcatenateArrays<T>(params T[][] arrays)
-   4279 {
-   4280 int resultLength = 0;
-   4281 foreach (T[] o in arrays)
-   4282 {
-   4283 resultLength += o.Length;
-   4284 }
-   4285 T[] result = new T[resultLength];
-   4286 int offset = 0;
-   4287 for (int x = 0; x < arrays.Length; x++)
-   4288 {
-   4289 arrays[x].CopyTo(result, offset);
-   4290 offset += arrays[x].Length;
-   4291 }
-   4292 return result;
-   4293 }
-   4294  
-   4295 ///////////////////////////////////////////////////////////////////////////
-   4296 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4297 ///////////////////////////////////////////////////////////////////////////
-   4298 /// <summary>
-   4299 /// Permutes an array in reverse a given number of times.
-   4300 /// </summary>
-   4301 /// <typeparam name="T">the array type</typeparam>
-   4302 /// <param name="input">the array</param>
-   4303 /// <param name="times">the number of times to permute</param>
-   4304 /// <returns>the array with the elements permuted</returns>
-   4305 private static T[] wasReversePermuteArrayElements<T>(T[] input, int times)
-   4306 {
-   4307 if (times.Equals(0)) return input;
-   4308 T[] slice = new T[input.Length];
-   4309 Array.Copy(input, 1, slice, 0, input.Length - 1);
-   4310 Array.Copy(input, 0, slice, input.Length - 1, 1);
-   4311 return wasReversePermuteArrayElements(slice, --times);
-   4312 }
-   4313  
-   4314 ///////////////////////////////////////////////////////////////////////////
-   4315 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4316 ///////////////////////////////////////////////////////////////////////////
-   4317 /// <summary>
-   4318 /// Permutes an array forward a given number of times.
-   4319 /// </summary>
-   4320 /// <typeparam name="T">the array type</typeparam>
-   4321 /// <param name="input">the array</param>
-   4322 /// <param name="times">the number of times to permute</param>
-   4323 /// <returns>the array with the elements permuted</returns>
-   4324 private static T[] wasForwardPermuteArrayElements<T>(T[] input, int times)
-   4325 {
-   4326 if (times.Equals(0)) return input;
-   4327 T[] slice = new T[input.Length];
-   4328 Array.Copy(input, input.Length - 1, slice, 0, 1);
-   4329 Array.Copy(input, 0, slice, 1, input.Length - 1);
-   4330 return wasForwardPermuteArrayElements(slice, --times);
-   4331 }
-   4332  
-   4333 ///////////////////////////////////////////////////////////////////////////
-   4334 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4335 ///////////////////////////////////////////////////////////////////////////
-   4336 /// <summary>
-   4337 /// Encrypt or decrypt a message given a set of rotors, plugs and a reflector.
-   4338 /// </summary>
-   4339 /// <param name="message">the message to encyrpt or decrypt</param>
-   4340 /// <param name="rotors">any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g</param>
-   4341 /// <param name="plugs">the letter representing the start character for the rotor</param>
-   4342 /// <param name="reflector">any one of: B, b, C, c</param>
-   4343 /// <returns>either a decrypted or encrypted string</returns>
-   4344 private static string wasEnigma(string message, char[] rotors, char[] plugs, char reflector)
-   4345 {
-   4346 Dictionary<char, char[]> def_rotors = new Dictionary<char, char[]>
-   4347 {
-   4348 {
-   4349 '1', new[]
-   4350 {
-   4351 'e', 'k', 'm', 'f', 'l',
-   4352 'g', 'd', 'q', 'v', 'z',
-   4353 'n', 't', 'o', 'w', 'y',
-   4354 'h', 'x', 'u', 's', 'p',
-   4355 'a', 'i', 'b', 'r', 'c',
-   4356 'j'
-   4357 }
-   4358 },
-   4359 {
-   4360 '2', new[]
-   4361 {
-   4362 'a', 'j', 'd', 'k', 's',
-   4363 'i', 'r', 'u', 'x', 'b',
-   4364 'l', 'h', 'w', 't', 'm',
-   4365 'c', 'q', 'g', 'z', 'n',
-   4366 'p', 'y', 'f', 'v', 'o',
-   4367 'e'
-   4368 }
-   4369 },
-   4370 {
-   4371 '3', new[]
-   4372 {
-   4373 'b', 'd', 'f', 'h', 'j',
-   4374 'l', 'c', 'p', 'r', 't',
-   4375 'x', 'v', 'z', 'n', 'y',
-   4376 'e', 'i', 'w', 'g', 'a',
-   4377 'k', 'm', 'u', 's', 'q',
-   4378 'o'
-   4379 }
-   4380 },
-   4381 {
-   4382 '4', new[]
-   4383 {
-   4384 'e', 's', 'o', 'v', 'p',
-   4385 'z', 'j', 'a', 'y', 'q',
-   4386 'u', 'i', 'r', 'h', 'x',
-   4387 'l', 'n', 'f', 't', 'g',
-   4388 'k', 'd', 'c', 'm', 'w',
-   4389 'b'
-   4390 }
-   4391 },
-   4392 {
-   4393 '5', new[]
-   4394 {
-   4395 'v', 'z', 'b', 'r', 'g',
-   4396 'i', 't', 'y', 'u', 'p',
-   4397 's', 'd', 'n', 'h', 'l',
-   4398 'x', 'a', 'w', 'm', 'j',
-   4399 'q', 'o', 'f', 'e', 'c',
-   4400 'k'
-   4401 }
-   4402 },
-   4403 {
-   4404 '6', new[]
-   4405 {
-   4406 'j', 'p', 'g', 'v', 'o',
-   4407 'u', 'm', 'f', 'y', 'q',
-   4408 'b', 'e', 'n', 'h', 'z',
-   4409 'r', 'd', 'k', 'a', 's',
-   4410 'x', 'l', 'i', 'c', 't',
-   4411 'w'
-   4412 }
-   4413 },
-   4414 {
-   4415 '7', new[]
-   4416 {
-   4417 'n', 'z', 'j', 'h', 'g',
-   4418 'r', 'c', 'x', 'm', 'y',
-   4419 's', 'w', 'b', 'o', 'u',
-   4420 'f', 'a', 'i', 'v', 'l',
-   4421 'p', 'e', 'k', 'q', 'd',
-   4422 't'
-   4423 }
-   4424 },
-   4425 {
-   4426 '8', new[]
-   4427 {
-   4428 'f', 'k', 'q', 'h', 't',
-   4429 'l', 'x', 'o', 'c', 'b',
-   4430 'j', 's', 'p', 'd', 'z',
-   4431 'r', 'a', 'm', 'e', 'w',
-   4432 'n', 'i', 'u', 'y', 'g',
-   4433 'v'
-   4434 }
-   4435 },
-   4436 {
-   4437 'b', new[]
-   4438 {
-   4439 'l', 'e', 'y', 'j', 'v',
-   4440 'c', 'n', 'i', 'x', 'w',
-   4441 'p', 'b', 'q', 'm', 'd',
-   4442 'r', 't', 'a', 'k', 'z',
-   4443 'g', 'f', 'u', 'h', 'o',
-   4444 's'
-   4445 }
-   4446 },
-   4447 {
-   4448 'g', new[]
-   4449 {
-   4450 'f', 's', 'o', 'k', 'a',
-   4451 'n', 'u', 'e', 'r', 'h',
-   4452 'm', 'b', 't', 'i', 'y',
-   4453 'c', 'w', 'l', 'q', 'p',
-   4454 'z', 'x', 'v', 'g', 'j',
-   4455 'd'
-   4456 }
-   4457 }
-   4458 };
-   4459  
-   4460 Dictionary<char, char[]> def_reflectors = new Dictionary<char, char[]>
-   4461 {
-   4462 {
-   4463 'B', new[]
-   4464 {
-   4465 'a', 'y', 'b', 'r', 'c', 'u', 'd', 'h',
-   4466 'e', 'q', 'f', 's', 'g', 'l', 'i', 'p',
-   4467 'j', 'x', 'k', 'n', 'm', 'o', 't', 'z',
-   4468 'v', 'w'
-   4469 }
-   4470 },
-   4471 {
-   4472 'b', new[]
-   4473 {
-   4474 'a', 'e', 'b', 'n', 'c', 'k', 'd', 'q',
-   4475 'f', 'u', 'g', 'y', 'h', 'w', 'i', 'j',
-   4476 'l', 'o', 'm', 'p', 'r', 'x', 's', 'z',
-   4477 't', 'v'
-   4478 }
-   4479 },
-   4480 {
-   4481 'C', new[]
-   4482 {
-   4483 'a', 'f', 'b', 'v', 'c', 'p', 'd', 'j',
-   4484 'e', 'i', 'g', 'o', 'h', 'y', 'k', 'r',
-   4485 'l', 'z', 'm', 'x', 'n', 'w', 't', 'q',
-   4486 's', 'u'
-   4487 }
-   4488 },
-   4489 {
-   4490 'c', new[]
-   4491 {
-   4492 'a', 'r', 'b', 'd', 'c', 'o', 'e', 'j',
-   4493 'f', 'n', 'g', 't', 'h', 'k', 'i', 'v',
-   4494 'l', 'm', 'p', 'w', 'q', 'z', 's', 'x',
-   4495 'u', 'y'
-   4496 }
-   4497 }
-   4498 };
-   4499  
-   4500 // Setup rotors from plugs.
-   4501 foreach (char rotor in rotors)
-   4502 {
-   4503 char plug = plugs[Array.IndexOf(rotors, rotor)];
-   4504 int i = Array.IndexOf(def_rotors[rotor], plug);
-   4505 if (i.Equals(0)) continue;
-   4506 def_rotors[rotor] = wasConcatenateArrays(new[] {plug},
-   4507 wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i, i), i, -1),
-   4508 wasGetSubArray(wasDeleteSubArray(def_rotors[rotor], i + 1, -1), 0, i - 1));
-   4509 }
-   4510  
-   4511 StringBuilder result = new StringBuilder();
-   4512 foreach (char c in message)
-   4513 {
-   4514 if (!char.IsLetter(c))
-   4515 {
-   4516 result.Append(c);
-   4517 continue;
-   4518 }
-   4519  
-   4520 // Normalize to lower.
-   4521 char l = char.ToLower(c);
-   4522  
-   4523 Action<char[]> rotate = o =>
-   4524 {
-   4525 int i = o.Length - 1;
-   4526 do
-   4527 {
-   4528 def_rotors[o[0]] = wasForwardPermuteArrayElements(def_rotors[o[0]], 1);
-   4529 if (i.Equals(0))
-   4530 {
-   4531 rotors = wasReversePermuteArrayElements(o, 1);
-   4532 continue;
-   4533 }
-   4534 l = wasGetElementAt(def_rotors[o[1]], Array.IndexOf(def_rotors[o[0]], l) - 1);
-   4535 o = wasReversePermuteArrayElements(o, 1);
-   4536 } while (--i > -1);
-   4537 };
-   4538  
-   4539 // Forward pass through the Enigma's rotors.
-   4540 rotate.Invoke(rotors);
-   4541  
-   4542 // Reflect
-   4543 int x = Array.IndexOf(def_reflectors[reflector], l);
-   4544 l = (x + 1)%2 == 0 ? def_reflectors[reflector][x - 1] : def_reflectors[reflector][x + 1];
-   4545  
-   4546 // Reverse the order of the rotors.
-   4547 Array.Reverse(rotors);
-   4548  
-   4549 // Reverse pass through the Enigma's rotors.
-   4550 rotate.Invoke(rotors);
-   4551  
-   4552 if (char.IsUpper(c))
-   4553 {
-   4554 l = char.ToUpper(l);
-   4555 }
-   4556 result.Append(l);
-   4557 }
-   4558  
-   4559 return result.ToString();
-   4560 }
-   4561  
-   4562 ///////////////////////////////////////////////////////////////////////////
-   4563 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4564 ///////////////////////////////////////////////////////////////////////////
-   4565 /// <summary>
-   4566 /// Expand the VIGENRE key to the length of the input.
-   4567 /// </summary>
-   4568 /// <param name="input">the input to expand to</param>
-   4569 /// <param name="enc_key">the key to expand</param>
-   4570 /// <returns>the expanded key</returns>
-   4571 private static string wasVigenereExpandKey(string input, string enc_key)
-   4572 {
-   4573 string exp_key = string.Empty;
-   4574 int i = 0, j = 0;
-   4575 do
-   4576 {
-   4577 char p = input[i];
-   4578 if (!char.IsLetter(p))
-   4579 {
-   4580 exp_key += p;
-   4581 ++i;
-   4582 continue;
-   4583 }
-   4584 int m = j%enc_key.Length;
-   4585 exp_key += enc_key[m];
-   4586 ++j;
-   4587 ++i;
-   4588 } while (i < input.Length);
-   4589 return exp_key;
-   4590 }
-   4591  
-   4592 ///////////////////////////////////////////////////////////////////////////
-   4593 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4594 ///////////////////////////////////////////////////////////////////////////
-   4595 /// <summary>
-   4596 /// Encrypt using VIGENERE.
-   4597 /// </summary>
-   4598 /// <param name="input">the input to encrypt</param>
-   4599 /// <param name="enc_key">the key to encrypt with</param>
-   4600 /// <returns>the encrypted input</returns>
-   4601 private static string wasEncryptVIGENERE(string input, string enc_key)
-   4602 {
-   4603 char[] a =
-   4604 {
-   4605 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-   4606 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
-   4607 };
-   4608  
-   4609 enc_key = wasVigenereExpandKey(input, enc_key);
-   4610 string result = string.Empty;
-   4611 int i = 0;
-   4612 do
-   4613 {
-   4614 char p = input[i];
-   4615 if (!char.IsLetter(p))
-   4616 {
-   4617 result += p;
-   4618 ++i;
-   4619 continue;
-   4620 }
-   4621 char q =
-   4622 wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i]))[
-   4623 Array.IndexOf(a, char.ToLowerInvariant(p))];
-   4624 if (char.IsUpper(p))
-   4625 {
-   4626 q = char.ToUpperInvariant(q);
-   4627 }
-   4628 result += q;
-   4629 ++i;
-   4630 } while (i < input.Length);
-   4631 return result;
-   4632 }
-   4633  
-   4634 ///////////////////////////////////////////////////////////////////////////
-   4635 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
-   4636 ///////////////////////////////////////////////////////////////////////////
-   4637 /// <summary>
-   4638 /// Decrypt using VIGENERE.
-   4639 /// </summary>
-   4640 /// <param name="input">the input to decrypt</param>
-   4641 /// <param name="enc_key">the key to decrypt with</param>
-   4642 /// <returns>the decrypted input</returns>
-   4643 private static string wasDecryptVIGENERE(string input, string enc_key)
-   4644 {
-   4645 char[] a =
-   4646 {
-   4647 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-   4648 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
-   4649 };
-   4650  
-   4651 enc_key = wasVigenereExpandKey(input, enc_key);
-   4652 string result = string.Empty;
-   4653 int i = 0;
-   4654 do
-   4655 {
-   4656 char p = input[i];
-   4657 if (!char.IsLetter(p))
-   4658 {
-   4659 result += p;
-   4660 ++i;
-   4661 continue;
-   4662 }
-   4663 char q =
-   4664 a[
-   4665 Array.IndexOf(wasReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i])),
-   4666 char.ToLowerInvariant(p))];
-   4667 if (char.IsUpper(p))
-   4668 {
-   4669 q = char.ToUpperInvariant(q);
-   4670 }
-   4671 result += q;
-   4672 ++i;
-   4673 } while (i < input.Length);
-   4674 return result;
-   4675 }
-   4676  
-   4677 ///////////////////////////////////////////////////////////////////////////
-   4678 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
-   4679 ///////////////////////////////////////////////////////////////////////////
-   4680 /// <summary>
-   4681 /// An implementation of the ATBASH cypher for latin alphabets.
-   4682 /// </summary>
-   4683 /// <param name="data">the data to encrypt or decrypt</param>
-   4684 /// <returns>the encrypted or decrypted data</returns>
-   4685 private static string wasATBASH(string data)
-   4686 {
-   4687 char[] a =
-   4688 {
-   4689 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-   4690 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
-   4691 };
-   4692  
-   4693 char[] input = data.ToArray();
-   4694  
-   4695 Parallel.ForEach(Enumerable.Range(0, data.Length), i =>
-   4696 {
-   4697 char e = input[i];
-   4698 if (!char.IsLetter(e)) return;
-   4699 int x = 25 - Array.BinarySearch(a, char.ToLowerInvariant(e));
-   4700 if (!char.IsUpper(e))
-   4701 {
-   4702 input[i] = a[x];
-   4703 return;
-   4704 }
-   4705 input[i] = char.ToUpperInvariant(a[x]);
-   4706 });
-   4707  
-   4708 return new string(input);
-   4709 }
-   4710  
3003 } 4711 #endregion
3004 } 4712 }
3005 } 4713 }
3006   4714  
-   4715
Generated by GNU Enscript 1.6.5.90.
-   4716  
-   4717  
-   4718