server/src/bindings/bind_gmtool.c

267 lines
6.0 KiB
C
Raw Normal View History

#include <platform.h>
#include <curses.h>
#include "bind_gmtool.h"
#include "../gmtool.h"
#include "../gmtool_structs.h"
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <modules/autoseed.h>
#include <util/log.h>
#include <lua.h>
#include <tolua.h>
static int
tolua_run_mapper(lua_State* L)
{
run_mapper();
return 0;
}
static int
tolua_highlight_region(lua_State* L)
{
region * r = tolua_tousertype(L, 1, 0);
int select = tolua_toboolean(L, 2, 0);
highlight_region(r, select);
return 0;
}
static int
tolua_current_region(lua_State* L)
{
map_region * mr = cursor_region(&current_state->display, &current_state->cursor);
tolua_pushusertype(L, mr?mr->r:NULL, TOLUA_CAST "region");
return 1;
}
static int
tolua_select_coordinate(lua_State* L)
{
int nx = (int)tolua_tonumber(L, 1, 0);
int ny = (int)tolua_tonumber(L, 2, 0);
int select = tolua_toboolean(L, 3, 0);
if (current_state) {
select_coordinate(current_state->selected, nx, ny, select);
}
return 0;
}
static int
tolua_select_region(lua_State* L)
{
region * r = tolua_tousertype(L, 1, 0);
int select = tolua_toboolean(L, 2, 0);
if (current_state && r) {
select_coordinate(current_state->selected, r->x, r->y, select);
}
return 0;
}
typedef struct tag_iterator {
selection * list;
tag * node;
region * r;
int hash;
} tag_iterator;
void
tag_advance(tag_iterator * iter)
{
while (iter->hash!=MAXTHASH) {
if (iter->node) {
iter->node = iter->node->nexthash;
}
while (!iter->node && iter->hash != MAXTHASH) {
if (++iter->hash != MAXTHASH) {
iter->node = iter->list->tags[iter->hash];
}
}
if (iter->node) {
iter->r = findregion(iter->node->coord.x, iter->node->coord.y);
if (iter->r) {
break;
}
}
}
}
void
tag_rewind(tag_iterator * iter)
{
if (iter->list) {
iter->r = NULL;
iter->node = iter->list->tags[0];
iter->hash = 0;
if (iter->node) {
iter->r = findregion(iter->node->coord.x, iter->node->coord.y);
}
if (!iter->r) {
tag_advance(iter);
}
} else {
iter->node = 0;
iter->hash = MAXTHASH;
}
}
static int
tolua_tags_next(lua_State *L)
{
tag_iterator * iter = (tag_iterator *)lua_touserdata(L, lua_upvalueindex(1));
if (iter->node) {
tolua_pushusertype(L, (void*)iter->r, TOLUA_CAST "region");
tag_advance(iter);
return 1;
}
else {
return 0; /* no more values to return */
}
}
static int
tolua_selected_regions(lua_State* L)
{
tag_iterator * iter = (tag_iterator*)lua_newuserdata(L, sizeof(tag_iterator));
luaL_getmetatable(L, "tag_iterator");
lua_setmetatable(L, -2);
iter->list = current_state->selected;
tag_rewind(iter);
lua_pushcclosure(L, tolua_tags_next, 1);
return 1;
}
static int
tolua_state_open(lua_State* L)
{
unused(L);
state_open();
return 0;
}
static int
tolua_state_close(lua_State* L)
{
unused(L);
state_close(current_state);
return 0;
}
static int
tolua_make_island(lua_State * L)
{
int x = (int)tolua_tonumber(L, 1, 0);
int y = (int)tolua_tonumber(L, 2, 0);
int s = (int)tolua_tonumber(L, 3, 0);
int n = (int)tolua_tonumber(L, 4, s / 3);
n = build_island_e3(x, y, n, s);
tolua_pushnumber(L, n);
return 1;
}
static int paint_handle;
static struct lua_State * paint_state;
static void
lua_paint_info(struct window * wnd, const struct state * st)
{
struct lua_State * L = paint_state;
int nx = st->cursor.x, ny = st->cursor.y;
pnormalize(&nx, &ny, st->cursor.pl);
lua_rawgeti(L, LUA_REGISTRYINDEX, paint_handle);
tolua_pushnumber(L, nx);
tolua_pushnumber(L, ny);
if (lua_pcall(L, 2, 1, 0)!=0) {
const char* error = lua_tostring(L, -1);
log_error(("paint function failed: %s\n", error));
lua_pop(L, 1);
tolua_error(L, TOLUA_CAST "event handler call failed", NULL);
} else {
const char* result = lua_tostring(L, -1);
WINDOW * win = wnd->handle;
int size = getmaxx(win)-2;
int line = 0, maxline = getmaxy(win)-2;
const char * str = result;
wxborder(win);
while (*str && line<maxline) {
const char * end = strchr(str, '\n');
if (!end) break;
else {
size_t len = end-str;
int bytes = MIN((int)len, size);
mvwaddnstr(win, line++, 1, str, bytes);
wclrtoeol(win);
str = end + 1;
}
}
}
}
static int
tolua_set_display(lua_State * L)
{
int type = lua_type(L, 1);
if (type==LUA_TFUNCTION) {
lua_pushvalue(L, 1);
paint_handle = luaL_ref(L, LUA_REGISTRYINDEX);
paint_state = L;
set_info_function(&lua_paint_info);
} else {
set_info_function(NULL);
}
return 0;
}
static int
tolua_make_block(lua_State * L)
{
int x = (int)tolua_tonumber(L, 1, 0);
int y = (int)tolua_tonumber(L, 2, 0);
int r = (int)tolua_tonumber(L, 3, 6);
const char * str = tolua_tostring(L, 4, TOLUA_CAST "ocean");
const struct terrain_type * ter = get_terrain(str);
make_block(x, y, r, ter);
return 0;
}
void
tolua_gmtool_open(lua_State* L)
{
/* register user types */
tolua_usertype(L, TOLUA_CAST "tag_iterator");
tolua_module(L, NULL, 0);
tolua_beginmodule(L, NULL);
{
tolua_module(L, TOLUA_CAST "gmtool", 0);
tolua_beginmodule(L, TOLUA_CAST "gmtool");
{
tolua_function(L, TOLUA_CAST "open", &tolua_state_open);
tolua_function(L, TOLUA_CAST "close", &tolua_state_close);
tolua_function(L, TOLUA_CAST "editor", &tolua_run_mapper);
tolua_function(L, TOLUA_CAST "get_selection", &tolua_selected_regions);
tolua_function(L, TOLUA_CAST "get_cursor", &tolua_current_region);
tolua_function(L, TOLUA_CAST "highlight", &tolua_highlight_region);
tolua_function(L, TOLUA_CAST "select", &tolua_select_region);
tolua_function(L, TOLUA_CAST "select_at", &tolua_select_coordinate);
tolua_function(L, TOLUA_CAST "set_display", &tolua_set_display);
tolua_function(L, TOLUA_CAST "make_block", &tolua_make_block);
tolua_function(L, TOLUA_CAST "make_island", &tolua_make_island);
}
tolua_endmodule(L);
}
tolua_endmodule(L);
}