-using System;\r
-using System.Collections.Generic;\r
-using System.IO;\r
-using System.Text;\r
-using System.Windows.Forms;\r
-using RadegastNc;\r
-using OpenMetaverse;\r
-\r
-namespace Radegast\r
-{\r
- public class RadegastInstance\r
- {\r
- private GridClient client;\r
- private RadegastNetcom netcom;\r
-\r
- private ImageCache imageCache;\r
- private StateManager state;\r
- private ConfigManager config;\r
-\r
- private frmMain mainForm;\r
- private TabsConsole tabsConsole;\r
- public readonly string userDir;\r
- public readonly string animCacheDir;\r
-\r
- public Dictionary<UUID, Group> groups;\r
- public Dictionary<UUID, string> nameCache = new Dictionary<UUID,string>();\r
-\r
- public delegate void OnAvatarNameCallBack(UUID agentID, string agentName);\r
- public event OnAvatarNameCallBack OnAvatarName;\r
-\r
- public readonly bool advancedDebugging = false;\r
- public readonly bool MonoRuntime;\r
-\r
- public RadegastInstance()\r
- {\r
- try\r
- {\r
- userDir = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), Properties.Resources.ProgramName);\r
- if (!Directory.Exists(userDir))\r
- {\r
- Directory.CreateDirectory(userDir);\r
- }\r
- }\r
- catch (Exception) \r
- {\r
- userDir = System.Environment.CurrentDirectory;\r
- };\r
- animCacheDir = Path.Combine(userDir, @"anim_cache");\r
-\r
- // Are we running mono?\r
- if (null == Type.GetType("Mono.Runtime"))\r
- {\r
- MonoRuntime = false;\r
- }\r
- else\r
- {\r
- MonoRuntime = true;\r
- }\r
-\r
- Settings.PIPELINE_REFRESH_INTERVAL = 2000.0f;\r
-\r
- client = new GridClient();\r
- client.Settings.ALWAYS_REQUEST_OBJECTS = true;\r
- client.Settings.ALWAYS_DECODE_OBJECTS = true;\r
- client.Settings.OBJECT_TRACKING = true;\r
- client.Settings.ENABLE_SIMSTATS = true;\r
- client.Settings.FETCH_MISSING_INVENTORY = true;\r
- client.Settings.MULTIPLE_SIMS = true;\r
- client.Settings.SEND_AGENT_THROTTLE = true;\r
- client.Settings.SEND_AGENT_UPDATES = true;\r
-\r
- client.Settings.USE_TEXTURE_CACHE = true;\r
- client.Settings.TEXTURE_CACHE_DIR = Path.Combine(userDir, "cache");\r
- client.Assets.Cache.AutoPruneEnabled = false;\r
- \r
- client.Throttle.Texture = 2446000.0f;\r
- client.Throttle.Asset = 2446000.0f;\r
- client.Settings.THROTTLE_OUTGOING_PACKETS = true;\r
- client.Settings.LOGIN_TIMEOUT = 120 * 1000;\r
- client.Settings.SIMULATOR_TIMEOUT = 120 * 1000;\r
-\r
- netcom = new RadegastNetcom(client);\r
-\r
- imageCache = new ImageCache();\r
- state = new StateManager(this);\r
- InitializeConfig();\r
-\r
- mainForm = new frmMain(this);\r
- mainForm.InitializeControls();\r
- tabsConsole = mainForm.TabConsole;\r
-\r
- Application.ApplicationExit += new EventHandler(Application_ApplicationExit);\r
- groups = new Dictionary<UUID, Group>();\r
- \r
- client.Groups.OnCurrentGroups += new GroupManager.CurrentGroupsCallback(Groups_OnCurrentGroups);\r
- client.Groups.OnGroupLeft += new GroupManager.GroupLeftCallback(Groups_OnGroupLeft);\r
- client.Groups.OnGroupDropped += new GroupManager.GroupDroppedCallback(Groups_OnGroupDropped);\r
- client.Groups.OnGroupJoined += new GroupManager.GroupJoinedCallback(Groups_OnGroupJoined);\r
- client.Groups.OnGroupProfile += new GroupManager.GroupProfileCallback(Groups_OnGroupProfile);\r
- client.Avatars.OnAvatarNames += new AvatarManager.AvatarNamesCallback(Avatars_OnAvatarNames);\r
- }\r
-\r
- public void CleanUp()\r
- {\r
- if (client != null)\r
- {\r
- client.Groups.OnCurrentGroups -= new GroupManager.CurrentGroupsCallback(Groups_OnCurrentGroups);\r
- client.Groups.OnGroupLeft -= new GroupManager.GroupLeftCallback(Groups_OnGroupLeft);\r
- client.Groups.OnGroupDropped -= new GroupManager.GroupDroppedCallback(Groups_OnGroupDropped);\r
- client.Groups.OnGroupJoined -= new GroupManager.GroupJoinedCallback(Groups_OnGroupJoined);\r
- client.Groups.OnGroupProfile -= new GroupManager.GroupProfileCallback(Groups_OnGroupProfile);\r
- client.Avatars.OnAvatarNames -= new AvatarManager.AvatarNamesCallback(Avatars_OnAvatarNames);\r
- }\r
-\r
- if (MonoRuntime)\r
- {\r
- Environment.Exit(0);\r
- }\r
-\r
- }\r
-\r
- void Avatars_OnAvatarNames(Dictionary<UUID, string> names)\r
- {\r
- lock (nameCache)\r
- {\r
- foreach (KeyValuePair<UUID, string> av in names)\r
- {\r
- if (OnAvatarName != null) try { OnAvatarName(av.Key, av.Value); }\r
- catch (Exception) { };\r
-\r
- if (!nameCache.ContainsKey(av.Key))\r
- {\r
- nameCache.Add(av.Key, av.Value);\r
- }\r
- }\r
- }\r
- }\r
-\r
- public string getAvatarName(UUID key)\r
- {\r
- if (nameCache.ContainsKey(key))\r
- {\r
- return nameCache[key];\r
- }\r
- else\r
- {\r
- client.Avatars.RequestAvatarName(key);\r
- return "Loading...";\r
- }\r
- }\r
-\r
- void Groups_OnGroupProfile(Group group)\r
- {\r
- if (groups.ContainsKey(group.ID))\r
- {\r
- groups[group.ID] = group;\r
- }\r
- }\r
-\r
- void Groups_OnGroupJoined(UUID groupID, bool success)\r
- {\r
- if (success && !groups.ContainsKey(groupID))\r
- {\r
- groups.Add(groupID, new Group());\r
- client.Groups.RequestGroupProfile(groupID);\r
- }\r
- }\r
-\r
- void Groups_OnGroupLeft(UUID groupID, bool success)\r
- {\r
- if (groups.ContainsKey(groupID))\r
- {\r
- groups.Remove(groupID);\r
- }\r
- }\r
-\r
- void Groups_OnGroupDropped(UUID groupID)\r
- {\r
- if (groups.ContainsKey(groupID))\r
- {\r
- groups.Remove(groupID);\r
- }\r
- }\r
-\r
- void Groups_OnCurrentGroups(Dictionary<UUID, Group> gr)\r
- {\r
- this.groups = gr;\r
- }\r
-\r
- private void Application_ApplicationExit(object sender, EventArgs e)\r
- {\r
- config.SaveCurrentConfig();\r
- }\r
-\r
- private void InitializeConfig()\r
- {\r
- config = new ConfigManager(this);\r
- config.ApplyDefault();\r
-\r
- netcom.LoginOptions.FirstName = config.CurrentConfig.FirstName;\r
- netcom.LoginOptions.LastName = config.CurrentConfig.LastName;\r
- netcom.LoginOptions.Password = config.CurrentConfig.PasswordMD5;\r
- netcom.LoginOptions.IsPasswordMD5 = true;\r
- }\r
-\r
- public GridClient Client\r
- {\r
- get { return client; }\r
- }\r
-\r
- public RadegastNetcom Netcom\r
- {\r
- get { return netcom; }\r
- }\r
-\r
- public ImageCache ImageCache\r
- {\r
- get { return imageCache; }\r
- }\r
-\r
- public StateManager State\r
- {\r
- get { return state; }\r
- }\r
-\r
- public ConfigManager Config\r
- {\r
- get { return config; }\r
- }\r
-\r
- public frmMain MainForm\r
- {\r
- get { return mainForm; }\r
- }\r
-\r
- public TabsConsole TabConsole\r
- {\r
- get { return tabsConsole; }\r
- }\r
- }\r
-}\r
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2010, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Windows.Forms;
+using Radegast.Commands;
+using Radegast.Netcom;
+using Radegast.Media;
+using OpenMetaverse;
+
+namespace Radegast
+{
+ public class RadegastInstance
+ {
+ #region OnRadegastFormCreated
+ public event Action<RadegastForm> RadegastFormCreated;
+ /// <summary>
+ /// Triggers the RadegastFormCreated event.
+ /// </summary>
+ public virtual void OnRadegastFormCreated(RadegastForm radForm)
+ {
+ if (RadegastFormCreated != null) RadegastFormCreated(radForm);
+ }
+ #endregion
+
+ private GridClient client;
+ private RadegastNetcom netcom;
+
+ private StateManager state;
+
+ private frmMain mainForm;
+
+ // Singleton, there can be only one instance
+ private static RadegastInstance globalInstance = null;
+ public static RadegastInstance GlobalInstance
+ {
+ get
+ {
+ if (globalInstance == null)
+ {
+ globalInstance = new RadegastInstance(new GridClient());
+ }
+ return globalInstance;
+ }
+ }
+
+ /// <summary>
+ /// When was Radegast started (UTC)
+ /// </summary>
+ public readonly DateTime StartupTimeUTC;
+
+ /// <summary>
+ /// Time zone of the current world (currently hard coded to US Pacific time)
+ /// </summary>
+ public TimeZoneInfo WordTimeZone;
+
+ private string userDir;
+ /// <summary>
+ /// System (not grid!) user's dir
+ /// </summary>
+ public string UserDir { get { return userDir; } }
+
+ /// <summary>
+ /// Grid client's user dir for settings and logs
+ /// </summary>
+ public string ClientDir
+ {
+ get
+ {
+ if (client != null && client.Self != null && !string.IsNullOrEmpty(client.Self.Name))
+ {
+ return Path.Combine(userDir, client.Self.Name);
+ }
+ else
+ {
+ return Environment.CurrentDirectory;
+ }
+ }
+ }
+
+ public string InventoryCacheFileName { get { return Path.Combine(ClientDir, "inventory.cache"); } }
+
+ private string globalLogFile;
+ public string GlobalLogFile { get { return globalLogFile; } }
+
+ private bool monoRuntime;
+ public bool MonoRuntime { get { return monoRuntime; } }
+
+ private Dictionary<UUID, Group> groups = new Dictionary<UUID, Group>();
+ public Dictionary<UUID, Group> Groups { get { return groups; } }
+
+ private Settings globalSettings;
+ /// <summary>
+ /// Global settings for the entire application
+ /// </summary>
+ public Settings GlobalSettings { get { return globalSettings; } }
+
+ private Settings clientSettings;
+ /// <summary>
+ /// Per client settings
+ /// </summary>
+ public Settings ClientSettings { get { return clientSettings; } }
+
+ public Dictionary<UUID, string> nameCache = new Dictionary<UUID, string>();
+
+ public const string INCOMPLETE_NAME = "Loading...";
+
+ public readonly bool advancedDebugging = false;
+
+ private PluginManager pluginManager;
+ /// <summary> Handles loading plugins and scripts</summary>
+ public PluginManager PluginManager { get { return pluginManager; } }
+
+ private MediaManager mediaManager;
+ /// <summary>
+ /// Radegast media manager for playing streams and in world sounds
+ /// </summary>
+ public MediaManager MediaManager { get { return mediaManager; } }
+
+
+ private CommandsManager commandsManager;
+ /// <summary>
+ /// Radegast command manager for executing textual console commands
+ /// </summary>
+ public CommandsManager CommandsManager { get { return commandsManager; } }
+
+ /// <summary>
+ /// Radegast ContextAction manager for context sensitive actions
+ /// </summary>
+ public ContextActionsManager ContextActionManager { get; private set; }
+
+ private RadegastMovement movement;
+ /// <summary>
+ /// Allows key emulation for moving avatar around
+ /// </summary>
+ public RadegastMovement Movement { get { return movement; } }
+
+ private InventoryClipboard inventoryClipboard;
+ /// <summary>
+ /// The last item that was cut or copied in the inventory, used for pasting
+ /// in a different place on the inventory, or other places like profile
+ /// that allow sending copied inventory items
+ /// </summary>
+ public InventoryClipboard InventoryClipboard
+ {
+ get { return inventoryClipboard; }
+ set
+ {
+ inventoryClipboard = value;
+ OnInventoryClipboardUpdated(EventArgs.Empty);
+ }
+ }
+
+ private RLVManager rlv;
+
+ /// <summary>
+ /// Manager for RLV functionality
+ /// </summary>
+ public RLVManager RLV { get { return rlv; } }
+
+ private GridManager gridManager;
+ /// <summary>Manages default params for different grids</summary>
+ public GridManager GridManger { get { return gridManager; } }
+
+ #region Events
+
+ #region ClientChanged event
+ /// <summary>The event subscribers, null of no subscribers</summary>
+ private EventHandler<ClientChangedEventArgs> m_ClientChanged;
+
+ ///<summary>Raises the ClientChanged Event</summary>
+ /// <param name="e">A ClientChangedEventArgs object containing
+ /// the old and the new client</param>
+ protected virtual void OnClientChanged(ClientChangedEventArgs e)
+ {
+ EventHandler<ClientChangedEventArgs> handler = m_ClientChanged;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ /// <summary>Thread sync lock object</summary>
+ private readonly object m_ClientChangedLock = new object();
+
+ /// <summary>Raised when the GridClient object in the main Radegast instance is changed</summary>
+ public event EventHandler<ClientChangedEventArgs> ClientChanged
+ {
+ add { lock (m_ClientChangedLock) { m_ClientChanged += value; } }
+ remove { lock (m_ClientChangedLock) { m_ClientChanged -= value; } }
+ }
+ #endregion ClientChanged event
+
+ #region InventoryClipboardUpdated event
+ /// <summary>The event subscribers, null of no subscribers</summary>
+ private EventHandler<EventArgs> m_InventoryClipboardUpdated;
+
+ ///<summary>Raises the InventoryClipboardUpdated Event</summary>
+ /// <param name="e">A EventArgs object containing
+ /// the old and the new client</param>
+ protected virtual void OnInventoryClipboardUpdated(EventArgs e)
+ {
+ EventHandler<EventArgs> handler = m_InventoryClipboardUpdated;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ /// <summary>Thread sync lock object</summary>
+ private readonly object m_InventoryClipboardUpdatedLock = new object();
+
+ /// <summary>Raised when the GridClient object in the main Radegast instance is changed</summary>
+ public event EventHandler<EventArgs> InventoryClipboardUpdated
+ {
+ add { lock (m_InventoryClipboardUpdatedLock) { m_InventoryClipboardUpdated += value; } }
+ remove { lock (m_InventoryClipboardUpdatedLock) { m_InventoryClipboardUpdated -= value; } }
+ }
+ #endregion InventoryClipboardUpdated event
+
+
+ #endregion Events
+
+ public RadegastInstance(GridClient client0)
+ {
+ // incase something else calls GlobalInstance while we are loading
+ globalInstance = this;
+
+#if !DEBUG
+ Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
+ Application.ThreadException += HandleThreadException;
+#endif
+
+ client = client0;
+
+ // Initialize current time zone, and mark when we started
+ GetWorldTimeZone();
+ StartupTimeUTC = DateTime.UtcNow;
+
+ // Are we running mono?
+ monoRuntime = Type.GetType("Mono.Runtime") != null;
+
+ netcom = new RadegastNetcom(this);
+ state = new StateManager(this);
+ mediaManager = new MediaManager(this);
+ commandsManager = new CommandsManager(this);
+ ContextActionManager = new ContextActionsManager(this);
+ movement = new RadegastMovement(this);
+
+ InitializeLoggingAndConfig();
+ InitializeClient(client);
+
+ rlv = new RLVManager(this);
+ gridManager = new GridManager(this);
+ gridManager.LoadGrids();
+
+ mainForm = new frmMain(this);
+ mainForm.InitializeControls();
+
+ mainForm.Load += new EventHandler(mainForm_Load);
+ pluginManager = new PluginManager(this);
+ pluginManager.ScanAndLoadPlugins();
+ }
+
+ private void InitializeClient(GridClient client)
+ {
+ client.Settings.MULTIPLE_SIMS = true;
+
+ client.Settings.USE_INTERPOLATION_TIMER = false;
+ client.Settings.ALWAYS_REQUEST_OBJECTS = true;
+ client.Settings.ALWAYS_DECODE_OBJECTS = true;
+ client.Settings.OBJECT_TRACKING = true;
+ client.Settings.ENABLE_SIMSTATS = true;
+ client.Settings.FETCH_MISSING_INVENTORY = true;
+ client.Settings.SEND_AGENT_THROTTLE = true;
+ client.Settings.SEND_AGENT_UPDATES = true;
+
+ client.Settings.USE_ASSET_CACHE = true;
+ client.Settings.ASSET_CACHE_DIR = Path.Combine(userDir, "cache");
+ client.Assets.Cache.AutoPruneEnabled = false;
+
+ client.Throttle.Total = 5000000f;
+ client.Settings.THROTTLE_OUTGOING_PACKETS = false;
+ client.Settings.LOGIN_TIMEOUT = 120 * 1000;
+ client.Settings.SIMULATOR_TIMEOUT = 120 * 1000;
+ client.Settings.MAX_CONCURRENT_TEXTURE_DOWNLOADS = 20;
+
+ RegisterClientEvents(client);
+ }
+
+ private void RegisterClientEvents(GridClient client)
+ {
+ client.Groups.CurrentGroups += new EventHandler<CurrentGroupsEventArgs>(Groups_CurrentGroups);
+ client.Groups.GroupLeaveReply += new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
+ client.Groups.GroupDropped += new EventHandler<GroupDroppedEventArgs>(Groups_GroupsChanged);
+ client.Groups.GroupJoinedReply += new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
+ client.Avatars.UUIDNameReply += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
+ if (netcom != null)
+ netcom.ClientConnected += new EventHandler<EventArgs>(netcom_ClientConnected);
+ }
+
+ private void UnregisterClientEvents(GridClient client)
+ {
+ client.Groups.CurrentGroups -= new EventHandler<CurrentGroupsEventArgs>(Groups_CurrentGroups);
+ client.Groups.GroupLeaveReply -= new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
+ client.Groups.GroupDropped -= new EventHandler<GroupDroppedEventArgs>(Groups_GroupsChanged);
+ client.Groups.GroupJoinedReply -= new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
+ client.Avatars.UUIDNameReply -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
+ if (netcom != null)
+ netcom.ClientConnected -= new EventHandler<EventArgs>(netcom_ClientConnected);
+ }
+
+ private void GetWorldTimeZone()
+ {
+ try
+ {
+ foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())
+ {
+ if (tz.Id == "Pacific Standard Time" || tz.Id == "America/Los_Angeles")
+ {
+ WordTimeZone = tz;
+ break;
+ }
+ }
+ }
+ catch (Exception) { }
+ }
+
+ public DateTime GetWorldTime()
+ {
+ DateTime now;
+
+ try
+ {
+ if (WordTimeZone != null)
+ now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, WordTimeZone);
+ else
+ now = DateTime.UtcNow.AddHours(-7);
+ }
+ catch (Exception)
+ {
+ now = DateTime.UtcNow.AddHours(-7);
+ }
+
+ return now;
+ }
+
+
+ public void Reconnect()
+ {
+ TabConsole.DisplayNotificationInChat("Attempting to reconnect...", ChatBufferTextStyle.StatusDarkBlue);
+ Logger.Log("Attemting to reconnect", Helpers.LogLevel.Info, client);
+ GridClient oldClient = client;
+ client = new GridClient();
+ UnregisterClientEvents(oldClient);
+ InitializeClient(client);
+ OnClientChanged(new ClientChangedEventArgs(oldClient, client));
+ netcom.Login();
+ }
+
+ public void CleanUp()
+ {
+ if (gridManager != null)
+ {
+ gridManager.Dispose();
+ gridManager = null;
+ }
+
+ if (rlv != null)
+ {
+ rlv.Dispose();
+ rlv = null;
+ }
+
+ if (client != null)
+ {
+ UnregisterClientEvents(client);
+ }
+
+ if (pluginManager != null)
+ {
+ pluginManager.Dispose();
+ pluginManager = null;
+ }
+
+ if (movement != null)
+ {
+ movement.Dispose();
+ movement = null;
+ }
+ if (commandsManager != null)
+ {
+ commandsManager.Dispose();
+ commandsManager = null;
+ }
+ if (ContextActionManager != null)
+ {
+ ContextActionManager.Dispose();
+ ContextActionManager = null;
+ }
+ if (mediaManager != null)
+ {
+ mediaManager.Dispose();
+ mediaManager = null;
+ }
+ if (state != null)
+ {
+ state.Dispose();
+ state = null;
+ }
+ if (netcom != null)
+ {
+ netcom.Dispose();
+ netcom = null;
+ }
+ if (mainForm != null)
+ {
+ mainForm.Load -= new EventHandler(mainForm_Load);
+ }
+ Logger.Log("RadegastInstance finished cleaning up.", Helpers.LogLevel.Debug);
+ }
+
+ void mainForm_Load(object sender, EventArgs e)
+ {
+ pluginManager.StartPlugins();
+ }
+
+ void netcom_ClientConnected(object sender, EventArgs e)
+ {
+ try
+ {
+ if (!Directory.Exists(ClientDir))
+ Directory.CreateDirectory(ClientDir);
+ }
+ catch (Exception ex)
+ {
+ Logger.Log("Failed to create client directory", Helpers.LogLevel.Warning, ex);
+ }
+
+ clientSettings = new Settings(Path.Combine(ClientDir, "client_settings.xml"));
+ }
+
+
+ void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)
+ {
+ lock (nameCache)
+ {
+ foreach (KeyValuePair<UUID, string> av in e.Names)
+ {
+ if (!nameCache.ContainsKey(av.Key))
+ {
+ nameCache.Add(av.Key, av.Value);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fetches avatar name
+ /// </summary>
+ /// <param name="key">Avatar UUID</param>
+ /// <param name="blocking">Should we wait until the name is retrieved</param>
+ /// <returns>Avatar name</returns>
+ public string getAvatarName(UUID key, bool blocking)
+ {
+ if (!blocking)
+ return getAvatarName(key);
+
+ string name = null;
+
+ using (ManualResetEvent gotName = new ManualResetEvent(false))
+ {
+
+ EventHandler<UUIDNameReplyEventArgs> handler = (object sender, UUIDNameReplyEventArgs e) =>
+ {
+ if (e.Names.ContainsKey(key))
+ {
+ name = e.Names[key];
+ gotName.Set();
+ }
+ };
+
+ client.Avatars.UUIDNameReply += handler;
+ name = getAvatarName(key);
+
+ if (name == INCOMPLETE_NAME)
+ {
+ gotName.WaitOne(10 * 1000, false);
+ }
+
+ client.Avatars.UUIDNameReply -= handler;
+ }
+ return name;
+
+ }
+
+ /// <summary>
+ /// Fetches avatar name from cache, if not in cache will requst name from the server
+ /// </summary>
+ /// <param name="key">Avatar UUID</param>
+ /// <returns>Avatar name</returns>
+ public string getAvatarName(UUID key)
+ {
+ lock (nameCache)
+ {
+ if (key == UUID.Zero)
+ {
+ return "(???) (???)";
+ }
+ if (nameCache.ContainsKey(key))
+ {
+ return nameCache[key];
+ }
+ else
+ {
+ client.Avatars.RequestAvatarName(key);
+ return INCOMPLETE_NAME;
+ }
+ }
+ }
+
+ public void getAvatarNames(List<UUID> keys)
+ {
+ lock (nameCache)
+ {
+ List<UUID> newNames = new List<UUID>();
+ foreach (UUID key in keys)
+ {
+ if (!nameCache.ContainsKey(key))
+ {
+ newNames.Add(key);
+ }
+ }
+ if (newNames.Count > 0)
+ {
+ client.Avatars.RequestAvatarNames(newNames);
+ }
+ }
+ }
+
+ public bool haveAvatarName(UUID key)
+ {
+ lock (nameCache)
+ {
+ if (nameCache.ContainsKey(key))
+ return true;
+ else
+ return false;
+ }
+ }
+
+ void Groups_GroupsChanged(object sender, EventArgs e)
+ {
+ client.Groups.RequestCurrentGroups();
+ }
+
+ public static string SafeFileName(string fileName)
+ {
+ foreach (char lDisallowed in Path.GetInvalidFileNameChars())
+ {
+ fileName = fileName.Replace(lDisallowed.ToString(), "_");
+ }
+
+ return fileName;
+ }
+
+ public void LogClientMessage(string fileName, string message)
+ {
+ lock (this)
+ {
+ try
+ {
+ foreach (char lDisallowed in System.IO.Path.GetInvalidFileNameChars())
+ {
+ fileName = fileName.Replace(lDisallowed.ToString(), "_");
+ }
+
+ File.AppendAllText(Path.Combine(ClientDir, fileName),
+ DateTime.Now.ToString("yyyy-MM-dd [HH:mm:ss] ") + message + Environment.NewLine);
+ }
+ catch (Exception) { }
+ }
+ }
+
+ void Groups_CurrentGroups(object sender, CurrentGroupsEventArgs e)
+ {
+ this.groups = e.Groups;
+ }
+
+ private void InitializeLoggingAndConfig()
+ {
+ try
+ {
+ userDir = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), Properties.Resources.ProgramName);
+ if (!Directory.Exists(userDir))
+ {
+ Directory.CreateDirectory(userDir);
+ }
+ }
+ catch (Exception)
+ {
+ userDir = System.Environment.CurrentDirectory;
+ };
+
+ globalLogFile = Path.Combine(userDir, Properties.Resources.ProgramName + ".log");
+ globalSettings = new Settings(Path.Combine(userDir, "settings.xml"));
+ }
+
+ public GridClient Client
+ {
+ get { return client; }
+ }
+
+ public RadegastNetcom Netcom
+ {
+ get { return netcom; }
+ }
+
+ public StateManager State
+ {
+ get { return state; }
+ }
+
+ public frmMain MainForm
+ {
+ get { return mainForm; }
+ }
+
+ public TabsConsole TabConsole
+ {
+ get { return mainForm.TabConsole; }
+ }
+
+ public void HandleThreadException(object sender, ThreadExceptionEventArgs e)
+ {
+ Logger.Log("Unhandled Thread Exception: "
+ + e.Exception.Message + Environment.NewLine
+ + e.Exception.StackTrace + Environment.NewLine,
+ Helpers.LogLevel.Error,
+ client);
+#if DEBUG
+ Application.Exit();
+#endif
+ }
+ }
+
+ #region Event classes
+ public class ClientChangedEventArgs : EventArgs
+ {
+ private GridClient m_OldClient;
+ private GridClient m_Client;
+
+ public GridClient OldClient { get { return m_OldClient; } }
+ public GridClient Client { get { return m_Client; } }
+
+ public ClientChangedEventArgs(GridClient OldClient, GridClient Client)
+ {
+ m_OldClient = OldClient;
+ m_Client = Client;
+ }
+ }
+ #endregion Event classes
+}