示例#1
0
        /// <summary>
        /// Spawns monster.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - int    monsterId
        /// - string mapName
        /// - float  x
        /// - float  y
        /// - float  z
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int spawn(IntPtr L)
        {
            var monsterId = Melua.luaL_checkinteger(L, 1);
            var mapName   = Melua.luaL_checkstring(L, 2);
            var x         = (float)Melua.luaL_checknumber(L, 3);
            var y         = (float)Melua.luaL_checknumber(L, 4);
            var z         = (float)Melua.luaL_checknumber(L, 5);

            Melua.lua_pop(L, 5);

            var map = ChannelServer.Instance.World.GetMap(mapName);

            if (map == null)
            {
                return(Melua.melua_error(L, "Map '{0}' not found.", mapName));
            }

            var monster = new Monster(monsterId, NpcType.Monster);

            monster.Position = new Position(x, y, z);

            map.AddMonster(monster);

            return(0);
        }
示例#2
0
        private int loadxmlfile(IntPtr L)
        {
            var fileName = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            fileName = ModPack.NormalizePath(fileName);

            if (!fileName.EndsWith(".xml") && !fileName.EndsWith(".xml.compiled"))
            {
                return(Melua.melua_error(L, "Expected XML file extension."));
            }

            if (!FileExistsInPackages(fileName))
            {
                return(Melua.melua_error(L, "File '{0}' not found in packages.", fileName));
            }

            try
            {
                _loadedXmlFile   = fileName;
                _loadedXmlModder = _modPack.GetXmlModder(fileName);

                return(0);
            }
            catch (XmlException ex)
            {
                _loadedXmlFile   = null;
                _loadedXmlModder = null;

                return(Melua.melua_error(L, "Failed to parse XML: '{0}'", ex.Message));
            }
        }
示例#3
0
        private int addelement(IntPtr L)
        {
            if (!IsXmlFileLoaded())
            {
                return(Melua.melua_error(L, "No XML file loaded."));
            }

            var selector = Melua.luaL_checkstring(L, 1);
            var xml      = Melua.luaL_checkstring(L, 2);

            Melua.lua_pop(L, 2);

            if (!IsXPathValid(selector))
            {
                return(Melua.melua_error(L, "Invalid XPath."));
            }

            XElement element;

            try
            {
                element = XElement.Parse(xml);
            }
            catch (XmlException ex)
            {
                return(Melua.melua_error(L, "Failed to parse XML element: {0}", ex.Message));
            }

            var modder = _loadedXmlModder;

            _modPack.AddMod(new XmlElementAdder(modder, selector, element));

            return(0);
        }
示例#4
0
        /// <summary>
        /// Removes the specified amount of items with the given id from
        /// character's inventory.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - int itemId
        /// - int amount
        ///
        /// Result:
        /// - int removedCount
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int removeitem(IntPtr L)
        {
            var conn      = this.GetConnectionFromState(L);
            var character = conn.SelectedCharacter;

            var itemId = Melua.luaL_checkinteger(L, 1);
            var amount = Melua.luaL_checkinteger(L, 2);

            Melua.lua_pop(L, 2);

            var itemData = ChannelServer.Instance.Data.ItemDb.Find(itemId);

            if (itemData == null)
            {
                return(Melua.melua_error(L, "Unknown item id."));
            }

            amount = Math.Max(0, amount);

            var removed = character.Inventory.Remove(itemId, amount, InventoryItemRemoveMsg.Given);

            Melua.lua_pushinteger(L, removed);

            return(1);
        }
示例#5
0
        /// <summary>
        /// Adds the specified amount of items to the character's inventory.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - int itemId
        /// - int amount
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int additem(IntPtr L)
        {
            var conn      = this.GetConnectionFromState(L);
            var character = conn.SelectedCharacter;

            var itemId = Melua.luaL_checkinteger(L, 1);
            var amount = Melua.luaL_checkinteger(L, 2);

            Melua.lua_pop(L, 2);

            var itemData = ChannelServer.Instance.Data.ItemDb.Find(itemId);

            if (itemData == null)
            {
                return(Melua.melua_error(L, "Unknown item id."));
            }

            try
            {
                character.Inventory.Add(itemId, amount, InventoryAddType.PickUp);
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
                return(Melua.melua_error(L, "Failed to add item to inventory."));
            }

            return(0);
        }
