Compare commits

...

46 Commits

Author SHA1 Message Date
sofar d6a66860af Prevent divide by zero (#2106)
This forces all explosions to damage entities within the 1 node
range. If that needs to be disabled, the damage_radius needs to
be set to 0.
2018-05-18 12:50:47 +02:00
paramat 6d850f23a5 Flower spread ABM: Optimise
Match maximum spread density to maximum mapgen density for flowers.
Place 3 flora nodes at once instead of 1.
Change ABM chance value to 300 to match previous spread rate.
ABM becomes 3 times less intensive.
2018-05-18 12:50:47 +02:00
paramat 2c1af0861f Doors: Avoid crash on nil player in 'can dig door' 2018-05-18 12:50:47 +02:00
Jat15 d2ae721235 Stairs: unbind table groups (#2036)
Unbind table groups for base block, stairs, slabs.
2018-05-18 12:50:18 +02:00
paramat 01db55cee5 default:dirt_with_snow: Re-add to soil group
Previously, saplings were not growing if the dirt they are on turned to
'dirt with snow' before growth.
Also for consistency with other dirt nodes.
2018-05-06 20:44:30 +02:00
Ekdohibs 4ba2b5179e Furnace: Fix being able to cook items without enough fuel
This was triggered when too much time had elapsed when timer was called.
Also, fix timer resolution giving free fuel time.
2018-05-06 20:44:30 +02:00
Diego Martínez a5092c0df6 creative: Add missing tooltips. 2018-05-06 20:44:30 +02:00
paramat 575c098bae Book textures: Reset colour profiles to remove warnings 2018-05-06 20:44:22 +02:00
paramat cddd59b578 Book textures: Replace with more original textures 2018-05-06 20:40:45 +02:00
ezhh 7a4b1e0ce1 Default: Make burntimes more rational and consistent 2017-12-05 21:24:02 +01:00
DTA7 0216fa08ec Add nil checks for placer 2017-11-19 23:03:38 +01:00
raymoo ca3e807d35 Creative: Make the placenode registration check for non-player placers 2017-11-19 23:03:38 +01:00
raymoo ca38bb2390 Creative: Make handle_node_drops override work for non-player diggers 2017-11-19 23:03:38 +01:00
Coder12a 7d07c52d09 Books: Convert \r to \n
Some files or editors may use \r instand of \n like notepad++. If you copy
text written in notepad++ and pasted into the book. The book will only have
one page.
2017-11-19 23:03:38 +01:00
SmallJoker 532013a032 Creative: Cache inventory items on load 2017-11-19 23:03:38 +01:00
tenplus1 a52622669f TNT: Add tnt.boom defaults
This adds def, def.radius and def.damage_radius defaults to the
tnt.boom() function if they aren't specified on call.
2017-11-19 23:03:38 +01:00
SmallJoker ce5e668681 Bones: Return bones when taking the last ItemStack 2017-11-19 23:03:38 +01:00
tenplus1 6530fa914b Flowers: Add waterlily right-click checks
Check for on_rightclick functions of nodes when holding a waterlily.
2017-11-19 23:03:38 +01:00
rubenwardy 86eb0e1617 Sfinv: Remove possibility of infinite loop when homepage doesn't exist 2017-11-19 23:03:38 +01:00
rubenwardy 93fb9b36ce Sfinv: Rename navigation tabs to reduce chance of a conflict 2017-11-19 23:03:38 +01:00
danielmeek32 09e3505ea1 Chests: Fix locked chest protection against explosions (#1886)
Fixes #1885
2017-11-19 23:03:38 +01:00
tenplus1 cecbfc1676 Chests: Fix open chest after player leave (#1884)
This should fix the chest staying open when a player disconnects while inside.
2017-11-19 23:03:38 +01:00
tenplus1 fba6f6a4cf TNT: Add explode_center flag
Add 'explode_centre' flag which when false explodes as normal and when true runs on_blast on centre node as well as dropping items.
2017-11-19 23:03:38 +01:00
tenplus1 6053456af1 Mushroom spread: Optimise and make overridable
Move mushroom spread ABM action into a global and overridable function.
Optimise spread code.
Reduce spread range to reduce spread through walls.
2017-11-19 23:03:38 +01:00
Hybrid Dog cc2f75b2f9 Register fence: Allow setting nodedefs to 'false' 2017-11-19 23:03:38 +01:00
tenplus1 b6ef71c92e TNT's tnt:boom cleanup (#1868)
The tnt:boom node doesn't actually need the on_construct and on_timer functions to remove the node after 0.4 seconds as the tnt_explode function already does this beforehand.
2017-11-19 23:03:38 +01:00
SmallJoker 876da2fbc6 Beds: Do not crash when placing in an unknown node 2017-11-19 23:03:38 +01:00
paramat ea45ca57a5 Lava cooling: Increase interval to 2
An excessive load has been reported caused by the node searching, so even
when no lava is present.
2017-11-19 23:03:34 +01:00
SmallJoker 6fa3ebfa75 Carts: Check for last pathfinder predition too Minor fix to reduce cart jitter slightly 2017-11-19 22:57:28 +01:00
SmallJoker efe6fb6dfb TNT: Only burn visually connected powder (#1857) 2017-11-19 22:57:28 +01:00
SmallJoker 1aeb2baa91 Creative: Prevent unauthorized item access (#1840) 2017-11-19 22:57:28 +01:00
Ezhh e4d6425846 Correct farming/stairs dependency (#1838) 2017-11-19 22:57:28 +01:00
Paramat 81f885795d Crafting: Remove duplicate reversed recipes (#1777)
For axes and hoes only use one recipe that matches the appearance of the texture and in inventory.
2017-11-19 22:53:53 +01:00
paramat f3e29bc2cc Saplings: Reduce grow time to ABM equivalent
Previous times were chosen using statistical maths, but reports suggested
this was too long.
I tested by timing an ABM acting on 100 nodes, with interval and chance equal
to the old sapling ABM.
50 at 4m59s.
99 at 24m58s.
100 at 26m58s.
So choose a grow time between 5 and 25 min for tree and bush saplings.
If 'can grow' is false at grow time the timer is reset to 5 min.
2017-11-19 22:53:53 +01:00
DS-Minetest 3a72f7b84b Add backface_culling to open chests and fencegates 2017-11-19 22:53:53 +01:00
Foz 20bd4560f8 TNT: Track TNT owner in metadata for protection mods
It is useful for protection mods to know who owns an exploding
TNT block. This allows the blocks destroyed by the TNT to be
limited to the same ones the owner could destroy without using
TNT.

TNT placed within a protected area by the area owner, and later
ignited by another player will destroy within the protected area
nodes the igniter may not otherwise be able to interact with. Any
player could significantly increase the size of an explosion by
placing more TNT in an adjacent unprotected area if the original
TNT block was placed withing 1 node of such a boundary. This
feature sounds dangerous, but we are talking about TNT. Players
should use it carefully.
2017-11-19 22:53:53 +01:00
SmallJoker 8991b9fe54 Carts: Do not connect rails with gunpowder (#1812) 2017-11-19 22:53:53 +01:00
Johannes Fritz aea6c5dd1d Stairs: Add backface culling to stair meshes
If backface culling is not specified for a tile in 'images' it is set to true.
Slabs already have backface culling due to being defined as nodeboxes (which
are then converted to meshnodes).
2017-11-19 22:53:53 +01:00
paramat da41caca66 Chests: Check 'def' of node above chest to avoid crash
In 'chest_lid_obstructed(pos)' check for nil 'def' to avoid a crash caused by
an unknown node above the chest.
2017-11-19 22:53:14 +01:00
red-001 103af98864 Books: Also limit the max size of the title
This limits the max size of the full title of the book to `80` letters and
the size of the part thats displayed in the tooltip to `35` letters.
2017-11-19 22:53:14 +01:00
red-001 26606b0520 Books: Limit the size of books
Really large books just waste hard drive space and the engine is not designed to
handle that much data in item metadata, this can cause strange things to happen.
2017-11-19 22:52:00 +01:00
red-001 706844e8bf Books: Add nil value checks to the book formspec handler 2017-11-19 22:52:00 +01:00
paramat a56274c230 Stairs: Use one recipe matching inventory appearence
No longer have 2 recipes for stairs, choose the one that matches the appearence
in inventory (stair rising toward the right).
Helps to reduce recipe count now that an increasing number of stairs are
being registered.
2017-11-19 22:52:00 +01:00
vorunbekannt75@web.de 3512226867 Default: Revert "Default: Shorter and better ABMs"
This reverts commit e523c3a296 to re-enable
the overriding and redefinition of these global functions.
2017-11-19 17:16:32 +01:00
ShadowNinja d5b9fee6fe Merge 0.4.16 into stable-0.4 2017-06-03 17:22:59 -04:00
sfan5 437860feff Merge tag '0.4.15' into stable-0.4
0.4.15
2016-12-22 23:00:57 +01:00
32 changed files with 411 additions and 352 deletions

View File

@ -155,7 +155,8 @@ The doors mod allows modders to register custom doors and trapdoors.
### Fence gate definition ### Fence gate definition
description = "Wooden Fence Gate", description = "Wooden Fence Gate",
texture = "default_wood.png", texture = "default_wood.png", -- `backface_culling` will automatically be
-- set to `true` if not specified.
material = "default:wood", material = "default:wood",
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
sounds = default.node_sound_wood_defaults(), -- optional sounds = default.node_sound_wood_defaults(), -- optional
@ -303,12 +304,13 @@ TNT API
* `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`. * `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`.
* `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png". * `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png".
`tnt.boom(position, definition)` `tnt.boom(position[, definition])`
^ Create an explosion. ^ Create an explosion.
* `position` The center of explosion. * `position` The center of explosion.
* `definition` The TNT definion as passed to `tnt.register` * `definition` The TNT definion as passed to `tnt.register` with the following addition:
* `explode_center` false by default which removes TNT node on blast, when true will explode center node.
`tnt.burn(position, [nodename])` `tnt.burn(position, [nodename])`

View File

@ -49,21 +49,24 @@ function beds.register_bed(name, def)
local node = minetest.get_node(under) local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name] local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and if udef and udef.on_rightclick and
not (placer and placer:get_player_control().sneak) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack, return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end
local pos local pos
if minetest.registered_items[minetest.get_node(under).name].buildable_to then if udef and udef.buildable_to then
pos = under pos = under
else else
pos = pointed_thing.above pos = pointed_thing.above
end end
if minetest.is_protected(pos, placer:get_player_name()) and local player_name = placer and placer:get_player_name() or ""
not minetest.check_player_privs(placer, "protection_bypass") then
minetest.record_protection_violation(pos, placer:get_player_name()) if minetest.is_protected(pos, player_name) and
not minetest.check_player_privs(player_name, "protection_bypass") then
minetest.record_protection_violation(pos, player_name)
return itemstack return itemstack
end end
@ -72,12 +75,13 @@ function beds.register_bed(name, def)
return itemstack return itemstack
end end
local dir = minetest.dir_to_facedir(placer:get_look_dir()) local dir = placer and placer:get_look_dir() and
minetest.dir_to_facedir(placer:get_look_dir()) or 0
local botpos = vector.add(pos, minetest.facedir_to_dir(dir)) local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
if minetest.is_protected(botpos, placer:get_player_name()) and if minetest.is_protected(botpos, player_name) and
not minetest.check_player_privs(placer, "protection_bypass") then not minetest.check_player_privs(player_name, "protection_bypass") then
minetest.record_protection_violation(botpos, placer:get_player_name()) minetest.record_protection_violation(botpos, player_name)
return itemstack return itemstack
end end
@ -90,7 +94,7 @@ function beds.register_bed(name, def)
minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
if not (creative and creative.is_enabled_for if not (creative and creative.is_enabled_for
and creative.is_enabled_for(placer:get_player_name())) then and creative.is_enabled_for(player_name)) then
itemstack:take_item() itemstack:take_item()
end end
return itemstack return itemstack

View File

@ -230,7 +230,8 @@ minetest.register_craftitem("boats:boat", {
local node = minetest.get_node(under) local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name] local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and if udef and udef.on_rightclick and
not (placer and placer:get_player_control().sneak) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack, return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end
@ -244,9 +245,12 @@ minetest.register_craftitem("boats:boat", {
pointed_thing.under.y = pointed_thing.under.y + 0.5 pointed_thing.under.y = pointed_thing.under.y + 0.5
boat = minetest.add_entity(pointed_thing.under, "boats:boat") boat = minetest.add_entity(pointed_thing.under, "boats:boat")
if boat then if boat then
boat:setyaw(placer:get_look_horizontal()) if placer then
if not (creative and creative.is_enabled_for boat:setyaw(placer:get_look_horizontal())
and creative.is_enabled_for(placer:get_player_name())) then end
local player_name = placer and placer:get_player_name() or ""
if not (creative and creative.is_enabled_for and
creative.is_enabled_for(player_name)) then
itemstack:take_item() itemstack:take_item()
end end
end end

View File

@ -68,6 +68,12 @@ minetest.register_node("bones:bones", {
on_metadata_inventory_take = function(pos, listname, index, stack, player) on_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_inventory():is_empty("main") then if meta:get_inventory():is_empty("main") then
local inv = player:get_inventory()
if inv:room_for_item("main", {name = "bones:bones"}) then
inv:add_item("main", {name = "bones:bones"})
else
minetest.add_item(pos, "bones:bones")
end
minetest.remove_node(pos) minetest.remove_node(pos)
end end
end, end,

View File

@ -69,7 +69,8 @@ function bucket.register_liquid(source, flowing, itemname, inventory_image, name
-- Call on_rightclick if the pointed node defines it -- Call on_rightclick if the pointed node defines it
if ndef and ndef.on_rightclick and if ndef and ndef.on_rightclick and
user and not user:get_player_control().sneak then not (user and user:is_player() and
user:get_player_control().sneak) then
return ndef.on_rightclick( return ndef.on_rightclick(
pointed_thing.under, pointed_thing.under,
node, user, node, user,

View File

@ -58,7 +58,8 @@ end
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
local pos = self.object:getpos() local pos = self.object:getpos()
if not self.railtype then local vel = self.object:getvelocity()
if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then
local node = minetest.get_node(pos).name local node = minetest.get_node(pos).name
self.railtype = minetest.get_item_group(node, "connect_to_raillike") self.railtype = minetest.get_item_group(node, "connect_to_raillike")
end end
@ -105,7 +106,6 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
return return
end end
-- Player punches cart to alter velocity -- Player punches cart to alter velocity
local vel = self.object:getvelocity()
if puncher:get_player_name() == self.driver then if puncher:get_player_name() == self.driver then
if math.abs(vel.x + vel.z) > carts.punch_speed_max then if math.abs(vel.x + vel.z) > carts.punch_speed_max then
return return
@ -367,7 +367,8 @@ minetest.register_craftitem("carts:cart", {
local node = minetest.get_node(under) local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name] local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and if udef and udef.on_rightclick and
not (placer and placer:get_player_control().sneak) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack, return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end

View File

@ -159,23 +159,29 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
end end
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
if vector.equals(old_pos, pos_) then
return true
end
local pos = vector.round(pos_) local pos = vector.round(pos_)
local pf_pos = vector.round(old_pos) local pf_pos = vector.round(old_pos)
local pf_dir = vector.new(old_dir) local pf_dir = vector.new(old_dir)
for i = 1, 3 do for i = 1, 3 do
if vector.equals(pf_pos, pos) then pf_dir, pf_switch = carts:get_rail_direction(
-- Success! Cart moved on correctly pf_pos, pf_dir, ctrl, pf_switch, railtype)
return true
end
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
if vector.equals(pf_dir, {x=0, y=0, z=0}) then if vector.equals(pf_dir, {x=0, y=0, z=0}) then
-- No way forwards -- No way forwards
return false return false
end end
pf_pos = vector.add(pf_pos, pf_dir) pf_pos = vector.add(pf_pos, pf_dir)
if vector.equals(pf_pos, pos) then
-- Success! Cart moved on correctly
return true
end
end end
-- Cart not found -- Cart not found
return false return false
@ -211,7 +217,12 @@ end
function carts:get_rail_groups(additional_groups) function carts:get_rail_groups(additional_groups)
-- Get the default rail groups and add more when a table is given -- Get the default rail groups and add more when a table is given
local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1} local groups = {
dig_immediate = 2,
attached_node = 1,
rail = 1,
connect_to_raillike = minetest.raillike_group("rail")
}
if type(additional_groups) == "table" then if type(additional_groups) == "table" then
for k, v in pairs(additional_groups) do for k, v in pairs(additional_groups) do
groups[k] = v groups[k] = v

View File

@ -40,16 +40,16 @@ end
-- Unlimited node placement -- Unlimited node placement
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)
return creative.is_enabled_for(placer:get_player_name()) if placer and placer:is_player() then
return creative.is_enabled_for(placer:get_player_name())
end
end) end)
-- Don't pick up if the item is already in the inventory -- Don't pick up if the item is already in the inventory
local old_handle_node_drops = minetest.handle_node_drops local old_handle_node_drops = minetest.handle_node_drops
function minetest.handle_node_drops(pos, drops, digger) function minetest.handle_node_drops(pos, drops, digger)
if not digger or not digger:is_player() then if not digger or not digger:is_player() or
return not creative.is_enabled_for(digger:get_player_name()) then
end
if not creative.is_enabled_for(digger:get_player_name()) then
return old_handle_node_drops(pos, drops, digger) return old_handle_node_drops(pos, drops, digger)
end end
local inv = digger:get_inventory() local inv = digger:get_inventory()

View File

@ -1,4 +1,19 @@
local player_inventory = {} local player_inventory = {}
local inventory_cache = {}
local function init_creative_cache(items)
inventory_cache[items] = {}
local i_cache = inventory_cache[items]
for name, def in pairs(items) do
if def.groups.not_in_creative_inventory ~= 1 and
def.description and def.description ~= "" then
i_cache[name] = def
end
end
table.sort(i_cache)
return i_cache
end
function creative.init_creative_inventory(player) function creative.init_creative_inventory(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
@ -10,22 +25,25 @@ function creative.init_creative_inventory(player)
minetest.create_detached_inventory("creative_" .. player_name, { minetest.create_detached_inventory("creative_" .. player_name, {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2) allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2)
if not to_list == "main" then local name = player2 and player2:get_player_name() or ""
return count if not creative.is_enabled_for(name) or
else to_list == "main" then
return 0 return 0
end end
return count
end, end,
allow_put = function(inv, listname, index, stack, player2) allow_put = function(inv, listname, index, stack, player2)
return 0 return 0
end, end,
allow_take = function(inv, listname, index, stack, player2) allow_take = function(inv, listname, index, stack, player2)
local name = player2 and player2:get_player_name() or ""
if not creative.is_enabled_for(name) then
return 0
end
return -1 return -1
end, end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) on_move = function(inv, from_list, from_index, to_list, to_index, count, player2)
end, end,
on_put = function(inv, listname, index, stack, player2)
end,
on_take = function(inv, listname, index, stack, player2) on_take = function(inv, listname, index, stack, player2)
if stack and stack:get_count() > 0 then if stack and stack:get_count() > 0 then
minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory") minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory")
@ -42,11 +60,11 @@ function creative.update_creative_inventory(player_name, tab_content)
creative.init_creative_inventory(minetest.get_player_by_name(player_name)) creative.init_creative_inventory(minetest.get_player_by_name(player_name))
local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name}) local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name})
for name, def in pairs(tab_content) do local items = inventory_cache[tab_content] or init_creative_cache(tab_content)
if not (def.groups.not_in_creative_inventory == 1) and
def.description and def.description ~= "" and for name, def in pairs(items) do
(def.name:find(inv.filter, 1, true) or if def.name:find(inv.filter, 1, true) or
def.description:lower():find(inv.filter, 1, true)) then def.description:lower():find(inv.filter, 1, true) then
creative_list[#creative_list+1] = name creative_list[#creative_list+1] = name
end end
end end
@ -100,6 +118,8 @@ function creative.register_tab(name, title, items)
button[2.75,3.4;0.8,0.5;creative_clear;X] button[2.75,3.4;0.8,0.5;creative_clear;X]
tooltip[creative_search;Search] tooltip[creative_search;Search]
tooltip[creative_clear;Reset] tooltip[creative_clear;Reset]
tooltip[creative_prev;Previous page]
tooltip[creative_next;Next page]
listring[current_player;main] listring[current_player;main]
field_close_on_enter[creative_filter;false] field_close_on_enter[creative_filter;false]
]] .. ]] ..
@ -158,10 +178,6 @@ function creative.register_tab(name, title, items)
}) })
end end
minetest.register_on_joinplayer(function(player)
creative.update_creative_inventory(player:get_player_name(), minetest.registered_items)
end)
creative.register_tab("all", "All", minetest.registered_items) creative.register_tab("all", "All", minetest.registered_items)
creative.register_tab("nodes", "Nodes", minetest.registered_nodes) creative.register_tab("nodes", "Nodes", minetest.registered_nodes)
creative.register_tab("tools", "Tools", minetest.registered_tools) creative.register_tab("tools", "Tools", minetest.registered_tools)

View File

@ -119,6 +119,7 @@ paramat (CC BY-SA 3.0):
default_silver_sandstone.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) default_silver_sandstone.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0)
default_silver_sandstone_brick.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) default_silver_sandstone_brick.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0)
default_silver_sandstone_block.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) default_silver_sandstone_block.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0)
default_bookshelf_slot.png -- Derived from a texture by Gambit (CC-BY-SA 3.0)
brunob.santos (CC BY-SA 4.0): brunob.santos (CC BY-SA 4.0):
default_desert_cobble.png default_desert_cobble.png
@ -131,7 +132,6 @@ BlockMen (CC BY-SA 3.0):
default_gold_ingot.png default_gold_ingot.png
default_tool_steelsword.png default_tool_steelsword.png
default_diamond.png default_diamond.png
default_book.png
default_tool_*.png default_tool_*.png
default_lava_source_animated.png default_lava_source_animated.png
default_lava_flowing_animated.png default_lava_flowing_animated.png
@ -145,11 +145,7 @@ BlockMen (CC BY-SA 3.0):
bubble.png bubble.png
gui_*.png gui_*.png
Wuzzy (CC BY-SA 3.0):
default_bookshelf_slot.png (based on default_book.png)
sofar (CC BY-SA 3.0): sofar (CC BY-SA 3.0):
default_book_written.png, based on default_book.png
default_aspen_sapling default_aspen_sapling
default_aspen_tree default_aspen_tree
default_aspen_tree_top, derived from default_pine_tree_top (by paramat) default_aspen_tree_top, derived from default_pine_tree_top (by paramat)
@ -186,6 +182,7 @@ Gambit (CC BY-SA 3.0):
default_snowball.png default_snowball.png
default_key.png default_key.png
default_key_skeleton.png default_key_skeleton.png
default_book.png
asl97 (CC BY-SA 3.0): asl97 (CC BY-SA 3.0):
default_ice.png default_ice.png
@ -221,6 +218,9 @@ kilbith (CC BY-SA 3.0):
default_tin_ingot.png default_tin_ingot.png
default_tin_lump.png default_tin_lump.png
CloudyProton (CC BY-SA 3.0):
default_book_written.png, based on default_book.png by Gambit
Glass breaking sounds (CC BY 3.0): Glass breaking sounds (CC BY 3.0):
1: http://www.freesound.org/people/cmusounddesign/sounds/71947/ 1: http://www.freesound.org/people/cmusounddesign/sounds/71947/
2: http://www.freesound.org/people/Tomlija/sounds/97669/ 2: http://www.freesound.org/people/Tomlija/sounds/97669/

