Falling sand and gravel

This commit is contained in:
Perttu Ahola 2011-11-17 16:21:17 +02:00
parent cc03718d3c
commit 1220b642eb
3 changed files with 233 additions and 55 deletions

@ -98,8 +98,9 @@ end
-- --
-- EnvRef is basically ServerEnvironment and ServerMap combined. -- EnvRef is basically ServerEnvironment and ServerMap combined.
-- EnvRef methods: -- EnvRef methods:
-- - add_node(pos, content); pos={x=num, y=num, z=num} -- - add_node(pos, node)
-- TODO: content -> MapNode as described below -- - remove_node(pos)
-- - get_node(pos)
-- --
-- ObjectRef is basically ServerActiveObject. -- ObjectRef is basically ServerActiveObject.
-- ObjectRef methods: -- ObjectRef methods:
@ -117,28 +118,11 @@ end
-- MapNode representation: -- MapNode representation:
-- {name="name", param1=num, param2=num} -- {name="name", param1=num, param2=num}
-- --
-- Position representation:
-- {x=num, y=num, z=num}
--
print("omg lol") -- print("minetest dump: "..dump(minetest))
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)
minetest.register_tool("WPick", { minetest.register_tool("WPick", {
image = "tool_woodpick.png", 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 = { local TNT = {
-- Static definition
-- Maybe handle gravity and collision this way? dunno -- Maybe handle gravity and collision this way? dunno
physical = true, -- physical = true,
weight = 5, -- weight = 5,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "cube", visual = "cube",
textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"}, 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 -- Initial value for our timer
timer = 0, timer = 0,
-- List names of state variables, for serializing object state -- 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 -- Called periodically
@ -665,9 +683,106 @@ print("TNT dump: "..dump(TNT))
print("Registering TNT"); print("Registering TNT");
minetest.register_entity("TNT", 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:") print("minetest.registered_entities:")
dump2(minetest.registered_entities) dump2(minetest.registered_entities)
--
-- Some random pre-implementation planning and drafting
--
--[[ --[[
function TNT:on_rightclick(clicker) function TNT:on_rightclick(clicker)
print("TNT:on_rightclick()") print("TNT:on_rightclick()")
@ -677,7 +792,7 @@ function TNT:on_rightclick(clicker)
pos = self.object:getpos() pos = self.object:getpos()
print("TNT:on_rightclick(): object position: "..dump(pos)) 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} 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 end
--]] --]]

@ -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); int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
if(ret){ if(ret){
errorstream<<"Failed to load and run script from "<<path<<":"<<std::endl; 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] "<<lua_tostring(L, -1)<<std::endl;
errorstream<<"[LUA] "<<std::endl;
lua_pop(L, 1); // Pop error message from stack lua_pop(L, 1); // Pop error message from stack
return false; return false;
} }

@ -126,18 +126,16 @@ public:
static v3f readFloatPos(lua_State *L, int index) static v3f readFloatPos(lua_State *L, int index)
{ {
v3f pos; v3f pos;
lua_pushvalue(L, index); // Push pos luaL_checktype(L, index, LUA_TTABLE);
luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, index, "x");
lua_getfield(L, -1, "x");
pos.X = lua_tonumber(L, -1); pos.X = lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
lua_getfield(L, -1, "y"); lua_getfield(L, index, "y");
pos.Y = lua_tonumber(L, -1); pos.Y = lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
lua_getfield(L, -1, "z"); lua_getfield(L, index, "z");
pos.Z = lua_tonumber(L, -1); pos.Z = lua_tonumber(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
lua_pop(L, 1); // Pop pos
pos *= BS; // Scale to internal format pos *= BS; // Scale to internal format
return pos; return pos;
} }
@ -153,6 +151,18 @@ static void pushpos(lua_State *L, v3s16 p)
lua_setfield(L, -2, "z"); 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) static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
{ {
lua_newtable(L); lua_newtable(L);
@ -169,11 +179,19 @@ static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef)
lua_getfield(L, index, "name"); lua_getfield(L, index, "name");
const char *name = lua_tostring(L, -1); const char *name = lua_tostring(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
u8 param1;
lua_getfield(L, index, "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); lua_pop(L, 1);
u8 param2;
lua_getfield(L, index, "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); lua_pop(L, 1);
return MapNode(ndef, name, param1, param2); return MapNode(ndef, name, param1, param2);
} }
@ -551,9 +569,8 @@ private:
// Exported functions // Exported functions
// EnvRef:add_node(pos, content) // EnvRef:add_node(pos, node)
// pos = {x=num, y=num, z=num} // pos = {x=num, y=num, z=num}
// content = number
static int l_add_node(lua_State *L) static int l_add_node(lua_State *L)
{ {
infostream<<"EnvRef::l_add_node()"<<std::endl; infostream<<"EnvRef::l_add_node()"<<std::endl;
@ -561,26 +578,61 @@ private:
ServerEnvironment *env = o->m_env; ServerEnvironment *env = o->m_env;
if(env == NULL) return 0; if(env == NULL) return 0;
// pos // pos
v3s16 pos; v3s16 pos = readpos(L, 2);
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
// content // content
u16 content = 0; MapNode n = readnode(L, 3, env->getGameDef()->ndef());
lua_pushvalue(L, 3); // Push content
content = lua_tonumber(L, -1);
lua_pop(L, 1); // Pop content
// Do it // Do it
env->getMap().addNodeWithEvent(pos, MapNode(content)); 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
const char *name = lua_tostring(L, 3);
// Do it
ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, "");
env->addActiveObject(obj);
return 0; return 0;
} }
@ -650,6 +702,9 @@ public:
const char EnvRef::className[] = "EnvRef"; const char EnvRef::className[] = "EnvRef";
const luaL_reg EnvRef::methods[] = { const luaL_reg EnvRef::methods[] = {
method(EnvRef, add_node), method(EnvRef, add_node),
method(EnvRef, remove_node),
method(EnvRef, get_node),
method(EnvRef, add_luaentity),
{0,0} {0,0}
}; };
@ -1281,6 +1336,8 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
// State: object is at top of stack // State: object is at top of stack
// Get step function // Get step function
lua_getfield(L, -1, "on_step"); lua_getfield(L, -1, "on_step");
if(lua_isnil(L, -1))
return;
luaL_checktype(L, -1, LUA_TFUNCTION); luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self lua_pushvalue(L, object); // self
lua_pushnumber(L, dtime); // dtime 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 // State: object is at top of stack
// Get function // Get function
lua_getfield(L, -1, "on_punch"); lua_getfield(L, -1, "on_punch");
if(lua_isnil(L, -1))
return;
luaL_checktype(L, -1, LUA_TFUNCTION); luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self lua_pushvalue(L, object); // self
objectref_get_or_create(L, puncher); // Clicker reference 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 // State: object is at top of stack
// Get function // Get function
lua_getfield(L, -1, "on_rightclick"); lua_getfield(L, -1, "on_rightclick");
if(lua_isnil(L, -1))
return;
luaL_checktype(L, -1, LUA_TFUNCTION); luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self lua_pushvalue(L, object); // self
objectref_get_or_create(L, clicker); // Clicker reference objectref_get_or_create(L, clicker); // Clicker reference