示例#6
0
        /// <summary>
        /// Removes thread and the associated state from the manager.
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public void RemoveThread(LuaThread thread)
        {
            if (thread == null || thread.L == IntPtr.Zero)
            {
                return;
            }

            lock (_glSyncLock)
            {
                // Remove thread from stack and update all stack indexes,
                // as the removal will shift all following elements.
                Melua.lua_remove(GL, thread.StackIndex);

                lock (_states)
                {
                    foreach (var state in _states.Values)
                    {
                        if (state.LuaThread.StackIndex > thread.StackIndex)
                        {
                            state.LuaThread.StackIndex--;
                        }
                    }
                }
            }

            lock (_states)
                _states.Remove(thread.L);

            // Apparently there is no lua_closethread()?
        }
示例#7
0
        /// <summary>
        /// Loads file from given path.
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private bool LoadFile(string filePath)
        {
            if (!File.Exists(filePath))
            {
                Log.Error("ScriptManager.LoadFile: File '{0}' not found.", filePath);
                return(false);
            }

            // Load file
            var result = Melua.luaL_loadfile(GL, filePath);

            if (result != 0)
            {
                Log.Error("ScriptManager.LoadFile: Failed to compile '{0}' (Error code: {1}).\n{2}", filePath, result, Melua.lua_tostring(GL, -1));
                return(false);
            }

            // Execute it
            if (Melua.lua_pcall(GL, 0, 0, 0) != 0)
            {
                Log.Error("ScriptManager.LoadFile: Failed to load '{0}'.\n{1}", filePath, Melua.lua_tostring(GL, -1));
                return(false);
            }

            return(true);
        }
示例#8
0
        /// <summary>
        /// Calls function with connection's script state.
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="functionName"></param>
        public void Call(ChannelConnection conn, string functionName)
        {
            var NL = conn.ScriptState.NL;

            Melua.lua_getglobal(NL, functionName);
            if (Melua.lua_isnil(NL, -1))
            {
                Log.Error("ScriptManager.Call: Function '{0}' not found.", functionName);
                return;
            }

            var result = Melua.lua_resume(NL, 0);

            // Log error if result is not success or yield
            if (result != 0 && result != Melua.LUA_YIELD)
            {
                Log.Error("ScriptManager.Call: Error while executing '{0}' for {1}.\n{2}", functionName, conn.Account.Name, Melua.lua_tostring(NL, -1));
                result = 0;                 // Set to 0 to close dialog on error
            }

            // Close dialog if end of function was reached
            if (result == 0)
            {
                Send.ZC_DIALOG_CLOSE(conn);
                conn.ScriptState.CurrentNpc = null;
            }
        }
示例#9
0
        /// <summary>
        /// Sends dialog select message to client, showing a message and a
        /// list of options to select from.
        /// </summary>
        /// <remarks>
        /// Select can take an arbitrary amount of options.
        ///
        /// Parameters:
        /// - string message
        /// - string options...
        ///
        /// Result:
        /// The number of the selected option, starting from 1.
        /// Returns 0 on error.
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int select(IntPtr L)
        {
            // Check arguments and return 0 on error
            var argc = Melua.lua_gettop(L);

            if (argc == 0)
            {
                Log.Warning("select: No arguments.");
                Melua.lua_pushinteger(L, 0);
                return(1);
            }

            var conn = this.GetConnectionFromState(L);

            // Get arguments, first argument is the message, everything afterwards
            // is one option to select from.
            var args = new string[argc];

            for (int i = 1; i <= argc; ++i)
            {
                var arg = Melua.luaL_checkstring(L, i);
                this.HandleCustomCode(conn, ref arg);
                args[i - 1] = arg;
            }

            Melua.lua_pop(L, argc);

            this.AttachNpcName(conn, ref args[0]);

            Send.ZC_DIALOG_SELECT(conn, args);

            return(Melua.lua_yield(L, 1));
        }
示例#10
0
        /// <summary>
        /// Sends dialog input message, showing a message and a text field,
        /// for the user to put in a string.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - string message
        ///
        /// Result:
        /// The string put in by the user.
        /// Returns empty string on error.
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int input(IntPtr L)
        {
            // Check arguments and return empty string on error
            var argc = Melua.lua_gettop(L);

            if (argc == 0)
            {
                Log.Warning("input: No arguments.");
                Melua.lua_pushstring(L, "");
                return(1);
            }

            var conn = this.GetConnectionFromState(L);

            // Get message
            var msg = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            this.HandleCustomCode(conn, ref msg);
            this.AttachNpcName(conn, ref msg);

            Send.ZC_DIALOG_STRINGINPUT(conn, msg);

            return(Melua.lua_yield(L, 1));
        }