View File

@ -190,6 +190,9 @@ minetest.register_craft({
} }
}) })
-- Axes
-- Recipes face left to match appearence in textures and inventory
minetest.register_craft({ minetest.register_craft({
output = 'default:axe_wood', output = 'default:axe_wood',
recipe = { recipe = {
@ -244,60 +247,6 @@ minetest.register_craft({
} }
}) })
minetest.register_craft({
output = 'default:axe_wood',
recipe = {
{'group:wood', 'group:wood'},
{'group:stick', 'group:wood'},
{'group:stick',''},
}
})
minetest.register_craft({
output = 'default:axe_stone',
recipe = {
{'group:stone', 'group:stone'},
{'group:stick', 'group:stone'},
{'group:stick', ''},
}
})
minetest.register_craft({
output = 'default:axe_steel',
recipe = {
{'default:steel_ingot', 'default:steel_ingot'},
{'group:stick', 'default:steel_ingot'},
{'group:stick', ''},
}
})
minetest.register_craft({
output = 'default:axe_bronze',
recipe = {
{'default:bronze_ingot', 'default:bronze_ingot'},
{'group:stick', 'default:bronze_ingot'},
{'group:stick', ''},
}
})
minetest.register_craft({
output = 'default:axe_mese',
recipe = {
{'default:mese_crystal', 'default:mese_crystal'},
{'group:stick', 'default:mese_crystal'},
{'group:stick', ''},
}
})
minetest.register_craft({
output = 'default:axe_diamond',
recipe = {
{'default:diamond', 'default:diamond'},
{'group:stick', 'default:diamond'},
{'group:stick', ''},
}
})
minetest.register_craft({ minetest.register_craft({
output = 'default:sword_wood', output = 'default:sword_wood',
recipe = { recipe = {
@ -904,7 +853,7 @@ minetest.register_craft({
-- Fuels -- Fuels
-- --
-- Support use of group:tree -- Support use of group:tree, includes default:tree which has the same burn time
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "group:tree", recipe = "group:tree",
@ -927,12 +876,6 @@ minetest.register_craft({
burntime = 26, burntime = 26,
}) })
minetest.register_craft({
type = "fuel",
recipe = "default:tree",
burntime = 30,
})
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:acacia_tree", recipe = "default:acacia_tree",
@ -946,7 +889,7 @@ minetest.register_craft({
}) })
-- Support use of group:wood -- Support use of group:wood, includes default:wood which has the same burn time
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "group:wood", recipe = "group:wood",
@ -965,12 +908,6 @@ minetest.register_craft({
burntime = 6, burntime = 6,
}) })
minetest.register_craft({
type = "fuel",
recipe = "default:wood",
burntime = 7,
})
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:acacia_wood", recipe = "default:acacia_wood",
@ -984,53 +921,47 @@ minetest.register_craft({
}) })
-- Support use of group:sapling -- Support use of group:sapling, includes default:sapling which has the same burn time
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "group:sapling", recipe = "group:sapling",
burntime = 10, burntime = 5,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:bush_sapling", recipe = "default:bush_sapling",
burntime = 6, burntime = 3,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:acacia_bush_sapling", recipe = "default:acacia_bush_sapling",
burntime = 7, burntime = 4,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:aspen_sapling", recipe = "default:aspen_sapling",
burntime = 8, burntime = 4,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:pine_sapling", recipe = "default:pine_sapling",
burntime = 9, burntime = 5,
})
minetest.register_craft({
type = "fuel",
recipe = "default:sapling",
burntime = 10,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:acacia_sapling", recipe = "default:acacia_sapling",
burntime = 11, burntime = 6,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:junglesapling", recipe = "default:junglesapling",
burntime = 12, burntime = 6,
}) })
@ -1080,13 +1011,13 @@ minetest.register_craft({
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:junglegrass", recipe = "default:junglegrass",
burntime = 2, burntime = 3,
}) })
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "group:leaves", recipe = "group:leaves",
burntime = 1, burntime = 4,
}) })
minetest.register_craft({ minetest.register_craft({
@ -1098,7 +1029,7 @@ minetest.register_craft({
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:papyrus", recipe = "default:papyrus",
burntime = 1, burntime = 3,
}) })
minetest.register_craft({ minetest.register_craft({
@ -1110,7 +1041,7 @@ minetest.register_craft({
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:ladder_wood", recipe = "default:ladder_wood",
burntime = 2, burntime = 7,
}) })
minetest.register_craft({ minetest.register_craft({
@ -1143,12 +1074,6 @@ minetest.register_craft({
burntime = 30, burntime = 30,
}) })
minetest.register_craft({
type = "fuel",
recipe = "default:apple",
burntime = 3,
})
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "default:coal_lump", recipe = "default:coal_lump",

View File

@ -75,12 +75,16 @@ local function book_on_use(itemstack, user)
return itemstack return itemstack
end end
local max_text_size = 10000
local max_title_size = 80
local short_title_size = 35
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "default:book" then return end if formname ~= "default:book" then return end
local inv = player:get_inventory() local inv = player:get_inventory()
local stack = player:get_wielded_item() local stack = player:get_wielded_item()
if fields.save and fields.title ~= "" and fields.text ~= "" then if fields.save and fields.title and fields.text
and fields.title ~= "" and fields.text ~= "" then
local new_stack, data local new_stack, data
if stack:get_name() ~= "default:book_written" then if stack:get_name() ~= "default:book_written" then
local count = stack:get_count() local count = stack:get_count()
@ -99,11 +103,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
if not data then data = {} end if not data then data = {} end
data.title = fields.title data.title = fields.title:sub(1, max_title_size)
data.owner = player:get_player_name() data.owner = player:get_player_name()
data.description = "\""..fields.title.."\" by "..data.owner local short_title = data.title
data.text = fields.text -- Don't bother triming the title if the trailing dots would make it longer
data.text_len = #data.text if #short_title > short_title_size + 3 then
short_title = short_title:sub(1, short_title_size) .. "..."
end
data.description = "\""..short_title.."\" by "..data.owner
data.text = fields.text:sub(1, max_text_size)
data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n")
data.page = 1 data.page = 1
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)

View File

@ -136,10 +136,12 @@ if minetest.settings:get_bool("enable_lavacooling") ~= false then
label = "Lava cooling", label = "Lava cooling",
nodenames = {"default:lava_source", "default:lava_flowing"}, nodenames = {"default:lava_source", "default:lava_flowing"},
neighbors = {"group:cools_lava", "group:water"}, neighbors = {"group:cools_lava", "group:water"},
interval = 1, interval = 2,
chance = 2, chance = 2,
catch_up = false, catch_up = false,
action = default.cool_lava, action = function(...)
default.cool_lava(...)
end,
}) })
end end
@ -222,7 +224,9 @@ minetest.register_abm({
neighbors = {"group:sand"}, neighbors = {"group:sand"},
interval = 12, interval = 12,
chance = 83, chance = 83,
action = default.grow_cactus action = function(...)
default.grow_cactus(...)
end
}) })
minetest.register_abm({ minetest.register_abm({
@ -231,7 +235,9 @@ minetest.register_abm({
neighbors = {"default:dirt", "default:dirt_with_grass"}, neighbors = {"default:dirt", "default:dirt_with_grass"},
interval = 14, interval = 14,
chance = 71, chance = 71,
action = default.grow_papyrus action = function(...)
default.grow_papyrus(...)
end
}) })
@ -291,7 +297,7 @@ function default.register_fence(name, def)
groups = {}, groups = {},
} }
for k, v in pairs(default_fields) do for k, v in pairs(default_fields) do
if not def[k] then if def[k] == nil then
def[k] = v def[k] = v
end end
end end
@ -313,7 +319,7 @@ end
-- Prevent decay of placed leaves -- Prevent decay of placed leaves
default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) default.after_place_leaves = function(pos, placer, itemstack, pointed_thing)
if placer and not placer:get_player_control().sneak then if placer and placer:is_player() and not placer:get_player_control().sneak then
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
node.param2 = 1 node.param2 = 1
minetest.set_node(pos, node) minetest.set_node(pos, node)

