corrade-vassal – Blame information for rev 22

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