corrade-vassal – Diff between revs 17 and 18

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