View File

@ -119,7 +119,7 @@ local function furnace_node_timer(pos, elapsed)
local fuel local fuel
local update = true local update = true
while update do while elapsed > 0 and update do
update = false update = false
srclist = inv:get_list("src") srclist = inv:get_list("src")
@ -134,13 +134,18 @@ local function furnace_node_timer(pos, elapsed)
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
cookable = cooked.time ~= 0 cookable = cooked.time ~= 0
local el = math.min(elapsed, fuel_totaltime - fuel_time)
if cookable then -- fuel lasts long enough, adjust el to cooking duration
el = math.min(el, cooked.time - src_time)
end
-- Check if we have enough fuel to burn -- Check if we have enough fuel to burn
if fuel_time < fuel_totaltime then if fuel_time < fuel_totaltime then
-- The furnace is currently active and has enough fuel -- The furnace is currently active and has enough fuel
fuel_time = fuel_time + elapsed fuel_time = fuel_time + el
-- If there is a cookable item then check if it is ready yet -- If there is a cookable item then check if it is ready yet
if cookable then if cookable then
src_time = src_time + elapsed src_time = src_time + el
if src_time >= cooked.time then if src_time >= cooked.time then
-- Place result in dst list if possible -- Place result in dst list if possible
if inv:room_for_item("dst", cooked.item) then if inv:room_for_item("dst", cooked.item) then
@ -149,6 +154,9 @@ local function furnace_node_timer(pos, elapsed)
src_time = src_time - cooked.time src_time = src_time - cooked.time
update = true update = true
end end
else
-- Item could not be cooked: probably missing fuel
update = true
end end
end end
else else
@ -166,8 +174,7 @@ local function furnace_node_timer(pos, elapsed)
-- Take fuel from fuel list -- Take fuel from fuel list
inv:set_stack("fuel", 1, afterfuel.items[1]) inv:set_stack("fuel", 1, afterfuel.items[1])
update = true update = true
fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime) fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time)
src_time = src_time + elapsed
end end
else else
-- We don't need to get new fuel since there is no cookable item -- We don't need to get new fuel since there is no cookable item
@ -177,7 +184,7 @@ local function furnace_node_timer(pos, elapsed)
fuel_time = 0 fuel_time = 0
end end
elapsed = 0 elapsed = elapsed - el
end end
if fuel and fuel_totaltime > fuel.time then if fuel and fuel_totaltime > fuel.time then

