corrade-vassal – Rev 13
?pathlinks?
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using OpenMetaverse;
using wasSharp;
using Parallel = System.Threading.Tasks.Parallel;
using Timer = System.Timers.Timer;
namespace Vassal
{
public partial class Vassal : Form
{
public static Timer vassalTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Timer overviewTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Timer residentListTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Timer estateTopTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Timer regionsStateTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Timer estateTexturesTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
public static Image[] groundTextureImages = new Image[4];
public static volatile int regionsStateCheckIndex;
public static VassalConfiguration vassalConfiguration = new VassalConfiguration();
public static Vassal vassalForm;
public static readonly object ClientInstanceTeleportLock = new object();
public static readonly object RegionsStateCheckLock = new object();
/// <summary>
/// Corrade's input filter function.
/// </summary>
private static readonly Func<string, string> wasInput = o =>
{
if (string.IsNullOrEmpty(o)) return string.Empty;
foreach (Filter filter in vassalConfiguration.InputFilters)
{
switch (filter)
{
case Filter.RFC1738:
o = Web.URLUnescapeDataString(o);
break;
case Filter.RFC3986:
o = Web.URIUnescapeDataString(o);
break;
case Filter.ENIGMA:
o = Cryptography.ENIGMA(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
vassalConfiguration.ENIGMA.plugs.ToArray(),
vassalConfiguration.ENIGMA.reflector);
break;
case Filter.VIGENERE:
o = Cryptography.DecryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
break;
case Filter.ATBASH:
o = Cryptography.ATBASH(o);
break;
case Filter.BASE64:
o = Encoding.UTF8.GetString(Convert.FromBase64String(o));
break;
}
}
return o;
};
/// <summary>
/// Corrade's output filter function.
/// </summary>
private static readonly Func<string, string> wasOutput = o =>
{
if (string.IsNullOrEmpty(o)) return string.Empty;
foreach (Filter filter in vassalConfiguration.OutputFilters)
{
switch (filter)
{
case Filter.RFC1738:
o = Web.URLEscapeDataString(o);
break;
case Filter.RFC3986:
o = Web.URIEscapeDataString(o);
break;
case Filter.ENIGMA:
o = Cryptography.ENIGMA(o, vassalConfiguration.ENIGMA.rotors.ToArray(),
vassalConfiguration.ENIGMA.plugs.ToArray(),
vassalConfiguration.ENIGMA.reflector);
break;
case Filter.VIGENERE:
o = Cryptography.EncryptVIGENERE(o, vassalConfiguration.VIGENERESecret);
break;
case Filter.ATBASH:
o = Cryptography.ATBASH(o);
break;
case Filter.BASE64:
o = Convert.ToBase64String(Encoding.UTF8.GetBytes(o));
break;
}
}
return o;
};
private static readonly Action updateCurrentRegionName = () =>
{
try
{
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "Name"}
}, wasOutput), 60000);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.BeginInvoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Failed to query Corrade for current region."; }));
return;
}
switch (success)
{
case true:
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.CurrentRegionAt.Visible = true;
vassalForm.CurrentRegionName.Visible = true;
vassalForm.CurrentRegionName.Text =
CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).Last();
}));
break;
default:
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.CurrentRegionAt.Visible = false;
vassalForm.CurrentRegionName.Visible = false;
vassalForm.StatusText.Text = @"Error getting current region: " +
wasInput(KeyValue.Get("error", result));
}));
break;
}
}
catch (Exception ex)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text =
@"Error getting current region: " +
ex.Message;
}));
}
};
public Vassal()
{
InitializeComponent();
vassalForm = this;
}
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Sends a post request to an URL with set key-value pairs.
/// </summary>
/// <param name="URL">the url to send the message to</param>
/// <param name="message">key-value pairs to send</param>
/// <param name="millisecondsTimeout">the time in milliseconds for the request to timeout</param>
private static string wasPOST(string URL, Dictionary<string, string> message, uint millisecondsTimeout)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(URL);
request.UserAgent = VASSAL_CONSTANTS.USER_AGENT;
request.Proxy = WebRequest.DefaultWebProxy;
request.Pipelined = true;
request.KeepAlive = true;
request.Timeout = (int) millisecondsTimeout;
request.ReadWriteTimeout = (int) millisecondsTimeout;
request.AllowAutoRedirect = true;
request.AllowWriteStreamBuffering = true;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Method = WebRequestMethods.Http.Post;
// set the content type based on chosen output filers
switch (vassalConfiguration.OutputFilters.Last())
{
case Filter.RFC1738:
request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.WWW_FORM_URLENCODED;
break;
default:
request.ContentType = VASSAL_CONSTANTS.CONTENT_TYPE.TEXT_PLAIN;
break;
}
// send request
using (Stream requestStream = request.GetRequestStream())
{
using (StreamWriter dataStream = new StreamWriter(requestStream))
{
dataStream.Write(KeyValue.Encode(message));
}
}
// read response
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (
StreamReader streamReader = new StreamReader(responseStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
catch (Exception)
{
}
return null;
}
private void RegionSelected(object sender, EventArgs e)
{
new Thread(() =>
{
try
{
// Stop timers.
vassalTimer.Stop();
overviewTabTimer.Stop();
regionsStateTabTimer.Stop();
residentListTabTimer.Stop();
estateTopTabTimer.Stop();
estateTexturesTabTimer.Stop();
Monitor.Enter(ClientInstanceTeleportLock);
string selectedRegionName = string.Empty;
Vector3 selectedRegionPosition = Vector3.Zero;
bool startTeleport = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
ListViewItem listViewItem = LoadedRegionsBox.SelectedItem as ListViewItem;
switch (listViewItem != null && LoadedRegionsBox.SelectedIndex != -1)
{
case true:
selectedRegionName = listViewItem.Text;
selectedRegionPosition = (Vector3) listViewItem.Tag;
startTeleport = true;
break;
default:
startTeleport = false;
break;
}
}));
if (!startTeleport) throw new Exception();
// Announce teleport.
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.RegionTeleportGroup.Enabled = false;
vassalForm.StatusProgress.Value = 0;
vassalForm.StatusText.Text = @"Teleporting to " + selectedRegionName;
}));
// Pause for teleport (10 teleports / 15s allowed).
Thread.Sleep(700);
int elapsedSeconds = 0;
Timer teleportTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
teleportTimer.Elapsed += (o, p) =>
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusProgress.Value =
Math.Min(
(int)
(100d*
(TimeSpan.FromSeconds(++elapsedSeconds).TotalMilliseconds/
vassalConfiguration.TeleportTimeout)), 100);
}));
};
teleportTimer.Start();
string result = null;
ManualResetEvent receivedPOST = new ManualResetEvent(false);
new Thread(() =>
{
result = wasInput(wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"region", selectedRegionName},
{"position", selectedRegionPosition.ToString()},
{"fly", "True"}
}, wasOutput), vassalConfiguration.TeleportTimeout));
receivedPOST.Set();
}) {IsBackground = true}.Start();
receivedPOST.WaitOne((int) vassalConfiguration.TeleportTimeout, false);
teleportTimer.Stop();
switch (!string.IsNullOrEmpty(result) && KeyValue.Get("success", result) == "True")
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Now at " + selectedRegionName;
vassalForm.CurrentRegionName.Text = selectedRegionName;
}));
break;
default:
switch (!string.IsNullOrEmpty(result))
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Failed teleporting to " + selectedRegionName +
@": " +
KeyValue.Get("error", result);
}));
break;
default:
vassalForm.Invoke(
(MethodInvoker)
(() =>
{
vassalForm.StatusText.Text = @"Failed teleporting to " +
selectedRegionName;
}));
break;
}
break;
}
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Error communicating with Corrade: " + ex.Message; }));
}
finally
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.StatusProgress.Value = 100;
vassalForm.RegionTeleportGroup.Enabled = true;
// Set the map image to the loading spinner.
Assembly thisAssembly = Assembly.GetExecutingAssembly();
Stream file =
thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif");
switch (file != null)
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage;
RegionAvatarsMap.Image = Image.FromStream(file);
RegionAvatarsMap.Refresh();
}));
break;
}
// Clear the resident list table.
ResidentListGridView.Rows.Clear();
// Clear the top scripts table.
TopScriptsGridView.Rows.Clear();
// Clear the top colliders table.
TopCollidersGridView.Rows.Clear();
// Clear the estate list table.
EstateListGridView.Rows.Clear();
// Clear the estate list selection box.
EstateListSelectBox.SelectedIndex = -1;
// Invalidate data for overview tab.
vassalForm.CurrentRegionAt.Visible = false;
vassalForm.CurrentRegionName.Visible = false;
Agents.Text = string.Empty;
Agents.Enabled = false;
LastLag.Text = string.Empty;
LastLag.Enabled = false;
Dilation.Text = string.Empty;
Dilation.Enabled = false;
FPS.Text = string.Empty;
FPS.Enabled = false;
PhysicsFPS.Text = string.Empty;
PhysicsFPS.Enabled = false;
ActiveScripts.Text = string.Empty;
ActiveScripts.Enabled = false;
ScriptTime.Text = string.Empty;
ScriptTime.Enabled = false;
FrameTime.Text = string.Empty;
FrameTime.Enabled = false;
ScriptedObjects.Text = string.Empty;
ScriptedObjects.Enabled = false;
PhysicsTime.Text = string.Empty;
PhysicsTime.Enabled = false;
NetTime.Text = string.Empty;
NetTime.Enabled = false;
Objects.Text = string.Empty;
Objects.Enabled = false;
}));
Monitor.Exit(ClientInstanceTeleportLock);
// start timers
vassalTimer.Start();
overviewTabTimer.Start();
regionsStateTabTimer.Start();
residentListTabTimer.Start();
estateTopTabTimer.Start();
estateTexturesTabTimer.Start();
}
})
{IsBackground = true}.Start();
}
private void SettingsRequested(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() => { VassalStatusGroup.Enabled = false; }));
SettingsForm settingsForm = new SettingsForm {TopMost = true};
settingsForm.Show();
}
private void VassalShown(object sender, EventArgs e)
{
// Set the version
vassalForm.Version.Text = @"v" + VASSAL_CONSTANTS.VASSAL_VERSION;
// Disable estate manager tabs since we will enable these dynamically.
EstateTopTab.Enabled = false;
EstateListsTab.Enabled = false;
ResidentListBanGroup.Enabled = false;
ResidentListTeleportHomeGroup.Enabled = false;
EstateTerrainDownloadUploadGroup.Enabled = false;
EstateVariablesGroup.Enabled = false;
// Estate textures
RegionTexturesLowUUIDApplyBox.Enabled = false;
RegionTexturesLowUUIDApplyButton.Enabled = false;
RegionTexturesMiddleLowUUIDApplyBox.Enabled = false;
RegionTexturesMiddleLowUUIDApplyButton.Enabled = false;
RegionTexturesMiddleHighUUIDApplyBox.Enabled = false;
RegionTexturesMiddleHighUUIDApplyButton.Enabled = false;
RegionTexturesHighUUIDApplyBox.Enabled = false;
RegionTexturesHighUUIDApplyButton.Enabled = false;
// Get the configuration file settings if it exists.
if (File.Exists(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE))
{
// Load the configuration.
VassalConfiguration.Load(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE, ref vassalConfiguration);
// Apply settings
RegionRestartDelayBox.Text = vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture);
}
// Get all the regions if they exist.
if (File.Exists(VASSAL_CONSTANTS.VASSAL_REGIONS))
{
Vector3 localPosition;
List<KeyValuePair<string, Vector3>> ConfiguredRegions = new List<KeyValuePair<string, Vector3>>(
File.ReadAllLines(VASSAL_CONSTANTS.VASSAL_REGIONS)
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
Vector3.TryParse(p.Last(), out localPosition)
? localPosition
: Vector3.Zero).OrderBy(o => o.Key).ToDictionary(o => o.Key, o => o.Value));
// Populate the loaded regions.
LoadedRegionsBox.Items.Clear();
LoadedRegionsBox.Items.AddRange(
ConfiguredRegions.Select(o => (object) new ListViewItem {Text = o.Key, Tag = o.Value})
.ToArray());
// Populate the batch restart grid view.
BatchRestartGridView.Rows.Clear();
foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions)
{
BatchRestartGridView.Rows.Add(data.Key, data.Value.ToString());
}
// Populate the regions state grid view.
foreach (KeyValuePair<string, Vector3> data in ConfiguredRegions)
{
RegionsStateGridView.Rows.Add(data.Key, "Check pening...");
}
}
// Start the vassal timer.
vassalTimer.Elapsed += (o, p) =>
{
if (!Monitor.TryEnter(ClientInstanceTeleportLock))
return;
try
{
// Check Corrade connection status.
TcpClient tcpClient = new TcpClient();
Uri uri = new Uri(vassalConfiguration.HTTPServerURL);
tcpClient.Connect(uri.Host, uri.Port);
// port open
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.CurrentRegionAt.Visible = true;
vassalForm.CurrentRegionName.Visible = true;
Assembly thisAssembly = Assembly.GetExecutingAssembly();
Stream file =
thisAssembly.GetManifestResourceStream("Vassal.img.online.png");
switch (file != null)
{
case true:
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
ConnectionStatusPictureBox.Image = Image.FromStream(file);
ConnectionStatusPictureBox.Refresh();
}));
break;
}
Tabs.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
catch (Exception)
{
// port closed
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.CurrentRegionAt.Visible = false;
vassalForm.CurrentRegionName.Visible = false;
Assembly thisAssembly = Assembly.GetExecutingAssembly();
Stream file =
thisAssembly.GetManifestResourceStream("Vassal.img.offline.png");
switch (file != null)
{
case true:
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
ConnectionStatusPictureBox.Image = Image.FromStream(file);
ConnectionStatusPictureBox.Refresh();
}));
break;
}
Tabs.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
}
try
{
// Get the simulator name and if we are an estate manager.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{
"data", CSV.FromEnumerable(new[]
{
"Name",
"IsEstateManager"
})
}
}, wasOutput), vassalConfiguration.DataTimeout);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (data.Count.Equals(0))
throw new Exception();
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
// Drop access to features if we are not estate managers.
bool isEstateManager;
switch (
bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) &&
isEstateManager)
{
case true: // we are an estate manager
EstateTopTab.Enabled = true;
EstateListsTab.Enabled = true;
ResidentListBanGroup.Enabled = true;
ResidentListTeleportHomeGroup.Enabled = true;
EstateTerrainDownloadUploadGroup.Enabled = true;
EstateVariablesGroup.Enabled = true;
RegionToolsRegionDebugGroup.Enabled = true;
RegionToolsRegionInfoGroup.Enabled = true;
// Estate textures
RegionTexturesLowUUIDApplyBox.Enabled = true;
RegionTexturesLowUUIDApplyButton.Enabled = true;
RegionTexturesMiddleLowUUIDApplyBox.Enabled = true;
RegionTexturesMiddleLowUUIDApplyButton.Enabled = true;
RegionTexturesMiddleHighUUIDApplyBox.Enabled = true;
RegionTexturesMiddleHighUUIDApplyButton.Enabled = true;
RegionTexturesHighUUIDApplyBox.Enabled = true;
RegionTexturesHighUUIDApplyButton.Enabled = true;
break;
default:
EstateTopTab.Enabled = false;
EstateListsTab.Enabled = false;
ResidentListBanGroup.Enabled = false;
ResidentListTeleportHomeGroup.Enabled = false;
EstateTerrainDownloadUploadGroup.Enabled = false;
EstateVariablesGroup.Enabled = false;
RegionToolsRegionDebugGroup.Enabled = false;
RegionToolsRegionInfoGroup.Enabled = false;
// Estate textures
RegionTexturesLowUUIDApplyBox.Enabled = false;
RegionTexturesLowUUIDApplyButton.Enabled = false;
RegionTexturesMiddleLowUUIDApplyBox.Enabled = false;
RegionTexturesMiddleLowUUIDApplyButton.Enabled = false;
RegionTexturesMiddleHighUUIDApplyBox.Enabled = false;
RegionTexturesMiddleHighUUIDApplyButton.Enabled = false;
RegionTexturesHighUUIDApplyBox.Enabled = false;
RegionTexturesHighUUIDApplyButton.Enabled = false;
break;
}
// Show the region name.
vassalForm.CurrentRegionName.Text = data[data.IndexOf("Name") + 1];
vassalForm.CurrentRegionAt.Visible = true;
vassalForm.CurrentRegionName.Visible = true;
}));
}
catch (Exception)
{
}
Monitor.Exit(ClientInstanceTeleportLock);
};
vassalTimer.Start();
// Start the overview timer.
overviewTabTimer.Elapsed += (o, p) =>
{
// Do not do anything in case the tab is not selected.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(OverviewTab); }));
if (!run)
{
overviewTabTimer.Stop();
return;
}
overviewTabTimer.Stop();
try
{
// Start measuring the lag to Corrade.
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// Get the statistics.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{
"data", CSV.FromEnumerable(new[]
{
"Agents",
"LastLag",
"Dilation",
"FPS",
"PhysicsFPS",
"ActiveScripts",
"ScriptTime",
"Objects",
"FrameTime",
"ScriptedObjects",
"PhysicsTime",
"NetTime",
"AvatarPositions"
})
}
}, wasOutput), vassalConfiguration.DataTimeout);
stopWatch.Stop();
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (data.Count.Equals(0))
throw new Exception();
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
// Populate the overview tab.
Agents.Text = data[data.IndexOf("Agents") + 1];
Agents.Enabled = true;
LastLag.Text = data[data.IndexOf("LastLag") + 1];
LastLag.Enabled = true;
Dilation.Text = data[data.IndexOf("Dilation") + 1];
Dilation.Enabled = true;
FPS.Text = data[data.IndexOf("FPS") + 1];
FPS.Enabled = true;
PhysicsFPS.Text = data[data.IndexOf("PhysicsFPS") + 1];
PhysicsFPS.Enabled = true;
ActiveScripts.Text = data[data.IndexOf("ActiveScripts") + 1];
ActiveScripts.Enabled = true;
ScriptTime.Text = data[data.IndexOf("ScriptTime") + 1];
ScriptTime.Enabled = true;
FrameTime.Text = data[data.IndexOf("FrameTime") + 1];
FrameTime.Enabled = true;
ScriptedObjects.Text = data[data.IndexOf("ScriptedObjects") + 1];
ScriptedObjects.Enabled = true;
PhysicsTime.Text = data[data.IndexOf("PhysicsTime") + 1];
PhysicsTime.Enabled = true;
NetTime.Text = data[data.IndexOf("NetTime") + 1];
NetTime.Enabled = true;
Objects.Text = data[data.IndexOf("Objects") + 1];
Objects.Enabled = true;
// Show the overview lag time.
CorradePollTimeDial.Value =
(float) Math.Min(TimeSpan.FromMilliseconds(stopWatch.ElapsedMilliseconds).TotalSeconds,
CorradePollTimeDial.MaxValue);
}));
// Get avatar positions.
// Pattern: [...], X, 10, Y, 63, Z, 200, [...], X, 52, Y, 73, Z, 55, [...[...]]
float X = 0, Y = 0, Z = 0;
List<Vector3> positions = data.Select((x, i) => new {Item = x, Index = i})
.Where(x => x.Item.Equals("X") || x.Item.Equals("Y") || x.Item.Equals("Z"))
.Select(z => data[z.Index + 1]).Select((x, i) => new {Value = x, Index = i})
.GroupBy(x => x.Index/3)
.Select(x => x.Select(v => v.Value).ToList())
.Where(
x =>
float.TryParse(x[0], out X) && float.TryParse(x[1], out Y) &&
float.TryParse(x[2], out Z))
.Select(x => new Vector3(X, Y, Z))
.ToList();
// Get the map image.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getgridregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "MapImageID"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception();
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"item", data.Last()},
{"type", "Texture"},
{"format", "Jpeg"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
Image mapImage;
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
mapImage = Image.FromStream(memoryStream);
}
// Draw the avatars onto the map.
Graphics mapGraphics = Graphics.FromImage(mapImage);
foreach (Vector3 position in positions)
{
mapGraphics.FillEllipse(Brushes.Chartreuse,
new Rectangle((int) position.X, (int) position.Y, 4, 4));
}
mapGraphics.DrawImage(mapImage, new Point(0, 0));
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
RegionAvatarsMap.SizeMode = PictureBoxSizeMode.StretchImage;
RegionAvatarsMap.Image = mapImage;
RegionAvatarsMap.Refresh();
}));
}
catch (Exception)
{
}
overviewTabTimer.Start();
};
overviewTabTimer.Start();
regionsStateTabTimer.Elapsed += (o, p) =>
{
// Do not do anything in case the tab is not selected.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(RegionsStateTab); }));
if (!run)
{
regionsStateTabTimer.Stop();
return;
}
regionsStateTabTimer.Stop();
try
{
string regionName = string.Empty;
vassalForm.Invoke((MethodInvoker) (() =>
{
regionName =
RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateRegionName"].Value
.ToString();
RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
Color.Gold;
}));
if (string.IsNullOrEmpty(regionName))
throw new Exception();
// Get the region status.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getgridregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"region", regionName},
{"data", "Access"}
}, wasOutput), vassalConfiguration.DataTimeout);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception();
string status = data.Last();
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (status)
{
case "Unknown":
case "Down":
case "NonExistent":
RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
Color.LightPink;
RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value =
status;
break;
default:
RegionsStateGridView.Rows[regionsStateCheckIndex].DefaultCellStyle.BackColor =
Color.LightGreen;
RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastState"].Value =
"Up";
break;
}
RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateLastCheck"].Value = DateTime
.Now.ToUniversalTime()
.ToString(LINDEN_CONSTANTS.LSL.DATE_TIME_STAMP);
}));
}
catch (Exception)
{
}
finally
{
++regionsStateCheckIndex;
vassalForm.Invoke((MethodInvoker) (() =>
{
if (regionsStateCheckIndex >= RegionsStateGridView.Rows.Count)
{
regionsStateCheckIndex = 0;
}
}));
}
regionsStateTabTimer.Start();
};
regionsStateTabTimer.Start();
// Start the top scores timer.
estateTopTabTimer.Elapsed += (o, p) =>
{
// Do not do anything in case the tab is not selected.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(EstateTopTab); }));
if (!run)
{
estateTopTabTimer.Stop();
return;
}
estateTopTabTimer.Stop();
try
{
// Get the top scripts.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiontop"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", "scripts"}
}, wasOutput), vassalConfiguration.DataTimeout);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
HashSet<List<string>> data =
new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/5)
.Select(x => x.Select(v => v.Value).ToList()));
if (data.Count.Equals(0))
throw new Exception();
vassalForm.Invoke((MethodInvoker) (() =>
{
// Remove rows that are not in the data update.
foreach (
int index in
TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>()
.Where(
topScriptsRow =>
!data.Any(q => q[2].Equals(topScriptsRow.Cells["TopScriptsUUID"].Value)))
.Select(q => q.Index))
{
TopScriptsGridView.Rows.RemoveAt(index);
}
// Now update or add new data.
foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5)))
{
DataGridViewRow row =
TopScriptsGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(q => q.Cells["TopScriptsUUID"].Value.Equals(dataComponents[2]));
switch (row != null)
{
case true: // the row exists, so update it.
row.Cells["TopScriptsScore"].Value = dataComponents[0];
row.Cells["TopScriptsTaskName"].Value = dataComponents[1];
row.Cells["TopScriptsUUID"].Value = dataComponents[2];
row.Cells["TopScriptsOwner"].Value = dataComponents[3];
row.Cells["TopScriptsPosition"].Value = dataComponents[4];
break;
case false: // the row dosn't exist, so add it.
TopScriptsGridView.Rows.Add(dataComponents[0], dataComponents[1], dataComponents[2],
dataComponents[3], dataComponents[4]);
break;
}
}
}));
// Get the top colliders.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiontop"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", "colliders"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
data = new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/5)
.Select(x => x.Select(v => v.Value).ToList()));
if (data.Count.Equals(0))
throw new Exception();
vassalForm.Invoke((MethodInvoker) (() =>
{
// Remove rows that are not in the data update.
foreach (
int index in
TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>()
.Where(
topCollidersRow =>
!data.Any(q => q[2].Equals(topCollidersRow.Cells["TopCollidersUUID"].Value)))
.Select(q => q.Index))
{
TopCollidersGridView.Rows.RemoveAt(index);
}
// Now update or add new data.
foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(5)))
{
DataGridViewRow row =
TopCollidersGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(q => q.Cells["TopCollidersUUID"].Value.Equals(dataComponents[2]));
switch (row != null)
{
case true: // the row exists, so update it.
row.Cells["TopCollidersScore"].Value = dataComponents[0];
row.Cells["TopSCollidersTaskName"].Value = dataComponents[1];
row.Cells["TopCollidersUUID"].Value = dataComponents[2];
row.Cells["TopCollidersOwner"].Value = dataComponents[3];
row.Cells["TopCollidersPosition"].Value = dataComponents[4];
break;
case false: // the row dosn't exist, so add it.
TopCollidersGridView.Rows.Add(dataComponents[0], dataComponents[1],
dataComponents[2],
dataComponents[3], dataComponents[4]);
break;
}
}
}));
}
catch (Exception)
{
}
estateTopTabTimer.Start();
};
estateTopTabTimer.Start();
// Start the resident list timer.
residentListTabTimer.Elapsed += (o, p) =>
{
// Do not do anything in case the tab is not selected.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(ResidentListTab); }));
if (!run)
{
residentListTabTimer.Stop();
return;
}
residentListTabTimer.Stop();
try
{
// Get the avatar positions.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getavatarpositions"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"entity", "region"}
}, wasOutput), vassalConfiguration.DataTimeout);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
HashSet<List<string>> data =
new HashSet<List<string>>(CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/3)
.Select(x => x.Select(v => v.Value).ToList()));
if (data.Count.Equals(0))
throw new Exception();
vassalForm.Invoke((MethodInvoker) (() =>
{
// Remove rows that are not in the data update.
foreach (
int index in
ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>()
.Where(
residentListRow =>
!data.Any(q => q[1].Equals(residentListRow.Cells["ResidentListUUID"].Value)))
.Select(q => q.Index))
{
ResidentListGridView.Rows.RemoveAt(index);
}
// Now update or add new data.
foreach (List<string> dataComponents in data.Where(q => q.Count.Equals(3)))
{
DataGridViewRow row =
ResidentListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(q => q.Cells["ResidentListUUID"].Value.Equals(dataComponents[1]));
switch (row != null)
{
case true: // the row exists, so update it.
row.Cells["ResidentListName"].Value = dataComponents[0];
row.Cells["ResidentListUUID"].Value = dataComponents[1];
row.Cells["ResidentListPosition"].Value = dataComponents[2];
break;
case false: // the row dosn't exist, so add it.
ResidentListGridView.Rows.Add(dataComponents[0], dataComponents[1],
dataComponents[2]);
break;
}
}
}));
}
catch (Exception)
{
}
residentListTabTimer.Start();
};
residentListTabTimer.Start();
estateTexturesTabTimer.Elapsed += (o, p) =>
{
// Do not do anything in case the tab is not selected.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() => { run = Tabs.SelectedTab.Equals(EstateTexturesTab); }));
if (!run)
{
estateTexturesTabTimer.Stop();
return;
}
estateTexturesTabTimer.Stop();
try
{
// Get the region terrain texture UUIDs.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregionterraintextures"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password}
}, wasOutput), vassalConfiguration.DataTimeout);
bool success;
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception();
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(4))
throw new Exception();
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTexturesLowUUIDBox.Text = data[0];
if (string.IsNullOrEmpty(RegionTexturesLowUUIDApplyBox.Text))
{
RegionTexturesLowUUIDApplyBox.Text = data[0];
}
RegionTexturesMiddleLowUUIDBox.Text = data[1];
if (string.IsNullOrEmpty(RegionTexturesMiddleLowUUIDApplyBox.Text))
{
RegionTexturesMiddleLowUUIDApplyBox.Text = data[1];
}
RegionTexturesMiddleHighUUIDBox.Text = data[2];
if (string.IsNullOrEmpty(RegionTexturesMiddleHighUUIDApplyBox.Text))
{
RegionTexturesMiddleHighUUIDApplyBox.Text = data[2];
}
RegionTexturesHighUUIDBox.Text = data[3];
if (string.IsNullOrEmpty(RegionTexturesHighUUIDApplyBox.Text))
{
RegionTexturesHighUUIDApplyBox.Text = data[1];
}
}));
Parallel.ForEach(Enumerable.Range(0, 4), i =>
{
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"item", data[i]},
{"type", "Texture"},
{"format", "Jpeg"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result) ||
!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
return;
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
groundTextureImages[i] = Image.FromStream(memoryStream);
}
switch (i)
{
case 0:
vassalForm.BeginInvoke(
(MethodInvoker)
(() => { RegionTexturesLowPictureBox.Image = groundTextureImages[0]; }));
break;
case 1:
vassalForm.BeginInvoke(
(MethodInvoker)
(() => { RegionTexturesMiddleLowPictureBox.Image = groundTextureImages[1]; }));
break;
case 2:
vassalForm.BeginInvoke(
(MethodInvoker)
(() => { RegionTexturesMiddleHighPictureBox.Image = groundTextureImages[2]; }));
break;
case 3:
vassalForm.BeginInvoke(
(MethodInvoker)
(() => { RegionTexturesHighPictureBox.Image = groundTextureImages[3]; }));
break;
}
});
}
catch (Exception)
{
}
estateTexturesTabTimer.Start();
};
estateTexturesTabTimer.Start();
}
private void RequestedEditRegions(object sender, EventArgs e)
{
// Clear any selection.
LoadedRegionsBox.SelectedIndex = -1;
RegionEditForm regionEditForm = new RegionEditForm {TopMost = true};
regionEditForm.Show();
}
private void RequestSelecting(object sender, TabControlCancelEventArgs e)
{
e.Cancel = !e.TabPage.Enabled;
}
private void RequestExportTopScripts(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.ExportCSVDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.ExportCSVDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"exporting...";
vassalForm.StatusProgress.Value = 0;
using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
{
foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows)
{
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
topScriptsRow.Cells["TopScriptsScore"].Value.ToString(),
topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString(),
topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(),
topScriptsRow.Cells["TopScriptsOwner"].Value.ToString(),
topScriptsRow.Cells["TopScriptsPosition"].Value.ToString()
}));
}
}
vassalForm.StatusText.Text = @"exported";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
private void RequestExportTopColliders(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.ExportCSVDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.ExportCSVDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"exporting...";
vassalForm.StatusProgress.Value = 0;
using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
{
foreach (DataGridViewRow topCollidersRow in TopCollidersGridView.Rows)
{
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
topCollidersRow.Cells["TopCollidersScore"].Value.ToString(),
topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString(),
topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(),
topCollidersRow.Cells["TopCollidersOwner"].Value.ToString(),
topCollidersRow.Cells["TopCollidersPosition"].Value.ToString()
}));
}
}
vassalForm.StatusText.Text = @"exported";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
private void RequestFilterTopScripts(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
Regex topScriptsRowRegex;
switch (!string.IsNullOrEmpty(TopScriptsFilter.Text))
{
case true:
topScriptsRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled);
break;
default:
topScriptsRowRegex = new Regex(@".+?", RegexOptions.Compiled);
break;
}
foreach (DataGridViewRow topScriptsRow in TopScriptsGridView.Rows.AsParallel().Cast<DataGridViewRow>())
{
topScriptsRow.Visible =
topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsScore"].Value.ToString()) ||
topScriptsRowRegex.IsMatch(
topScriptsRow.Cells["TopScriptsTaskName"].Value.ToString()) ||
topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString()) ||
topScriptsRowRegex.IsMatch(topScriptsRow.Cells["TopScriptsOwner"].Value.ToString()) ||
topScriptsRowRegex.IsMatch(
topScriptsRow.Cells["TopScriptsPosition"].Value.ToString());
}
}));
}
private void RequestFilterTopColliders(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
Regex topCollidersRowRegex;
switch (!string.IsNullOrEmpty(TopScriptsFilter.Text))
{
case true:
topCollidersRowRegex = new Regex(TopScriptsFilter.Text, RegexOptions.Compiled);
break;
default:
topCollidersRowRegex = new Regex(@".+?", RegexOptions.Compiled);
break;
}
foreach (
DataGridViewRow topCollidersRow in TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>())
{
topCollidersRow.Visible =
topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersScore"].Value.ToString()) ||
topCollidersRowRegex.IsMatch(
topCollidersRow.Cells["TopCollidersTaskName"].Value.ToString()) ||
topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString()) ||
topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersOwner"].Value.ToString()) ||
topCollidersRowRegex.IsMatch(
topCollidersRow.Cells["TopCollidersPosition"].Value.ToString());
}
}));
}
private void RequestReturnTopScriptsObjects(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopScriptsButton.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
// Enqueue all the UUIDs to return.
Queue<KeyValuePair<UUID, Vector3>> returnUUIDs = new Queue<KeyValuePair<UUID, Vector3>>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow topScriptsRow in
TopScriptsGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
Vector3 objectPosition;
UUID returnUUID;
if (!UUID.TryParse(topScriptsRow.Cells["TopScriptsUUID"].Value.ToString(), out returnUUID) ||
!Vector3.TryParse(topScriptsRow.Cells["TopScriptsPosition"].Value.ToString(), out objectPosition))
continue;
returnUUIDs.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition));
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (returnUUIDs.Count.Equals(0))
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopScriptsButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
return;
}
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 0; }));
int totalObjects = returnUUIDs.Count;
do
{
// Dequeue the first object.
KeyValuePair<UUID, Vector3> objectData = returnUUIDs.Dequeue();
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Returning object UUID: " + objectData.Key; }));
string currentRegionName = string.Empty;
vassalForm.Invoke((MethodInvoker) (() => { currentRegionName = CurrentRegionName.Text; }));
// Teleport to the object.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"position", objectData.Value.ToString()},
{"region", currentRegionName},
{"fly", "True"}
}, wasOutput), vassalConfiguration.TeleportTimeout);
if (string.IsNullOrEmpty(result))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
continue;
}
// Return the object.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "derez"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"item", objectData.Key.ToString()},
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half
{"type", "ReturnToOwner"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
continue;
}
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"No success status could be retrieved. "; }));
continue;
}
switch (success)
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Returned object: " + objectData.Key;
// Remove the row from the grid view.
DataGridViewRow row =
TopScriptsGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(
o => o.Cells["TopScriptsUUID"].Value.Equals(objectData.Key.ToString()));
if (row == null) return;
int i = row.Index;
TopScriptsGridView.Rows.RemoveAt(i);
}));
break;
case false:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
@": " +
wasInput(KeyValue.Get("error", result));
}));
break;
}
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusProgress.Value =
Math.Min((int) (100d*Math.Abs(returnUUIDs.Count - totalObjects)/totalObjects), 100);
}));
} while (!returnUUIDs.Count.Equals(0));
vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 100; }));
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Allow teleports and enable button.
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopScriptsButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestReturnTopCollidersObjects(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopCollidersButton.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
// Enqueue all the UUIDs to return.
Queue<KeyValuePair<UUID, Vector3>> returnObjectUUIDQueue = new Queue<KeyValuePair<UUID, Vector3>>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow topCollidersRow in
TopCollidersGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
Vector3 objectPosition;
UUID returnUUID;
if (!UUID.TryParse(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(), out returnUUID) ||
!Vector3.TryParse(topCollidersRow.Cells["TopCollidersPosition"].Value.ToString(),
out objectPosition))
continue;
returnObjectUUIDQueue.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition));
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (returnObjectUUIDQueue.Count.Equals(0))
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopCollidersButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
return;
}
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 0; }));
int totalObjects = returnObjectUUIDQueue.Count;
do
{
// Dequeue the first object.
KeyValuePair<UUID, Vector3> objectData = returnObjectUUIDQueue.Dequeue();
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Returning UUID: " + objectData.Key; }));
string currentRegionName = string.Empty;
vassalForm.Invoke((MethodInvoker) (() => { currentRegionName = CurrentRegionName.Text; }));
// Teleport to the object.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"position", objectData.Value.ToString()},
{"region", currentRegionName},
{"fly", "True"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
continue;
}
// Return the object.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "derez"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"item", objectData.Key.ToString()},
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half
{"type", "ReturnToOwner"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Error communicating with Corrade."; }));
continue;
}
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"No success status could be retrieved. "; }));
continue;
}
switch (success)
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Returned object: " + objectData.Key;
// Remove the row from the grid view.
DataGridViewRow row =
TopCollidersGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(
o => o.Cells["TopCollidersUUID"].Value.Equals(objectData.Key.ToString()));
if (row == null) return;
int i = row.Index;
TopCollidersGridView.Rows.RemoveAt(i);
}));
break;
case false:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Could not return object " + objectData.Key +
@": " +
wasInput(KeyValue.Get("error", result));
}));
break;
}
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusProgress.Value =
Math.Min(
(int) (100d*Math.Abs(returnObjectUUIDQueue.Count - totalObjects)/totalObjects), 100);
}));
} while (!returnObjectUUIDQueue.Count.Equals(0));
vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusProgress.Value = 100; }));
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Allow teleports and enable button.
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.ReturnTopScriptsButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestBatchRestart(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.BatchRestartButton.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
// Enqueue all the regions to restart.
Queue<KeyValuePair<string, Vector3>> restartRegionQueue = new Queue<KeyValuePair<string, Vector3>>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow topCollidersRow in
BatchRestartGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
Vector3 objectPosition;
string regionName = topCollidersRow.Cells["BatchRestartRegionName"].Value.ToString();
if (string.IsNullOrEmpty(regionName) ||
!Vector3.TryParse(topCollidersRow.Cells["BatchRestartPosition"].Value.ToString(),
out objectPosition))
continue;
restartRegionQueue.Enqueue(new KeyValuePair<string, Vector3>(regionName, objectPosition));
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (restartRegionQueue.Count.Equals(0))
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.BatchRestartButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
return;
}
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
do
{
// Dequeue the first object.
KeyValuePair<string, Vector3> restartRegionData = restartRegionQueue.Dequeue();
DataGridViewRow currentDataGridViewRow = null;
vassalForm.Invoke((MethodInvoker) (() =>
{
currentDataGridViewRow = vassalForm.BatchRestartGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(
o =>
o.Cells["BatchRestartRegionName"].Value.ToString()
.Equals(restartRegionData.Key, StringComparison.OrdinalIgnoreCase) &&
o.Cells["BatchRestartPosition"].Value.ToString()
.Equals(restartRegionData.Value.ToString(),
StringComparison.OrdinalIgnoreCase));
}));
if (currentDataGridViewRow == null) continue;
try
{
bool success = false;
string result;
// Retry to teleport to each region a few times.
int teleportRetries = 3;
do
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Attempting to teleport to " + restartRegionData.Key +
@" " + @"(" +
teleportRetries.ToString(Utils.EnUsCulture) +
@")";
}));
// Teleport to the region.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "teleport"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"position", restartRegionData.Value.ToString()},
{"region", restartRegionData.Key},
{"fly", "True"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
{
vassalForm.Invoke(
(MethodInvoker)
(() =>
{
vassalForm.StatusText.Text = @"Error communicating with Corrade.";
}));
continue;
}
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
{
vassalForm.Invoke(
(MethodInvoker)
(() =>
{
vassalForm.StatusText.Text = @"No success status could be retrieved. ";
}));
continue;
}
switch (success)
{
case true:
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Teleport succeeded."; }));
break;
default:
// In case the destination is to close (Corrade status code 37559),
// then we are on the same region so no need to retry.
uint status; //37559
switch (
uint.TryParse(wasInput(KeyValue.Get("status", result)), out status) &&
status.Equals(37559))
{
case true: // We are on the region already!
success = true;
break;
default:
vassalForm.Invoke(
(MethodInvoker)
(() => { vassalForm.StatusText.Text = @"Teleport failed."; }));
break;
}
break;
}
// Pause for teleport (10 teleports / 15s allowed).
Thread.Sleep(700);
} while (!success && !(--teleportRetries).Equals(0));
if (!success)
throw new Exception("Failed to teleport to region.");
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getregiondata"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", "IsEstateManager"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate rights.");
List<string> data = CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))).ToList();
if (!data.Count.Equals(2))
throw new Exception("Could not retrieve estate rights.");
bool isEstateManager;
switch (
bool.TryParse(data[data.IndexOf("IsEstateManager") + 1], out isEstateManager) &&
isEstateManager)
{
case true: // we are an estate manager
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "restartregion"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"action", "restart"},
{
"delay",
vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture)
}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not schedule a region restart.");
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Region scheduled for restart.";
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = @"Region scheduled for restart.";
}
}));
break;
default:
throw new Exception("No estate manager rights for region restart.");
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = ex.Message;
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = ex.Message;
}
}));
}
finally
{
// Pause for teleport (10 teleports / 15s allowed).
Thread.Sleep(700);
}
} while (!restartRegionQueue.Count.Equals(0));
}
catch (Exception)
{
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Allow teleports and enable button.
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.BatchRestartButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestFilterResidentList(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
Regex residentListRowRegex;
switch (!string.IsNullOrEmpty(ResidentListFilter.Text))
{
case true:
residentListRowRegex = new Regex(ResidentListFilter.Text, RegexOptions.Compiled);
break;
default:
residentListRowRegex = new Regex(@".+?", RegexOptions.Compiled);
break;
}
foreach (
DataGridViewRow residentListRow in ResidentListGridView.Rows.AsParallel().Cast<DataGridViewRow>())
{
residentListRow.Visible =
residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListName"].Value.ToString()) ||
residentListRowRegex.IsMatch(
residentListRow.Cells["ResidentListUUID"].Value.ToString()) ||
residentListRowRegex.IsMatch(residentListRow.Cells["ResidentListPosition"].Value.ToString());
}
}));
}
private void RequestBanAgents(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
ResidentListTeleportHomeGroup.Enabled = false;
ResidentListBanGroup.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
// Enqueue all the agents to ban.
Queue<UUID> agentsQueue = new Queue<UUID>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow residentListRow in
ResidentListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
UUID agentUUID;
if (!UUID.TryParse(residentListRow.Cells["ResidentListUUID"].Value.ToString(), out agentUUID))
continue;
agentsQueue.Enqueue(agentUUID);
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (agentsQueue.Count.Equals(0))
{
vassalForm.Invoke((MethodInvoker) (() =>
{
ResidentListBanGroup.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
return;
}
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
do
{
// Dequeue the first object.
UUID agentUUID = agentsQueue.Dequeue();
DataGridViewRow currentDataGridViewRow = null;
vassalForm.Invoke((MethodInvoker) (() =>
{
currentDataGridViewRow = vassalForm.ResidentListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(
o =>
o.Cells["ResidentListUUID"].Value.ToString()
.Equals(agentUUID.ToString(), StringComparison.OrdinalIgnoreCase));
}));
if (currentDataGridViewRow == null) continue;
try
{
bool alsoBan = false;
vassalForm.Invoke(
(MethodInvoker) (() => { alsoBan = vassalForm.ResidentBanAllEstatesBox.Checked; }));
// Ban the resident.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", "ban"},
{"action", "add"},
{"agent", agentUUID.ToString()},
{"all", alsoBan.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
switch (success)
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Resident banned.";
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = @"Resident banned.";
}
}));
break;
default:
throw new Exception("Unable to ban resident.");
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = ex.Message;
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = ex.Message;
}
}));
}
} while (agentsQueue.Count.Equals(0));
}
catch (Exception)
{
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Allow teleports and enable button.
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
ResidentListTeleportHomeGroup.Enabled = true;
ResidentListBanGroup.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestRipTerrain(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
RipTerrainButton.Enabled = false;
}));
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
// Get the map heights.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getterrainheight"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"entity", "region"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not get terrain heights.");
List<double> heights = new List<double>();
foreach (string map in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result))))
{
double height;
if (!double.TryParse(map, out height))
continue;
heights.Add(height);
}
if (heights.Count.Equals(0))
throw new Exception("Could not get terrain heights.");
double maxHeight = heights.Max();
using (Bitmap bitmap = new Bitmap(256, 256))
{
foreach (int x in Enumerable.Range(1, 255))
{
foreach (int y in Enumerable.Range(1, 255))
{
bitmap.SetPixel(x, 256 - y,
Color.FromArgb(
Math.Max(
(int) Numerics.MapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0),
0, 0));
}
}
Bitmap closureBitmap = (Bitmap) bitmap.Clone();
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.SavePNGFileDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.SavePNGFileDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"saving terrain...";
vassalForm.StatusProgress.Value = 0;
closureBitmap.Save(file, ImageFormat.Png);
vassalForm.StatusText.Text = @"terrain saved";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
finally
{
closureBitmap.Dispose();
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
}
catch (Exception ex)
{
vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
RipTerrainButton.Enabled = true;
}));
}
}) {IsBackground = true}.Start();
}
private void RequestDownloadTerrain(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
DownloadTerrainButton.Enabled = false;
}));
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
// Download the terrain.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "terrain"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"action", "get"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not download terrain.");
byte[] data = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.SaveRawFileDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.SaveRawFileDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"saving terrain...";
vassalForm.StatusProgress.Value = 0;
File.WriteAllBytes(file, data);
vassalForm.StatusText.Text = @"terrain saved";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
catch (Exception ex)
{
vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
DownloadTerrainButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestUploadTerrain(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
UploadTerrainButton.Enabled = false;
}));
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
byte[] data = null;
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (vassalForm.LoadRawFileDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.LoadRawFileDialog.FileName;
vassalForm.StatusText.Text = @"loading terrain...";
vassalForm.StatusProgress.Value = 0;
data = File.ReadAllBytes(file);
vassalForm.StatusText.Text = @"terrain loaded";
vassalForm.StatusProgress.Value = 100;
break;
}
}));
// Upload the terrain.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "terrain"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"action", "set"},
{"data", Convert.ToBase64String(data)}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not upload terrain.");
}
catch (Exception ex)
{
vassalForm.BeginInvoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
UploadTerrainButton.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestTabsChanged(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
overviewTabTimer.Stop();
regionsStateTabTimer.Stop();
residentListTabTimer.Stop();
estateTopTabTimer.Stop();
if (Tabs.SelectedTab.Equals(OverviewTab))
{
overviewTabTimer.Start();
return;
}
if (Tabs.SelectedTab.Equals(RegionsStateTab))
{
regionsStateTabTimer.Start();
return;
}
if (Tabs.SelectedTab.Equals(ResidentListTab))
{
residentListTabTimer.Start();
return;
}
if (Tabs.SelectedTab.Equals(EstateTopTab))
{
estateTopTabTimer.Start();
return;
}
if (Tabs.SelectedTab.Equals(EstateTexturesTab))
{
estateTexturesTabTimer.Start();
}
}));
}
private void RequestFilterEstateList(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
Regex estateListRowRegex;
switch (!string.IsNullOrEmpty(EstateListFilter.Text))
{
case true:
estateListRowRegex = new Regex(EstateListFilter.Text, RegexOptions.Compiled);
break;
default:
estateListRowRegex = new Regex(@".+?", RegexOptions.Compiled);
break;
}
foreach (DataGridViewRow estateListRow in EstateListGridView.Rows.AsParallel().Cast<DataGridViewRow>())
{
estateListRow.Visible =
estateListRowRegex.IsMatch(estateListRow.Cells["EstateListName"].Value.ToString());
}
}));
}
private void EstateListSelected(object sender, EventArgs e)
{
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
EstateListsResidentsGroup.Enabled = false;
EstateListsGroupsGroup.Enabled = false;
queryEstateList = false;
break;
}
}));
if (!queryEstateList) return;
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
// Disable controls.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
EstateListsResidentsGroup.Enabled = false;
EstateListsGroupsGroup.Enabled = false;
}));
// Get the selected estate list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate list.");
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
.Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
{
vassalForm.Invoke(
(MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { vassalForm.StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable controls
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.RegionTeleportGroup.Enabled = true;
switch (selectedEstateListType)
{
case "ban":
case "manager":
case "user":
EstateListsResidentsGroup.Enabled = true;
EstateListsGroupsGroup.Enabled = false;
break;
case "group":
EstateListsResidentsGroup.Enabled = false;
EstateListsGroupsGroup.Enabled = true;
break;
}
}));
}
})
{IsBackground = true}.Start();
}
private void RequestRemoveEstateListMember(object sender, EventArgs e)
{
// Get the estate list type.
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
if (vassalForm.EstateListSelectBox.SelectedItem == null)
{
queryEstateList = false;
return;
}
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
queryEstateList = false;
break;
}
}));
// If not estate list type is selected then return.
if (!queryEstateList) return;
// Enqueue all the regions to restart.
Queue<UUID> estateListMembersQueue = new Queue<UUID>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow estateListRow in
EstateListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
UUID estateListMemberUUID;
if (!UUID.TryParse(estateListRow.Cells["EstateListUUID"].Value.ToString(),
out estateListMemberUUID))
continue;
estateListMembersQueue.Enqueue(estateListMemberUUID);
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (estateListMembersQueue.Count.Equals(0)) return;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
RemoveEstateListMemberButton.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
UUID memberUUID = UUID.Zero;
do
{
try
{
memberUUID = estateListMembersQueue.Dequeue();
// Remove the agent or group from the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType},
{"action", "remove"},
{selectedEstateListType.Equals("group") ? "target" : "agent", memberUUID.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to remove member");
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
int i in
EstateListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(
o =>
o.Cells["EstateListUUID"].Value.ToString()
.Equals(memberUUID.ToString(),
StringComparison.OrdinalIgnoreCase)).Select(o => o.Index)
)
{
EstateListGridView.Rows.RemoveAt(i);
}
}));
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + memberUUID; }));
}
} while (!estateListMembersQueue.Count.Equals(0));
}
catch (Exception)
{
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable teleports and enable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
RemoveEstateListMemberButton.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestEstateListsAddResident(object sender, EventArgs e)
{
// Get the estate list type.
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
queryEstateList = false;
break;
}
}));
// If not estate list type is selected then return.
if (!queryEstateList) return;
string firstName = string.Empty;
string lastName = string.Empty;
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (string.IsNullOrEmpty(EstateListsResidentFirstName.Text))
{
case true:
EstateListsResidentFirstName.BackColor = Color.MistyRose;
return;
default:
EstateListsResidentFirstName.BackColor = Color.Empty;
break;
}
firstName = EstateListsResidentFirstName.Text;
switch (string.IsNullOrEmpty(EstateListsResidentLastName.Text))
{
case true:
EstateListsResidentLastName.BackColor = Color.MistyRose;
return;
default:
EstateListsResidentLastName.BackColor = Color.Empty;
break;
}
lastName = EstateListsResidentLastName.Text;
}));
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName)) return;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
EstateListsResidentsGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
// Add the resident to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType},
{"action", "add"},
{"firstname", firstName},
{"lastname", lastName}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to add resident");
// Retrieve the estate list for updates.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate list.");
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
.Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
{
vassalForm.Invoke(
(MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
}
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + firstName + @" " + lastName; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable teleports and enable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
EstateListsResidentsGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestEstateListsAddGroup(object sender, EventArgs e)
{
// Get the estate list type.
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
queryEstateList = false;
break;
}
}));
// If not estate list type is selected then return.
if (!queryEstateList) return;
string target = string.Empty;
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (string.IsNullOrEmpty(EstateListsAddGroupBox.Text))
{
case true:
EstateListsAddGroupBox.BackColor = Color.MistyRose;
return;
default:
EstateListsAddGroupBox.BackColor = Color.Empty;
break;
}
target = EstateListsAddGroupBox.Text;
}));
if (string.IsNullOrEmpty(target)) return;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
EstateListsGroupsGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType},
{"action", "add"},
{"target", target}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to add group");
// Retrieve the estate list for updates.
result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate list.");
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
.Select(x => x.Select(v => v.Value).ToList()).Where(x => x.Count.Equals(2)))
{
vassalForm.Invoke(
(MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable teleports and enable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
EstateListsGroupsGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestRegionDebugApply(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
ApplyRegionDebugButton.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
bool scripts = false;
bool collisons = false;
bool physics = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
scripts = RegionDebugScriptsBox.Checked;
collisons = RegionDebugCollisionsBox.Checked;
physics = RegionDebugPhysicsBox.Checked;
}));
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregiondebug"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"scripts", scripts.ToString()},
{"collisions", collisons.ToString()},
{"physics", physics.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to set region debug");
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
}
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
ApplyRegionDebugButton.Enabled = true;
}));
})
{IsBackground = true}.Start();
}
private void RequestApplyRegionInfo(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
ApplyRegionInfoButton.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
bool terraform = false;
bool fly = false;
bool damage = false;
bool resell = false;
bool push = false;
bool parcel = false;
bool mature = false;
uint agentLimit = 20;
double objectBonus = 2.0;
bool run = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
terraform = RegionInfoTerraformBox.Checked;
fly = RegionInfoFlyBox.Checked;
damage = RegionInfoDamageBox.Checked;
resell = RegioninfoResellBox.Checked;
push = RegionInfoPushBox.Checked;
parcel = RegionInfoParcelBox.Checked;
mature = RegionInfoMatureBox.Checked;
switch (!uint.TryParse(RegionInfoAgentLimitBox.Text, out agentLimit))
{
case true:
RegionInfoAgentLimitBox.BackColor = Color.MistyRose;
return;
default:
RegionInfoAgentLimitBox.BackColor = Color.Empty;
run = true;
break;
}
switch (!double.TryParse(RegionInfoObjectBonusBox.Text, out objectBonus))
{
case true:
RegionInfoObjectBonusBox.BackColor = Color.MistyRose;
return;
default:
RegionInfoAgentLimitBox.BackColor = Color.Empty;
break;
}
run = true;
}));
if (!run) return;
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregioninfo"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"terraform", terraform.ToString()},
{"fly", fly.ToString()},
{"damage", damage.ToString()},
{"resell", resell.ToString()},
{"push", push.ToString()},
{"parcel", parcel.ToString()},
{"mature", mature.ToString()},
{"limit", agentLimit.ToString(Utils.EnUsCulture)},
{"bonus", objectBonus.ToString(Utils.EnUsCulture)}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to set region info");
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
}
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
ApplyRegionInfoButton.Enabled = true;
}));
})
{IsBackground = true}.Start();
}
private void RequestEstateTexturesApply(object sender, EventArgs e)
{
List<UUID> groundTextureUUIDs = new List<UUID>();
vassalForm.Invoke((MethodInvoker) (() =>
{
UUID textureUUID;
switch (!UUID.TryParse(RegionTexturesLowUUIDApplyBox.Text, out textureUUID))
{
case true:
RegionTexturesLowUUIDApplyBox.BackColor = Color.MistyRose;
return;
default:
RegionTexturesLowUUIDApplyBox.BackColor = Color.Empty;
break;
}
groundTextureUUIDs.Add(textureUUID);
switch (!UUID.TryParse(RegionTexturesMiddleLowUUIDApplyBox.Text, out textureUUID))
{
case true:
RegionTexturesMiddleLowUUIDApplyBox.BackColor = Color.MistyRose;
return;
default:
RegionTexturesMiddleLowUUIDApplyBox.BackColor = Color.Empty;
break;
}
groundTextureUUIDs.Add(textureUUID);
switch (!UUID.TryParse(RegionTexturesMiddleHighUUIDApplyBox.Text, out textureUUID))
{
case true:
RegionTexturesMiddleHighUUIDApplyBox.BackColor = Color.MistyRose;
return;
default:
RegionTexturesMiddleHighUUIDApplyBox.BackColor = Color.Empty;
break;
}
groundTextureUUIDs.Add(textureUUID);
switch (!UUID.TryParse(RegionTexturesHighUUIDApplyBox.Text, out textureUUID))
{
case true:
RegionTexturesHighUUIDApplyBox.BackColor = Color.MistyRose;
return;
default:
RegionTexturesHighUUIDApplyBox.BackColor = Color.Empty;
break;
}
groundTextureUUIDs.Add(textureUUID);
}));
if (!groundTextureUUIDs.Count.Equals(4)) return;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
GroundTexturesGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
// Set the debug settings.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregionterraintextures"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"data", CSV.FromEnumerable(groundTextureUUIDs.Select(o => o.ToString()))}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to apply estate ground textures");
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
}
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
GroundTexturesGroup.Enabled = true;
}));
})
{IsBackground = true};
}
private void RequestDownloadRegionTexture(object sender, EventArgs e)
{
string textureName = string.Empty;
UUID textureUUID = UUID.Zero;
bool run = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
Button button = sender as Button;
if (button == null)
{
run = false;
return;
}
textureName = button.Tag.ToString();
switch (textureName)
{
case "Low":
if (!UUID.TryParse(RegionTexturesLowUUIDBox.Text, out textureUUID))
{
run = false;
return;
}
goto case "MiddleLow";
case "MiddleLow":
if (!UUID.TryParse(RegionTexturesMiddleLowUUIDBox.Text, out textureUUID))
{
run = false;
return;
}
goto case "MiddleHigh";
case "MiddleHigh":
if (!UUID.TryParse(RegionTexturesMiddleHighUUIDBox.Text, out textureUUID))
{
run = false;
return;
}
goto case "High";
case "High":
if (!UUID.TryParse(RegionTexturesHighUUIDBox.Text, out textureUUID))
{
run = false;
return;
}
run = true;
break;
}
}));
if (!run) return;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
GroundTexturesGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "download"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"item", textureUUID.ToString()},
{"type", "Texture"},
{"format", "Png"}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
byte[] mapImageBytes = Convert.FromBase64String(wasInput(KeyValue.Get("data", result)));
Image mapImage;
using (MemoryStream memoryStream = new MemoryStream(mapImageBytes, 0, mapImageBytes.Length))
{
mapImage = Image.FromStream(memoryStream);
}
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.SavePNGFileDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.SavePNGFileDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"saving texture...";
vassalForm.StatusProgress.Value = 0;
mapImage.Save(file, ImageFormat.Png);
vassalForm.StatusText.Text = @"texture saved";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
finally
{
mapImage.Dispose();
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
}
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
GroundTexturesGroup.Enabled = true;
}));
})
{IsBackground = true}.Start();
}
private void RequestEstateListsAddGroupsFromCSV(object sender, EventArgs e)
{
// Get the estate list type.
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
queryEstateList = false;
break;
}
}));
// If not estate list type is selected then return.
if (!queryEstateList) return;
Queue<KeyValuePair<string, UUID>> targets = new Queue<KeyValuePair<string, UUID>>();
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (vassalForm.LoadCSVFile.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.LoadCSVFile.FileName;
try
{
vassalForm.StatusText.Text = @"loading group list...";
vassalForm.StatusProgress.Value = 0;
// import groups
UUID targetUUID;
foreach (KeyValuePair<string, UUID> target in
File.ReadAllLines(file)
.AsParallel()
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
UUID.TryParse(p.Last(), out targetUUID)
? targetUUID
: UUID.Zero))
{
targets.Enqueue(target);
}
vassalForm.StatusText.Text = @"group list loaded";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
break;
}
}));
if (targets.Count.Equals(0)) return;
int initialQueueSize = targets.Count;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
EstateListsGroupsGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
do
{
KeyValuePair<string, UUID> target = targets.Dequeue();
vassalForm.Invoke((MethodInvoker) (() =>
{
StatusText.Text = @"Adding to estate list: " + target.Key;
vassalForm.StatusProgress.Value =
Math.Min((int) (100d*Math.Abs(targets.Count - initialQueueSize)/initialQueueSize), 100);
}));
// Skip any items that already exist.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
run =
!EstateListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Any(o => o.Cells["EstateListUUID"].Value.ToString().Equals(target.Value.ToString()));
}));
if (!run) continue;
// Skip broken UUIDs.
if (target.Value.Equals(UUID.Zero)) continue;
try
{
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType},
{"action", "add"},
{"target", target.Value.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to add group");
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target.Value; }));
}
} while (!targets.Count.Equals(0));
// Retrieve the estate list.
try
{
// Retrieve the estate list for updates.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate list.");
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
.Select(x => x.Select(v => v.Value).ToList()))
{
vassalForm.BeginInvoke(
(MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable teleports and enable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
EstateListsGroupsGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestEstateListsAddResidentsFromCSV(object sender, EventArgs e)
{
// Get the estate list type.
string selectedEstateListType = string.Empty;
bool queryEstateList = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
if (vassalForm.EstateListSelectBox.SelectedItem == null) return;
selectedEstateListType = vassalForm.EstateListSelectBox.SelectedItem.ToString();
switch (
!string.IsNullOrEmpty(selectedEstateListType) && vassalForm.EstateListSelectBox.SelectedIndex != -1)
{
case true:
queryEstateList = true;
break;
default:
queryEstateList = false;
break;
}
}));
// If not estate list type is selected then return.
if (!queryEstateList) return;
Queue<KeyValuePair<string, UUID>> targets = new Queue<KeyValuePair<string, UUID>>();
vassalForm.Invoke((MethodInvoker) (() =>
{
switch (vassalForm.LoadCSVFile.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.LoadCSVFile.FileName;
try
{
vassalForm.StatusText.Text = @"loading residents list...";
vassalForm.StatusProgress.Value = 0;
// import groups
UUID targetUUID;
foreach (KeyValuePair<string, UUID> target in
File.ReadAllLines(file)
.AsParallel()
.Select(o => new List<string>(CSV.ToEnumerable(o)))
.Where(o => o.Count == 2)
.ToDictionary(o => o.First(),
p =>
UUID.TryParse(p.Last(), out targetUUID)
? targetUUID
: UUID.Zero))
{
targets.Enqueue(target);
}
vassalForm.StatusText.Text = @"residents list loaded";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
break;
}
}));
if (targets.Count.Equals(0)) return;
int initialQueueSize = targets.Count;
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
EstateListsResidentsGroup.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
do
{
KeyValuePair<string, UUID> target = targets.Dequeue();
vassalForm.Invoke((MethodInvoker) (() =>
{
StatusText.Text = @"Adding to estate list: " + target.Key;
vassalForm.StatusProgress.Value =
Math.Min((int) (100d*Math.Abs(targets.Count - initialQueueSize)/initialQueueSize), 100);
}));
// Skip any items that already exist.
bool run = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
run =
!EstateListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Any(o => o.Cells["EstateListUUID"].Value.ToString().Equals(target.Value.ToString()));
}));
if (!run) continue;
// Skip broken UUIDs.
if (target.Value.Equals(UUID.Zero)) continue;
try
{
// Add the group to the list.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType},
{"action", "add"},
{"agent", target.Value.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to add resident");
}
catch (Exception ex)
{
vassalForm.Invoke(
(MethodInvoker) (() => { StatusText.Text = ex.Message + @": " + target.Value; }));
}
} while (!targets.Count.Equals(0));
// Retrieve the estate list.
try
{
// Retrieve the estate list for updates.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "getestatelist"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"type", selectedEstateListType}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
if (!success)
throw new Exception("Could not retrieve estate list.");
vassalForm.Invoke((MethodInvoker) (() => { EstateListGridView.Rows.Clear(); }));
foreach (List<string> data in CSV.ToEnumerable(wasInput(KeyValue.Get("data", result)))
.Where(x => !string.IsNullOrEmpty(x))
.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/2)
.Select(x => x.Select(v => v.Value).ToList()))
{
vassalForm.BeginInvoke(
(MethodInvoker) (() => { EstateListGridView.Rows.Add(data.First(), data.Last()); }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Enable teleports and enable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
EstateListsResidentsGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestExportEstateList(object sender, EventArgs e)
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
switch (vassalForm.ExportCSVDialog.ShowDialog())
{
case DialogResult.OK:
string file = vassalForm.ExportCSVDialog.FileName;
new Thread(() =>
{
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
try
{
vassalForm.StatusText.Text = @"exporting...";
vassalForm.StatusProgress.Value = 0;
using (StreamWriter streamWriter = new StreamWriter(file, false, Encoding.UTF8))
{
foreach (DataGridViewRow estateListRow in EstateListGridView.Rows)
{
streamWriter.WriteLine(CSV.FromEnumerable(new[]
{
estateListRow.Cells["EstateListName"].Value.ToString(),
estateListRow.Cells["EstateListUUID"].Value.ToString()
}));
}
}
vassalForm.StatusText.Text = @"exported";
vassalForm.StatusProgress.Value = 100;
}
catch (Exception ex)
{
vassalForm.StatusText.Text = ex.Message;
}
}));
})
{IsBackground = true}.Start();
break;
}
}));
}
private void RequestTeleportHome(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
ResidentListTeleportHomeGroup.Enabled = false;
ResidentListBanGroup.Enabled = false;
RegionTeleportGroup.Enabled = false;
}));
// Enqueue all the agents to teleport home.
Queue<UUID> agentsQueue = new Queue<UUID>();
vassalForm.Invoke((MethodInvoker) (() =>
{
foreach (
DataGridViewRow residentListRow in
ResidentListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.Where(o => o.Selected || o.Cells.Cast<DataGridViewCell>().Any(p => p.Selected)))
{
UUID agentUUID;
if (!UUID.TryParse(residentListRow.Cells["ResidentListUUID"].Value.ToString(), out agentUUID))
continue;
agentsQueue.Enqueue(agentUUID);
}
}));
// If no rows were selected, enable teleports, the return button and return.
if (agentsQueue.Count.Equals(0))
{
vassalForm.Invoke((MethodInvoker) (() =>
{
ResidentListBanGroup.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
return;
}
new Thread(() =>
{
Monitor.Enter(ClientInstanceTeleportLock);
try
{
do
{
// Dequeue the first object.
UUID agentUUID = agentsQueue.Dequeue();
DataGridViewRow currentDataGridViewRow = null;
vassalForm.Invoke((MethodInvoker) (() =>
{
currentDataGridViewRow = vassalForm.ResidentListGridView.Rows.AsParallel()
.Cast<DataGridViewRow>()
.FirstOrDefault(
o =>
o.Cells["ResidentListUUID"].Value.ToString()
.Equals(agentUUID.ToString(), StringComparison.OrdinalIgnoreCase));
}));
if (currentDataGridViewRow == null) continue;
try
{
// Teleport the user home.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "estateteleportusershome"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"avatars", agentUUID.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade.");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved.");
switch (success)
{
case true:
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = @"Resident teleported home.";
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightGreen;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = @"Resident teleported home.";
}
}));
break;
default:
throw new Exception("Unable to teleport resident home.");
}
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() =>
{
vassalForm.StatusText.Text = ex.Message;
currentDataGridViewRow.Selected = false;
currentDataGridViewRow.DefaultCellStyle.BackColor = Color.LightPink;
foreach (
DataGridViewCell cell in
currentDataGridViewRow.Cells.AsParallel().Cast<DataGridViewCell>())
{
cell.ToolTipText = ex.Message;
}
}));
}
} while (agentsQueue.Count.Equals(0));
}
catch (Exception)
{
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
// Allow teleports and enable button.
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
ResidentListTeleportHomeGroup.Enabled = true;
ResidentListBanGroup.Enabled = true;
RegionTeleportGroup.Enabled = true;
}));
}
})
{IsBackground = true}.Start();
}
private void RequestSetVariables(object sender, EventArgs e)
{
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = false;
SetTerrainVariablesButton.Enabled = false;
}));
new Thread(() =>
{
try
{
Monitor.Enter(ClientInstanceTeleportLock);
int waterHeight = 10;
int terrainRaiseLimit = 100;
int terrainLowerLimit = -100;
bool useEstateSun = true;
bool fixedSun = false;
int sunPosition = 18;
bool run = false;
vassalForm.Invoke((MethodInvoker) (() =>
{
useEstateSun = TerrainToolsUseEstateSunBox.Checked;
fixedSun = TerrainToolsFixedSunBox.Checked;
switch (!int.TryParse(TerrainToolsWaterHeightBox.Text, out waterHeight))
{
case true:
TerrainToolsWaterHeightBox.BackColor = Color.MistyRose;
return;
default:
TerrainToolsWaterHeightBox.BackColor = Color.Empty;
break;
}
switch (!int.TryParse(TerrainToolsTerrainRaiseLimitBox.Text, out terrainRaiseLimit))
{
case true:
TerrainToolsTerrainRaiseLimitBox.BackColor = Color.MistyRose;
return;
default:
TerrainToolsTerrainRaiseLimitBox.BackColor = Color.Empty;
break;
}
switch (!int.TryParse(TerrainToolsTerrainLowerLimitBox.Text, out terrainLowerLimit))
{
case true:
TerrainToolsTerrainLowerLimitBox.BackColor = Color.MistyRose;
return;
default:
TerrainToolsTerrainLowerLimitBox.BackColor = Color.Empty;
break;
}
switch (!int.TryParse(TerrainToolsSunPositionBox.Text, out sunPosition))
{
case true:
TerrainToolsSunPositionBox.BackColor = Color.MistyRose;
return;
default:
TerrainToolsSunPositionBox.BackColor = Color.Empty;
break;
}
run = true;
}));
if (!run) return;
// Set the terrain variables.
string result = wasPOST(vassalConfiguration.HTTPServerURL,
KeyValue.Escape(new Dictionary<string, string>
{
{"command", "setregionterrainvariables"},
{"group", vassalConfiguration.Group},
{"password", vassalConfiguration.Password},
{"waterheight", waterHeight.ToString()},
{"terrainraiselimit", terrainRaiseLimit.ToString()},
{"terrainlowerlimit", terrainLowerLimit.ToString()},
{"useestatesun", useEstateSun.ToString()},
{"fixedsun", fixedSun.ToString()},
{"sunposition", sunPosition.ToString()}
}, wasOutput), vassalConfiguration.DataTimeout);
if (string.IsNullOrEmpty(result))
throw new Exception("Error communicating with Corrade");
bool success;
if (!bool.TryParse(wasInput(KeyValue.Get("success", result)), out success))
throw new Exception("No success status could be retrieved");
if (!success)
throw new Exception("Unable to set region variables");
}
catch (Exception ex)
{
vassalForm.Invoke((MethodInvoker) (() => { StatusText.Text = ex.Message; }));
}
finally
{
Monitor.Exit(ClientInstanceTeleportLock);
}
// Block teleports and disable button.
vassalForm.Invoke((MethodInvoker) (() =>
{
RegionTeleportGroup.Enabled = true;
SetTerrainVariablesButton.Enabled = true;
}));
})
{IsBackground = true}.Start();
}
private void ReconnectRequested(object sender, EventArgs e)
{
// Spawn a thread to check Corrade's connection status.
new Thread(() =>
{
TcpClient tcpClient = new TcpClient();
try
{
Uri uri = new Uri(vassalConfiguration.HTTPServerURL);
tcpClient.Connect(uri.Host, uri.Port);
// port open
vassalForm.BeginInvoke((MethodInvoker) (() => { vassalForm.Tabs.Enabled = true; }));
// set the loading spinner
if (vassalForm.RegionAvatarsMap.Image == null)
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
Stream file =
thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif");
switch (file != null)
{
case true:
vassalForm.BeginInvoke((MethodInvoker) (() =>
{
vassalForm.RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage;
vassalForm.RegionAvatarsMap.Image = Image.FromStream(file);
vassalForm.RegionAvatarsMap.Refresh();
}));
break;
}
}
}
catch (Exception)
{
// port closed
vassalForm.BeginInvoke((MethodInvoker) (() => { vassalForm.Tabs.Enabled = false; }));
}
})
{IsBackground = true}.Start();
}
/// <summary>
/// Linden constants.
/// </summary>
public struct LINDEN_CONSTANTS
{
public struct ALERTS
{
public const string NO_ROOM_TO_SIT_HERE = @"No room to sit here, try another spot.";
public const string UNABLE_TO_SET_HOME =
@"You can only set your 'Home Location' on your land or at a mainland Infohub.";
public const string HOME_SET = @"Home position set.";
}
public struct ASSETS
{
public struct NOTECARD
{
public const string NEWLINE = "\n";
public const uint MAXIMUM_BODY_LENTH = 65536;
}
}
public struct AVATARS
{
public const uint SET_DISPLAY_NAME_SUCCESS = 200;
public const string LASTNAME_PLACEHOLDER = @"Resident";
public const uint MAXIMUM_DISPLAY_NAME_CHARACTERS = 31;
public const uint MINIMUM_DISPLAY_NAME_CHARACTERS = 1;
public const uint MAXIMUM_NUMBER_OF_ATTACHMENTS = 38;
public struct PROFILE
{
public const uint SECOND_LIFE_TEXT_SIZE = 510;
public const uint FIRST_LIFE_TEXT_SIZE = 253;
}
public struct PICKS
{
public const uint MAXIMUM_PICKS = 10;
public const uint MAXIMUM_PICK_DESCRIPTION_SIZE = 1022;
}
public struct CLASSIFIEDS
{
public const uint MAXIMUM_CLASSIFIEDS = 100;
}
}
public struct PRIMITIVES
{
public const uint MAXIMUM_NAME_SIZE = 63;
public const uint MAXIMUM_DESCRIPTION_SIZE = 127;
public const double MAXIMUM_REZ_HEIGHT = 4096.0;
public const double MINIMUM_SIZE_X = 0.01;
public const double MINIMUM_SIZE_Y = 0.01;
public const double MINIMUM_SIZE_Z = 0.01;
public const double MAXIMUM_SIZE_X = 64.0;
public const double MAXIMUM_SIZE_Y = 64.0;
public const double MAXIMUM_SIZE_Z = 64.0;
}
public struct OBJECTS
{
public const uint MAXIMUM_PRIMITIVE_COUNT = 256;
}
public struct DIRECTORY
{
public struct EVENT
{
public const uint SEARCH_RESULTS_COUNT = 200;
}
public struct GROUP
{
public const uint SEARCH_RESULTS_COUNT = 100;
}
public struct LAND
{
public const uint SEARCH_RESULTS_COUNT = 100;
}
public struct PEOPLE
{
public const uint SEARCH_RESULTS_COUNT = 100;
}
}
public struct ESTATE
{
public const uint REGION_RESTART_DELAY = 120;
public const uint MAXIMUM_BAN_LIST_LENGTH = 500;
public const uint MAXIMUM_GROUP_LIST_LENGTH = 63;
public const uint MAXIMUM_USER_LIST_LENGTH = 500;
public const uint MAXIMUM_MANAGER_LIST_LENGTH = 10;
public struct MESSAGES
{
public const string REGION_RESTART_MESSAGE = @"restart";
}
}
public struct PARCELS
{
public const double MAXIMUM_AUTO_RETURN_TIME = 999999;
public const uint MINIMUM_AUTO_RETURN_TIME = 0;
public const uint MAXIMUM_NAME_LENGTH = 63;
public const uint MAXIMUM_DESCRIPTION_LENGTH = 255;
}
public struct GRID
{
public const string SECOND_LIFE = @"Second Life";
public const string TIME_ZONE = @"Pacific Standard Time";
}
public struct CHAT
{
public const uint MAXIMUM_MESSAGE_LENGTH = 1024;
}
public struct GROUPS
{
public const uint MAXIMUM_NUMBER_OF_ROLES = 10;
public const string EVERYONE_ROLE_NAME = @"Everyone";
public const uint MAXIMUM_GROUP_NAME_LENGTH = 35;
public const uint MAXIMUM_GROUP_TITLE_LENGTH = 20;
}
public struct NOTICES
{
public const uint MAXIMUM_NOTICE_MESSAGE_LENGTH = 512;
}
public struct LSL
{
public const string CSV_DELIMITER = @", ";
public const float SENSOR_RANGE = 96;
public const string DATE_TIME_STAMP = @"yyy-MM-ddTHH:mm:ss.ffffffZ";
}
public struct REGION
{
public const float TELEPORT_MINIMUM_DISTANCE = 1;
public const float DEFAULT_AGENT_LIMIT = 40;
public const float DEFAULT_OBJECT_BONUS = 1;
public const bool DEFAULT_FIXED_SUN = false;
public const float DEFAULT_TERRAIN_LOWER_LIMIT = -4;
public const float DEFAULT_TERRAIN_RAISE_LIMIT = 4;
public const bool DEFAULT_USE_ESTATE_SUN = true;
public const float DEFAULT_WATER_HEIGHT = 20;
public const float SUNRISE = 6;
}
public struct VIEWER
{
public const float MAXIMUM_DRAW_DISTANCE = 4096;
}
public struct TELEPORTS
{
public struct THROTTLE
{
public const uint MAX_TELEPORTS = 10;
public const uint GRACE_SECONDS = 15;
}
}
}
/// <summary>
/// Constants used by Corrade.
/// </summary>
public struct VASSAL_CONSTANTS
{
/// <summary>
/// Copyright.
/// </summary>
public const string COPYRIGHT = @"(c) Copyright 2013 Wizardry and Steamworks";
public const string WIZARDRY_AND_STEAMWORKS = @"Wizardry and Steamworks";
public const string VASSAL = @"Vassal";
public const string WIZARDRY_AND_STEAMWORKS_WEBSITE = @"http://grimore.org";
/// <summary>
/// Vassal version.
/// </summary>
public static readonly string VASSAL_VERSION = Assembly.GetEntryAssembly().GetName().Version.ToString();
/// <summary>
/// Corrade user agent.
/// </summary>
public static readonly string USER_AGENT =
$"{VASSAL}/{VASSAL_VERSION} ({WIZARDRY_AND_STEAMWORKS_WEBSITE})";
/// <summary>
/// Vassal compile date.
/// </summary>
public static readonly string VASSAL_COMPILE_DATE = new DateTime(2000, 1, 1).Add(new TimeSpan(
TimeSpan.TicksPerDay*Assembly.GetEntryAssembly().GetName().Version.Build + // days since 1 January 2000
TimeSpan.TicksPerSecond*2*Assembly.GetEntryAssembly().GetName().Version.Revision)).ToLongDateString();
/// <summary>
/// Vassal configuration file.
/// </summary>
public static readonly string VASSAL_CONFIGURATION_FILE = @"Vassal.ini";
/// <summary>
/// Vassal regions file.
/// </summary>
public static readonly string VASSAL_REGIONS = @"Regions.csv";
/// <summary>
/// Conten-types that Corrade can send and receive.
/// </summary>
public struct CONTENT_TYPE
{
public const string TEXT_PLAIN = @"text/plain";
public const string WWW_FORM_URLENCODED = @"application/x-www-form-urlencoded";
}
}
#region CRYPTOGRAPHY
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.