示例#11
0
        /// <summary>
        /// Pushes the arguments onto the Lua stack.
        /// </summary>
        /// <param name="NL"></param>
        /// <param name="args"></param>
        private static void PushArguments(IntPtr NL, params object[] args)
        {
            foreach (var arg in args)
            {
                switch (arg)
                {
                case byte v: Melua.lua_pushinteger(NL, v); break;

                case bool v: Melua.lua_pushboolean(NL, v); break;

                case short v: Melua.lua_pushinteger(NL, v); break;

                case int v: Melua.lua_pushinteger(NL, v); break;

                case float v: Melua.lua_pushnumber(NL, v); break;

                case double v: Melua.lua_pushnumber(NL, v); break;

                case string v: Melua.lua_pushstring(NL, v); break;

                default:
                {
                    Log.Warning("ScriptManager.PushArguments: Invalid argument type '{0}', pushing 'int 0' instead.", arg.GetType().Name);
                    Melua.lua_pushinteger(NL, 0);
                    break;
                }
                }
            }
        }
示例#12
0
        public bool LoadMods(string modPath)
        {
            var errors = false;

            var mainModFiles = Directory.EnumerateFiles(modPath, "main.lua", SearchOption.AllDirectories);

            if (!mainModFiles.Any())
            {
                return(false);
            }

            Trace.WriteLine("Mods found: " + mainModFiles.Count());

            foreach (var filePath in mainModFiles)
            {
                var folderPath = (Path.GetDirectoryName(filePath));
                var folderName = Path.GetFileName(folderPath);

                _cwd = Path.GetFullPath(folderPath);
                this.ModCount++;

                Trace.WriteLine(string.Format("Loading '{0}'...", folderName));

                if (Melua.luaL_dofile(L, filePath) != 0)
                {
                    Trace.WriteLine(string.Format("Error in {1}", folderName, Melua.lua_tostring(L, -1)));
                    errors = true;
                }
            }

            return(errors);
        }
示例#13
0
        /// <summary>
        /// Sends dialog numberrange message, showing a message and a small text field,
        /// for the user to put in a number.
        /// </summary>
        /// <remarks>
        /// NUMBERRANGE uses CZ_DIALOG_SELECT for its response,
        /// which means the number range is that of a byte, 0~255.
        ///
        /// Parameters:
        /// - string message
        /// - int min (optional, defaults to 0)
        /// - int max (optional, defaults to 255)
        ///
        /// Result:
        /// The number put in by the user.
        /// Returns 0 on error.
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int numinput(IntPtr L)
        {
            // Check arguments and return 0 on error
            var argc = Melua.lua_gettop(L);

            if (argc == 0)
            {
                Log.Warning("numinput: No arguments.");
                Melua.lua_pushinteger(L, 0);
                return(1);
            }

            var conn = this.GetConnectionFromState(L);

            int min = 0, max = 255;

            // Get arguments
            var msg = Melua.luaL_checkstring(L, 1);

            if (argc >= 3)
            {
                min = Melua.luaL_checkinteger(L, 2);
                max = Melua.luaL_checkinteger(L, 3);
            }

            Melua.lua_pop(L, argc);

            this.HandleCustomCode(conn, ref msg);
            this.AttachNpcName(conn, ref msg);

            Send.ZC_DIALOG_NUMBERRANGE(conn, msg, min, max);

            return(Melua.lua_yield(L, 1));
        }
示例#14
0
        private int include(IntPtr L)
        {
            var path = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            return(this.DoPath(L, path, false));
        }
示例#15
0
        /// <summary>
        /// Registers function on global Lua state.
        /// </summary>
        /// <param name="functionName"></param>
        private void Register(Melua.LuaNativeFunction function)
        {
            // Keep a reference, so it's not garbage collected...?
            var func = new Melua.LuaNativeFunction(function);

            _functions.Add(func);
            Melua.lua_register(GL, function.Method.Name, func);
        }
示例#16
0
        private int require(IntPtr L)
        {
            var path = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            return(this.DoPath(L, path, true));
        }
