InsaneProtestor/mods/ip_terumet/interop/terumet_api.lua
2022-11-22 00:44:34 -05:00

235 lines
10 KiB
Lua

-- API for other mods to interface with this mod
-- register an external block for use in making heatline versions and/or reinforced versions
-- if you wish to exclude one or the other, pass {heatline=true} or {reinforced=true} as 3rd argument
-- register an item that provide Repair Material to Equipment Reformer
-- value = repair material value provided by 1 item
function terumet.register_repair_material(id, value)
-- TODO error checking
terumet.options.repm.repair_mats[id] = value
end
-- register a tool that can be repaired in Equipment Reformer
-- needed_mat = amount of repair material value to repair fully worn tool
function terumet.register_repairable_item(id, needed_mat)
-- TODO error checking
terumet.options.repm.repairable[id] = needed_mat
end
-- register a new alloy smelter recipe
-- required data keys and descriptions:
local ALLOY_REQUIRED = {
result='[itemstack string] what will be output',
input='[table, 1-4 stacks] table of itemstacks consumed as input',
time='[float] time in seconds to process',
flux='[integer] amount of terumetal flux consumed from tank',
}
function terumet.register_alloy_recipe(data)
if not data then
error('terumet.register_alloy_recipe: no recipe data provided')
end
for req_key, desc in pairs(ALLOY_REQUIRED) do
if not data[req_key] then
error(string.format('terumet.register_alloy_recipe: recipe data is missing required key %s: %s', req_key, desc))
end
end
if type(data.input) ~= 'table' or #data.input < 1 or #data.input > 4 then
error('terumet.register_alloy_recipe: invalid input; must be a table of 1-4 itemstack strings (inclusive)')
end
table.insert(terumet.options.smelter.recipes, 1, data)
end
-- TODO error checking
function terumet.register_vacoven_recipe(data)
table.insert(terumet.options.vac_oven.recipes, data)
end
-- register a new crystallized material with the provided data
-- ID of created item will be 'terumet:item_cryst_<SUFFIX>'
-- IMPORTANT NOTE: a single source item can only be defined as a single crystal
-- for example, trying to add a new crystal for 'default:copper_lump' will override the default one
--
-- required data keys and descriptions:
local CRYSTAL_REQUIRED = {
suffix='[string] ID suffix for crystallized item',
color='[colorspec] minetest colorspec for crystallized item color',
name='[string] name of crystallized item',
cooking_result='[itemstack string] result of cooking crystallized item',
}
function terumet.register_crystal(data)
local this_func = 'terumet.register_crystal'
if not data then
error(this_func..': no data provided')
end
for req_key, desc in pairs(CRYSTAL_REQUIRED) do
if not data[req_key] then
error(string.format('%s: data missing required key %s: %s', this_func, req_key, desc))
end
end
local crys_id = terumet.id('item_cryst_'..data.suffix)
minetest.register_craftitem( crys_id, {
description = data.name,
inventory_image = terumet.crystal_tex(data.color),
})
minetest.register_craft{ type = 'cooking',
output = data.cooking_result,
recipe = crys_id,
cooktime = 5
}
return crys_id -- returns crystal item ID
end
-- register an item that can be put into crystal vulcanizer
-- requires source item and result, optionally include integer modifier
-- by default creates 2 result items, but count_modifier is added to that value
-- +1 more result item if vulcanizer has upgrade
function terumet.register_vulcan_result(source, result, count_modifier, specialized)
count_modifier = count_modifier or 0
local this_func = 'terumet.register_vulcan_result'
if not source then error(this_func..': no source item provided') end
if not result then error(this_func..': no result item provided') end
local count = 2 + count_modifier
if( count < 1 ) then count = 1 end
terumet.options.vulcan.recipes[source] = {result, count, specialized}
end
-- register that a node can generate heat when extracted by the Environmental Entropy Extraction Heater (EEE Heater)
local ENTROPIC_REQUIRED = {
node='[string] id of node that can be extracted',
hu_per_s='[integer] number of heat units extracted per second',
extract_time='[float] total amount of time to extract this node',
}
-- optional keys:
-- change_to: [string] what node this node will change into after extraction - if nil, the node will not change and thus can be extracted over and over (like air by default)
function terumet.register_entropic_node(data)
if not data then
error('terumet.register_entropic_node: no data provided')
end
for req_key, desc in pairs(ENTROPIC_REQUIRED) do
if not data[req_key] then
error(string.format('terumet.register_entropic_node: data is missing required key %s: %s', req_key, desc))
end
end
terumet.options.heater.entropy.EFFECTS[data.node] = {hu_per_s=data.hu_per_s, extract_time=data.extract_time, change_to=data.change_to}
end
local STANDARD_INV_LISTS = {'in', 'out', 'fuel', 'upgrade'}
local EXTERNAL_MACHINES = {}
local MACHINE_REQUIRED = {
name='[string] Name of machine',
node_tiles='[minetest tiles definition] Tiles for machine node',
heat_max='[integer] Base maximum heat units that can be stored by machine',
input_slots='[integer, 0-4 expected] Size of input inventory',
output_slots='[integer, 0-4 expected] Size of output inventory',
has_fuel_slot='[boolean] Whether machine has direct fuel slot',
upgrade_slots='[integer, 0-6 expected] Size of upgrade inventory',
tick_time='[float] Time in seconds between machine ticks',
tick_function='[fn(machine_state, dt) -> boolean] Function called when machine ticks. Return true to tick again in tick_time seconds.'
}
-- optional keys:
-- heat_provider: [boolean] true if machine generates/provides heat to adjacent machines
-- heat_transfer: [integer] Maximum amount of heat machine can send in 1 tick
-- node_name: [string] name to give machine's node. if not provided, uses same as 'name'
-- node_param2: [string] param2 to give machine's node (same as minetest's nodedef param2 setting: facedir/none/etc. )
-- custom_init: [fn(pos, meta, inv) -> nil] custom initialization for setting inventories or other metadata of a new machine
-- custom_write: [fn(machine_state)] function to call when saving machine state to metadata
-- custom_read: [fn(machine_state)] function to call when reading machine state from metadata
-- -- machine formspec options --
-- <basic>
-- machinefs_theme: [string] definition of background/listcolors for machine's formspec
-- machinefs_func: [fn(machine_state) -> string] custom function that returns formspec definition for main area above inventory in interface
-- -- <OR advanced> --
-- custom_fsdef: [fsdef table] entire customized formspec definition table for machine to use, see terumet/machine/machine.lua:build_fs for more information
-- [IMPORTANT] => using custom_fsdef completely overrides use of machinefs_* funcs and default formspec so everything must be defined
function terumet.register_heat_machine( id, data )
if not data then
error('terumet.register_heat_machine: no data provided')
end
for req_key, desc in pairs(MACHINE_REQUIRED) do
if not data[req_key] then
error(string.format('terumet.register_heat_machine: data is missing required key %s: %s', req_key, desc))
end
end
local machine_tm_class = {
name = data.name,
timer = data.tick_time,
fsdef = data.custom_fsdef or {
control_buttons = {
terumet.machine.buttondefs.HEAT_XFER_TOGGLE,
},
machine = data.machinefs_func or terumet.NO_FUNCTION,
input = {data.input_slots > 0},
output = {data.output_slots > 0},
fuel_slot = {data.fuel_slot},
theme = data.machinefs_theme,
},
default_heat_xfer = (data.heat_provider and terumet.machine.HEAT_XFER_MODE.PROVIDE_ONLY) or terumet.machine.HEAT_XFER_MODE.ACCEPT,
get_drop_contents = function(machine)
local drops = {}
for _,std_list in ipairs(STANDARD_INV_LISTS) do
default.get_inventory_drops(machine.pos, std_list, drops)
end
return drops
end
}
local node_def = terumet.machine.nodedef{
description = data.node_name or data.name,
tiles = data.node_tiles,
param2 = data.node_param2,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if data.upgrade_slots > 0 then inv:set_size('upgrade', data.upgrade_slots) end
if data.input_slots > 0 then inv:set_size('in', data.input_slots) end
if data.output_slots > 0 then inv:set_size('out', data.output_slots) end
if data.has_fuel_slot then inv:set_size('fuel', 1) end
if data.custom_init then data.custom_init(pos, meta, inv) end
local init = {
class = machine_tm_class,
state = 0,
state_time = 0,
heat_level = 0,
max_heat = data.heat_max,
status_text = 'New',
inv = inv,
meta = meta,
pos = pos,
}
terumet.machine.write_state(pos, init)
terumet.machine.set_timer(init)
end,
on_timer = function(pos, dt)
local machine = terumet.machine.tick_read_state(pos)
local re_tick = false
if not terumet.machine.check_overheat(machine, data.heat_max) then
re_tick = data.tick_function(machine, dt)
if machine.heat_xfer_mode == terumet.machine.HEAT_XFER_MODE.PROVIDE_ONLY then
terumet.machine.push_heat_adjacent(machine, data.heat_transfer or 50)
end
if data.has_fuel_slot then
terumet.machine.process_fuel(machine)
re_tick = not machine.need_heat
end
end
-- write status back to meta
terumet.machine.write_state(pos, machine)
return re_tick
end,
_terumach_class = machine_tm_class
}
minetest.register_node( id, node_def )
EXTERNAL_MACHINES[id] = data
end