forked from Mineclonia/Mineclonia
Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
cora | c711380064 | |
cora | b1189433a4 | |
cora | 2ef8f788c2 | |
cora | 7375cc0706 | |
cora | 22ec7a65d8 | |
Lizzy Fleckenstein | 4cfb65003b | |
Lizzy Fleckenstein | 5060e600d7 | |
Lizzy Fleckenstein | 20900cccd5 | |
Lizzy Fleckenstein | 51f3869ffe | |
cora | 89d63080be |
|
@ -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
|
||||
|
||||
|
|
|
@ -1,36 +1,66 @@
|
|||
mcl_weather.nether_dust = {}
|
||||
mcl_weather.nether_dust.particles_count = 99
|
||||
mcl_weather.nether_dust.particlespawners = {}
|
||||
|
||||
-- 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()
|
||||
})
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
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])
|
||||
end
|
||||
mcl_weather.nether_dust.add_dust_particles(player)
|
||||
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)
|
||||
end
|
||||
end)
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
mcl_weather.nether_dust.delete_particlespawners(player)
|
||||
end)
|
||||
|
|
|
@ -82,7 +82,7 @@ local dispenserdef = {
|
|||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta2 = meta
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 3.5,
|
||||
|
|
|
@ -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
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local name = player:get_player_name()
|
||||
|
|
|
@ -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
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local name = player:get_player_name()
|
||||
|
|
|
@ -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
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta2 = meta:to_table()
|
||||
meta:from_table(oldmetadata)
|
||||
drop_anvil_items(pos, meta)
|
||||
meta:from_table(meta2:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
local name = player:get_player_name()
|
||||
|
|
|
@ -346,7 +346,7 @@ end
|
|||
|
||||
local drop_items_chest = function(pos, oldnode, oldmetadata)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta2 = meta
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end
|
||||
|
||||
local on_chest_blast = function(pos)
|
||||
|
|
|
@ -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 enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(combine_name) then
|
||||
if not enchanted_itemname or 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)
|
||||
|
|
|
@ -388,11 +388,12 @@ 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)
|
||||
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
|
||||
local floor = minetest.get_node(floorpos)
|
||||
floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
|
||||
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
|
||||
|
@ -406,8 +407,6 @@ 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]})
|
||||
|
|
|
@ -5,29 +5,6 @@ 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,
|
||||
|
@ -85,15 +62,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,
|
||||
|
@ -124,84 +101,16 @@ minetest.register_node("mcl_fire:fire", {
|
|||
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
|
||||
end
|
||||
end,
|
||||
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
|
||||
fire_timer(pos)
|
||||
end,
|
||||
drop = "",
|
||||
sounds = {},
|
||||
on_timer= function(pos)
|
||||
if not minetest.find_node_near(pos, 1, {"group:flammable"}) then
|
||||
minetest.remove_node(pos)
|
||||
return
|
||||
end
|
||||
-- Restart timer
|
||||
return true
|
||||
end,
|
||||
-- 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}
|
||||
|
@ -215,9 +124,8 @@ minetest.register_node("mcl_fire:fire", {
|
|||
if minetest.get_modpath("mcl_portals") then
|
||||
mcl_portals.light_nether_portal(pos)
|
||||
end
|
||||
|
||||
fire_timer(pos)
|
||||
spawn_smoke(pos)
|
||||
fire_timer(pos)
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
mcl_particles.delete_node_particlespawners(pos)
|
||||
|
@ -255,29 +163,7 @@ 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
|
||||
|
@ -402,114 +288,6 @@ 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
|
||||
|
@ -535,6 +313,125 @@ 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",
|
||||
|
|
|
@ -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
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
|
||||
on_construct = function(pos)
|
||||
|
|
|
@ -61,7 +61,7 @@ local def_hopper = {
|
|||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta2 = meta
|
||||
local meta2 = meta:to_table()
|
||||
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:to_table())
|
||||
meta:from_table(meta2)
|
||||
end,
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local name = player:get_player_name()
|
||||
|
|
|
@ -29,6 +29,9 @@ 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.
|
||||
|
@ -59,6 +62,65 @@ 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)
|
||||
|
@ -77,6 +139,7 @@ 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
|
||||
|
@ -769,56 +832,16 @@ 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)
|
||||
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
|
||||
|
||||
check_porticlespawners(pos)
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue