private void RunScriptMethod(LSLScriptInstance instance, string methodName, object[] parameters) { try { if (parameters != null && parameters.Length > 0) { instance.CallScriptMethod(methodName, parameters); } else { instance.CallScriptMethod(methodName); } } catch (Exception ex) { m_log.Error("Error executing method " + methodName + " in script " + instance.ID + ": " + ex); } lock (m_syncRoot) { // Mark this script as not having a running event instance.CurrentExecution = null; // Check if this script has more events. If so, add it back to // the end of the queue if (instance.EventCount > 0) { m_scriptsWithEvents.Enqueue(instance); } } }
private void SaveScriptState(LSLScriptInstance instance) { // Create a state file for this script byte[] scriptState = instance.GetSerializedState(); m_assetClient.StoreAsset(new Asset { ContentType = "application/vnd.ll.lslstate", CreatorID = instance.Host.OwnerID, Data = scriptState, ID = UUID.Combine(instance.ID, SCRIPT_STATE_MAGIC_ID), Local = true, Temporary = true, CreationDate = DateTime.UtcNow }); }
public void Init(byte[] scriptBinary, LSLScriptInstance instance) { m_instance = instance; // Load the assembly into this AppDomain and create an instance of the // SecondLife.Script class (the main script class) Assembly scriptAssembly = Assembly.Load(scriptBinary); m_script = scriptAssembly.CreateInstance("SecondLife.Script") as LSLScriptBase; m_script.Init(this); // Create a dictionary of FastInvoke delegates for each method in the script MethodInfo[] methodInfos = m_script.GetType().GetMethods(); m_methods = new Dictionary <string, FastInvokeDelegate>(); for (int i = 0; i < methodInfos.Length; i++) { if (methodInfos[i].Module.Assembly == scriptAssembly) { m_methods.Add(methodInfos[i].Name, FastInvoke.Create(methodInfos[i])); } } }
public void Init(byte[] scriptBinary, LSLScriptInstance instance) { m_instance = instance; // Load the assembly into this AppDomain and create an instance of the // SecondLife.Script class (the main script class) Assembly scriptAssembly = Assembly.Load(scriptBinary); m_script = scriptAssembly.CreateInstance("SecondLife.Script") as LSLScriptBase; m_script.Init(this); // Create a dictionary of FastInvoke delegates for each method in the script MethodInfo[] methodInfos = m_script.GetType().GetMethods(); m_methods = new Dictionary<string, FastInvokeDelegate>(); for (int i = 0; i < methodInfos.Length; i++) { if (methodInfos[i].Module.Assembly == scriptAssembly) m_methods.Add(methodInfos[i].Name, FastInvoke.Create(methodInfos[i])); } }
private void ScriptEventsThread() { while (m_running) { // Check if there are free threads in the script thread pool if (m_eventThreadPool.MaxThreads - m_eventThreadPool.InUseThreads > 0) { // Check HTTP requests // Check XML-RPC requests // Check listeners // Check timers CheckTimerEvents(); // Check sensors // Check grid requests // Dequeue the next script event LSLScriptInstance instance = null; EventParams scriptEvent = null; lock (m_syncRoot) { // Try to dequeue the next script with a pending event, // then the next pending event for that script if (m_scriptsWithEvents.Count > 0) { instance = m_scriptsWithEvents.Dequeue(); if (instance != null) { scriptEvent = instance.DequeueEvent(); } } } if (instance != null && scriptEvent != null) { if (scriptEvent.EventName == "timer") { instance.IsTimerEventQueued = false; } if (scriptEvent.EventName == "control") { instance.ControlEventsQueued--; } if (scriptEvent.EventName == "collision") { instance.IsCollisionEventQueued = false; } if (scriptEvent.EventName == "state") { // FIXME: //instance.SetState(scriptEvent.EventName); //LSLEventFlags flags = GetEventsForState(instance.ID, instance.State); } else { string methodName = instance.State + "_event_" + scriptEvent.EventName; // Convert the method arguments to LSL types and queue // this event handler on the thread pool ConvertParamsToLSLTypes(ref scriptEvent.Params); instance.CurrentExecution = m_eventThreadPool.QueueWorkItem(RunScriptMethod, instance, methodName, scriptEvent.Params); } } } else { m_log.Debug("No free threads in the script thread pool, sleeping..."); } // TODO: Dynamic sleeping interval? Thread.Sleep(XENGINE_LONG_SLEEP_INTERVAL); m_scheduler.ThreadKeepAlive(); } m_eventThreadPool.Dispose(); m_scheduler.RemoveThread(); }
private void StartScript(UUID sourceItemID, UUID sourceAssetID, ISceneEntity hostObject, byte[] scriptBinary) { // Create a new AppDomain for this script AppDomainSetup domainSetup = new AppDomainSetup(); domainSetup.LoaderOptimization = LoaderOptimization.SingleDomain; AppDomain scriptDomain = AppDomain.CreateDomain(sourceItemID + ".lsl", null, domainSetup); // Create an instance (that lives in this AppDomain) and a wrapper // (that lives in the script AppDomain) for this script LSLScriptInstance instance = new LSLScriptInstance(sourceItemID, sourceAssetID, hostObject, scriptDomain); LSLScriptWrapper wrapper = (LSLScriptWrapper)scriptDomain.CreateInstanceAndUnwrap( Assembly.GetExecutingAssembly().FullName, "Simian.Scripting.Linden.LSLScriptWrapper"); wrapper.Init(scriptBinary, instance); instance.Init(wrapper); lock (m_syncRoot) { // If this script is already running, shut it down StopScript(sourceItemID, false); // Keep track of this script m_scripts[sourceItemID] = instance; // Keep track of the entity containing this script Dictionary <UUID, LSLScriptInstance> entityScripts; if (!m_scriptedEntities.TryGetValue(hostObject.ID, out entityScripts)) { entityScripts = new Dictionary <UUID, LSLScriptInstance>(); m_scriptedEntities[hostObject.ID] = entityScripts; } entityScripts[instance.ID] = instance; } if (hostObject is LLPrimitive) { // Update the PrimFlags for the containing LLPrimitive LLPrimitive obj = (LLPrimitive)hostObject; bool hasCollisionEvents; PrimFlags oldFlags = obj.Prim.Flags; LSLEventFlags eventFlags = wrapper.GetEventsForState("default"); PrimFlags newFlags = oldFlags; newFlags &= ~(PrimFlags.Touch | PrimFlags.Money); newFlags |= PrimFlags.Scripted | LSLEventFlagsToPrimFlags(eventFlags, out hasCollisionEvents); // FIXME: Do something with hasCollisionEvents // Either update the PrimFlags for this prim or just schedule // it for serialization (since it has a new script) if (newFlags != oldFlags) { obj.Prim.Flags = newFlags; m_scene.EntityAddOrUpdate(this, obj, 0, (uint)LLUpdateFlags.PrimFlags); } else { m_scene.EntityAddOrUpdate(this, obj, UpdateFlags.Serialize, 0); } } // Fire the state_entry event to get this script started PostScriptEvent(new EventParams(sourceItemID, "state_entry", new object[0], new DetectParams[0])); }