Compare commits

..

5 Commits

Author SHA1 Message Date
My favourite Minetest cheat clients are Dragonfire and Waspsaliva. 23f1c51912 Merge pull request 'ITEMS/mcl_farming: Convert correct floor node to dirt as gourd grows' (#231) from fix-gourd-farmland-dirtification into master
Reviewed-on: Mineclonia/Mineclonia#231
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-15 22:07:24 +00:00
Nils Dagsson Moskopp 4d02af8c94
Convert correct floor node to dirt as gourd grows
Before this patch, growing a gourd (e.g. melon, pumpkin) would always
convert a node west of the node below the stem to dirt if belonged to
the group “dirtifies_below_solid”. This happened because of a loop in
which the variables floorpos and floor were re-used without setting a
new value … therefore, both floorpos and floor were always containing
the last values set in a previous loop instead of the correct values.

This patch fixes the problem by setting both variables in both loops.
2022-01-13 07:29:57 +01:00
Li0n_2 7ede0ca79a Merge pull request 'Fix shearsy wool typo in GROUPS.md' (#229) from JosiahWI/Mineclonia:fix-groups-typo into master
Reviewed-on: Mineclonia/Mineclonia#229
Reviewed-by: Li0n_2 <li0n_2@noreply.git.minetest.land>
2022-01-12 21:19:10 +00:00
JosiahWI e2e7e15b39
fix one character typo in GROUPS.md 2022-01-12 11:09:07 -06:00
cora 93a0879b40 Merge pull request 'MISC/mcl_selftests: Do not crash if minetest.find_nodes_in_area() lies' (#214) from fix-selftest-crash into master
Reviewed-on: Mineclonia/Mineclonia#214
Reviewed-by: cora <cora@noreply.git.minetest.land>
2021-12-20 22:42:59 +00:00
13 changed files with 328 additions and 277 deletions

View File

@ -21,7 +21,7 @@ The basic digging time groups determine by which tools a node can be dug.
* `swordy=1`: Diggable by sword (any material), and this node is *not* a cobweb
* `swordy_cobweb=1`: Diggable by sword (any material), and this node is a cobweb
* `shearsy=1`: Diggable by shears, and this node is *not* wool
* `shearsy=wool=1`: Diggable by shears, and this node is wool
* `shearsy_wool=1`: Diggable by shears, and this node is wool
* `handy=1`: Breakable by hand and this node gives it useful drop when dug by hand. All nodes which are breakable by pickaxe, axe, shovel, sword or shears are also automatically breakable by hand, but not neccess
* `creative_breakable=1`: Block is breakable by hand in creative mode. This group is implied if the node belongs to any other digging group

View File

@ -1,66 +1,36 @@
mcl_weather.nether_dust = {}
mcl_weather.nether_dust.particlespawners = {}
mcl_weather.nether_dust.particles_count = 99
local psdef= {
amount = 150,
time = 0,
minpos = vector.new(-15,-15,-15),
maxpos =vector.new(15,15,15),
minvel = vector.new(-0.3,-0.15,-1),
maxvel = vector.new(0.3,0.15,0.3),
minacc = vector.new(-1,-0.4,-1),
maxacc = vector.new(1,0.4,1),
minexptime = 1,
maxexptime = 10,
minsize = 0.2,
maxsize = 0.7,
collisiondetection = false,
collision_removal = false,
object_collision = false,
vertical = false
}
local function check_player(player)
local name=player:get_player_name()
if mcl_worlds.has_dust(player:get_pos()) and not mcl_weather.nether_dust.particlespawners[name] then
return true
end
end
mcl_weather.nether_dust.add_particlespawners = function(player)
local name=player:get_player_name(name)
mcl_weather.nether_dust.particlespawners[name]={}
psdef.playername = name
psdef.attached = player
psdef.glow = math.random(0,minetest.LIGHT_MAX)
for i=1,3 do
psdef.texture="mcl_particles_nether_dust"..i..".png"
mcl_weather.nether_dust.particlespawners[name][i]=minetest.add_particlespawner(psdef)
-- calculates coordinates and draw particles for Nether dust
mcl_weather.nether_dust.add_dust_particles = function(player)
for i=mcl_weather.nether_dust.particles_count, 1,-1 do
local rpx, rpy, rpz = mcl_weather.get_random_pos_by_player_look_dir(player)
minetest.add_particle({
pos = {x = rpx, y = rpy - math.random(6, 18), z = rpz},
velocity = {x = math.random(-30,30)*0.01, y = math.random(-15,15)*0.01, z = math.random(-30,30)*0.01},
acceleration = {x = math.random(-50,50)*0.02, y = math.random(-20,20)*0.02, z = math.random(-50,50)*0.02},
expirationtime = 3,
size = math.random(6,20)*0.01,
collisiondetection = false,
object_collision = false,
vertical = false,
glow = math.random(0,minetest.LIGHT_MAX),
texture = "mcl_particles_nether_dust"..tostring(i%3+1)..".png",
playername = player:get_player_name()
})
end
end
mcl_weather.nether_dust.delete_particlespawners = function(player)
local name=player:get_player_name(name)
if mcl_weather.nether_dust.particlespawners[name] then
for i=1,3 do
minetest.delete_particlespawner(mcl_weather.nether_dust.particlespawners[name][i])
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer < 0.7 then return end
timer = 0
for _, player in ipairs(minetest.get_connected_players()) do
if not mcl_worlds.has_dust(player:get_pos()) then
return false
end
mcl_weather.nether_dust.particlespawners[name]=nil
end
end
mcl_worlds.register_on_dimension_change(function(player, dimension)
if check_player(player) then
return mcl_weather.nether_dust.add_particlespawners(player)
end
mcl_weather.nether_dust.delete_particlespawners(player)
end)
minetest.register_on_joinplayer(function(player)
if check_player(player) then
mcl_weather.nether_dust.add_particlespawners(player)
mcl_weather.nether_dust.add_dust_particles(player)
end
end)
minetest.register_on_leaveplayer(function(player)
mcl_weather.nether_dust.delete_particlespawners(player)
end)

View File

@ -82,7 +82,7 @@ local dispenserdef = {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -92,7 +92,7 @@ local dispenserdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
_mcl_blast_resistance = 3.5,
_mcl_hardness = 3.5,

View File

@ -55,7 +55,7 @@ local dropperdef = {
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -65,7 +65,7 @@ local dropperdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -53,7 +53,7 @@ local dropperdef = {
sounds = mcl_sounds.node_sound_stone_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1, inv:get_size("main") do
@ -63,7 +63,7 @@ local dropperdef = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -101,14 +101,14 @@ local function update_anvil_slots(meta)
end
local can_combine = mcl_enchanting.combine(input1, input2)
if can_combine then
-- Add tool health together plus a small bonus
if def1.type == "tool" and def2.type == "tool" then
local new_wear = calculate_repair(input1:get_wear(), input2:get_wear(), SAME_TOOL_REPAIR_BOOST)
input1:set_wear(new_wear)
end
name_item = input1
new_output = name_item
-- Tool + repair item
@ -318,11 +318,11 @@ local anvildef = {
_mcl_after_falling = damage_anvil_by_falling,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta = minetest.get_meta(pos)
local meta2 = meta
meta:from_table(oldmetadata)
drop_anvil_items(pos, meta)
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local name = player:get_player_name()

View File

@ -346,7 +346,7 @@ end
local drop_items_chest = function(pos, oldnode, oldmetadata)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
if oldmetadata then
meta:from_table(oldmetadata)
end
@ -358,7 +358,7 @@ local drop_items_chest = function(pos, oldnode, oldmetadata)
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end
local on_chest_blast = function(pos)

View File

@ -23,7 +23,7 @@ end
function mcl_enchanting.load_enchantments(itemstack, enchantments)
if not mcl_enchanting.is_book(itemstack:get_name()) then
mcl_enchanting.unload_enchantments(itemstack)
mcl_enchanting.unload_enchantments(itemstack)
for enchantment, level in pairs(enchantments or mcl_enchanting.get_enchantments(itemstack)) do
local enchantment_def = mcl_enchanting.enchantments[enchantment]
if enchantment_def.on_enchant then
@ -160,7 +160,7 @@ function mcl_enchanting.combine(itemstack, combine_with)
local itemname = itemstack:get_name()
local combine_name = combine_with:get_name()
local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname)
if not enchanted_itemname or enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
return false
end
local enchantments = mcl_enchanting.get_enchantments(itemstack)

View File

@ -388,12 +388,11 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
{ x=0, y=0, z=-1 },
{ x=0, y=0, z=1 },
}
local floorpos, floor
for n=#neighbors, 1, -1 do
local offset = neighbors[n]
local blockpos = vector.add(stempos, offset)
floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
floor = minetest.get_node(floorpos)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local block = minetest.get_node(blockpos)
local soilgroup = minetest.get_item_group(floor.name, "soil")
if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name=="mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then
@ -407,6 +406,8 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
local r = math.random(1, #neighbors)
local offset = neighbors[r]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local p2
if offset.x == 1 then
minetest.set_node(stempos, {name=connected_stem_names[1]})

View File

@ -5,6 +5,29 @@ mcl_fire = {}
local S = minetest.get_translator("mcl_fire")
local N = function(s) return s end
-- inverse pyramid pattern above lava source, floor 1 of 2:
local lava_fire=
{
{ x =-1, y = 1, z =-1},
{ x =-1, y = 1, z = 0},
{ x =-1, y = 1, z = 1},
{ x = 0, y = 1, z =-1},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 1, z = 1},
{ x = 1, y = 1, z =-1},
{ x = 1, y = 1, z = 0},
{ x = 1, y = 1, z = 1}
}
local alldirs=
{
{ x =-1, y = 0, z = 0},
{ x = 1, y = 0, z = 0},
{ x = 0, y =-1, z = 0},
{ x = 0, y = 1, z = 0},
{ x = 0, y = 0, z =-1},
{ x = 0, y = 0, z = 1}
}
local spawn_smoke = function(pos)
mcl_particles.add_node_particlespawner(pos, {
amount = 0.1,
@ -62,15 +85,15 @@ local fire_death_messages = {
N("@1 died in a fire."),
}
local fire_timer = function(pos)
minetest.get_node_timer(pos):start(math.random(3, 7))
end
local spawn_fire = function(pos, age)
minetest.set_node(pos, {name="mcl_fire:fire", param2 = age})
minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
end
local function fire_timer(pos)
return minetest.get_node_timer(pos):start(math.random(30, 60))
end
minetest.register_node("mcl_fire:fire", {
description = S("Fire"),
_doc_items_longdesc = fire_help,
@ -101,16 +124,84 @@ minetest.register_node("mcl_fire:fire", {
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
end
end,
drop = "",
sounds = {},
on_timer= function(pos)
if not minetest.find_node_near(pos, 1, {"group:flammable"}) then
on_timer = function(pos)
local node = minetest.get_node(pos)
-- Age is a number from 0 to 15 and is increased every timer step.
-- "old" fire is more likely to be extinguished
local age = node.param2
local flammables = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"})
local below = minetest.get_node({x=pos.x, y=pos.z-1, z=pos.z})
local below_is_flammable = minetest.get_item_group(below.name, "flammable") > 0
-- Extinguish fire
if (not fire_enabled) and (math.random(1,3) == 1) then
minetest.remove_node(pos)
return
end
if age == 15 and not below_is_flammable then
minetest.remove_node(pos)
return
elseif age > 3 and #flammables == 0 and not below_is_flammable and math.random(1,4) == 1 then
minetest.remove_node(pos)
return
end
local age_add = 1
-- If fire spread is disabled, we have to skip the "destructive" code
if (not fire_enabled) then
if age + age_add <= 15 then
node.param2 = age + age_add
minetest.set_node(pos, node)
end
-- Restart timer
fire_timer(pos)
return
end
-- Spawn fire to nearby flammable nodes
local is_next_to_flammable = minetest.find_node_near(pos, 2, {"group:flammable"}) ~= nil
if is_next_to_flammable and math.random(1,2) == 1 then
-- The fire we spawn copies the age of this fire.
-- This prevents fire from spreading infinitely far as the fire fire dies off
-- quicker the further it has spreaded.
local age_next = math.min(15, age + math.random(0, 1))
-- Select random type of fire spread
local burntype = math.random(1,2)
if burntype == 1 then
-- Spawn fire in air
local nodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"})
while #nodes > 0 do
local r = math.random(1, #nodes)
if minetest.find_node_near(nodes[r], 1, {"group:flammable"}) then
spawn_fire(nodes[r], age_next)
break
else
table.remove(nodes, r)
end
end
else
-- Burn flammable block
local nodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"})
if #nodes > 0 then
local r = math.random(1, #nodes)
local nn = minetest.get_node(nodes[r]).name
local ndef = minetest.registered_nodes[nn]
local fgroup = minetest.get_item_group(nn, "flammable")
if ndef and ndef._on_burn then
ndef._on_burn(nodes[r])
elseif fgroup ~= -1 then
spawn_fire(nodes[r], age_next)
end
end
end
end
-- Regular age increase
if age + age_add <= 15 then
node.param2 = age + age_add
minetest.set_node(pos, node)
end
-- Restart timer
return true
fire_timer(pos)
end,
drop = "",
sounds = {},
-- Turn into eternal fire on special blocks, light Nether portal (if possible), start burning timer
on_construct = function(pos)
local bpos = {x=pos.x, y=pos.y-1, z=pos.z}
@ -124,8 +215,9 @@ minetest.register_node("mcl_fire:fire", {
if minetest.get_modpath("mcl_portals") then
mcl_portals.light_nether_portal(pos)
end
spawn_smoke(pos)
fire_timer(pos)
spawn_smoke(pos)
end,
on_destruct = function(pos)
mcl_particles.delete_node_particlespawners(pos)
@ -163,7 +255,29 @@ minetest.register_node("mcl_fire:eternal_fire", {
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
end
end,
on_timer = function(pos)
if fire_enabled then
local airs = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"})
while #airs > 0 do
local r = math.random(1, #airs)
if minetest.find_node_near(airs[r], 1, {"group:flammable"}) then
local node = minetest.get_node(airs[r])
local age = node.param2
local age_next = math.min(15, age + math.random(0, 1))
spawn_fire(airs[r], age_next)
break
else
table.remove(airs, r)
end
end
end
-- Restart timer
fire_timer(pos)
end,
-- Start burning timer and light Nether portal (if possible)
on_construct = function(pos)
fire_timer(pos)
if minetest.get_modpath("mcl_portals") then
mcl_portals.light_nether_portal(pos)
end
@ -288,6 +402,114 @@ if flame_sound then
end
--
-- ABMs
--
-- Extinguish all flames quickly with water and such
minetest.register_abm({
label = "Extinguish fire",
nodenames = {"mcl_fire:fire", "mcl_fire:eternal_fire"},
neighbors = {"group:puts_out_fire"},
interval = 3,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.remove_node(pos)
minetest.sound_play("fire_extinguish_flame",
{pos = pos, max_hear_distance = 16, gain = 0.15}, true)
end,
})
-- Enable the following ABMs according to 'enable fire' setting
local function has_flammable(pos)
local npos, node
for n, v in ipairs(alldirs) do
npos = vector.add(pos, v)
node = minetest.get_node_or_nil(npos)
if node and node.name and minetest.get_item_group(node.name, "flammable") ~= 0 then
return npos
end
end
return false
end
if not fire_enabled then
-- Occasionally remove fire if fire disabled
-- NOTE: Fire is normally extinguished in timer function
minetest.register_abm({
label = "Remove disabled fire",
nodenames = {"mcl_fire:fire"},
interval = 10,
chance = 10,
catch_up = false,
action = minetest.remove_node,
})
else -- Fire enabled
-- Set fire to air nodes
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"group:lava"},
neighbors = {"air"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local i, dir, target, node, i2, f
i = math.random(1,9)
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
i = ((i + math.random(0,7)) % 9) + 1
dir = lava_fire[i]
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z}
node = minetest.get_node(target)
if not node or node.name ~= "air" then
return
end
end
i2 = math.random(1,15)
if i2 < 10 then
local dir2, target2, node2
dir2 = lava_fire[i2]
target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z}
node2 = minetest.get_node(target2)
if node2 and node2.name == "air" then
f = has_flammable(target2)
if f then
minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z},
expirationtime=1, size=1.5, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
return
end
end
end
f = has_flammable(target)
if f then
minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z})
minetest.add_particle({
pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}),
velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z},
expirationtime=1, size=1, collisiondetection=false,
glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png"
})
end
end,
})
end
-- Set pointed_thing on (normal) fire.
-- * pointed_thing: Pointed thing to ignite
-- * player: Player who sets fire or nil if nobody
@ -313,125 +535,6 @@ mcl_fire.set_fire = function(pointed_thing, player, allow_on_fire)
end
end
--
-- ABMs
--
-- Extinguish all flames quickly with water and such
minetest.register_abm({
label = "Extinguish fire",
nodenames = {"mcl_fire:fire", "mcl_fire:eternal_fire"},
neighbors = {"group:puts_out_fire"},
interval = 3,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.remove_node(pos)
minetest.sound_play("fire_extinguish_flame",
{pos = pos, max_hear_distance = 16, gain = 0.15}, true)
end,
})
-- Enable the following ABMs according to 'enable fire' setting
-- [...]a fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range.
-- https://minecraft.fandom.com/wiki/Fire#Spread
local function has_flammable(pos)
return minetest.find_node_near(pos, 1, {"group:flammable"})
end
local function check_aircube(p1,p2)
local nds=minetest.find_nodes_in_area(p1,p2,{"air"})
for k,v in pairs(nds) do
if has_flammable(v) then return v end
end
end
-- [...] a fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to).
local function get_ignitable(pos)
return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1)))
end
-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block.
local function get_ignitable_by_lava(pos)
return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil
end
if not fire_enabled then
-- Occasionally remove fire if fire disabled
-- NOTE: Fire is normally extinguished in timer function
minetest.register_abm({
label = "Remove disabled fire",
nodenames = {"mcl_fire:fire"},
interval = 10,
chance = 10,
catch_up = false,
action = minetest.remove_node,
})
else -- Fire enabled
-- Fire Spread
minetest.register_abm({
label = "Ignite flame",
nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"},
interval = 7,
chance = 12,
catch_up = false,
action = function(pos)
local p = get_ignitable(pos)
if p then
minetest.set_node(p, {name = "mcl_fire:fire"})
end
end
})
--lava fire spread
minetest.register_abm({
label = "Ignite fire by lava",
nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"},
neighbors = {"air","group:flammable"},
interval = 7,
chance = 3,
catch_up = false,
action = function(pos)
local p=get_ignitable_by_lava(pos)
if p then
minetest.set_node(p, {name = "mcl_fire:fire"})
end
end,
})
-- Remove flammable nodes around basic flame
minetest.register_abm({
label = "Remove flammable nodes",
nodenames = {"mcl_fire:fire","mcl_fire:eternal_fire"},
neighbors = {"group:flammable"},
interval = 5,
chance = 18,
catch_up = false,
action = function(pos)
local p = minetest.find_node_near(pos, 1, {"group:flammable"})
if not p then
return
end
local flammable_node = minetest.get_node(p)
local def = minetest.registered_nodes[flammable_node.name]
if def.on_burn then
def.on_burn(p)
else
minetest.swap_node(p, {name = "mcl_fire:fire"})
fire_timer(p)
minetest.check_for_falling(p)
end
end
})
end
minetest.register_lbm({
label = "Smoke particles from fire",
name = "mcl_fire:smoke",

View File

@ -451,7 +451,7 @@ minetest.register_node("mcl_furnaces:furnace", {
on_timer = furnace_node_timer,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for _, listname in ipairs({"src", "dst", "fuel"}) do
@ -461,7 +461,7 @@ minetest.register_node("mcl_furnaces:furnace", {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
on_construct = function(pos)

View File

@ -61,7 +61,7 @@ local def_hopper = {
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta2 = meta:to_table()
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
for i=1,inv:get_size("main") do
@ -71,7 +71,7 @@ local def_hopper = {
minetest.add_item(p, stack)
end
end
meta:from_table(meta2)
meta:from_table(meta2:to_table())
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local name = player:get_player_name()

View File

@ -29,9 +29,6 @@ if minetest.features.use_texture_alpha_string_modes then
PORTAL_ALPHA = nil
end
local PORTICLE_DISTANCE = 15 --how far to send particle spawners for the portalnodes
local porticlespawners = {}
-- Table of objects (including players) which recently teleported by a
-- Nether portal. Those objects have a brief cooloff period before they
-- can teleport again. This prevents annoying back-and-forth teleportation.
@ -62,65 +59,6 @@ local function nether_to_overworld(x)
return LIMIT - math.abs(((x * OVERWORLD_TO_NETHER_SCALE + LIMIT) % (LIMIT*4)) - (LIMIT*2))
end
local function remove_particlespawner_at_position(playername,pos)
if not porticlespawners[minetest.pos_to_string(pos)] or porticlespawners[minetest.pos_to_string(pos)][playername] == nil then return end
minetest.delete_particlespawner(porticlespawners[minetest.pos_to_string(pos)][playername],playername)
porticlespawners[minetest.pos_to_string(pos)][playername]=nil
end
local function add_particlespawner_at_position(player,pos,node)
if not porticlespawners[minetest.pos_to_string(pos)] then porticlespawners[minetest.pos_to_string(pos)] = {} end
if porticlespawners[minetest.pos_to_string(pos)][player:get_player_name()] ~= nil then return end
porticlespawners[minetest.pos_to_string(pos)][player:get_player_name()]=minetest.add_particlespawner({
amount = node_particles_allowed_level + 1,
minpos = vector.add(pos, vector.new(-3,-3,-3)),
maxpos = vector.add(pos, vector.new(3,3,3)),
minvel = vector.new(-0.5,-0.5,-0.5),
maxvel = vector.new(0.5,0.5,0.5),
minacc = vector.new(-0.5,-0.5,-0.5),
maxacc = vector.new(0.5,0.5,0.5),
minexptime = 0.1,
maxexptime = 2.4,
minsize = 0.3,
maxsize = 1.8,
time=0,
collisiondetection = false,
texture = "mcl_particles_nether_portal.png",
playername = player:get_player_name(),
})
end
local function add_porticlespawners(pos,node)
--Add particlespawners for all players in range
for _,obj in pairs(minetest.get_connected_players()) do
if vector.distance(obj:get_pos(),pos) <= PORTICLE_DISTANCE then
add_particlespawner_at_position(obj,pos,node)
end
end
end
local function remove_porticlespawners(pos,force)
--Remove particlespawners for all players out of range
-- force removes all particlespawners for the given position regardless of range
if porticlespawners[minetest.pos_to_string(pos)] then
for k,v in pairs(porticlespawners[minetest.pos_to_string(pos)]) do
local p=minetest.get_player_by_name(k)
local dst=PORTICLE_DISTANCE+1 --if player is logged off remove the particlespawner
if p and p:is_player() then
dst=vector.distance(p:get_pos(),pos)
end
if dst > PORTICLE_DISTANCE or force then
remove_particlespawner_at_position(k,pos)
end
end
end
end
local function check_porticlespawners(pos,node)
add_porticlespawners(pos,node)
remove_porticlespawners(pos)
end
-- Destroy portal if pos (portal frame or portal node) got destroyed
local function destroy_nether_portal(pos)
local meta = minetest.get_meta(pos)
@ -139,7 +77,6 @@ local function destroy_nether_portal(pos)
local node = minetest.get_node(pos)
if node and (node.name == "mcl_portals:portal" and (orientation == nil or (node.param2 == orientation))) then
minetest.log("action", "[mcl_portal] Destroying Nether portal at " .. minetest.pos_to_string(pos))
remove_porticlespawners(pos,true)
return minetest.remove_node(pos)
end
end
@ -832,16 +769,56 @@ local function teleport(obj, portal_pos)
end
end
minetest.register_abm({
label = "Nether portal teleportation and particles",
nodenames = {"mcl_portals:portal"},
interval = 1,
chance = 1,
action = function(pos, node)
check_porticlespawners(pos)
local o = node.param2 -- orientation
local d = math.random(0, 1) -- direction
local time = math.random() * 1.9 + 0.5
local velocity, acceleration
if o == 1 then
velocity = {x = math.random() * 0.7 + 0.3, y = math.random() - 0.5, z = math.random() - 0.5}
acceleration = {x = math.random() * 1.1 + 0.3, y = math.random() - 0.5, z = math.random() - 0.5}
else
velocity = {x = math.random() - 0.5, y = math.random() - 0.5, z = math.random() * 0.7 + 0.3}
acceleration = {x = math.random() - 0.5, y = math.random() - 0.5, z = math.random() * 1.1 + 0.3}
end
local distance = vector.add(vector.multiply(velocity, time), vector.multiply(acceleration, time * time / 2))
if d == 1 then
if o == 1 then
distance.x = -distance.x
velocity.x = -velocity.x
acceleration.x = -acceleration.x
else
distance.z = -distance.z
velocity.z = -velocity.z
acceleration.z = -acceleration.z
end
end
distance = vector.subtract(pos, distance)
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 15)) do
if obj:is_player() then
minetest.add_particlespawner({
amount = node_particles_allowed_level + 1,
minpos = distance,
maxpos = distance,
minvel = velocity,
maxvel = velocity,
minacc = acceleration,
maxacc = acceleration,
minexptime = time,
maxexptime = time,
minsize = 0.3,
maxsize = 1.8,
collisiondetection = false,
texture = "mcl_particles_nether_portal.png",
playername = obj:get_player_name(),
})
end
end
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do --maikerumine added for objects to travel
local lua_entity = obj:get_luaentity() --maikerumine added for objects to travel
if (obj:is_player() or lua_entity) and prevent_portal_chatter(obj) then