729 lines
25 KiB
Lua
729 lines
25 KiB
Lua
--[[
|
|
X Farming. Extends Minetest farming mod with new plants, crops and ice fishing.
|
|
Copyright (C) 2024 SaKeL
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to juraj.vajda@gmail.com
|
|
--]]
|
|
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
|
|
|
local stove_fire_sounds = {}
|
|
|
|
local function get_grid_matrix_items(grid)
|
|
local grid_matrix = table.copy(grid)
|
|
local _items = {}
|
|
|
|
for row, items in ipairs(grid_matrix) do
|
|
for item_pos, item in pairs(items) do
|
|
if item.itemstring ~= '' then
|
|
-- add entity position to item table
|
|
item.ent_pos = item_pos
|
|
table.insert(_items, item)
|
|
end
|
|
end
|
|
end
|
|
|
|
return _items
|
|
end
|
|
|
|
local function add_item_to_grid_matrix(grid_matrix, item)
|
|
local result = {}
|
|
|
|
for row, items in ipairs(grid_matrix) do
|
|
local found = false
|
|
|
|
for item_pos, _item in pairs(items) do
|
|
if _item.itemstring == '' then
|
|
grid_matrix[row][item_pos] = item
|
|
result.added_to_row = row
|
|
result.added_to_pos = item_pos
|
|
found = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if found then
|
|
break
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
local function stop_stove_sound(pos, fadeout_step)
|
|
local hash = minetest.hash_node_position(pos)
|
|
local sound_ids = stove_fire_sounds[hash]
|
|
|
|
if sound_ids then
|
|
for _, sound_id in ipairs(sound_ids) do
|
|
minetest.sound_fade(sound_id, -1, 0)
|
|
end
|
|
|
|
stove_fire_sounds[hash] = nil
|
|
end
|
|
end
|
|
|
|
local function remove_item_from_grid_matrix(grid_matrix, item)
|
|
local result = {}
|
|
|
|
for row, items in ipairs(grid_matrix) do
|
|
local found = false
|
|
|
|
for item_pos, _item in pairs(items) do
|
|
if _item.itemstring == item.itemstring then
|
|
grid_matrix[row][item_pos] = {
|
|
itemstring = '',
|
|
output = {}
|
|
}
|
|
result.removed_from_row = row
|
|
result.removed_from_pos = item_pos
|
|
found = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if found then
|
|
break
|
|
end
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
local function add_item_smoke_particles(pos)
|
|
local particlespawner_def = {
|
|
amount = 5,
|
|
time = 1,
|
|
minpos = vector.new(pos.x - 0.1, pos.y, pos.z - 0.1),
|
|
maxpos = vector.new(pos.x + 0.1, pos.y, pos.z + 0.1),
|
|
minvel = vector.new(-0.1, 0.2, -0.1),
|
|
maxvel = vector.new(0.1, 0.4, 0.1),
|
|
minacc = vector.new(0, 0.1, 0),
|
|
maxacc = vector.new(0, 0.2, 0),
|
|
minexptime = 1,
|
|
maxexptime = 3,
|
|
minsize = 1,
|
|
maxsize = 1.5,
|
|
texture = 'x_farming_stove_item_smoke_particle.png',
|
|
collisiondetection = true
|
|
}
|
|
|
|
if minetest.has_feature({ dynamic_add_media_table = true, particlespawner_tweenable = true }) then
|
|
-- new syntax, after v5.6.0
|
|
particlespawner_def = {
|
|
amount = 5,
|
|
time = 1,
|
|
pos = {
|
|
min = vector.new(pos.x - 0.1, pos.y, pos.z - 0.1),
|
|
max = vector.new(pos.x + 0.1, pos.y, pos.z + 0.1)
|
|
},
|
|
size = {
|
|
min = 1,
|
|
max = 1.5,
|
|
},
|
|
vel = {
|
|
min = vector.new(-0.1, 0.2, -0.1),
|
|
max = vector.new(0.1, 0.4, 0.1)
|
|
},
|
|
acc = {
|
|
min = vector.new(0, 0.1, 0),
|
|
max = vector.new(0, 0.2, 0)
|
|
},
|
|
exptime = {
|
|
min = 1,
|
|
max = 3
|
|
},
|
|
texture = {
|
|
name = 'x_farming_stove_item_smoke_particle.png',
|
|
alpha_tween = {
|
|
1, 0.5,
|
|
style = 'fwd',
|
|
reps = 1
|
|
},
|
|
scale_tween = {
|
|
{ x = 1, y = 1 },
|
|
{ x = 0.5, y = 0.5 },
|
|
}
|
|
},
|
|
collisiondetection = true
|
|
}
|
|
end
|
|
|
|
minetest.add_particlespawner(particlespawner_def)
|
|
end
|
|
|
|
-- Entity
|
|
|
|
minetest.register_entity('x_farming:stove_food', {
|
|
initial_properties = {
|
|
visual = 'wielditem',
|
|
visual_size = { x = 0.2, y = 0.2, z = 0.2 },
|
|
physical = false,
|
|
collide_with_objects = false,
|
|
collisionbox = { 0, 0, 0, 0, 0, 0 },
|
|
-- collisionbox = { -0.15, -0.05, -0.15, 0.15, 0.05, 0.15 },
|
|
selectionbox = { 0, 0, 0, 0, 0, 0 },
|
|
-- selectionbox = { -0.15, -0.05, -0.15, 0.15, 0.05, 0.15 },
|
|
pointable = false,
|
|
makes_footstep_sound = false,
|
|
static_save = true,
|
|
shaded = true,
|
|
glow = 4
|
|
},
|
|
on_activate = function(self, staticdata, dtime_s)
|
|
if not self or not staticdata or staticdata == '' then
|
|
self.object:remove()
|
|
return
|
|
end
|
|
|
|
local _staticdata = minetest.deserialize(staticdata)
|
|
|
|
for key, value in pairs(_staticdata) do
|
|
self[key] = value
|
|
end
|
|
|
|
self._nodechecktimer = 2
|
|
|
|
self.object:set_armor_groups({ immortal = 1, stove_food = 1, fleshy = 100 })
|
|
|
|
self.object:set_properties({
|
|
wield_item = _staticdata.itemname,
|
|
infotext = _staticdata.itemname,
|
|
})
|
|
end,
|
|
on_step = function(self, dtime, moveresult)
|
|
self._nodechecktimer = self._nodechecktimer - dtime
|
|
|
|
if self._nodechecktimer <= 0 then
|
|
self._nodechecktimer = 2
|
|
local pos = self.object:get_pos()
|
|
local node_above = minetest.get_node(vector.new(pos.x, pos.y + 0.5, pos.z))
|
|
local node_under = minetest.get_node(vector.new(pos.x, pos.y - 0.5, pos.z))
|
|
|
|
-- drop items if above is obstructed or no heat_source below
|
|
if node_above.name ~= 'air'
|
|
or minetest.get_item_group(node_under.name, 'heat_source') < 1
|
|
then
|
|
local meta = minetest.get_meta(vector.new(pos.x, pos.y - 0.5, pos.z))
|
|
local grid_matrix = minetest.deserialize(meta:get_string('grid_matrix'))
|
|
|
|
if not grid_matrix then
|
|
return
|
|
end
|
|
|
|
local grid_items = get_grid_matrix_items(grid_matrix)
|
|
|
|
-- remove item from stove meta
|
|
for i, value in ipairs(grid_items) do
|
|
remove_item_from_grid_matrix(grid_matrix, value)
|
|
end
|
|
|
|
meta:set_string('grid_matrix', minetest.serialize(grid_matrix))
|
|
|
|
-- remove entity and drop item
|
|
minetest.add_item(pos, ItemStack({ name = self.itemname }))
|
|
self.object:remove()
|
|
return
|
|
end
|
|
end
|
|
end,
|
|
get_staticdata = function(self)
|
|
local staticdata = {
|
|
itemname = self.itemname
|
|
}
|
|
return minetest.serialize(staticdata)
|
|
end,
|
|
})
|
|
|
|
-- Nodes
|
|
minetest.register_node('x_farming:stove', {
|
|
description = S('Stove inactive)'),
|
|
tiles = {
|
|
'x_farming_stove_top.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_front.png',
|
|
},
|
|
paramtype2 = '4dir',
|
|
is_ground_content = false,
|
|
groups = {
|
|
-- MTG
|
|
cracky = 2,
|
|
-- MCL
|
|
pickaxey = 1,
|
|
container = 4,
|
|
deco_block = 1,
|
|
material_stone = 1
|
|
},
|
|
_mcl_blast_resistance = 3.5,
|
|
_mcl_hardness = 3.5,
|
|
sounds = x_farming.node_sound_stone_defaults(),
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local infotext = S('Stove inactive.') .. ' ' .. S('Activate by torch or flint and steel.')
|
|
local node = minetest.get_node(pos)
|
|
|
|
local x_shift = -0.6
|
|
local m_pos = vector.new(pos.x - 0.6, pos.y + 0.5, pos.z)
|
|
-- param2 = 0 or 2
|
|
local initial_grid_matrix = {
|
|
[1] = {
|
|
[vector.to_string(vector.new(m_pos.x + (1 * 0.3), m_pos.y, m_pos.z + 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + (2 * 0.3), m_pos.y, m_pos.z + 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + (3 * 0.3), m_pos.y, m_pos.z + 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
}
|
|
},
|
|
[2] = {
|
|
[vector.to_string(vector.new(m_pos.x + (1 * 0.3), m_pos.y, m_pos.z - 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + (2 * 0.3), m_pos.y, m_pos.z - 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + (3 * 0.3), m_pos.y, m_pos.z - 0.2))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
}
|
|
},
|
|
}
|
|
|
|
if node.param2 == 1 or node.param2 == 3 then
|
|
m_pos = vector.new(pos.x, pos.y + 0.5, pos.z + x_shift)
|
|
|
|
initial_grid_matrix = {
|
|
[1] = {
|
|
[vector.to_string(vector.new(m_pos.x + 0.2, m_pos.y, m_pos.z + (1 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + 0.2, m_pos.y, m_pos.z + (2 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x + 0.2, m_pos.y, m_pos.z + (3 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
}
|
|
},
|
|
[2] = {
|
|
[vector.to_string(vector.new(m_pos.x - 0.2, m_pos.y, m_pos.z + (1 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x - 0.2, m_pos.y, m_pos.z + (2 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
},
|
|
[vector.to_string(vector.new(m_pos.x - 0.2, m_pos.y, m_pos.z + (3 * 0.3)))] = {
|
|
itemstring = '',
|
|
output = {},
|
|
cooked_time = 0
|
|
}
|
|
},
|
|
}
|
|
end
|
|
|
|
meta:set_string('grid_matrix', minetest.serialize(initial_grid_matrix))
|
|
meta:set_string('infotext', infotext)
|
|
end,
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos)
|
|
local stack = player:get_wielded_item()
|
|
local stack_name = stack:get_name()
|
|
|
|
if minetest.get_item_group(stack_name, 'torch') > 0
|
|
or stack_name == 'fire:flint_and_steel'
|
|
or stack_name == 'mcl_fire:flint_and_steel'
|
|
then
|
|
local infotext = S('Stove active.') .. ' ' .. S('De-activate with shovel. Stove will de-activate by its self after a while if there are no items to cook.')
|
|
meta:set_string('infotext', infotext)
|
|
minetest.swap_node(pos, { name = 'x_farming:stove_active', param2 = node.param2 })
|
|
minetest.get_node_timer(pos):start(1)
|
|
end
|
|
|
|
return itemstack
|
|
end,
|
|
on_rotate = function()
|
|
return false
|
|
end
|
|
})
|
|
|
|
-- Active stove
|
|
minetest.register_node('x_farming:stove_active', {
|
|
description = S('Stove active'),
|
|
tiles = {
|
|
{
|
|
name = 'x_farming_stove_top_animated.png',
|
|
animation = {
|
|
type = 'vertical_frames',
|
|
aspect_w = 16,
|
|
aspect_h = 16,
|
|
length = 5
|
|
},
|
|
},
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
'x_farming_stove_side.png',
|
|
{
|
|
name = 'x_farming_stove_front_animated.png',
|
|
animation = {
|
|
type = 'vertical_frames',
|
|
aspect_w = 16,
|
|
aspect_h = 16,
|
|
length = 2
|
|
},
|
|
},
|
|
},
|
|
paramtype2 = '4dir',
|
|
is_ground_content = false,
|
|
groups = {
|
|
-- MTG
|
|
cracky = 2,
|
|
heat_source = 1,
|
|
not_in_creative_inventory = 1,
|
|
-- MCL
|
|
pickaxey = 1,
|
|
container = 4,
|
|
deco_block = 1,
|
|
material_stone = 1
|
|
},
|
|
_mcl_blast_resistance = 3.5,
|
|
_mcl_hardness = 3.5,
|
|
sounds = x_farming.node_sound_stone_defaults(),
|
|
light_source = 8,
|
|
drop = 'x_farming:stove',
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local infotext = S('Stove active.') .. ' ' .. S('De-activate with shovel. Stove will de-activate by its self after a while if there are no items to cook.')
|
|
|
|
meta:set_string('infotext', infotext)
|
|
end,
|
|
on_timer = function(pos, elapsed)
|
|
local meta = minetest.get_meta(pos)
|
|
local grid_matrix = minetest.deserialize(meta:get_string('grid_matrix'))
|
|
|
|
if not grid_matrix then
|
|
return
|
|
end
|
|
|
|
local timer_elapsed = meta:get_int('timer_elapsed') or 0
|
|
meta:set_int('timer_elapsed', timer_elapsed + 1)
|
|
|
|
-- total running time without items to cook
|
|
local total_running_time = meta:get_float('total_running_time') or 0
|
|
local grid_items = get_grid_matrix_items(grid_matrix)
|
|
|
|
if #grid_items == 0 then
|
|
total_running_time = total_running_time + elapsed
|
|
elseif total_running_time > 0 then
|
|
-- reset time when added another item to cook
|
|
total_running_time = 0
|
|
end
|
|
|
|
if total_running_time > 180 then
|
|
-- extinguish stove
|
|
total_running_time = 0
|
|
meta:set_float('total_running_time', total_running_time)
|
|
|
|
local node = minetest.get_node(pos)
|
|
minetest.swap_node(pos, { name = 'x_farming:stove', param2 = node.param2 })
|
|
meta:set_int('timer_elapsed', 0)
|
|
local infotext = S('Stove inactive.') .. ' ' .. S('Activate by torch or flint and steel.')
|
|
meta:set_string('infotext', infotext)
|
|
stop_stove_sound(pos)
|
|
|
|
return false
|
|
end
|
|
|
|
-- play sound
|
|
if timer_elapsed == 0 or (timer_elapsed + 1) % 5 == 0 then
|
|
local sound_id = minetest.sound_play('x_farming_stove_active', { pos = pos, max_hear_distance = 16, gain = 0.25 })
|
|
local hash = minetest.hash_node_position(pos)
|
|
|
|
stove_fire_sounds[hash] = stove_fire_sounds[hash] or {}
|
|
table.insert(stove_fire_sounds[hash], sound_id)
|
|
|
|
-- Only remember the 3 last sound handles
|
|
if #stove_fire_sounds[hash] > 3 then
|
|
table.remove(stove_fire_sounds[hash], 1)
|
|
end
|
|
|
|
-- Remove the sound ID automatically from table after 11 seconds
|
|
minetest.after(11, function()
|
|
if not stove_fire_sounds[hash] then
|
|
return
|
|
end
|
|
|
|
for f = #stove_fire_sounds[hash], 1, -1 do
|
|
if stove_fire_sounds[hash][f] == sound_id then
|
|
table.remove(stove_fire_sounds[hash], f)
|
|
end
|
|
end
|
|
|
|
if #stove_fire_sounds[hash] == 0 then
|
|
stove_fire_sounds[hash] = nil
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- cook items, update cooked times
|
|
-- if cooked drop items and remove from meta
|
|
for row, items in ipairs(grid_matrix) do
|
|
for item_pos, item in pairs(items) do
|
|
if item.itemstring ~= '' then
|
|
grid_matrix[row][item_pos].cooked_time = (grid_matrix[row][item_pos].cooked_time or 0) + elapsed
|
|
|
|
-- drop cooked item and remove from meta
|
|
if grid_matrix[row][item_pos].cooked_time > item.output.time then
|
|
-- drop cooked item
|
|
minetest.add_item(vector.from_string(item_pos), ItemStack(item.output.item))
|
|
|
|
-- drop recipe replacements
|
|
for _, replacement in ipairs(item.output.replacements) do
|
|
minetest.add_item(vector.from_string(item_pos), ItemStack(replacement))
|
|
end
|
|
|
|
-- remove from metadata
|
|
local removed_items_result = remove_item_from_grid_matrix(grid_matrix, item)
|
|
|
|
if removed_items_result.removed_from_pos then
|
|
-- remove entity
|
|
for _, o in ipairs(minetest.get_objects_inside_radius(pos, 0.7)) do
|
|
local armor_groups = o:get_armor_groups() or {}
|
|
|
|
if armor_groups.stove_food and armor_groups.stove_food > 0 then
|
|
if o:get_pos() and vector.to_string(vector.new(o:get_pos())) == removed_items_result.removed_from_pos then
|
|
o:remove()
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Play cooling sound
|
|
minetest.sound_play('x_farming_stove_sizzle', {
|
|
pos = vector.from_string(item_pos),
|
|
max_hear_distance = 16,
|
|
gain = 0.07
|
|
}, true)
|
|
else
|
|
add_item_smoke_particles(vector.from_string(item_pos))
|
|
end
|
|
|
|
-- restore entity items after `clearobjects`
|
|
local missing_items = table.copy(items)
|
|
|
|
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 0.7)) do
|
|
local armor_groups = obj:get_armor_groups() or {}
|
|
|
|
if armor_groups.stove_food and armor_groups.stove_food > 0 then
|
|
local lua_ent = obj:get_luaentity()
|
|
|
|
if lua_ent and obj:get_pos() then
|
|
-- match entity with metadata
|
|
-- removing the one we found and leaving
|
|
-- only the ones what needs to be restored
|
|
for ent_pos, value in pairs(missing_items) do
|
|
local obj_pos = vector.to_string(vector.new(obj:get_pos()))
|
|
|
|
if obj_pos == ent_pos then
|
|
missing_items[obj_pos] = nil
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for ent_pos, value in pairs(missing_items) do
|
|
if value.itemstring ~= '' then
|
|
local staticdata = {
|
|
itemname = value.itemstring
|
|
}
|
|
|
|
local obj = minetest.add_entity(
|
|
vector.from_string(ent_pos),
|
|
'x_farming:stove_food',
|
|
minetest.serialize(staticdata)
|
|
)
|
|
|
|
if obj then
|
|
obj:set_rotation(vector.from_string(value.ent_rot))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- set meta
|
|
meta:set_string('grid_matrix', minetest.serialize(grid_matrix))
|
|
meta:set_float('total_running_time', total_running_time)
|
|
|
|
return true
|
|
end,
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos)
|
|
local wield_stack = player:get_wielded_item()
|
|
local wield_stack_name = wield_stack:get_name()
|
|
|
|
-- de-activate stove
|
|
if minetest.get_item_group(wield_stack_name, 'shovel') > 0 then
|
|
minetest.swap_node(pos, { name = 'x_farming:stove', param2 = node.param2 })
|
|
meta:set_int('timer_elapsed', 0)
|
|
local infotext = S('Stove inactive.') .. ' ' .. S('Activate by torch or flint and steel.')
|
|
meta:set_string('infotext', infotext)
|
|
stop_stove_sound(pos)
|
|
end
|
|
|
|
-- check if item is cook-able
|
|
local output = minetest.get_craft_result({
|
|
method = 'cooking',
|
|
width = 1,
|
|
items = { itemstack }
|
|
})
|
|
|
|
if output.item:is_empty() then
|
|
-- item is not cook-able
|
|
return itemstack
|
|
end
|
|
|
|
-- check if space above
|
|
if minetest.get_node(vector.new(pos.x, pos.y + 1, pos.z)).name ~= 'air' then
|
|
return itemstack
|
|
end
|
|
|
|
local grid_matrix = minetest.deserialize(meta:get_string('grid_matrix'))
|
|
local grid_items = get_grid_matrix_items(grid_matrix)
|
|
|
|
if #grid_items >= 6 then
|
|
-- stove is full
|
|
return itemstack
|
|
end
|
|
|
|
local _output = {
|
|
time = output.time,
|
|
replacements = {},
|
|
item = output.item:to_table()
|
|
}
|
|
|
|
for _, value in ipairs(output.replacements) do
|
|
table.insert(_output.replacements, value:to_table())
|
|
end
|
|
|
|
-- degrees to radians
|
|
local pitch = -90 * (math.pi / 180)
|
|
local roll = math.pi * 2 + node.param2 * math.pi / 2
|
|
|
|
-- x = pitch (elevation), y = yaw (heading), z = roll (bank)
|
|
local ent_rot = vector.new(pitch, 0, roll)
|
|
local added_item_result = add_item_to_grid_matrix(grid_matrix, {
|
|
itemstring = wield_stack_name,
|
|
output = _output,
|
|
ent_rot = vector.to_string(ent_rot),
|
|
cooked_time = 0
|
|
})
|
|
|
|
if not (added_item_result.added_to_row and added_item_result.added_to_pos) then
|
|
return itemstack
|
|
end
|
|
|
|
local ent_pos = vector.from_string(added_item_result.added_to_pos)
|
|
|
|
if not ent_pos then
|
|
return itemstack
|
|
end
|
|
|
|
-- Add Entity
|
|
local staticdata = {
|
|
itemname = wield_stack_name
|
|
}
|
|
|
|
local obj = minetest.add_entity(
|
|
ent_pos,
|
|
'x_farming:stove_food',
|
|
minetest.serialize(staticdata)
|
|
)
|
|
|
|
if obj then
|
|
-- 90 degress to radians
|
|
obj:set_rotation(ent_rot)
|
|
end
|
|
|
|
-- Play cooling sound
|
|
minetest.sound_play('x_farming_stove_sizzle_put', {
|
|
pos = ent_pos,
|
|
max_hear_distance = 16,
|
|
gain = 0.1
|
|
}, true)
|
|
|
|
meta:set_string('grid_matrix', minetest.serialize(grid_matrix))
|
|
itemstack:take_item()
|
|
|
|
return itemstack
|
|
end,
|
|
on_destruct = function(pos)
|
|
stop_stove_sound(pos)
|
|
end,
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
if not oldmetadata.fields.grid_matrix then
|
|
return
|
|
end
|
|
|
|
local objs = minetest.get_objects_inside_radius(pos, 0.7)
|
|
local grid_matrix = minetest.deserialize(oldmetadata.fields.grid_matrix)
|
|
local grid_items = get_grid_matrix_items(grid_matrix)
|
|
|
|
-- remove entitites
|
|
for _, obj in ipairs(objs) do
|
|
local armor_groups = obj:get_armor_groups() or {}
|
|
|
|
if armor_groups.stove_food and armor_groups.stove_food > 0 then
|
|
obj:remove()
|
|
end
|
|
end
|
|
|
|
-- drop items
|
|
for _, item in ipairs(grid_items) do
|
|
minetest.add_item(vector.new(pos.x, pos.y + 0.7, pos.z), ItemStack(item.itemstring))
|
|
end
|
|
end,
|
|
on_rotate = function()
|
|
return false
|
|
end
|
|
})
|