Exemple #1
0
        private bool EnsureScriptEnvironment()
        {
            if (m_scriptEnvironment == null)
            {
                m_scriptEnvironment = new ScriptEnvironment(this);

                if (!m_scriptEnvironment.Create())
                {
                    this.Log().Error("Resource {0} caused an error during loading. Please see the above lines for details.", Name);

                    State = ResourceState.Stopped;
                    return false;
                }
            }

            return true;
        }
Exemple #2
0
        public void TriggerEvent(string eventName, string argsSerialized, int source)
        {
            List <Delegate> eventHandlers;

            if (!m_eventHandlers.TryGetValue(eventName, out eventHandlers))
            {
                return;
            }

            m_luaEnvironment["source"] = source;

            var lastEnvironment = ms_currentEnvironment;

            ms_currentEnvironment = this;

            var oldLastEnvironment = LastEnvironment;

            LastEnvironment = lastEnvironment;

            //var unpacker = (Func<object, LuaResult>)((LuaTable)m_luaEnvironment["msgpack"])["unpack"];
            //var table = unpacker(argsSerialized);

            dynamic  luaEnvironment = m_luaEnvironment;
            LuaTable table          = luaEnvironment.msgpack.unpack(argsSerialized);

            var args = new object[0];

            if (table != null)
            {
                args = new object[table.Length];
                var i = 0;

                foreach (var value in table)
                {
                    args[i] = value.Value;
                    i++;
                }
            }

            foreach (var handler in eventHandlers)
            {
                try
                {
                    var methodParameters = handler.Method.GetParameters();
                    var localArgs        = args;
                    int ignoreAppend     = 0;

                    if (methodParameters.Length >= 1 && (methodParameters.Last().ParameterType == typeof(LuaTable) || methodParameters.First().ParameterType == typeof(Closure)))
                    {
                        ignoreAppend = 1;
                    }

                    localArgs = localArgs.Take(methodParameters.Length - ignoreAppend).ToArray();

                    handler.DynamicInvoke(localArgs);
                }
                catch (Exception e)
                {
                    Game.RconPrint.Print("Error in resource {0}: {1}\n", m_resource.Name, e.Message);

                    this.Log().Error(() => "Error executing event handler for event " + eventName + " in resource " + m_resource.Name + ": " + e.Message, e);

                    PrintLuaStackTrace(e);

                    while (e != null)
                    {
                        if (e.InnerException != null)
                        {
                            this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);

                            PrintLuaStackTrace(e.InnerException);
                        }

                        e = e.InnerException;
                    }

                    //eventHandlers.Clear();

                    ms_currentEnvironment = lastEnvironment;
                    LastEnvironment       = oldLastEnvironment;

                    return;
                }
            }

            ms_currentEnvironment = lastEnvironment;
            LastEnvironment       = oldLastEnvironment;
        }
