--- /dev/null
+// \r
+// Radegast Metaverse Client\r
+// Copyright (c) 2009, Radegast Development Team\r
+// All rights reserved.\r
+// \r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are met:\r
+// \r
+// * Redistributions of source code must retain the above copyright notice,\r
+// this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above copyright\r
+// notice, this list of conditions and the following disclaimer in the\r
+// documentation and/or other materials provided with the distribution.\r
+// * Neither the name of the application "Radegast", nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+// \r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// $Id: IMTextManager.cs 361 2009-10-24 15:04:57Z latifer $\r
+//\r
+using System;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Text;\r
+using System.Reflection;\r
+using OpenMetaverse;\r
+using OpenMetaverse.StructuredData;\r
+\r
+namespace Radegast\r
+{\r
+ public class ClientSignatures\r
+ {\r
+ public static Dictionary<UUID, string> Signatures { get; private set; }\r
+\r
+ static ClientSignatures()\r
+ {\r
+ Signatures = new Dictionary<UUID, string>();\r
+\r
+ try\r
+ {\r
+ OSDMap clients = (OSDMap)OSDParser.DeserializeLLSDXml(Properties.Resources.client_signatures);\r
+\r
+ foreach (KeyValuePair<string, OSD> kvp in clients)\r
+ {\r
+ UUID sig;\r
+ \r
+ if (UUID.TryParse(kvp.Key, out sig))\r
+ {\r
+ if (kvp.Value.Type == OSDType.Map)\r
+ {\r
+ OSDMap client = (OSDMap)kvp.Value;\r
+ if (client.ContainsKey("name"))\r
+ {\r
+ Signatures.Add(sig, client["name"].AsString());\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ catch \r
+ {\r
+ Logger.Log("Failed to parse client signatures.", Helpers.LogLevel.Warning);\r
+ }\r
+ }\r
+ }\r
+}\r
\r
public string InventoryCacheFileName { get { return Path.Combine(ClientDir, "inventory.cache"); } }\r
\r
- private string animCacheDir;\r
- public string AnimCacheDir { get { return animCacheDir; } }\r
-\r
private string globalLogFile;\r
public string GlobalLogFile { get { return globalLogFile; } }\r
\r
userDir = System.Environment.CurrentDirectory;\r
};\r
\r
- animCacheDir = Path.Combine(userDir, @"anim_cache");\r
globalLogFile = Path.Combine(userDir, Properties.Resources.ProgramName + ".log");\r
globalSettings = new Settings(Path.Combine(userDir, "settings.xml"));\r
}\r
private int n;\r
private List<FriendInfo> friends;\r
private FriendInfo friend;\r
+ private byte[] animData;\r
\r
public AnimDetail(RadegastInstance instance, Avatar av, UUID anim, int n)\r
{\r
\r
private void AnimDetail_Load(object sender, EventArgs e)\r
{\r
- if (File.Exists(instance.AnimCacheDir + "/" + anim + ".fail"))\r
+ if (Animations.ToDictionary().ContainsKey(anim))\r
{\r
Visible = false;\r
+ Dispose();\r
return;\r
}\r
\r
cbFriends.Items.Add(f);\r
}\r
\r
- if (File.Exists(instance.AnimCacheDir + "/" + anim + ".sla"))\r
- {\r
- pnlSave.Visible = true;\r
- return;\r
- }\r
-\r
-\r
instance.Client.Assets.RequestAsset(anim, AssetType.Animation, true, Assets_OnAssetReceived);\r
}\r
\r
{\r
try\r
{\r
- byte[] data = File.ReadAllBytes(instance.AnimCacheDir + "/" + anim + ".sla");\r
- File.WriteAllBytes(dlg.FileName, data);\r
+ File.WriteAllBytes(dlg.FileName, animData);\r
}\r
catch (Exception ex)\r
{\r
{\r
if (InvokeRequired)\r
{\r
- Invoke(new MethodInvoker(delegate()\r
- {\r
- Assets_OnAssetReceived(transfer, asset);\r
- }));\r
+ Invoke(new MethodInvoker(() => Assets_OnAssetReceived(transfer, asset)));\r
return;\r
}\r
\r
if (transfer.Success)\r
{\r
Logger.Log("Animation " + anim + " download success " + asset.AssetData.Length + " bytes.", Helpers.LogLevel.Debug);\r
- File.WriteAllBytes(instance.AnimCacheDir + "/" + anim + ".sla", asset.AssetData);\r
pnlSave.Visible = true;\r
+ animData = asset.AssetData;\r
}\r
else\r
{\r
Logger.Log("Animation " + anim + " download failed.", Helpers.LogLevel.Debug);\r
- FileStream f = File.Create(instance.AnimCacheDir + "/" + anim + ".fail");\r
- f.Close();\r
Visible = false;\r
+ Dispose();\r
}\r
}\r
\r
\r
private void btnSend_Click(object sender, EventArgs e)\r
{\r
- byte[] data = File.ReadAllBytes(instance.AnimCacheDir + "/" + anim + ".sla");\r
- instance.Client.Inventory.RequestCreateItemFromAsset(data, boxAnimName.Text, "(No description)", AssetType.Animation, InventoryType.Animation, instance.Client.Inventory.FindFolderForType(AssetType.Animation), On_ItemCreated);\r
+ if (animData == null) return;\r
+\r
+ instance.Client.Inventory.RequestCreateItemFromAsset(animData, boxAnimName.Text, "(No description)", AssetType.Animation, InventoryType.Animation, instance.Client.Inventory.FindFolderForType(AssetType.Animation), On_ItemCreated);\r
lblStatus.Text = "Uploading...";\r
cbFriends.Enabled = false;\r
}\r
if (disposing && (components != null)) {\r
components.Dispose();\r
}\r
+ \r
+ if (disposing)\r
+ {\r
+ foreach (System.Windows.Forms.Control c in Controls)\r
+ {\r
+ if (!c.IsDisposed)\r
+ c.Dispose();\r
+ }\r
+ }\r
base.Dispose(disposing);\r
}\r
\r
private Avatar av;\r
private List<UUID> seenAnim = new List<UUID>();\r
private int n = 0;\r
- private static bool checkedDir = false;\r
\r
public AnimTab(RadegastInstance instance, Avatar av)\r
{\r
\r
private void AnimTab_Load(object sender, EventArgs e)\r
{\r
- if (!checkedDir) {\r
- checkedDir = true;\r
- if (!Directory.Exists(instance.AnimCacheDir))\r
- {\r
- Directory.CreateDirectory(instance.AnimCacheDir);\r
- }\r
- }\r
}\r
}\r
}\r
{\r
components.Dispose();\r
}\r
+\r
+ if (disposing)\r
+ {\r
+ lock (tabs)\r
+ {\r
+ System.Collections.Generic.List<string> tabNames = new System.Collections.Generic.List<string>(tabs.Keys);\r
+ for (int i = 0; i < tabNames.Count; i++)\r
+ {\r
+ if (tabNames[i] != "chat")\r
+ ForceCloseTab(tabNames[i]);\r
+ }\r
+ ForceCloseTab("chat");\r
+ }\r
+ }\r
+\r
base.Dispose(disposing);\r
}\r
\r
if (tabs.ContainsKey("login"))\r
{\r
if (selectedTab.Name == "login")\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
ForceCloseTab("login");\r
}\r
\r
{\r
DisposeOnlineTabs();\r
\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
DisplayNotificationInChat("Logged out.");\r
\r
}\r
if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;\r
\r
DisposeOnlineTabs();\r
-\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
DisplayNotificationInChat("Disconnected: " + e.Message, ChatBufferTextStyle.Error);\r
}\r
\r
}\r
\r
/// <summary>\r
+ /// Make default tab (chat) active\r
+ /// </summary>\r
+ public void SelectDefaultTab()\r
+ {\r
+ if (TabExists("chat"))\r
+ tabs["chat"].Select();\r
+ }\r
+ /// <summary>\r
/// Displays notification in the main chat tab\r
/// </summary>\r
/// <param name="msg">Message to be printed in the chat tab</param>\r
/// </summary>\r
private void DisposeOnlineTabs()\r
{\r
- ForceCloseTab("voice");\r
-\r
- // Mono crashes if we try to open map for the second time\r
- if (!instance.MonoRuntime)\r
- ForceCloseTab("map");\r
- else\r
- tabs["map"].Hide();\r
-\r
- ForceCloseTab("search");\r
- ForceCloseTab("inventory");\r
- ForceCloseTab("groups");\r
- ForceCloseTab("friends");\r
+ lock (tabs)\r
+ {\r
+ ForceCloseTab("voice");\r
+\r
+ // Mono crashes if we try to open map for the second time\r
+ if (!instance.MonoRuntime)\r
+ ForceCloseTab("map");\r
+ else if (TabExists("map"))\r
+ tabs["map"].Hide();\r
+\r
+ ForceCloseTab("search");\r
+ ForceCloseTab("inventory");\r
+ ForceCloseTab("groups");\r
+ ForceCloseTab("friends");\r
+ }\r
}\r
\r
private void ForceCloseTab(string name)\r
if (selectedTab != null && selectedTab == tab)\r
{\r
tab.Deselect();\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
}\r
}\r
\r
{\r
RadegastTab tab = (RadegastTab)sender;\r
\r
- if (selectedTab != null && selectedTab == tab)\r
+ if (selectedTab != null && selectedTab == tab && tab.Name != "chat")\r
{\r
tab.Deselect();\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
}\r
\r
tabs.Remove(tab.Name);\r
{\r
if (!selectedTab.AllowDetach) return;\r
RadegastTab tab = selectedTab;\r
- tabs["chat"].Select();\r
+ SelectDefaultTab();\r
tab.Detach(instance);\r
}\r
\r
this.tmnuPrefs = new System.Windows.Forms.ToolStripMenuItem();\r
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();\r
this.tmnuExit = new System.Windows.Forms.ToolStripMenuItem();\r
+ this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\r
this.tbtnWorld = new System.Windows.Forms.ToolStripDropDownButton();\r
this.tmnuControlFly = new System.Windows.Forms.ToolStripMenuItem();\r
this.tmnuControlAlwaysRun = new System.Windows.Forms.ToolStripMenuItem();\r
this.tbtnMap = new System.Windows.Forms.ToolStripButton();\r
this.tbnObjects = new System.Windows.Forms.ToolStripButton();\r
this.lblTime = new System.Windows.Forms.ToolStripLabel();\r
- this.tbtnVoice = new System.Windows.Forms.ToolStripButton();\r
this.tbtnMedia = new System.Windows.Forms.ToolStripButton();\r
+ this.tbtnVoice = new System.Windows.Forms.ToolStripButton();\r
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();\r
this.tbtnHelp = new System.Windows.Forms.ToolStripDropDownButton();\r
this.keyboardShortcutsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\r
this.reconnectToolStripMenuItem,\r
this.tmnuPrefs,\r
this.toolStripMenuItem2,\r
- this.tmnuExit});\r
+ this.tmnuExit,\r
+ this.testToolStripMenuItem});\r
this.tbtnSLeek.Image = global::Radegast.Properties.Resources.computer_16;\r
this.tbtnSLeek.ImageTransparentColor = System.Drawing.Color.Magenta;\r
this.tbtnSLeek.Name = "tbtnSLeek";\r
this.tmnuExit.Text = "E&xit";\r
this.tmnuExit.Click += new System.EventHandler(this.tmnuExit_Click);\r
// \r
+ // testToolStripMenuItem\r
+ // \r
+ this.testToolStripMenuItem.Name = "testToolStripMenuItem";\r
+ this.testToolStripMenuItem.Size = new System.Drawing.Size(155, 22);\r
+ this.testToolStripMenuItem.Text = "Test";\r
+ this.testToolStripMenuItem.Visible = false;\r
+ this.testToolStripMenuItem.Click += new System.EventHandler(this.testToolStripMenuItem_Click);\r
+ // \r
// tbtnWorld\r
// \r
this.tbtnWorld.AutoToolTip = false;\r
this.lblTime.Size = new System.Drawing.Size(30, 22);\r
this.lblTime.Text = "--:--";\r
// \r
- // tbtnVoice\r
- // \r
- this.tbtnVoice.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
- this.tbtnVoice.Enabled = false;\r
- this.tbtnVoice.Image = ((System.Drawing.Image)(resources.GetObject("tbtnVoice.Image")));\r
- this.tbtnVoice.ImageTransparentColor = System.Drawing.Color.Magenta;\r
- this.tbtnVoice.Name = "tbtnVoice";\r
- this.tbtnVoice.Size = new System.Drawing.Size(40, 22);\r
- this.tbtnVoice.Text = "Voice";\r
- this.tbtnVoice.Click += new System.EventHandler(this.tbtnVoice_Click);\r
- // \r
// tbtnMedia\r
// \r
this.tbtnMedia.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
this.tbtnMedia.Visible = false;\r
this.tbtnMedia.Click += new System.EventHandler(this.tbtnMedia_Click);\r
// \r
+ // tbtnVoice\r
+ // \r
+ this.tbtnVoice.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\r
+ this.tbtnVoice.Enabled = false;\r
+ this.tbtnVoice.Image = ((System.Drawing.Image)(resources.GetObject("tbtnVoice.Image")));\r
+ this.tbtnVoice.ImageTransparentColor = System.Drawing.Color.Magenta;\r
+ this.tbtnVoice.Name = "tbtnVoice";\r
+ this.tbtnVoice.Size = new System.Drawing.Size(40, 22);\r
+ this.tbtnVoice.Text = "Voice";\r
+ this.tbtnVoice.Click += new System.EventHandler(this.tbtnVoice_Click);\r
+ // \r
// toolStripSeparator2\r
// \r
this.toolStripSeparator2.Name = "toolStripSeparator2";\r
public System.Windows.Forms.ToolStripMenuItem reconnectToolStripMenuItem;\r
private System.Windows.Forms.ToolStripMenuItem keyboardShortcutsToolStripMenuItem;\r
private System.Windows.Forms.ToolStripButton tbtnVoice;\r
+ public System.Windows.Forms.ToolStripMenuItem testToolStripMenuItem;\r
}\r
}\r
\r
using Radegast.Netcom;\r
using OpenMetaverse;\r
using OpenMetaverse.StructuredData;\r
+using OpenMetaverse.Assets;\r
\r
namespace Radegast\r
{\r
\r
private void DisplayAutoReconnectForm()\r
{\r
+ if (IsDisposed) return;\r
+\r
if (InvokeRequired)\r
{\r
BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));\r
))\r
{\r
Name = "Reconnect Delay Thread",\r
- IsBackground = false\r
+ IsBackground = true\r
}\r
).Start();\r
}\r
private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)\r
{\r
client.Assets.Cache.Clear();\r
- DirectoryInfo di = new DirectoryInfo(instance.AnimCacheDir);\r
- FileInfo[] files = di.GetFiles();\r
-\r
- int num = 0;\r
- foreach (FileInfo file in files)\r
- {\r
- file.Delete();\r
- ++num;\r
- }\r
-\r
- Logger.Log("Wiped out " + num + " files from the anim cache directory.", Helpers.LogLevel.Debug);\r
-\r
}\r
\r
private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)\r
}\r
}\r
}\r
+\r
+ // Menu item for testing out stuff\r
+ private void testToolStripMenuItem_Click(object sender, EventArgs e)\r
+ {\r
+ foreach (KeyValuePair<UUID, string> kvp in Sounds.ToDictionary())\r
+ {\r
+ client.Assets.RequestAsset(kvp.Key, AssetType.Sound, true, (AssetDownload transfer, Asset asset) =>\r
+ {\r
+ System.Console.WriteLine("Sound '{0}' download success: {1}", transfer.AssetID, transfer.Success);\r
+ }\r
+ );\r
+ }\r
+ }\r
+\r
#endregion\r
}\r
}
\ No newline at end of file
// NetcomSync is used for raising certain events on the\r
// GUI/main thread. Useful if you're modifying GUI controls\r
// in the client app when responding to those events.\r
- private ISynchronizeInvoke netcomSync;\r
+ private Control netcomSync;\r
\r
#region ClientConnected event\r
/// <summary>The event subscribers, null of no subscribers</summary>\r
RegisterClientEvents(client);\r
}\r
\r
+ private bool CanSyncInvoke\r
+ {\r
+ get\r
+ {\r
+ return netcomSync != null && !netcomSync.IsDisposed && netcomSync.IsHandleCreated && netcomSync.InvokeRequired;\r
+ }\r
+ }\r
+\r
public void Dispose()\r
{\r
if (client != null)\r
\r
void Self_IM(object sender, InstantMessageEventArgs e)\r
{\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnInstantMessageRaise(OnInstantMessageReceived), new object[] { e });\r
else\r
OnInstantMessageReceived(e);\r
{\r
loggedIn = true;\r
client.Self.RequestBalance();\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
{\r
netcomSync.BeginInvoke(new ClientConnectedRaise(OnClientConnected), new object[] { EventArgs.Empty });\r
}\r
\r
LoginProgressEventArgs ea = new LoginProgressEventArgs(e.Status, e.Message);\r
\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnClientLoginRaise(OnClientLoginStatus), new object[] { e });\r
else\r
OnClientLoginStatus(e);\r
{\r
loggedIn = false;\r
\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnClientLogoutRaise(OnClientLoggedOut), new object[] { EventArgs.Empty });\r
else\r
OnClientLoggedOut(EventArgs.Empty);\r
if (e.Status == TeleportStatus.Finished || e.Status == TeleportStatus.Failed)\r
teleporting = false;\r
\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnTeleportStatusRaise(OnTeleportStatusChanged), new object[] { e });\r
else\r
OnTeleportStatusChanged(e);\r
\r
private void Self_ChatFromSimulator(object sender, ChatEventArgs e)\r
{\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnChatRaise(OnChatReceived), new object[] { e });\r
else\r
OnChatReceived(e);\r
{\r
loggedIn = false;\r
\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnClientDisconnectRaise(OnClientDisconnected), new object[] { e });\r
else\r
OnClientDisconnected(e);\r
\r
void Self_MoneyBalance(object sender, BalanceEventArgs e)\r
{\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnMoneyBalanceRaise(OnMoneyBalanceUpdated), new object[] { e });\r
else\r
OnMoneyBalanceUpdated(e);\r
\r
void Self_AlertMessage(object sender, AlertMessageEventArgs e)\r
{\r
- if (netcomSync != null && netcomSync.InvokeRequired)\r
+ if (CanSyncInvoke)\r
netcomSync.BeginInvoke(new OnAlertMessageRaise(OnAlertMessageReceived), new object[] { e });\r
else\r
OnAlertMessageReceived(e);\r
set { loginOptions = value; }\r
}\r
\r
- public ISynchronizeInvoke NetcomSync\r
+ public Control NetcomSync\r
{\r
get { return netcomSync; }\r
set { netcomSync = value; }\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>\r
+ ///<!-- $Id$ -->\r
+ ///<llsd>\r
+ /// <map>\r
+ /// <key>0bcd5f5d-a4ce-9ea4-f9e8-15132653b3d8</key>\r
+ /// <map>\r
+ /// <key>color</key>\r
+ /// <array>\r
+ /// <real>2</real>\r
+ /// <real>1</real>\r
+ ///\r
+ /// <real>1.6000000238418579</real>\r
+ /// <real>1</real>\r
+ /// </array>\r
+ /// <key>multiple</key>\r
+ /// <real>2</real>\r
+ /// <key>name</key>\r
+ ///\r
+ /// <string>MoyMix</string>\r
+ /// </map>\r
+ /// <key>0f6723d2-5b23-6b58-08ab-308112b33786</key>\r
+ /// <map>\r
+ /// <key>color</key> [rest of string was truncated]";.\r
+ /// </summary>\r
+ public static string client_signatures {\r
+ get {\r
+ return ResourceManager.GetString("client_signatures", resourceCulture);\r
+ }\r
+ }\r
+ \r
public static System.Drawing.Bitmap computer_16 {\r
get {\r
object obj = ResourceManager.GetObject("computer_16", resourceCulture);\r
<data name="UpdateCheckUri" xml:space="preserve">\r
<value>http://update.radegastclient.org/svc/get_latest</value>\r
</data>\r
+ <data name="client_signatures" type="System.Resources.ResXFileRef, System.Windows.Forms">\r
+ <value>../Resources/client_signatures.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>\r
+ </data>\r
</root>
\ No newline at end of file
<ItemGroup>\r
<Compile Include="Core\AutoPilot.cs" />\r
<Compile Include="Core\ChatBufferItem.cs" />\r
+ <Compile Include="Core\ClientSignatures.cs" />\r
<Compile Include="Core\Commands\CommandsManager.cs" />\r
<Compile Include="Core\Commands\ICommandInterpreter.cs" />\r
<Compile Include="Core\Commands\IRadegastCommand.cs" />\r
<None Include="Resources\checkerboard.png" />\r
<Content Include="Resources\btn_play.png" />\r
<Content Include="Resources\btn_stop.png" />\r
+ <None Include="Resources\client_signatures.txt" />\r
<Content Include="Resources\radegast_large.png" />\r
<Content Include="worldmap.html">\r
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>\r
+<!-- $Id: $ -->\r
+<llsd>\r
+ <map>\r
+ <key>0bcd5f5d-a4ce-9ea4-f9e8-15132653b3d8</key>\r
+ <map>\r
+ <key>color</key>\r
+ <array>\r
+ <real>2</real>\r
+ <real>1</real>\r
+\r
+ <real>1.6000000238418579</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+ <real>2</real>\r
+ <key>name</key>\r
+\r
+ <string>MoyMix</string>\r
+ </map>\r
+ <key>0f6723d2-5b23-6b58-08ab-308112b33786</key>\r
+ <map>\r
+ <key>color</key>\r
+ <array>\r
+ <real>0</real>\r
+\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+ <real>2</real>\r
+\r
+ <key>name</key>\r
+ <string>CryoLife</string>\r
+ </map>\r
+ <key>11ad2452-ce54-8d65-7c23-05589b59f516</key>\r
+ <map>\r
+ <key>color</key>\r
+ <array>\r
+\r
+ <real>0</real>\r
+ <real>0.5</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VerticalLife</string>\r
+ </map>\r
+ <key>1c29480c-c608-df87-28bb-964fb64c5366</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1.6000000238418579</real>\r
+ <real>1.6000000238418579</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Gemini</string>\r
+ </map>\r
+ <key>2a9a406c-f448-68f2-4e38-878f8c46c190</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>0.89999997615814209</real>\r
+ <real>0.69999998807907104</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>Meerkat</string>\r
+ </map>\r
+ <key>2c9c1e0b-e5d1-263e-16b1-7fc6d169f3d6</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>PhoxSL</string>\r
+ </map>\r
+ <key>3ab7e2fa-9572-ef36-1a30-d855dbea4f92</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0.5</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VerticalLife</string>\r
+ </map>\r
+ <key>4da16427-d81e-e816-f346-aaf4741b8056</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>iLife</string>\r
+ </map>\r
+ <key>4e8dcf80-336b-b1d8-ef3e-08dacf015a0f</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Sapphire</string>\r
+ </map>\r
+ <key>5262d71a-88f7-ef40-3b15-00ea148ab4b5</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1.6000000238418579</real>\r
+ <real>1.6000000238418579</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Gemini.Bot</string>\r
+ </map>\r
+ <key>58a8b7ec-1455-7162-5d96-d3c3ead2ed71</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0.5</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VerticalLife</string>\r
+ </map>\r
+ <key>5aa5c70d-d787-571b-0495-4fc1bdef1500</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>0</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>LGG proxy</string>\r
+ </map>\r
+ <key>77662f23-c77a-9b4d-5558-26b757b2144c</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0.60000002384185791</real>\r
+ <real>0.20000000298023224</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>PSL</string>\r
+ </map>\r
+ <key>7c4d47a3-0c51-04d1-fa47-e4f3ac12f59b</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Kung Fu</string>\r
+ </map>\r
+ <key>8183e823-c443-2142-6eb6-2ab763d4f81c</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>Day Oh proxy</string>\r
+ </map>\r
+ <key>81b3e921-ee31-aa57-ff9b-ec1f28e41da1</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1.2000000476837158</real>\r
+ <real>1.2000000476837158</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>2</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Infinity</string>\r
+ </map>\r
+ <key>841ef25b-3b90-caf9-ea3d-5649e755db65</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0.5</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VerticalLife</string>\r
+ </map>\r
+ <key>872c0005-3095-0967-866d-11cd71115c22</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ <real>2</real>\r
+ <real>3</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>3</real>\r
+ <key>name</key>\r
+ <string><-- Fag</string>\r
+ </map>\r
+ <key>9422e9d7-7b11-83e4-6262-4a8db4716a3b</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>0</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>BetaLife</string>\r
+ </map>\r
+ <key>9ba526b6-f43d-6b60-42de-ce62a25ee7fb</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>0</real>\r
+ <key>name</key>\r
+ <string>nolife</string>\r
+ </map>\r
+ <key>adcbe893-7643-fd12-f61c-0b39717e2e32</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>0.5</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>tyk3n</string>\r
+ </map>\r
+ <key>b6820989-bf42-ff59-ddde-fd3fd3a74fe4</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>0.89999997615814209</real>\r
+ <real>0.69999998807907104</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>Meerkat</string>\r
+ </map>\r
+ <key>c252d89d-6f7c-7d90-f430-d140d2e3fbbe</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>0</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VLife</string>\r
+ </map>\r
+ <key>c5b570ca-bb7e-3c81-afd1-f62646b20014</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Kung Fu</string>\r
+ </map>\r
+ <key>ccb509cf-cc69-e569-38f1-5086c687afd1</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1.6000000238418579</real>\r
+ <real>0.20000000298023224</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>2</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Ruby</string>\r
+ </map>\r
+ <key>ccda2b3b-e72c-a112-e126-fee238b67218</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>2</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>Emerald</string>\r
+ </map>\r
+ <key>d3eb4a5f-aec5-4bcb-b007-cce9efe89d37</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0.60000002384185791</real>\r
+ <real>0</real>\r
+ <real>2</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>rivlife</string>\r
+ </map>\r
+ <key>e52d21f7-3c8b-819f-a3db-65c432295dac</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>CryoLife</string>\r
+ </map>\r
+ <key>e734563e-1c31-2a35-3ed5-8552c807439f</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0</real>\r
+ <real>0.5</real>\r
+ <real>1</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>VerticalLife</string>\r
+ </map>\r
+ <key>f3fd74a6-fee7-4b2f-93ae-ddcb5991da04</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0.60000002384185791</real>\r
+ <real>0.20000000298023224</real>\r
+ <real>0.80000001192092896</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>PSL</string>\r
+ </map>\r
+ <key>f5a48821-9a98-d09e-8d6a-50cc08ba9a47</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>2</real>\r
+ <real>2</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>2</real>\r
+ <key>name</key>\r
+ <string>NeilLife</string>\r
+ </map>\r
+ <key>f5feab57-bde5-2074-97af-517290213eaa</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>0.36000001430511475</real>\r
+ <real>0.36000001430511475</real>\r
+ <real>0.36000001430511475</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>0</real>\r
+ <key>name</key>\r
+ <string>Onyx</string>\r
+ </map>\r
+ <key>ffce04ff-5303-4909-a044-d37af7ab0b0e</key>\r
+ <map>\r
+ <key>color</key>\r
+\r
+ <array>\r
+ <real>1</real>\r
+ <real>0.5</real>\r
+ <real>0</real>\r
+ <real>1</real>\r
+ </array>\r
+ <key>multiple</key>\r
+\r
+ <real>1</real>\r
+ <key>name</key>\r
+ <string>Corgi</string>\r
+ </map>\r
+ <key>isComplete</key>\r
+ <string>true</string>\r
+\r
+ </map>\r
+</llsd>\r