示例#17
0
        /// <summary>
        /// Returns a script state for the connection.
        /// </summary>
        /// <param name="conn"></param>
        /// <returns></returns>
        public ScriptState CreateScriptState(ChannelConnection conn)
        {
            var NL    = Melua.lua_newthread(GL);
            var state = new ScriptState(conn, NL);

            lock (_states)
                _states.Add(NL, state);
            return(state);
        }
示例#18
0
        //-----------------------------------------------------------------//
        // SCRIPT FUNCTIONS												   //
        //-----------------------------------------------------------------//

        /// <summary>
        /// Prints message in console using Console.WriteLine.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - string message
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int print(IntPtr L)
        {
            var msg = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            Console.WriteLine(msg);

            return(0);
        }
示例#19
0
        //-----------------------------------------------------------------//
        // SCRIPT FUNCTIONS												   //
        //-----------------------------------------------------------------//

        /// <summary>
        /// Prints and logs debug message.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - string message
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int logdebug(IntPtr L)
        {
            var msg = Melua.luaL_checkstring(L, 1);

            Melua.lua_pop(L, 1);

            Log.Debug(msg);

            return(0);
        }
示例#20
0
        /// <summary>
        /// Returns table, containing information about the current date/time.
        /// </summary>
        /// <remarks>
        /// Result:
        /// {
        ///		integer year,     -- Current year
        ///		integer month,    -- Current month
        ///		integer day,      -- Current day
        ///		integer weekday,  -- Day of the week (0-6), starting on Sunday
        ///		integer yearday,  -- Day of the current year
        ///		integer hour,     -- Current hours (0-23)
        ///		integer min,      -- Current minutes (0-59)
        ///		integer sec,      -- Current seconds (0-59)
        ///		integer msec,     -- Current milliseconds (0-999)
        ///		boolean isdst,    -- Is Daylight Saving Time?
        ///		integer unixts,   -- Unix timestamp
        /// }
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int gettime(IntPtr L)
        {
            var now = DateTime.Now;

            // TODO: Could a general table generation like this be cached?

            Melua.lua_newtable(L);

            Melua.lua_pushstring(L, "year");
            Melua.lua_pushinteger(L, now.Year);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "month");
            Melua.lua_pushinteger(L, now.Month);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "day");
            Melua.lua_pushinteger(L, now.Day);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "weekday");
            Melua.lua_pushinteger(L, (int)now.DayOfWeek);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "yearday");
            Melua.lua_pushinteger(L, now.DayOfYear);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "hour");
            Melua.lua_pushinteger(L, now.Hour);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "min");
            Melua.lua_pushinteger(L, now.Minute);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "sec");
            Melua.lua_pushinteger(L, now.Second);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "msec");
            Melua.lua_pushinteger(L, now.Millisecond);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "isdst");
            Melua.lua_pushboolean(L, now.IsDaylightSavingTime());
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "unixts");
            Melua.lua_pushinteger(L, (int)(now.ToUniversalTime().Subtract(UnixEpoch)).TotalSeconds);
            Melua.lua_settable(L, -3);

            return(1);
        }
示例#21
0
        /// <summary>
        /// Called if Lua panics.
        /// </summary>
        /// <param name="L"></param>
        /// <returns></returns>
        private int OnPanic(IntPtr L)
        {
            var error = string.Format("unprotected error in call to Lua API ({0})", Melua.lua_tostring(L, -1));

            // Throwing an exception to get out of here, which should stop
            // Lua from exiting the host process, causes a stack overflow
            // for some reason.
            //throw new Exception("Lua panic: " + error);

            Log.Error("Lua panic: " + error);
            return(0);
        }
示例#22
0
文件: Melua.cs 项目: xyfc/Melua
        public void type()
        {
            var L = Melua.luaL_newstate();

            Melua.lua_pushinteger(L, 123);
            Assert.Equal(Melua.LUA_TNUMBER, Melua.lua_type(L, -1));

            Melua.lua_pushstring(L, "123");
            Assert.Equal(Melua.LUA_TSTRING, Melua.lua_type(L, -1));

            Melua.lua_newtable(L);
            Assert.Equal(Melua.LUA_TTABLE, Melua.lua_type(L, -1));
        }
