corrade-vassal – Blame information for rev 13

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