// // ORIGINAL CODE BASE IS Copyright (C) 2006-2010 by Alphons van der Heijden. // The code was donated on 2010-04-28 by Alphons van der Heijden to Brandon 'Dimentox Travanti' Husbands & // Malcolm J. Kudra, who in turn License under the GPLv2 in agreement with Alphons van der Heijden's wishes. // // The community would like to thank Alphons for all of his hard work, blood sweat and tears. Without his work // the community would be stuck with crappy editors. // // The source code in this file ("Source Code") is provided by The LSLEditor Group to you under the terms of the GNU // General Public License, version 2.0 ("GPL"), unless you have obtained a separate licensing agreement ("Other // License"), formally executed by you and The LSLEditor Group. // Terms of the GPL can be found in the gplv2.txt document. // // GPLv2 Header // ************ // LSLEditor, a External editor for the LSL Language. // Copyright (C) 2010 The LSLEditor Group. // // This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any // later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with this program; if not, write to the Free // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // ******************************************************************************************************************** // The above copyright notice and this permission notice shall be included in copies or substantial portions of the // Software. // ******************************************************************************************************************** // // // // SecondLifeHost.cs // // using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Text; using System.Threading; using System.Windows.Forms; using LSLEditor.Helpers; [module: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "Reviewed.")] namespace LSLEditor { /// /// Represents an event with a single string argument. /// public class SecondLifeHostEventArgs : EventArgs { /// /// Stores the text of the message. /// public string Message; /// /// Initialises a new instance of the class. /// /// String Text. public SecondLifeHostEventArgs(string strMessage) { this.Message = strMessage; } } /// /// Represents a linked message event. /// public class SecondLifeHostMessageLinkedEventArgs : EventArgs { /// /// Stores the index of the sending link. /// public SecondLife.integer LinkIndex; /// /// Stores a 32 bit numerical value. /// public SecondLife.integer Number; /// /// Stores a text string. /// public SecondLife.String Text; /// /// Stores a key. /// public SecondLife.key ID; /// /// Initialises a new instance of the class. /// /// /// /// /// public SecondLifeHostMessageLinkedEventArgs(SecondLife.integer iLinkIndex, SecondLife.integer iNumber, SecondLife.String sText, SecondLife.key kID) { this.LinkIndex = iLinkIndex; this.Number = iNumber; this.Text = sText; this.ID = kID; } } /// /// Represents a chat event. /// public class SecondLifeHostChatEventArgs : EventArgs { /// /// Stores the 32-bit number of the channel. /// public SecondLife.integer Channel; /// /// Stores the name of the object/avatar. /// public SecondLife.String Name; /// /// Stores the key of the objewct/avatar. /// public SecondLife.key ID; /// /// Stores the text of the message. /// public SecondLife.String Message; /// /// Stores the type of communication the event represents. /// public CommunicationType How; /// /// Initialises a new instance of the class. /// /// Channel to communicate on. Some communication types have channel limitations. /// Name of object/avatar. /// UUID of object/avatar. /// Text of message. /// Type of communication (CommunicationType enum). public SecondLifeHostChatEventArgs(SecondLife.integer channel, SecondLife.String name, SecondLife.key id, SecondLife.String message, CommunicationType how) { this.Channel = channel; this.Name = name; this.ID = id; this.Message = message; this.How = how; } } /// /// SecondLifeHost class. /// public class SecondLifeHost : IDisposable { /// /// Stores a list of ListenFilters /// private List lstListenFilter; /// /// Stores a list of the links in an object. /// private List lstLinks; /// /// Stores the SecondLife object representing the script. /// private SecondLife slSecondLife; /// /// not sure? /// private TaskQueue tqTaskQueue; /// /// Flag indicating an event has occurred. /// private AutoResetEvent areStateChanged; /// /// Stores and controls a thread?. /// private Thread tStateWatcher; /// /// An editor form? /// private LSLEditorForm efMainForm; /// /// A compiled assembly of the LSL script. /// private Assembly assCompiledAssembly; /// /// Stores the path to the script (including script name). /// public string FullPath; /// /// Stores globally unique ID. /// public Guid GUID; /// /// Stores SecondLifeHostMessageHandler function. /// /// Sender of message. /// SecondLifeHostEventArgs object. public delegate void SecondLifeHostMessageHandler(object sender, SecondLifeHostEventArgs e); /// /// OnVerboseMessage event handler. /// public event SecondLifeHostMessageHandler OnVerboseMessage; /// /// OnStateChange event handler. /// public event SecondLifeHostMessageHandler OnStateChange; /// /// Stores SecondLifeHostChatHandler function. /// /// The sender. /// SecondLifeHostChatEventArgs object. public delegate void SecondLifeHostChatHandler(object sender, SecondLifeHostChatEventArgs e); /// /// OnChat event handler. /// public event SecondLifeHostChatHandler OnChat; /// /// Stores SecondLifeHostMessageLinkedHandler function. /// /// The caller. /// SecondLifeHostMessageLinkedEventArgs object. public delegate void SecondLifeHostMessageLinkedHandler(object sender, SecondLifeHostMessageLinkedEventArgs e); /// /// OnMessageLinked event handler. /// public event SecondLifeHostMessageLinkedHandler OnMessageLinked; /// /// OnDie event handler. /// public event EventHandler OnDie; /// /// OnReset event handler. /// public event EventHandler OnReset; /// /// OnListenChannelsChanged event handler. /// public event EventHandler OnListenChannelsChanged; /// /// Stores a timer. /// public System.Timers.Timer Timer; /// /// Stores the timer for a Sensor event. /// public System.Timers.Timer SensorTimer; /// /// Name of currently active state. /// public string CurrentStateName; /// /// Name of state to switch to. /// private string strNewStateName; /// /// Name of the containing object/prim. /// private string strObjectName; /// /// Description of the containing object/prim. /// private string strObjectDescription; /// /// Initialises a new instance of the class. /// /// Editor form this host is atached to. /// Assembly of the compiled script. /// Full path (including file name) to the script. /// UUID of the containing object? public SecondLifeHost(LSLEditorForm mainForm, Assembly assCompiledAssembly, string strFullPath, Guid guid) { this.lstListenFilter = null; this.lstLinks = null; this.slSecondLife = null; this.tqTaskQueue = new TaskQueue(); this.areStateChanged = new AutoResetEvent(false); this.tStateWatcher = new Thread(new ThreadStart(StateWatch)); this.tStateWatcher.Name = "StateWatch"; this.tStateWatcher.IsBackground = true; this.tStateWatcher.Start(); this.efMainForm = mainForm; this.assCompiledAssembly = assCompiledAssembly; this.FullPath = strFullPath; this.GUID = guid; this.strObjectName = Path.GetFileNameWithoutExtension(this.FullPath); this.strObjectDescription = ""; this.Timer = new System.Timers.Timer(); this.Timer.AutoReset = true; this.Timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); this.SensorTimer = new System.Timers.Timer(); this.SensorTimer.AutoReset = true; this.SensorTimer.Elapsed += new System.Timers.ElapsedEventHandler(sensor_timer_Elapsed); this.strNewStateName = "default"; this.CurrentStateName = ""; } /// /// Performs the timer event? /// /// The caller. /// ElapsedEventArgs object. private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { ExecuteSecondLife("timer"); } /// /// Watches for the flag to switch state, and enacts the change when needed. /// private void StateWatch() { while (true) { this.areStateChanged.WaitOne(); this.tqTaskQueue.Start(); // is implicit Stop() old Queue if (this.CurrentStateName != this.strNewStateName) { this.CurrentStateName = this.strNewStateName; ExecuteSecondLife("state_exit"); // Changing to CurrentStateName on this thread! (not ExecuteSecondLife) this.tqTaskQueue.Invoke(this, "SetState"); } } } /// /// Raises the flag for switching state. If the Force argument is true it ensures a state change. /// /// /// public void State(string strStateName, bool blnForce) { if (this.assCompiledAssembly != null) { if (blnForce) { this.CurrentStateName = ""; } this.strNewStateName = strStateName; this.areStateChanged.Set(); } } /// /// Initialises a new state. /// private void SetState() { if (assCompiledAssembly != null) { slSecondLife = assCompiledAssembly.CreateInstance("LSLEditor.State_" + CurrentStateName) as SecondLife; if (slSecondLife == null) { MessageBox.Show("State " + CurrentStateName + " does not exist!"); return; } lstListenFilter = new List(); lstLinks = new List(); // Make friends slSecondLife.host = this; // Update runtime userinterface by calling event handler if (OnStateChange != null) { OnStateChange(this, new SecondLifeHostEventArgs(CurrentStateName)); } ExecuteSecondLife("state_entry"); } } /// /// Gets a methods arguments using reflection. /// /// /// public string GetArgumentsFromMethod(string strName) { string strArgs = ""; if (this.slSecondLife != null) { MethodInfo mi = slSecondLife.GetType().GetMethod(strName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (mi != null) { int intI = 0; foreach (ParameterInfo pi in mi.GetParameters()) { if (intI > 0) { strArgs += ","; } strArgs += pi.ParameterType.ToString() + " " + pi.Name; intI++; } } } return strArgs; } /// /// Runtime output of LSL event info. /// /// /// public void VerboseEvent(string strEventName, object[] args) { StringBuilder sb = new StringBuilder(); sb.Append("*** "); sb.Append(strEventName); sb.Append('('); for (int intI = 0; intI < args.Length; intI++) { if (intI > 0) { sb.Append(','); } sb.Append(args[intI].ToString()); } sb.Append(")"); VerboseMessage(sb.ToString()); } /// /// Queue the method for execution. /// /// Some method (is it event or state?). /// Array of arguments for the method. public void ExecuteSecondLife(string strName, params object[] args) { if (slSecondLife != null) { VerboseEvent(strName, args); this.tqTaskQueue.Invoke(slSecondLife, strName, args); } } /// /// Fetches the names of all events (limited to current state?) in the script. /// /// List of events. public ArrayList GetEvents() { ArrayList ar = new ArrayList(); if (slSecondLife != null) { foreach (MethodInfo mi in slSecondLife.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { ar.Add(mi.Name); } } ar.Sort(); return ar; } /// /// Reset the script? /// public void Reset() { if (OnReset != null) { OnReset(this, new EventArgs()); } } /// /// Stop executing the script. Resets the queue, timer etc. first. /// public void Die() { if (OnDie != null) { OnDie(this, new EventArgs()); } if (slSecondLife != null) { // stop all timers this.Timer.Stop(); this.SensorTimer.Stop(); this.tqTaskQueue.Stop(); this.tqTaskQueue.Dispose(); this.tqTaskQueue = null; this.slSecondLife = null; } } /// /// Disposal method. Resets the Queue, Sensor, Timer, XMLRPC, etc. /// public void Dispose() { if (tqTaskQueue != null) { this.tqTaskQueue.Stop(); this.tqTaskQueue.Dispose(); this.tqTaskQueue = null; } if (listXmlRpc != null) { foreach (XMLRPC xmlRpc in listXmlRpc) { xmlRpc.CloseChannel(); } } if (slSecondLife != null) { this.Timer.Stop(); this.SensorTimer.Stop(); this.efMainForm = null; this.slSecondLife = null; } } #region Link functions /// /// The Link structure holds data used in Link Messaging. /// private struct Link { /// /// Data - 32 bit integer. /// public int Number; /// /// Data - string. /// public string Text; /// /// Data - SL key. /// public SecondLife.key ID; /// /// Destination for the data. /// public SecondLife.key Target; /// /// Initialises a new instance of the type. /// /// 32 bit integer data. /// string data. /// SL key data. /// Destination for the message. public Link(int number, string name, SecondLife.key id, SecondLife.key target) { this.Number = number; this.Text = name; this.ID = id; this.Target = target; } } /// /// Resets the link list, "breaking" them. /// public void llBreakAllLinks() { lstLinks = new List(); } /// /// Removes the specified Link from the list. /// /// The index number of the link to remove. public void llBreakLink(int iLinkIndex) { foreach (Link link in this.lstLinks) { if (link.Number == iLinkIndex) { this.lstLinks.Remove(link); break; } } } #endregion #region Listen functions /// /// Fetches the names of the ListenFilters. /// /// Array of ListenFilter names. public string[] GetListenChannels() // for GroupboxEvent { List list = new List(); foreach (ListenFilter lf in lstListenFilter) { list.Add(lf.Channel.ToString()); } return list.ToArray(); } /// /// ListenFilter type structure. /// private struct ListenFilter { /// /// Channel to listen on. /// public int Channel; /// /// Name of object/avatar to listen for. /// public string Name; /// /// Key of object/avatar to listen for. /// public SecondLife.key ID; /// /// Text from object/avatar to listen for. /// public string Message; /// /// Flag indicating whether this filter is enabled or not. /// public bool Active; /// /// Initialises a new instance of the type. /// /// Channel to listen to (required). /// Name to listen for (can be empty). /// UUID to listen for (can be empty/null). /// Text to listen for (can be empty). public ListenFilter(int channel, string name, SecondLife.key id, string message) { this.Channel = channel; this.Name = name; this.ID = id; this.Message = message; this.Active = true; } } /// /// Control for a ListenFilter /// /// 32 bit integer handle of the ListenFilter. /// Flag indicating whether to enable or disable. public void llListenControl(int number, int active) { for (int intI = 0; intI < lstListenFilter.Count; intI++) { ListenFilter lf = lstListenFilter[intI]; if (lf.GetHashCode() == number) { lf.Active = (bool)(active == 1); lstListenFilter[intI] = lf; break; } } } /// /// Removes a ListenFilter from the list. /// /// 32 bit integer handle of the ListenFilter. public void llListenRemove(int intHandle) { for (int intI = 0; intI < lstListenFilter.Count; intI++) { ListenFilter lf = lstListenFilter[intI]; if (lf.GetHashCode() == intHandle) { lstListenFilter.RemoveAt(intI); break; } } } /// /// Creates a ListenFilter from the llListen paramters. /// /// Channel to listen ot. /// Name of object/avatar to listen for. /// Key of object/avatar to listen for. /// Text from object/avatar to listen for. /// 32 bit integer handle. public int llListen(int channel, string name, SecondLife.key id, string message) { if (lstListenFilter.Count >= 64) { Chat(this, 0, "LSLEditor", SecondLife.NULL_KEY, "Maximum of 64 listens!!!", CommunicationType.Shout); return 0; } ListenFilter lf = new ListenFilter(channel, name, id, message); lstListenFilter.Add(lf); if (OnListenChannelsChanged != null) { OnListenChannelsChanged(this, null); } return lf.GetHashCode(); } /// /// Determines whether paremeters have a matching ListenFilter entry. /// /// /// /// /// /// True if a matche is found, otherwise false. private bool CheckListenFilter(int channel, string name, SecondLife.key id, string message) { ListenFilter lfToCheck = new ListenFilter(channel, name, id, message); foreach (ListenFilter lf in lstListenFilter) { if (!lf.Active) { continue; } if (lf.Channel != lfToCheck.Channel) { continue; } if (lf.Name != "" && lf.Name != lfToCheck.Name) { continue; } if (lf.ID != Guid.Empty.ToString() && lf.ID != "" && lf.ID != lfToCheck.ID) { continue; } if (lf.Message != "" && lf.Message != lfToCheck.Message) { continue; } return true; } return false; } /// /// // sink listen /// /// SecondLifeHostChatEventArgs object. public void Listen(SecondLifeHostChatEventArgs e) { if (slSecondLife != null) { if (CheckListenFilter(e.Channel, e.Name, e.ID, e.Message)) { ExecuteSecondLife("listen", e.Channel, e.Name, e.ID, e.Message); } } } #endregion /// /// Raise a chat event. /// /// /// Channel to send message on. /// Name of sender. /// Key of sender. /// Message to send. /// CommunicatioType enumerator value. public void Chat(object sender, int channel, string name, SecondLife.key id, string message, CommunicationType how) { if (OnChat != null) { OnChat(sender, new SecondLifeHostChatEventArgs(channel, name, id, message, how)); } } /// /// Raise a linked message event. /// /// /// /// /// public void MessageLinked(SecondLife.integer iLlinkIndex, SecondLife.integer iNumber, SecondLife.String sText, SecondLife.key kID) { if (OnMessageLinked != null) { OnMessageLinked(this, new SecondLifeHostMessageLinkedEventArgs(iLlinkIndex, iNumber, sText, kID)); } } /// /// // sink /// /// public void LinkMessage(SecondLifeHostMessageLinkedEventArgs e) { ExecuteSecondLife("link_message", e.LinkIndex, e.Number, e.Text, e.ID); } /// /// /// /// /// /// /// public SecondLife.key Http(string strURL, SecondLife.list lParameters, string strBody) { SecondLife.key kID = SecondLife.NULL_KEY; if (slSecondLife != null) { System.Net.WebProxy proxy = null; if (Properties.Settings.Default.ProxyServer != "") { proxy = new System.Net.WebProxy(Properties.Settings.Default.ProxyServer.Replace("http://", "")); } if (Properties.Settings.Default.ProxyUserid != "" && proxy != null) { proxy.Credentials = new System.Net.NetworkCredential(Properties.Settings.Default.ProxyUserid, Properties.Settings.Default.ProxyPassword); } kID = new SecondLife.key(Guid.NewGuid()); ////WebRequestClass a = new WebRequestClass(proxy, secondLife, Url, Parameters, Body, Key); try { HTTPRequest.Request(proxy, slSecondLife, strURL, lParameters, strBody, kID); } catch (Exception exception) { VerboseMessage(exception.Message); } } return kID; } /// /// /// /// /// /// public void Email(string strRecipient, string strSubject, string strBody) { if (slSecondLife != null) { SmtpClient client = new SmtpClient(); client.SmtpServer = Properties.Settings.Default.EmailServer; string strName = GetObjectName(); string strObjectName = string.Format("Object-Name: {0}", strName); SecondLife.vector vRegionCorner = slSecondLife.llGetRegionCorner(); string strRegionName = slSecondLife.llGetRegionName(); string strRegion = string.Format("Region: {0} ({1},{2})", strRegionName, vRegionCorner.x, vRegionCorner.y); SecondLife.vector pos = slSecondLife.llGetPos(); string strPosition = string.Format("Local-Position: ({0},{1},{2})", (int)pos.x, (int)pos.y, (int)pos.z); string strPrefix = strObjectName + "\r\n"; strPrefix += strRegion + "\r\n"; strPrefix += strPosition + "\r\n\r\n"; MailMessage msg = new MailMessage(); msg.To = strRecipient; msg.Subject = strSubject; msg.Body = strPrefix + strBody; msg.From = Properties.Settings.Default.EmailAddress; msg.Headers.Add("Reply-to", msg.From); ////MailAttachment myAttachment = new MailAttachment(strAttachmentFile); ////msg.Attachments.Add(myAttachment); VerboseMessage(client.Send(msg)); } } /// /// /// /// public void VerboseMessage(string strMessage) { if (OnVerboseMessage != null) { OnVerboseMessage(this, new SecondLifeHostEventArgs(strMessage)); } } /// /// /// /// /// /// /// /// /// /// public delegate void ShowDialogDelegate( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.String message, SecondLife.list buttons, SecondLife.integer channel); /// /// /// /// /// /// /// /// /// /// private void Dialog( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.String message, SecondLife.list buttons, SecondLife.integer channel) { llDialogForm lldfDialogForm = new llDialogForm(host, objectName, k, name, message, buttons, channel); lldfDialogForm.Left = this.efMainForm.Right - lldfDialogForm.Width - 5; lldfDialogForm.Top = this.efMainForm.Top + 30; lldfDialogForm.Show(this.efMainForm); this.efMainForm.llDialogForms.Add(lldfDialogForm); } /// /// /// /// /// /// /// public void llDialog(SecondLife.key avatar, SecondLife.String message, SecondLife.list buttons, SecondLife.integer channel) { if (message.ToString().Length >= 512) { VerboseMessage("llDialog: message too long, must be less than 512 characters"); return; } if (message.ToString().Length == 0) { VerboseMessage("llDialog: must supply a message"); return; } for (int intI = 0; intI < buttons.Count; intI++) { if (buttons[intI].ToString() == "") { VerboseMessage("llDialog: all buttons must have label strings"); return; } if (buttons[intI].ToString().Length > 24) { VerboseMessage("llDialog:Button Labels can not have more than 24 characters"); return; } } if (buttons.Count == 0) { buttons = new SecondLife.list(new string[] { "OK" }); } this.efMainForm.Invoke(new ShowDialogDelegate(Dialog), this, (SecondLife.String)GetObjectName(), slSecondLife.llGetOwner(), (SecondLife.String)Properties.Settings.Default.AvatarName, message, buttons, channel); } /// /// /// /// /// /// /// /// /// public delegate void ShowTextBoxDelegate( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.String message, SecondLife.integer channel); /// /// /// /// /// /// /// /// /// private void TextBox( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.String message, SecondLife.integer channel) { llTextBoxForm tbfTextBoxForm = new llTextBoxForm(host, objectName, k, name, message, channel); tbfTextBoxForm.Left = this.efMainForm.Left + (this.efMainForm.Width / 2) - (tbfTextBoxForm.Width / 2); tbfTextBoxForm.Top = this.efMainForm.Top + (this.efMainForm.Height / 2) - (tbfTextBoxForm.Height / 2); tbfTextBoxForm.Show(this.efMainForm); this.efMainForm.llTextBoxForms.Add(tbfTextBoxForm); } /// /// /// /// /// /// public void llTextBox(SecondLife.key avatar, SecondLife.String message, SecondLife.integer channel) { if (message.ToString().Length >= 512) { VerboseMessage("llTextBox: message too long, must be less than 512 characters"); return; } if (message.ToString().Length == 0) { VerboseMessage("llTextBos: must supply a message"); return; } this.efMainForm.Invoke(new ShowTextBoxDelegate(TextBox), this, (SecondLife.String)GetObjectName(), slSecondLife.llGetOwner(), (SecondLife.String)Properties.Settings.Default.AvatarName, message, channel); } /// /// /// /// public void SetPermissions(SecondLife.integer intPermissions) { ExecuteSecondLife("run_time_permissions", intPermissions); } /// /// /// /// /// /// /// /// /// private delegate void RequestPermissionsDelegate( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.key agent, SecondLife.integer intPermissions); /// /// /// /// /// /// /// /// /// private void RequestPermissions( SecondLifeHost host, SecondLife.String objectName, SecondLife.key k, SecondLife.String name, SecondLife.key agent, SecondLife.integer intPermissions) { PermissionsForm pfPermissionForm = new PermissionsForm(this, GetObjectName(), slSecondLife.llGetOwner(), Properties.Settings.Default.AvatarName, agent, intPermissions); pfPermissionForm.Left = this.efMainForm.Right - pfPermissionForm.Width - 5; pfPermissionForm.Top = this.efMainForm.Top + 30; pfPermissionForm.Show(this.efMainForm); this.efMainForm.PermissionForms.Add(pfPermissionForm); } /// /// /// /// /// public void llRequestPermissions(SecondLife.key agent, SecondLife.integer intPermissions) { this.efMainForm.Invoke( new RequestPermissionsDelegate(RequestPermissions), this, (SecondLife.String)GetObjectName(), slSecondLife.llGetOwner(), (SecondLife.String)Properties.Settings.Default.AvatarName, agent, intPermissions); } /// /// /// private int intControls = -1; /// /// /// /// public void SendControl(Keys keys) { if (intControls >= 0 || this.slSecondLife != null) { // check againt m_intControls TODO!!!!! int held = 0; int change = 0; if ((keys & Keys.Up) == Keys.Up) { held |= SecondLife.CONTROL_UP; } if ((keys & Keys.Down) == Keys.Down) { held |= SecondLife.CONTROL_DOWN; } if ((keys & Keys.Left) == Keys.Left) { held |= SecondLife.CONTROL_LEFT; } if ((keys & Keys.Right) == Keys.Right) { held |= SecondLife.CONTROL_RIGHT; } ExecuteSecondLife("control", (SecondLife.key)Properties.Settings.Default.AvatarKey, (SecondLife.integer)held, (SecondLife.integer)change); } } /// /// /// /// /// /// public void TakeControls(int intControls, int accept, int pass_on) { this.intControls = intControls; } /// /// /// public void ReleaseControls() { this.intControls = -1; } #region Notecards /// /// /// /// /// /// private void GetNotecardLineWorker(SecondLife.key k, string strPath, int line) { StreamReader sr = new StreamReader(strPath); int intI = 0; string strData = SecondLife.EOF; while (!sr.EndOfStream) { string strLine = sr.ReadLine(); if (intI == line) { strData = strLine; break; } intI++; } sr.Close(); ExecuteSecondLife("dataserver", k, (SecondLife.String)strData); } /// /// /// /// /// /// public SecondLife.key GetNotecardLine(string name, int line) { string strPath = efMainForm.SolutionExplorer.GetPath(this.GUID, name); if (strPath == string.Empty) { strPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name); } if (!File.Exists(strPath)) { VerboseMessage("Notecard: " + strPath + " not found"); tqTaskQueue.Invoke(slSecondLife, "llSay", (SecondLife.integer)0, (SecondLife.String)("Couldn't find notecard " + name)); return SecondLife.NULL_KEY; } SecondLife.key k = new SecondLife.key(Guid.NewGuid()); tqTaskQueue.Invoke(this, "GetNotecardLineWorker", k, strPath, line); return k; } /// /// /// /// /// private void GetNumberOfNotecardLinesWorker(SecondLife.key k, string strPath) { StreamReader sr = new StreamReader(strPath); int intI = 0; while (!sr.EndOfStream) { string strLine = sr.ReadLine(); intI++; } sr.Close(); ExecuteSecondLife("dataserver", k, (SecondLife.String)intI.ToString()); } /// /// /// /// /// public SecondLife.key GetNumberOfNotecardLines(string name) { string strPath = efMainForm.SolutionExplorer.GetPath(this.GUID, name); if (strPath == string.Empty) { strPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name); } if (!File.Exists(strPath)) { VerboseMessage("Notecard: " + strPath + " not found"); tqTaskQueue.Invoke(slSecondLife, "llSay", (SecondLife.integer)0, (SecondLife.String)("Couldn't find notecard " + name)); return SecondLife.NULL_KEY; } SecondLife.key k = new SecondLife.key(Guid.NewGuid()); tqTaskQueue.Invoke(this, "GetNumberOfNotecardLinesWorker", k, strPath); return k; } #endregion #region XML-RPC /// /// /// private List listXmlRpc; /// /// /// public void llOpenRemoteDataChannel() { if (listXmlRpc == null) { listXmlRpc = new List(); } XMLRPC xmlRpc = new XMLRPC(); xmlRpc.OnRequest += new XMLRPC.RequestEventHandler(xmlRpc_OnRequest); xmlRpc.OpenChannel(listXmlRpc.Count); listXmlRpc.Add(xmlRpc); ExecuteSecondLife( "remote_data", SecondLife.REMOTE_DATA_CHANNEL, xmlRpc.guid, new SecondLife.key(Guid.NewGuid()), (SecondLife.String)"LSLEditor", (SecondLife.integer)0, (SecondLife.String)("Listening on " + xmlRpc.Prefix)); } /// /// /// /// /// private void xmlRpc_OnRequest(object sender, XmlRpcRequestEventArgs e) { XMLRPC xmlRpc = sender as XMLRPC; ExecuteSecondLife( "remote_data", SecondLife.REMOTE_DATA_REQUEST, e.channel, e.message_id, e.sender, e.iData, e.sData); } /// /// /// /// public void llCloseRemoteDataChannel(SecondLife.key channel) { if (listXmlRpc != null) { foreach (XMLRPC xmlRpc in listXmlRpc) { if (xmlRpc.guid == channel.guid) { xmlRpc.CloseChannel(); break; } } } } /// /// /// /// /// /// /// public void llRemoteDataReply(SecondLife.key channel, SecondLife.key message_id, string sdata, int idata) { if (listXmlRpc != null) { foreach (XMLRPC xmlRpc in listXmlRpc) { if (xmlRpc.guid == channel.guid) { xmlRpc.RemoteDataReply(channel.guid, message_id.guid, sdata, idata); break; } } } } /// /// // Wiki sais this is not working in InWorld /// /// /// /// /// /// public SecondLife.key llSendRemoteData(SecondLife.key kChannelID, string dest, int idata, string sdata) { XMLRPC xmlRpc = new XMLRPC(); xmlRpc.OnReply += new XMLRPC.RequestEventHandler(xmlRpc_OnReply); SecondLife.key message_id = xmlRpc.SendRemoteData(kChannelID, dest, idata, sdata); return message_id; } /// /// // Wiki sais currently disabled /// /// /// private void xmlRpc_OnReply(object sender, XmlRpcRequestEventArgs e) { ExecuteSecondLife( "remote_data", SecondLife.REMOTE_DATA_REPLY, e.channel, e.message_id, (SecondLife.String)"", // Wiki e.iData, e.sData); } #endregion /// /// /// /// /// public string GetObjectName(Guid guid) { string strObjectName = efMainForm.SolutionExplorer.GetObjectName(guid); return strObjectName != string.Empty ? strObjectName : this.strObjectName; } /// /// /// /// public string GetObjectName() { return GetObjectName(this.GUID); } /// /// /// /// public void SetObjectName(string name) { if (!efMainForm.SolutionExplorer.SetObjectName(this.GUID, name)) { strObjectName = name; } } /// /// /// /// /// public string GetObjectDescription(Guid guid) { string strObjectDescription = efMainForm.SolutionExplorer.GetObjectDescription(guid); if (strObjectDescription != string.Empty) { return strObjectDescription; } else { return this.strObjectDescription; } } /// /// /// /// public string GetObjectDescription() { return GetObjectDescription(this.GUID); } /// /// /// /// public void SetObjectDescription(string description) { if (!efMainForm.SolutionExplorer.SetObjectDescription(this.GUID, description)) { this.strObjectDescription = description; } } /// /// /// /// public string GetScriptName() { string strScriptName = efMainForm.SolutionExplorer.GetScriptName(this.GUID); if (strScriptName == string.Empty) { strScriptName = this.FullPath; } if (Properties.Settings.Default.llGetScriptName) { strScriptName = Path.GetFileNameWithoutExtension(strScriptName); } else { strScriptName = Path.GetFileName(strScriptName); } return strScriptName; } /// /// /// /// public SecondLife.key GetKey() { string strGuid = efMainForm.SolutionExplorer.GetKey(this.GUID); if (strGuid == string.Empty) { return new SecondLife.key(this.GUID); } return new SecondLife.key(strGuid); } /// /// /// /// /// /// public SecondLife.String GetInventoryName(SecondLife.integer type, SecondLife.integer number) { string strInventoryName = efMainForm.SolutionExplorer.GetInventoryName(this.GUID, type, number); if (strInventoryName == string.Empty) { return "**GetInventoryName only works in SolutionExplorer**"; } return strInventoryName; } /// /// /// /// /// public SecondLife.key GetInventoryKey(SecondLife.String name) { string strInventoryKey = efMainForm.SolutionExplorer.GetInventoryKey(this.GUID, name); if (strInventoryKey == string.Empty) { return new SecondLife.key(Guid.Empty); } return new SecondLife.key(strInventoryKey); } /// /// /// /// /// public SecondLife.integer GetInventoryNumber(SecondLife.integer type) { return efMainForm.SolutionExplorer.GetInventoryNumber(this.GUID, type); } /// /// /// /// /// public SecondLife.integer GetInventoryType(SecondLife.String name) { return efMainForm.SolutionExplorer.GetInventoryType(this.GUID, name); } /// /// /// /// public void RemoveInventory(SecondLife.String name) { efMainForm.SolutionExplorer.RemoveInventory(this.GUID, name); } /// /// /// /// /// public System.Media.SoundPlayer GetSoundPlayer(string sound) { string strPath = efMainForm.SolutionExplorer.GetPath(this.GUID, sound); if (strPath == string.Empty) { strPath = sound; } return new System.Media.SoundPlayer(strPath); } /// /// /// /// /// private void sensor_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { SecondLife.integer total_number = 1; ExecuteSecondLife("sensor", total_number); } } }