#include <stdlib.h>
#include "scripting.h"
#include "mud.h"
lua_State * lua;
void stackDump (lua_State *L) {
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) { /* repeat for each level */
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING: /* strings */
printf("`%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN: /* booleans */
printf(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER: /* numbers */
printf("%g", lua_tonumber(L, i));
break;
default: /* other values */
printf("%s", lua_typename(L, t));
break;
}
printf(" "); /* put a separator */
}
printf("\n"); /* end the listing */
}
/* Two arguments, Filename to load, int indicating where file goes.*/
int lua_load_data( lua_State *L)
{
FILE * fp;
char filename[MAX_BUFFER];
const char *text = luaL_checkstring(L, 1);
char *key;
char *data;
int location = luaL_checkint(L, 2);
bool found;
bool done;
int type;
char * word;
lua_pop(L, 2);
switch(location)
{
case 1: /*Will be a constant later.*/
sprintf(filename, "../players/%s.luadat", text);
break;
}
if ((fp = fopen(filename, "r")) == NULL)
{
lua_pushnil(L);
return 1;
}
lua_newtable(L);
word = fread_word(fp);
done = FALSE;
while (!done)
{
found = FALSE;
switch (word[0])
{
case 'K':
key = fread_string(fp);
type = fread_number(fp);
data = fread_string(fp);
switch(type)
{
case LUA_TSTRING:
lua_pushstring(L, data);
break;
case LUA_TNUMBER:
lua_pushinteger(L, atoi(data));
break;
case LUA_TBOOLEAN:
lua_pushboolean(L, atoi(data));
break;
}
lua_setfield(L, 1, key);
found = TRUE;
free(key);
free(data);
break;
case 'E':
if (!strcasecmp(word, "EOF")) {done = TRUE; found = TRUE; break;}
break;
}
if (!found)
{
bug("read_dirfile: unexpected '%s' in file %s.", word, filename);
}
/* read one more */
if (!done)
{
word = fread_word(fp);
}
}
fclose(fp);
return 1;
}
/* Three arguments, filename to save to, int indicating where file goes. (Ignored for now), table of data,*/
int lua_save_data( lua_State *L)
{
FILE * fp;
char filename[MAX_BUFFER];
const char *text = luaL_checkstring(L, 1);
const char *key;
int location = luaL_checkint(L, 2);
int type;
luaL_checktype(L, 3, LUA_TTABLE);
switch (location)
{
case 1: /*Will be a constant later.*/
sprintf(filename, "../players/%s.luadat", text);
break;
}
if ((fp = fopen(filename, "w")) == NULL)
{
bug("Unable to write to %s in lua_save_data, file type %d", text, type);
lua_pop(L, 3);
return 0;
}
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, 3) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
key = luaL_checkstring(L, -2);
type = lua_type(L, -1);
fprintf(fp, "Key %s~%d %s~\n", key, type,luaL_checkstring(L, -1));
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 1);
}
fprintf(fp, "%s\n", FILE_TERMINATOR);
fclose(fp);
lua_pop(L, 3);
return 0;
}
/*One argument in lua. the string to be logged. */
int lua_log_string(lua_State * L)
{
const char *text = luaL_checkstring(L,1);
lua_pop(L, 1);
log_string(text);
return 0;
}
/* Two arguments from lua. dMob (brain:plr), and arg. */
int lua_help(lua_State * l)
{
const char *text;
char * arg;
D_MOBILE *dMob;
text = luaL_checkstring(l, -1);
dMob = (D_MOBILE *)luaL_checkudata(l, 1, "dMobile");
lua_pop(l, 2);
arg= strdup(text);
cmd_help(dMob, arg);
free(arg);
return 0;
}
/* Two arguments from lua. dMob (brain:plr), and arg. */
int lua_linkdead(lua_State * l)
{
const char *text;
char * arg;
D_MOBILE *dMob;
text = luaL_checkstring(l, -1);
dMob = (D_MOBILE *)luaL_checkudata(l, 1, "dMobile");
lua_pop(l, 2);
arg= strdup(text);
cmd_linkdead(dMob, arg);
free(arg);
return 0;
}
/* Two arguments in lua. dMob (brain:plr), and arg, the text to be sent to the player*/
int lua_text_to_mobile(lua_State *l)
{
const char *text;
D_MOBILE *dMob;
text = luaL_checkstring(l, -1);
dMob = (D_MOBILE *)luaL_checkudata(l, 1, "dMobile");
lua_pop(l, 2);
text_to_mobile(dMob, text);
return 0;
}
int lua_quit(lua_State *l)
{
const char *text;
D_MOBILE *dMob;
text = luaL_checkstring(l, -1);
dMob = (D_MOBILE *)luaL_checkudata(l, 1, "dMobile");
lua_pop(l, 2);
text_to_mobile(dMob, "Dream until the dream comes true.\n\r");
lua_getglobal(lua, "unregister_player");
dMobile_to_lua(dMob, lua);
if (lua_pcall(lua, 1, 0, 0) != 0)
{
log_string("Error in unregister_player: %s", luaL_checkstring(lua,-1));
lua_pop(l, 1);
return 0;
}
cmd_quit(dMob, NULL);
return 0;
}
void register_func(const char * name, lua_CFunction func)
{
lua_pushcfunction(lua, func);
lua_setglobal(lua, name);
}
void function_hook(lua_State * l , lua_Debug * ar)
{
char buf[MAX_BUFFER];
lua_getinfo(l, "n", ar);
lua_getinfo(l, "S", ar);
sprintf(buf, "function hook caught: %s, %s, %s, %s", ar->name, ar->namewhat, ar->what, ar->source );
puts(buf);
}
void dMobile_to_lua(D_MOBILE *dMob, lua_State *l)
{
lua_pushlightuserdata(l, dMob);
luaL_getmetatable(l, "dMobile");
lua_setmetatable(l, -2);
}
void register_dMobile(D_MOBILE *dMob)
{
lua_getglobal(lua, "register_player");
dMobile_to_lua(dMob, lua);
lua_pushstring(lua, dMob->name);
if (lua_pcall(lua, 2, 0, 0) != 0)
{
log_string("Error in register_dMobile: %s", luaL_checkstring(lua,-1));
lua_pop(lua, 1);
}
}
/* Two arguments in lua. dMob (brain:plr), and arg, which is ignored.*/
int lua_enter_shell(lua_State *l)
{
D_MOBILE *dMob;
const char * text;
char * arg;
dMob = (D_MOBILE *)luaL_checkudata(l, 1, "dMobile");
text = luaL_checkstring(l, -1);
if (IS_ADMIN(dMob))
{
if (text[0] == '\0')
{
dMob->shell = TRUE;
text_to_mobile(dMob, "Entering shell.\n\r");
}
else
{
arg = strdup(text);
dMob->shell = TRUE;
handle_cmd_input(dMob->socket , arg);
free(arg);
dMob->shell = FALSE;
}
}
else
{
text_to_mobile(dMob, "Insufficent security to enter the shell.\n\r");
}
return 0;
}
void input_to_lua(D_MOBILE *dMob, char * command, char * arg)
{
lua_getglobal(lua, "player_input");
dMobile_to_lua(dMob, lua);
lua_pushstring(lua, command);
lua_pushstring(lua, arg);
if (lua_pcall(lua, 3, 0, 0) != 0)
{
log_string("Error in input_to_lua: %s", luaL_checkstring(lua,-1));
lua_pop(lua, 1);
}
}
int lua_code_level(lua_State *l)
{
lua_Debug debug_info;
int level= 0;
int rlevel = 5;
DIRFILE_ENTRY *targ;
lua_pop(l, 1);
while (lua_getstack(l, level++, &debug_info) == 1)
{
lua_getinfo(l, "n", &debug_info);
lua_getinfo(l, "S", &debug_info);
lua_getinfo(l, "l", &debug_info);
/*sprintf(buf, "Stack Frame %d: %s, %s, %s, %s %d",level, debug_info.name, debug_info.namewhat, debug_info.what, debug_info.source, debug_info.currentline );
puts(buf); */
if (strcasecmp(debug_info.source, "=[C]") && strcasecmp(debug_info.source, "=(tail call)"))
{
targ = get_dirfile_from_real_path(debug_info.source, NULL);
if (rlevel < targ->eSecurity)
rlevel = targ->eSecurity;
}
}
lua_pushinteger(l, rlevel);
return 1;
}
bool is_code_core(lua_State *l)
{
lua_Debug debug_info;
int level= 0;
bool core = TRUE;
DIRFILE_ENTRY *targ;
lua_pop(l, 1);
while (lua_getstack(l, level++, &debug_info) == 1)
{
lua_getinfo(l, "n", &debug_info);
lua_getinfo(l, "S", &debug_info);
lua_getinfo(l, "l", &debug_info);
/*sprintf(buf, "Stack Frame %d: %s, %s, %s, %s %d",level, debug_info.name, debug_info.namewhat, debug_info.what, debug_info.source, debug_info.currentline );
puts(buf);*/
if (strcasecmp(debug_info.source, "=[C]") && strcasecmp(debug_info.source, "=(tail call)"))
{
targ = get_dirfile_from_real_path(debug_info.source, NULL);
if (!strcasecmp(targ->creator, "core"))
{
core = TRUE;
}
else
{
core = FALSE;
break;
}
}
else
{
core = TRUE;
}
}
return core;
}
/*No arguments. */
int lua_is_code_core(lua_State *l)
{
if (is_code_core(l) == TRUE)
{
lua_pushboolean(l, TRUE);
}
else
{
lua_pushboolean(l,FALSE);
}
return 1;
}
void init_lua()
{
lua = lua_open();
luaL_openlibs(lua);
log_string("Lua Initied");
register_func("log_string", lua_log_string);
register_func("text_to_player", lua_text_to_mobile);
register_func("enter_shell", lua_enter_shell);
register_func("save_data", lua_save_data);
register_func("do_quit", lua_quit);
register_func("load_data", lua_load_data);
register_func("is_core", lua_is_code_core);
register_func("help", lua_help);
register_func("linkdead", lua_linkdead);
register_func("code_level", lua_code_level);
luaL_newmetatable(lua, "dMobile" );
}