View File

@ -19,7 +19,7 @@ Licenses of media (textures, models and sounds)
----------------------------------------------- -----------------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Copyright (C) 2010-2016: Copyright (C) 2010-2017:
celeron55, Perttu Ahola <celeron55@gmail.com> celeron55, Perttu Ahola <celeron55@gmail.com>
Cisoun Cisoun
G4JC G4JC
@ -44,6 +44,7 @@ Copyright (C) 2010-2016:
GreenXenith GreenXenith
kaeza kaeza
kilbith kilbith
CloudyProton
You are free to: You are free to:
Share — copy and redistribute the material in any medium or format. Share — copy and redistribute the material in any medium or format.
@ -111,7 +112,6 @@ http://creativecommons.org/licenses/by-sa/4.0/
Attribution-ShareAlike 2.0 Generic (CC BY-SA 2.0) Attribution-ShareAlike 2.0 Generic (CC BY-SA 2.0)
Copyright (C) 2014-2016 Neuromancer Copyright (C) 2014-2016 Neuromancer
You are free to: You are free to:
Share — copy and redistribute the material in any medium or format. Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially. Adapt — remix, transform, and build upon the material for any purpose, even commercially.

View File

@ -440,7 +440,7 @@ minetest.register_node("default:dirt_with_snow", {
tiles = {"default_snow.png", "default_dirt.png", tiles = {"default_snow.png", "default_dirt.png",
{name = "default_dirt.png^default_snow_side.png", {name = "default_dirt.png^default_snow_side.png",
tileable_vertical = false}}, tileable_vertical = false}},
groups = {crumbly = 3, spreading_dirt_type = 1, snowy = 1}, groups = {crumbly = 3, soil = 1, spreading_dirt_type = 1, snowy = 1},
drop = 'default:dirt', drop = 'default:dirt',
sounds = default.node_sound_dirt_defaults({ sounds = default.node_sound_dirt_defaults({
footstep = {name = "default_snow_footstep", gain = 0.15}, footstep = {name = "default_snow_footstep", gain = 0.15},
@ -608,7 +608,7 @@ minetest.register_node("default:sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(2400,4800)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -673,9 +673,7 @@ minetest.register_node("default:apple", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
after_place_node = function(pos, placer, itemstack) after_place_node = function(pos, placer, itemstack)
if placer:is_player() then minetest.set_node(pos, {name = "default:apple", param2 = 1})
minetest.set_node(pos, {name = "default:apple", param2 = 1})
end
end, end,
}) })
@ -742,7 +740,7 @@ minetest.register_node("default:junglesapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(2400,4800)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -821,7 +819,7 @@ minetest.register_node("default:pine_sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(2400,4800)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -901,7 +899,7 @@ minetest.register_node("default:acacia_sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(2400,4800)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -979,7 +977,7 @@ minetest.register_node("default:aspen_sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(2400,4800)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -1362,7 +1360,7 @@ minetest.register_node("default:bush_sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(1200, 2400)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -1433,7 +1431,7 @@ minetest.register_node("default:acacia_bush_sapling", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos) on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(1200, 2400)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end, end,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
@ -1783,13 +1781,14 @@ local function get_chest_formspec(pos)
end end
local function chest_lid_obstructed(pos) local function chest_lid_obstructed(pos)
local above = { x = pos.x, y = pos.y + 1, z = pos.z } local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local def = minetest.registered_nodes[minetest.get_node(above).name] local def = minetest.registered_nodes[minetest.get_node(above).name]
-- allow ladders, signs, wallmounted things and torches to not obstruct -- allow ladders, signs, wallmounted things and torches to not obstruct
if def.drawtype == "airlike" or if def and
(def.drawtype == "airlike" or
def.drawtype == "signlike" or def.drawtype == "signlike" or
def.drawtype == "torchlike" or def.drawtype == "torchlike" or
(def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then (def.drawtype == "nodebox" and def.paramtype2 == "wallmounted")) then
return false return false
end end
return true return true
@ -1797,6 +1796,24 @@ end
local open_chests = {} local open_chests = {}
local function chest_lid_close(pn)
local pos = open_chests[pn].pos
local sound = open_chests[pn].sound
local swap = open_chests[pn].swap
open_chests[pn] = nil
for k, v in pairs(open_chests) do
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
return true
end
end
local node = minetest.get_node(pos)
minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap,
param2 = node.param2 })
minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10})
end
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "default:chest" then if formname ~= "default:chest" then
return return
@ -1810,23 +1827,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return return
end end
local pos = open_chests[pn].pos chest_lid_close(pn)
local sound = open_chests[pn].sound
local swap = open_chests[pn].swap
local node = minetest.get_node(pos)
open_chests[pn] = nil
for k, v in pairs(open_chests) do
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
return true
end
end
minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap,
param2 = node.param2 })
minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10})
return true return true
end) end)
minetest.register_on_leaveplayer(function(player)
local pn = player:get_player_name()
if open_chests[pn] then
chest_lid_close(pn)
end
end)
function default.register_chest(name, d) function default.register_chest(name, d)
local def = table.copy(d) local def = table.copy(d)
def.drawtype = "mesh" def.drawtype = "mesh"
@ -1960,6 +1971,13 @@ function default.register_chest(name, d)
open_chests[clicker:get_player_name()] = { pos = pos, open_chests[clicker:get_player_name()] = { pos = pos,
sound = def.sound_close, swap = name } sound = def.sound_close, swap = name }
end end
def.on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "main", drops)
drops[#drops+1] = "default:" .. name
minetest.remove_node(pos)
return drops
end
end end
def.on_metadata_inventory_move = function(pos, from_list, from_index, def.on_metadata_inventory_move = function(pos, from_list, from_index,
@ -1977,27 +1995,28 @@ function default.register_chest(name, d)
" takes " .. stack:get_name() .. " takes " .. stack:get_name() ..
" from chest at " .. minetest.pos_to_string(pos)) " from chest at " .. minetest.pos_to_string(pos))
end end
def.on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "main", drops)
drops[#drops+1] = "default:chest"
minetest.remove_node(pos)
return drops
end
local def_opened = table.copy(def) local def_opened = table.copy(def)
local def_closed = table.copy(def) local def_closed = table.copy(def)
def_opened.mesh = "chest_open.obj" def_opened.mesh = "chest_open.obj"
for i = 1, #def_opened.tiles do
if type(def_opened.tiles[i]) == "string" then
def_opened.tiles[i] = {name = def_opened.tiles[i], backface_culling = true}
elseif def_opened.tiles[i].backface_culling == nil then
def_opened.tiles[i].backface_culling = true
end
end
def_opened.drop = "default:" .. name def_opened.drop = "default:" .. name
def_opened.groups.not_in_creative_inventory = 1 def_opened.groups.not_in_creative_inventory = 1
def_opened.selection_box = { def_opened.selection_box = {
type = "fixed", type = "fixed",
fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 }, fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 },
} }
def_opened.can_dig = function() def_opened.can_dig = function()
return false return false
end end
def_opened.on_blast = function() end
def_closed.mesh = nil def_closed.mesh = nil
def_closed.drawtype = nil def_closed.drawtype = nil

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

