fix mergeconflicts

This commit is contained in:
tchncs 2016-05-02 10:16:25 +02:00
commit f4fc4294b7
22 changed files with 824 additions and 405 deletions

View file

@ -39,8 +39,8 @@ Beds API
* `beds.read_spawns() ` Returns a table containing players respawn positions
* `beds.kick_players()` Forces all players to leave bed
* `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping
###Bed definition
### Bed definition
{
description = "Simple Bed",
@ -85,12 +85,12 @@ The doors mod allows modders to register custom doors and trapdoors.
* `def` See [#Fence gate definition]
`doors.get(pos)`
* `pos` A position as a table, e.g `{x = 1, y = 1, z = 1}`
* Returns an ObjecRef to a door, or nil if the position does not contain a door
###Methods
* Returns an ObjectRef to a door, or nil if the position does not contain a door
### Methods
:open(player) -- Open the door object, returns if door was opened
:close(player) -- Close the door object, returns if door was closed
:toggle(player) -- Toggle the door state, returns if state was toggled
@ -101,7 +101,7 @@ The doors mod allows modders to register custom doors and trapdoors.
has the permissions needed to open this door. If omitted then no
permission checks are performed.
###Door definition
### Door definition
description = "Door description",
inventory_image = "mod_door_inv.png",
@ -113,7 +113,7 @@ The doors mod allows modders to register custom doors and trapdoors.
sound_close = sound play for close door, -- optional
protected = false, -- If true, only placer can open the door (locked for others)
###Trapdoor definition
### Trapdoor definition
description = "Trapdoor description",
inventory_image = "mod_trapdoor_inv.png",
@ -125,7 +125,7 @@ The doors mod allows modders to register custom doors and trapdoors.
sound_close = sound play for close door, -- optional
protected = false, -- If true, only placer can open the door (locked for others)
###Fence gate definition
### Fence gate definition
description = "Wooden Fence Gate",
texture = "default_wood.png",
@ -135,6 +135,7 @@ The doors mod allows modders to register custom doors and trapdoors.
Fence API
---------
Allows creation of new fences with "fencelike" drawtype.
`default.register_fence(name, item definition)`
@ -144,7 +145,7 @@ Allows creation of new fences with "fencelike" drawtype.
nodedef fields here except drawtype. The fence group will always be added
for this node.
###fence definition
### fence definition
name = "default:fence_wood",
description = "Wooden Fence",
@ -153,8 +154,9 @@ Allows creation of new fences with "fencelike" drawtype.
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
sounds = default.node_sound_wood_defaults(),
#Walls API
Walls API
---------
The walls API allows easy addition of stone auto-connecting wall nodes.
walls.register(name, desc, texture, mat, sounds)
@ -175,7 +177,7 @@ The farming API allows you to easily register plants and hoes.
`farming.register_plant(name, Plant definition)`
* Register a new growing plant, see [#Plant definition]
###Hoe Definition
### Hoe Definition
{
@ -190,7 +192,7 @@ The farming API allows you to easily register plants and hoes.
}
}
###Plant definition
### Plant definition
{
description = "", -- Description of seed item
@ -204,11 +206,115 @@ The farming API allows you to easily register plants and hoes.
Fire API
--------
New node def property:
`on_burn(pos)`
* Called when fire attempts to remove a burning node.
* `pos` Position of the burning node.
Give Initial Stuff API
----------------------
`give_initial_stuff.give(player)`
^ Give initial stuff to "player"
`give_initial_stuff.add(stack)`
^ Add item to the initial stuff
^ Stack can be an ItemStack or a item name eg: "default:dirt 99"
^ Can be called after the game has loaded
`give_initial_stuff.clear()`
^ Removes all items from the initial stuff
^ Can be called after the game has loaded
`give_initial_stuff.get_list()`
^ returns list of item stacks
`give_initial_stuff.set_list(list)`
^ List of initial items with numeric indices.
`give_initial_stuff.add_from_csv(str)`
^ str is a comma separated list of initial stuff
^ Adds items to the list of items to be given
TNT API
----------
`tnt.register_tnt(definition)`
^ Register a new type of tnt.
* `name` The name of the node. If no prefix is given `tnt` is used.
* `description` A description for your TNT.
* `radius` The radius within which the TNT can destroy nodes. The default is 3.
* `damage_radius` The radius within which the TNT can damage players and mobs. By default it is twice the `radius`.
* `disable_drops` Disable drops. By default it is set to false.
* `ignore_protection` Don't check `minetest.is_protected` before removing a node.
* `ignore_on_blast` Don't call `on_blast` even if a node has one.
* `tiles` Textures for node
* `side` Side tiles. By default the name of the tnt with a suffix of `_side.png`.
* `top` Top tile. By default the name of the tnt with a suffix of `_top.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".
`tnt.boom(position, definition)`
^ Create an explosion.
* `position` The center of explosion.
* `definition` The TNT definion as passed to `tnt.register`
`tnt.burn(position)`
^ Ignite TNT at position
To make dropping items from node inventories easier, you can use the
following helper function from 'default':
default.get_inventory_drops(pos, inventory, drops)
^ Return drops from node inventory "inventory" in drops.
* `pos` - the node position
* `inventory` - the name of the inventory (string)
* `drops` - an initialized list
The function returns no values. The drops are returned in the `drops`
parameter, and drops is not reinitialized so you can call it several
times in a row to add more inventory items to it.
`on_blast` callbacks:
Both nodedefs and entitydefs can provide an `on_blast()` callback
`nodedef.on_blast(pos, intensity)`
^ Allow drop and node removal overriding
* `pos` - node position
* `intensity` - TNT explosion measure. larger or equal to 1.0
^ Should return a list of drops (e.g. {"default:stone"})
^ Should perform node removal itself. If callback exists in the nodedef
^ then the TNT code will not destroy this node.
`entitydef.on_blast(luaobj, damage)`
^ Allow TNT effects on entities to be overridden
* `luaobj` - LuaEntityRef of the entity
* `damage` - suggested HP damage value
^ Should return a list of (bool do_damage, bool do_knockback, table drops)
* `do_damage` - if true then TNT mod wil damage the entity
* `do_knockback` - if true then TNT mod will knock the entity away
* `drops` - a list of drops, e.g. {"wool:red"}
Screwdriver API
---------------
@ -270,7 +376,7 @@ Creates panes that automatically connect to each other
* `subname`: used for nodename. Result: "xpanes:subname" and "xpanes:subname_{2..15}"
* `def`: See [#Pane definition]
###Pane definition
### Pane definition
{
textures = {"texture_Bottom_top", "texture_left_right", "texture_front_back"}, -- More tiles aren't supported
@ -356,7 +462,7 @@ default.player_get_animation(player)
* Any of the fields of the returned table may be nil.
* player: PlayerRef
###Model Definition
### Model Definition
{
animation_speed = 30, -- Default animation speed, in FPS.
@ -395,7 +501,7 @@ To make recipes that will work with any dye ever made by anybody, define
them based on groups. You can select any group of groups, based on your need for
amount of colors.
###Color groups
### Color groups
Base color groups:
@ -450,7 +556,7 @@ Example of one shapeless recipe using a color group:
recipe = {'<mod>:item_no_color', 'group:basecolor_yellow'},
})
###Color lists
### Color lists
* `dye.basecolors` are an array containing the names of available base colors
@ -465,7 +571,7 @@ Trees
* `default.grow_jungle_tree(pos)`
* Grows a mgv6 jungletree at pos
* `default.grow_pine_tree(pos)`
* `default.grow_pine_tree(pos)`
* Grows a mgv6 pinetree at pos
* `default.grow_new_apple_tree(pos)`

View file

@ -18,8 +18,9 @@
# 'permanent flame' nodes will remain with either setting
#disable_fire = false
# Whether steel tools, torches and cobblestone should be given to new players
# Whether the stuff in initial_stuff should be given to new players
#give_initial_stuff = false
#initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,default:torch 99,default:cobble 99
# Whether the TNT mod should be enabled
#enable_tnt = <true in singleplayer, false in multiplayer>

View file

@ -41,10 +41,12 @@ function beds.save_spawns()
if not beds.spawn then
return
end
local data = {}
local output = io.open(org_file, "w")
for i, v in pairs(beds.spawn) do
output:write(v.x .. " " .. v.y .. " " .. v.z .. " " .. i .. "\n")
for k, v in pairs(beds.spawn) do
table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, k))
end
output:write(table.concat(data))
io.close(output)
end