示例#23
0
文件: Melua.cs 项目: xyfc/Melua
        public void typename()
        {
            var L = Melua.luaL_newstate();

            Melua.lua_pushinteger(L, 123);
            Assert.Equal("number", Melua.luaL_typename(L, -1));

            Melua.lua_pushstring(L, "123");
            Assert.Equal("string", Melua.luaL_typename(L, -1));

            Melua.lua_newtable(L);
            Assert.Equal("table", Melua.luaL_typename(L, -1));
        }
示例#24
0
文件: Melua.cs 项目: xyfc/Melua
        public void tonumber()
        {
            var L = Melua.luaL_newstate();

            Melua.lua_pushstring(L, "123");
            Assert.Equal(123, Melua.lua_tonumber(L, -1));

            Melua.lua_pushstring(L, "0x123");
            Assert.Equal(0x123, Melua.lua_tonumber(L, -1));

            Melua.lua_pushstring(L, "0x12AB34");
            Assert.Equal(0x12AB34, Melua.lua_tonumber(L, -1));
        }
示例#25
0
        private int removeelements(IntPtr L)
        {
            if (!IsXmlFileLoaded())
            {
                return(Melua.melua_error(L, "No XML file loaded."));
            }

            var selectors = new HashSet <string>();

            if (Melua.lua_isstring(L, -1))
            {
                var selector = Melua.luaL_checkstring(L, 1);
                Melua.lua_pop(L, 1);

                if (!IsXPathValid(selector))
                {
                    return(Melua.melua_error(L, "Invalid XPath."));
                }

                selectors.Add(selector);
            }
            else if (Melua.lua_istable(L, -1))
            {
                Melua.lua_pushnil(L);
                while (Melua.lua_next(L, -2) != 0)
                {
                    var selector = Melua.luaL_checkstring(L, -1);
                    Melua.lua_pop(L, 1);

                    if (!IsXPathValid(selector))
                    {
                        return(Melua.melua_error(L, "Invalid XPath."));
                    }

                    selectors.Add(selector);
                }
            }
            else
            {
                return(Melua.melua_error(L, "Invalid argument type '{0}'.", Melua.luaL_typename(L, -1)));
            }

            var modder = _loadedXmlModder;

            foreach (var selector in selectors)
            {
                _modPack.AddMod(new XmlElementRemover(modder, selector));
            }

            return(0);
        }
示例#26
0
        /// <summary>
        /// Resumes dialog script after yielding.
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="argument"></param>
        public void ResumeDialog(ChannelConnection conn, params object[] arguments)
        {
            if (conn.ScriptState.LuaThread == null)
            {
                Send.ZC_DIALOG_CLOSE(conn);
                Log.Warning("ScriptManager: Resume on empty ScriptState from user '{0}'.", conn.Account.Name);
                return;
            }

            var NL   = conn.ScriptState.LuaThread.L;
            var argc = arguments?.Length ?? 0;

            // Reset current shop in case we came from one.
            conn.ScriptState.CurrentShop = null;

            if (argc != 0)
            {
                PushArguments(NL, arguments);

                // If arguments were passed, we can assume we're coming from
                // a selection handler, which's windows don't disappear when
                // sending the next message. So let's close it before
                // continuing.
                Send.ZC_DIALOG_CLOSE(conn);
            }

            var result = Melua.lua_resume(NL, argc);

            // Log error if result is not success or yield
            if (result != 0 && result != Melua.LUA_YIELD)
            {
                Log.Error("ScriptManager.Call: Error while resuming script for {0}.\n{1}", conn.Account.Name, Melua.lua_tostring(NL, -1));
                result = 0;                 // Set to 0 to close dialog on error
            }

            // Close dialog if end of function was reached
            if (result == 0)
            {
                // Only close from here if the end was reached after an
                // argument-less resume, since close is already called
                // from the argument handling to get rid of the selection
                // dialog.
                if (argc == 0)
                {
                    Send.ZC_DIALOG_CLOSE(conn);
                }

                conn.ScriptState.Reset();
            }
        }
示例#27
0
文件: Melua.cs 项目: xyfc/Melua
        public void tocfunction()
        {
            var L = Melua.luaL_newstate();
            var n = 0;

            Melua.melua_register(L, "foo", _ => { n += 1; return(0); });
            Melua.melua_register(L, "bar", _ => { var func = Melua.lua_tocfunction(L, 1); func(L); return(0); });

            Melua.luaL_dostring(L, "foo()");
            Assert.Equal(1, n);

            Melua.luaL_dostring(L, "bar(foo)");
            Assert.Equal(2, n);
        }