After

Width:  |  Height:  |  Size: 140 B

View File

@ -389,7 +389,8 @@ minetest.register_tool("default:key", {
local node = minetest.get_node(under) local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name] local def = minetest.registered_nodes[node.name]
if def and def.on_rightclick and if def and def.on_rightclick and
not (placer and placer:get_player_control().sneak) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return def.on_rightclick(under, node, placer, itemstack, return def.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end

View File

@ -63,7 +63,8 @@ minetest.register_node("default:torch", {
local node = minetest.get_node(under) local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name] local def = minetest.registered_nodes[node.name]
if def and def.on_rightclick and if def and def.on_rightclick and
((not placer) or (placer and not placer:get_player_control().sneak)) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return def.on_rightclick(under, node, placer, itemstack, return def.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end

View File

@ -31,12 +31,12 @@ local function is_snow_nearby(pos)
end end
-- Sapling ABM -- Grow sapling
function default.grow_sapling(pos) function default.grow_sapling(pos)
if not default.can_grow(pos) then if not default.can_grow(pos) then
-- try a bit later again -- try again 5 min later
minetest.get_node_timer(pos):start(math.random(240, 600)) minetest.get_node_timer(pos):start(300)
return return
end end
@ -94,7 +94,7 @@ minetest.register_lbm({
"default:pine_sapling", "default:acacia_sapling", "default:pine_sapling", "default:acacia_sapling",
"default:aspen_sapling"}, "default:aspen_sapling"},
action = function(pos) action = function(pos)
minetest.get_node_timer(pos):start(math.random(1200, 2400)) minetest.get_node_timer(pos):start(math.random(300, 1500))
end end
}) })
@ -468,7 +468,9 @@ function default.sapling_on_place(itemstack, placer, pointed_thing,
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
local pdef = node and minetest.registered_nodes[node.name] local pdef = node and minetest.registered_nodes[node.name]
if pdef and pdef.on_rightclick and not placer:get_player_control().sneak then if pdef and pdef.on_rightclick and
not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing) return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing)
end end
@ -481,7 +483,7 @@ function default.sapling_on_place(itemstack, placer, pointed_thing,
end end
end end
local player_name = placer:get_player_name() local player_name = placer and placer:get_player_name() or ""
-- Check sapling position for protection -- Check sapling position for protection
if minetest.is_protected(pos, player_name) then if minetest.is_protected(pos, player_name) then
minetest.record_protection_violation(pos, player_name) minetest.record_protection_violation(pos, player_name)

View File

@ -203,12 +203,7 @@ end
local function can_dig_door(pos, digger) local function can_dig_door(pos, digger)
replace_old_owner_information(pos) replace_old_owner_information(pos)
if default.can_interact_with_node(digger, pos) then return default.can_interact_with_node(digger, pos)
return true
else
minetest.record_protection_violation(pos, digger:get_player_name())
return false
end
end end
function doors.register(name, def) function doors.register(name, def)
@ -266,7 +261,8 @@ function doors.register(name, def)
local node = minetest.get_node(pointed_thing.under) local node = minetest.get_node(pointed_thing.under)
local pdef = minetest.registered_nodes[node.name] local pdef = minetest.registered_nodes[node.name]
if pdef and pdef.on_rightclick and if pdef and pdef.on_rightclick and
not placer:get_player_control().sneak then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return pdef.on_rightclick(pointed_thing.under, return pdef.on_rightclick(pointed_thing.under,
node, placer, itemstack, pointed_thing) node, placer, itemstack, pointed_thing)
end end
@ -290,12 +286,12 @@ function doors.register(name, def)
return itemstack return itemstack
end end
local pn = placer:get_player_name() local pn = placer and placer:get_player_name() or ""
if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then
return itemstack return itemstack
end end
local dir = minetest.dir_to_facedir(placer:get_look_dir()) local dir = placer and minetest.dir_to_facedir(placer:get_look_dir()) or 0
local ref = { local ref = {
{x = -1, y = 0, z = 0}, {x = -1, y = 0, z = 0},
@ -712,7 +708,7 @@ function doors.register_fencegate(name, def)
local fence = { local fence = {
description = def.description, description = def.description,
drawtype = "mesh", drawtype = "mesh",
tiles = {def.texture}, tiles = {},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
sunlight_propagates = true, sunlight_propagates = true,
@ -734,6 +730,16 @@ function doors.register_fencegate(name, def)
}, },
} }
if type(def.texture) == "string" then
fence.tiles[1] = {name = def.texture, backface_culling = true}
elseif def.texture.backface_culling == nil then
fence.tiles[1] = table.copy(def.texture)
fence.tiles[1].backface_culling = true
else
fence.tiles[1] = def.texture
end
if not fence.sounds then if not fence.sounds then
fence.sounds = default.node_sound_wood_defaults() fence.sounds = default.node_sound_wood_defaults()
end end

View File

@ -118,15 +118,6 @@ farming.register_hoe = function(name, def)
{"", "group:stick", ""} {"", "group:stick", ""}
} }
}) })
-- Reverse Recipe
minetest.register_craft({
output = name:sub(2),
recipe = {
{"", def.material, def.material},
{"", "group:stick", ""},
{"", "group:stick", ""}
}
})
end end
end end
@ -153,12 +144,14 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
local under = minetest.get_node(pt.under) local under = minetest.get_node(pt.under)
local above = minetest.get_node(pt.above) local above = minetest.get_node(pt.above)
if minetest.is_protected(pt.under, placer:get_player_name()) then local player_name = placer and placer:get_player_name() or ""
minetest.record_protection_violation(pt.under, placer:get_player_name())
if minetest.is_protected(pt.under, player_name) then
minetest.record_protection_violation(pt.under, player_name)
return return
end end
if minetest.is_protected(pt.above, placer:get_player_name()) then if minetest.is_protected(pt.above, player_name) then
minetest.record_protection_violation(pt.above, placer:get_player_name()) minetest.record_protection_violation(pt.above, player_name)
return return
end end
@ -189,7 +182,7 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
minetest.add_node(pt.above, {name = plantname, param2 = 1}) minetest.add_node(pt.above, {name = plantname, param2 = 1})
tick(pt.above) tick(pt.above)
if not (creative and creative.is_enabled_for if not (creative and creative.is_enabled_for
and creative.is_enabled_for(placer:get_player_name())) then and creative.is_enabled_for(player_name)) then
itemstack:take_item() itemstack:take_item()
end end
return itemstack return itemstack
@ -319,7 +312,8 @@ farming.register_plant = function(name, def)
local node = minetest.get_node(under) local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name] local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and if udef and udef.on_rightclick and
not (placer and placer:get_player_control().sneak) then not (placer and placer:is_player() and
placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack, return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack pointed_thing) or itemstack
end end

