From bb4e8618287385d9c8c7ae56cfe5287a7674dd09 Mon Sep 17 00:00:00 2001 From: SFENCE Date: Sat, 4 Sep 2021 18:47:47 +0200 Subject: [PATCH] Add basic extensions support for power, liquid, items and control. --- API.md | 53 ++- appliance.lua | 827 +++++++++++++++++++++------------------------- control.lua | 21 ++ extensions.lua | 9 + functions.lua | 40 ++- init.lua | 1 + item_supply.lua | 123 +++++++ liquid_supply.lua | 67 ++++ power_supply.lua | 250 ++++++++++++++ 9 files changed, 937 insertions(+), 454 deletions(-) create mode 100644 control.lua create mode 100644 extensions.lua create mode 100644 item_supply.lua create mode 100644 liquid_supply.lua create mode 100644 power_supply.lua diff --git a/API.md b/API.md index e2468db..09a1401 100644 --- a/API.md +++ b/API.md @@ -1,10 +1,53 @@ -Appliance API -================ +# Appliance API + See example folder for appliance examples. -Appliance table parameters -========================== +## Appliances API functions (common) + +### appliances.swap_node(pos, name) + +* Function swap node by using minetest.swap_node fucntion. +* Metadata of node isn't affected. +* pos - node position +* name - new node name + +### appliances.register_craft_type(type_name, type_def) + +* Register craft type. +* type_name - Unique name of crafting type +* type_def - table with definition of crafting type + * description - description of crafting type + * icon - icon picture name + * width - width of recipe + * height - height of recipe + * dynamic_display_size - unified_inventory callback only + +### appliances.register_craft(craft_def) + +* Register craft recipe. +* craft_def - table with craft recipe definition + * type - type of recipe + * output - recipe product + * items - input items + +## Appliance recipes + +## Appliance power supply + +Some power supply should be always registered. + +## Appliance object functions + +Methods of object appliances.appliance. + +### appliance:new(def) + +### appliance:power_data_register(power_data) + +* Take only useful power_data + +## Appliance table parameters appliance.input\_stack = "input"; -- input stack name, can be nil, can be same as output\_stack appliance.input\_stack\_size = 1; -- zero value will disable stack creation @@ -32,7 +75,7 @@ Power data ### Keys - ordered by priority: "LV", "MV", "HV" -> powered by technic LV, MV or HV "mesecons" -> powered by messecons - "hand" -> powered by punching + "punch" -> powered by punching "time" -> only time is need to create output diff --git a/appliance.lua b/appliance.lua index 6266049..d6f0489 100644 --- a/appliance.lua +++ b/appliance.lua @@ -25,200 +25,87 @@ appliance.use_stack_size = 1; appliance.output_stack = "output"; appliance.output_stack_size = 4; --- -appliance.have_tubes = true; +appliance.items_connect_sides = {"right", "left"}; -- right, left, front, back, top, bottom --- is appliance connected to water? -local pipe_connections = { - left = minetest.dir_to_facedir({x=0,y=0,z=-1}), - right = minetest.dir_to_facedir({x=0,y=0,z=1}), - top = nil, - bottom = nil, - front = minetest.dir_to_facedir({x=-1,y=0,z=0}), - back = minetest.dir_to_facedir({x=1,y=0,z=0}), -} -appliance.need_water = false; -appliance.pipe_side = "top"; -- right, left, front, back, bottom -if appliances.have_pipeworks then - local pipeworks_pipe_loaded = { - ["pipeworks:pipe_1_loaded"] = true, - ["pipeworks:pipe_2_loaded"] = true, - ["pipeworks:pipe_3_loaded"] = true, - ["pipeworks:pipe_4_loaded"] = true, - ["pipeworks:pipe_5_loaded"] = true, - ["pipeworks:pipe_6_loaded"] = true, - ["pipeworks:pipe_7_loaded"] = true, - ["pipeworks:pipe_8_loaded"] = true, - ["pipeworks:pipe_9_loaded"] = true, - ["pipeworks:pipe_10_loaded"] = true, - }; - local pipeworks_pipe_with_facedir_loaded = { - ["pipeworks:valve_on_loaded"] = true, - ["pipeworks:entry_panel_loaded"] = true, - ["pipeworks:flow_sensor_loaded"] = true, - ["pipeworks:straight_pipe_loaded"] = true, - }; - - function appliance:have_water(pos) - local node = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}); - if node then - if (pipeworks_pipe_loaded[node.name]) then +appliance.liquid_connect_sides = {"top"}; -- right, left, front, back, top, bottom +function appliance:have_liquid(pos, meta) + for supply_name, supply_data in pairs(self.liquid_data) do + local supply = appliances.liquid_supplies[supply_name] + if supply and supply.have_liquid then + if (supply.have_liquid(self, supply_data, pos, meta)) then return true; end - if (pipeworks_pipe_with_facedir_loaded[node.name]) then - if (minetest.facedir_to_dir(node.param2).y~=0) then - return true; - end - end end - return false; end -else - function appliance:have_water(pos) - if (minetest.find_node_near(pos, 1, "group:water", false)) then - return true; - else - return false; + return false; +end + +appliance.power_connect_sides = {"back"}; -- right, left, front, back, top, bottom + +appliance.power_data = {}; +appliance.liquid_data = {}; +appliance.item_data = {}; +appliance.control_data = {}; + +appliance.meta_infotext = "infotext"; + +local function disable_supply_data(supplies_data, supply_data) + if (supply_data~=nil) then + if (supply_data.disable~=nil) then + for _,key in pairs(supply_data.disable) do + supplies_data[key] = nil; + end + supply_data.disable = nil; end end end - ---[[ -local power_data = { - ["LV"] = { - demand = 100, - run_speed = 1, - -- list of power_data to disable if this one is aviable - -- used when power data is registered by function - disable = {"mesecons","time"}, - }, - ["mesecons"] = { - run_speed = 1, - disable = {"LV","time"}, - }, - ["time"] = { - run_speed = 1, - disable = {"LV","mesecons"}, - }, -} ---]] - -appliance.power_data = nil; -- nil mean, power is not required -appliance.meta_infotext = "infotext"; - -local function disable_power_data(power_data, eu_data) - if (eu_data~=nil) then - if (eu_data.disable~=nil) then - for _, key in pairs(eu_data.disable) do - power_data[key] = nil; - end - eu_data.disable = nil; - end +local function disable_supplies_data(supplies_data) + for _,supply_data in pairs(supplies_data) do + disable_supply_data(supplies_data, supply_data); end - + return supplies_data; end function appliance:power_data_register(power_data) - if appliances.have_technic then - disable_power_data(power_data, power_data["LV"]); - disable_power_data(power_data, power_data["MV"]); - disable_power_data(power_data, power_data["HV"]); - end - if appliances.have_mesecons then - disable_power_data(power_data, power_data["mesecons"]); - end - - if true then - disable_power_data(power_data, power_data["punch"]); - disable_power_data(power_data, power_data["time"]); - end - self.power_data = power_data; + self.power_data = disable_supplies_data(power_data); +end +function appliance:liquid_data_register(liquid_data) + self.liquid_data = disable_supplies_data(liquid_data); +end +function appliance:item_data_register(item_data) + self.item_data = disable_supplies_data(item_data); +end +function appliance:control_data_register(control_data) + self.control_data = disable_supplies_data(control_data); end -function appliance:is_powered(meta) - if appliances.have_technic then - -- check if node is powered LV - local eu_data = self.power_data["LV"]; - if (eu_data~=nil) then - local eu_demand = eu_data.demand; - local eu_input = meta:get_int("LV_EU_input"); - if (eu_input>=eu_demand) then - return eu_data.run_speed; +function appliance:is_powered(pos, meta) + for supply_name, supply_data in pairs(self.power_data) do + local supply = appliances.power_supplies[supply_name] + if supply and supply.is_powered then + local speed = supply.is_powered(self, supply_data, pos, meta) + if (speed~=0) then + return speed; end end - -- check if node is powered MV - local eu_data = self.power_data["MV"]; - if (eu_data~=nil) then - local eu_demand = eu_data.demand; - local eu_input = meta:get_int("MV_EU_input"); - if (eu_input>=eu_demand) then - return eu_data.run_speed; - end - end - -- check if node is powered HV - local eu_data = self.power_data["HV"]; - if (eu_data~=nil) then - local eu_demand = eu_data.demand; - local eu_input = meta:get_int("HV_EU_input"); - if (eu_input>=eu_demand) then - return eu_data.run_speed; - end - end - end - if appliances.have_mesecons then - -- mesecon powered - local eu_data = self.power_data["mesecons"]; - if (eu_data~=nil) then - local is_powered = meta:get_int("is_powered"); - if (is_powered~=0) then - return eu_data.run_speed; - end - end - end - if true then - -- punch - local eu_data = self.power_data["punch"]; - if (eu_data~=nil) then - local is_punched = meta:get_int("is_punched"); - if (is_punched~=0) then - return eu_data.run_speed; - end - end - -- time only - local eu_data = self.power_data["time"]; - if (eu_data~=nil) then - return eu_data.run_speed; - end end return 0; end -function appliance:power_need(meta) - local eu_data = self.power_data["LV"]; - if (eu_data~=nil) then - meta:set_int("LV_EU_demand", eu_data.demand) - end - local eu_data = self.power_data["MV"]; - if (eu_data~=nil) then - meta:set_int("MV_EU_demand", eu_data.demand) - end - local eu_data = self.power_data["HV"]; - if (eu_data~=nil) then - meta:set_int("HV_EU_demand", eu_data.demand) +function appliance:power_need(pos, meta) + for supply_name, supply_data in pairs(self.power_data) do + local supply = appliances.power_supplies[supply_name] + if supply and supply.power_need then + supply.power_need(self, supply_data, pos, meta) + end end end -function appliance:power_idle(meta) - local eu_data = self.power_data["LV"]; - if (eu_data~=nil) then - meta:set_int("LV_EU_demand", 0) - end - local eu_data = self.power_data["MV"]; - if (eu_data~=nil) then - meta:set_int("MV_EU_demand", 0) - end - local eu_data = self.power_data["HV"]; - if (eu_data~=nil) then - meta:set_int("HV_EU_demand", 0) +function appliance:power_idle(pos, meta) + for supply_name, supply_data in pairs(self.power_data) do + local supply = appliances.power_supplies[supply_name] + if supply and supply.power_idle then + supply.power_idle(self, supply_data, pos, meta) + end end end @@ -253,7 +140,13 @@ appliance.have_usage = true; appliance.stoppable_production = true; appliance.stoppable_consumption = true; +appliance.have_control = false; + function appliance:recipe_register_input(input_name, input_def) + if (not self.have_input) then + minetest.log("error", "Input is disabled. Registration of input recipe cannot be finished."); + return; + end if (self.input_stack_size <= 1) then self.recipes.inputs[input_name] = input_def; else @@ -271,6 +164,10 @@ function appliance:recipe_register_input(input_name, input_def) end end function appliance:recipe_register_usage(usage_name, usage_def) + if (not self.have_usage) then + minetest.log("error", "Usage is disabled. Registration of usage recipe cannot be finished."); + return; + end if (not self.recipes.usages) then self.recipes.usages = {}; end @@ -279,48 +176,50 @@ end function appliance:recipe_aviable_input(inventory) local input = nil; - if (self.input_stack_size <= 1) then - local input_stack = inventory:get_stack(self.input_stack, 1) - local input_name = input_stack:get_name(); - input = self.recipes.inputs[input_name]; - if (input==nil) then - return nil, nil - end - if (input_stack:get_count()0) or (consumption_time>0)) then self:interrupt_production(pos, meta, inv, use_input, use_usage, production_time, consumption_time); end - self:waiting(pos, meta); + if ((use_input==nil) and self.have_input) or (use_usage==nil) and self.have_usage then + self:deactivate(pos, meta); + return false; + else + self:waiting(pos, meta); + end return true; end @@ -875,11 +717,13 @@ function appliance:cb_on_timer(pos, elapsed) -- time update local production_step_size = 0; local consumption_step_size = 0; - if self.recipes.usages then + if use_input and use_usage then production_step_size = self:recipe_step_size(use_usage.production_step_size*speed); consumption_step_size = self:recipe_step_size(speed*use_input.consumption_step_size); - else + elseif use_input then production_step_size = self:recipe_step_size(speed); + elseif use_usage then + consumption_step_size = self:recipe_step_size(speed); end production_time = production_time + production_step_size; @@ -902,27 +746,36 @@ function appliance:cb_on_timer(pos, elapsed) end -- production done - if (production_time>=use_input.production_time) then - local output = self:recipe_select_output(use_input.outputs); - if (not self:recipe_room_for_output(inv, output)) then - self:waiting(pos, meta); - return true; + if (use_input) then + if (production_time>=use_input.production_time) then + local output = self:recipe_select_output(use_input.outputs); + if (not self:recipe_room_for_output(inv, output)) then + self:waiting(pos, meta); + return true; + end + self:recipe_output_to_stack(inv, output); + self:recipe_input_from_stack(inv, use_input); + production_time = 0; + meta:set_int("production_time", 0); end - self:recipe_output_to_stack(inv, output); - self:recipe_input_from_stack(inv, use_input); - production_time = 0; - meta:set_int("production_time", 0); end if use_usage then - self:update_formspec(meta, production_time, use_input.production_time, consumption_time, use_usage.consumption_time) - meta:set_int("production_time", production_time) + if (use_input) then + self:update_formspec(meta, production_time, use_input.production_time, consumption_time, use_usage.consumption_time) + meta:set_int("production_time", production_time) + else + self:update_formspec(meta, 0, 3, consumption_time, use_usage.consumption_time) + end meta:set_int("consumption_time", consumption_time) - else + elseif (use_input) then self:update_formspec(meta, production_time, use_input.production_time, 0, 1) meta:set_int("production_time", production_time) end + -- cb_on_production callback + self:cb_on_production(pos, meta, use_input, use_usage); + -- have aviable production recipe? local continue_timer = self:after_timer_step(pos, meta, inv, production_time); if (continue_timer==false) then @@ -954,7 +807,7 @@ function appliance:cb_on_metadata_inventory_put(pos, listname, index, stack, pla -- have aviable production recipe? local use_input, use_usage = self:recipe_aviable_input(inv) - if use_input then + if ((use_input~=nil) or (not self.have_input)) or ((use_usage~=nil) or (not self.have_usage)) then self:activate(pos, meta); return else @@ -997,16 +850,11 @@ function appliance:cb_on_construct(pos) inv:set_size(self.output_stack, self.output_stack_size) end end + self:call_on_construct(pos, meta) end function appliance:cb_after_place_node(pos, placer, itemstack, pointed_thing) - if appliance.have_pipeworks then - pipeworks.scan_for_pipe_objects(pos); - pipeworks.scan_for_tube_objects(pos); - end - if (not appliance.have_mesecon) then - minetest.get_meta(pos):set_int("is_powered", 1); - end + self:call_after_place_node(pos, placer, itemstack, pointed_thing) end -- register appliance @@ -1018,6 +866,21 @@ function appliance:register_nodes(shared_def, inactive_def, active_def) local node_def_inactive = table.copy(shared_def); + -- fix data (supplies, controls) + self.extensions_data = {} + for power_name,power_data in pairs(self.power_data) do + self.extensions_data[power_name] = power_data; + end + for liquid_name,liquid_data in pairs(self.liquid_data) do + self.extensions_data[liquid_name] = liquid_data; + end + for item_name,item_data in pairs(self.item_data) do + self.extensions_data[item_name] = item_data; + end + for control_name,control_data in pairs(self.control_data) do + self.extensions_data[control_name] = control_data; + end + -- use .."" to prevent string object share node_def_inactive.description = self.node_description..""; if (self.node_help) then @@ -1025,91 +888,9 @@ function appliance:register_nodes(shared_def, inactive_def, active_def) end node_def_inactive.short_description = self.node_description..""; - local need_power = false; - local technic_power = false; - local mesecons_power = false; - if self.power_data then - need_power = true; - end - if appliances.have_technic then - if self.power_data then - if self.power_data["LV"] then - node_def_inactive.groups.technic_machine = 1; - node_def_inactive.groups.technic_lv = 1; - technic_power = true; - end - if self.power_data["MV"] then - node_def_inactive.groups.technic_machine = 1; - node_def_inactive.groups.technic_mv = 1; - technic_power = true; - end - if self.power_data["HV"] then - node_def_inactive.groups.technic_machine = 1; - node_def_inactive.groups.technic_hv = 1; - technic_power = true; - end - end - end - if appliances.have_mesecons then - if self.power_data then - if self.power_data["no_technic"] then - if (not appliances.have_technic) then - mesecons_power = true; - end - end - if self.power_data["mesecons"] then - mesecons_power = true; - end - end - end - if technic_power then - -- power connect (technic) - node_def_inactive.connect_sides = {"back"}; - - node_def_inactive.technic_run = function (pos, node) - self:cb_technic_run(pos, node); - end - - self.meta_infotext = "technic_info"; - end - if mesecons_power then - -- mesecon action - node_def_inactive.mesecons = - { - effector = { - action_on = function (pos, node) - self:cb_mesecons_effector_action_off(pos, node); - end, - action_off = function (pos, node) - self:cb_mesecons_effector_action_off(pos, node); - end, - } - }; - end - if self.need_water then - -- pipe connect - - node_def_inactive.pipe_connections = {}; - node_def_inactive.pipe_connections[self.pipe_side] = true; - node_def_inactive.pipe_connections[self.pipe_side.."_param2"] = pipe_connections[self.pipe_side]; - end - if appliances.have_pipeworks then - if self.have_tubes then - node_def_inactive.groups.tubedevice = 1; - node_def_inactive.groups.tubedevice_receiver = 1; - node_def_inactive.tube = - { - insert_object = function(pos, node, stack, direction, owner) - return self:cb_tube_insert_object(pos, node, stack, direction, owner); - end, - can_insert = function(pos, node, stack, direction, owner) - return self:cb_tube_can_insert(pos, node, stack, direction, owner); - end, - connect_sides = {left = 1, right = 1}, - input_inventory = self.output_stack, - }; - end - end + self:call_update_node_def(node_def_inactive) + self:cb_after_update_node_def(node_def_inactive) + node_def_inactive.can_dig = function (pos, player) return self:cb_can_dig(pos, player); end @@ -1155,6 +936,11 @@ function appliance:register_nodes(shared_def, inactive_def, active_def) node_def_active.groups.not_in_creative_inventory = 1; + self:call_update_node_inactive_def(node_def_inactive); + self:cb_after_update_node_inactive_def(node_def_inactive) + self:call_update_node_active_def(node_def_active); + self:cb_after_update_node_active_def(node_def_inactive) + if inactive_def then for key, value in pairs(inactive_def) do node_def_inactive[key] = value; @@ -1169,24 +955,10 @@ function appliance:register_nodes(shared_def, inactive_def, active_def) minetest.register_node(self.node_name_inactive, node_def_inactive); minetest.register_node(self.node_name_active, node_def_active); - if appliances.have_technic then - if node_def_inactive.groups.technic_lv then - technic.register_machine("LV", self.node_name_inactive, technic.receiver) - technic.register_machine("LV", self.node_name_active, technic.receiver) - end - if node_def_inactive.groups.technic_mv then - technic.register_machine("MV", self.node_name_inactive, technic.receiver) - technic.register_machine("MV", self.node_name_active, technic.receiver) - end - if node_def_inactive.groups.technic_hv then - technic.register_machine("HV", self.node_name_inactive, technic.receiver) - technic.register_machine("HV", self.node_name_active, technic.receiver) - end - end - + self:call_after_register_node() end --- register recipes to unified_inventory +-- register recipes to unified_inventory/craftguide/i3 function appliance:register_recipes(inout_type, usage_type) if (self.input_stack_size<=1) then for input, recipe in pairs(self.recipes.inputs) do @@ -1240,4 +1012,163 @@ function appliance:register_recipes(inout_type, usage_type) end end +-- extensions callbacks +function appliance:call_activate(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.activate then + extension.activate(self, extension_data, pos, meta) + end + end +end +function appliance:call_deactivate(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.deactivate then + extension.deactivate(self, extension_data, pos, meta) + end + end +end +function appliance:call_running(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.running then + extension.running(self, extension_data, pos, meta) + end + end +end +function appliance:call_waiting(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.waiting then + extension.waiting(self, extension_data, pos, meta) + end + end +end +function appliance:call_no_power(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.no_power then + extension.no_power(self, extension_data, pos, meta) + end + end +end + +function appliance:call_update_node_def(node_def) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.update_node_def then + extension.update_node_def(self, extension_data, node_def) + end + end +end +function appliance:cb_after_update_node_def(node_def) +end + +function appliance:call_update_node_inactive_def(node_def) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.update_node_inactive_def then + extension.update_node_inactive_def(self, extension_data, node_def) + end + end +end +function appliance:cb_after_update_node_inactive_def(node_def) +end + +function appliance:call_update_node_active_def(node_def) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.update_node_active_def then + extension.update_node_active_def(self, extension_data, node_def) + end + end +end +function appliance:cb_after_update_node_active_def(node_def) +end + +function appliance:call_after_register_node() + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.after_register_node then + extension.after_register_node(self, extension_data) + end + end +end + +function appliance:call_on_construct(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.on_construct then + extension.on_construct(self, extension_data, pos, meta) + end + end +end + +function appliance:call_on_destruct(pos, meta) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.on_destruct then + extension.on_destruct(self, extension_data, pos, meta) + end + end +end + +function appliance:call_after_destruct(pos, oldnode) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.after_destruct then + extension.after_destruct(self, extension_data, pos, oldnode) + end + end +end + +function appliance:call_after_place_node(pos, placer, itemstack, pointed_thing) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.after_place_node then + extension.after_place_node(self, extension_data, pos, placer, itemstack, pointed_thing) + end + end +end + +function appliance:call_after_dig_node(pos, oldnode, oldmetadata, digger) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.after_dig_node then + extension.after_dig_node(self, extension_data, pos, oldnode, oldmetadata, digger) + end + end +end + +function appliance:call_can_dig(pos, player) + local can_dig = true; + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.can_dig then + if (not extension.can_dig(self, extension_data, pos, player)) then + can_dig = false; + end + end + end + return can_dig; +end + +function appliance:call_on_punch(pos, node, puncher, pointed_thing) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.on_punch then + extension.on_punch(self, extension_data, pos, node, puncher, pointed_thing) + end + end +end + +function appliance:call_on_blast(pos, intensity) + for extension_name, extension_data in pairs(self.extensions_data) do + local extension = appliances.all_extensions[extension_name] + if extension and extension.on_blast then + extension.on_blast(self, extension_data, pos, intensity) + end + end +end diff --git a/control.lua b/control.lua new file mode 100644 index 0000000..1aeed92 --- /dev/null +++ b/control.lua @@ -0,0 +1,21 @@ + +appliances.controls = {} + +function appliances.add_control(control_name, control_def) + if appliances.all_extensions[control_name] then + minetest.log("error", "Another appliances mod extension with name \""..control_name.."\" is already registered.") + return ; + end + appliances.item_supplies[control_name] = control_def; + appliances.all_extensions[control_name] = control_def; +end + +-- mesecons +if appliances.have_mesecons then + local control = + { + + }; +end + +-- digilines? diff --git a/extensions.lua b/extensions.lua new file mode 100644 index 0000000..c525489 --- /dev/null +++ b/extensions.lua @@ -0,0 +1,9 @@ + +local modpath = minetest.get_modpath(minetest.get_current_modname()); + +appliances.all_extensions = {} + +dofile(modpath.."/power_supply.lua"); +dofile(modpath.."/liquid_supply.lua"); +dofile(modpath.."/item_supply.lua"); +dofile(modpath.."/control.lua"); diff --git a/functions.lua b/functions.lua index b45865b..253301d 100644 --- a/functions.lua +++ b/functions.lua @@ -104,4 +104,42 @@ function appliances.register_craft(craft_def) end end end - + +-- generate conversion table +-- add this vector to position vector to get position on wanted side +local facedir_toside = {front={},back={},right={},left={},bottom={},top={}} +for facedir=0,23 do + axis = math.floor(facedir/4); + around = facedir%4; + facedir_toside.back[facedir] = minetest.facedir_to_dir(axis+around) + facedir_toside.front[facedir] = minetest.facedir_to_dir(axis+(around+2)%4) + facedir_toside.left[facedir] = minetest.facedir_to_dir(axis+(around+1)%4) + facedir_toside.right[facedir] = minetest.facedir_to_dir(axis+(around+3)%4) + facedir_toside.bottom[facedir] = vector.cross(facedir_toside.front[facedir], facedir_toside.left[facedir]) + facedir_toside.top[facedir] = vector.multiply(facedir_toside.bottom[facedir], -1) +end +function appliances.get_side_pos(pos_from, side) + local node_from = minetest.get_node(pos_from); + return vector.add(pos_from, facedir_toside[side][node_from.param2%32]) +end + +appliances.opposite_side = { + front = "back", + back = "front", + right = "left", + left = "right", + bottom = "top", + top = "bottom", + } + +function appliances.is_connected_to(pos_from, pos_to, sides) + local node_from = minetest.get_node(pos_from); + for _,side in pairs(sides) do + local side_pos = appliances.get_side_pos(pos_from, side); + if vector.equals(pos_to, side_pos) then + return side + end + end + return nil +end + diff --git a/init.lua b/init.lua index b1822e2..a81da9e 100644 --- a/init.lua +++ b/init.lua @@ -13,4 +13,5 @@ appliances.have_i3 = minetest.get_modpath("i3")~=nil; dofile(modpath.."/functions.lua"); dofile(modpath.."/appliance.lua"); +dofile(modpath.."/extensions.lua"); diff --git a/item_supply.lua b/item_supply.lua new file mode 100644 index 0000000..9a27820 --- /dev/null +++ b/item_supply.lua @@ -0,0 +1,123 @@ + + +appliances.item_supplies = {} + +function appliances.add_item_supply(supply_name, item_supply) + if appliances.all_extensions[supply_name] then + minetest.log("error", "Another appliances mod extension with name \""..supply_name.."\" is already registered.") + return ; + end + appliances.item_supplies[supply_name] = item_supply; + appliances.all_extensions[supply_name] = item_supply; +end + +-- pipeworks +if appliances.pipeworks then + -- tube can insert + function appliance:tube_can_insert (pos, node, stack, direction, owner) + if self.recipes then + if self.have_input then + if (self.input_stack_size <= 1) then + local input = self.recipes.inputs[stack:get_name()]; + if input then + return self:recipe_inventory_can_put(pos, self.input_stack, 1, stack, nil); + end + else + for index = 1,self.input_stack_size do + local can_insert = self:recipe_inventory_can_put(pos, self.input_stack, index, stack, nil); + if (can_insert~=0) then + return can_insert; + end + end + end + end + if self.have_usage then + local usage = self.recipes.usages[stack:get_name()]; + if usage then + return self:recipe_inventory_can_put(pos, self.use_stack, 1, stack, nil); + end + end + end + return false; + end + function appliance:tube_insert (pos, node, stack, direction, owner) + if self.recipes then + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory(); + + if self.have_input then + if (self.input_stack_size <= 1) then + local input = self.recipes.inputs[stack:get_name()]; + if input then + return inv:add_item(self.input_stack, stack); + end + else + for index = 1,self.input_stack_size do + local can_insert = self:recipe_inventory_can_put(pos, self.input_stack, index, stack, nil); + if (can_insert~=0) then + local input_stack = inv:get_stack(self.input_stack,index); + local remind = input_stack:add_item(stack); + inv:set_stack(self.input_stack,index, input_stack); + return remind; + end + end + end + end + if self.have_usage then + local usages = self.recipes.usages[stack:get_name()]; + if usages then + return inv:add_item(self.use_stack, stack); + end + end + end + + minetest.log("error", "Unexpected call of tube_insert function. Stack "..stack:to_string().." cannot be added to inventory.") + + return stack; + end + -- appliance node callbacks for pipeworks + function appliance:cb_tube_insert_object(pos, node, stack, direction, owner) + local stack = self:tube_insert(pos, node, stack, direction, owner); + + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory(); + local use_input, use_usage = self:recipe_aviable_input(inv) + if use_input then + self:activate(pos, meta); + end + + return stack; + end + function appliance:cb_tube_can_insert(pos, node, stack, direction, owner) + return self:tube_can_insert(pos, node, stack, direction, owner); + end + local item_supply = + { + update_node_def = function (self, power_data, node_def) + node_def.groups.tubedevice = 1; + node_def.groups.tubedevice_receiver = 1; + node_def.tube = + { + insert_object = function(pos, node, stack, direction, owner) + return self:cb_tube_insert_object(pos, node, stack, direction, owner); + end, + can_insert = function(pos, node, stack, direction, owner) + return self:cb_tube_can_insert(pos, node, stack, direction, owner); + end, + connect_sides = {}, + input_inventory = self.output_stack, + }; + for _,side in pairs(items_connect_sides)do + node_def.connect_sides[side] = 1 + end + end, + after_dig_node = function(self, liquid_data, pos) + pipeworks.scan_for_tube_objects(pos); + end, + after_place_node = function(self, liquid_data, pos) + pipeworks.scan_for_tube_objects(pos); + end, + }; + appliances.add_item_supply("item_tube", power_supply) +end + diff --git a/liquid_supply.lua b/liquid_supply.lua new file mode 100644 index 0000000..7d46cff --- /dev/null +++ b/liquid_supply.lua @@ -0,0 +1,67 @@ + + +appliances.liquid_supplies = {} + +function appliances.add_liquid_supply(supply_name, liquid_supply) + if appliances.all_extensions[supply_name] then + minetest.log("error", "Another appliances mod extension with name \""..supply_name.."\" is already registered.") + return ; + end + appliances.liquid_supplies[supply_name] = liquid_supply; + appliances.all_extensions[supply_name] = liquid_supply; +end + +-- pipeworks +if appliances.have_pipeworks then + local pipeworks_pipe_loaded = { + ["pipeworks:pipe_1_loaded"] = true, + ["pipeworks:pipe_2_loaded"] = true, + ["pipeworks:pipe_3_loaded"] = true, + ["pipeworks:pipe_4_loaded"] = true, + ["pipeworks:pipe_5_loaded"] = true, + ["pipeworks:pipe_6_loaded"] = true, + ["pipeworks:pipe_7_loaded"] = true, + ["pipeworks:pipe_8_loaded"] = true, + ["pipeworks:pipe_9_loaded"] = true, + ["pipeworks:pipe_10_loaded"] = true, + }; + local pipeworks_pipe_with_facedir_loaded = { + ["pipeworks:valve_on_loaded"] = true, + ["pipeworks:entry_panel_loaded"] = true, + ["pipeworks:flow_sensor_loaded"] = true, + ["pipeworks:straight_pipe_loaded"] = true, + }; + local liquid_supply = + { + -- have_liquid function + have_liquid = function(liquid_data, pos) + local node = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}); + if node then + if (pipeworks_pipe_loaded[node.name]) then + return true; + end + if (pipeworks_pipe_with_facedir_loaded[node.name]) then + if (minetest.facedir_to_dir(node.param2).y~=0) then + return true; + end + end + end + return false; + end, + update_node_def = function(liquid_data, node_def) + node_def.pipe_connections = {}; + for _,pipe_side in pairs(self.liquid_connect_sides) do + node_def.pipe_connections[pipe_side] = true; + node_def.pipe_connections[pipe_side.."_param2"] = pipe_connections[pipe_side]; + end + end, + after_place_node = function(self, liquid_data, pos) + pipeworks.scan_for_pipe_objects(pos); + end, + after_dig_node = function(self, liquid_data, pos) + pipeworks.scan_for_pipe_objects(pos); + end, + }; + appliances.add_liquid_supply("water_pipe", liquid_supply) +end + diff --git a/power_supply.lua b/power_supply.lua new file mode 100644 index 0000000..ddceedb --- /dev/null +++ b/power_supply.lua @@ -0,0 +1,250 @@ + +appliances.power_supplies = {} + +function appliances.add_power_supply(supply_name, power_supply) + if appliances.all_extensions[supply_name] then + minetest.log("error", "Another appliances mod extension with name \""..supply_name.."\" is already registered.") + return ; + end + appliances.power_supplies[supply_name] = power_supply; + appliances.all_extensions[supply_name] = power_supply; +end + +-- time +if true then + local power_supply = + { + is_powered = function (self, power_supply, pos, meta) + return power_supply.run_speed; + end, + }; + appliances.add_power_supply("time", power_supply) +end + +-- punch +if true then + local power_supply = + { + is_powered = function (self, power_supply, pos, meta) + local is_powered = meta:get_int("is_powered"); + if (is_powered~=0) then + meta:set_int("is_powered", 0); + return power_supply.run_speed; + end + return 0; + end, + power_need = function (self, power_supply, pos, meta) + meta:set_int("is_powered", 0); + end, + power_idle = function (self, power_supply, pos, meta) + meta:set_int("is_powered", 0); + end, + on_punch = function (self, power_supply, pos, node, puncher, pointed_thing) + local meta = minetest.get_meta(pos); + meta:set_int("is_powered", 1); + + end, + }; + appliances.add_power_supply("punch", power_supply) +end + +-- mesecons +if appliances.have_mesecons then + local power_supply = + { + is_powered = function (self, power_supply, pos, meta) + local is_powered = meta:get_int("is_powered"); + if (is_powered~=0) then + return power_supply.run_speed; + end + return 0; + end, + power_need = function (self, power_supply, pos, meta) + meta:set_int("LV_EU_demand", power_supply.demand) + end, + power_idle = function (self, power_supply, pos, meta) + meta:set_int("LV_EU_demand", 0) + end, + update_node_def = function (self, power_supply, node_def) + node_def.effector = { + action_on = function (pos, node) + minetest.get_meta(pos):set_int("is_powered", 1); + end, + action_off = function (pos, node) + minetest.get_meta(pos):set_int("is_powered", 0); + end, + } + end, + update_node_inactive_def = function (self, power_supply, node_def) + end, + update_node_active_def = function (self, power_supply, node_def) + end, + after_place_node = function (self, power_supply, pos, meta) + minetest.get_meta(pos):set_int("is_powered", 0); + end, + }; + appliances.add_power_supply("mesecons", power_supply) +end + +-- technic +if appliances.have_technic then + -- LV + local power_supply = + { + is_powered = function (self, power_data, pos, meta) + local eu_input = meta:get_int("LV_EU_input"); + if (eu_input>=power_data.demand) then + return power_data.run_speed; + end + return 0; + end, + power_need = function (self, power_data, pos, meta) + meta:set_int("LV_EU_demand", power_data.demand) + end, + power_idle = function (self, power_data, pos, meta) + meta:set_int("LV_EU_demand", 0) + end, + activate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + deactivate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + running = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + waiting = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + no_power = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + update_node_def = function (self, power_data, node_def) + self.meta_infotext = "technic_info"; + node_def.groups.technic_machine = 1; + node_def.groups.technic_lv = 1; + node_def.connect_sides = self.power_connect_sides; + node_def.technic_run = function (pos, node) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end + node_def.technic_no_network = function (pos, node) + end + end, + after_register_node = function (self, power_data) + technic.register_machine("LV", self.node_name_inactive, technic.receiver) + technic.register_machine("LV", self.node_name_active, technic.receiver) + end, + on_construct = function (self, power_data, pos, meta) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end, + }; + appliances.add_power_supply("LV", power_supply) + -- MV + local power_supply = + { + is_powered = function (self, power_data, pos, meta) + local eu_input = meta:get_int("MV_EU_input"); + if (eu_input>=power_data.demand) then + return power_data.run_speed; + end + return 0; + end, + power_need = function (self, power_data, pos, meta) + meta:set_int("MV_EU_demand", power_data.demand) + end, + power_idle = function (self, power_data, pos, meta) + meta:set_int("MV_EU_demand", 0) + end, + activate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + deactivate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + running = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + waiting = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + no_power = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + update_node_def = function (self, power_data, node_def) + self.meta_infotext = "technic_info"; + node_def.groups.technic_machine = 1; + node_def.groups.technic_mv = 1; + node_def.connect_sides = self.power_connect_sides; + node_def.technic_run = function (pos, node) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end + node_def.technic_no_network = function (pos, node) + end + end, + after_register_node = function (self, power_data) + technic.register_machine("MV", self.node_name_inactive, technic.receiver) + technic.register_machine("MV", self.node_name_active, technic.receiver) + end, + on_construct = function (self, power_data, pos, meta) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end, + }; + appliances.add_power_supply("MV", power_supply) + -- HV + local power_supply = + { + is_powered = function (self, power_data, pos, meta) + local eu_input = meta:get_int("HV_EU_input"); + if (eu_input>=power_data.demand) then + return power_data.run_speed; + end + return 0; + end, + power_need = function (self, power_data, pos, meta) + meta:set_int("HV_EU_demand", power_data.demand) + end, + power_idle = function (self, power_data, pos, meta) + meta:set_int("HV_EU_demand", 0) + end, + activate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + deactivate = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + running = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + waiting = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + no_power = function(self, power_data, pos, meta) + meta:set_string("infotext", meta:get_string("technic_info")); + end, + update_node_def = function (self, power_data, node_def) + self.meta_infotext = "technic_info"; + node_def.groups.technic_machine = 1; + node_def.groups.technic_hv = 1; + node_def.connect_sides = self.power_connect_sides; + node_def.technic_run = function (pos, node) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end + node_def.technic_no_network = function (pos, node) + end + end, + after_register_node = function (self, power_data) + technic.register_machine("HV", self.node_name_inactive, technic.receiver) + technic.register_machine("HV", self.node_name_active, technic.receiver) + end, + on_construct = function (self, power_data, pos, meta) + local meta = minetest.get_meta(pos); + meta:set_string("infotext", meta:get_string("technic_info")); + end, + }; + appliances.add_power_supply("HV", power_supply) +end