summaryrefslogblamecommitdiff
path: root/src/scripting/lua.cpp
blob: 099e3268002a17f5dddded370ee2744bde5dc514 (plain) (tree)
















































                                                                             
                           









































                                                                                 
                              
 


                                     






                                              
                                        
     



                                                                          

                 
                                   




































                                                                        
/*
 *  The Mana World Server
 *  Copyright 2007 The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  The Mana World 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
 *  any later version.
 *
 *  The Mana World 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 The Mana World; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  $Id$
 */

#include <cassert>

extern "C" {
#include <lualib.h>
#include <lauxlib.h>
}

#include "resourcemanager.h"
#include "scripting/script.hpp"
#include "utils/logger.h"

/**
 * Implementation of the Script class for Lua.
 */
class LuaScript: public Script
{
    public:

        LuaScript(lua_State *);

        ~LuaScript();

        void prepare(std::string const &);

        void push(int);

        void push(Thing *);

        int execute();

    private:

        lua_State *mState;
        int nbArgs;
};

LuaScript::LuaScript(lua_State *s):
    mState(s),
    nbArgs(-1)
{
    luaL_openlibs(mState);
    // A Lua state is like a function, so "execute" it in order to initialize it.
    int res = lua_pcall(mState, 0, 0, 0);
    if (res)
    {
        LOG_ERROR("Failure while initializing Lua script: "
                  << lua_tostring(mState, 0));
    }
}

LuaScript::~LuaScript()
{
    lua_close(mState);
}

void LuaScript::prepare(std::string const &name)
{
    assert(nbArgs == -1);
    lua_getglobal(mState, name.c_str());
    nbArgs = 0;
}

void LuaScript::push(int v)
{
    assert(nbArgs >= 0);
    lua_pushinteger(mState, v);
    ++nbArgs;
}

void LuaScript::push(Thing *v)
{
    assert(nbArgs >= 0);
    lua_pushlightuserdata(mState, v);
    ++nbArgs;
}

int LuaScript::execute()
{
    assert(nbArgs >= 0);
    int res = lua_pcall(mState, nbArgs, 1, 0);
    nbArgs = -1;
    if (res || !lua_isnumber(mState, 1))
    {
        LOG_WARN("Failure while calling Lua function: error=" << res
                 << ", type=" << lua_typename(mState, lua_type(mState, 1))
                 << ", message=" << lua_tostring(mState, 1));
        lua_pop(mState, 1);
        return 0;
    }
    res = lua_tointeger(mState, 1);
    lua_pop(mState, 1);
    return res;
}

static Script *loadScript(std::string const &filename)
{
    // Load the file through resource manager.
    ResourceManager *resman = ResourceManager::getInstance();
    int fileSize;
    char *buffer = (char *)resman->loadFile(filename, fileSize);
    if (!buffer) return NULL;

    lua_State *s = luaL_newstate();
    int res = luaL_loadstring(s, buffer);
    free(buffer);

    switch(res)
    {
        case 0:
            LOG_INFO("Successfully loaded script " << filename);
            return new LuaScript(s);
        case LUA_ERRSYNTAX:
            LOG_ERROR("Syntax error while loading script " << filename);
    }

    lua_close(s);
    return NULL;
}

struct LuaRegister
{
    LuaRegister() { Script::registerEngine("lua", loadScript); }
};

static LuaRegister dummy;