/Vassal/Vassal/VassalForm.cs |
@@ -10,9 +10,11 @@ |
using System.ComponentModel; |
using System.Data; |
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; |
@@ -29,15 +31,211 @@ |
public partial class Vassal : Form |
{ |
public static System.Timers.Timer overviewTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); |
public static System.Timers.Timer residentListTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); |
public static System.Timers.Timer topScriptsTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); |
public static System.Timers.Timer topCollidersTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); |
public static System.Timers.Timer regionsStateTabTimer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); |
public static volatile int regionsStateCheckIndex = 0; |
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> |
/// 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; |
} |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
private static double wasMapValueToRange(double value, double xMin, double xMax, double yMin, double yMax) |
{ |
return yMin + ( |
( |
yMax - yMin |
) |
* |
( |
value - xMin |
) |
/ |
( |
xMax - xMin |
) |
); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary>RFC1738 URL Escapes a string</summary> |
/// <param name="data">a string to escape</param> |
/// <returns>an RFC1738 escaped string</returns> |
@@ -980,7 +1178,7 @@ |
{ |
case true: |
selectedRegionName = listViewItem.Text; |
selectedRegionPosition = (Vector3)listViewItem.Tag; |
selectedRegionPosition = (Vector3) listViewItem.Tag; |
startTeleport = true; |
break; |
default: |
@@ -990,10 +1188,10 @@ |
})); |
|
if (!startTeleport) return; |
|
|
|
// Announce teleport. |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.RegionTeleportGroup.Enabled = false; |
vassalForm.StatusProgress.Value = 0; |
@@ -1078,7 +1276,7 @@ |
finally |
{ |
Monitor.Exit(ClientInstanceTeleportLock); |
vassalForm.Invoke((MethodInvoker) (() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
vassalForm.StatusProgress.Value = 100; |
vassalForm.RegionTeleportGroup.Enabled = true; |
@@ -1097,6 +1295,8 @@ |
})); |
break; |
} |
// Clear the resident list table. |
ResidentListGridView.Rows.Clear(); |
// Clear the top scripts table. |
TopScriptsGridView.Rows.Clear(); |
// Clear the top colliders table. |
@@ -1122,8 +1322,8 @@ |
Objects.Enabled = false; |
})); |
} |
}).Start(); |
|
}) |
{IsBackground = true}.Start(); |
} |
|
private void SettingsRequested(object sender, EventArgs e) |
@@ -1140,6 +1340,7 @@ |
// Disable estate manager tabs since we will enable these dynamically. |
TopScriptsTab.Enabled = false; |
TopCollidersTab.Enabled = false; |
ResidentListBanGroup.Enabled = false; |
|
// Get the configuration file settings if it exists. |
if (File.Exists(VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE)) |
@@ -1150,6 +1351,40 @@ |
RegionRestartDelayBox.Text = vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture); |
} |
|
// Spawn a thread to check Corrade's connection status. |
new Thread(() => |
{ |
TcpClient tcpClient = new TcpClient(); |
try |
{ |
System.Uri uri = new System.Uri(vassalConfiguration.HTTPServerURL); |
tcpClient.Connect(uri.Host, uri.Port); |
// port open |
vassalForm.BeginInvoke((MethodInvoker) (() => { Tabs.Enabled = true; })); |
// set the loading spinner |
Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); |
System.IO.Stream file = |
thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif"); |
switch (file != null) |
{ |
case true: |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage; |
RegionAvatarsMap.Image = Image.FromStream(file); |
RegionAvatarsMap.Refresh(); |
})); |
break; |
} |
} |
catch (Exception) |
{ |
// port closed |
vassalForm.BeginInvoke((MethodInvoker) (() => { Tabs.Enabled = false; })); |
} |
}) |
{IsBackground = true}.Start(); |
|
// Get all the regions if they exist. |
if (File.Exists(VASSAL_CONSTANTS.VASSAL_REGIONS)) |
{ |
@@ -1174,24 +1409,13 @@ |
{ |
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..."); |
} |
} |
|
// Set the map image to the loading spinner. |
Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly(); |
System.IO.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; |
} |
|
// Start the overview timer. |
overviewTabTimer.Elapsed += (o, p) => |
{ |
@@ -1200,12 +1424,7 @@ |
|
try |
{ |
// Do not do anything in case the tab is not selected. |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
if (!Tabs.SelectedTab.Equals(OverviewTab)) |
throw new Exception(); |
})); |
// Always run the overview regardless which tab is active. |
|
// Get the statistics. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
@@ -1240,7 +1459,7 @@ |
if (data.Count.Equals(0)) |
throw new Exception(); |
|
vassalForm.Invoke((MethodInvoker) (() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
// Drop access to features if we are not estate managers. |
bool isEstateManager; |
@@ -1251,10 +1470,12 @@ |
case true: // we are an estate manager |
TopScriptsTab.Enabled = true; |
TopCollidersTab.Enabled = true; |
ResidentListBanGroup.Enabled = true; |
break; |
default: |
TopScriptsTab.Enabled = false; |
TopCollidersTab.Enabled = false; |
ResidentListBanGroup.Enabled = false; |
break; |
} |
|
@@ -1355,7 +1576,7 @@ |
} |
mapGraphics.DrawImage(mapImage, new Point(0, 0)); |
|
vassalForm.Invoke((MethodInvoker) (() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
RegionAvatarsMap.SizeMode = PictureBoxSizeMode.StretchImage; |
RegionAvatarsMap.Image = mapImage; |
@@ -1374,21 +1595,113 @@ |
}; |
overviewTabTimer.Start(); |
|
// Start the top scores timer. |
topScriptsTabTimer.Elapsed += (o, p) => |
regionsStateTabTimer.Elapsed += (o, p) => |
{ |
if (!Monitor.TryEnter(ClientInstanceTeleportLock)) |
// Do not do anything in case the tab is not selected. |
bool run = false; |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
run = Tabs.SelectedTab.Equals(RegionsStateTab); |
})); |
if (!run) return; |
|
if (!Monitor.TryEnter(RegionsStateCheckLock)) |
return; |
|
try |
{ |
// Do not do anything in case the tab is not selected. |
string regionName = string.Empty; |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
if (!Tabs.SelectedTab.Equals(TopScriptsTab)) |
throw new Exception(); |
regionName = |
RegionsStateGridView.Rows[regionsStateCheckIndex].Cells["RegionsStateRegionName"].Value |
.ToString(); |
})); |
|
if (string.IsNullOrEmpty(regionName)) |
throw new Exception(); |
|
// Get the region status. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "getgridregiondata"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"region", regionName}, |
{"data", "Access"} |
}), vassalConfiguration.DataTimeout); |
|
bool success; |
if (string.IsNullOrEmpty(result) || |
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) |
throw new Exception(); |
|
List<string> data = wasCSVToEnumerable(wasInput(wasKeyValueGet("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(Vassal.LINDEN_CONSTANTS.LSL.DATE_TIME_STAMP); |
|
})); |
} |
catch (Exception) |
{ |
|
} |
finally |
{ |
Monitor.Exit(RegionsStateCheckLock); |
++regionsStateCheckIndex; |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
if (regionsStateCheckIndex >= RegionsStateGridView.Rows.Count) |
{ |
regionsStateCheckIndex = 0; |
} |
})); |
} |
}; |
regionsStateTabTimer.Start(); |
|
// Start the top scores timer. |
topScriptsTabTimer.Elapsed += (o, p) => |
{ |
// Do not do anything in case the tab is not selected. |
bool run = false; |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
run = Tabs.SelectedTab.Equals(TopScriptsTab); |
})); |
if (!run) return; |
|
if (!Monitor.TryEnter(ClientInstanceTeleportLock)) |
return; |
|
try |
{ |
// Get the statistics. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
@@ -1463,18 +1776,19 @@ |
// Start the top colliders timer. |
topCollidersTabTimer.Elapsed += (o, p) => |
{ |
// Do not do anything in case the tab is not selected. |
bool run = false; |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
run = Tabs.SelectedTab.Equals(TopCollidersTab); |
})); |
if (!run) return; |
|
if (!Monitor.TryEnter(ClientInstanceTeleportLock)) |
return; |
|
try |
{ |
// Do not do anything in case the tab is not selected. |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
if (!Tabs.SelectedTab.Equals(TopCollidersTab)) |
throw new Exception(); |
})); |
|
// Get the statistics. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
@@ -1528,7 +1842,8 @@ |
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], |
TopCollidersGridView.Rows.Add(dataComponents[0], dataComponents[1], |
dataComponents[2], |
dataComponents[3], dataComponents[4]); |
break; |
} |
@@ -1546,6 +1861,92 @@ |
} |
}; |
topCollidersTabTimer.Start(); |
|
// Start the resident list timer. |
residentListTimer.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) return; |
|
if (!Monitor.TryEnter(ClientInstanceTeleportLock)) |
return; |
|
try |
{ |
// Get the avatar positions. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "getavatarpositions"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"entity", "region"} |
}), vassalConfiguration.DataTimeout); |
|
bool success; |
if (string.IsNullOrEmpty(result) || |
!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) |
throw new Exception(); |
|
HashSet<List<string>> data = |
new HashSet<List<string>>(wasCSVToEnumerable(wasInput(wasKeyValueGet("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) |
{ |
|
} |
finally |
{ |
Monitor.Exit(ClientInstanceTeleportLock); |
} |
}; |
residentListTimer.Start(); |
} |
|
private void RequestedEditRegions(object sender, EventArgs e) |
@@ -1602,7 +2003,7 @@ |
} |
})); |
}) |
{IsBackground = true, Priority = ThreadPriority.Normal}.Start(); |
{IsBackground = true}.Start(); |
break; |
} |
})); |
@@ -1649,7 +2050,7 @@ |
} |
})); |
}) |
{IsBackground = true, Priority = ThreadPriority.Normal}.Start(); |
{IsBackground = true}.Start(); |
break; |
} |
})); |
@@ -1685,7 +2086,7 @@ |
|
private void RequestFilterTopColliders(object sender, EventArgs e) |
{ |
vassalForm.BeginInvoke((MethodInvoker)(() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
Regex topCollidersRowRegex; |
switch (!string.IsNullOrEmpty(TopScriptsFilter.Text)) |
@@ -1697,7 +2098,8 @@ |
topCollidersRowRegex = new Regex(@".+?", RegexOptions.Compiled); |
break; |
} |
foreach (DataGridViewRow topCollidersRow in TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>()) |
foreach ( |
DataGridViewRow topCollidersRow in TopCollidersGridView.Rows.AsParallel().Cast<DataGridViewRow>()) |
{ |
topCollidersRow.Visible = |
topCollidersRowRegex.IsMatch(topCollidersRow.Cells["TopCollidersScore"].Value.ToString()) || |
@@ -1742,7 +2144,7 @@ |
// If no rows were selected, enable teleports, the return button and return. |
if (returnUUIDs.Count.Equals(0)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.ReturnTopScriptsButton.Enabled = true; |
RegionTeleportGroup.Enabled = true; |
@@ -1776,7 +2178,7 @@ |
{ |
currentRegionName = CurrentRegionName.Text; |
})); |
|
|
// Teleport to the object. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
@@ -1791,7 +2193,7 @@ |
|
if (string.IsNullOrEmpty(result)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Error communicating with Corrade."; |
})); |
@@ -1806,7 +2208,7 @@ |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"item", objectData.Key.ToString()}, |
{"range", "32" }, // maximal prim size = 64 - middle bounding box at half |
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half |
{"type", "ReturnToOwner"} |
}), vassalConfiguration.DataTimeout); |
|
@@ -1836,11 +2238,11 @@ |
{ |
vassalForm.StatusText.Text = @"Returned object: " + objectData.Key.ToString(); |
// Remove the row from the grid view. |
DataGridViewRow row = |
TopScriptsGridView.Rows.AsParallel() |
.Cast<DataGridViewRow>() |
.FirstOrDefault( |
o => o.Cells["TopScriptsUUID"].Value.Equals(objectData.Key.ToString())); |
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); |
@@ -1870,7 +2272,7 @@ |
} |
catch (Exception ex) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; |
})); |
@@ -1879,7 +2281,7 @@ |
{ |
Monitor.Exit(ClientInstanceTeleportLock); |
// Allow teleports and enable button. |
vassalForm.BeginInvoke((MethodInvoker)(() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
vassalForm.ReturnTopScriptsButton.Enabled = true; |
RegionTeleportGroup.Enabled = true; |
@@ -1892,7 +2294,7 @@ |
private void RequestReturnTopCollidersObjects(object sender, EventArgs e) |
{ |
// Block teleports and disable button. |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.ReturnTopCollidersButton.Enabled = false; |
RegionTeleportGroup.Enabled = false; |
@@ -1899,8 +2301,8 @@ |
})); |
|
// Enqueue all the UUIDs to return. |
Queue<KeyValuePair<UUID, Vector3>> returnUUIDs = new Queue<KeyValuePair<UUID, Vector3>>(); |
vassalForm.Invoke((MethodInvoker)(() => |
Queue<KeyValuePair<UUID, Vector3>> returnObjectUUIDQueue = new Queue<KeyValuePair<UUID, Vector3>>(); |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
foreach ( |
DataGridViewRow topCollidersRow in |
@@ -1911,16 +2313,17 @@ |
Vector3 objectPosition; |
UUID returnUUID; |
if (!UUID.TryParse(topCollidersRow.Cells["TopCollidersUUID"].Value.ToString(), out returnUUID) || |
!Vector3.TryParse(topCollidersRow.Cells["TopCollidersPosition"].Value.ToString(), out objectPosition)) |
!Vector3.TryParse(topCollidersRow.Cells["TopCollidersPosition"].Value.ToString(), |
out objectPosition)) |
continue; |
returnUUIDs.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition)); |
returnObjectUUIDQueue.Enqueue(new KeyValuePair<UUID, Vector3>(returnUUID, objectPosition)); |
} |
})); |
|
// If no rows were selected, enable teleports, the return button and return. |
if (returnUUIDs.Count.Equals(0)) |
if (returnObjectUUIDQueue.Count.Equals(0)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.ReturnTopCollidersButton.Enabled = true; |
RegionTeleportGroup.Enabled = true; |
@@ -1934,23 +2337,23 @@ |
|
try |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusProgress.Value = 0; |
})); |
int totalObjects = returnUUIDs.Count; |
int totalObjects = returnObjectUUIDQueue.Count; |
do |
{ |
// Dequeue the first object. |
KeyValuePair<UUID, Vector3> objectData = returnUUIDs.Dequeue(); |
KeyValuePair<UUID, Vector3> objectData = returnObjectUUIDQueue.Dequeue(); |
|
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Returning UUID: " + objectData.Key.ToString(); |
})); |
|
string currentRegionName = string.Empty; |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
currentRegionName = CurrentRegionName.Text; |
})); |
@@ -1969,7 +2372,7 @@ |
|
if (string.IsNullOrEmpty(result)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Error communicating with Corrade."; |
})); |
@@ -1984,13 +2387,13 @@ |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"item", objectData.Key.ToString()}, |
{"range", "32" }, // maximal prim size = 64 - middle bounding box at half |
{"range", "32"}, // maximal prim size = 64 - middle bounding box at half |
{"type", "ReturnToOwner"} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Error communicating with Corrade."; |
})); |
@@ -2000,7 +2403,7 @@ |
bool success; |
if (!bool.TryParse(wasInput(wasKeyValueGet("success", result)), out success)) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"No success status could be retrieved. "; |
})); |
@@ -2010,15 +2413,15 @@ |
switch (success) |
{ |
case true: |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Returned object: " + objectData.Key.ToString(); |
// Remove the row from the grid view. |
DataGridViewRow row = |
TopCollidersGridView.Rows.AsParallel() |
.Cast<DataGridViewRow>() |
.FirstOrDefault( |
o => o.Cells["TopCollidersUUID"].Value.Equals(objectData.Key.ToString())); |
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); |
@@ -2025,7 +2428,7 @@ |
})); |
break; |
case false: |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Could not return object " + objectData.Key.ToString() + |
@": " + |
@@ -2034,14 +2437,14 @@ |
break; |
} |
|
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusProgress.Value = |
Math.Min((int)(Math.Abs(returnUUIDs.Count - totalObjects) / |
(double)totalObjects), 100); |
Math.Min((int) (Math.Abs(returnObjectUUIDQueue.Count - totalObjects)/ |
(double) totalObjects), 100); |
})); |
} while (!returnUUIDs.Count.Equals(0)); |
vassalForm.Invoke((MethodInvoker)(() => |
} while (!returnObjectUUIDQueue.Count.Equals(0)); |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusProgress.Value = 100; |
})); |
@@ -2048,7 +2451,7 @@ |
} |
catch (Exception ex) |
{ |
vassalForm.Invoke((MethodInvoker)(() => |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Unexpected error: " + ex.Message; |
})); |
@@ -2057,7 +2460,7 @@ |
{ |
Monitor.Exit(ClientInstanceTeleportLock); |
// Allow teleports and enable button. |
vassalForm.BeginInvoke((MethodInvoker)(() => |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
vassalForm.ReturnTopScriptsButton.Enabled = true; |
RegionTeleportGroup.Enabled = true; |
@@ -2064,12 +2467,539 @@ |
})); |
} |
}) |
{ IsBackground = true }.Start(); |
{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, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "teleport"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"position", restartRegionData.Value.ToString()}, |
{"region", restartRegionData.Key}, |
{"fly", "True"} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
{ |
vassalForm.Invoke((MethodInvoker) (() => |
{ |
vassalForm.StatusText.Text = @"Error communicating with Corrade."; |
})); |
continue; |
} |
if (!bool.TryParse(wasInput(wasKeyValueGet("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."; |
})); |
Thread.Sleep(TimeSpan.FromSeconds(1).Milliseconds); |
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(wasKeyValueGet("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."; |
})); |
Thread.Sleep(10000); |
break; |
} |
break; |
} |
} while (!success && !(--teleportRetries).Equals(0)); |
|
if (!success) |
throw new Exception("Failed to teleport to region."); |
|
result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "getregiondata"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"data", "IsEstateManager"} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
throw new Exception("Error communicating with Corrade."); |
|
if (!bool.TryParse(wasInput(wasKeyValueGet("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 = wasCSVToEnumerable(wasInput(wasKeyValueGet("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, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "restartregion"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"action", "restart"}, |
{ |
"delay", vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture) |
} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
throw new Exception("Error communicating with Corrade."); |
|
if (!bool.TryParse(wasInput(wasKeyValueGet("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; |
} |
})); |
} |
} 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) (() => |
{ |
ResidentListBanGroup.Enabled = false; |
RegionTeleportGroup.Enabled = false; |
})); |
|
// Enqueue all the regions to restart. |
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; |
})); |
|
// Teleport to the region. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "setestatelist"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"type", "ban"}, |
{"action", "add"}, |
{"agent", agentUUID.ToString()}, |
{"all", alsoBan.ToString()} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
throw new Exception("Error communicating with Corrade."); |
|
bool success; |
if (!bool.TryParse(wasInput(wasKeyValueGet("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) (() => |
{ |
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 statistics. |
string result = wasPOST(vassalConfiguration.HTTPServerURL, |
wasKeyValueEscape(new Dictionary<string, string> |
{ |
{"command", "getterrainheight"}, |
{"group", vassalConfiguration.Group}, |
{"password", vassalConfiguration.Password}, |
{"entity", "region"} |
}), vassalConfiguration.DataTimeout); |
|
if (string.IsNullOrEmpty(result)) |
throw new Exception("Error communicating with Corrade."); |
|
bool success; |
if (!bool.TryParse(wasInput(wasKeyValueGet("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 wasCSVToEnumerable(wasInput(wasKeyValueGet("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((int) wasMapValueToRange(heights[256*x + y], 0, maxHeight, 0, 255), 0, 0)); |
} |
} |
Bitmap closureBitmap = (Bitmap)bitmap.Clone(); |
vassalForm.BeginInvoke((MethodInvoker) (() => |
{ |
switch (vassalForm.SaveTerrainFileDialog.ShowDialog()) |
{ |
case DialogResult.OK: |
string file = vassalForm.SaveTerrainFileDialog.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, Priority = ThreadPriority.Normal}.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(); |
} |
} |
} |