added autumn leaves; made the whole functionaly more versatile and less dependent on snow as such

This commit is contained in:
Sokomine 2014-07-23 23:41:06 +02:00
parent b24ed824b2
commit 1a874f3ac8
4 changed files with 300 additions and 166 deletions

View File

@ -1,16 +1,28 @@
moresnow = {}
--------------------------------------------------------------------------------
-- Configuration
--------------------------------------------------------------------------------
-- if set to true, fallen autum leaves will be supported just like snow
-- The txture and idea for them came from LazyJ.
moresnow.enable_autumnleaves = true
-- the snow cannon allows to create snow
moresnow.enable_snow_cannon = true
-- with this set, the snow cannon can *shoot* snowballs - which will fly a long way;
-- on servers, set this to false
moresnow.crazy_mode = true
-- end of configuration
--------------------------------------------------------------------------------
-- defines the on_construct function for falling/placed snow(balls)
dofile(minetest.get_modpath("moresnow")..'/snow_on_construct.lua');
-- devines the 8 types of snow covers: general nodebox snow cover, stairs, slabs,
-- outer edge stair, inner edge stair, 3x homedecor shingles/technic cnc shapes
dofile(minetest.get_modpath("moresnow")..'/snow_cover_nodes.lua');
-- which snow node equivals which leaves node?
moresnow.nodetypes = {'snow','autumnleaves'};
moresnow.build_translation_table();
-- some defines which fascilitate identification of nodes
moresnow.c_ignore = minetest.get_content_id( 'ignore' );
@ -29,8 +41,7 @@ moresnow.c_snow_ramp_inner = minetest.get_content_id( 'moresnow:snow_ramp_inner
-- this is important for finding the right snow cover to put on the shape below
dofile(minetest.get_modpath("moresnow")..'/snow_analyze_shapes.lua');
-- a snow cannon that shoots snow around
dofile(minetest.get_modpath("moresnow")..'/snow_cannon.lua');
if( moresnow.enable_snow_cannon ) then
dofile(minetest.get_modpath("moresnow")..'/snow_cannon.lua');
end
-- TODO: make the autumnleaves from LazyJ working
-- TODO: add a function to use this with voxelmanip

View File

@ -149,6 +149,10 @@ moresnow.snow_cannon_update_formspec = function( meta, is_active )
else
start = 'start';
end
local button_crazy = '';
if( moresnow.crazy_mode ) then
button_crazy = "button_exit[6.5,1.5;2,0.5;crazy;crazy]";
end
meta:set_string( 'formspec',
"size[10.5,8]"..
( default.gui_bg or '')..
@ -160,7 +164,7 @@ moresnow.snow_cannon_update_formspec = function( meta, is_active )
"button_exit[6.5,0;2,0.5;"..start..";"..start.."]"..
"button_exit[6.5,0.5;2,0.5;ordered;ordered]"..
"button_exit[6.5,1.0;2,0.5;random;random]"..
"button_exit[6.5,1.5;2,0.5;crazy;crazy]"..
button_crazy..
"label[0,2;Water reservoir:]"..
"label[2,2;Fill up with water buckets or ice blocks.]"..
"list[current_name;buckets;0,2.5;10,1;]"..

View File

@ -2,10 +2,9 @@
-- the general node definition for all these snow tops (only name and nodebox vary)
moresnow.register_snow_top = function( node_name, fixed_nodebox )
minetest.register_node( node_name, {
minetest.register_node( 'moresnow:snow_'..node_name, {
description = "Snow",
tiles = {"default_snow.png"},
-- tiles = {"moreautumn.png"},
inventory_image = "default_snowball.png",
wield_image = "default_snowball.png",
is_ground_content = true,
@ -25,24 +24,87 @@ moresnow.register_snow_top = function( node_name, fixed_nodebox )
footstep = {name="default_snow_footstep", gain=0.25},
dug = {name="default_snow_footstep", gain=0.75},
}),
on_construct = moresnow.on_construct,
on_construct = function( pos )
return moresnow.on_construct_snow( pos, 'moresnow:snow_'..node_name );
end,
})
if( moresnow.enable_autumnleaves ) then
minetest.register_node( 'moresnow:autumnleaves_'..node_name, {
description = "fallen leaves",
tiles = {"moreautumn.png"},
inventory_image = "moreautumn.png",
wield_image = "moreautumn.png",
is_ground_content = true,
paramtype = "light",
paramtype2 = "facedir",
buildable_to = true,
drawtype = "nodebox",
node_box = {
-- leveled would not work well in this situation
type = "fixed",
fixed = fixed_nodebox,
},
drop = "moresnow:autumnleaves",
groups = {falling_node=1, float=1, not_in_creative_inventory=1, snappy=3, flammable=2, leaves=1, not_in_creative_inventory=1},
sounds = default.node_sound_leaves_defaults(),
on_construct = function( pos )
return moresnow.on_construct_leaves( pos, 'moresnow:autumnleaves_'..node_name );
end,
})
end
end
-- define the leaves
if( moresnow.enable_autumnleaves ) then
minetest.register_node( "moresnow:autumnleaves", {
description = "fallen leaves",
tiles = {"moreautumn.png"},
inventory_image = "moreautumn.png",
wield_image = "moreautumn.png",
is_ground_content = true,
paramtype = "light",
-- drawtype = "allfaces_optional",
waving = 1,
buildable_to = true,
leveled = 7, -- can pile up as well
drawtype = "nodebox",
node_box = {
type = "leveled",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -0.5+2/16, 0.5},
},
},
groups = {falling_node=1, float=1, snappy=3, flammable=2, leaves=1},
sounds = default.node_sound_leaves_defaults(),
on_construct = function( pos )
return moresnow.on_construct_leaves( pos, 'moresnow:autumnleaves' );
end,
})
end
-- now that on_construct has been defined, we can start creating the actual nodes
minetest.registered_nodes[ 'default:snow' ].on_construct = moresnow.on_construct;
minetest.registered_nodes[ 'default:snow' ].on_construct = function( pos )
return moresnow.on_construct_snow( pos, 'default:snow' );
end
-- the nodebox for this snow node lies one node DEEPER than the node the snow is in;
-- thus, nodebox-like nodes covered by snow may look less strange
moresnow.register_snow_top( "moresnow:snow_top", {{-0.5, -1.5, -0.5, 0.5, -1.5+2/16, 0.5}} );
moresnow.register_snow_top( "moresnow:snow_stair_top", {
moresnow.register_snow_top( "top", {{-0.5, -1.5, -0.5, 0.5, -1.5+2/16, 0.5}} );
moresnow.register_snow_top( "stair_top", {
{-0.5, -1.0, -0.5, 0.5, -1.0+2/16, 0},
{-0.5, -0.5, 0, 0.5, -0.5+2/16, 0.5},
{-0.5, -1.0+2/16, 0-1/32, 0.5, -0.5, 0 },
{-0.5, -1.5, -0.5-1/32, 0.5, -1.0, -0.5},
});
moresnow.register_snow_top( "moresnow:snow_slab_top", { {-0.5, -1.0, -0.5, 0.5, -1.0+2/16, 0.5}});
moresnow.register_snow_top( "moresnow:snow_outer_stair_top", {
moresnow.register_snow_top( "slab_top", { {-0.5, -1.0, -0.5, 0.5, -1.0+2/16, 0.5}});
-- these shapes exist in moreblocks only
if( minetest.get_modpath( 'moreblocks' )) then
moresnow.register_snow_top( "outer_stair_top", {
{-0.5, -1.0, -0.5, 0, -1.0+2/16, 0 },
{-0.5, -0.5, 0, 0, -0.5+2/16, 0.5},
{ 0, -1.0, -0.5, 0.5, -1.0+2/16, 0.5},
@ -53,7 +115,7 @@ moresnow.register_snow_top( "moresnow:snow_outer_stair_top", {
{0, -1.0+2/16, 0, 0+1/32, -0.5, 0.5},
{0.5, -1.5, -0.5, 0.5+1/32, -1.0, 0.5},
});
moresnow.register_snow_top( "moresnow:snow_inner_stair_top", {
moresnow.register_snow_top( "inner_stair_top", {
{ 0, -1.0, -0.5, 0.5, -1.0+2/16, 0 },
{ 0, -0.5, 0, 0.5, -0.5+2/16, 0.5},
@ -62,6 +124,7 @@ moresnow.register_snow_top( "moresnow:snow_inner_stair_top", {
{ 0, -1.0+2/16, 0-1/32, 0.5, -0.5, 0 },
{ 0, -1.0+2/16, -0.5, 0+1/32, -0.5, 0},
});
end
moresnow.register_shape = function( shape, new_name )
@ -99,8 +162,8 @@ end
-- only add these if either technic (with its cnc machine) or homedecor (with shingles) are installed
if( minetest.get_modpath( 'homedecor' )
or minetest.get_modpath( 'technic' )) then
moresnow.register_shape( 1, 'moresnow:snow_ramp_top' );
moresnow.register_shape( 2, 'moresnow:snow_ramp_outer_top');
moresnow.register_shape( 3, 'moresnow:snow_ramp_inner_top');
moresnow.register_shape( 1, 'ramp_top' );
moresnow.register_shape( 2, 'ramp_outer_top');
moresnow.register_shape( 3, 'ramp_inner_top');
end

View File

@ -1,161 +1,217 @@
moresnow.on_construct = function( pos )
local posb = {x=pos.x, y=pos.y-1, z=pos.z};
local node = minetest.get_node( posb );
if( node and node.name and minetest.registered_nodes[ node.name ] ) then
local suggested = moresnow.snow_cover[ minetest.get_content_id( node.name )];
-- if it is some solid node, keep the snow cover
if( not( suggested )) then
-- change the node below if it's some kind of dirt
if( node.name == 'default:dirt_with_grass' or node.name == 'default:dirt' ) then
minetest.set_node( posb, {name="default:dirt_with_snow"});
end
return;
end
moresnow.translation_table = {}
suggested = minetest.get_name_from_content_id( suggested );
moresnow.build_translation_table = function()
local shapes = {'top', 'stair_top', 'slab_top',
'outer_stair_top', 'inner_stair_top',
'ramp_top', 'ramp_outer_top', 'ramp_inner_top' };
-- no rule for this node
if( not( suggested )) then
return;
end
for _,t in ipairs(moresnow.nodetypes) do
local p2 = node.param2;
-- homedecor and technic have diffrent ideas about param2...
local p2o = moresnow.snow_param2_offset[ minetest.get_content_id( node.name )];
if( p2o ) then
p2 = (p2 + p2o ) % 4;
end
moresnow.translation_table[ t ] = {};
-- if this is a stair or a roof node from homedecor or technics cnc machine;
-- those nodes are all comparable regarding rotation
if( suggested == 'moresnow:snow_stair_top' or suggested == 'moresnow:snow_ramp_top' ) then
if( p2==5 or p2==7 or p2==9 or p2==11 or p2==12 or p2==14 or p2==16 or p2==18 ) then
suggested = 'moresnow:snow_top';
-- stair turned upside down
elseif( p2==6 or p2==8 or p2==15 or p2==17 or p2==20 or p2==21 or p2==22 or p2==23) then
suggested = 'default:snow';
-- all these transform into stairs; however, adding the offset (our snow node lies lower than a normal node) would cause chaos
elseif( p2 ==19) then
p2 = 1;
elseif( p2 ==4 ) then
p2 = 2;
elseif( p2 ==13) then
p2 = 3;
elseif( p2 ==10) then
p2 = 0;
-- else it really is a stiar
end
elseif( suggested == 'moresnow:snow_slab_top' ) then
-- vertical slab; tread as a nodebox
if( p2 >= 4 and p2 <= 19 ) then
suggested = 'moresnow:snow_top';
-- slab turned upside down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = 'default:snow';
-- else it's a slab
end
elseif( suggested == 'moresnow:snow_ramp_outer_top' ) then
-- treat like a nodebox
if( p2>=4 and p2 <= 19 ) then
suggested = 'moresnow:snow_top';
-- upside-down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = 'default:snow';
end
elseif( suggested == 'moresnow:snow_ramp_inner_top' ) then
-- treat like a nodebox
if( p2>=4 and p2 <= 19 ) then
suggested = 'moresnow:snow_top';
-- upside-down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = 'default:snow';
for _,v in ipairs( shapes ) do
local id1 = minetest.get_content_id( 'moresnow:snow_'..v );
local id2 = minetest.get_content_id( 'moresnow:'..t..'_'..v );
if( id1 ) then
moresnow.translation_table[ t ][ id1 ] = id2;
end
end
-- snow_top is a special node suitable for nodeboxes; BUT: it only looks acceptable if the
-- node below that nodebox/torch/fence/etc is a solid one
if( suggested == 'moresnow:snow_top' ) then
local node2 = minetest.get_node( {x=pos.x, y=pos.y-2, z=pos.z});
if( node2 and node2.name and node2.name == 'default:snow' ) then
if( node2.param2 and node2.param2+8 >= 64 ) then
minetest.set_node( {x=pos.y,y=pos.y-2, z=pos.z}, { name = 'default:snowblock' } );
return;
else
if( not( node2.param2 )) then
node2.param2 = 8;
end
minetest.set_node( {x=pos.x,y=pos.y-2, z=pos.z}, { name = 'default:snow', param2 = (node2.param2+8) } );
minetest.remove_node( pos );
return;
end
end
-- no information about the node below available - we don't know what to do
if( not( node2 ) or node2.name == 'air' or node2.name == 'ignore' ) then
-- in such a case it helps to drop the snow and let it fall until it hits something
if( node2 and node2.name == 'air' ) then
minetest.remove_node( pos );
spawn_falling_node( {x=pos.x, y=pos.y-2, z=pos.z}, {name="default:snow"})
-- else we did not find a sane place for this snow; give up and remove the snow
else
minetest.remove_node( pos );
end
return;
end
local suggested2 = moresnow.snow_cover[ minetest.get_content_id( node2.name )];
-- give up
if( not( suggested2 )) then
minetest.remove_node( pos );
return;
end
suggested2 = minetest.get_name_from_content_id( suggested2 );
-- if the node below this one can't handle a normal snow cover, we can't put a snow top on our node either
if( suggested2 ~= 'default:snow' ) then
minetest.remove_node( pos );
return;
end
end
if( suggested ) then
local old = minetest.get_node( pos );
if( suggested == 'default:snow' ) then
-- if there is snow already, make it higher
if( old and old.name and old.name == suggested ) then
if( old.param2 and old.param2 + 8 >= 64 ) then
minetest.set_node( pos, { name = 'default:snowblock' } );
-- we are done - the next snow will land on the surface of the snowblock below
return;
--[[
local above = minetest.get_node( {x=pos.x, y=pos.y+1, z=pos.z} );
if( above and above.name and above.name == 'air' ) then
minetest.set_node( {x=pos.x, y=pos.y+1, z=pos.z}, { name = 'default:snow', param2 = 8 } );
return;
end
--]]
elseif( not( old.param2 ) or old.param2 < 1 ) then
p2 = 8;
else
p2 = old.param2 + 1;
end
-- prevent the snow from getting higher
else
p2 = 0;
end
end
if( old and old.name and (old.name ~= suggested or ( old.param2 and old.param2 ~= p2))) then
-- swap_node does not seem to affect param2
minetest.swap_node( pos, { name = suggested, param2 = p2} );
end
local id1 = minetest.get_content_id( 'default:snow' );
local id2 = minetest.get_content_id( 'moresnow:'..t );
if( id1 ) then
moresnow.translation_table[ t ][ id1 ] = id2;
end
end
end
moresnow.on_construct_snow = function( pos, falling_node_name )
if( not( falling_node_name )) then
falling_node_name = 'default:snow';
end
local res = moresnow.on_construct( pos, falling_node_name, 'default:snow', 'snow' );
if( res ) then
minetest.swap_node( pos, res );
end
end
moresnow.on_construct_leaves = function( pos, falling_node_name )
-- TODO: translate the result to the leaves nodes
if( not( falling_node_name )) then
falling_node_name = 'moresnow:autumnleaves';
end
local res = moresnow.on_construct( pos, falling_node_name, 'moresnow:autumnleaves', 'autumnleaves' );
if( res ) then
minetest.swap_node( pos, res );
end
end
-- this function works with content ids because we want it to call for falling
-- snow nodes AND from mapgen (where content ids are at hand)
moresnow.suggest_snow_type = function( node_content_id, p2 )
local suggested = moresnow.snow_cover[ node_content_id ];
-- if it is some solid node, keep the snow cover
if( node_content_id == moresnow.c_snow or not( suggested ) or suggested == moresnow.c_ignore or suggested == moresnow.c_air) then
return { new_id = moresnow.c_snow, param2 = 0 };
end
if( not( p2 )) then
p2 = 0;
end
-- homedecor and technic have diffrent ideas about param2...
local p2o = moresnow.snow_param2_offset[ node_content_id ];
if( p2o ) then
p2 = (p2 + p2o ) % 4;
end
-- if this is a stair or a roof node from homedecor or technics cnc machine;
-- those nodes are all comparable regarding rotation
if( suggested == moresnow.c_snow_stair
or suggested == moresnow.c_snow_ramp_top ) then
if( p2==5 or p2==7 or p2==9 or p2==11 or p2==12 or p2==14 or p2==16 or p2==18 ) then
suggested = moresnow.c_snow_top;
-- stair turned upside down
elseif( p2==6 or p2==8 or p2==15 or p2==17 or p2==20 or p2==21 or p2==22 or p2==23) then
suggested = moresnow.c_snow;
-- all these transform into stairs; however, adding the offset (our snow node lies lower than a normal node) would cause chaos
elseif( p2 ==19) then
p2 = 1;
elseif( p2 ==4 ) then
p2 = 2;
elseif( p2 ==13) then
p2 = 3;
elseif( p2 ==10) then
p2 = 0;
-- else it really is a stiar
end
elseif( suggested == moresnow.c_snow_slab ) then
-- vertical slab; tread as a nodebox
if( p2 >= 4 and p2 <= 19 ) then
suggested = moresnow.c_snow_top;
-- slab turned upside down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = moresnow.c_snow;
-- else it's a slab
end
elseif( suggested == moresnow.c_snow_ramp_outer ) then
-- treat like a nodebox
if( p2>=4 and p2 <= 19 ) then
suggested = moresnow.c_snow_top;
-- upside-down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = moresnow.c_snow;
end
elseif( suggested == moresnow.c_snow_ramp_inner ) then
-- treat like a nodebox
if( p2>=4 and p2 <= 19 ) then
suggested = moresnow.c_snow_top;
-- upside-down
elseif( p2 >= 20 and p2 <= 23 ) then
suggested = moresnow.c_snow;
end
end
return { new_id = suggested, param2 = p2 };
end
-- default_name is the name of the node that would be placed in case of a solid underground
-- (usually default:snow)
moresnow.on_construct_select_shape = function( pos, falling_node_name, default_name )
-- get the node one below
local node1 = minetest.get_node( {x=pos.x, y=pos.y-1, z=pos.z});
-- no information about that node available; give up
if( not(node1) or not(node1.name) or not(minetest.registered_nodes[ node1.name ] )) then
return;
end
local res = moresnow.suggest_snow_type( minetest.get_content_id( node1.name ), node1.param2 );
-- snow_top is a special node suitable for nodeboxes; BUT: it only looks acceptable if the
-- node below that nodebox/torch/fence/etc is a solid one
if( res.new_id == moresnow.c_snow_top ) then
-- get the node below the node below
local node2 = minetest.get_node( {x=pos.x, y=pos.y-2, z=pos.z});
if( node2 and node2.name and node2.name == default_name ) then
return;
end
-- no information about the node below available - we don't know what to do
if( not( node2 ) or node2.name == 'air' or node2.name == 'ignore' ) then
-- in such a case it helps to drop the snow and let it fall until it hits something
if( node2 and node2.name == 'air' ) then
-- let the snow continue to fall
spawn_falling_node( {x=pos.x, y=pos.y-2, z=pos.z}, {name= default_name})
end
return { remove_node = true};
end
local new_id2 = moresnow.snow_cover[ minetest.get_content_id( node2.name )];
-- if the node below this one can't handle a normal snow cover, we can't put a snow top on our node either
if( not( new_id2 ) or new_id2 ~= moresnow.c_snow) then
return { remove_node = true};
end
-- else continue with c_snow_top
end
return res;
end
-- we need to make sure not to replace the node with the same content
moresnow.on_construct = function( pos, falling_node_name, default_name, node_type )
-- get the node we're talking about
local node0 = minetest.get_node( pos );
local res = moresnow.on_construct_select_shape( pos, falling_node_name, default_name );
if( res and res.remove_node ) then
-- check if we're removing the right node
if( node0 and node0.name and node0.name == falling_node_name) then
minetest.remove_node( pos );
end
return; -- we're finished
end
if( not( res ) ) then
-- will be handled by the engine
if( falling_node_name == default_name ) then
return;
-- the falling node was not default:snow (or an aequivalent); but we need default:snow here
elseif( node0 and node0.name and node0.name ~= default_name) then
return { name = default_name, param2 = 0 };
-- fallback
else
return;
end
end
if( node_type and moresnow.translation_table[ node_type ] ) then
res.new_id = moresnow.translation_table[ node_type ][ res.new_id ];
if( not( res.new_id )) then
return;
end
end
local suggested = minetest.get_name_from_content_id( res.new_id );
if( node0 and node0.name and (node0.name ~= suggested or ( suggested ~= default_name and node0.param2 and node0.param2 ~= res.param2))) then
return { name = suggested, param2 = res.param2};
end
end