corrade-vassal – Blame information for rev 20

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