#include "content_sao.h" // For LuaEntitySAO and PlayerSAO
#include "itemdef.h"
#include "nodedef.h"
+#include "biome.h"
#include "craftdef.h"
#include "main.h" // For g_settings
#include "settings.h" // For accessing g_settings
#include "noise.h" // PseudoRandom for LuaPseudoRandom
#include "util/pointedthing.h"
#include "rollback.h"
+#include "treegen.h"
static void stackDump(lua_State *L, std::ostream &o)
{
{0, NULL},
};
+struct EnumString es_BiomeTerrainType[] =
+{
+ {BIOME_TERRAIN_NORMAL, "normal"},
+ {BIOME_TERRAIN_LIQUID, "liquid"},
+ {BIOME_TERRAIN_NETHER, "nether"},
+ {BIOME_TERRAIN_AETHER, "aether"},
+ {BIOME_TERRAIN_FLAT, "flat"},
+ {0, NULL},
+};
+
/*
C struct <-> Lua table converter functions
*/
lua_pop(L, 1);
getstringfield(L, -1, "visual", prop->visual);
+
+ getstringfield(L, -1, "mesh", prop->mesh);
lua_getfield(L, -1, "visual_size");
if(lua_istable(L, -1))
}
}
lua_pop(L, 1);
+
+ lua_getfield(L, -1, "colors");
+ if(lua_istable(L, -1)){
+ prop->colors.clear();
+ int table = lua_gettop(L);
+ lua_pushnil(L);
+ while(lua_next(L, table) != 0){
+ // key at index -2 and value at index -1
+ if(lua_isstring(L, -1))
+ prop->colors.push_back(readARGB8(L, -1));
+ else
+ prop->colors.push_back(video::SColor(255, 255, 255, 255));
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ }
+ lua_pop(L, 1);
lua_getfield(L, -1, "spritediv");
if(lua_istable(L, -1))
if(lua_istable(L, -1))
prop->initial_sprite_basepos = read_v2s16(L, -1);
lua_pop(L, 1);
-
+
getboolfield(L, -1, "is_visible", prop->is_visible);
getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
warn_if_field_exists(L, index, "tool_digging_properties",
"deprecated: use tool_capabilities");
-
+
lua_getfield(L, index, "tool_capabilities");
if(lua_istable(L, -1)){
def.tool_capabilities = new ToolCapabilities(
{
if(index < 0)
index = lua_gettop(L) + 1 + index;
-
+
TileDef tiledef;
// key at index -2 and value at index
index = lua_gettop(L) + 1 + index;
ContentFeatures f;
-
+
/* Cache existence of some callbacks */
lua_getfield(L, index, "on_construct");
if(!lua_isnil(L, -1)) f.has_on_construct = true;
f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
NDT_NORMAL);
getfloatfield(L, index, "visual_scale", f.visual_scale);
-
+
// tiles = {}
lua_getfield(L, index, "tiles");
// If nil, try the deprecated name "tile_images" instead
}
}
lua_pop(L, 1);
-
+
// special_tiles = {}
lua_getfield(L, index, "special_tiles");
// If nil, try the deprecated name "special_materials" instead
f.alpha = getintfield_default(L, index, "alpha", 255);
/* Other stuff */
-
+
lua_getfield(L, index, "post_effect_color");
if(!lua_isnil(L, -1))
f.post_effect_color = readARGB8(L, -1);
"deprecated: use 'drop' field");
warn_if_field_exists(L, index, "metadata_name",
"deprecated: use on_add and metadata callbacks");
-
+
// True for all ground-like things like stone and mud, false for eg. trees
getboolfield(L, index, "is_ground_content", f.is_ground_content);
f.light_propagates = (f.param_type == CPT_LIGHT);
// the slowest possible
f.liquid_viscosity = getintfield_default(L, index,
"liquid_viscosity", f.liquid_viscosity);
+ getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
// Amount of light the node emits
f.light_source = getintfield_default(L, index,
"light_source", f.light_source);
f.damage_per_second = getintfield_default(L, index,
"damage_per_second", f.damage_per_second);
-
+
lua_getfield(L, index, "node_box");
if(lua_istable(L, -1))
f.node_box = read_nodebox(L, -1);
getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
// Set to true if wall_mounted used to be set to true
getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
-
+
// Sound table
lua_getfield(L, index, "sounds");
if(lua_istable(L, -1)){
static const luaL_reg methods[];
// Exported functions
-
+
// garbage collector
static int gc_object(lua_State *L)
{
{
return m_stack;
}
-
+
// LuaItemStack(itemstack or itemstring or table or nil)
// Creates an LuaItemStack and leaves it on top of stack
static int create_object(lua_State *L)
if(!ud) luaL_typerror(L, narg, className);
return *(InvRef**)ud; // unbox pointer
}
-
+
static Inventory* getinv(lua_State *L, InvRef *ref)
{
return get_server(L)->getInventory(ref->m_loc);
// Inform other things that the inventory has changed
get_server(L)->setInventoryModified(ref->m_loc);
}
-
+
// Exported functions
-
+
// garbage collector
static int gc_object(lua_State *L) {
InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
return 1;
}
+ // get_width(self, listname)
+ static int l_get_width(lua_State *L)
+ {
+ InvRef *ref = checkobject(L, 1);
+ const char *listname = luaL_checkstring(L, 2);
+ InventoryList *list = getlist(L, ref, listname);
+ if(list){
+ lua_pushinteger(L, list->getWidth());
+ } else {
+ lua_pushinteger(L, 0);
+ }
+ return 1;
+ }
+
// set_size(self, listname, size)
static int l_set_size(lua_State *L)
{
return 0;
}
+ // set_width(self, listname, size)
+ static int l_set_width(lua_State *L)
+ {
+ InvRef *ref = checkobject(L, 1);
+ const char *listname = luaL_checkstring(L, 2);
+ int newwidth = luaL_checknumber(L, 3);
+ Inventory *inv = getinv(L, ref);
+ InventoryList *list = inv->getList(listname);
+ if(list){
+ list->setWidth(newwidth);
+ } else {
+ return 0;
+ }
+ reportInventoryChange(L, ref);
+ return 0;
+ }
+
// get_stack(self, listname, i) -> itemstack
static int l_get_stack(lua_State *L)
{
return 1;
}
+ // get_location() -> location (like minetest.get_inventory(location))
+ static int l_get_location(lua_State *L)
+ {
+ InvRef *ref = checkobject(L, 1);
+ const InventoryLocation &loc = ref->m_loc;
+ switch(loc.type){
+ case InventoryLocation::PLAYER:
+ lua_newtable(L);
+ lua_pushstring(L, "player");
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, loc.name.c_str());
+ lua_setfield(L, -2, "name");
+ return 1;
+ case InventoryLocation::NODEMETA:
+ lua_newtable(L);
+ lua_pushstring(L, "nodemeta");
+ lua_setfield(L, -2, "type");
+ push_v3s16(L, loc.p);
+ lua_setfield(L, -2, "name");
+ return 1;
+ case InventoryLocation::DETACHED:
+ lua_newtable(L);
+ lua_pushstring(L, "detached");
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, loc.name.c_str());
+ lua_setfield(L, -2, "name");
+ return 1;
+ case InventoryLocation::UNDEFINED:
+ case InventoryLocation::CURRENT_PLAYER:
+ break;
+ }
+ lua_newtable(L);
+ lua_pushstring(L, "undefined");
+ lua_setfield(L, -2, "type");
+ return 1;
+ }
+
public:
InvRef(const InventoryLocation &loc):
m_loc(loc)
method(InvRef, is_empty),
method(InvRef, get_size),
method(InvRef, set_size),
+ method(InvRef, get_width),
+ method(InvRef, set_width),
method(InvRef, get_stack),
method(InvRef, set_stack),
method(InvRef, get_list),
method(InvRef, room_for_item),
method(InvRef, contains_item),
method(InvRef, remove_item),
+ method(InvRef, get_location),
{0,0}
};
if(!ud) luaL_typerror(L, narg, className);
return *(NodeMetaRef**)ud; // unbox pointer
}
-
+
static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create)
{
NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"NodeMetaRef::reportMetadataChange");
}
-
+
// Exported functions
-
+
// garbage collector
static int gc_object(lua_State *L) {
NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
InvRef::createNodeMeta(L, ref->m_p);
return 1;
}
-
+
// to_table(self)
static int l_to_table(lua_State *L)
{
{
NodeMetaRef *ref = checkobject(L, 1);
int base = 2;
-
+
if(lua_isnil(L, base)){
// No metadata
ref->m_env->getMap().removeNodeMetadata(ref->m_p);
if(!ud) luaL_typerror(L, narg, className);
return *(ObjectRef**)ud; // unbox pointer
}
-
+
static ServerActiveObject* getobject(ObjectRef *ref)
{
ServerActiveObject *co = ref->m_object;
return NULL;
return (LuaEntitySAO*)obj;
}
-
+
static PlayerSAO* getplayersao(ObjectRef *ref)
{
ServerActiveObject *obj = getobject(ref);
return NULL;
return (PlayerSAO*)obj;
}
-
+
static Player* getplayer(ObjectRef *ref)
{
PlayerSAO *playersao = getplayersao(ref);
return NULL;
return playersao->getPlayer();
}
-
+
// Exported functions
-
+
// garbage collector
static int gc_object(lua_State *L) {
ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
co->m_removed = true;
return 0;
}
-
+
// getpos(self)
// returns: {x=num, y=num, z=num}
static int l_getpos(lua_State *L)
lua_setfield(L, -2, "z");
return 1;
}
-
+
// setpos(self, pos)
static int l_setpos(lua_State *L)
{
co->setPos(pos);
return 0;
}
-
+
// moveto(self, pos, continuous=false)
static int l_moveto(lua_State *L)
{
return 0;
}
- // punch(self, puncher, tool_capabilities, direction, time_from_last_punch)
+ // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
static int l_punch(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *puncher = getobject(puncher_ref);
if(co == NULL) return 0;
if(puncher == NULL) return 0;
- ToolCapabilities toolcap = read_tool_capabilities(L, 3);
- v3f dir = read_v3f(L, 4);
+ v3f dir;
+ if(lua_type(L, 5) != LUA_TTABLE)
+ dir = co->getBasePosition() - puncher->getBasePosition();
+ else
+ dir = read_v3f(L, 5);
float time_from_last_punch = 1000000;
- if(lua_isnumber(L, 5))
- time_from_last_punch = lua_tonumber(L, 5);
+ if(lua_isnumber(L, 3))
+ time_from_last_punch = lua_tonumber(L, 3);
+ ToolCapabilities toolcap = read_tool_capabilities(L, 4);
+ dir.normalize();
// Do it
- puncher->punch(dir, &toolcap, puncher, time_from_last_punch);
+ co->punch(dir, &toolcap, puncher, time_from_last_punch);
return 0;
}
return 0;
}
+ // set_animation(self, frame_range, frame_speed, frame_blend)
+ static int l_set_animation(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if(co == NULL) return 0;
+ // Do it
+ v2f frames = v2f(1, 1);
+ if(!lua_isnil(L, 2))
+ frames = read_v2f(L, 2);
+ float frame_speed = 15;
+ if(!lua_isnil(L, 3))
+ frame_speed = lua_tonumber(L, 3);
+ float frame_blend = 0;
+ if(!lua_isnil(L, 4))
+ frame_blend = lua_tonumber(L, 4);
+ co->setAnimation(frames, frame_speed, frame_blend);
+ return 0;
+ }
+
+ // set_bone_position(self, std::string bone, v3f position, v3f rotation)
+ static int l_set_bone_position(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if(co == NULL) return 0;
+ // Do it
+ std::string bone = "";
+ if(!lua_isnil(L, 2))
+ bone = lua_tostring(L, 2);
+ v3f position = v3f(0, 0, 0);
+ if(!lua_isnil(L, 3))
+ position = read_v3f(L, 3);
+ v3f rotation = v3f(0, 0, 0);
+ if(!lua_isnil(L, 4))
+ rotation = read_v3f(L, 4);
+ co->setBonePosition(bone, position, rotation);
+ return 0;
+ }
+
+ // set_attach(self, parent, bone, position, rotation)
+ static int l_set_attach(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ObjectRef *parent_ref = checkobject(L, 2);
+ ServerActiveObject *co = getobject(ref);
+ ServerActiveObject *parent = getobject(parent_ref);
+ if(co == NULL) return 0;
+ if(parent == NULL) return 0;
+ // Do it
+ std::string bone = "";
+ if(!lua_isnil(L, 3))
+ bone = lua_tostring(L, 3);
+ v3f position = v3f(0, 0, 0);
+ if(!lua_isnil(L, 4))
+ position = read_v3f(L, 4);
+ v3f rotation = v3f(0, 0, 0);
+ if(!lua_isnil(L, 5))
+ rotation = read_v3f(L, 5);
+ co->setAttachment(parent->getId(), bone, position, rotation);
+ return 0;
+ }
+
+ // set_detach(self)
+ static int l_set_detach(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if(co == NULL) return 0;
+ // Do it
+ co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
+ return 0;
+ }
+
// set_properties(self, properties)
static int l_set_properties(lua_State *L)
{
co->setVelocity(pos);
return 0;
}
-
+
// getvelocity(self)
static int l_getvelocity(lua_State *L)
{
pushFloatPos(L, v);
return 1;
}
-
+
// setacceleration(self, {x=num, y=num, z=num})
static int l_setacceleration(lua_State *L)
{
co->setAcceleration(pos);
return 0;
}
-
+
// getacceleration(self)
static int l_getacceleration(lua_State *L)
{
pushFloatPos(L, v);
return 1;
}
-
+
// setyaw(self, radians)
static int l_setyaw(lua_State *L)
{
co->setYaw(yaw);
return 0;
}
-
+
// getyaw(self)
static int l_getyaw(lua_State *L)
{
lua_pushnumber(L, yaw);
return 1;
}
-
+
// settexturemod(self, mod)
static int l_settexturemod(lua_State *L)
{
co->setTextureMod(mod);
return 0;
}
-
+
// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
// select_horiz_by_yawpitch=false)
static int l_setsprite(lua_State *L)
lua_pushstring(L, name.c_str());
return 1;
}
-
+
// get_luaentity(self)
static int l_get_luaentity(lua_State *L)
{
luaentity_get(L, co->getId());
return 1;
}
-
+
/* Player-only */
// is_player(self)
lua_pushboolean(L, (player != NULL));
return 1;
}
-
+
// get_player_name(self)
static int l_get_player_name(lua_State *L)
{
lua_pushstring(L, player->getName());
return 1;
}
-
+
// get_look_dir(self)
static int l_get_look_dir(lua_State *L)
{
lua_pushlstring(L, formspec.c_str(), formspec.size());
return 1;
}
-
+
+ // get_player_control(self)
+ static int l_get_player_control(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if(player == NULL){
+ lua_pushlstring(L, "", 0);
+ return 1;
+ }
+ // Do it
+ PlayerControl control = player->getPlayerControl();
+ lua_newtable(L);
+ lua_pushboolean(L, control.up);
+ lua_setfield(L, -2, "up");
+ lua_pushboolean(L, control.down);
+ lua_setfield(L, -2, "down");
+ lua_pushboolean(L, control.left);
+ lua_setfield(L, -2, "left");
+ lua_pushboolean(L, control.right);
+ lua_setfield(L, -2, "right");
+ lua_pushboolean(L, control.jump);
+ lua_setfield(L, -2, "jump");
+ lua_pushboolean(L, control.aux1);
+ lua_setfield(L, -2, "aux1");
+ lua_pushboolean(L, control.sneak);
+ lua_setfield(L, -2, "sneak");
+ lua_pushboolean(L, control.LMB);
+ lua_setfield(L, -2, "LMB");
+ lua_pushboolean(L, control.RMB);
+ lua_setfield(L, -2, "RMB");
+ return 1;
+ }
+
+ // get_player_control_bits(self)
+ static int l_get_player_control_bits(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if(player == NULL){
+ lua_pushlstring(L, "", 0);
+ return 1;
+ }
+ // Do it
+ lua_pushnumber(L, player->keyPressed);
+ return 1;
+ }
+
public:
ObjectRef(ServerActiveObject *object):
m_object(object)
ObjectRef *o = checkobject(L, -1);
o->m_object = NULL;
}
-
+
static void Register(lua_State *L)
{
lua_newtable(L);
method(ObjectRef, get_wielded_item),
method(ObjectRef, set_wielded_item),
method(ObjectRef, set_armor_groups),
+ method(ObjectRef, set_animation),
+ method(ObjectRef, set_bone_position),
+ method(ObjectRef, set_attach),
+ method(ObjectRef, set_detach),
method(ObjectRef, set_properties),
// LuaEntitySAO-only
method(ObjectRef, setvelocity),
method(ObjectRef, get_look_yaw),
method(ObjectRef, set_inventory_formspec),
method(ObjectRef, get_inventory_formspec),
+ method(ObjectRef, get_player_control),
+ method(ObjectRef, get_player_control_bits),
{0,0}
};
private:
int seed;
int octaves;
- double persistence;
- double scale;
+ float persistence;
+ float scale;
static const char className[];
static const luaL_reg methods[];
}
public:
- LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence,
- double a_scale):
+ LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
+ float a_scale):
seed(a_seed),
octaves(a_octaves),
persistence(a_persistence),
{
int seed = luaL_checkint(L, 1);
int octaves = luaL_checkint(L, 2);
- double persistence = luaL_checknumber(L, 3);
- double scale = luaL_checknumber(L, 4);
+ float persistence = luaL_checknumber(L, 3);
+ float scale = luaL_checknumber(L, 4);
LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
if(!ud) luaL_typerror(L, narg, className);
return *(NodeTimerRef**)ud; // unbox pointer
}
-
+
static int l_set(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e));
return 0;
}
-
+
static int l_start(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0));
return 0;
}
-
+
static int l_stop(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
env->getMap().removeNodeTimer(o->m_p);
return 0;
}
-
+
static int l_is_started(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
lua_pushboolean(L,(t.timeout != 0));
return 1;
}
-
+
static int l_get_timeout(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
lua_pushnumber(L,t.timeout);
return 1;
}
-
+
static int l_get_elapsed(lua_State *L)
{
NodeTimerRef *o = checkobject(L, 1);
NodeTimerRef *o = checkobject(L, -1);
o->m_env = NULL;
}
-
+
static void Register(lua_State *L)
{
lua_newtable(L);
if(!ud) luaL_typerror(L, narg, className);
return *(EnvRef**)ud; // unbox pointer
}
-
+
// Exported functions
// EnvRef:set_node(pos, node)
v3s16 pos = read_v3s16(L, 2);
MapNode n = readnode(L, 3, ndef);
// Do it
- MapNode n_old = env->getMap().getNodeNoEx(pos);
- // Call destructor
- if(ndef->get(n_old).has_on_destruct)
- scriptapi_node_on_destruct(L, pos, n_old);
- // Replace node
- bool succeeded = env->getMap().addNodeWithEvent(pos, n);
- if(succeeded){
- // Call post-destructor
- if(ndef->get(n_old).has_after_destruct)
- scriptapi_node_after_destruct(L, pos, n_old);
- // Call constructor
- if(ndef->get(n).has_on_construct)
- scriptapi_node_on_construct(L, pos, n);
- }
+ bool succeeded = env->setNode(pos, n);
lua_pushboolean(L, succeeded);
return 1;
}
// parameters
v3s16 pos = read_v3s16(L, 2);
// Do it
- MapNode n_old = env->getMap().getNodeNoEx(pos);
- // Call destructor
- if(ndef->get(n_old).has_on_destruct)
- scriptapi_node_on_destruct(L, pos, n_old);
- // Replace with air
- // This is slightly optimized compared to addNodeWithEvent(air)
- bool succeeded = env->getMap().removeNodeWithEvent(pos);
- if(succeeded){
- // Call post-destructor
- if(ndef->get(n_old).has_after_destruct)
- scriptapi_node_after_destruct(L, pos, n_old);
- }
+ bool succeeded = env->removeNode(pos);
lua_pushboolean(L, succeeded);
- // Air doesn't require constructor
return 1;
}
if(lua_isnumber(L, 3))
time_of_day = 24000.0 * lua_tonumber(L, 3);
time_of_day %= 24000;
- u32 dnr = time_to_daynight_ratio(time_of_day);
+ u32 dnr = time_to_daynight_ratio(time_of_day, true);
MapNode n = env->getMap().getNodeNoEx(pos);
try{
MapNode n = env->getMap().getNode(pos);
lua_getglobal(L, "table");
lua_getfield(L, -1, "insert");
int table_insert = lua_gettop(L);
-
+
lua_newtable(L);
int table = lua_gettop(L);
for(s16 x=minp.X; x<=maxp.X; x++)
int seeddiff = luaL_checkint(L, 2);
int octaves = luaL_checkint(L, 3);
- double persistence = luaL_checknumber(L, 4);
- double scale = luaL_checknumber(L, 5);
+ float persistence = luaL_checknumber(L, 4);
+ float scale = luaL_checknumber(L, 5);
LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = n;
return 1;
}
+ // EnvRef:clear_objects()
+ // clear all objects in the environment
+ static int l_clear_objects(lua_State *L)
+ {
+ EnvRef *o = checkobject(L, 1);
+ o->m_env->clearAllObjects();
+ return 0;
+ }
+
+ static int l_spawn_tree(lua_State *L)
+ {
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->m_env;
+ if(env == NULL) return 0;
+ v3s16 p0 = read_v3s16(L, 2);
+
+ treegen::TreeDef tree_def;
+ std::string trunk,leaves,fruit;
+ INodeDefManager *ndef = env->getGameDef()->ndef();
+
+ if(lua_istable(L, 3))
+ {
+ getstringfield(L, 3, "axiom", tree_def.initial_axiom);
+ getstringfield(L, 3, "rules_a", tree_def.rules_a);
+ getstringfield(L, 3, "rules_b", tree_def.rules_b);
+ getstringfield(L, 3, "rules_c", tree_def.rules_c);
+ getstringfield(L, 3, "rules_d", tree_def.rules_d);
+ getstringfield(L, 3, "trunk", trunk);
+ tree_def.trunknode=ndef->getId(trunk);
+ getstringfield(L, 3, "leaves", leaves);
+ tree_def.leavesnode=ndef->getId(leaves);
+ tree_def.leaves2_chance=0;
+ getstringfield(L, 3, "leaves2", leaves);
+ if (leaves !="")
+ {
+ tree_def.leaves2node=ndef->getId(leaves);
+ getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance);
+ }
+ getintfield(L, 3, "angle", tree_def.angle);
+ getintfield(L, 3, "iterations", tree_def.iterations);
+ getintfield(L, 3, "random_level", tree_def.iterations_random_level);
+ getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
+ getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
+ tree_def.fruit_chance=0;
+ getstringfield(L, 3, "fruit", fruit);
+ if (fruit != "")
+ {
+ tree_def.fruitnode=ndef->getId(fruit);
+ getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
+ }
+ }
+ else
+ return 0;
+ treegen::spawn_ltree (env, p0, ndef, tree_def);
+ return 1;
+ }
+
public:
EnvRef(ServerEnvironment *env):
m_env(env)
EnvRef *o = checkobject(L, -1);
o->m_env = NULL;
}
-
+
static void Register(lua_State *L)
{
lua_newtable(L);
method(EnvRef, find_node_near),
method(EnvRef, find_nodes_in_area),
method(EnvRef, get_perlin),
+ //method{EnvRef, get_perlin_map_2d},
+ //method{EnvRef, get_perlin_map_3d},
+ method(EnvRef, clear_objects),
+ method(EnvRef, spawn_tree),
{0,0}
};
static const luaL_reg methods[];
// Exported functions
-
+
// garbage collector
static int gc_object(lua_State *L)
{
{
return m_pseudo;
}
-
+
// LuaPseudoRandom(seed)
// Creates an LuaPseudoRandom and leaves it on top of stack
static int create_object(lua_State *L)
u32 active_object_count, u32 active_object_count_wider)
{
lua_State *L = m_lua;
-
+
realitycheck(L);
assert(lua_checkstack(L, 20));
StackUnroller stack_unroller(L);
lua_gettable(L, registered_abms);
if(lua_isnil(L, -1))
assert(0);
-
+
// Call action
luaL_checktype(L, -1, LUA_TTABLE);
lua_getfield(L, -1, "action");
return 0;
}
+// request_shutdown()
+static int l_request_shutdown(lua_State *L)
+{
+ get_server(L)->requestShutdown();
+ return 0;
+}
+
+// get_server_status()
+static int l_get_server_status(lua_State *L)
+{
+ lua_pushstring(L, wide_to_narrow(get_server(L)->getStatusString()).c_str());
+ return 1;
+}
+
+// register_biome_groups({frequencies})
+static int l_register_biome_groups(lua_State *L)
+{
+ luaL_checktype(L, 1, LUA_TTABLE);
+ int index = 1;
+ if (!lua_istable(L, index))
+ throw LuaError(L, "register_biome_groups: parameter is not a table");
+
+ BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
+ if (!bmgr) {
+ verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl;
+ return 0;
+ }
+
+ lua_pushnil(L);
+ for (int i = 1; lua_next(L, index) != 0; i++) {
+ bmgr->addBiomeGroup(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ return 0;
+}
+
+// register_biome({lots of stuff})
+static int l_register_biome(lua_State *L)
+{
+ luaL_checktype(L, 1, LUA_TTABLE);
+ int index = 1, groupid;
+ std::string nodename;
+
+ IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
+ BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
+ if (!bmgr) {
+ verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
+ return 0;
+ }
+
+ groupid = getintfield_default(L, index, "group_id", 0);
+
+ enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
+ "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
+ Biome *b = bmgr->createBiome(terrain);
+
+ b->name = getstringfield_default(L, index, "name", "");
+
+ if (getstringfield(L, index, "node_top", nodename))
+ b->n_top = MapNode(ndef->getId(nodename));
+ else
+ b->n_top = MapNode(CONTENT_IGNORE);
+
+ if (getstringfield(L, index, "node_filler", nodename))
+ b->n_filler = MapNode(ndef->getId(nodename));
+ else
+ b->n_filler = b->n_top;
+
+ b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0);
+
+ b->height_min = getintfield_default(L, index, "height_min", 0);
+ b->height_max = getintfield_default(L, index, "height_max", 0);
+ b->heat_min = getfloatfield_default(L, index, "heat_min", 0.);
+ b->heat_max = getfloatfield_default(L, index, "heat_max", 0.);
+ b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.);
+ b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.);
+
+ b->np = new NoiseParams; // should read an entire NoiseParams later on...
+ getfloatfield(L, index, "scale", b->np->scale);
+ getfloatfield(L, index, "offset", b->np->offset);
+
+ b->groupid = (s8)groupid;
+ b->flags = 0; //reserved
+
+ bmgr->addBiome(b);
+
+ verbosestream << "register_biome: " << b->name << std::endl;
+ return 0;
+}
+
// register_item_raw({lots of stuff})
static int l_register_item_raw(lua_State *L)
{
else
def.node_placement_prediction = "";
}
-
+
// Register item definition
idef->registerItem(def);
// Get the writable item definition manager from the server
IWritableItemDefManager *idef =
get_server(L)->getWritableItemDefManager();
-
+
idef->registerAlias(name, convert_to);
-
+
return 0; /* number of results */
}
// Get the writable craft definition manager from the server
IWritableCraftDefManager *craftdef =
get_server(L)->getWritableCraftDefManager();
-
+
std::string type = getstringfield_default(L, table, "type", "shaped");
/*
return 1;
}
+// get_ban_list()
+static int l_get_ban_list(lua_State *L)
+{
+ lua_pushstring(L, get_server(L)->getBanDescription("").c_str());
+ return 1;
+}
+
+// get_ban_description()
+static int l_get_ban_description(lua_State *L)
+{
+ const char * ip_or_name = luaL_checkstring(L, 1);
+ lua_pushstring(L, get_server(L)->getBanDescription(std::string(ip_or_name)).c_str());
+ return 1;
+}
+
+// ban_player()
+static int l_ban_player(lua_State *L)
+{
+ const char * name = luaL_checkstring(L, 1);
+ Player *player = get_env(L)->getPlayer(name);
+ if(player == NULL)
+ {
+ lua_pushboolean(L, false); // no such player
+ return 1;
+ }
+ try
+ {
+ Address addr = get_server(L)->getPeerAddress(get_env(L)->getPlayer(name)->peer_id);
+ std::string ip_str = addr.serializeString();
+ get_server(L)->setIpBanned(ip_str, name);
+ }
+ catch(con::PeerNotFoundException) // unlikely
+ {
+ dstream << __FUNCTION_NAME << ": peer was not found" << std::endl;
+ lua_pushboolean(L, false); // error
+ return 1;
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// unban_player_or_ip()
+static int l_unban_player_of_ip(lua_State *L)
+{
+ const char * ip_or_name = luaL_checkstring(L, 1);
+ get_server(L)->unsetIpBanned(ip_or_name);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
// get_inventory(location)
static int l_get_inventory(lua_State *L)
{
std::string name = checkstringfield(L, 1, "name");
loc.setDetached(name);
}
-
+
if(get_server(L)->getInventory(loc) != NULL)
InvRef::create(L, loc);
else
return 1;
}
+// show_formspec(playername,formname,formspec)
+static int l_show_formspec(lua_State *L)
+{
+ const char *playername = luaL_checkstring(L, 1);
+ const char *formname = luaL_checkstring(L, 2);
+ const char *formspec = luaL_checkstring(L, 3);
+
+ if(get_server(L)->showFormspec(playername,formspec,formname))
+ {
+ lua_pushboolean(L, true);
+ }else{
+ lua_pushboolean(L, false);
+ }
+ return 1;
+}
+
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_dig_params(lua_State *L)
{
lua_getfield(L, input_i, "items");
std::vector<ItemStack> items = read_items(L, -1);
lua_pop(L, 1); // items
-
+
IGameDef *gdef = get_server(L);
ICraftDefManager *cdef = gdef->cdef();
CraftInput input(method, width, items);
char tmp[20];
int input_i = 1;
std::string o_item = luaL_checkstring(L,input_i);
-
+
IGameDef *gdef = get_server(L);
ICraftDefManager *cdef = gdef->cdef();
CraftInput input;
static const struct luaL_Reg minetest_f [] = {
{"debug", l_debug},
{"log", l_log},
+ {"request_shutdown", l_request_shutdown},
+ {"get_server_status", l_get_server_status},
{"register_item_raw", l_register_item_raw},
{"register_alias_raw", l_register_alias_raw},
{"register_craft", l_register_craft},
+ {"register_biome", l_register_biome},
+ {"register_biome_groups", l_register_biome_groups},
{"setting_set", l_setting_set},
{"setting_get", l_setting_get},
{"setting_getbool", l_setting_getbool},
{"chat_send_all", l_chat_send_all},
{"chat_send_player", l_chat_send_player},
{"get_player_privs", l_get_player_privs},
+ {"get_ban_list", l_get_ban_list},
+ {"get_ban_description", l_get_ban_description},
+ {"ban_player", l_ban_player},
+ {"unban_player_or_ip", l_unban_player_of_ip},
{"get_inventory", l_get_inventory},
{"create_detached_inventory_raw", l_create_detached_inventory_raw},
+ {"show_formspec", l_show_formspec},
{"get_dig_params", l_get_dig_params},
{"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname},
lua_newtable(L);
luaL_register(L, NULL, minetest_f);
lua_setglobal(L, "minetest");
-
+
// Get the main minetest table
lua_getglobal(L, "minetest");
<<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
return false;
}
-
+
bool success = false;
try{
lua_getfield(L, -1, "registered_abms");
luaL_checktype(L, -1, LUA_TTABLE);
int registered_abms = lua_gettop(L);
-
+
if(lua_istable(L, registered_abms)){
int table = lua_gettop(L);
lua_pushnil(L);
LuaABM *abm = new LuaABM(L, id, trigger_contents,
required_neighbors, trigger_interval, trigger_chance);
-
+
env->addActiveBlockModifier(abm);
// removes value, keeps key for next iteration
lua_getfield(L, -1, "object_refs");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
-
+
// object_refs[id] = object
lua_pushnumber(L, cobj->getId()); // Push id
lua_pushvalue(L, object); // Copy object to top of stack
lua_getfield(L, -1, "object_refs");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
-
+
// Get object_refs[id]
lua_pushnumber(L, cobj->getId()); // Push id
lua_gettable(L, objectstable);
lua_replace(L, rv);
else if(mode == RUN_CALLBACKS_MODE_AND ||
mode == RUN_CALLBACKS_MODE_AND_SC){
- if(lua_toboolean(L, rv) == true &&
- lua_toboolean(L, -1) == false)
+ if((bool)lua_toboolean(L, rv) == true &&
+ (bool)lua_toboolean(L, -1) == false)
lua_replace(L, rv);
else
lua_pop(L, 1);
}
else if(mode == RUN_CALLBACKS_MODE_OR ||
mode == RUN_CALLBACKS_MODE_OR_SC){
- if(lua_toboolean(L, rv) == false &&
- lua_toboolean(L, -1) == true)
+ if((bool)lua_toboolean(L, rv) == false &&
+ (bool)lua_toboolean(L, -1) == true)
lua_replace(L, rv);
else
lua_pop(L, 1);
// Handle short circuit modes
if(mode == RUN_CALLBACKS_MODE_AND_SC &&
- lua_toboolean(L, rv) == false)
+ (bool)lua_toboolean(L, rv) == false)
break;
else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
- lua_toboolean(L, rv) == true)
+ (bool)lua_toboolean(L, rv) == true)
break;
// value removed, keep key for next iteration
return ate;
}
+void scriptapi_on_shutdown(lua_State *L)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ // Get registered shutdown hooks
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_on_shutdown");
+ // Call callbacks
+ scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST);
+}
+
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
{
realitycheck(L);
realitycheck(L);
assert(lua_checkstack(L, 20));
StackUnroller stack_unroller(L);
-
+
get_auth_handler(L);
lua_getfield(L, -1, "get_auth");
if(lua_type(L, -1) != LUA_TFUNCTION)
lua_pushstring(L, playername.c_str());
if(lua_pcall(L, 1, 1, 0))
script_error(L, "error: %s", lua_tostring(L, -1));
-
+
// nil = login not allowed
if(lua_isnil(L, -1))
return false;
luaL_checktype(L, -1, LUA_TTABLE);
-
+
std::string password;
bool found = getstringfield(L, -1, "password", password);
if(!found)
if(dst_privs)
read_privileges(L, -1, *dst_privs);
lua_pop(L, 1);
-
+
return true;
}
realitycheck(L);
assert(lua_checkstack(L, 20));
StackUnroller stack_unroller(L);
-
+
get_auth_handler(L);
lua_getfield(L, -1, "create_auth");
if(lua_type(L, -1) != LUA_TFUNCTION)
realitycheck(L);
assert(lua_checkstack(L, 20));
StackUnroller stack_unroller(L);
-
+
get_auth_handler(L);
lua_getfield(L, -1, "set_password");
if(lua_type(L, -1) != LUA_TFUNCTION)
player
*/
-void scriptapi_on_player_receive_fields(lua_State *L,
+void scriptapi_on_player_receive_fields(lua_State *L,
ServerActiveObject *player,
const std::string &formname,
const std::map<std::string, std::string> &fields)
// If that is nil or on error, return false and stack is unchanged
// If that is a function, returns true and pushes the
// function onto the stack
+// If minetest.registered_items[name] doesn't exist, minetest.nodedef_default
+// is tried instead so unknown items can still be manipulated to some degree
static bool get_item_callback(lua_State *L,
const char *name, const char *callbackname)
{
// Should be a table
if(lua_type(L, -1) != LUA_TTABLE)
{
+ // Report error and clean up
errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
lua_pop(L, 1);
- return false;
+
+ // Try minetest.nodedef_default instead
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "nodedef_default");
+ lua_remove(L, -2);
+ luaL_checktype(L, -1, LUA_TTABLE);
}
lua_getfield(L, -1, callbackname);
lua_remove(L, -2);
lua_pushnumber(L,dtime);
if(lua_pcall(L, 2, 1, 0))
script_error(L, "error: %s", lua_tostring(L, -1));
- if(lua_isboolean(L,-1) && lua_toboolean(L,-1) == true)
+ if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true)
return true;
-
+
return false;
}
StackUnroller stack_unroller(L);
INodeDefManager *ndef = get_server(L)->ndef();
-
+
// If node doesn't exist, we don't know what callback to call
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
if(node.getContent() == CONTENT_IGNORE)
verbosestream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
<<name<<"\""<<std::endl;
StackUnroller stack_unroller(L);
-
+
// Get minetest.registered_entities[name]
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "registered_entities");
}
int prototype_table = lua_gettop(L);
//dump2(L, "prototype_table");
-
+
// Create entity object
lua_newtable(L);
int object = lua_gettop(L);
// Set object metatable
lua_pushvalue(L, prototype_table);
lua_setmetatable(L, -2);
-
+
// Add object reference
// This should be userdata with metatable ObjectRef
objectref_get(L, id);
lua_pushnumber(L, id); // Push id
lua_pushvalue(L, object); // Copy object to top of stack
lua_settable(L, -3);
-
+
return true;
}
void scriptapi_luaentity_activate(lua_State *L, u16 id,
- const std::string &staticdata)
+ const std::string &staticdata, u32 dtime_s)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
verbosestream<<"scriptapi_luaentity_activate: id="<<id<<std::endl;
StackUnroller stack_unroller(L);
-
+
// Get minetest.luaentities[id]
luaentity_get(L, id);
int object = lua_gettop(L);
-
+
// Get on_activate function
lua_pushvalue(L, object);
lua_getfield(L, -1, "on_activate");
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
lua_pushlstring(L, staticdata.c_str(), staticdata.size());
- // Call with 2 arguments, 0 results
- if(lua_pcall(L, 2, 0, 0))
+ lua_pushinteger(L, dtime_s);
+ // Call with 3 arguments, 0 results
+ if(lua_pcall(L, 3, 0, 0))
script_error(L, "error running function on_activate: %s\n",
lua_tostring(L, -1));
}
lua_getfield(L, -1, "luaentities");
luaL_checktype(L, -1, LUA_TTABLE);
int objectstable = lua_gettop(L);
-
+
// Set luaentities[id] = nil
lua_pushnumber(L, id); // Push id
lua_pushnil(L);
lua_settable(L, objectstable);
-
+
lua_pop(L, 2); // pop luaentities, minetest
}
// Get minetest.luaentities[id]
luaentity_get(L, id);
int object = lua_gettop(L);
-
+
// Get get_staticdata function
lua_pushvalue(L, object);
lua_getfield(L, -1, "get_staticdata");
if(lua_isnil(L, -1))
return "";
-
+
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
// Call with 1 arguments, 1 results
if(lua_pcall(L, 1, 1, 0))
script_error(L, "error running function get_staticdata: %s\n",
lua_tostring(L, -1));
-
+
size_t len=0;
const char *s = lua_tolstring(L, -1, &len);
return std::string(s, len);
// Set default values that differ from ObjectProperties defaults
prop->hp_max = 10;
-
+
/* Read stuff */
-
+
prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
getboolfield(L, -1, "physical", prop->physical);
lua_pop(L, 1);
getstringfield(L, -1, "visual", prop->visual);
-
+
+ getstringfield(L, -1, "mesh", prop->mesh);
+
// Deprecated: read object properties directly
read_object_properties(L, -1, prop);
-
+
// Read initial_properties
lua_getfield(L, -1, "initial_properties");
read_object_properties(L, -1, prop);