summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-25 19:54:59 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-25 19:54:59 +0000
commit7ce53143a6ea781bb9bd2eb29995c6d160331328 (patch)
tree3a9aa283080572b5cc8fbb0eb9f30a8cdb55e465 /crawl-ref/source
parent648c698c072f989a8e351efbac07a0c9afb9b638 (diff)
downloadcrawl-ref-7ce53143a6ea781bb9bd2eb29995c6d160331328.tar.gz
crawl-ref-7ce53143a6ea781bb9bd2eb29995c6d160331328.zip
.des files can use a global Lua prelude (before maps are defined) that runs
at start of game, before any maps are loaded, and does not run in the context of any specific map. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1654 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/clua.cc22
-rw-r--r--crawl-ref/source/luadgn.cc32
-rw-r--r--crawl-ref/source/luadgn.h12
-rw-r--r--crawl-ref/source/mapdef.cc16
-rw-r--r--crawl-ref/source/mapdef.h3
-rw-r--r--crawl-ref/source/maps.cc46
-rw-r--r--crawl-ref/source/maps.h3
-rw-r--r--crawl-ref/source/util/levcomp.ypp21
8 files changed, 116 insertions, 39 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 63f901f051..8ea71c26e4 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -532,18 +532,22 @@ bool CLua::callfn(const char *fn, int nargs, int nret)
lua_State *ls = state();
if (!ls)
return (false);
-
- lua_getglobal(ls, fn);
- if (!lua_isfunction(ls, -1))
+
+ // If a function is not provided on the stack, get the named function.
+ if (fn)
{
- lua_settop(ls, -nargs - 2);
- return (false);
+ lua_getglobal(ls, fn);
+ if (!lua_isfunction(ls, -1))
+ {
+ lua_settop(ls, -nargs - 2);
+ return (false);
+ }
+
+ // Slide the function in front of its args and call it.
+ if (nargs)
+ lua_insert(ls, -nargs - 1);
}
- // Slide the function in front of its args and call it.
- if (nargs)
- lua_insert(ls, -nargs - 1);
-
lua_call_throttle strangler(this);
int err = lua_pcall(ls, nargs, nret, 0);
set_error(err, ls);
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index bdc5494275..bce024b312 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -7,6 +7,7 @@
#include "AppHdr.h"
#include "clua.h"
+#include "files.h"
#include "luadgn.h"
#include "mapdef.h"
@@ -44,6 +45,26 @@ dlua_chunk::dlua_chunk(const std::string &_context)
clear();
}
+void dlua_chunk::write(FILE *outf) const
+{
+ writeString(outf, chunk, LUA_CHUNK_MAX_SIZE);
+ if (!chunk.empty())
+ {
+ writeString(outf, file);
+ writeLong(outf, first);
+ }
+}
+
+void dlua_chunk::read(FILE *inf)
+{
+ chunk = readString(inf, LUA_CHUNK_MAX_SIZE);
+ if (!chunk.empty())
+ {
+ file = readString(inf);
+ first = readLong(inf);
+ }
+}
+
void dlua_chunk::clear()
{
file.clear();
@@ -82,15 +103,15 @@ int dlua_chunk::check_op(CLua *interp, int err)
return (err);
}
-int dlua_chunk::load(CLua *interp)
+int dlua_chunk::load(CLua &interp)
{
if (trimmed_string(chunk).empty())
return (-1000);
- return check_op(interp,
- interp->loadstring(chunk.c_str(), context.c_str()));
+ return check_op(&interp,
+ interp.loadstring(chunk.c_str(), context.c_str()));
}
-int dlua_chunk::load_call(CLua *interp, const char *fn)
+int dlua_chunk::load_call(CLua &interp, const char *fn)
{
int err = load(interp);
if (err == -1000)
@@ -98,11 +119,12 @@ int dlua_chunk::load_call(CLua *interp, const char *fn)
if (err)
return (err);
- return check_op(interp, interp->callfn(fn, 1, 0));
+ return check_op(&interp, !interp.callfn(fn, fn? 1 : 0, 0));
}
std::string dlua_chunk::orig_error() const
{
+ rewrite_chunk_errors(error);
return (error);
}
diff --git a/crawl-ref/source/luadgn.h b/crawl-ref/source/luadgn.h
index f8b272f544..6c619af05e 100644
--- a/crawl-ref/source/luadgn.h
+++ b/crawl-ref/source/luadgn.h
@@ -13,6 +13,9 @@
extern CLua dlua;
+// Lua chunks cannot exceed 512K. Which is plenty!
+const int LUA_CHUNK_MAX_SIZE = 512 * 1024;
+
class dlua_chunk
{
private:
@@ -27,7 +30,7 @@ private:
std::string get_chunk_prefix(const std::string &s) const;
public:
- std::string error;
+ mutable std::string error;
public:
dlua_chunk(const std::string &_context = "dlua_chunk");
@@ -35,8 +38,8 @@ public:
void add(int line, const std::string &line);
void set_chunk(const std::string &s);
- int load(CLua *interp);
- int load_call(CLua *interp, const char *function);
+ int load(CLua &interp);
+ int load_call(CLua &interp, const char *function);
void set_file(const std::string &s);
const std::string &lua_string() const { return chunk; }
@@ -44,6 +47,9 @@ public:
bool rewrite_chunk_errors(std::string &err) const;
bool empty() const;
+
+ void write(FILE *) const;
+ void read(FILE *);
};
void init_dungeon_lua();
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 5323c421a0..edae6afa9f 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -849,8 +849,8 @@ void map_def::write_full(FILE *outf)
cache_offset = ftell(outf);
writeShort(outf, 0x1eaf); // Level indicator.
writeString(outf, name);
- writeString(outf, prelude.lua_string(), LUA_CHUNK_MAX_SIZE);
- writeString(outf, main.lua_string(), LUA_CHUNK_MAX_SIZE);
+ prelude.write(outf);
+ main.write(outf);
}
void map_def::read_full(FILE *inf)
@@ -869,8 +869,8 @@ void map_def::read_full(FILE *inf)
"Please reload your game.",
file.c_str()).c_str());
- prelude.set_chunk(readString(inf, LUA_CHUNK_MAX_SIZE));
- main.set_chunk(readString(inf, LUA_CHUNK_MAX_SIZE));
+ prelude.read(inf);
+ main.read(inf);
}
void map_def::load()
@@ -899,7 +899,7 @@ void map_def::write_index(FILE *outf) const
writeString(outf, tags);
writeString(outf, place);
write_depth_ranges(outf);
- writeString(outf, prelude.lua_string(), LUA_CHUNK_MAX_SIZE);
+ prelude.write(outf);
}
void map_def::read_index(FILE *inf)
@@ -911,7 +911,7 @@ void map_def::read_index(FILE *inf)
tags = readString(inf);
place = readString(inf);
read_depth_ranges(inf);
- prelude.set_chunk(readString(inf, LUA_CHUNK_MAX_SIZE));
+ prelude.read(inf);
index_only = true;
}
@@ -940,7 +940,7 @@ void map_def::set_file(const std::string &s)
std::string map_def::run_lua(bool run_main)
{
dlua.callfn("dgn_set_map", "m", this);
- int err = prelude.load(&dlua);
+ int err = prelude.load(dlua);
if (err == -1000)
lua_pushnil(dlua);
else if (err)
@@ -950,7 +950,7 @@ std::string map_def::run_lua(bool run_main)
lua_pushnil(dlua);
else
{
- err = main.load(&dlua);
+ err = main.load(dlua);
if (err == -1000)
lua_pushnil(dlua);
else if (err)
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index c2ef6e897d..8e1db25209 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -394,9 +394,6 @@ typedef std::map<int, keyed_mapspec> keyed_specs;
typedef std::vector<level_range> depth_ranges;
-// Lua chunks cannot exceed 512K. Which is plenty!
-const int LUA_CHUNK_MAX_SIZE = 512 * 1024;
-
class map_def
{
public:
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 22e62c9df7..ccff83396e 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -355,11 +355,16 @@ const map_def *map_by_index(int index)
/////////////////////////////////////////////////////////////////////////////
// Reading maps from .des files.
-dlua_chunk lc_file_prelude;
+// All global preludes.
+std::vector<dlua_chunk> global_preludes;
+
+// Map-specific prelude.
+dlua_chunk lc_global_prelude("global_prelude");
std::string lc_desfile;
map_def lc_map;
level_range lc_range;
depth_ranges lc_default_depths;
+bool lc_run_global_prelude = true;
std::set<std::string> map_files_read;
@@ -370,16 +375,17 @@ void reset_map_parser()
lc_map.init();
lc_range.reset();
lc_default_depths.clear();
- lc_file_prelude.clear();
+ lc_global_prelude.clear();
yylineno = 1;
+ lc_run_global_prelude = true;
}
////////////////////////////////////////////////////////////////////////////
static bool checked_des_index_dir = false;
-#define DESCACHE_VER 1000
+#define DESCACHE_VER 1001
static void check_des_index_dir()
{
@@ -425,7 +431,19 @@ static bool verify_map_full(const std::string &base)
static bool load_map_index(const std::string &base)
{
- FILE *inf = fopen((base + ".idx").c_str(), "rb");
+ // If there's a global prelude, load that first.
+ FILE *inf = fopen((base + ".lux").c_str(), "rb");
+ if (inf)
+ {
+ lc_global_prelude.read(inf);
+ fclose(inf);
+
+ global_preludes.push_back( lc_global_prelude );
+ }
+
+ inf = fopen((base + ".idx").c_str(), "rb");
+ if (!inf)
+ end(1, true, "Unable to read %s", (base + ".idx").c_str());
// Discard version (it's been checked by verify_map_index).
readLong(inf);
const int nmaps = readShort(inf);
@@ -460,17 +478,15 @@ static bool load_map_cache(const std::string &filename)
static void write_map_prelude(const std::string &filebase)
{
- const std::string luafile = filebase + ".lua";
- if (lc_file_prelude.empty())
+ const std::string luafile = filebase + ".lux";
+ if (lc_global_prelude.empty())
{
unlink(luafile.c_str());
return;
}
- FILE *outf = fopen(luafile.c_str(), "w");
- if (!outf)
- end(1, true, "Unable to open %s for writing", luafile.c_str());
- fprintf(outf, "%s", lc_file_prelude.lua_string().c_str());
+ FILE *outf = fopen(luafile.c_str(), "wb");
+ lc_global_prelude.write(outf);
fclose(outf);
}
@@ -539,6 +555,7 @@ static void parse_maps(const std::string &s)
yyparse();
fclose(dat);
+ global_preludes.push_back( lc_global_prelude );
write_map_cache(s, file_start, vdefs.size());
}
@@ -572,6 +589,15 @@ void add_parsed_map( const map_def &md )
void run_map_preludes()
{
+ for (int i = 0, size = global_preludes.size(); i < size; ++i)
+ {
+ dlua_chunk &chunk = global_preludes[i];
+ if (!chunk.empty())
+ {
+ if (chunk.load_call(dlua, NULL))
+ mprf(MSGCH_WARN, "Lua error: %s", chunk.orig_error().c_str());
+ }
+ }
for (int i = 0, size = vdefs.size(); i < size; ++i)
{
if (!vdefs[i].prelude.empty())
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index 8274a957e9..91de437ffe 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -52,10 +52,11 @@ void reset_map_parser();
std::string get_descache_path(const std::string &file,
const std::string &ext);
-extern dlua_chunk map_file_prelude;
extern std::string lc_desfile;
extern map_def lc_map;
extern level_range lc_range;
extern depth_ranges lc_default_depths;
+extern dlua_chunk lc_global_prelude;
+extern bool lc_run_global_prelude;
#endif
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index fb82c36e00..0a3cb8ada1 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -89,6 +89,7 @@ definition : def {}
;
def : defdepth {}
+ | global_lua {}
;
defdepth : DEFAULT_DEPTH STRING
@@ -104,6 +105,15 @@ defdepth : DEFAULT_DEPTH STRING
level : name map_specs
{
lc_map.set_file(lc_desfile);
+
+ if (lc_run_global_prelude && !lc_global_prelude.empty())
+ {
+ lc_global_prelude.set_file(lc_desfile);
+ lc_run_global_prelude = false;
+ if (lc_global_prelude.load_call(dlua, NULL))
+ yyerror( lc_global_prelude.orig_error().c_str() );
+ }
+
std::string err = lc_map.validate();
if (!err.empty())
yyerror(err.c_str());
@@ -164,6 +174,17 @@ metaline : place
| prelude_lua
;
+global_lua : MAIN global_lua_lines { }
+
+global_lua_lines : /* empty */ { }
+ | global_lua_lines global_lua_line { }
+ ;
+
+global_lua_line : LUA_LINE
+ {
+ lc_global_prelude.add(yylineno, $1);
+ }
+
main_lua : MAIN main_lua_lines { }
main_lua_lines : /* empty */ { }