corrade-vassal – Diff between revs 20 and 22

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