corrade-vassal – Blame information for rev 16

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