Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/LuaState.cc @ 6014

Last change on this file since 6014 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Benjamin Knecht
24 *      Reto Grieder
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "LuaState.h"
31
32#include <tolua/tolua++.h>
33extern "C" {
34#include <lua.h>
35#include <lualib.h>
36}
37
38#include "util/Debug.h"
39#include "Resource.h"
40#include "ToluaBindCore.h"
41
42namespace orxonox
43{
44    LuaState::ToluaInterfaceMap LuaState::toluaInterfaces_s;
45    std::vector<LuaState*> LuaState::instances_s;
46
47    // Do this after declaring toluaInterfaces_s and instances_s to avoid larger problems
48    DeclareToluaInterface(Core);
49
50    LuaState::LuaState()
51        : bIsRunning_(false)
52        , includeParseFunction_(NULL)
53    {
54        // Create new lua state and configure it
55        luaState_ = lua_open();
56#if LUA_VERSION_NUM == 501
57        luaL_openlibs(luaState_);
58#else
59        luaopen_base(luaState_);
60        luaopen_string(luaState_);
61        luaopen_table(luaState_);
62        luaopen_math(luaState_);
63        luaopen_io(luaState_);
64        luaopen_debug(luaState_);
65#endif
66
67        // Open all available tolua interfaces
68        this->openToluaInterfaces(luaState_);
69
70        // Create dummy file info
71        sourceFileInfo_.reset(new ResourceInfo());
72        sourceFileInfo_->group = "General";
73        sourceFileInfo_->size = 0;
74
75        // Push 'this' pointer
76        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
77        lua_setglobal(luaState_, "luaState");
78
79        // Parse init script
80        this->doFile("LuaStateInit.lua");
81    }
82
83    LuaState::~LuaState()
84    {
85        lua_close(luaState_);
86    }
87
88    shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
89    {
90        shared_ptr<ResourceInfo> sourceInfo;
91        if (resourceGroup != "NoResourceGroupProvided")
92            sourceInfo = Resource::getInfo(filename, resourceGroup);
93
94        // Continue search if not explicitely forbidden
95        if (bSearchOtherPaths && sourceInfo == NULL)
96        {
97            // Call might be relative to the file currently being processed
98            sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename, sourceFileInfo_->group);
99            if (sourceInfo == NULL)
100            {
101                // Maybe find something in the same group but in the root path
102                sourceInfo = Resource::getInfo(filename, sourceFileInfo_->group);
103            }
104        }
105        return sourceInfo;
106    }
107
108    void LuaState::includeFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
109    {
110        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
111        if (sourceInfo != NULL)
112            this->includeString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
113        else
114            COUT(2) << "LuaState: Cannot include file '" << filename << "' in resource group '"
115                    << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
116    }
117
118    void LuaState::includeString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
119    {
120        // Parse string with provided include parser (otherwise don't preparse at all)
121        std::string luaInput;
122        if (includeParseFunction_ != NULL)
123            luaInput = (*includeParseFunction_)(code);
124        else
125            luaInput = code;
126
127        this->doString(luaInput, sourceFileInfo);
128    }
129
130    void LuaState::doFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
131    {
132        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
133        if (sourceInfo != NULL)
134            this->doString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
135        else
136            COUT(2) << "LuaState: Cannot do file '" << filename << "' in resource group '"
137                << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
138    }
139
140    void LuaState::doString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
141    {
142        // Save the oold source file info
143        shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
144        // Only override if sourceFileInfo provides useful information
145        if (sourceFileInfo != NULL)
146            sourceFileInfo_ = sourceFileInfo;
147
148        int error = 0;
149#if LUA_VERSION_NUM != 501
150        LoadS ls;
151        ls.s = code.c_str();
152        ls.size = code.size();
153        error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
154#else
155        error = luaL_loadstring(luaState_, code.c_str());
156#endif
157
158        // execute the chunk
159        if (error == 0)
160            error = lua_pcall(luaState_, 0, 1, 0);
161        if (error != 0)
162        {
163            std::string origin;
164            if (sourceFileInfo != NULL)
165                origin = " originating from " + sourceFileInfo_->filename;
166            COUT(2) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
167            // return value is nil
168            lua_pushnil(luaState_);
169        }
170        // push return value because it will get lost since the return value of this function is void
171        lua_setglobal(luaState_, "LuaStateReturnValue");
172
173        // Load the old info again
174        sourceFileInfo_ = oldSourceFileInfo;
175    }
176
177    void LuaState::luaPrint(const std::string& str)
178    {
179        output_ << str;
180    }
181
182    void LuaState::luaLog(unsigned int level, const std::string& message)
183    {
184        OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
185    }
186
187    bool LuaState::fileExists(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
188    {
189        shared_ptr<ResourceInfo> info =  this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
190        if (info == NULL)
191            return false;
192        else
193            return true;
194    }
195
196#if LUA_VERSION_NUM != 501
197    const char * LuaState::lua_Chunkreader(lua_State *L, void *data, size_t *size)
198    {
199        LoadS* ls = static_cast<LoadS*>(data);
200        if (ls->size == 0)
201            return NULL;
202        *size = ls->size;
203        ls->size = 0;
204        return ls->s;
205    }
206#endif
207
208    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
209    {
210        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
211        {
212            if (it->first == name || it->second == function)
213            {
214                COUT(2) << "Warning: Trying to add a Tolua interface with the same name or function." << std::endl;
215                return true;
216            }
217        }
218        toluaInterfaces_s[name] = function;
219
220        // Open interface in all LuaStates
221        for (std::vector<LuaState*>::const_iterator it = instances_s.begin(); it != instances_s.end(); ++it)
222            (*function)((*it)->luaState_);
223
224        // Return dummy bool
225        return true;
226    }
227
228    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
229    {
230        ToluaInterfaceMap::iterator it = toluaInterfaces_s.find(name);
231        if (it == toluaInterfaces_s.end())
232        {
233            COUT(2) << "Warning: Cannot remove Tolua interface '" << name << "': Not found" << std::endl;
234            return true;
235        }
236
237        // Close interface in all LuaStates
238        for (std::vector<LuaState*>::const_iterator itState = instances_s.begin(); itState != instances_s.end(); ++itState)
239        {
240            lua_pushnil((*itState)->luaState_);
241            lua_setglobal((*itState)->luaState_, it->first.c_str());
242        }
243
244        // Remove entry
245        toluaInterfaces_s.erase(it);
246
247        // Return dummy bool
248        return true;
249    }
250
251    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
252    {
253        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
254            (*it->second)(state);
255    }
256
257    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
258    {
259        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
260        {
261            lua_pushnil(state);
262            lua_setglobal(state, it->first.c_str());
263        }
264    }
265}
Note: See TracBrowser for help on using the repository browser.