View File

@ -1,2 +1,3 @@
default default
wool wool
stairs

View File

@ -98,6 +98,16 @@ minetest.register_node("farming:straw", {
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
}) })
stairs.register_stair_and_slab(
"straw",
"farming:straw",
{snappy = 3, flammable = 4},
{"farming_straw.png"},
"Straw Stair",
"Straw Slab",
default.node_sound_leaves_defaults()
)
minetest.register_abm({ minetest.register_abm({
label = "Farming soil", label = "Farming soil",
nodenames = {"group:field"}, nodenames = {"group:field"},

View File

@ -127,24 +127,29 @@ function flowers.flower_spread(pos, node)
local pos0 = vector.subtract(pos, 4) local pos0 = vector.subtract(pos, 4)
local pos1 = vector.add(pos, 4) local pos1 = vector.add(pos, 4)
if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 3 then -- Maximum flower density created by mapgen is 13 per 9x9 area.
-- The limit of 7 below was tuned by in-game testing to result in a maximum
-- flower density by ABM spread of 13 per 9x9 area.
-- Warning: Setting this limit theoretically without in-game testing
-- results in a maximum flower density by ABM spread that is far too high.
if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 7 then
return return
end end
local soils = minetest.find_nodes_in_area_under_air( local soils = minetest.find_nodes_in_area_under_air(
pos0, pos1, "group:soil") pos0, pos1, "group:soil")
if #soils > 0 then local num_soils = #soils
local seedling = soils[math.random(#soils)] if num_soils >= 1 then
local seedling_above = for si = 1, math.min(3, num_soils) do
{x = seedling.x, y = seedling.y + 1, z = seedling.z} local soil = soils[math.random(num_soils)]
light = minetest.get_node_light(seedling_above) local soil_above = {x = soil.x, y = soil.y + 1, z = soil.z}
if not light or light < 13 or light = minetest.get_node_light(soil_above)
-- Desert sand is in the soil group if light and light >= 13 and
minetest.get_node(seedling).name == "default:desert_sand" then -- Desert sand is in the soil group
return minetest.get_node(soil).name ~= "default:desert_sand" then
minetest.set_node(soil_above, {name = node.name})
end
end end
minetest.set_node(seedling_above, {name = node.name})
end end
end end
@ -152,7 +157,7 @@ minetest.register_abm({
label = "Flower spread", label = "Flower spread",
nodenames = {"group:flora"}, nodenames = {"group:flora"},
interval = 13, interval = 13,
chance = 96, chance = 300,
action = function(...) action = function(...)
flowers.flower_spread(...) flowers.flower_spread(...)
end, end,
@ -204,38 +209,34 @@ minetest.register_node("flowers:mushroom_brown", {
-- Mushroom spread and death -- Mushroom spread and death
function flowers.mushroom_spread(pos, node)
if minetest.get_node_light(pos, nil) == 15 then
minetest.remove_node(pos)
return
end
local positions = minetest.find_nodes_in_area_under_air(
{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1},
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
{"group:soil", "group:tree"})
if #positions == 0 then
return
end
local pos2 = positions[math.random(#positions)]
pos2.y = pos2.y + 1
if minetest.get_node_light(pos, 0.5) <= 3 and
minetest.get_node_light(pos2, 0.5) <= 3 then
minetest.set_node(pos2, {name = node.name})
end
end
minetest.register_abm({ minetest.register_abm({
label = "Mushroom spread", label = "Mushroom spread",
nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"},
interval = 11, interval = 11,
chance = 50, chance = 150,
action = function(pos, node) action = function(...)
if minetest.get_node_light(pos, nil) == 15 then flowers.mushroom_spread(...)
minetest.remove_node(pos) end,
return
end
local random = {
x = pos.x + math.random(-2, 2),
y = pos.y + math.random(-1, 1),
z = pos.z + math.random(-2, 2)
}
local random_node = minetest.get_node_or_nil(random)
if not random_node or random_node.name ~= "air" then
return
end
local node_under = minetest.get_node_or_nil({x = random.x,
y = random.y - 1, z = random.z})
if not node_under then
return
end
if (minetest.get_item_group(node_under.name, "soil") ~= 0 or
minetest.get_item_group(node_under.name, "tree") ~= 0) and
minetest.get_node_light(pos, 0.5) <= 3 and
minetest.get_node_light(random, 0.5) <= 3 then
minetest.set_node(random, {name = node.name})
end
end
}) })
@ -280,12 +281,17 @@ minetest.register_node("flowers:waterlily", {
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.above local pos = pointed_thing.above
local node = minetest.get_node(pointed_thing.under).name local node = minetest.get_node(pointed_thing.under)
local def = minetest.registered_nodes[node] local def = minetest.registered_nodes[node.name]
local player_name = placer:get_player_name() local player_name = placer and placer:get_player_name() or ""
if def and def.on_rightclick then
return def.on_rightclick(pointed_thing.under, node, placer, itemstack,
pointed_thing)
end
if def and def.liquidtype == "source" and if def and def.liquidtype == "source" and
minetest.get_item_group(node, "water") > 0 then minetest.get_item_group(node.name, "water") > 0 then
if not minetest.is_protected(pos, player_name) then if not minetest.is_protected(pos, player_name) then
minetest.set_node(pos, {name = "flowers:waterlily", minetest.set_node(pos, {name = "flowers:waterlily",
param2 = math.random(0, 3)}) param2 = math.random(0, 3)})

View File

@ -85,9 +85,10 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
end end
local pos = pointed_thing.under local pos = pointed_thing.under
local player_name = user and user:get_player_name() or ""
if minetest.is_protected(pos, user:get_player_name()) then if minetest.is_protected(pos, player_name) then
minetest.record_protection_violation(pos, user:get_player_name()) minetest.record_protection_violation(pos, player_name)
return return
end end
@ -133,8 +134,8 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses)
minetest.check_for_falling(pos) minetest.check_for_falling(pos)
end end
if not (creative and creative.is_enabled_for if not (creative and creative.is_enabled_for and
and creative.is_enabled_for(user:get_player_name())) then creative.is_enabled_for(player_name)) then
itemstack:add_wear(65535 / ((uses or 200) - 1)) itemstack:add_wear(65535 / ((uses or 200) - 1))
end end

View File

@ -29,7 +29,8 @@ end
function sfinv.get_nav_fs(player, context, nav, current_idx) function sfinv.get_nav_fs(player, context, nav, current_idx)
-- Only show tabs if there is more than one page -- Only show tabs if there is more than one page
if #nav > 1 then if #nav > 1 then
return "tabheader[0,0;tabs;" .. table.concat(nav, ",") .. ";" .. current_idx .. ";true;false]" return "tabheader[0,0;sfinv_nav_tabs;" .. table.concat(nav, ",") ..
";" .. current_idx .. ";true;false]"
else else
return "" return ""
end end
@ -84,9 +85,20 @@ function sfinv.get_formspec(player, context)
return page:get(player, context) return page:get(player, context)
else else
local old_page = context.page local old_page = context.page
context.page = sfinv.get_homepage_name(player) local home_page = sfinv.get_homepage_name(player)
if old_page == home_page then
minetest.log("error", "[sfinv] Couldn't find " .. dump(old_page) ..
", which is also the old page")
return ""
end
context.page = home_page
assert(sfinv.pages[context.page], "[sfinv] Invalid homepage") assert(sfinv.pages[context.page], "[sfinv] Invalid homepage")
minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. " so using switching to homepage") minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) ..
" so switching to homepage")
return sfinv.get_formspec(player, context) return sfinv.get_formspec(player, context)
end end
end end
@ -151,8 +163,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
-- Was a tab selected? -- Was a tab selected?
if fields.tabs and context.nav then if fields.sfinv_nav_tabs and context.nav then
local tid = tonumber(fields.tabs) local tid = tonumber(fields.sfinv_nav_tabs)
if tid and tid > 0 then if tid and tid > 0 then
local id = context.nav[tid] local id = context.nav[tid]
local page = sfinv.pages[id] local page = sfinv.pages[id]

View File

@ -1,2 +1 @@
default default
farming

View File

@ -22,21 +22,23 @@ local function rotate_and_place(itemstack, placer, pointed_thing)
local p1 = pointed_thing.above local p1 = pointed_thing.above
local param2 = 0 local param2 = 0
local placer_pos = placer:getpos() if placer then
if placer_pos then local placer_pos = placer:getpos()
param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) if placer_pos then
end param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
end
local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
local fpos = finepos.y % 1 local fpos = finepos.y % 1
if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
or (fpos < -0.5 and fpos > -0.999999999) then or (fpos < -0.5 and fpos > -0.999999999) then
param2 = param2 + 20 param2 = param2 + 20
if param2 == 21 then if param2 == 21 then
param2 = 23 param2 = 23
elseif param2 == 23 then elseif param2 == 23 then
param2 = 21 param2 = 21
end
end end
end end
return minetest.item_place(itemstack, placer, pointed_thing, param2) return minetest.item_place(itemstack, placer, pointed_thing, param2)
@ -46,16 +48,29 @@ end
-- Node will be called stairs:stair_<subname> -- Node will be called stairs:stair_<subname>
function stairs.register_stair(subname, recipeitem, groups, images, description, sounds) function stairs.register_stair(subname, recipeitem, groups, images, description, sounds)
groups.stair = 1 local stair_images = {}
for i, image in ipairs(images) do
if type(image) == "string" then
stair_images[i] = {
name = image,
backface_culling = true,
}
elseif image.backface_culling == nil then -- override using any other value
stair_images[i] = table.copy(image)
stair_images[i].backface_culling = true
end
end
local new_groups = table.copy(groups)
new_groups.stair = 1
minetest.register_node(":stairs:stair_" .. subname, { minetest.register_node(":stairs:stair_" .. subname, {
description = description, description = description,
drawtype = "mesh", drawtype = "mesh",
mesh = "stairs_stair.obj", mesh = "stairs_stair.obj",
tiles = images, tiles = stair_images,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
is_ground_content = false, is_ground_content = false,
groups = groups, groups = new_groups,
sounds = sounds, sounds = sounds,
selection_box = { selection_box = {
type = "fixed", type = "fixed",
@ -89,16 +104,7 @@ function stairs.register_stair(subname, recipeitem, groups, images, description,
end end
if recipeitem then if recipeitem then
minetest.register_craft({ -- Recipe matches appearence in inventory
output = 'stairs:stair_' .. subname .. ' 8',
recipe = {
{recipeitem, "", ""},
{recipeitem, recipeitem, ""},
{recipeitem, recipeitem, recipeitem},
},
})
-- Flipped recipe for the silly minecrafters
minetest.register_craft({ minetest.register_craft({
output = 'stairs:stair_' .. subname .. ' 8', output = 'stairs:stair_' .. subname .. ' 8',
recipe = { recipe = {
@ -132,7 +138,8 @@ local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4}
-- Node will be called stairs:slab_<subname> -- Node will be called stairs:slab_<subname>
function stairs.register_slab(subname, recipeitem, groups, images, description, sounds) function stairs.register_slab(subname, recipeitem, groups, images, description, sounds)
groups.slab = 1 local new_groups = table.copy(groups)
new_groups.slab = 1
minetest.register_node(":stairs:slab_" .. subname, { minetest.register_node(":stairs:slab_" .. subname, {
description = description, description = description,
drawtype = "nodebox", drawtype = "nodebox",
@ -140,7 +147,7 @@ function stairs.register_slab(subname, recipeitem, groups, images, description,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
is_ground_content = false, is_ground_content = false,
groups = groups, groups = new_groups,
sounds = sounds, sounds = sounds,
node_box = { node_box = {
type = "fixed", type = "fixed",
@ -149,8 +156,9 @@ function stairs.register_slab(subname, recipeitem, groups, images, description,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local under = minetest.get_node(pointed_thing.under) local under = minetest.get_node(pointed_thing.under)
local wield_item = itemstack:get_name() local wield_item = itemstack:get_name()
local player_name = placer and placer:get_player_name() or ""
local creative_enabled = (creative and creative.is_enabled_for local creative_enabled = (creative and creative.is_enabled_for
and creative.is_enabled_for(placer:get_player_name())) and creative.is_enabled_for(player_name))
if under and under.name:find("stairs:slab_") then if under and under.name:find("stairs:slab_") then
-- place slab using under node orientation -- place slab using under node orientation
@ -166,9 +174,8 @@ function stairs.register_slab(subname, recipeitem, groups, images, description,
if not recipeitem then if not recipeitem then
return itemstack return itemstack
end end
local player_name = placer:get_player_name()
if minetest.is_protected(pointed_thing.under, player_name) and not if minetest.is_protected(pointed_thing.under, player_name) and not
minetest.check_player_privs(placer, "protection_bypass") then minetest.check_player_privs(player_name, "protection_bypass") then
minetest.record_protection_violation(pointed_thing.under, minetest.record_protection_violation(pointed_thing.under,
player_name) player_name)
return return
@ -538,16 +545,6 @@ stairs.register_stair_and_slab(
default.node_sound_stone_defaults() default.node_sound_stone_defaults()
) )
stairs.register_stair_and_slab(
"straw",
"farming:straw",
{snappy = 3, flammable = 4},
{"farming_straw.png"},
"Straw Stair",
"Straw Slab",
default.node_sound_leaves_defaults()
)
stairs.register_stair_and_slab( stairs.register_stair_and_slab(
"steelblock", "steelblock",
"default:steelblock", "default:steelblock",

View File

@ -86,8 +86,8 @@ end
local basic_flame_on_construct -- cached value local basic_flame_on_construct -- cached value
local function destroy(drops, npos, cid, c_air, c_fire, local function destroy(drops, npos, cid, c_air, c_fire,
on_blast_queue, on_construct_queue, on_blast_queue, on_construct_queue,
ignore_protection, ignore_on_blast) ignore_protection, ignore_on_blast, owner)
if not ignore_protection and minetest.is_protected(npos, "") then if not ignore_protection and minetest.is_protected(npos, owner) then
return cid return cid
end end
@ -208,6 +208,7 @@ local function add_effects(pos, radius, drops)
collisiondetection = false, collisiondetection = false,
vertical = false, vertical = false,
texture = "tnt_boom.png", texture = "tnt_boom.png",
glow = 15,
}) })
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 64, amount = 64,
@ -266,13 +267,13 @@ function tnt.burn(pos, nodename)
elseif def.on_ignite then elseif def.on_ignite then
def.on_ignite(pos) def.on_ignite(pos)
elseif minetest.get_item_group(name, "tnt") > 0 then elseif minetest.get_item_group(name, "tnt") > 0 then
minetest.swap_node(pos, {name = name .. "_burning"})
minetest.sound_play("tnt_ignite", {pos = pos}) minetest.sound_play("tnt_ignite", {pos = pos})
minetest.set_node(pos, {name = name .. "_burning"})
minetest.get_node_timer(pos):start(1) minetest.get_node_timer(pos):start(1)
end end
end end
local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast, owner, explode_center)
pos = vector.round(pos) pos = vector.round(pos)
-- scan for adjacent TNT nodes first, and enlarge the explosion -- scan for adjacent TNT nodes first, and enlarge the explosion
local vm1 = VoxelManip() local vm1 = VoxelManip()
@ -286,6 +287,10 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning") local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning")
local c_tnt_boom = minetest.get_content_id("tnt:boom") local c_tnt_boom = minetest.get_content_id("tnt:boom")
local c_air = minetest.get_content_id("air") local c_air = minetest.get_content_id("air")
-- make sure we still have explosion even when centre node isnt tnt related
if explode_center then
count = 1
end
for z = pos.z - 2, pos.z + 2 do for z = pos.z - 2, pos.z + 2 do
for y = pos.y - 2, pos.y + 2 do for y = pos.y - 2, pos.y + 2 do
@ -333,7 +338,7 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
if cid ~= c_air then if cid ~= c_air then
data[vi] = destroy(drops, p, cid, c_air, c_fire, data[vi] = destroy(drops, p, cid, c_air, c_fire,
on_blast_queue, on_construct_queue, on_blast_queue, on_construct_queue,
ignore_protection, ignore_on_blast) ignore_protection, ignore_on_blast, owner)
end end
end end
vi = vi + 1 vi = vi + 1
@ -375,16 +380,26 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
queued_data.fn(queued_data.pos) queued_data.fn(queued_data.pos)
end end
minetest.log("action", "TNT owned by " .. owner .. " detonated at " ..
minetest.pos_to_string(pos) .. " with radius " .. radius)
return drops, radius return drops, radius
end end
function tnt.boom(pos, def) function tnt.boom(pos, def)
def = def or {}
def.radius = def.radius or 1
def.damage_radius = def.damage_radius or def.radius * 2
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if not def.explode_center then
minetest.set_node(pos, {name = "tnt:boom"})
end
minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64}) minetest.sound_play("tnt_explode", {pos = pos, gain = 1.5, max_hear_distance = 2*64})
minetest.set_node(pos, {name = "tnt:boom"})
local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection, local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection,
def.ignore_on_blast) def.ignore_on_blast, owner, def.explode_center)
-- append entity drops -- append entity drops
local damage_radius = (radius / def.radius) * def.damage_radius local damage_radius = (radius / math.max(1, def.radius)) * def.damage_radius
entity_physics(pos, damage_radius, drops) entity_physics(pos, damage_radius, drops)
if not def.disable_drops then if not def.disable_drops then
eject_drops(drops, pos, radius) eject_drops(drops, pos, radius)
@ -400,12 +415,6 @@ minetest.register_node("tnt:boom", {
walkable = false, walkable = false,
drop = "", drop = "",
groups = {dig_immediate = 3}, groups = {dig_immediate = 3},
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.4)
end,
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
-- unaffected by explosions -- unaffected by explosions
on_blast = function() end, on_blast = function() end,
}) })
@ -508,17 +517,17 @@ minetest.register_node("tnt:gunpowder_burning", {
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
for dx = -1, 1 do for dx = -1, 1 do
for dz = -1, 1 do for dz = -1, 1 do
for dy = -1, 1 do if math.abs(dx) + math.abs(dz) == 1 then
if not (dx == 0 and dz == 0) then for dy = -1, 1 do
tnt.burn({ tnt.burn({
x = pos.x + dx, x = pos.x + dx,
y = pos.y + dy, y = pos.y + dy,
z = pos.z + dz, z = pos.z + dz,
}) })
end
end end
end end
end end
end
minetest.remove_node(pos) minetest.remove_node(pos)
end, end,
-- unaffected by explosions -- unaffected by explosions
@ -579,9 +588,16 @@ function tnt.register_tnt(def)
is_ground_content = false, is_ground_content = false,
groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5}, groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5},
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
if placer:is_player() then
local meta = minetest.get_meta(pos)
meta:set_string("owner", placer:get_player_name())
end
end,
on_punch = function(pos, node, puncher) on_punch = function(pos, node, puncher)
if puncher:get_wielded_item():get_name() == "default:torch" then if puncher:get_wielded_item():get_name() == "default:torch" then
minetest.set_node(pos, {name = name .. "_burning"}) minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
minetest.log("action", puncher:get_player_name() .. minetest.log("action", puncher:get_player_name() ..
" ignites " .. node.name .. " at " .. " ignites " .. node.name .. " at " ..
minetest.pos_to_string(pos)) minetest.pos_to_string(pos))
@ -600,10 +616,12 @@ function tnt.register_tnt(def)
} }
}, },
on_burn = function(pos) on_burn = function(pos)
minetest.set_node(pos, {name = name .. "_burning"}) minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
end, end,
on_ignite = function(pos, igniter) on_ignite = function(pos, igniter)
minetest.set_node(pos, {name = name .. "_burning"}) minetest.swap_node(pos, {name = name .. "_burning"})
minetest.registered_nodes[name .. "_burning"].on_construct(pos)
end, end,
}) })
end end