Exemple #3
0
        public bool Create()
        {
            ScriptEnvironment lastEnvironment = null, oldLastEnvironment = null;

            try
            {
                if (ms_luaState == null)
                {
                    ms_luaState = new Lua();

                    //ms_luaDebug = new LuaStackTraceDebugger();
                    ms_luaDebug = null;

                    if (Resource.Manager.Configuration.ScriptDebug)
                    {
                        ms_luaDebug = new LuaStackTraceDebugger();
                    }

                    ms_luaCompileOptions             = new LuaCompileOptions();
                    ms_luaCompileOptions.DebugEngine = ms_luaDebug;

                    ms_initChunks = new []
                    {
                        ms_luaState.CompileChunk("system/MessagePack.lua", ms_luaCompileOptions),
                        ms_luaState.CompileChunk("system/dkjson.lua", ms_luaCompileOptions),
                        ms_luaState.CompileChunk("system/resource_init.lua", ms_luaCompileOptions)
                    };
                }

                m_luaEnvironment = ms_luaState.CreateEnvironment <LuaGlobal>();

                foreach (var func in ms_luaFunctions)
                {
                    //m_luaEnvironment[func.Key] = Delegate.CreateDelegate
                    var parameters = func.Value.GetParameters()
                                     .Select(p => p.ParameterType)
                                     .Concat(new Type[] { func.Value.ReturnType })
                                     .ToArray();

                    var delegType = Expression.GetDelegateType
                                    (
                        parameters
                                    );

                    var deleg = Delegate.CreateDelegate
                                (
                        delegType,
                        null,
                        func.Value
                                );

                    var expParameters = parameters.Take(parameters.Count() - 1).Select(a => Expression.Parameter(a)).ToArray();

                    var pushedEnvironment = Expression.Variable(typeof(PushedEnvironment));

                    Expression <Func <PushedEnvironment> >   preFunc  = () => PushEnvironment(this);
                    Expression <Action <PushedEnvironment> > postFunc = env => env.PopEnvironment();

                    Expression body;

                    if (func.Value.ReturnType.Name != "Void")
                    {
                        var retval = Expression.Variable(func.Value.ReturnType);

                        body = Expression.Block
                               (
                            func.Value.ReturnType,
                            new[] { retval, pushedEnvironment },

                            Expression.Assign
                            (
                                pushedEnvironment,
                                Expression.Invoke(preFunc)
                            ),

                            Expression.Assign
                            (
                                retval,
                                Expression.Call(func.Value, expParameters)
                            ),

                            Expression.Invoke(postFunc, pushedEnvironment),

                            retval
                               );
                    }
                    else
                    {
                        body = Expression.Block
                               (
                            func.Value.ReturnType,
                            new[] { pushedEnvironment },

                            Expression.Assign
                            (
                                pushedEnvironment,
                                Expression.Invoke(preFunc)
                            ),

                            Expression.Call(func.Value, expParameters),

                            Expression.Invoke(postFunc, pushedEnvironment)
                               );
                    }

                    var lambda = Expression.Lambda(delegType, body, expParameters);

                    m_luaEnvironment[func.Key] = lambda.Compile();
                }

                InitHandler = null;

                /*m_luaNative = LuaL.LuaLNewState();
                 * LuaL.LuaLOpenLibs(m_luaNative);
                 *
                 * LuaLib.LuaNewTable(m_luaNative);
                 * LuaLib.LuaSetGlobal(m_luaNative, "luanet");
                 *
                 * InitHandler = null;
                 *
                 * m_luaState = new NLua.Lua(m_luaNative);*/

                lock (m_luaEnvironment)
                {
                    lastEnvironment       = ms_currentEnvironment;
                    ms_currentEnvironment = this;

                    oldLastEnvironment = LastEnvironment;
                    LastEnvironment    = lastEnvironment;

                    // load global data files
                    foreach (var chunk in ms_initChunks)
                    {
                        m_luaEnvironment.DoChunk(chunk);
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                this.Log().Error(() => "Error creating script environment for resource " + m_resource.Name + ": " + e.Message, e);

                if (e.InnerException != null)
                {
                    this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);
                }

                PrintLuaStackTrace(e);
            }
            finally
            {
                ms_currentEnvironment = lastEnvironment;
                LastEnvironment       = oldLastEnvironment;
            }

            return(false);
        }
        internal static PushedEnvironment PushEnvironment(ScriptEnvironment env)
        {
            var penv = new PushedEnvironment();
            penv.LastEnvironment = ms_currentEnvironment;
            ms_currentEnvironment = env;

            penv.OldLastEnvironment = LastEnvironment;
            LastEnvironment = penv.LastEnvironment;

            return penv;
        }
Exemple #5
0
        public bool Stop()
        {
            if (State != ResourceState.Running && State != ResourceState.Starting)
            {
                throw new InvalidOperationException(string.Format("Tried to stop a resource ({0}) that wasn't running.", Name));
            }

            this.Log().Info("Stopping resource {0} (last state: {1}).", Name, State);

            if (State == ResourceState.Running)
            {
                if (!Manager.TriggerEvent("onResourceStop", -1, Name))
                {
                    return false;
                }
            }

            var dependants = Dependants.GetRange(0, Dependants.Count);

            foreach (var dependant in dependants)
            {
                var dependantResource = Manager.GetResource(dependant);

                dependantResource.Stop();
            }

            Dependants.Clear();

            foreach (var dependency in Dependencies)
            {
                var dependencyResource = Manager.GetResource(dependency);

                dependencyResource.RemoveDependant(Name);
            }

            // remove the watcher
            m_watcher.Dispose();
            m_watcher = null;

            // dispose of the script environment
            m_scriptEnvironment.Dispose();
            m_scriptEnvironment = null;

            if (State == ResourceState.Running)
            {
                // broadcast a stop message to all clients
                var clients = ClientInstances.Clients.Where(c => c.Value.NetChannel != null).Select(c => c.Value);

                foreach (var client in clients)
                {
                    client.SendReliableCommand(0x45E855D7, Encoding.UTF8.GetBytes(Name)); // msgResStop
                }
            }

            // done!
            State = ResourceState.Stopped;

            return true;
        }
        public void Tick()
        {
            var timers = m_timers.GetRange(0, m_timers.Count);
            var now = Time.CurrentTime;

            foreach (var timer in timers)
            {
                if (now >= timer.TickFrom)
                {
                    lock (m_luaEnvironment)
                    {
                        var lastEnvironment = ms_currentEnvironment;
                        ms_currentEnvironment = this;

                        var oldLastEnvironment = LastEnvironment;
                        LastEnvironment = lastEnvironment;

                        try
                        {
                            timer.Function.DynamicInvoke();
                        }
                        catch (Exception e)
                        {
                            this.Log().Error(() => "Error invoking timer in resource " + m_resource.Name + ": " + e.Message, e);

                            PrintLuaStackTrace(e);

                            if (e.InnerException != null)
                            {
                                this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);

                                PrintLuaStackTrace(e.InnerException);
                            }
                        }

                        ms_currentEnvironment = lastEnvironment;
                        LastEnvironment = oldLastEnvironment;

                        m_timers.Remove(timer);
                    }
                }
            }
        }
        public void TriggerEvent(string eventName, string argsSerialized, int source)
        {
            List<Delegate> eventHandlers;

            if (!m_eventHandlers.TryGetValue(eventName, out eventHandlers))
            {
                return;
            }

            m_luaEnvironment["source"] = source;

            var lastEnvironment = ms_currentEnvironment;
            ms_currentEnvironment = this;

            var oldLastEnvironment = LastEnvironment;
            LastEnvironment = lastEnvironment;

            //var unpacker = (Func<object, LuaResult>)((LuaTable)m_luaEnvironment["msgpack"])["unpack"];
            //var table = unpacker(argsSerialized);

            dynamic luaEnvironment = m_luaEnvironment;
            LuaTable table = luaEnvironment.msgpack.unpack(argsSerialized);

            var args = new object[0];

            if (table != null)
            {
                args = new object[table.Length];
                var i = 0;

                foreach (var value in table)
                {
                    args[i] = value.Value;
                    i++;
                }
            }

            foreach (var handler in eventHandlers)
            {
                try
                {
                    var methodParameters = handler.Method.GetParameters();
                    var localArgs = args;
                    int ignoreAppend = 0;

                    if (methodParameters.Length >= 1 && (methodParameters.Last().ParameterType == typeof(LuaTable) || methodParameters.First().ParameterType == typeof(Closure)))
                    {
                        ignoreAppend = 1;
                    }

                    localArgs = localArgs.Take(methodParameters.Length - ignoreAppend).ToArray();

                    handler.DynamicInvoke(localArgs);
                }
                catch (Exception e)
                {
                    Game.RconPrint.Print("Error in resource {0}: {1}\n", m_resource.Name, e.Message);

                    this.Log().Error(() => "Error executing event handler for event " + eventName + " in resource " + m_resource.Name + ": " + e.Message, e);

                    PrintLuaStackTrace(e);

                    while (e != null)
                    {
                        if (e.InnerException != null)
                        {
                            this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);

                            PrintLuaStackTrace(e.InnerException);
                        }

                        e = e.InnerException;
                    }

                    eventHandlers.Clear();

                    ms_currentEnvironment = lastEnvironment;
                    LastEnvironment = oldLastEnvironment;

                    return;
                }
            }

            ms_currentEnvironment = lastEnvironment;
            LastEnvironment = oldLastEnvironment;
        }
        public bool LoadScripts()
        {
            ScriptEnvironment lastEnvironment = null, oldLastEnvironment = null;

            try
            {
                lastEnvironment = ms_currentEnvironment;
                ms_currentEnvironment = this;

                oldLastEnvironment = LastEnvironment;
                LastEnvironment = lastEnvironment;

                // load scripts defined in this resource
                foreach (var script in m_resource.ServerScripts)
                {
                    lock (m_luaEnvironment)
                    {
                        var chunk = ms_luaState.CompileChunk(Path.Combine(m_resource.Path, script), ms_luaCompileOptions);
                        m_luaEnvironment.DoChunk(chunk);
                        m_curChunks.Add(chunk);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                this.Log().Error(() => "Error creating script environment for resource " + m_resource.Name + ": " + e.Message, e);

                if (e.InnerException != null)
                {
                    this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);
                }

                PrintLuaStackTrace(e);
            }
            finally
            {
                ms_currentEnvironment = lastEnvironment;
                LastEnvironment = oldLastEnvironment;
            }

            return false;
        }
        public bool DoInitFile(bool preParse)
        {
            ScriptEnvironment lastEnvironment = null, oldLastEnvironment = null;

            try
            {
                lastEnvironment = ms_currentEnvironment;
                ms_currentEnvironment = this;

                oldLastEnvironment = LastEnvironment;
                LastEnvironment = lastEnvironment;

                lock (m_luaEnvironment)
                {
                    var initFunction = ms_luaState.CompileChunk(Path.Combine(m_resource.Path, "__resource.lua"), ms_luaCompileOptions);
                    var initDelegate = new Func<LuaResult>(() => m_luaEnvironment.DoChunk(initFunction));

                    InitHandler.DynamicInvoke(initDelegate, preParse);
                }

                if (!preParse)
                {
                    foreach (var script in m_serverScripts)
                    {
                        var chunk = ms_luaState.CompileChunk(Path.Combine(m_resource.Path, script), ms_luaCompileOptions);
                        m_luaEnvironment.DoChunk(chunk);
                        m_curChunks.Add(chunk);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                this.Log().Error(() => "Error creating script environment for resource " + m_resource.Name + ": " + e.Message, e);

                if (e.InnerException != null)
                {
                    this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);
                }

                PrintLuaStackTrace(e);
            }
            finally
            {
                ms_currentEnvironment = lastEnvironment;
                LastEnvironment = oldLastEnvironment;
            }

            return false;
        }
        public bool Create()
        {
            ScriptEnvironment lastEnvironment = null, oldLastEnvironment = null;

            try
            {
                if (ms_luaState == null)
                {
                    ms_luaState = new Lua();

                    //ms_luaDebug = new LuaStackTraceDebugger();
                    ms_luaDebug = null;

                    if (Resource.Manager.Configuration.ScriptDebug)
                    {
                        ms_luaDebug = new LuaStackTraceDebugger();
                    }

                    ms_luaCompileOptions = new LuaCompileOptions();
                    ms_luaCompileOptions.DebugEngine = ms_luaDebug;

                    ms_initChunks = new []
                    {
                        ms_luaState.CompileChunk("system/MessagePack.lua", ms_luaCompileOptions),
                        ms_luaState.CompileChunk("system/dkjson.lua", ms_luaCompileOptions),
                        ms_luaState.CompileChunk("system/resource_init.lua", ms_luaCompileOptions)
                    };
                }

                m_luaEnvironment = ms_luaState.CreateEnvironment();

                foreach (var func in ms_luaFunctions)
                {
                    //m_luaEnvironment[func.Key] = Delegate.CreateDelegate
                    var parameters = func.Value.GetParameters()
                                    .Select(p => p.ParameterType)
                                    .Concat(new Type[] { func.Value.ReturnType })
                                    .ToArray();

                    var delegType = Expression.GetDelegateType
                    (
                        parameters
                    );

                    var deleg = Delegate.CreateDelegate
                    (
                        delegType,
                        null,
                        func.Value
                    );

                    var expParameters = parameters.Take(parameters.Count() - 1).Select(a => Expression.Parameter(a)).ToArray();

                    var pushedEnvironment = Expression.Variable(typeof(PushedEnvironment));

                    Expression<Func<PushedEnvironment>> preFunc = () => PushEnvironment(this);
                    Expression<Action<PushedEnvironment>> postFunc = env => env.PopEnvironment();

                    Expression body;

                    if (func.Value.ReturnType.Name != "Void")
                    {
                        var retval = Expression.Variable(func.Value.ReturnType);

                        body = Expression.Block
                        (
                            func.Value.ReturnType,
                            new[] { retval, pushedEnvironment },

                            Expression.Assign
                            (
                                pushedEnvironment,
                                Expression.Invoke(preFunc)
                            ),

                            Expression.Assign
                            (
                                retval,
                                Expression.Call(func.Value, expParameters)
                            ),

                            Expression.Invoke(postFunc, pushedEnvironment),

                            retval
                        );
                    }
                    else
                    {
                        body = Expression.Block
                        (
                            func.Value.ReturnType,
                            new[] { pushedEnvironment },

                            Expression.Assign
                            (
                                pushedEnvironment,
                                Expression.Invoke(preFunc)
                            ),

                            Expression.Call(func.Value, expParameters),

                            Expression.Invoke(postFunc, pushedEnvironment)
                        );
                    }

                    var lambda = Expression.Lambda(delegType, body, expParameters);

                    m_luaEnvironment[func.Key] = lambda.Compile();
                }

                InitHandler = null;

                /*m_luaNative = LuaL.LuaLNewState();
                LuaL.LuaLOpenLibs(m_luaNative);

                LuaLib.LuaNewTable(m_luaNative);
                LuaLib.LuaSetGlobal(m_luaNative, "luanet");

                InitHandler = null;

                m_luaState = new NLua.Lua(m_luaNative);*/

                lock (m_luaEnvironment)
                {
                    lastEnvironment = ms_currentEnvironment;
                    ms_currentEnvironment = this;

                    oldLastEnvironment = LastEnvironment;
                    LastEnvironment = lastEnvironment;

                    // load global data files
                    foreach (var chunk in ms_initChunks)
                    {
                        m_luaEnvironment.DoChunk(chunk);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                this.Log().Error(() => "Error creating script environment for resource " + m_resource.Name + ": " + e.Message, e);

                if (e.InnerException != null)
                {
                    this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);
                }

                PrintLuaStackTrace(e);
            }
            finally
            {
                ms_currentEnvironment = lastEnvironment;
                LastEnvironment = oldLastEnvironment;
            }

            return false;
        }
        public string CallExport(Delegate func, string argsSerialized)
        {
            lock (m_luaEnvironment)
            {
                var lastEnvironment = ms_currentEnvironment;
                ms_currentEnvironment = this;

                var oldLastEnvironment = LastEnvironment;
                LastEnvironment = lastEnvironment;

                string retstr = "";

                try
                {
                    // unpack
                    var unpacker = (Func<string, LuaTable>)((LuaTable)m_luaEnvironment["msgpack"])["unpack"];
                    var table = unpacker(argsSerialized);

                    var args = new object[table.Length];
                    var i = 0;

                    foreach (var value in table)
                    {
                        args[i] = value.Value;
                        i++;
                    }

                    // invoke
                    var objects = (LuaResult)func.DynamicInvoke(args.Take(func.Method.GetParameters().Length - 1).ToArray());

                    // pack return values
                    retstr = EventScriptFunctions.SerializeArguments(objects);
                }
                catch (Exception e)
                {
                    this.Log().Error(() => "Error invoking reference for resource " + m_resource.Name + ": " + e.Message, e);

                    if (e.InnerException != null)
                    {
                        this.Log().Error(() => "Inner exception: " + e.InnerException.Message, e.InnerException);
                    }

                    PrintLuaStackTrace(e);
                }

                ms_currentEnvironment = lastEnvironment;
                LastEnvironment = oldLastEnvironment;

                return retstr;
            }
        }
        static async Task PerformHttpRequest(string url, Func <object, object, object, LuaResult> cb, string method = "GET", string data = "", LuaTable headers = null)
        {
            var webRequest = HttpWebRequest.CreateHttp(url);

            webRequest.Method = method;

            var senv = ScriptEnvironment.CurrentEnvironment;

            if (headers != null)
            {
                foreach (var header in headers)
                {
                    var key   = header.Key.ToString();
                    var value = header.Value.ToString();

                    if (key.Equals("content-type", StringComparison.InvariantCultureIgnoreCase))
                    {
                        webRequest.ContentType = value;
                    }
                    else
                    {
                        webRequest.Headers.Add(key, value);
                    }
                }
            }

            try
            {
                if (data != string.Empty)
                {
                    var reqStream = await webRequest.GetRequestStreamAsync();

                    var dataBytes = Encoding.UTF8.GetBytes(data);

                    await reqStream.WriteAsync(dataBytes, 0, dataBytes.Length);
                }

                var response = await webRequest.GetResponseAsync() as HttpWebResponse;

                // store headers
                var respHeaders = new LuaTable();

                for (int i = 0; i < response.Headers.Count; i++)
                {
                    respHeaders[response.Headers.Keys[i]] = response.Headers[i];
                }

                // get the response
                var respStream   = response.GetResponseStream();
                var streamReader = new StreamReader(respStream);

                var responseText = await streamReader.ReadToEndAsync();

                try
                {
                    var penv = ScriptEnvironment.PushEnvironment(senv);
                    cb(0, responseText, respHeaders);
                    penv.PopEnvironment();
                }
                catch (Exception e)
                {
                    webRequest.Log().Error("Error in callback for web request: {0}", e.Message);

                    ScriptEnvironment.PrintLuaStackTrace(e);
                }
            }
            catch (WebException e)
            {
                webRequest.Log().Warn("Web request to {0} failed: {1}", url, e.Message);

                try
                {
                    var penv = ScriptEnvironment.PushEnvironment(senv);
                    cb((int)((HttpWebResponse)e.Response).StatusCode, null, null);
                    penv.PopEnvironment();
                }
                catch (Exception e2)
                {
                    webRequest.Log().Error("Error in callback for web request: {0}", e2.Message);

                    ScriptEnvironment.PrintLuaStackTrace(e2);
                }
            }
        }