mud/lua/
mud/player/
/***************************************************************************
 *           ____                                                          *
 *        ,'' _,-`.                                                        *
 *      ,'  ,'_|                                                           *
 *     /   / <>|             Lunacy (C) 2009                               *
 *    :   :    \             Version: 1.0                                  *
 *    :   :    _\            Written by: Johnny Starr                      *
 *     \   \  -|             File: lua_interface.c                         *
 *      `.  `._|             Desc: Main Lua interface for Lua scripting    *
 *        `..__`-.'                                                        *
 *                                                                         *
 ***************************************************************************
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 ***************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "merc.h"
#include "lua_header.h"

/* global Lua state declaration, used for server calls to Lua */
lua_State *global_L;

/*
static void get_traceback_function ( lua_State *L )
{
	lua_pushliteral (L, LUA_DBLIBNAME);
	lua_rawget      (L, LUA_GLOBALSINDEX);

	if (!lua_istable (L, -1)) {
		lua_pop (L, 2);
		lua_pushnil (L);
		return;
	}

	lua_pushstring(L, "traceback");
	lua_rawget    (L, -2);

	if (!lua_isfunction (L, -1)) {
		lua_pop (L, 2);
		lua_pushnil(L);
		return;
	}

	lua_remove (L, -2);
}

*/

/* errorL() a general error message handler */
void errorL (char *fmt, ...)
{
    CHAR_DATA *ch;
    char buf[MAX_STRING_LENGTH];
    va_list args;
    va_start (args, fmt);
    vsprintf (buf, fmt, args);
    va_end (args);

    for (ch = char_list; ch != NULL; ch = ch->next)
        if (!IS_NPC(ch))
            sendf(ch, "%s\r\n", buf);
}

/* stack_dump() another testing function to view contents of stack */
void L_stack_dump( lua_State *L )
{

	int i;
	int top = lua_gettop(L);
	for ( i = 1; i <= top; i++ ) {
		int t = lua_type(L, i);
		switch(t) {
			case LUA_TSTRING:
				errorL("String: %s\r\n", lua_tostring(L, i));
			break;

			case LUA_TBOOLEAN:
				errorL(lua_toboolean(L, i) ? "true\r\n" : "false\r\n");
			break;

			case LUA_TNUMBER:
				errorL("Number: %g\r\n", lua_tostring(L, i));
			break;

			case LUA_TUSERDATA:
				errorL("Userdata: %s\r\n", lua_tostring(L, i));
			break;

			default:
				errorL("Other: %s\r\n", lua_tostring(L, i));
			break;
		}
	
	}
	errorL("\r\n");
}







/* constructs global lua_State* */
void load_global_lua(void)
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
	luaL_newmetatable(L, "lunacy.ch");
	lua_pushvalue(L, -1);
	lua_setfield(L, -2, "__index");
   	L_register_charlib(L); 
	L_register_mudlib(L);

    if (luaL_loadfile(L, "../lua/mud.lua") || lua_pcall(L, 0, 0, 0))
        errorL ("LUA-ERROR [%s: %s]\r\n", __FUNCTION__, lua_tostring(L, -1));
    if (luaL_loadfile(L, "../lua/player.lua") || lua_pcall(L, 0, 0, 0))
        errorL ("LUA-ERROR [%s: %s]\r\n", __FUNCTION__, lua_tostring(L, -1));
	/* global Lua state */
    global_L = L;

	lua_settop(L, 0);
}


/* constructs new lua_State* for character */
void load_char_lua( CHAR_DATA *ch )
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
 	
	luaL_newmetatable(L, "lunacy.ch");
	lua_pushvalue(L, -1);
	lua_setfield(L, -2, "__index");
	L_register_charlib(L);
    
	if (luaL_loadfile(L, "../lua/player.lua") || lua_pcall(L, 0, 0, 0))
        errorL ("LUA-ERROR [%s: %s]\r\n", __FUNCTION__, lua_tostring(L, -1));
	if (luaL_loadfile(L, "../lua/olc.lua") || lua_pcall(L, 0, 0, 0))
        errorL ("LUA-ERROR [%s: %s]\r\n", __FUNCTION__, lua_tostring(L, -1));
 	if (luaL_loadfile(L, "../lua/battle.lua") || lua_pcall(L, 0, 0, 0))
        errorL ("LUA-ERROR [%s: %s]\r\n", __FUNCTION__, lua_tostring(L, -1));   
	if (L)
        ch->L = L;
    else
        bug ("load_char_lua: bad lua state", 0);

	lua_settop(L, 0);
}

/* main lua interface. Hooks into lua and returns a char* string for output */
char* call_lua(lua_State *L, CHAR_DATA *actor, void *target, int call_type, char *func, char *argument)
{
    int err = 0;
    char *output = NULL;

    switch (call_type) {
        /* one text argument */
    case LCALL_CHAR_SCRIPT:
        lua_getglobal(L, func);                               /* stack: function ...                  */		
		CHAR_DATA **ptr = (CHAR_DATA **)lua_newuserdata( L,
										sizeof(CHAR_DATA**));
		*ptr = actor;
		luaL_getmetatable(L, "lunacy.ch");	
		lua_setmetatable(L, -2);                              /* stack: function(udata) ...           */
		lua_pushstring(L, argument);                          /* stack: function(udata, argument) ... */

        err = lua_pcall(L, 2, 1, 0);

        if (lua_isstring(L, -1))
            output = str_dup( lua_tostring(L, -1));
        else
            output = NULL;
        break;

	case LCALL_OLC:

        lua_getglobal(L, func);                               /* stack: function ...                  */		
		CHAR_DATA **ptr2 = (CHAR_DATA **)lua_newuserdata( L,
										sizeof(CHAR_DATA**));
		*ptr2 = actor;
		luaL_getmetatable(L, "lunacy.ch");	
		lua_setmetatable(L, -2);                              /* stack: function(udata) ...           */
		lua_pushstring(L, argument);                          /* stack: function(udata, argument) ... */

        err = lua_pcall(L, 3, 1, 0);

        if (lua_isstring(L, -1))
            output = str_dup( lua_tostring(L, -1));
        else
            output = NULL;
        break;

	case LCALL_COLOR:
		lua_getglobal(L, func);
		lua_pushstring(L, argument);
		err = lua_pcall(L, 1, 1, 0);
        if (lua_isstring(L, -1))
            output = str_dup( lua_tostring(L, -1));
        else
            output = NULL;

        break;

    default:
        bug("call_lua: bad call_type", 0);
    }

    if (err) {
        errorL ("#RLua Error: %s{w", lua_tostring(L, -1));
        return NULL;
    }

	lua_pop(L, 1);
    return (output);
}