/*
gcc -Wall -shared -fPIC -o mtmapgenc.so main.c
*/
#include <stdio.h> /* Just for basic testing (e.g. printf()) */
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#define LUA_NAMESPACE "mtmgc"
#define MODNAME "[caverealms]"
#if LUA_VERSION_NUM > 501
# define luaL_reg luaL_Reg
#endif
/* Default values for (some) settings */
#define DEFAULT_TCAVE 0.5
struct settings {
int ymin; /* bottom realm limit */
int ymax; /* top realm limit */
double tcave; /* cave threshold */
};
struct mapgen {
int x0, x1,
y0, y1,
z0, z1;
uint16_t *nvals_cave,
*nvals_wave,
*nvals_biome;
uint16_t *data;
};
struct nodeids {
size_t n;
uint16_t *cid;
};
enum {
C_AIR
};
static int l_gencaverealm(lua_State *L);
/* Private functions */
static int parseargs(lua_State *L, struct settings *cfg, struct mapgen *mapg, struct nodeids *nids);
static int parsearg_settings(lua_State *L, struct settings *cfg, int tidx);
static void parsearg_noisedata(lua_State *L, struct mapgen *mapg, int tidx);
static void parsearg_nodeidtable(lua_State *L, struct nodeids *nids, int tidx);
static void parsearg_mapgeom(lua_State *L, struct mapgen *mapg, int tidx);
const struct luaL_reg lua_funcs[] = {
{ "gencaverealms", l_gencaverealm },
{ NULL, NULL}
};
int luaopen_cavemapgenc(lua_State *L)
{
const luaL_reg *f;
luaL_newmetatable(L, LUA_NAMESPACE);
lua_pushstring(L, "__index");
lua_newtable(L);
/* "install" functions into metatable */
for (f = lua_funcs; f->func != NULL && f->name != NULL; f++) {
lua_pushcfunction(L, f->func);
lua_setfield(L, -2, f->name);
}
return 1;
}
/*********************************************************************
Functions 'exported' to Lua
*********************************************************************/
/* "Lua Prototype": void f(settingstable, nodeidtable); */
static int l_gencaverealm(lua_State *L)
{
struct settings cfg;
struct mapgen mapg;
struct nodeids nids = {0};
if (!parseargs(L, &cfg, &mapg, &nids)) {
lua_pushstring(L, MODNAME" Error parsing settings");
lua_error(L);
}
printf("[%s] %d, %d, %d\n", MODNAME, mapg.x0, mapg.y0, mapg.z0);
//printf("[%s] %d, %d, %f\n", MODNAME, cfg.ymin, cfg.ymax, cfg.tcave);
if (nids.cid) free (nids.cid);
return 0;
}
/*********************************************************************
Private
*********************************************************************/
/* (settingstable, nodeidtable) */
static int parseargs(lua_State *L, struct settings *cfg, struct mapgen *mapg, struct nodeids *nids)
{
luaL_checktype(L, 1, LUA_TTABLE);
parsearg_settings(L, cfg, 1);
luaL_checktype(L, 2, LUA_TTABLE);
parsearg_nodeidtable(L, nids, 2);
luaL_checktype(L, 3, LUA_TTABLE);
//parsearg_noisedata(L, mapg, 3);
luaL_checktype(L, 4, LUA_TTABLE);
parsearg_mapgeom(L, mapg, 4);
luaL_checktype(L, 5, LUA_TUSERDATA);
mapg->data = *(uint16_t **)(lua_touserdata(L, 5));
return 1;
}
static int parsearg_settings(lua_State *L, struct settings *cfg, int tidx)
{
lua_getfield(L, tidx, "ymin");
cfg->ymin = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "ymax");
cfg->ymax = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "tcave");
cfg->tcave = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : DEFAULT_TCAVE;
lua_pop(L, 3); /* Restore Lua stack */
if (cfg->ymax == cfg->ymin) {
lua_pushstring(L, MODNAME" Error: ymin and ymax are equal");
lua_error(L);
}
return 1;
}
static void parsearg_nodeidtable(lua_State *L, struct nodeids *nids, int tidx)
{
size_t n, i;
n = luaL_getn(L, tidx);
nids->n = n;
nids->cid = malloc(sizeof *nids->cid * n);
if (!nids->cid) {
lua_pushstring(L, MODNAME" Error: could not allocate memory");
lua_error(L);
}
for (i = 0; i < n; i++) {
lua_pushinteger(L, i+1);
lua_gettable(L, -2);
if(lua_isnumber(L, -1)) {
nids->cid[i] = lua_tonumber(L, -1);
} else {
lua_pushstring(L, MODNAME" Error: expected number (nodeid)");
lua_error(L);
}
lua_pop(L, 1);
}
}
static void parsearg_noisedata(lua_State *L, struct mapgen *mapg, int tidx)
{
lua_getfield(L, tidx, "nvals_cave");
mapg->nvals_cave = lua_isuserdata(L, -1) ? *(uint16_t **)(lua_touserdata(L, -1)) : NULL;
lua_getfield(L, tidx, "nvals_wave");
mapg->nvals_wave = lua_isuserdata(L, -1) ? *(uint16_t **)(lua_touserdata(L, -1)) : NULL;
lua_getfield(L, tidx, "nvals_biome");
mapg->nvals_biome = lua_isuserdata(L, -1) ? *(uint16_t **)(lua_touserdata(L, -1)) : NULL;
if (!(mapg->nvals_cave && mapg->nvals_wave && mapg->nvals_biome)) {
lua_pushstring(L, MODNAME" Error: noise values not supplied");
lua_error(L);
}
lua_pop(L, 3);
}
static void parsearg_mapgeom(lua_State *L, struct mapgen *mapg, int tidx)
{
lua_getfield(L, tidx, "x0");
mapg->x0 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "x1");
mapg->x1 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "y0");
mapg->y0 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "y1");
mapg->y1 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "x0");
mapg->z0 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
lua_getfield(L, tidx, "x1");
mapg->z1 = lua_isnumber(L, -1) ? lua_tointeger(L, -1) : 0;
}