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

@ -40,7 +40,7 @@ Beds API
* `beds.kick_players()` Forces all players to leave bed * `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 * `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping
###Bed definition ### Bed definition
{ {
description = "Simple Bed", description = "Simple Bed",
@ -87,9 +87,9 @@ The doors mod allows modders to register custom doors and trapdoors.
`doors.get(pos)` `doors.get(pos)`
* `pos` A position as a table, e.g `{x = 1, y = 1, z = 1}` * `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 * Returns an ObjectRef to a door, or nil if the position does not contain a door
###Methods ### Methods
:open(player) -- Open the door object, returns if door was opened :open(player) -- Open the door object, returns if door was opened
:close(player) -- Close the door object, returns if door was closed :close(player) -- Close the door object, returns if door was closed
@ -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 has the permissions needed to open this door. If omitted then no
permission checks are performed. permission checks are performed.
###Door definition ### Door definition
description = "Door description", description = "Door description",
inventory_image = "mod_door_inv.png", 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 sound_close = sound play for close door, -- optional
protected = false, -- If true, only placer can open the door (locked for others) protected = false, -- If true, only placer can open the door (locked for others)
###Trapdoor definition ### Trapdoor definition
description = "Trapdoor description", description = "Trapdoor description",
inventory_image = "mod_trapdoor_inv.png", 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 sound_close = sound play for close door, -- optional
protected = false, -- If true, only placer can open the door (locked for others) protected = false, -- If true, only placer can open the door (locked for others)
###Fence gate definition ### Fence gate definition
description = "Wooden Fence Gate", description = "Wooden Fence Gate",
texture = "default_wood.png", texture = "default_wood.png",
@ -135,6 +135,7 @@ The doors mod allows modders to register custom doors and trapdoors.
Fence API Fence API
--------- ---------
Allows creation of new fences with "fencelike" drawtype. Allows creation of new fences with "fencelike" drawtype.
`default.register_fence(name, item definition)` `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 nodedef fields here except drawtype. The fence group will always be added
for this node. for this node.
###fence definition ### fence definition
name = "default:fence_wood", name = "default:fence_wood",
description = "Wooden Fence", 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}, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
#Walls API Walls API
--------- ---------
The walls API allows easy addition of stone auto-connecting wall nodes. The walls API allows easy addition of stone auto-connecting wall nodes.
walls.register(name, desc, texture, mat, sounds) 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)` `farming.register_plant(name, Plant definition)`
* Register a new growing plant, see [#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 description = "", -- Description of seed item
@ -204,11 +206,115 @@ The farming API allows you to easily register plants and hoes.
Fire API Fire API
-------- --------
New node def property:
`on_burn(pos)` `on_burn(pos)`
* Called when fire attempts to remove a burning node. * Called when fire attempts to remove a burning node.
* `pos` Position of the 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 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}" * `subname`: used for nodename. Result: "xpanes:subname" and "xpanes:subname_{2..15}"
* `def`: See [#Pane definition] * `def`: See [#Pane definition]
###Pane definition ### Pane definition
{ {
textures = {"texture_Bottom_top", "texture_left_right", "texture_front_back"}, -- More tiles aren't supported 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. * Any of the fields of the returned table may be nil.
* player: PlayerRef * player: PlayerRef
###Model Definition ### Model Definition
{ {
animation_speed = 30, -- Default animation speed, in FPS. 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 them based on groups. You can select any group of groups, based on your need for
amount of colors. amount of colors.
###Color groups ### Color groups
Base 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'}, recipe = {'<mod>:item_no_color', 'group:basecolor_yellow'},
}) })
###Color lists ### Color lists
* `dye.basecolors` are an array containing the names of available base colors * `dye.basecolors` are an array containing the names of available base colors

View file

@ -18,8 +18,9 @@
# 'permanent flame' nodes will remain with either setting # 'permanent flame' nodes will remain with either setting
#disable_fire = false #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 #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 # Whether the TNT mod should be enabled
#enable_tnt = <true in singleplayer, false in multiplayer> #enable_tnt = <true in singleplayer, false in multiplayer>

View file

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

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

View file

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

View file

@ -144,7 +144,6 @@ BlockMen (CC BY-SA 3.0):
default_mineral_mese.png default_mineral_mese.png
default_meselamp.png default_meselamp.png
bubble.png bubble.png
heart.png
gui_*.png gui_*.png
sofar (CC BY-SA 3.0): sofar (CC BY-SA 3.0):
@ -222,3 +221,6 @@ Mito551 (sounds) (CC BY-SA):
default_dirt_footstep.1.ogg default_dirt_footstep.1.ogg
default_dirt_footstep.2.ogg default_dirt_footstep.2.ogg
default_glass_footstep.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", inventory_image = "default_paper.png",
}) })
local lpp = 14 -- Lines per book's page
local function book_on_use(itemstack, user) local function book_on_use(itemstack, user)
local player_name = user:get_player_name() local player_name = user:get_player_name()
local data = minetest.deserialize(itemstack:get_metadata()) local data = minetest.deserialize(itemstack:get_metadata())
local formspec, title, text, owner = "", "", "", player_name 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 if data then
title = data.title title = data.title
text = data.text text = data.text
owner = data.owner owner = data.owner
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
lines[#lines+1] = str
end
if data.page then if data.page then
page = data.page page = data.page
page_max = data.page_max 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
end end
@ -44,8 +53,8 @@ local function book_on_use(itemstack, user)
"tablecolumns[color;text]" .. "tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[0.4,0;7,0.5;title;#FFFF00," .. minetest.formspec_escape(title) .. "]" .. "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( "textarea[0.5,1.5;7.5,7;;" ..
(cpp * page) - cpp, cpp * page)) .. ";]" .. minetest.formspec_escape(string ~= "" and string or text) .. ";]" ..
"button[2.4,7.6;0.8,0.8;book_prev;<]" .. "button[2.4,7.6;0.8,0.8;book_prev;<]" ..
"label[3.2,7.7;Page " .. page .. " of " .. page_max .. "]" .. "label[3.2,7.7;Page " .. page .. " of " .. page_max .. "]" ..
"button[4.9,7.6;0.8,0.8;book_next;>]" "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 if not data then data = {} end
data.title = fields.title data.title = fields.title
data.text = fields.text data.text = fields.text
data.text_len = fields.text:len() data.text_len = #data.text
data.page = 1 data.page = 1
data.chars_per_page = 650 data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
data.page_max = math.ceil(data.text_len / data.chars_per_page)
data.owner = player:get_player_name() data.owner = player:get_player_name()
local data_str = minetest.serialize(data) 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) stack:set_metadata(data_str)
end end
player:set_wielded_item(stack)
elseif fields.book_next or fields.book_prev then elseif fields.book_next or fields.book_prev then
local data = minetest.deserialize(stack:get_metadata()) local data = minetest.deserialize(stack:get_metadata())
if not data.page then return end 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) stack:set_metadata(data_str)
book_on_use(stack, player) book_on_use(stack, player)
end end
player:set_wielded_item(stack)
end) end)
minetest.register_craftitem("default:book", { minetest.register_craftitem("default:book", {

View file

@ -49,6 +49,18 @@ function default.node_sound_sand_defaults(table)
return table return table
end 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) function default.node_sound_wood_defaults(table)
table = table or {} table = table or {}
table.footstep = table.footstep 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 -- 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({ minetest.register_abm({
nodenames = {"default:dirt"}, 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, interval = 6,
chance = 67, chance = 67,
catch_up = false, catch_up = false,
action = function(pos, node) 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 above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name if (minetest.get_node_light(above) or 0) < 13 then
local nodedef = minetest.registered_nodes[name] return
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"})
end 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
end end
}) })
-- --
-- Grass and dry grass removed in darkness -- Grass and dry grass removed in darkness
-- --
minetest.register_abm({ 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, interval = 8,
chance = 50, chance = 50,
catch_up = false, catch_up = false,

View file

@ -90,66 +90,6 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
return stack:get_count() return stack:get_count()
end end
--
-- Node definitions
--
minetest.register_node("default:furnace", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_front.png"
},
paramtype2 = "facedir",
groups = {cracky=2},
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,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
minetest.register_node("default:furnace_active", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png",
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}
},
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
groups = {cracky=2, not_in_creative_inventory=1},
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,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
--
-- ABM
--
local function swap_node(pos, name) local function swap_node(pos, name)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if node.name == name then if node.name == name then
@ -159,11 +99,7 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node) minetest.swap_node(pos, node)
end end
minetest.register_abm({ local function furnace_node_timer(pos, elapsed)
nodenames = {"default:furnace", "default:furnace_active"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
-- --
-- Inizialize metadata -- Inizialize metadata
-- --
@ -172,19 +108,7 @@ minetest.register_abm({
local src_time = meta:get_float("src_time") or 0 local src_time = meta:get_float("src_time") or 0
local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
--
-- Inizialize inventory
--
local inv = meta:get_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 srclist = inv:get_list("src")
local fuellist = inv:get_list("fuel") local fuellist = inv:get_list("fuel")
local dstlist = inv:get_list("dst") local dstlist = inv:get_list("dst")
@ -235,7 +159,6 @@ minetest.register_abm({
fuel_totaltime = fuel.time fuel_totaltime = fuel.time
fuel_time = 0 fuel_time = 0
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
@ -264,17 +187,24 @@ minetest.register_abm({
local fuel_state = "Empty" local fuel_state = "Empty"
local active = "inactive " local active = "inactive "
local result = false
if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then
active = "active " active = "active "
local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100) local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
fuel_state = fuel_percent .. "%" fuel_state = fuel_percent .. "%"
formspec = active_formspec(fuel_percent, item_percent) formspec = active_formspec(fuel_percent, item_percent)
swap_node(pos, "default:furnace_active") swap_node(pos, "default:furnace_active")
-- make sure timer restarts automatically
result = true
else else
if not fuellist[1]:is_empty() then if not fuellist[1]:is_empty() then
fuel_state = "0%" fuel_state = "0%"
end end
swap_node(pos, "default:furnace") swap_node(pos, "default:furnace")
-- stop timer on the inactive furnace
local timer = minetest.get_node_timer(pos)
timer:stop()
end end
local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")" local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")"
@ -287,5 +217,94 @@ minetest.register_abm({
meta:set_float("src_time", src_time) meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec) meta:set_string("formspec", formspec)
meta:set_string("infotext", infotext) meta:set_string("infotext", infotext)
return result
end
--
-- Node definitions
--
minetest.register_node("default:furnace", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_front.png"
},
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
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, 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,
}) })
minetest.register_node("default:furnace_active", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png",
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}
},
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
groups = {cracky=2, not_in_creative_inventory=1},
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,
})

Binary file not shown.

Binary file not shown.

View file

@ -353,10 +353,7 @@ minetest.register_node("default:gravel", {
description = "Gravel", description = "Gravel",
tiles = {"default_gravel.png"}, tiles = {"default_gravel.png"},
groups = {crumbly = 2, falling_node = 1}, groups = {crumbly = 2, falling_node = 1},
sounds = default.node_sound_dirt_defaults({ sounds = default.node_sound_gravel_defaults(),
footstep = {name = "default_gravel_footstep", gain = 0.5},
dug = {name = "default_gravel_footstep", gain = 1.0},
}),
drop = { drop = {
max_items = 1, max_items = 1,
items = { items = {
@ -947,7 +944,7 @@ minetest.register_node("default:junglegrass", {
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, walkable = false,
buildable_to = true, 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(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
@ -968,7 +965,7 @@ minetest.register_node("default:grass_1", {
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, walkable = false,
buildable_to = true, 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(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
@ -998,7 +995,7 @@ for i = 2, 5 do
buildable_to = true, buildable_to = true,
drop = "default:grass_1", drop = "default:grass_1",
groups = {snappy = 3, flora = 1, attached_node = 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(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
@ -1019,7 +1016,8 @@ minetest.register_node("default:dry_grass_1", {
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, walkable = false,
buildable_to = true, 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(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
@ -1047,8 +1045,8 @@ for i = 2, 5 do
sunlight_propagates = true, sunlight_propagates = true,
walkable = false, walkable = false,
buildable_to = true, buildable_to = true,
groups = {snappy = 3, flammable = 3, flora = 1, groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1,
attached_node = 1, not_in_creative_inventory=1}, not_in_creative_inventory=1, dry_grass = 1},
drop = "default:dry_grass_1", drop = "default:dry_grass_1",
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
selection_box = { selection_box = {
@ -1473,6 +1471,13 @@ minetest.register_node("default:chest", {
" 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,
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", { minetest.register_node("default:chest_locked", {
@ -1596,6 +1601,13 @@ minetest.register_node("default:bookshelf", {
minetest.log("action", player:get_player_name() .. minetest.log("action", player:get_player_name() ..
" takes stuff from bookshelf at " .. minetest.pos_to_string(pos)) " takes stuff from bookshelf at " .. minetest.pos_to_string(pos))
end, 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) local function register_sign(material, desc, def)
@ -1757,7 +1769,7 @@ minetest.register_node("default:obsidian_glass", {
is_ground_content = false, is_ground_content = false,
sunlight_propagates = true, sunlight_propagates = true,
sounds = default.node_sound_glass_defaults(), 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 end
-- replace old doors of this type automatically -- 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"}, nodenames = {name.."_b_1", name.."_b_2"},
interval = 7.0, action = function(pos, node)
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local l = tonumber(node.name:sub(-1)) local l = tonumber(node.name:sub(-1))
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local h = meta:get_int("right") + 1 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}, fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
}, },
fertility = def.fertility, 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) on_place = function(itemstack, placer, pointed_thing)
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname) return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname)
end end,
}) })
-- Register harvest -- Register harvest

View file

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

View file

@ -71,19 +71,17 @@ end
-- Flower spread -- Flower spread
-- Public function to enable override by mods
minetest.register_abm({ function flowers.flower_spread(pos, node)
nodenames = {"group:flora"},
neighbors = {"default:dirt_with_grass", "default:desert_sand"},
interval = 13,
chance = 96,
action = function(pos, node)
pos.y = pos.y - 1 pos.y = pos.y - 1
local under = minetest.get_node(pos) local under = minetest.get_node(pos)
pos.y = pos.y + 1 pos.y = pos.y + 1
if under.name == "default:desert_sand" then if under.name == "default:desert_sand" then
minetest.set_node(pos, {name = "default:dry_shrub"}) minetest.set_node(pos, {name = "default:dry_shrub"})
elseif under.name ~= "default:dirt_with_grass" then return
elseif under.name ~= "default:dirt_with_grass" and
under.name ~= "default:dirt_with_dry_grass" then
return return
end end
@ -92,18 +90,14 @@ minetest.register_abm({
return return
end end
local pos0 = {x = pos.x - 4, y = pos.y - 4, z = pos.z - 4} local pos0 = vector.subtract(pos, 4)
local pos1 = {x = pos.x + 4, y = pos.y + 4, z = pos.z + 4} local pos1 = vector.add(pos, 4)
if #minetest.find_nodes_in_area(pos0, pos1, "group:flora_block") > 0 then if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 3 then
return return
end end
local flowers = minetest.find_nodes_in_area(pos0, pos1, "group:flora") local seedling = minetest.find_nodes_in_area_under_air(pos0, pos1,
if #flowers > 3 then {"default:dirt_with_grass", "default:dirt_with_dry_grass"})
return
end
local seedling = minetest.find_nodes_in_area(pos0, pos1, "default:dirt_with_grass")
if #seedling > 0 then if #seedling > 0 then
seedling = seedling[math.random(#seedling)] seedling = seedling[math.random(#seedling)]
seedling.y = seedling.y + 1 seedling.y = seedling.y + 1
@ -111,10 +105,18 @@ minetest.register_abm({
if not light or light < 13 then if not light or light < 13 then
return return
end end
if minetest.get_node(seedling).name == "air" then
minetest.set_node(seedling, {name = node.name}) minetest.set_node(seedling, {name = node.name})
end end
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, end,
}) })
@ -161,7 +163,9 @@ minetest.register_node("flowers:mushroom_brown", {
} }
}) })
-- mushroom spread and death
-- Mushroom spread and death
minetest.register_abm({ minetest.register_abm({
nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"},
interval = 11, interval = 11,
@ -169,17 +173,15 @@ minetest.register_abm({
action = function(pos, node) action = function(pos, node)
if minetest.get_node_light(pos, nil) == 15 then if minetest.get_node_light(pos, nil) == 15 then
minetest.remove_node(pos) 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 return
end 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 return
end end
local node_under = minetest.get_node_or_nil({x = random.x, local node_under = minetest.get_node_or_nil({x = random.x,
@ -187,15 +189,19 @@ minetest.register_abm({
if not node_under then if not node_under then
return return
end end
if minetest.get_item_group(node_under.name, "soil") ~= 0 and
minetest.get_node_light(pos, nil) <= 9 and if (minetest.get_item_group(node_under.name, "soil") ~= 0 or
minetest.get_node_light(random, nil) <= 9 then 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}) minetest.set_node(random, {name = node.name})
end end
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_brown", "flowers:mushroom_brown")
minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red") minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red")
minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown") minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown")
@ -220,6 +226,7 @@ minetest.register_node("flowers:waterlily", {
sunlight_propagates = true, sunlight_propagates = true,
groups = {snappy = 3, flower = 1}, groups = {snappy = 3, flower = 1},
sounds = default.node_sound_leaves_defaults(), sounds = default.node_sound_leaves_defaults(),
node_placement_prediction = "",
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.46875, 0.5} 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} 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 pos = pointed_thing.above
local node = minetest.get_node(pointed_thing.under).name local node = minetest.get_node(pointed_thing.under).name
local def = minetest.registered_nodes[node] 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 if def and def.liquidtype == "source" and minetest.get_item_group(node, "water") > 0 then
if not minetest.is_protected(pos, player_name) then
minetest.set_node(pos, {name = "flowers:waterlily", param2 = math.random(0, 3)}) 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
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") 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) -- loss probabilities array (one in X will be lost)
local loss_prob = {} local loss_prob = {}
@ -52,23 +43,22 @@ local function eject_drops(drops, pos, radius)
local drop_pos = vector.new(pos) local drop_pos = vector.new(pos)
for _, item in pairs(drops) do for _, item in pairs(drops) do
local count = item:get_count() local count = item:get_count()
local max = item:get_stack_max()
if count > max then
item:set_count(max)
end
while count > 0 do while count > 0 do
if count < max then local take = math.max(1,math.min(radius * radius,
item:set_count(count) item:get_count(),
end item:get_stack_max()))
rand_pos(pos, drop_pos, radius) 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 if obj then
obj:get_luaentity().collect = true obj:get_luaentity().collect = true
obj:setacceleration({x=0, y=-10, z=0}) obj:setacceleration({x = 0, y = -10, z = 0})
obj:setvelocity({x=math.random(-3, 3), y=10, obj:setvelocity({x = math.random(-3, 3),
z=math.random(-3, 3)}) y = math.random(0, 10),
z = math.random(-3, 3)})
end end
count = count - max count = count - take
end end
end end
end end
@ -88,27 +78,27 @@ local function add_drop(drops, item)
end end
end end
local fire_node = {name="fire:basic_flame"}
local function destroy(drops, pos, cid) local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_protection, ignore_on_blast)
if minetest.is_protected(pos, "") then if not ignore_protection and minetest.is_protected(npos, "") then
return return cid
end end
local def = cid_data[cid] local def = cid_data[cid]
if def and def.on_blast then
def.on_blast(vector.new(pos), 1) if not def then
return return c_air
end elseif not ignore_on_blast and def.on_blast then
if def and def.flammable then on_blast_queue[#on_blast_queue + 1] = {pos = vector.new(npos), on_blast = def.on_blast}
minetest.set_node(pos, fire_node) return cid
elseif def.flammable then
return c_fire
else else
minetest.remove_node(pos)
if def then
local node_drops = minetest.get_node_drops(def.name, "") local node_drops = minetest.get_node_drops(def.name, "")
for _, item in ipairs(node_drops) do for _, item in ipairs(node_drops) do
add_drop(drops, item) add_drop(drops, item)
end end
end return c_air
end end
end end
@ -125,61 +115,179 @@ local function calc_velocity(pos1, pos2, old_vel, power)
-- Add old velocity -- Add old velocity
vel = vector.add(vel, old_vel) 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 return vel
end end
local function entity_physics(pos, radius) local function entity_physics(pos, radius, drops)
-- Make the damage radius larger than the destruction radius
radius = radius * 2
local objs = minetest.get_objects_inside_radius(pos, radius) local objs = minetest.get_objects_inside_radius(pos, radius)
for _, obj in pairs(objs) do for _, obj in pairs(objs) do
local obj_pos = obj:getpos() local obj_pos = obj:getpos()
local obj_vel = obj:getvelocity()
local dist = math.max(1, vector.distance(pos, obj_pos)) local dist = math.max(1, vector.distance(pos, obj_pos))
if obj_vel ~= nil then local damage = (4 / dist) * radius
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:setvelocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10)) obj_vel, radius * 10))
end end
if do_damage then
local damage = (4 / dist) * radius if not obj:get_armor_groups().immortal then
obj:set_hp(obj:get_hp() - damage) 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
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({ minetest.add_particlespawner({
amount = 128, amount = 64,
time = 1, time = 0.5,
minpos = vector.subtract(pos, radius / 2), minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2), maxpos = vector.add(pos, radius / 2),
minvel = {x=-20, y=-20, z=-20}, minvel = {x = -10, y = -10, z = -10},
maxvel = {x=20, y=20, z=20}, maxvel = {x = 10, y = 10, z = 10},
minacc = vector.new(), minacc = vector.new(),
maxacc = vector.new(), maxacc = vector.new(),
minexptime = 1, minexptime = 1,
maxexptime = 3, maxexptime = 2.5,
minsize = 8, minsize = radius * 3,
maxsize = 16, maxsize = radius * 5,
texture = "tnt_smoke.png", 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 end
local function burn(pos) function tnt.burn(pos)
local name = minetest.get_node(pos).name local name = minetest.get_node(pos).name
if name == "tnt:tnt" then local group = minetest.get_item_group(name, "tnt")
minetest.sound_play("tnt_ignite", {pos=pos}) if group > 0 then
minetest.set_node(pos, {name="tnt:tnt_burning"}) 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)
elseif name == "tnt:gunpowder" then elseif name == "tnt:gunpowder" then
minetest.sound_play("tnt_gunpowder_burning", {pos=pos, gain=2}) minetest.set_node(pos, {name = "tnt:gunpowder_burning"})
minetest.set_node(pos, {name="tnt:gunpowder_burning"})
minetest.get_node_timer(pos):start(1)
end end
end end
local function explode(pos, radius) local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast)
local pos = vector.round(pos) 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 vm = VoxelManip()
local pr = PseudoRandom(os.time()) local pr = PseudoRandom(os.time())
local p1 = vector.subtract(pos, radius) local p1 = vector.subtract(pos, radius)
@ -189,22 +297,21 @@ local function explode(pos, radius)
local data = vm:get_data() local data = vm:get_data()
local drops = {} local drops = {}
local p = {} local on_blast_queue = {}
local c_air = minetest.get_content_id("air")
local c_fire = minetest.get_content_id("fire:basic_flame")
for z = -radius, radius do for z = -radius, radius do
for y = -radius, radius do for y = -radius, radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z) local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
for x = -radius, radius do for x = -radius, radius do
if (x * x) + (y * y) + (z * z) <= local r = vector.length(vector.new(x, y, z))
(radius * radius) + pr:next(-radius, radius) then if (radius * radius) / (r * r) >= (pr:next(80, 125) / 100) then
local cid = data[vi] local cid = data[vi]
p.x = pos.x + x local p = {x = pos.x + x, y = pos.y + y, z = pos.z + z}
p.y = pos.y + y
p.z = pos.z + z
if cid ~= c_air then 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
end end
vi = vi + 1 vi = vi + 1
@ -212,71 +319,61 @@ local function explode(pos, radius)
end end
end end
return drops 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
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
return drops, radius
end end
function tnt.boom(pos, def)
local function boom(pos) 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"})
minetest.set_node(pos, {name="tnt:boom"}) local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection,
minetest.get_node_timer(pos):start(0.5) def.ignore_on_blast)
-- append entity drops
local drops = explode(pos, radius) local damage_radius = (radius / def.radius) * def.damage_radius
entity_physics(pos, radius) entity_physics(pos, damage_radius, drops)
if not def.disable_drops then
eject_drops(drops, pos, radius) eject_drops(drops, pos, radius)
add_effects(pos, radius) end
add_effects(pos, radius, drops)
end 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"})
end
end
end,
on_blast = function(pos, intensity)
burn(pos)
end,
--mesecons = {effector = {action_on = boom}},
})
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,
})
minetest.register_node("tnt:boom", { minetest.register_node("tnt:boom", {
drawtype = "plantlike", drawtype = "airlike",
tiles = {"tnt_boom.png"},
light_source = default.LIGHT_MAX, light_source = default.LIGHT_MAX,
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) on_timer = function(pos, elapsed)
minetest.remove_node(pos) minetest.remove_node(pos)
end, end,
@ -298,18 +395,18 @@ minetest.register_node("tnt:gunpowder", {
type = "fixed", type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, 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(), sounds = default.node_sound_leaves_defaults(),
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
if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then if(minetest.check_player_privs(puncher:get_player_name(), {trusted_player=true})) then
burn(pos) tnt.burn(pos)
end end
end end
end, end,
on_blast = function(pos, intensity) on_blast = function(pos, intensity)
burn(pos) tnt.burn(pos)
end, 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}, fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
}, },
drop = "", 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(), sounds = default.node_sound_leaves_defaults(),
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 for dy = -1, 1 do
if not (dx == 0 and dz == 0) then if not (dx == 0 and dz == 0) then
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,
@ -380,14 +477,18 @@ minetest.register_node("tnt:gunpowder_burning", {
end, end,
-- unaffected by explosions -- unaffected by explosions
on_blast = function() end, 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({ minetest.register_abm({
nodenames = {"tnt:tnt", "tnt:gunpowder"}, nodenames = {"group:tnt", "tnt:gunpowder"},
neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"}, neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"},
interval = 4, interval = 4,
chance = 1, chance = 1,
action = burn, action = tnt.burn,
}) })
minetest.register_craft({ minetest.register_craft({
@ -404,3 +505,82 @@ minetest.register_craft({
{"", "group:wood", ""} {"", "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", { minetest.register_node("vessels:shelf", {
description = "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, is_ground_content = false,
groups = {choppy=3,oddly_breakable_by_hand=2,flammable=3}, groups = {choppy=3,oddly_breakable_by_hand=2,flammable=3},
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
@ -48,6 +48,13 @@ minetest.register_node("vessels:shelf", {
minetest.log("action", player:get_player_name() .. minetest.log("action", player:get_player_name() ..
" takes stuff from vessels shelf at ".. minetest.pos_to_string(pos)) " takes stuff from vessels shelf at ".. minetest.pos_to_string(pos))
end, 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({ minetest.register_craft({