@ -1 +0,0 @@
Subproject commit ffaf921ce4a5644c62eced2754bffe1a41950e73

View file

@ -123,6 +123,8 @@ minetest.register_node("bones:bones", {
return true
end
end,
on_blast = function(pos)
end,
})
local function may_replace(pos, player)

View file

@ -144,7 +144,6 @@ BlockMen (CC BY-SA 3.0):
default_mineral_mese.png
default_meselamp.png
bubble.png
heart.png
gui_*.png
sofar (CC BY-SA 3.0):
@ -222,3 +221,6 @@ Mito551 (sounds) (CC BY-SA):
default_dirt_footstep.1.ogg
default_dirt_footstep.2.ogg
default_glass_footstep.ogg
KevDoy (CC BY-SA 3.0)
heart.png

View file

@ -11,21 +11,30 @@ minetest.register_craftitem("default:paper", {
inventory_image = "default_paper.png",
})
local lpp = 14 -- Lines per book's page
local function book_on_use(itemstack, user)
local player_name = user:get_player_name()
local data = minetest.deserialize(itemstack:get_metadata())
local formspec, title, text, owner = "", "", "", player_name
local page, page_max, cpp = 1, 1, 650
local page, page_max, lines, string = 1, 1, {}, ""
if data then
title = data.title
text = data.text
owner = data.owner
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
lines[#lines+1] = str
end
if data.page then
page = data.page
page_max = data.page_max
cpp = data.chars_per_page
for i = ((lpp * page) - lpp) + 1, lpp * page do
if not lines[i] then break end
string = string .. lines[i] .. "\n"
end
end
end
@ -44,8 +53,8 @@ local function book_on_use(itemstack, user)
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[0.4,0;7,0.5;title;#FFFF00," .. minetest.formspec_escape(title) .. "]" ..
"textarea[0.5,1.5;7.5,7;;" .. minetest.formspec_escape(text:sub(
(cpp * page) - cpp, cpp * page)) .. ";]" ..
"textarea[0.5,1.5;7.5,7;;" ..
minetest.formspec_escape(string ~= "" and string or text) .. ";]" ..
"button[2.4,7.6;0.8,0.8;book_prev;<]" ..
"label[3.2,7.7;Page " .. page .. " of " .. page_max .. "]" ..
"button[4.9,7.6;0.8,0.8;book_next;>]"
@ -76,10 +85,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not data then data = {} end
data.title = fields.title
data.text = fields.text
data.text_len = fields.text:len()
data.text_len = #data.text
data.page = 1
data.chars_per_page = 650
data.page_max = math.ceil(data.text_len / data.chars_per_page)
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
data.owner = player:get_player_name()
local data_str = minetest.serialize(data)
@ -94,8 +102,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
stack:set_metadata(data_str)
end
player:set_wielded_item(stack)
elseif fields.book_next or fields.book_prev then
local data = minetest.deserialize(stack:get_metadata())
if not data.page then return end
@ -116,6 +122,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
stack:set_metadata(data_str)
book_on_use(stack, player)
end
player:set_wielded_item(stack)
end)
minetest.register_craftitem("default:book", {

View file

@ -49,6 +49,18 @@ function default.node_sound_sand_defaults(table)
return table
end
function default.node_sound_gravel_defaults(table)
table = table or {}
table.footstep = table.footstep or
{name = "default_gravel_footstep", gain = 0.5}
table.dug = table.dug or
{name = "default_gravel_footstep", gain = 1.0}
table.place = table.place or
{name = "default_place_node", gain = 1.0}
default.node_sound_defaults(table)
return table
end
function default.node_sound_wood_defaults(table)
table = table or {}
table.footstep = table.footstep or
@ -110,6 +122,21 @@ minetest.register_abm({
})
--
-- optimized helper to put all items in an inventory into a drops list
--
function default.get_inventory_drops(pos, inventory, drops)
local inv = minetest.get_meta(pos):get_inventory()
local n = #drops
for i = 1, inv:get_size(inventory) do
local stack = inv:get_stack(inventory, i)
if stack:get_count() > 0 then
drops[n+1] = stack:to_table()
n = n + 1
end
end
end
--
-- Papyrus and cactus growing
--
@ -342,38 +369,71 @@ minetest.register_abm({
--
-- Grass growing on well-lit dirt
-- Convert dirt to something that fits the environment
--
minetest.register_abm({
nodenames = {"default:dirt"},
neighbors = {"air"},
neighbors = {
"default:dirt_with_grass",
"default:dirt_with_dry_grass",
"default:dirt_with_snow",
"group:grass",
"group:dry_grass",
"default:snow",
},
interval = 6,
chance = 67,
catch_up = false,
action = function(pos, node)
-- Most likely case, half the time it's too dark for this.
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
if nodedef and (nodedef.sunlight_propagates or nodedef.paramtype == "light") and
nodedef.liquidtype == "none" and
(minetest.get_node_light(above) or 0) >= 13 then
if name == "default:snow" or name == "default:snowblock" then
minetest.set_node(pos, {name = "default:dirt_with_snow"})
else
minetest.set_node(pos, {name = "default:dirt_with_grass"})
if (minetest.get_node_light(above) or 0) < 13 then
return
end
-- Look for likely neighbors.
local p2 = minetest.find_node_near(pos, 1, {"default:dirt_with_grass",
"default:dirt_with_dry_grass", "default:dirt_with_snow"})
if p2 then
-- But the node needs to be under air in this case.
local n2 = minetest.get_node(above)
if n2 and n2.name == "air" then
local n3 = minetest.get_node(p2)
minetest.set_node(pos, {name = n3.name})
return
end
end
-- Anything on top?
local n2 = minetest.get_node(above)
if not n2 then
return
end
local name = n2.name
-- Snow check is cheapest, so comes first.
if name == "default:snow" then
minetest.set_node(pos, {name = "default:dirt_with_snow"})
-- Most likely case first.
elseif minetest.get_item_group(name, "grass") ~= 0 then
minetest.set_node(pos, {name = "default:dirt_with_grass"})
elseif minetest.get_item_group(name, "dry_grass") ~= 0 then
minetest.set_node(pos, {name = "default:dirt_with_dry_grass"})
end
end
})
--
-- Grass and dry grass removed in darkness
--
minetest.register_abm({
nodenames = {"default:dirt_with_grass", "default:dirt_with_dry_grass"},
nodenames = {
"default:dirt_with_grass",
"default:dirt_with_dry_grass",
"default:dirt_with_snow",
},
interval = 8,
chance = 50,
catch_up = false,

View file

@ -90,6 +90,137 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
return stack:get_count()
end
local function swap_node(pos, name)
local node = minetest.get_node(pos)
if node.name == name then
return
end
node.name = name
minetest.swap_node(pos, node)
end
local function furnace_node_timer(pos, elapsed)
--
-- Inizialize metadata
--
local meta = minetest.get_meta(pos)
local fuel_time = meta:get_float("fuel_time") or 0
local src_time = meta:get_float("src_time") or 0
local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
local inv = meta:get_inventory()
local srclist = inv:get_list("src")
local fuellist = inv:get_list("fuel")
local dstlist = inv:get_list("dst")
--
-- Cooking
--
-- Check if we have cookable content
local cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
local cookable = true
if cooked.time == 0 then
cookable = false
end
-- Check if we have enough fuel to burn
if fuel_time < fuel_totaltime then
-- The furnace is currently active and has enough fuel
fuel_time = fuel_time + 1
-- If there is a cookable item then check if it is ready yet
if cookable then
src_time = src_time + 1
if src_time >= cooked.time then
-- Place result in dst list if possible
if inv:room_for_item("dst", cooked.item) then
inv:add_item("dst", cooked.item)
inv:set_stack("src", 1, aftercooked.items[1])
src_time = 0
end
end
end
else
-- Furnace ran out of fuel
if cookable then
-- We need to get new fuel
local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fuel.time == 0 then
-- No valid fuel in fuel list
fuel_totaltime = 0
fuel_time = 0
src_time = 0
else
-- Take fuel from fuel list
inv:set_stack("fuel", 1, afterfuel.items[1])
fuel_totaltime = fuel.time
fuel_time = 0
end
else
-- We don't need to get new fuel since there is no cookable item
fuel_totaltime = 0
fuel_time = 0
src_time = 0
end
end
--
-- Update formspec, infotext and node
--
local formspec = inactive_formspec
local item_state = ""
local item_percent = 0
if cookable then
item_percent = math.floor(src_time / cooked.time * 100)
item_state = item_percent .. "%"
else
if srclist[1]:is_empty() then
item_state = "Empty"
else
item_state = "Not cookable"
end
end
local fuel_state = "Empty"
local active = "inactive "
local result = false
if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then
active = "active "
local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
fuel_state = fuel_percent .. "%"
formspec = active_formspec(fuel_percent, item_percent)
swap_node(pos, "default:furnace_active")
-- make sure timer restarts automatically
result = true
else
if not fuellist[1]:is_empty() then
fuel_state = "0%"
end
swap_node(pos, "default:furnace")
-- stop timer on the inactive furnace
local timer = minetest.get_node_timer(pos)
timer:stop()
end
local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")"
--
-- Set meta values
--
meta:set_float("fuel_totaltime", fuel_totaltime)
meta:set_float("fuel_time", fuel_time)
meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec)
meta:set_string("infotext", infotext)
return result
end
--
-- Node definitions
--
@ -106,10 +237,40 @@ minetest.register_node("default:furnace", {
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
on_timer = furnace_node_timer,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", inactive_formspec)
local inv = meta:get_inventory()
inv:set_size('src', 1)
inv:set_size('fuel', 1)
inv:set_size('dst', 4)
end,
on_metadata_inventory_move = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(1.0)
end,
on_metadata_inventory_put = function(pos)
-- start timer function, it will sort out whether furnace can burn or not.
local timer = minetest.get_node_timer(pos)
timer:start(1.0)
end,
on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "src", drops)
default.get_inventory_drops(pos, "fuel", drops)
default.get_inventory_drops(pos, "dst", drops)
drops[#drops+1] = "default:furnace"
minetest.remove_node(pos)
return drops
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
@ -138,154 +299,12 @@ minetest.register_node("default:furnace_active", {
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_timer = furnace_node_timer,
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
--
-- ABM
--
local function swap_node(pos, name)
local node = minetest.get_node(pos)
if node.name == name then
return
end
node.name = name
minetest.swap_node(pos, node)
end
minetest.register_abm({
nodenames = {"default:furnace", "default:furnace_active"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
--
-- Inizialize metadata
--
local meta = minetest.get_meta(pos)
local fuel_time = meta:get_float("fuel_time") or 0
local src_time = meta:get_float("src_time") or 0
local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
--
-- Inizialize inventory
--
local inv = meta:get_inventory()
for listname, size in pairs({
src = 1,
fuel = 1,
dst = 4,
}) do
if inv:get_size(listname) ~= size then
inv:set_size(listname, size)
end
end
local srclist = inv:get_list("src")
local fuellist = inv:get_list("fuel")
local dstlist = inv:get_list("dst")
--
-- Cooking
--
-- Check if we have cookable content
local cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
local cookable = true
if cooked.time == 0 then
cookable = false
end
-- Check if we have enough fuel to burn
if fuel_time < fuel_totaltime then
-- The furnace is currently active and has enough fuel
fuel_time = fuel_time + 1
-- If there is a cookable item then check if it is ready yet
if cookable then
src_time = src_time + 1
if src_time >= cooked.time then
-- Place result in dst list if possible
if inv:room_for_item("dst", cooked.item) then
inv:add_item("dst", cooked.item)
inv:set_stack("src", 1, aftercooked.items[1])
src_time = 0
end
end
end
else
-- Furnace ran out of fuel
if cookable then
-- We need to get new fuel
local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fuel.time == 0 then
-- No valid fuel in fuel list
fuel_totaltime = 0
fuel_time = 0
src_time = 0
else
-- Take fuel from fuel list
inv:set_stack("fuel", 1, afterfuel.items[1])
fuel_totaltime = fuel.time
fuel_time = 0
end
else
-- We don't need to get new fuel since there is no cookable item
fuel_totaltime = 0
fuel_time = 0
src_time = 0
end
end
--
-- Update formspec, infotext and node
--
local formspec = inactive_formspec
local item_state = ""
local item_percent = 0
if cookable then
item_percent = math.floor(src_time / cooked.time * 100)
item_state = item_percent .. "%"
else
if srclist[1]:is_empty() then
item_state = "Empty"
else
item_state = "Not cookable"
end
end
local fuel_state = "Empty"
local active = "inactive "
if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then
active = "active "
local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
fuel_state = fuel_percent .. "%"
formspec = active_formspec(fuel_percent, item_percent)
swap_node(pos, "default:furnace_active")
else
if not fuellist[1]:is_empty() then
fuel_state = "0%"
end
swap_node(pos, "default:furnace")
end
local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")"
--
-- Set meta values
--
meta:set_float("fuel_totaltime", fuel_totaltime)
meta:set_float("fuel_time", fuel_time)
meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec)
meta:set_string("infotext", infotext)
end,
})

Binary file not shown.

Binary file not shown.

View file

@ -353,10 +353,7 @@ minetest.register_node("default:gravel", {
description = "Gravel",
tiles = {"default_gravel.png"},
groups = {crumbly = 2, falling_node = 1},
sounds = default.node_sound_dirt_defaults({
footstep = {name = "default_gravel_footstep", gain = 0.5},
dug = {name = "default_gravel_footstep", gain = 1.0},
}),
sounds = default.node_sound_gravel_defaults(),
drop = {
max_items = 1,
items = {
@ -947,7 +944,7 @@ minetest.register_node("default:junglegrass", {
sunlight_propagates = true,
walkable = false,
buildable_to = true,
groups = {snappy = 3, flora = 1, attached_node = 1},
groups = {snappy = 3, flora = 1, attached_node = 1, grass = 1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
@ -968,7 +965,7 @@ minetest.register_node("default:grass_1", {
sunlight_propagates = true,
walkable = false,
buildable_to = true,
groups = {snappy = 3, flora = 1, attached_node = 1},
groups = {snappy = 3, flora = 1, attached_node = 1, grass = 1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
@ -998,7 +995,7 @@ for i = 2, 5 do
buildable_to = true,
drop = "default:grass_1",
groups = {snappy = 3, flora = 1, attached_node = 1,
not_in_creative_inventory = 1},
not_in_creative_inventory = 1, grass = 1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
@ -1019,7 +1016,8 @@ minetest.register_node("default:dry_grass_1", {
sunlight_propagates = true,
walkable = false,
buildable_to = true,
groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1},
groups = {snappy = 3, flammable = 3, flora = 1,
attached_node = 1, dry_grass = 1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
@ -1047,8 +1045,8 @@ for i = 2, 5 do
sunlight_propagates = true,
walkable = false,
buildable_to = true,
groups = {snappy = 3, flammable = 3, flora = 1,
attached_node = 1, not_in_creative_inventory=1},
groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1,
not_in_creative_inventory=1, dry_grass = 1},
drop = "default:dry_grass_1",
sounds = default.node_sound_leaves_defaults(),
selection_box = {
@ -1473,6 +1471,13 @@ minetest.register_node("default:chest", {
" takes " .. stack:get_name() ..
" from chest at " .. minetest.pos_to_string(pos))
end,
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,
})
minetest.register_node("default:chest_locked", {
@ -1596,6 +1601,13 @@ minetest.register_node("default:bookshelf", {
minetest.log("action", player:get_player_name() ..
" takes stuff from bookshelf at " .. minetest.pos_to_string(pos))
end,
on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "books", drops)
drops[#drops+1] = "default:bookshelf"
minetest.remove_node(pos)
return drops
end,
})
local function register_sign(material, desc, def)
@ -1757,7 +1769,7 @@ minetest.register_node("default:obsidian_glass", {
is_ground_content = false,
sunlight_propagates = true,
sounds = default.node_sound_glass_defaults(),
groups = {cracky = 3, oddly_breakable_by_hand = 3},
groups = {cracky = 3},
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 B

After

Width:  |  Height:  |  Size: 377 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 771 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -203,11 +203,10 @@ function doors.register(name, def)
end
-- replace old doors of this type automatically
minetest.register_abm({
minetest.register_lbm({
name = ":doors:replace_" .. name:gsub(":", "_"),
nodenames = {name.."_b_1", name.."_b_2"},
interval = 7.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
action = function(pos, node)
local l = tonumber(node.name:sub(-1))
local meta = minetest.get_meta(pos)
local h = meta:get_int("right") + 1

View file

@ -220,9 +220,14 @@ farming.register_plant = function(name, def)
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
fertility = def.fertility,
sounds = default.node_sound_dirt_defaults({
dug = {name = "default_grass_footstep", gain = 0.2},
place = {name = "default_place_node", gain = 0.25},
}),
on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname)
end
end,
})
-- Register harvest

View file

@ -263,7 +263,7 @@ else
minetest.remove_node(p0)
return
end
if math.random(1, 4) == 1 then
if math.random(1, 3) == 1 then
-- remove flammable nodes around flame
local node = minetest.get_node(p)
local def = minetest.registered_nodes[node.name]

View file

@ -71,50 +71,52 @@ end
-- Flower spread
-- Public function to enable override by mods
minetest.register_abm({
nodenames = {"group:flora"},
neighbors = {"default:dirt_with_grass", "default:desert_sand"},
interval = 13,
chance = 96,
action = function(pos, node)
pos.y = pos.y - 1
local under = minetest.get_node(pos)
pos.y = pos.y + 1
if under.name == "default:desert_sand" then
minetest.set_node(pos, {name = "default:dry_shrub"})
elseif under.name ~= "default:dirt_with_grass" then
return
end
function flowers.flower_spread(pos, node)
pos.y = pos.y - 1
local under = minetest.get_node(pos)
pos.y = pos.y + 1
if under.name == "default:desert_sand" then
minetest.set_node(pos, {name = "default:dry_shrub"})
return
elseif under.name ~= "default:dirt_with_grass" and
under.name ~= "default:dirt_with_dry_grass" then
return
end
local light = minetest.get_node_light(pos)
local light = minetest.get_node_light(pos)
if not light or light < 13 then
return
end
local pos0 = vector.subtract(pos, 4)
local pos1 = vector.add(pos, 4)
if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 3 then
return
end
local seedling = minetest.find_nodes_in_area_under_air(pos0, pos1,
{"default:dirt_with_grass", "default:dirt_with_dry_grass"})
if #seedling > 0 then
seedling = seedling[math.random(#seedling)]
seedling.y = seedling.y + 1
light = minetest.get_node_light(seedling)
if not light or light < 13 then
return
end
minetest.set_node(seedling, {name = node.name})
end
end
local pos0 = {x = pos.x - 4, y = pos.y - 4, z = pos.z - 4}
local pos1 = {x = pos.x + 4, y = pos.y + 4, z = pos.z + 4}
if #minetest.find_nodes_in_area(pos0, pos1, "group:flora_block") > 0 then
return
end
local flowers = minetest.find_nodes_in_area(pos0, pos1, "group:flora")
if #flowers > 3 then
return
end
local seedling = minetest.find_nodes_in_area(pos0, pos1, "default:dirt_with_grass")
if #seedling > 0 then
seedling = seedling[math.random(#seedling)]
seedling.y = seedling.y + 1
light = minetest.get_node_light(seedling)
if not light or light < 13 then
return
end
if minetest.get_node(seedling).name == "air" then
minetest.set_node(seedling, {name = node.name})
end
end
minetest.register_abm({
nodenames = {"group:flora"},
neighbors = {"default:dirt_with_grass", "default:dirt_with_dry_grass",
"default:desert_sand"},
interval = 13,
chance = 96,
action = function(...)
flowers.flower_spread(...)
end,
})
@ -161,7 +163,9 @@ minetest.register_node("flowers:mushroom_brown", {
}
})
-- mushroom spread and death
-- Mushroom spread and death
minetest.register_abm({
nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"},
interval = 11,
@ -169,17 +173,15 @@ minetest.register_abm({
action = function(pos, node)
if minetest.get_node_light(pos, nil) == 15 then
minetest.remove_node(pos)
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 then
return
end
if random_node.name ~= "air" then
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,
@ -187,15 +189,19 @@ minetest.register_abm({
if not node_under then
return
end
if minetest.get_item_group(node_under.name, "soil") ~= 0 and
minetest.get_node_light(pos, nil) <= 9 and
minetest.get_node_light(random, nil) <= 9 then
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
})
-- these old mushroom related nodes can be simplified now
-- These old mushroom related nodes can be simplified now
minetest.register_alias("flowers:mushroom_spores_brown", "flowers:mushroom_brown")
minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red")
minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown")
@ -220,6 +226,7 @@ minetest.register_node("flowers:waterlily", {
sunlight_propagates = true,
groups = {snappy = 3, flower = 1},
sounds = default.node_sound_leaves_defaults(),
node_placement_prediction = "",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.46875, 0.5}
@ -229,12 +236,22 @@ minetest.register_node("flowers:waterlily", {
fixed = {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}
},
on_place = function(_, _, pointed_thing)
on_place = function(itemstack, placer, pointed_thing)
local pos = pointed_thing.above
local node = minetest.get_node(pointed_thing.under).name
local def = minetest.registered_nodes[node]
local player_name = placer:get_player_name()
if def and def.liquidtype == "source" and minetest.get_item_group(node, "water") > 0 then
minetest.set_node(pos, {name = "flowers:waterlily", param2 = math.random(0, 3)})
if not minetest.is_protected(pos, player_name) then
minetest.set_node(pos, {name = "flowers:waterlily", param2 = math.random(0, 3)})
else
minetest.chat_send_player(player_name, "This area is protected")
end
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
return itemstack
end
end
end
})

View file

@ -1,15 +1,6 @@
-- TNT will need privilege!
tnt = {}
core.register_privilege("trusted_player", "special grantings, used for tnt for example")
---We want to use it on server, so this is commented
-- Default to enabled in singleplayer and disabled in multiplayer
-- local singleplayer = minetest.is_singleplayer()
-- local setting = minetest.setting_getbool("enable_tnt")
-- if (not singleplayer and setting ~= true) or
-- (singleplayer and setting == false) then
-- return
-- end
-- loss probabilities array (one in X will be lost)
local loss_prob = {}
@ -52,23 +43,22 @@ local function eject_drops(drops, pos, radius)
local drop_pos = vector.new(pos)
for _, item in pairs(drops) do
local count = item:get_count()
local max = item:get_stack_max()
if count > max then
item:set_count(max)
end
while count > 0 do
if count < max then
item:set_count(count)
end
local take = math.max(1,math.min(radius * radius,
item:get_count(),
item:get_stack_max()))
rand_pos(pos, drop_pos, radius)
local obj = minetest.add_item(drop_pos, item)
local dropitem = ItemStack(item)
dropitem:set_count(take)
local obj = minetest.add_item(drop_pos, dropitem)
if obj then
obj:get_luaentity().collect = true
obj:setacceleration({x=0, y=-10, z=0})
obj:setvelocity({x=math.random(-3, 3), y=10,
z=math.random(-3, 3)})
obj:setacceleration({x = 0, y = -10, z = 0})
obj:setvelocity({x = math.random(-3, 3),
y = math.random(0, 10),
z = math.random(-3, 3)})
end
count = count - max
count = count - take
end
end
end
@ -88,27 +78,27 @@ local function add_drop(drops, item)
end
end
local fire_node = {name="fire:basic_flame"}
local function destroy(drops, pos, cid)
if minetest.is_protected(pos, "") then
return
local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_protection, ignore_on_blast)
if not ignore_protection and minetest.is_protected(npos, "") then
return cid
end
local def = cid_data[cid]
if def and def.on_blast then
def.on_blast(vector.new(pos), 1)
return
end
if def and def.flammable then
minetest.set_node(pos, fire_node)
if not def then
return c_air
elseif not ignore_on_blast and def.on_blast then
on_blast_queue[#on_blast_queue + 1] = {pos = vector.new(npos), on_blast = def.on_blast}
return cid
elseif def.flammable then
return c_fire
else
minetest.remove_node(pos)
if def then
local node_drops = minetest.get_node_drops(def.name, "")
for _, item in ipairs(node_drops) do
add_drop(drops, item)
end
local node_drops = minetest.get_node_drops(def.name, "")
for _, item in ipairs(node_drops) do
add_drop(drops, item)
end
return c_air
end
end
@ -125,61 +115,179 @@ local function calc_velocity(pos1, pos2, old_vel, power)
-- Add old velocity
vel = vector.add(vel, old_vel)
-- randomize it a bit
vel = vector.add(vel, {
x = math.random() - 0.5,
y = math.random() - 0.5,
z = math.random() - 0.5,
})
-- Limit to terminal velocity
dist = vector.length(vel)
if dist > 250 then
vel = vector.divide(vel, dist / 250)
end
return vel
end
local function entity_physics(pos, radius)
-- Make the damage radius larger than the destruction radius
radius = radius * 2
local function entity_physics(pos, radius, drops)
local objs = minetest.get_objects_inside_radius(pos, radius)
for _, obj in pairs(objs) do
local obj_pos = obj:getpos()
local obj_vel = obj:getvelocity()
local dist = math.max(1, vector.distance(pos, obj_pos))
if obj_vel ~= nil then
obj:setvelocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10))
end
local damage = (4 / dist) * radius
obj:set_hp(obj:get_hp() - damage)
if obj:is_player() then
-- currently the engine has no method to set
-- player velocity. See #2960
-- instead, we knock the player back 1.0 node, and slightly upwards
local dir = vector.normalize(vector.subtract(obj_pos, pos))
local moveoff = vector.multiply(dir, dist + 1.0)
local newpos = vector.add(pos, moveoff)
local newpos = vector.add(newpos, {x = 0, y = 0.2, z = 0})
obj:setpos(newpos)
obj:set_hp(obj:get_hp() - damage)
else
local do_damage = true
local do_knockback = true
local entity_drops = {}
local luaobj = obj:get_luaentity()
local objdef = minetest.registered_entities[luaobj.name]
if objdef and objdef.on_blast then
do_damage, do_knockback, entity_drops = objdef.on_blast(luaobj, damage)
end
if do_knockback then
local obj_vel = obj:getvelocity()
obj:setvelocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10))
end
if do_damage then
if not obj:get_armor_groups().immortal then
obj:punch(obj, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = damage},
}, nil)
end
end
for _, item in ipairs(entity_drops) do
add_drop(drops, item)
end
end
end
end
local function add_effects(pos, radius)
local function add_effects(pos, radius, drops)
minetest.add_particle({
pos = pos,
velocity = vector.new(),
acceleration = vector.new(),
expirationtime = 0.4,
size = radius * 10,
collisiondetection = false,
vertical = false,
texture = "tnt_boom.png",
})
minetest.add_particlespawner({
amount = 128,
time = 1,
amount = 64,
time = 0.5,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-20, y=-20, z=-20},
maxvel = {x=20, y=20, z=20},
minvel = {x = -10, y = -10, z = -10},
maxvel = {x = 10, y = 10, z = 10},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 1,
maxexptime = 3,
minsize = 8,
maxsize = 16,
maxexptime = 2.5,
minsize = radius * 3,
maxsize = radius * 5,
texture = "tnt_smoke.png",
})
-- we just dropped some items. Look at the items entities and pick
-- one of them to use as texture
local texture = "tnt_blast.png" --fallback texture
local most = 0
for name, stack in pairs(drops) do
local count = stack:get_count()
if count > most then
most = count
local def = minetest.registered_nodes[name]
if def and def.tiles and def.tiles[1] then
texture = def.tiles[1]
end
end
end
minetest.add_particlespawner({
amount = 64,
time = 0.1,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x = -3, y = 0, z = -3},
maxvel = {x = 3, y = 5, z = 3},
minacc = {x = 0, y = -10, z = 0},
maxacc = {x = 0, y = -10, z = 0},
minexptime = 0.8,
maxexptime = 2.0,
minsize = radius * 0.66,
maxsize = radius * 2,
texture = texture,
collisiondetection = true,
})
end
local function burn(pos)
function tnt.burn(pos)
local name = minetest.get_node(pos).name
if name == "tnt:tnt" then
minetest.sound_play("tnt_ignite", {pos=pos})
minetest.set_node(pos, {name="tnt:tnt_burning"})
local group = minetest.get_item_group(name, "tnt")
if group > 0 then
minetest.sound_play("tnt_ignite", {pos = pos})
minetest.set_node(pos, {name = name .. "_burning"})
minetest.get_node_timer(pos):start(1)
elseif name == "tnt:gunpowder" then
minetest.sound_play("tnt_gunpowder_burning", {pos=pos, gain=2})
minetest.set_node(pos, {name="tnt:gunpowder_burning"})
minetest.get_node_timer(pos):start(1)
minetest.set_node(pos, {name = "tnt:gunpowder_burning"})
end
end
local function explode(pos, radius)
local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
local pos = vector.round(pos)
-- scan for adjacent TNT nodes first, and enlarge the explosion
local vm1 = VoxelManip()
local p1 = vector.subtract(pos, 2)
local p2 = vector.add(pos, 2)
local minp, maxp = vm1:read_from_map(p1, p2)
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm1:get_data()
local count = 0
local c_tnt = minetest.get_content_id("tnt:tnt")
local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning")
local c_tnt_boom = minetest.get_content_id("tnt:boom")
local c_air = minetest.get_content_id("air")
for z = pos.z - 2, pos.z + 2 do
for y = pos.y - 2, pos.y + 2 do
local vi = a:index(pos.x - 2, y, z)
for x = pos.x - 2, pos.x + 2 do
local cid = data[vi]
if cid == c_tnt or cid == c_tnt_boom or cid == c_tnt_burning then
count = count + 1
data[vi] = c_air
end
vi = vi + 1
end
end
end
vm1:set_data(data)
vm1:write_to_map()
-- recalculate new radius
radius = math.floor(radius * math.pow(count, 1/3))
-- perform the explosion
local vm = VoxelManip()
local pr = PseudoRandom(os.time())
local p1 = vector.subtract(pos, radius)
@ -189,22 +297,21 @@ local function explode(pos, radius)
local data = vm:get_data()
local drops = {}
local p = {}
local c_air = minetest.get_content_id("air")
local on_blast_queue = {}
local c_fire = minetest.get_content_id("fire:basic_flame")
for z = -radius, radius do
for y = -radius, radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
for x = -radius, radius do
if (x * x) + (y * y) + (z * z) <=
(radius * radius) + pr:next(-radius, radius) then
local r = vector.length(vector.new(x, y, z))
if (radius * radius) / (r * r) >= (pr:next(80, 125) / 100) then
local cid = data[vi]
p.x = pos.x + x
p.y = pos.y + y
p.z = pos.z + z
local p = {x = pos.x + x, y = pos.y + y, z = pos.z + z}
if cid ~= c_air then
destroy(drops, p, cid)
data[vi] = destroy(drops, p, cid, c_air, c_fire,
on_blast_queue, ignore_protection,
ignore_on_blast)
end
end
vi = vi + 1
@ -212,71 +319,61 @@ local function explode(pos, radius)
end
end
return drops
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
vm:update_liquids()
-- call nodeupdate for everything within 1.5x blast radius
for z = -radius * 1.5, radius * 1.5 do
for x = -radius * 1.5, radius * 1.5 do
for y = -radius * 1.5, radius * 1.5 do
local s = vector.add(pos, {x = x, y = y, z = z})
local r = vector.distance(pos, s)
if r / radius < 1.4 then
nodeupdate(s)
end
end
end
end
local function boom(pos)
minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
minetest.set_node(pos, {name="tnt:boom"})
minetest.get_node_timer(pos):start(0.5)
local drops = explode(pos, radius)
entity_physics(pos, radius)
eject_drops(drops, pos, radius)
add_effects(pos, radius)
end
minetest.register_node("tnt:tnt", {
description = "TNT",
tiles = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png"},
is_ground_content = false,
groups = {dig_immediate=2},
sounds = default.node_sound_wood_defaults(),
on_punch = function(pos, node, puncher)
if puncher:get_wielded_item():get_name() == "default:torch" then
if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then
minetest.sound_play("tnt_ignite", {pos=pos})
minetest.set_node(pos, {name="tnt:tnt_burning"})
for _, data in ipairs(on_blast_queue) do
local dist = math.max(1, vector.distance(data.pos, pos))
local intensity = (radius * radius) / (dist * dist)
local node_drops = data.on_blast(data.pos, intensity)
if node_drops then
for _, item in ipairs(node_drops) do
add_drop(drops, item)
end
end
end,
on_blast = function(pos, intensity)
burn(pos)
end,
--mesecons = {effector = {action_on = boom}},
})
end
minetest.register_node("tnt:tnt_burning", {
tiles = {
{
name = "tnt_top_burning_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1,
}
},
"tnt_bottom.png", "tnt_side.png"},
light_source = 5,
drop = "",
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
minetest.get_node_timer(pos):start(4)
end,
on_timer = boom,
-- unaffected by explosions
on_blast = function() end,
})
return drops, radius
end
function tnt.boom(pos, def)
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,
def.ignore_on_blast)
-- append entity drops
local damage_radius = (radius / def.radius) * def.damage_radius
entity_physics(pos, damage_radius, drops)
if not def.disable_drops then
eject_drops(drops, pos, radius)
end
add_effects(pos, radius, drops)
end
minetest.register_node("tnt:boom", {
drawtype = "plantlike",
tiles = {"tnt_boom.png"},
drawtype = "airlike",
light_source = default.LIGHT_MAX,
walkable = false,
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,
@ -298,18 +395,18 @@ minetest.register_node("tnt:gunpowder", {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {dig_immediate=2,attached_node=1,connect_to_raillike=minetest.raillike_group("gunpowder")},
groups = {dig_immediate = 2, attached_node = 1, connect_to_raillike = minetest.raillike_group("gunpowder")},
sounds = default.node_sound_leaves_defaults(),
on_punch = function(pos, node, puncher)
if puncher:get_wielded_item():get_name() == "default:torch" then
if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then
burn(pos)
end
end
if puncher:get_wielded_item():get_name() == "default:torch" then
if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then
tnt.burn(pos)
end
end
end,
on_blast = function(pos, intensity)
burn(pos)
tnt.burn(pos)
end,
})
@ -360,14 +457,14 @@ minetest.register_node("tnt:gunpowder_burning", {
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
drop = "",
groups = {dig_immediate=2,attached_node=1,connect_to_raillike=minetest.raillike_group("gunpowder")},
groups = {dig_immediate = 2, attached_node = 1, connect_to_raillike = minetest.raillike_group("gunpowder")},
sounds = default.node_sound_leaves_defaults(),
on_timer = function(pos, elapsed)
for dx = -1, 1 do
for dz = -1, 1 do
for dy = -1, 1 do
if not (dx == 0 and dz == 0) then
burn({
tnt.burn({
x = pos.x + dx,
y = pos.y + dy,
z = pos.z + dz,
@ -380,14 +477,18 @@ minetest.register_node("tnt:gunpowder_burning", {
end,
-- unaffected by explosions
on_blast = function() end,
on_construct = function(pos)
minetest.sound_play("tnt_gunpowder_burning", {pos = pos, gain = 2})
minetest.get_node_timer(pos):start(1)
end,
})
minetest.register_abm({
nodenames = {"tnt:tnt", "tnt:gunpowder"},
nodenames = {"group:tnt", "tnt:gunpowder"},
neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"},
interval = 4,
chance = 1,
action = burn,
action = tnt.burn,
})
minetest.register_craft({
@ -404,3 +505,82 @@ minetest.register_craft({
{"", "group:wood", ""}
}
})
function tnt.register_tnt(def)
local name = ""
if not def.name:find(':') then
name = "tnt:" .. def.name
else
name = def.name
def.name = def.name:match(":([%w_]+)")
end
if not def.tiles then def.tiles = {} end
local tnt_top = def.tiles.top or def.name .. "_top.png"
local tnt_bottom = def.tiles.bottom or def.name .. "_bottom.png"
local tnt_side = def.tiles.side or def.name .. "_side.png"
local tnt_burning = def.tiles.burning or def.name .. "_top_burning_animated.png"
if not def.damage_radius then def.damage_radius = def.radius * 2 end
minetest.register_node(":" .. name, {
description = def.description,
tiles = {tnt_top, tnt_bottom, tnt_side},
is_ground_content = false,
groups = {dig_immediate = 2, mesecon = 2, tnt = 1},
sounds = default.node_sound_wood_defaults(),
on_punch = function(pos, node, puncher)
if puncher:get_wielded_item():get_name() == "default:torch" then
if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then
minetest.set_node(pos, {name = name .. "_burning"})
end
end
end,
on_blast = function(pos, intensity)
minetest.after(0.1, function()
tnt.boom(pos, def)
end)
end,
--mesecons = {effector =
-- {action_on =
-- function(pos)
-- tnt.boom(pos, def)
-- end
-- }
--},
})
minetest.register_node(":" .. name .. "_burning", {
tiles = {
{
name = tnt_burning,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1,
}
},
tnt_bottom, tnt_side
},
light_source = 5,
drop = "",
sounds = default.node_sound_wood_defaults(),
groups = {falling_node = 1},
on_timer = function(pos, elapsed)
tnt.boom(pos, def)
end,
-- unaffected by explosions
on_blast = function() end,
on_construct = function(pos)
minetest.sound_play("tnt_ignite", {pos = pos})
minetest.get_node_timer(pos):start(4)
nodeupdate(pos)
end,
})
end
tnt.register_tnt({
name = "tnt:tnt",
description = "TNT",
radius = radius,
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

View file

@ -15,7 +15,7 @@ local vessels_shelf_formspec =
minetest.register_node("vessels:shelf", {
description = "Vessels shelf",
tiles = {"default_wood.png", "default_wood.png", "default_wood.png^vessels_shelf.png"},
tiles = {"default_wood.png", "default_wood.png", "vessels_shelf.png"},
is_ground_content = false,
groups = {choppy=3,oddly_breakable_by_hand=2,flammable=3},
sounds = default.node_sound_wood_defaults(),
@ -48,6 +48,13 @@ minetest.register_node("vessels:shelf", {
minetest.log("action", player:get_player_name() ..
" takes stuff from vessels shelf at ".. minetest.pos_to_string(pos))
end,
on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "vessels", drops)
drops[#drops+1] = "vessels:shelf"
minetest.remove_node(pos)
return drops
end,
})
minetest.register_craft({