aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ScriptEngine/Shared/ScriptStructure.cs
blob: cbf333b716c12fc3f38ab4217d13bf40ee4f1e9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using OpenMetaverse;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.ScriptEngine.Shared;

namespace OpenSim.ScriptEngine.Shared
{
    public struct ScriptStructure
    {
        public RegionInfoStructure RegionInfo;
        public ScriptMetaData ScriptMetaData;

        public ScriptAssemblies.IScript ScriptObject;
        public string State;
        public bool Running;
        public bool Disabled;
        public string Source;
        public int StartParam;
        public AppDomain AppDomain;
        public Dictionary<string, IScriptApi> Apis;
        public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap;
        public uint LocalID;
        public UUID ItemID;
        public string AssemblyFileName;

        public string ScriptID { get { return LocalID.ToString() + "." + ItemID.ToString(); } }
        public string Name { get { return "Script:" + ScriptID; } }
        private bool Initialized;
        private Dictionary<string, Delegate> InternalFunctions;
        public string AssemblyName;

        public void ExecuteEvent(EventParams p)
        {
            ExecuteMethod(p, true);
        }

        public void ExecuteMethod(EventParams p)
        {
            ExecuteMethod(p, false);
        }
        private void ExecuteMethod(EventParams p, bool isEvent)
        {
            // First time initialization?
            if (!Initialized)
            {
                Initialized = true;
                CacheInternalFunctions();
            }

            lock (InternalFunctions)
            {
                // Make function name
                string FunctionName;
                if (isEvent)
                    FunctionName = State + "_event_" + p.EventName;
                else
                    FunctionName = p.EventName;

                // Check if this function exist
                if (!InternalFunctions.ContainsKey(FunctionName))
                {
                    // TODO: Send message in-world
                    //RegionInfo.Scene.
                    RegionInfo.Logger.ErrorFormat("[{0}] Script function \"{1}\" was not found.", Name, FunctionName);
                    return;
                }

                // Execute script function
                try
                {
                    InternalFunctions[FunctionName].DynamicInvoke(p.Params);
                }
                catch (Exception e)
                {
                    RegionInfo.Logger.ErrorFormat("[{0}] Execute \"{1}\" failed: {2}", Name, FunctionName, e.ToString());
                }
            }
        }

        /// <summary>
        /// Cache functions into a dictionary with delegates. Should be faster than reflection.
        /// </summary>
        private void CacheInternalFunctions()
        {
            Type scriptObjectType = ScriptObject.GetType();
            InternalFunctions = new Dictionary<string, Delegate>();

            MethodInfo[] methods = scriptObjectType.GetMethods();
            lock (InternalFunctions)
            {
                // Read all methods into a dictionary
                foreach (MethodInfo mi in methods)
                {
                    // TODO: We don't support overloading
                    if (!InternalFunctions.ContainsKey(mi.Name))
                        InternalFunctions.Add(mi.Name, Delegate.CreateDelegate(scriptObjectType, ScriptObject, mi));
                    else
                        RegionInfo.Logger.ErrorFormat("[{0}] Error: Script function \"{1}\" is already added. We do not support overloading.",
                            Name, mi.Name);
                }
            }
        }

    }
}