3 * Summary: Dungeon-builder Lua interface.
4 * Created by: dshaligram on Sat Jun 23 20:02:09 2007 UTC
16 static int dlua_compiled_chunk_writer(lua_State
*ls
, const void *p
,
19 std::ostringstream
&out
= *static_cast<std::ostringstream
*>(ud
);
20 out
.write(static_cast<const char *>(p
), sz
);
24 ///////////////////////////////////////////////////////////////////////////
27 dlua_chunk::dlua_chunk(const std::string
&_context
)
28 : file(), chunk(), compiled(), context(_context
), first(-1),
34 // Initialises a chunk from the function on the top of stack.
35 // This function must not be a closure, i.e. must not have any upvalues.
36 dlua_chunk::dlua_chunk(lua_State
*ls
)
37 : file(), chunk(), compiled(), context(), first(-1), last(-1), error()
41 lua_stack_cleaner
cln(ls
);
42 std::ostringstream out
;
43 const int err
= lua_dump(ls
, dlua_compiled_chunk_writer
, &out
);
46 const char *e
= lua_tostring(ls
, -1);
47 error
= e
? e
: "Unknown error compiling chunk";
52 dlua_chunk
dlua_chunk::precompiled(const std::string
&_chunk
)
55 dchunk
.compiled
= _chunk
;
59 std::string
dlua_chunk::describe(const std::string
&name
) const
63 return make_stringf("function %s()\n%s\nend\n",
64 name
.c_str(), chunk
.c_str());
67 void dlua_chunk::write(writer
& outf
) const
71 marshallByte(outf
, CT_EMPTY
);
75 if (!compiled
.empty())
77 marshallByte(outf
, CT_COMPILED
);
78 marshallString4(outf
, compiled
);
82 marshallByte(outf
, CT_SOURCE
);
83 marshallString4(outf
, chunk
);
86 marshallString4(outf
, file
);
87 marshallInt(outf
, first
);
90 void dlua_chunk::read(reader
& inf
)
93 chunk_t type
= static_cast<chunk_t
>(unmarshallByte(inf
));
99 unmarshallString4(inf
, chunk
);
102 unmarshallString4(inf
, compiled
);
105 unmarshallString4(inf
, file
);
106 first
= unmarshallInt(inf
);
109 void dlua_chunk::clear()
118 void dlua_chunk::set_file(const std::string
&s
)
123 void dlua_chunk::add(int line
, const std::string
&s
)
128 if (line
!= last
&& last
!= -1)
129 while (last
++ < line
)
137 void dlua_chunk::set_chunk(const std::string
&s
)
142 int dlua_chunk::check_op(CLua
&interp
, int err
)
144 error
= interp
.error
;
148 int dlua_chunk::load(CLua
&interp
)
150 if (!compiled
.empty())
151 return check_op(interp
,
152 interp
.loadbuffer(compiled
.c_str(), compiled
.length(),
158 return (E_CHUNK_LOAD_FAILURE
);
161 int err
= check_op(interp
,
162 interp
.loadstring(chunk
.c_str(), context
.c_str()));
165 std::ostringstream out
;
166 err
= lua_dump(interp
, dlua_compiled_chunk_writer
, &out
);
169 const char *e
= lua_tostring(interp
, -1);
170 error
= e
? e
: "Unknown error compiling chunk";
173 compiled
= out
.str();
177 int dlua_chunk::run(CLua
&interp
)
179 int err
= load(interp
);
182 // callfn returns true on success, but we want to return 0 on success.
183 return (check_op(interp
, !interp
.callfn(NULL
, 0, 0)));
186 int dlua_chunk::load_call(CLua
&interp
, const char *fn
)
188 int err
= load(interp
);
189 if (err
== E_CHUNK_LOAD_FAILURE
)
194 return check_op(interp
, !interp
.callfn(fn
, fn
? 1 : 0, 0));
197 std::string
dlua_chunk::orig_error() const
199 rewrite_chunk_errors(error
);
203 bool dlua_chunk::empty() const
205 return compiled
.empty() && trimmed_string(chunk
).empty();
208 bool dlua_chunk::rewrite_chunk_errors(std::string
&s
) const
210 const std::string contextm
= "[string \"" + context
+ "\"]:";
211 std::string::size_type dlwhere
= s
.find(contextm
);
213 if (dlwhere
== std::string::npos
)
218 s
= rewrite_chunk_prefix(s
);
222 // Our chunk is mentioned, go back through and rewrite lines.
223 std::vector
<std::string
> lines
= split_string("\n", s
);
224 std::string newmsg
= lines
[0];
225 bool wrote_prefix
= false;
226 for (int i
= 2, size
= lines
.size() - 1; i
< size
; ++i
)
228 const std::string
&st
= lines
[i
];
229 if (st
.find(context
) != std::string::npos
)
233 newmsg
= get_chunk_prefix(st
) + ": " + newmsg
;
237 newmsg
+= "\n" + rewrite_chunk_prefix(st
);
244 std::string
dlua_chunk::rewrite_chunk_prefix(const std::string
&line
,
245 bool skip_body
) const
247 std::string s
= line
;
248 const std::string contextm
= "[string \"" + context
+ "\"]:";
249 const std::string::size_type ps
= s
.find(contextm
);
250 if (ps
== std::string::npos
)
253 const std::string::size_type lns
= ps
+ contextm
.length();
254 std::string::size_type pe
= s
.find(':', ps
+ contextm
.length());
255 if (pe
!= std::string::npos
)
257 const std::string line_num
= s
.substr(lns
, pe
- lns
);
258 const int lnum
= atoi(line_num
.c_str());
259 const std::string newlnum
= make_stringf("%d", lnum
+ first
- 1);
260 s
= s
.substr(0, lns
) + newlnum
+ s
.substr(pe
);
261 pe
= lns
+ newlnum
.length();
264 return s
.substr(0, ps
) + (file
.empty()? context
: file
) + ":"
265 + (skip_body
? s
.substr(lns
, pe
- lns
)
269 std::string
dlua_chunk::get_chunk_prefix(const std::string
&sorig
) const
271 return rewrite_chunk_prefix(sorig
, true);
274 static void _dlua_register_constants(CLua
&lua
)
276 lua_pushstring(lua
, CORPSE_NEVER_DECAYS
);
277 lua
.setglobal("CORPSE_NEVER_DECAYS");
280 void init_dungeon_lua()
282 lua_stack_cleaner
clean(dlua
);
284 dluaopen_colour(dlua
);
285 dluaopen_crawl(dlua
);
287 dluaopen_mapgrd(dlua
);
288 dluaopen_monsters(dlua
);
292 luaL_openlib(dlua
, "feat", feat_dlib
, 0);
293 luaL_openlib(dlua
, "spells", spells_dlib
, 0);
294 luaL_openlib(dlua
, "debug", debug_dlib
, 0);
295 luaL_openlib(dlua
, "los", los_dlib
, 0);
297 dlua
.execfile("clua/dungeon.lua", true, true);
298 dlua
.execfile("clua/luamark.lua", true, true);
299 dlua
.execfile("clua/mapinit.lua", true, true);
301 lua_getglobal(dlua
, "dgn_run_map");
303 luaL_newmetatable(dlua
, MAP_METATABLE
);
305 luaopen_dgnevent(dlua
);
306 luaopen_mapmarker(dlua
);
309 register_itemlist(dlua
);
310 register_monslist(dlua
);
312 _dlua_register_constants(dlua
);