376 lines
9.9 KiB
C
376 lines
9.9 KiB
C
#include "scriptmine.h"
|
|
#include <dirent.h>
|
|
|
|
duk_context *ctx = NULL;
|
|
lua_State *Lg = NULL;
|
|
const char *name = NULL;
|
|
|
|
const char *air = "air";
|
|
|
|
const char *blockIDToNodeName[][2] =
|
|
{
|
|
{"1", "default:stone"},
|
|
{"2", "default:dirt_with_grass"},
|
|
{"3", "default:dirt"},
|
|
{"4", "default:cobble"},
|
|
{"5", "default:wood"},
|
|
{"5:1", "default:pine_wood"},
|
|
{"8", "default:water_source"},
|
|
{"9", "default:water_source"},
|
|
{"10", "default:lava_source"},
|
|
{"11", "default:lava_source"},
|
|
{"12", "default:sand"},
|
|
{"13", "default:gravel"},
|
|
{"14", "default:stone_with_gold"},
|
|
{"15", "default:stone_with_iron"},
|
|
{"17", "default:tree"},
|
|
{"17:1", "default:pine_tree"},
|
|
{"31", "default:grass_1"},
|
|
{"35", "wool:white"},
|
|
{"35:1", "wool:orange"},
|
|
{"35:2", "wool:magenta"},
|
|
{"35:4", "wool:yellow"},
|
|
{"35:5", "wool:green"},
|
|
{"35:6", "wool:pink"},
|
|
{"35:9", "wool:cyan"},
|
|
{"35:10", "wool:violet"},
|
|
{"35:11", "wool:blue"},
|
|
{"35:12", "wool:brown"},
|
|
{"35:13", "wool:dark_green"},
|
|
{"35:14", "wool:red"},
|
|
{"35:15", "wool:black"},
|
|
{"37", "flowers:dandelion_yellow"},
|
|
{"38", "flowers:rose"},
|
|
{"41", "default:goldblock"},
|
|
{"48", "default:mossycobble"},
|
|
{"49", "default:obsidian"},
|
|
{"50", "default:torch"},
|
|
{"57", "default:diamondblock"},
|
|
{"64", "doors:door_wood"},
|
|
{"65", "default:ladder_wood"},
|
|
{"98", "default:stonebrick"},
|
|
{"102", "xpanes:pane"},
|
|
{"109", "stairs:stair_stonebrick"},
|
|
{"126", "stairs:slab_wood"},
|
|
{"134", "stairs:stair_pine_wood"},
|
|
{"188", "default:fence_pine_wood"}
|
|
};
|
|
|
|
const char *blockID_to_node_name(const char *blockIDOrig)
|
|
{
|
|
char blockID[255];
|
|
size_t len = strlen(blockIDOrig);
|
|
if (len > 254)
|
|
return air;
|
|
strcpy(blockID, blockIDOrig);
|
|
if ((len > 2) && (strcmp(blockIDOrig + len - 2, ":0") == 0))
|
|
blockID[len - 2] = 0;
|
|
int maxBlockID = sizeof(blockIDToNodeName) / 2 / (sizeof(const char *));
|
|
for (int i = 0; i < maxBlockID; ++i)
|
|
{
|
|
if (strcmp(blockID, blockIDToNodeName[i][0]) == 0)
|
|
return blockIDToNodeName[i][1];
|
|
}
|
|
return air;
|
|
}
|
|
|
|
const char *node_name_to_blockID(const char *node_name)
|
|
{
|
|
int maxBlockID = sizeof(blockIDToNodeName) / 2 / (sizeof(const char *));
|
|
for (int i = 0; i < maxBlockID; ++i)
|
|
{
|
|
if (strcmp(node_name, blockIDToNodeName[i][1]) == 0)
|
|
return blockIDToNodeName[i][0];
|
|
}
|
|
return "0";
|
|
}
|
|
|
|
duk_ret_t echo(duk_context *ctx)
|
|
{
|
|
const char *text = duk_to_lstring(ctx, 0 /*index*/, NULL);
|
|
lua_getfield(Lg, LUA_GLOBALSINDEX, "minetest");
|
|
lua_getfield(Lg, -1, "chat_send_player");
|
|
lua_remove(Lg, -2);
|
|
lua_pushstring(Lg, name);
|
|
lua_pushstring(Lg, text);
|
|
lua_pushboolean(Lg, 0);
|
|
lua_call(Lg, 3, 1);
|
|
return 1;
|
|
}
|
|
|
|
duk_ret_t readFile(duk_context *ctx)
|
|
{
|
|
const char *text = duk_to_string(ctx, 0);
|
|
if (strcmp(text, "drone") == 0)
|
|
text = "drone/index";
|
|
char *filename = malloc(strlen(text) + 200);
|
|
strcpy(filename, "js/");
|
|
strcat(filename, text);
|
|
strcat(filename, ".js");
|
|
FILE *f = fopen(filename, "r");
|
|
if (NULL == f)
|
|
{
|
|
strcpy(filename, "js/drone/");
|
|
strcat(filename, text);
|
|
strcat(filename, ".js");
|
|
f = fopen(filename, "r");
|
|
if (NULL == f)
|
|
{
|
|
duk_push_undefined(ctx);
|
|
return 1;
|
|
}
|
|
}
|
|
fclose(f);
|
|
duk_push_string_file(ctx, filename);
|
|
free(filename);
|
|
return 1;
|
|
}
|
|
|
|
duk_ret_t get_node(duk_context *ctx)
|
|
{
|
|
int z = duk_to_int(ctx, -3);
|
|
int y = duk_to_int(ctx, -2);
|
|
int x = duk_to_int(ctx, -1);
|
|
lua_getfield(Lg, LUA_GLOBALSINDEX, "minetest"); // [minetest]
|
|
lua_getfield(Lg, -1, "get_node"); // [minetest get_node]
|
|
lua_remove(Lg, -2); // [get_node]
|
|
lua_newtable(Lg);
|
|
lua_pushnumber(Lg, x);
|
|
lua_setfield(Lg, -2, "x");
|
|
lua_pushnumber(Lg, y);
|
|
lua_setfield(Lg, -2, "y");
|
|
lua_pushnumber(Lg, z);
|
|
lua_setfield(Lg, -2, "z");
|
|
lua_call(Lg, 1, 1);
|
|
lua_getfield(Lg, -1, "name");
|
|
const char *node_name = lua_tostring(Lg, -1);
|
|
const char *blockID = node_name_to_blockID(node_name);
|
|
duk_idx_t ary_indx = duk_push_array(ctx);
|
|
duk_push_string(ctx, blockID);
|
|
duk_put_prop_string(ctx, ary_indx, "typeId");
|
|
duk_push_string(ctx, node_name);
|
|
duk_put_prop_string(ctx, ary_indx, "nodeName");
|
|
lua_remove(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
return 1;
|
|
}
|
|
|
|
duk_ret_t place_node(duk_context *ctx)
|
|
{
|
|
int z = duk_to_int(ctx, -4);
|
|
int y = duk_to_int(ctx, -3);
|
|
int x = duk_to_int(ctx, -2);
|
|
const char *blockID = duk_to_string(ctx, -1);
|
|
const char *nodeName = blockID_to_node_name(blockID);
|
|
lua_getfield(Lg, LUA_GLOBALSINDEX, "minetest"); // [minetest]
|
|
lua_getfield(Lg, -1, "place_node"); // [minetest new_node]
|
|
lua_remove(Lg, -2); // [set_node]
|
|
lua_newtable(Lg);
|
|
lua_pushnumber(Lg, x);
|
|
lua_setfield(Lg, -2, "x");
|
|
lua_pushnumber(Lg, y);
|
|
lua_setfield(Lg, -2, "y");
|
|
lua_pushnumber(Lg, z);
|
|
lua_setfield(Lg, -2, "z");
|
|
lua_newtable(Lg);
|
|
lua_pushstring(Lg, nodeName);
|
|
lua_setfield(Lg, -2, "name");
|
|
lua_call(Lg, 2, 0);
|
|
return 0;
|
|
}
|
|
|
|
duk_ret_t set_node(duk_context *ctx)
|
|
{
|
|
int z = duk_to_int(ctx, -4);
|
|
int y = duk_to_int(ctx, -3);
|
|
int x = duk_to_int(ctx, -2);
|
|
const char *blockID = duk_to_string(ctx, -1);
|
|
const char *nodeName = blockID_to_node_name(blockID);
|
|
lua_getfield(Lg, LUA_GLOBALSINDEX, "minetest"); // [minetest]
|
|
lua_getfield(Lg, -1, "set_node"); // [minetest new_node]
|
|
lua_remove(Lg, -2); // [set_node]
|
|
lua_newtable(Lg);
|
|
lua_pushnumber(Lg, x);
|
|
lua_setfield(Lg, -2, "x");
|
|
lua_pushnumber(Lg, y);
|
|
lua_setfield(Lg, -2, "y");
|
|
lua_pushnumber(Lg, z);
|
|
lua_setfield(Lg, -2, "z");
|
|
lua_newtable(Lg);
|
|
lua_pushstring(Lg, nodeName);
|
|
lua_setfield(Lg, -2, "name");
|
|
lua_call(Lg, 2, 0);
|
|
return 0;
|
|
}
|
|
|
|
duk_ret_t get_player_location(duk_context *ctx)
|
|
{
|
|
lua_getfield(Lg, LUA_GLOBALSINDEX, "minetest"); // [minetest]
|
|
lua_getfield(Lg, -1, "get_player_by_name"); // [minetest get_player_by_name]
|
|
lua_remove(Lg, -2); // [get_player_by_name]
|
|
lua_pushstring(Lg, name); // [get_player_by_name name]
|
|
lua_call(Lg, 1, 1); // [player]
|
|
lua_getmetatable(Lg, -1); // [player metatable]
|
|
lua_pushstring(Lg, "__index"); // [player metatable __index]
|
|
lua_rawget(Lg, -2); // [player metatable __index]
|
|
lua_pushstring(Lg, "getpos"); // [player metatable __index getpos]
|
|
lua_rawget(Lg, -2); // [player metatable __index getpos]
|
|
lua_pushvalue(Lg, -4); // [player metatable __index getpos player]
|
|
lua_call(Lg, 1, 1); // [player metatable __index postable]
|
|
lua_getfield(Lg, -1, "x");
|
|
int x = lua_tointeger(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
lua_getfield(Lg, -1, "y");
|
|
int y = lua_tointeger(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
lua_getfield(Lg, -1, "z");
|
|
int z = lua_tointeger(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
lua_remove(Lg, -1); // [player metatable __index]
|
|
lua_pushstring(Lg, "get_look_dir");
|
|
lua_rawget(Lg, -2); // [player metatable __index get_look_dir]
|
|
lua_pushvalue(Lg, -4); // [player metatable __index get_look_dir player]
|
|
lua_call(Lg, 1, 1); // [player metatable __index postable]
|
|
lua_getfield(Lg, -1, "x");
|
|
double xv = lua_tonumber(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
lua_getfield(Lg, -1, "z");
|
|
double zv = lua_tonumber(Lg, -1);
|
|
lua_remove(Lg, -1);
|
|
lua_remove(Lg, -1); // [player metatable __index]
|
|
lua_remove(Lg, -1); // [player metatable]
|
|
lua_remove(Lg, -1); // [player]
|
|
lua_remove(Lg, -1);
|
|
int facing = 0;
|
|
if (fabs(xv) > fabs(zv))
|
|
{
|
|
if (xv > 0)
|
|
{
|
|
facing = 1;
|
|
}
|
|
else
|
|
facing = 3;
|
|
}
|
|
else
|
|
{
|
|
if (zv > 0)
|
|
{
|
|
facing = 0;
|
|
}
|
|
else
|
|
{
|
|
facing = 2;
|
|
}
|
|
}
|
|
y += 1;
|
|
duk_idx_t ary_indx = duk_push_array(ctx);
|
|
duk_push_int(ctx, z);
|
|
duk_put_prop_string(ctx, ary_indx, "x");
|
|
duk_push_int(ctx, y);
|
|
duk_put_prop_string(ctx, ary_indx, "y");
|
|
duk_push_int(ctx, x);
|
|
duk_put_prop_string(ctx, ary_indx, "z");
|
|
duk_push_int(ctx, facing);
|
|
duk_put_prop_string(ctx, ary_indx, "facing");
|
|
return 1;
|
|
}
|
|
|
|
static int javascript(lua_State *L)
|
|
{
|
|
const char *cmd = lua_tostring(L, -1);
|
|
name = lua_tostring(L, -2);
|
|
Lg = L;
|
|
duk_peval_string(ctx, cmd);
|
|
return 1;
|
|
}
|
|
|
|
static void loadplugins(const char *modpath, const char *pluginpath)
|
|
{
|
|
char fullpath[2048];
|
|
strcpy(fullpath, modpath);
|
|
strcat(fullpath, "/");
|
|
strcat(fullpath, pluginpath);
|
|
DIR *dir = opendir(fullpath);
|
|
if (dir)
|
|
{
|
|
struct dirent *entry;
|
|
while ((entry = readdir(dir)) != NULL)
|
|
{
|
|
if (entry->d_type & DT_DIR)
|
|
{
|
|
if ((strcmp("..", entry->d_name) != 0) && (strcmp(".", entry->d_name) != 0))
|
|
{
|
|
char *tmppath = malloc(strlen(pluginpath) + 2 + strlen(entry->d_name));
|
|
strcpy(tmppath, pluginpath);
|
|
strcat(tmppath, "/");
|
|
strcat(tmppath, entry->d_name);
|
|
loadplugins(modpath, tmppath);
|
|
free(tmppath);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int len = strlen(entry->d_name);
|
|
if ((len > 3) && (strcmp(entry->d_name + len - 3, ".js") == 0))
|
|
{
|
|
char *tmppath = malloc(strlen(pluginpath) + 2 + len);
|
|
strcpy(tmppath, pluginpath);
|
|
strcat(tmppath, "/");
|
|
strcat(tmppath, entry->d_name);
|
|
tmppath[strlen(pluginpath) + 1 + len - 3] = 0;
|
|
duk_push_global_object(ctx);
|
|
duk_push_string(ctx, "require");
|
|
duk_get_prop(ctx, -2);
|
|
duk_push_string(ctx, tmppath);
|
|
duk_call(ctx, 1);
|
|
duk_pop_n(ctx, 2);
|
|
free(tmppath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int loadscript(lua_State *L)
|
|
{
|
|
const char *modpath = lua_tostring(L, -1);
|
|
char *fullpath = malloc(strlen(modpath) + 10);
|
|
strcpy(fullpath, modpath);
|
|
strcat(fullpath, "/js/scriptmine.js");
|
|
if (duk_peval_file_noresult(ctx, fullpath) != 0) {
|
|
printf("Error: %s\n", duk_safe_to_string(ctx, -1));
|
|
exit(1);
|
|
}
|
|
strcpy(fullpath, modpath);
|
|
strcat(fullpath, "/js");
|
|
loadplugins(fullpath, "plugins");
|
|
free(fullpath);
|
|
return 1;
|
|
}
|
|
|
|
int luaopen_scriptmine(lua_State *L)
|
|
{
|
|
ctx = duk_create_heap_default();
|
|
duk_push_global_object(ctx);
|
|
duk_push_c_function(ctx, echo, 1);
|
|
duk_put_prop_string(ctx, -2, "echo");
|
|
duk_push_c_function(ctx, readFile, 1);
|
|
duk_put_prop_string(ctx, -2, "readFile");
|
|
duk_push_c_function(ctx, get_node, 3);
|
|
duk_put_prop_string(ctx, -2, "get_node");
|
|
duk_push_c_function(ctx, place_node, 3);
|
|
duk_put_prop_string(ctx, -2, "place_node");
|
|
duk_push_c_function(ctx, set_node, 4);
|
|
duk_put_prop_string(ctx, -2, "set_node");
|
|
duk_push_c_function(ctx, get_player_location, 0);
|
|
duk_put_prop_string(ctx, -2, "get_player_location");
|
|
if (!ctx)
|
|
{
|
|
printf("Failed to create a Duktape heap.\n");
|
|
exit(1);
|
|
}
|
|
lua_register(L, "javascript", javascript);
|
|
lua_register(L, "loadscript", loadscript);
|
|
return 0;
|
|
}
|