示例#28
0
        /// <summary>
        /// Changes the player's hairstyle.
        /// </summary>
        /// <remarks>
        /// Parameters:
        /// - int hairId
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int changehair(IntPtr L)
        {
            var conn      = this.GetConnectionFromState(L);
            var character = conn.SelectedCharacter;

            var hairId = Melua.luaL_checkinteger(L, 1);

            Melua.lua_pop(L, 1);

            character.Hair = (byte)hairId;
            Send.ZC_UPDATED_PCAPPEARANCE(character);

            return(0);
        }
示例#29
0
        /// <summary>
        /// Calls function with connection's script state.
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="functionName"></param>
        /// <param name="arguments"></param>
        public ScriptCallResult Call(ChannelConnection conn, string functionName, params object[] arguments)
        {
            if (conn.ScriptState.LuaThread != null)
            {
                Log.Warning("ScriptManager.Call: A previous thread wasn't closed for user '{0}'.", conn.Account.Name);
            }

            // Prepare thread
            conn.ScriptState.LuaThread = this.GetNewThread(conn.ScriptState);

            var NL  = conn.ScriptState.LuaThread.L;
            var top = Melua.lua_gettop(_gL);

            // Get function
            Melua.lua_getglobal(NL, functionName);
            if (Melua.lua_isnil(NL, -1))
            {
                conn.ScriptState.Reset();
                return(new ScriptCallResult(ScriptCallResultType.NotFound));
            }

            // Push all arguments
            var argc = arguments?.Length ?? 0;

            if (argc != 0)
            {
                PushArguments(NL, arguments);
            }

            // Execute the function with the arguments
            var funcResult = Melua.lua_resume(NL, argc);

            // If result is not a success or yield, an error occurred.
            if (funcResult != 0 && funcResult != Melua.LUA_YIELD)
            {
                conn.ScriptState.Reset();

                var errorMessage = string.Format("Error while executing '{0}' for user '{1}': {2}", functionName, conn.Account.Name, Melua.lua_tostring(NL, -1));
                return(new ScriptCallResult(ScriptCallResultType.Error, errorMessage));
            }

            // We currently don't expect functions called this way to yield
            if (funcResult == Melua.LUA_YIELD)
            {
                Log.Warning("ScriptManager.Call: Script function '{0}' yielded for user '{1}', a behavior that's currently not handled.", functionName, conn.Account.Name);
            }

            conn.ScriptState.Reset();
            return(new ScriptCallResult(ScriptCallResultType.Success));
        }
示例#30
0
        /// <summary>
        /// Returns a table with information about the player.
        /// </summary>
        /// <remarks>
        /// Result:
        /// {
        ///		string  name,     -- Character's name
        ///		string  teamName, -- Character's team name
        ///		integer gender,   -- Character's gender
        ///		integer level,    -- Character's level
        ///		integer hp,       -- Character's HP
        ///		integer maxHp,    -- Character's max HP
        ///		integer sp,       -- Character's SP
        ///		integer maxSp,    -- Character's max SP
        ///		integer stamina,  -- Character's stamina
        ///		integer hair,     -- Character's hair
        /// }
        /// </remarks>
        /// <param name="L"></param>
        /// <returns></returns>
        private int getpc(IntPtr L)
        {
            var conn      = this.GetConnectionFromState(L);
            var character = conn.SelectedCharacter;

            Melua.lua_newtable(L);

            Melua.lua_pushstring(L, "name");
            Melua.lua_pushstring(L, character.Name);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "teamName");
            Melua.lua_pushstring(L, character.TeamName);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "gender");
            Melua.lua_pushinteger(L, (int)character.Gender);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "level");
            Melua.lua_pushinteger(L, character.Level);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "hp");
            Melua.lua_pushinteger(L, character.Hp);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "maxHp");
            Melua.lua_pushinteger(L, character.MaxHp);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "sp");
            Melua.lua_pushinteger(L, character.Sp);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "maxSp");
            Melua.lua_pushinteger(L, character.MaxSp);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "stamina");
            Melua.lua_pushinteger(L, character.Stamina);
            Melua.lua_settable(L, -3);

            Melua.lua_pushstring(L, "hair");
            Melua.lua_pushinteger(L, character.Hair);
            Melua.lua_settable(L, -3);

            return(1);
        }