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

@ -87,7 +87,7 @@ The doors mod allows modders to register custom doors and trapdoors.
`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
* Returns an ObjectRef to a door, or nil if the position does not contain a door
### Methods
@ -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)`
@ -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)
@ -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
---------------

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,66 +90,6 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
return stack:get_count()
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 node = minetest.get_node(pos)
if node.name == name then
@ -159,11 +99,7 @@ local function swap_node(pos, 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)
local function furnace_node_timer(pos, elapsed)
--
-- Inizialize metadata
--
@ -172,19 +108,7 @@ minetest.register_abm({
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")
@ -235,7 +159,6 @@ minetest.register_abm({
fuel_totaltime = fuel.time
fuel_time = 0
end
else
-- 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 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 .. ")"
@ -287,5 +217,94 @@ minetest.register_abm({
meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec)
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,
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",
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,19 +71,17 @@ 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)
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"})
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
end
@ -92,18 +90,14 @@ minetest.register_abm({
return
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
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 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")
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
@ -111,10 +105,18 @@ minetest.register_abm({
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,6 +173,7 @@ minetest.register_abm({
action = function(pos, node)
if minetest.get_node_light(pos, nil) == 15 then
minetest.remove_node(pos)
return
end
local random = {
x = pos.x + math.random(-2, 2),
@ -176,10 +181,7 @@ minetest.register_abm({
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
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
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,
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
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
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_vel, radius * 10))
end
local damage = (4 / dist) * radius
obj:set_hp(obj:get_hp() - damage)
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
local group = minetest.get_item_group(name, "tnt")
if group > 0 then
minetest.sound_play("tnt_ignite", {pos = pos})
minetest.set_node(pos, {name="tnt:tnt_burning"})
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)
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
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
local function boom(pos)
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"})
minetest.get_node_timer(pos):start(0.5)
local drops = explode(pos, radius)
entity_physics(pos, radius)
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)
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"})
add_effects(pos, radius, drops)
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", {
drawtype = "plantlike",
tiles = {"tnt_boom.png"},
drawtype = "airlike",
light_source = default.LIGHT_MAX,
walkable = false,
drop = "",
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,
@ -304,12 +401,12 @@ minetest.register_node("tnt:gunpowder", {
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)
tnt.burn(pos)
end
end
end,
on_blast = function(pos, intensity)
burn(pos)
tnt.burn(pos)
end,
})
@ -367,7 +464,7 @@ minetest.register_node("tnt:gunpowder_burning", {
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({