Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/Script.cc @ 1102

Last change on this file since 1102 was 1102, checked in by bknecht, 16 years ago

lua50 compatiple level code and loading, should work on tardis as well now

File size: 7.6 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 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "Script.h"
30
31#include <fstream>
32#include <map>
33
34#include "CoreIncludes.h"
35
36extern "C" {
37#include <lualib.h>
38#include <lauxlib.h>
39}
40
41#include "tolua++.h"
42#include "tolua/tolua_bind.h"
43
44namespace orxonox
45{
46  Script* Script::singletonRef = NULL;
47
48  Script::Script()
49  {
50    luaState_ = lua_open();
51    luaSource_ = "";
52#if LUA_VERSION_NUM == 501
53    luaL_openlibs(luaState_);
54#else
55    luaopen_base(luaState_);
56    luaopen_string(luaState_);
57    luaopen_table(luaState_);
58    luaopen_math(luaState_);
59    luaopen_io(luaState_);
60    luaopen_debug(luaState_);
61#endif
62    tolua_orxonox_open(luaState_);
63    output_ = "";
64  }
65
66  void Script::luaPrint(std::string str)
67  {
68    output_ += str;
69    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
70  }
71
72  /**
73      @brief Loads the specified file line by line
74      @param filename The filename of the file
75      @param luaTags if true, the loaded file gets stripped off luaTags
76  */
77  void Script::loadFile(std::string filename, bool luaTags)
78  {
79    std::ifstream file;
80    file.open(filename.c_str(), std::fstream::in);
81
82    if (!file.is_open())
83    {
84      // some error msg
85    }
86
87    char line[1024];
88    std::string levelString = "";
89
90    while (file.good() && !file.eof())
91    {
92      file.getline(line, 1024);
93      levelString += line;
94      levelString += "\n";
95    }
96
97    file.close();
98    //std::string output;
99
100    if (luaTags) luaSource_ = replaceLuaTags(levelString);
101    COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
102  }
103
104#if LUA_VERSION_NUM != 501
105  const char * Script::lua_Chunkreader(lua_State *L, void *data, size_t *size)
106  {
107    LoadS* ls = ((LoadS*)data);
108    if (ls->size == 0) return NULL;
109    *size = ls->size;
110    ls->size = 0;
111    return ls->s;
112  }
113#endif
114  void Script::run()
115  {
116    int error = 0;
117    std::string init = "local scr = orxonox.Script:getInstance()\nprint = function(s)\nscr:luaPrint(s)\nend\n";
118    init += luaSource_;
119#if LUA_VERSION_NUM == 501
120    error = luaL_loadstring(luaState_, init.c_str());
121#else
122    LoadS ls;
123    ls.s = init.c_str();
124    ls.size = init.size();
125    error = lua_load(luaState_, &orxonox::Script::lua_Chunkreader, &ls, init.c_str());
126#endif
127    if (error == 0)
128      error = lua_pcall(luaState_, 0, 0, 0);
129    if (error != 0) COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
130  }
131
132  unsigned int Script::getNextQuote(const std::string& text, unsigned int start)
133  {
134    unsigned int quote = start - 1;
135
136    while ((quote = text.find('\"', quote + 1)) != std::string::npos)
137    {
138      unsigned int backslash = quote;
139      unsigned int numbackslashes = 0;
140      for (; backslash > 0; backslash--, numbackslashes++)
141        if (text[backslash - 1] != '\\')
142          break;
143
144      if (numbackslashes % 2 == 0)
145        break;
146    }
147
148    return quote;
149  }
150
151  std::string Script::replaceLuaTags(const std::string& text)
152  {
153    // chreate map with all Lua tags
154    std::map<unsigned int, bool> luaTags;
155    {
156      unsigned int pos = 0;
157      while ((pos = text.find("<?lua", pos)) != std::string::npos)
158        luaTags[pos++] = true;
159    }
160    {
161      unsigned int pos = 0;
162      while ((pos = text.find("?>", pos)) != std::string::npos)
163        luaTags[pos++] = false;
164    }
165
166    // erase all tags from the map that are between two quotes
167    {
168      std::map<unsigned int, bool>::iterator it = luaTags.begin();
169      std::map<unsigned int, bool>::iterator it2 = it;
170      bool bBetweenQuotes = false;
171      unsigned int pos = 0;
172      while ((pos = getNextQuote(text, pos)) != std::string::npos)
173      {
174        while ((it != luaTags.end()) && (it->first < pos))
175        {
176          if (bBetweenQuotes) {
177            it2++;
178            if(it->second && !(it2->second) && it2->first < pos)
179              it = ++it2;
180            else
181              luaTags.erase(it++);
182          }
183          else
184            ++it;
185        }
186        bBetweenQuotes = !bBetweenQuotes;
187        pos++;
188      }
189    }
190
191    // check whether on every opening <?lua tag a closing ?> tag follows
192    {
193      bool expectedValue = true;
194      for (std::map<unsigned int, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
195      {
196        if ((*it).second == expectedValue)
197          expectedValue = !expectedValue;
198        else
199        {
200          expectedValue = false;
201          break;
202        }
203      }
204      if (!expectedValue) {
205        // todo: errorhandling
206        return "";
207      }
208    }
209
210    // cut the original string into pieces and put them together with print() instead of lua tags
211    std::string output;
212    {
213      std::map<unsigned int, bool>::iterator it = luaTags.begin();
214      bool bInPrintFunction = true;
215      unsigned int start = 0;
216      unsigned int end = 0;
217
218      do
219      {
220        if (it != luaTags.end())
221          end = (*(it++)).first;
222        else
223          end = std::string::npos;
224
225        unsigned int equalSignCounter = 0;
226
227        if (bInPrintFunction)
228        {
229          // count ['='[ and ]'='] and replace tags with print([[ and ]])
230          std::string temp = text.substr(start, end - start);
231          {
232            unsigned int pos = 0;
233            while ((pos = temp.find('[', pos)) != std::string::npos)
234            {
235              unsigned int tempCounter = 1;
236              unsigned int tempPos = pos++;
237              while(temp[++tempPos] == '=') {
238                tempCounter++;
239              }
240              if(temp[tempPos] != '[') {
241                tempCounter = 0;
242              }
243              else if(tempCounter == 0) {
244                tempCounter = 1;
245              }
246              if (tempCounter > equalSignCounter)
247                equalSignCounter = tempCounter;
248            }
249          }
250          {
251            unsigned int pos = 0;
252            while ((pos = temp.find(']', pos)) != std::string::npos)
253            {
254              unsigned int tempCounter = 1;
255              unsigned int tempPos = pos++;
256              while(temp[++tempPos] == '=') {
257                tempCounter++;
258              }
259              if(temp[tempPos] != ']') {
260                tempCounter = 0;
261              }
262              else if(tempCounter == 0) {
263                tempCounter = 1;
264              }
265              if (tempCounter > equalSignCounter)
266                equalSignCounter = tempCounter;
267            }
268          }
269          std::string equalSigns = "";
270          for(unsigned int i = 0; i < equalSignCounter; i++) {
271            equalSigns += "=";
272          }
273          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
274          start = end + 5;
275        }
276        else
277        {
278          output += text.substr(start, end - start);
279          start = end + 2;
280        }
281
282        bInPrintFunction = !bInPrintFunction;
283      }
284      while (end != std::string::npos);
285    }
286
287    return output;
288  }
289
290}
Note: See TracBrowser for help on using the repository browser.