mirror of
https://github.com/Splizard/minetest-mod-snow.git
synced 2025-06-30 07:10:21 +02:00
Initial commit.
This commit is contained in:
440
init.lua
Normal file
440
init.lua
Normal file
@ -0,0 +1,440 @@
|
||||
--[[
|
||||
Snow Biomes
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
]]--
|
||||
|
||||
snow = {}
|
||||
dofile(minetest.get_modpath("snow").."/mapgen.lua")
|
||||
dofile(minetest.get_modpath("snow").."/config.lua")
|
||||
|
||||
function minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
local item = itemstack:peek_item()
|
||||
local def = itemstack:get_definition()
|
||||
if def.type == "node" and pointed_thing.type == "node" then
|
||||
local pos = pointed_thing.above
|
||||
|
||||
----------------
|
||||
--Snow stuff
|
||||
--Allows placing nodes "through" snow.
|
||||
----------------
|
||||
local node = pointed_thing.under
|
||||
if minetest.env:get_node(node).name == "snow:snow" then
|
||||
|
||||
--Gets rid of client-side placement block
|
||||
minetest.env:add_node(pos,{name="air"})
|
||||
|
||||
minetest.env:remove_node(node)
|
||||
pos=node
|
||||
end
|
||||
----------------
|
||||
|
||||
local oldnode = minetest.env:get_node(pos)
|
||||
local olddef = ItemStack({name=oldnode.name}):get_definition()
|
||||
|
||||
if not olddef.buildable_to then
|
||||
minetest.log("info", placer:get_player_name() .. " tried to place"
|
||||
.. " node in invalid position " .. minetest.pos_to_string(pos)
|
||||
.. ", replacing " .. oldnode.name)
|
||||
return
|
||||
end
|
||||
|
||||
minetest.log("action", placer:get_player_name() .. " places node "
|
||||
.. def.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
local newnode = {name = def.name, param1 = 0, param2 = 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.paramtype2 == 'wallmounted' then
|
||||
local under = pointed_thing.under
|
||||
local above = pointed_thing.above
|
||||
local dir = {x = under.x - above.x, y = under.y - above.y, z = under.z - above.z}
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif def.paramtype2 == 'facedir' then
|
||||
local playerpos = placer:getpos() or {x=0,y=0,z=0}
|
||||
local dir = {x = pos.x - playerpos.x, y = pos.y - playerpos.y, z = pos.z - playerpos.z}
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
minetest.log("action", "facedir: " .. newnode.param2)
|
||||
end
|
||||
|
||||
-- Add node and update
|
||||
minetest.env:add_node(pos, newnode)
|
||||
|
||||
-- Run callback
|
||||
if def.after_place_node then
|
||||
def.after_place_node(pos, placer)
|
||||
end
|
||||
|
||||
-- Run script hook (deprecated)
|
||||
local _, callback
|
||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||
callback(pos, newnode, placer)
|
||||
end
|
||||
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
--Replace leaves so snow gets removed on decay.
|
||||
minetest.register_node(":default:leaves", {
|
||||
description = "Leaves",
|
||||
drawtype = "allfaces_optional",
|
||||
visual_scale = 1.3,
|
||||
tiles = {"default_leaves.png"},
|
||||
paramtype = "light",
|
||||
groups = {snappy=3, leafdecay=3, flammable=2},
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
{
|
||||
-- player will get sapling with 1/20 chance
|
||||
items = {'default:sapling'},
|
||||
rarity = 20,
|
||||
},
|
||||
{
|
||||
-- player will get leaves only if he get no saplings,
|
||||
-- this is because max_items is 1
|
||||
items = {'default:leaves'},
|
||||
}
|
||||
}
|
||||
},
|
||||
--Remove snow above leaves after decay.
|
||||
after_destruct = function(pos, node, digger)
|
||||
pos.y = pos.y + 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "snow:snow" then
|
||||
minetest.env:remove_node(pos)
|
||||
end
|
||||
end,
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
--Snowballs
|
||||
-------------
|
||||
snowball_GRAVITY=9
|
||||
snowball_VELOCITY=19
|
||||
|
||||
--Shoot snowball.
|
||||
local snow_shoot_snowball=function (item, player, pointed_thing)
|
||||
local playerpos=player:getpos()
|
||||
local obj=minetest.env:add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, "snow:snowball_entity")
|
||||
local dir=player:get_look_dir()
|
||||
obj:setvelocity({x=dir.x*snowball_VELOCITY, y=dir.y*snowball_VELOCITY, z=dir.z*snowball_VELOCITY})
|
||||
obj:setacceleration({x=dir.x*-3, y=-snowball_GRAVITY, z=dir.z*-3})
|
||||
item:take_item()
|
||||
return item
|
||||
end
|
||||
|
||||
--The snowball Entity
|
||||
snow_snowball_ENTITY={
|
||||
physical = false,
|
||||
timer=0,
|
||||
textures = {"snow_snowball.png"},
|
||||
lastpos={},
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
}
|
||||
|
||||
--Snowball_entity.on_step()--> called when snowball is moving.
|
||||
snow_snowball_ENTITY.on_step = function(self, dtime)
|
||||
self.timer=self.timer+dtime
|
||||
local pos = self.object:getpos()
|
||||
local node = minetest.env:get_node(pos)
|
||||
|
||||
--Become item when hitting a node.
|
||||
if self.lastpos.x~=nil then --If there is no lastpos for some reason.
|
||||
if node.name ~= "air" then
|
||||
minetest.env:place_node(self.lastpos,{name="snow:snow"})
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
self.lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
|
||||
end
|
||||
|
||||
minetest.register_entity("snow:snowball_entity", snow_snowball_ENTITY)
|
||||
|
||||
--Snowball.
|
||||
minetest.register_craftitem("snow:snowball", {
|
||||
Description = "Snowball",
|
||||
inventory_image = "snow_snowball.png",
|
||||
on_use = snow_shoot_snowball,
|
||||
})
|
||||
|
||||
--Snow.
|
||||
minetest.register_node("snow:snow", {
|
||||
tiles = {"snow_snow.png"},
|
||||
drawtype = "nodebox",
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
param2 = nil,
|
||||
--param2 is reserved for what vegetation is hiding inside.
|
||||
--mapgen defines the vegetation.
|
||||
--1 = Moss
|
||||
groups = {crumbly=3,melts=3},
|
||||
buildable_to = true,
|
||||
drop = 'snow:snowball',
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}
|
||||
},
|
||||
},
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_gravel_footstep", gain=0.45},
|
||||
}),
|
||||
--Update dirt node underneath snow.
|
||||
after_destruct = function(pos, node, digger)
|
||||
if node.param2 == 1 then
|
||||
minetest.env:add_node(pos,{name="snow:moss",param2=1})
|
||||
end
|
||||
pos.y = pos.y - 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "snow:dirt_with_snow" then
|
||||
minetest.env:add_node(pos,{name="default:dirt_with_grass"})
|
||||
end
|
||||
end,
|
||||
on_construct = function(pos, newnode)
|
||||
pos.y = pos.y - 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "default:dirt_with_grass" then
|
||||
minetest.env:remove_node(pos)
|
||||
minetest.env:add_node(pos,{name="snow:dirt_with_snow"})
|
||||
elseif nodename == "air" then
|
||||
pos.y = pos.y + 1
|
||||
minetest.env:remove_node(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
--Snow with dirt.
|
||||
minetest.register_node("snow:dirt_with_snow", {
|
||||
description = "Dirt with Snow",
|
||||
tiles = {"snow_snow.png", "default_dirt.png", "default_dirt.png^snow_snow_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
drop = 'default:dirt',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.4},
|
||||
}),
|
||||
--Place snow above this node when placed.
|
||||
after_place_node = function(pos, newnode)
|
||||
pos.y = pos.y + 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "air" then
|
||||
minetest.env:add_node(pos,{name="snow:snow"})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
--Gets rid of snow when the node underneath is dug.
|
||||
local unsnowify = function(pos, node, digger)
|
||||
if node.name == "default:dry_shrub" then
|
||||
pos.y = pos.y - 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "snow:dirt_with_snow" then
|
||||
minetest.env:add_node(pos,{name="default:dirt_with_grass"})
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
local nodename = minetest.env:get_node(pos).name
|
||||
if nodename == "snow:snow" then
|
||||
minetest.env:remove_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_dignode(unsnowify)
|
||||
|
||||
--Snow block.
|
||||
minetest.register_node("snow:snow_block", {
|
||||
description = "Snow",
|
||||
tiles = {"snow_snow.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3,melts=2,falling_node=1},
|
||||
drop = 'snow:snow_block',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.4},
|
||||
}),
|
||||
})
|
||||
|
||||
--Ice.
|
||||
minetest.register_node("snow:ice", {
|
||||
description = "Ice",
|
||||
tiles = {"snow_ice.png"},
|
||||
is_ground_content = true,
|
||||
groups = {snappy=2,cracky=3,melts=1},
|
||||
drop = 'snow:ice',
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
sounds = default.node_sound_glass_defaults({
|
||||
footstep = {name="default_stone_footstep", gain=0.4},
|
||||
}),
|
||||
})
|
||||
|
||||
--Moss.
|
||||
minetest.register_node("snow:moss", {
|
||||
description = "Moss",
|
||||
tiles = {"snow_moss.png"},
|
||||
drawtype = "signlike",
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "wallmounted",
|
||||
},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'snow:snow_block',
|
||||
recipe = {
|
||||
{'snow:snowball', 'snow:snowball'},
|
||||
{'snow:snowball', 'snow:snowball'},
|
||||
},
|
||||
})
|
||||
|
||||
--Melting
|
||||
--Any node part of the group melting will melt when near warm nodes such as lava, fire, torches, etc.
|
||||
--The amount of water that replaces the node is defined by the number on the group:
|
||||
--1: one water_flowing
|
||||
--2: four water_flowings
|
||||
--3: one water_source
|
||||
minetest.register_abm({
|
||||
nodenames = {"group:melts"},
|
||||
neighbors = {"default:desert_sand", "group:igniter","default:torch","default:furnace_active","group:hot"},
|
||||
interval = 2,
|
||||
chance = 2,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local intensity = minetest.get_item_group(node.name,"melts")
|
||||
if intensity == 1 then
|
||||
minetest.env:add_node(pos,{name="default:water_source"})
|
||||
elseif intensity == 2 then
|
||||
local check_place = function(pos,node)
|
||||
if minetest.env:get_node(pos).name == "air" then
|
||||
minetest.env:place_node(pos,node)
|
||||
end
|
||||
end
|
||||
minetest.env:add_node(pos,{name="default:water_flowing"})
|
||||
check_place({x=pos.x+1,y=pos.y,z=pos.z},{name="default:water_flowing"})
|
||||
check_place({x=pos.x-1,y=pos.y,z=pos.z},{name="default:water_flowing"})
|
||||
check_place({x=pos.x,y=pos.y+1,z=pos.z},{name="default:water_flowing"})
|
||||
check_place({x=pos.x,y=pos.y-1,z=pos.z},{name="default:water_flowing"})
|
||||
elseif intensity == 3 then
|
||||
minetest.env:add_node(pos,{name="default:water_flowing"})
|
||||
end
|
||||
nodeupdate(pos)
|
||||
end,
|
||||
})
|
||||
|
||||
--Freezing
|
||||
--Water freezes when in contact with snow.
|
||||
minetest.register_abm({
|
||||
nodenames = {"default:water_source"},
|
||||
neighbors = {"snow:snow", "snow:snow_block"},
|
||||
interval = 20,
|
||||
chance = 4,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
minetest.env:add_node(pos,{name="snow:ice"})
|
||||
end,
|
||||
})
|
||||
|
||||
--Spread moss to cobble.
|
||||
minetest.register_abm({
|
||||
nodenames = {"default:cobble"},
|
||||
neighbors = {"snow:moss"},
|
||||
interval = 20,
|
||||
chance = 6,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
minetest.env:add_node(pos,{name="default:mossycobble"})
|
||||
end,
|
||||
})
|
||||
|
||||
if snow.enable_snowfall then
|
||||
|
||||
--Snowing (WIP)
|
||||
snow_fall=function (pos)
|
||||
local obj=minetest.env:add_entity(pos, "snow:fall_entity")
|
||||
obj:setvelocity({x=0, y=-1, z=0})
|
||||
end
|
||||
|
||||
-- The snowfall Entity
|
||||
snow_fall_ENTITY={
|
||||
physical = true,
|
||||
timer=0,
|
||||
textures = {"snow_snowfall.png"},
|
||||
lastpos={},
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
}
|
||||
|
||||
|
||||
-- snowfall_entity.on_step()--> called when snow is falling
|
||||
snow_fall_ENTITY.on_step = function(self, dtime)
|
||||
self.timer=self.timer+dtime
|
||||
local pos = self.object:getpos()
|
||||
local node = minetest.env:get_node(pos)
|
||||
|
||||
if self.object:getvelocity().y == 0 then
|
||||
minetest.env:place_node(self.lastpos,{name="snow:snow"})
|
||||
self.object:remove()
|
||||
end
|
||||
|
||||
self.lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
|
||||
end
|
||||
|
||||
minetest.register_entity("snow:fall_entity", snow_fall_ENTITY)
|
||||
|
||||
--Snowing abm
|
||||
minetest.register_abm({
|
||||
nodenames = {"default:dirt_with_grass"},
|
||||
interval = 30,
|
||||
chance = 50,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local env = minetest.env
|
||||
local perlin1 = env:get_perlin(112,3, 0.5, 150)
|
||||
local test = perlin1:get2d({x=pos.x, y=pos.z})
|
||||
if test > 0.53 then
|
||||
if pos.y >= -10 then
|
||||
if not env:find_node_near(pos, 10, "default:desert_sand") then
|
||||
local ground_y = nil
|
||||
for y=10,0,-1 do
|
||||
if env:get_node({x=pos.x,y=y,z=pos.z}).name ~= "air" then
|
||||
ground_y = y
|
||||
break
|
||||
end
|
||||
end
|
||||
if ground_y then
|
||||
local n = env:get_node({x=pos.x,y=ground_y,z=pos.z})
|
||||
if math.random(4) == 1 or (n.name ~= "snow:snow" and n.name ~= "snow:snow_block" and n.name ~= "snow:ice" and n.name ~= "default:water_source") then
|
||||
snow_fall({x=pos.x,y=ground_y+15,z=pos.z})
|
||||
if snow.debug then
|
||||
print("snowfall at x"..pos.x.." y"..pos.z)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
Reference in New Issue
Block a user