socketmud/
socketmud/doc/
socketmud/help/
socketmud/players/
socketmud/scripts/
socketmud/scripts/brain_data/
socketmud/scripts/brain_data/base_brains/
socketmud/scripts/cmd_data/
socketmud/scripts/cmd_data/commands/
socketmud/scripts/home/
socketmud/scripts/home/LordLua/
#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" ); 
}