aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-11-17 16:21:17 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-11-29 19:13:49 +0200
commit1220b642ebf3c9a28b6eb88160ef63263fa00a44 (patch)
treefb19125f0c61d630b95d8a463395f6837e969bdd
parentcc03718d3c492a401bbc4b071d0ae1f0c808de95 (diff)
downloadminetest-1220b642ebf3c9a28b6eb88160ef63263fa00a44.tar.gz
minetest-1220b642ebf3c9a28b6eb88160ef63263fa00a44.tar.bz2
minetest-1220b642ebf3c9a28b6eb88160ef63263fa00a44.zip
Falling sand and gravel
-rw-r--r--data/mods/default/init.lua169
-rw-r--r--src/script.cpp2
-rw-r--r--src/scriptapi.cpp117
3 files changed, 233 insertions, 55 deletions
diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua
index 966b807ae..949816c9e 100644
--- a/data/mods/default/init.lua
+++ b/data/mods/default/init.lua
@@ -98,8 +98,9 @@ end
--
-- EnvRef is basically ServerEnvironment and ServerMap combined.
-- EnvRef methods:
--- - add_node(pos, content); pos={x=num, y=num, z=num}
--- TODO: content -> MapNode as described below
+-- - add_node(pos, node)
+-- - remove_node(pos)
+-- - get_node(pos)
--
-- ObjectRef is basically ServerActiveObject.
-- ObjectRef methods:
@@ -117,28 +118,11 @@ end
-- MapNode representation:
-- {name="name", param1=num, param2=num}
--
+-- Position representation:
+-- {x=num, y=num, z=num}
+--
-print("omg lol")
-print("minetest dump: "..dump(minetest))
-
--- Global environment step function
-function on_step(dtime)
- -- print("on_step")
-end
-
-minetest.register_globalstep(on_step)
-
-function on_placenode(p, node)
- print("on_placenode")
-end
-
-minetest.register_on_placenode(on_placenode)
-
-function on_dignode(p, node)
- print("on_dignode")
-end
-
-minetest.register_on_dignode(on_dignode)
+-- print("minetest dump: "..dump(minetest))
minetest.register_tool("WPick", {
image = "tool_woodpick.png",
@@ -626,10 +610,43 @@ minetest.register_craft({
}
})
+--
+-- Some common functions
+--
+
+function nodeupdate_single(p)
+ n = minetest.env:get_node(p)
+ if n.name == "sand" or n.name == "gravel" then
+ p_bottom = {x=p.x, y=p.y-1, z=p.z}
+ n_bottom = minetest.env:get_node(p_bottom)
+ if n_bottom.name == "air" then
+ minetest.env:remove_node(p)
+ minetest.env:add_luaentity(p, "falling_"..n.name)
+ nodeupdate(p)
+ end
+ end
+end
+
+function nodeupdate(p)
+ for x = -1,1 do
+ for y = -1,1 do
+ for z = -1,1 do
+ p2 = {x=p.x+x, y=p.y+y, z=p.z+z}
+ nodeupdate_single(p2)
+ end
+ end
+ end
+end
+
+--
+-- TNT (not functional)
+--
+
local TNT = {
+ -- Static definition
-- Maybe handle gravity and collision this way? dunno
- physical = true,
- weight = 5,
+ -- physical = true,
+ -- weight = 5,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "cube",
textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
@@ -638,7 +655,8 @@ local TNT = {
-- Initial value for our timer
timer = 0,
-- List names of state variables, for serializing object state
- state_variables = {"timer"},
+ -- (NOTE: not implemented and implementation will not be like this)
+ -- state_variables = {"timer"},
}
-- Called periodically
@@ -665,9 +683,106 @@ print("TNT dump: "..dump(TNT))
print("Registering TNT");
minetest.register_entity("TNT", TNT)
+--
+-- Falling stuff
+--
+
+function register_falling_node(nodename, texture)
+ minetest.register_entity("falling_"..nodename, {
+ -- Static definition
+ collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
+ visual = "cube",
+ textures = {texture,texture,texture,texture,texture,texture},
+ -- State
+ fallspeed = 0,
+ -- Methods
+ on_step = function(self, dtime)
+ -- Apply gravity manually
+ self.fallspeed = self.fallspeed + dtime * 5
+ fp = self.object:getpos()
+ fp.y = fp.y - self.fallspeed * dtime
+ self.object:moveto(fp, true)
+ -- Turn to actual sand when collides to ground or just move
+ bcp = {x=fp.x, y=fp.y-0.5, z=fp.z} -- Position of bottom center point
+ bcn = minetest.env:get_node(bcp)
+ if bcn.name ~= "air" then
+ -- Turn to a sand node
+ np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
+ minetest.env:add_node(np, {name=nodename})
+ self.object:remove()
+ else
+ -- Do nothing
+ end
+ end
+ })
+end
+
+register_falling_node("sand", "sand.png")
+register_falling_node("gravel", "gravel.png")
+
+--[[
+minetest.register_entity("falling_sand", {
+ -- Definition
+ collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
+ visual = "cube",
+ textures = {"sand.png","sand.png","sand.png","sand.png","sand.png","sand.png"},
+ -- State
+ fallspeed = 0,
+ -- Methods
+ on_step = function(self, dtime)
+ -- Apply gravity
+ self.fallspeed = self.fallspeed + dtime * 5
+ fp = self.object:getpos()
+ fp.y = fp.y - self.fallspeed * dtime
+ self.object:moveto(fp)
+ -- Turn to actual sand when collides to ground or just move
+ bcp = {x=fp.x, y=fp.y-0.5, z=fp.z} -- Position of bottom center point
+ bcn = minetest.env:get_node(bcp)
+ if bcn.name ~= "air" then
+ -- Turn to a sand node
+ np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
+ minetest.env:add_node(np, {name="sand"})
+ self.object:remove()
+ else
+ -- Do nothing
+ end
+ end
+})
+--]]
+
+--
+-- Global callbacks
+--
+
+-- Global environment step function
+function on_step(dtime)
+ -- print("on_step")
+end
+minetest.register_globalstep(on_step)
+
+function on_placenode(p, node)
+ print("on_placenode")
+ nodeupdate(p)
+end
+minetest.register_on_placenode(on_placenode)
+
+function on_dignode(p, node)
+ print("on_dignode")
+ nodeupdate(p)
+end
+minetest.register_on_dignode(on_dignode)
+
+--
+-- Done, print some random stuff
+--
+
print("minetest.registered_entities:")
dump2(minetest.registered_entities)
+--
+-- Some random pre-implementation planning and drafting
+--
+
--[[
function TNT:on_rightclick(clicker)
print("TNT:on_rightclick()")
@@ -677,7 +792,7 @@ function TNT:on_rightclick(clicker)
pos = self.object:getpos()
print("TNT:on_rightclick(): object position: "..dump(pos))
pos = {x=pos.x+0.5+1, y=pos.y+0.5, z=pos.z+0.5}
- --minetest.env:add_node(pos, 0)
+ --minetest.env:add_node(pos, {name="stone")
end
--]]
diff --git a/src/script.cpp b/src/script.cpp
index f58811090..16d8030d6 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -47,7 +47,9 @@ bool script_load(lua_State *L, const char *path)
int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
if(ret){
errorstream<<"Failed to load and run script from "<<path<<":"<<std::endl;
+ errorstream<<"[LUA] "<<std::endl;
errorstream<<"[LUA] "<<lua_tostring(L, -1)<<std::endl;
+ errorstream<<"[LUA] "<<std::endl;
lua_pop(L, 1); // Pop error message from stack
return false;
}
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index c9356fe4f..d25df18cb 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -126,18 +126,16 @@ public:
static v3f readFloatPos(lua_State *L, int index)
{
v3f pos;
- lua_pushvalue(L, index); // Push pos
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_getfield(L, -1, "x");
+ luaL_checktype(L, index, LUA_TTABLE);
+ lua_getfield(L, index, "x");
pos.X = lua_tonumber(L, -1);
lua_pop(L, 1);
- lua_getfield(L, -1, "y");
+ lua_getfield(L, index, "y");
pos.Y = lua_tonumber(L, -1);
lua_pop(L, 1);
- lua_getfield(L, -1, "z");
+ lua_getfield(L, index, "z");
pos.Z = lua_tonumber(L, -1);
lua_pop(L, 1);
- lua_pop(L, 1); // Pop pos
pos *= BS; // Scale to internal format
return pos;
}
@@ -153,6 +151,18 @@ static void pushpos(lua_State *L, v3s16 p)
lua_setfield(L, -2, "z");
}
+static v3s16 readpos(lua_State *L, int index)
+{
+ v3s16 p;
+ lua_getfield(L, index, "x");
+ p.X = lua_tonumber(L, -1);
+ lua_getfield(L, index, "y");
+ p.Y = lua_tonumber(L, -1);
+ lua_getfield(L, index, "z");
+ p.Z = lua_tonumber(L, -1);
+ return p;
+}
+
static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
{
lua_newtable(L);
@@ -169,11 +179,19 @@ static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
lua_getfield(L, index, "name");
const char *name = lua_tostring(L, -1);
lua_pop(L, 1);
+ u8 param1;
lua_getfield(L, index, "param1");
- u8 param1 = lua_tonumber(L, -1);
+ if(lua_isnil(L, -1))
+ param1 = 0;
+ else
+ param1 = lua_tonumber(L, -1);
lua_pop(L, 1);
+ u8 param2;
lua_getfield(L, index, "param2");
- u8 param2 = lua_tonumber(L, -1);
+ if(lua_isnil(L, -1))
+ param2 = 0;
+ else
+ param2 = lua_tonumber(L, -1);
lua_pop(L, 1);
return MapNode(ndef, name, param1, param2);
}
@@ -551,9 +569,8 @@ private:
// Exported functions
- // EnvRef:add_node(pos, content)
+ // EnvRef:add_node(pos, node)
// pos = {x=num, y=num, z=num}
- // content = number
static int l_add_node(lua_State *L)
{
infostream<<"EnvRef::l_add_node()"<<std::endl;
@@ -561,26 +578,61 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3s16 pos;
- lua_pushvalue(L, 2); // Push pos
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_getfield(L, -1, "x");
- pos.X = lua_tonumber(L, -1);
- lua_pop(L, 1);
- lua_getfield(L, -1, "y");
- pos.Y = lua_tonumber(L, -1);
- lua_pop(L, 1);
- lua_getfield(L, -1, "z");
- pos.Z = lua_tonumber(L, -1);
- lua_pop(L, 1);
- lua_pop(L, 1); // Pop pos
+ v3s16 pos = readpos(L, 2);
+ // content
+ MapNode n = readnode(L, 3, env->getGameDef()->ndef());
+ // Do it
+ env->getMap().addNodeWithEvent(pos, n);
+ return 0;
+ }
+
+ // EnvRef:remove_node(pos)
+ // pos = {x=num, y=num, z=num}
+ static int l_remove_node(lua_State *L)
+ {
+ infostream<<"EnvRef::l_remove_node()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->m_env;
+ if(env == NULL) return 0;
+ // pos
+ v3s16 pos = readpos(L, 2);
+ // Do it
+ env->getMap().removeNodeWithEvent(pos);
+ return 0;
+ }
+
+ // EnvRef:get_node(pos)
+ // pos = {x=num, y=num, z=num}
+ static int l_get_node(lua_State *L)
+ {
+ infostream<<"EnvRef::l_get_node()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->m_env;
+ if(env == NULL) return 0;
+ // pos
+ v3s16 pos = readpos(L, 2);
+ // Do it
+ MapNode n = env->getMap().getNodeNoEx(pos);
+ // Return node
+ pushnode(L, n, env->getGameDef()->ndef());
+ return 1;
+ }
+
+ // EnvRef:add_luaentity(pos, entityname)
+ // pos = {x=num, y=num, z=num}
+ static int l_add_luaentity(lua_State *L)
+ {
+ infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->m_env;
+ if(env == NULL) return 0;
+ // pos
+ v3f pos = readFloatPos(L, 2);
// content
- u16 content = 0;
- lua_pushvalue(L, 3); // Push content
- content = lua_tonumber(L, -1);
- lua_pop(L, 1); // Pop content
+ const char *name = lua_tostring(L, 3);
// Do it
- env->getMap().addNodeWithEvent(pos, MapNode(content));
+ ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
+ env->addActiveObject(obj);
return 0;
}
@@ -650,6 +702,9 @@ public:
const char EnvRef::className[] = "EnvRef";
const luaL_reg EnvRef::methods[] = {
method(EnvRef, add_node),
+ method(EnvRef, remove_node),
+ method(EnvRef, get_node),
+ method(EnvRef, add_luaentity),
{0,0}
};
@@ -1281,6 +1336,8 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
// State: object is at top of stack
// Get step function
lua_getfield(L, -1, "on_step");
+ if(lua_isnil(L, -1))
+ return;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
lua_pushnumber(L, dtime); // dtime
@@ -1304,6 +1361,8 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id,
// State: object is at top of stack
// Get function
lua_getfield(L, -1, "on_punch");
+ if(lua_isnil(L, -1))
+ return;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
objectref_get_or_create(L, puncher); // Clicker reference
@@ -1327,6 +1386,8 @@ void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
// State: object is at top of stack
// Get function
lua_getfield(L, -1, "on_rightclick");
+ if(lua_isnil(L, -1))
+ return;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
objectref_get_or_create(L, clicker); // Clicker reference