2023-02-12 00:32:53 +00:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
mcl_campfires = { }
2023-05-31 00:40:12 +00:00
local food_entity = { nil , nil , nil , nil }
2023-05-30 21:19:48 +00:00
2023-06-05 22:43:07 +00:00
local drop_inventory = mcl_util.drop_items_from_meta_container ( " main " )
2023-06-21 18:37:41 +00:00
local function campfire_drops ( pos , digger , drops , nodename )
local wield_item = digger : get_wielded_item ( )
local silk_touch = mcl_enchanting.has_enchantment ( wield_item , " silk_touch " )
local is_creative = minetest.is_creative_enabled ( digger : get_player_name ( ) )
local inv = digger : get_inventory ( )
if not is_creative then
if silk_touch then
minetest.add_item ( pos , nodename )
else
minetest.add_item ( pos , drops )
end
elseif is_creative and inv : room_for_item ( " main " , nodename ) and not inv : contains_item ( " main " , nodename ) then
inv : add_item ( " main " , nodename )
end
end
2023-06-05 22:43:07 +00:00
local function drop_items ( pos , node , oldmeta )
2023-06-05 22:51:30 +00:00
local meta = minetest.get_meta ( pos )
2023-06-05 22:43:07 +00:00
drop_inventory ( pos , node , oldmeta )
2023-06-05 23:12:57 +00:00
local entites = minetest.get_objects_inside_radius ( pos , 0.5 )
if entites then
for _ , food_entity in ipairs ( entites ) do
if food_entity then
if food_entity : get_luaentity ( ) . name == " mcl_campfires:food_entity " then
food_entity : remove ( )
for i = 1 , 4 do
meta : set_string ( " food_x_ " .. tostring ( i ) , nil )
meta : set_string ( " food_y_ " .. tostring ( i ) , nil )
meta : set_string ( " food_z_ " .. tostring ( i ) , nil )
2023-06-05 22:51:30 +00:00
end
end
end
end
2023-05-31 00:40:12 +00:00
end
2023-05-30 21:19:48 +00:00
end
2023-05-30 18:44:15 +00:00
2023-06-05 22:43:07 +00:00
local function on_blast ( pos )
local node = minetest.get_node ( pos )
drop_items ( pos , node )
minetest.remove_node ( pos )
end
function mcl_campfires . light_campfire ( pos )
local campfire = minetest.get_node ( pos )
local name = campfire.name .. " _lit "
minetest.set_node ( pos , { name = name , param2 = campfire.param2 } )
end
2023-05-30 18:44:15 +00:00
-- on_rightclick function to take items that are cookable in a campfire, and put them in the campfire inventory
function mcl_campfires . take_item ( pos , node , player , itemstack )
2023-05-30 21:31:58 +00:00
local campfire_spots = {
2023-06-05 22:51:30 +00:00
vector.new ( - 0.25 , - 0.04 , - 0.25 ) ,
vector.new ( 0.25 , - 0.04 , - 0.25 ) ,
vector.new ( 0.25 , - 0.04 , 0.25 ) ,
vector.new ( - 0.25 , - 0.04 , 0.25 ) ,
2023-05-30 21:31:58 +00:00
}
2023-06-05 22:51:30 +00:00
local food_entity = { nil , nil , nil , nil }
2023-05-30 18:44:15 +00:00
local is_creative = minetest.is_creative_enabled ( player : get_player_name ( ) )
local inv = player : get_inventory ( )
local campfire_meta = minetest.get_meta ( pos )
local campfire_inv = campfire_meta : get_inventory ( )
local timer = minetest.get_node_timer ( pos )
local stack = itemstack : peek_item ( 1 )
if minetest.get_item_group ( itemstack : get_name ( ) , " campfire_cookable " ) ~= 0 then
local cookable = minetest.get_craft_result ( { method = " cooking " , width = 1 , items = { itemstack } } )
if cookable then
2023-05-30 21:19:48 +00:00
for space = 1 , 4 do -- Cycle through spots
2023-05-30 18:44:15 +00:00
local spot = campfire_inv : get_stack ( " main " , space )
if not spot or spot == ( ItemStack ( " " ) or ItemStack ( " nil " ) ) then -- Check if the spot is empty or not
2023-05-30 21:19:48 +00:00
if not is_creative then itemstack : take_item ( 1 ) end -- Take the item if in creative
campfire_inv : set_stack ( " main " , space , stack ) -- Set the inventory itemstack at the empty spot
campfire_meta : set_int ( " cooktime_ " .. tostring ( space ) , 30 ) -- Set the cook time meta
2023-06-05 22:51:30 +00:00
food_entity [ space ] = minetest.add_entity ( pos + campfire_spots [ space ] , " mcl_campfires:food_entity " ) -- Spawn food item on the campfire
local food_luaentity = food_entity [ space ] : get_luaentity ( )
food_luaentity.wield_item = campfire_inv : get_stack ( " main " , space ) : get_name ( ) -- Set the wielditem of the food item to the food on the campfire
food_luaentity.wield_image = " mcl_mobitems_ " .. string.sub ( campfire_inv : get_stack ( " main " , space ) : get_name ( ) , 14 ) .. " _raw.png " -- Set the wield_image to the food item on the campfire
food_entity [ space ] : set_properties ( food_luaentity ) -- Apply changes to the food entity
2023-06-21 18:37:41 +00:00
campfire_meta : set_string ( " food_x_ " .. tostring ( space ) , tostring ( food_entity [ space ] : get_pos ( ) . x ) )
campfire_meta : set_string ( " food_y_ " .. tostring ( space ) , tostring ( food_entity [ space ] : get_pos ( ) . y ) )
campfire_meta : set_string ( " food_z_ " .. tostring ( space ) , tostring ( food_entity [ space ] : get_pos ( ) . z ) )
2023-05-30 18:44:15 +00:00
break
end
end
end
timer : start ( 1 ) -- Start cook timer
end
end
-- on_timer function to run the cook timer and cook items.
function mcl_campfires . cook_item ( pos , elapsed )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
local continue = 0
-- Cycle through slots to cook them.
for i = 1 , 4 do
local time_r = meta : get_int ( " cooktime_ " .. tostring ( i ) )
local item = inv : get_stack ( " main " , i )
2023-06-05 22:51:30 +00:00
local food_entity = nil
local food_x = tonumber ( meta : get_string ( " food_x_ " .. tostring ( i ) ) )
local food_y = tonumber ( meta : get_string ( " food_y_ " .. tostring ( i ) ) )
local food_z = tonumber ( meta : get_string ( " food_z_ " .. tostring ( i ) ) )
if food_x and food_y and food_z then
2023-06-21 17:50:11 +00:00
local entites = minetest.get_objects_inside_radius ( vector.new ( food_x , food_y , food_z ) , 0 )
2023-06-05 22:51:30 +00:00
if entites then
for _ , entity in ipairs ( entites ) do
if entity then
2023-06-21 18:37:41 +00:00
local luaentity = entity : get_luaentity ( )
2023-06-05 22:54:03 +00:00
if luaentity then
2023-06-21 18:37:41 +00:00
local name = luaentity.name
2023-06-05 22:54:03 +00:00
if name == " mcl_campfires:food_entity " then
food_entity = entity
2023-06-21 17:50:11 +00:00
food_entity : set_properties ( { wield_item = inv : get_stack ( " main " , i ) : get_name ( ) } )
2023-06-05 22:54:03 +00:00
end
2023-06-05 22:51:30 +00:00
end
end
end
end
end
2023-05-30 18:44:15 +00:00
if item ~= ( ItemStack ( " " ) or ItemStack ( " nil " ) ) then
-- Item hasn't been cooked completely, continue cook timer countdown.
if time_r and time_r ~= 0 and time_r > 0 then
meta : set_int ( " cooktime_ " .. tostring ( i ) , time_r - 1 )
-- Item cook timer is up, finish cooking process and drop cooked item.
elseif time_r <= 0 then
local cooked = minetest.get_craft_result ( { method = " cooking " , width = 1 , items = { item } } )
if cooked then
2023-06-05 22:51:30 +00:00
if food_entity then
food_entity : remove ( ) -- Remove visual food entity
meta : set_string ( " food_x_ " .. tostring ( i ) , nil )
meta : set_string ( " food_y_ " .. tostring ( i ) , nil )
meta : set_string ( " food_z_ " .. tostring ( i ) , nil )
end
2023-05-30 21:19:48 +00:00
minetest.add_item ( pos , cooked.item ) -- Drop Cooked Item
2023-06-27 23:00:42 +00:00
-- Throw some Experience Points because why not?
-- Food is cooked, xp is deserved for using this unique cooking method. Take that Minecraft ;)
local dir = vector.divide ( minetest.facedir_to_dir ( minetest.get_node ( pos ) . param2 ) , - 1.95 )
mcl_experience.throw_xp ( vector.add ( pos , dir ) , 1 )
2023-05-30 21:19:48 +00:00
inv : set_stack ( " main " , i , " " ) -- Clear Inventory
continue = continue + 1 -- Indicate that the slot is clear.
2023-05-30 18:44:15 +00:00
end
end
end
end
-- Not all slots are empty, continue timer.
if continue ~= 4 then
return true
-- Slots are empty, stop node timer.
else
return false
end
end
2023-02-12 00:32:53 +00:00
function mcl_campfires . register_campfire ( name , def )
-- Define Campfire
minetest.register_node ( name , {
description = def.description ,
_tt_help = S ( " Cooks food and keeps bees happy. " ) ,
_doc_items_longdesc = S ( " Campfires have multiple uses, including keeping bees happy, cooking raw meat and fish, and as a trap. " ) ,
inventory_image = def.inv_texture ,
wield_image = def.inv_texture ,
drawtype = " mesh " ,
mesh = " mcl_campfires_campfire.obj " ,
tiles = { { name = " mcl_campfires_log.png " } , } ,
use_texture_alpha = " clip " ,
groups = { handy = 1 , axey = 1 , material_wood = 1 , not_in_creative_inventory = 1 , campfire = 1 , } ,
paramtype = " light " ,
2023-06-21 18:37:41 +00:00
paramtype2 = " 4dir " ,
2023-06-05 22:43:07 +00:00
_on_ignite = function ( player , node )
mcl_campfires.light_campfire ( node.under )
return true
2023-02-12 00:32:53 +00:00
end ,
2023-06-21 18:37:41 +00:00
drop = " " ,
2023-06-05 22:43:07 +00:00
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2023-02-12 00:32:53 +00:00
selection_box = {
type = ' fixed ' ,
fixed = { - .5 , - .5 , - .5 , .5 , - .05 , .5 } , --left, bottom, front, right, top
} ,
collision_box = {
type = ' fixed ' ,
fixed = { - .5 , - .5 , - .5 , .5 , - .05 , .5 } ,
} ,
_mcl_blast_resistance = 2 ,
_mcl_hardness = 2 ,
2023-06-21 18:37:41 +00:00
after_dig_node = function ( pos , node , oldmeta , digger )
campfire_drops ( pos , digger , def.drops , name .. " _lit " )
end ,
2023-02-12 00:32:53 +00:00
} )
--Define Lit Campfire
minetest.register_node ( name .. " _lit " , {
description = def.description ,
_tt_help = S ( " Cooks food and keeps bees happy. " ) ,
_doc_items_longdesc = S ( " Campfires have multiple uses, including keeping bees happy, cooking raw meat and fish, and as a trap. " ) ,
inventory_image = def.inv_texture ,
wield_image = def.inv_texture ,
drawtype = " mesh " ,
mesh = " mcl_campfires_campfire_lit.obj " ,
tiles = { {
name = def.fire_texture ,
animation = {
type = " vertical_frames " ,
aspect_w = 16 ,
aspect_h = 16 ,
length = 2.0
} } ,
{ name = def.lit_logs_texture ,
animation = {
type = " vertical_frames " ,
aspect_w = 16 ,
aspect_h = 16 ,
length = 2.0
} }
} ,
use_texture_alpha = " clip " ,
2023-06-05 22:43:07 +00:00
groups = { handy = 1 , axey = 1 , material_wood = 1 , lit_campfire = 1 } ,
2023-02-12 00:32:53 +00:00
paramtype = " light " ,
2023-06-21 18:37:41 +00:00
paramtype2 = " 4dir " ,
2023-05-30 18:44:15 +00:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
inv : set_size ( " main " , 4 )
end ,
2023-02-12 00:32:53 +00:00
on_rightclick = function ( pos , node , player , itemstack , pointed_thing )
2023-06-05 22:43:07 +00:00
if minetest.get_item_group ( itemstack : get_name ( ) , " shovel " ) ~= 0 then
local protected = mcl_util.check_position_protection ( pos , player )
if not protected then
if not minetest.is_creative_enabled ( player : get_player_name ( ) ) then
-- Add wear (as if digging a shovely node)
local toolname = itemstack : get_name ( )
local wear = mcl_autogroup.get_wear ( toolname , " shovely " )
if wear then
itemstack : add_wear ( wear )
end
end
node.name = name
minetest.set_node ( pos , node )
minetest.sound_play ( " fire_extinguish_flame " , { pos = pos , gain = 0.25 , max_hear_distance = 16 } , true )
end
2023-06-07 23:13:19 +00:00
elseif minetest.get_item_group ( itemstack : get_name ( ) , " campfire_cookable " ) ~= 0 then
mcl_campfires.take_item ( pos , node , player , itemstack )
else
minetest.item_place_node ( itemstack , player , pointed_thing )
2023-02-12 00:32:53 +00:00
end
end ,
2023-05-30 18:44:15 +00:00
on_timer = mcl_campfires.cook_item ,
2023-06-21 18:37:41 +00:00
drop = " " ,
2023-02-12 00:32:53 +00:00
light_source = def.lightlevel ,
2023-06-05 22:43:07 +00:00
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2023-02-12 00:32:53 +00:00
selection_box = {
type = " fixed " ,
fixed = { - .5 , - .5 , - .5 , .5 , - .05 , .5 } , --left, bottom, front, right, top
} ,
collision_box = {
type = " fixed " ,
fixed = { - .5 , - .5 , - .5 , .5 , - .05 , .5 } ,
} ,
_mcl_blast_resistance = 2 ,
_mcl_hardness = 2 ,
2023-06-21 19:12:38 +00:00
damage_per_second = def.damage , -- FIXME: Once entity burning is fixed, this needs to be removed.
2023-05-30 21:19:48 +00:00
on_blast = on_blast ,
2023-06-21 18:37:41 +00:00
after_dig_node = function ( pos , node , oldmeta , digger )
drop_items ( pos , node , oldmeta )
campfire_drops ( pos , digger , def.drops , name .. " _lit " )
end ,
2023-06-07 23:13:19 +00:00
_mcl_campfires_smothered_form = name ,
2023-02-12 00:32:53 +00:00
} )
end
local function burn_in_campfire ( obj )
local p = obj : get_pos ( )
if p then
local n = minetest.find_node_near ( p , 0.4 , { " group:lit_campfire " } , true )
if n then
mcl_burning.set_on_fire ( obj , 5 )
end
end
end
local etime = 0
minetest.register_globalstep ( function ( dtime )
etime = dtime + etime
if etime < 0.5 then return end
etime = 0
for _ , pl in pairs ( minetest.get_connected_players ( ) ) do
2023-06-21 19:12:38 +00:00
local armor_feet = pl : get_inventory ( ) : get_stack ( " armor " , 5 )
if pl and pl : get_player_control ( ) . sneak or ( minetest.global_exists ( " mcl_enchanting " ) and mcl_enchanting.has_enchantment ( armor_feet , " frost_walker " ) ) or ( minetest.global_exists ( " mcl_potions " ) and mcl_potions.player_has_effect ( pl , " fire_proof " ) ) then
return
end
2023-02-12 00:32:53 +00:00
burn_in_campfire ( pl )
end
for _ , ent in pairs ( minetest.luaentities ) do
if ent.is_mob then
2023-06-21 19:12:38 +00:00
burn_in_campfire ( ent.object ) -- FIXME: Mobs don't seem to burn properly anymore.
2023-02-12 00:32:53 +00:00
end
end
end )
2023-05-30 21:13:37 +00:00
function mcl_campfires . generate_smoke ( pos , haybale )
local smoke_timer
if haybale then
smoke_timer = 8
else
smoke_timer = 4.75
end
minetest.add_particle ( {
pos = pos ,
velocity = vector.new ( 0 , 1 , 0 ) ,
texture = " mcl_particles_smoke.png " ,
size = 10 ,
acceleration = vector.new ( 0 , 0.5 , 0 ) ,
collisiondetection = true ,
expirationtime = smoke_timer ,
} )
end
minetest.register_abm ( {
label = " Campfire Smoke " ,
nodenames = { " group:lit_campfire " } ,
interval = 2 ,
chance = 2 ,
action = function ( pos , node )
local node_below = vector.offset ( pos , 0 , - 1 , 0 )
local haybale = false
if minetest.get_node ( node_below ) . name == " mcl_farming:hay_block " then
haybale = true
end
mcl_campfires.generate_smoke ( pos , haybale )
end ,
} )