-- IndustrialTest -- Copyright (C) 2023 mrkubax10 -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- This program 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 General Public License for more details. -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . local machine={} local simpleElectricItemProcessor={} industrialtest.internal.mclAfterDigNode=function(pos,oldmeta,lists) -- Taken from https://git.minetest.land/MineClone2/MineClone2/src/branch/master/mods/ITEMS/mcl_furnaces/init.lua#L538 local meta=minetest.get_meta(pos) local meta2=meta meta:from_table(oldmeta) local inv=meta:get_inventory() for _,listname in ipairs(lists) do local stack=inv:get_stack(listname,1) if not stack:is_empty() then local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5} minetest.add_item(p, stack) end end meta:from_table(meta2:to_table()) end industrialtest.internal.chargeFromPowerStorageItem=function(meta,inv) local shouldRerunTimer=false local shouldUpdateFormspec=false local powerStorageSlot=inv:get_stack("powerStorage",1) if not powerStorageSlot:is_empty() then local stackMeta=powerStorageSlot:get_meta() if industrialtest.api.transferPower(stackMeta,meta,stackMeta:get_int("industrialtest.powerFlow"))>0 then shouldUpdateFormspec=true shouldRerunTimer=stackMeta:get_int("industrialtest.powerAmount")>0 and not industrialtest.api.isFullyCharged(meta) industrialtest.api.updateItemPowerText(powerStorageSlot) inv:set_stack("powerStorage",1,powerStorageSlot) end end return shouldRerunTimer,shouldUpdateFormspec end function industrialtest.internal.registerMachine(config) local definition={ description=config.displayName, on_construct=function(pos) machine.onConstruct(pos,config) end, on_destruct=function(pos) machine.onDestruct(pos,config) end, on_timer=function(pos,elapsed) local shouldRerunTimer,_=machine.onTimer(pos,elapsed,config) return shouldRerunTimer end, allow_metadata_inventory_move=function(pos,fromList,fromIndex,toList,toIndex,count) return machine.allowMetadataInventoryMove(pos,fromList,fromIndex,toList,toIndex,count,config) end, allow_metadata_inventory_put=function(pos,listname,index,stack,player) return machine.allowMetadataInventoryPut(pos,listname,index,stack,player,config) end, allow_metadata_inventory_take=function(pos,listname,index,stack,player) return machine.allowMetadataInventoryTake(pos,listname,index,stack,player,config) end, on_metadata_inventory_put=function(pos,listname,index,stack,player) machine.onMetadataInventoryPut(pos,listname,index,stack) if config.onMetadataInventoryPut then config.onMetadataInventoryPut(pos,listname,index,stack,player) end end, on_metadata_inventory_move=function(pos,fromList,fromIndex,toList,toIndex,count) machine.onMetadataInventoryMove(pos,fromList,fromIndex,toList,toIndex) if config.onMetadataInventoryPut then config.onMetadataInventoryMove(pos,fromList,fromIndex,toList,toIndex,count) end end, on_metadata_inventory_take=function(pos,listname,index,stack,player) machine.onMetadataInventoryTake(pos,listname,index,stack) if config.onMetadataInventoryTake then config.onMetadataInventoryTake(pos,listname,index,stack,player) end end, _industrialtest_updateFormspec=function(pos) machine.updateFormspec(pos,config) end, _industrialtest_getFormspec=function(pos) if config.withoutFormspec then return "" end return machine.getFormspec(pos,config) end } definition.groups._industrialtest_wrenchUnmountable=1 if config.requiresWrench then definition.drop="industrialtest:machine_block" end if config.customKeys then for key,value in pairs(config.customKeys) do definition[key]=value end end if config.groups then for key,value in pairs(config.groups) do definition.groups[key]=value end end minetest.register_node("industrialtest:"..config.name,definition) if config.registerActiveVariant then definition=table.copy(definition) definition.description=nil definition.on_timer=function(pos,elapsed) local meta=minetest.get_meta(pos) local inv=meta:get_inventory() local shouldRerunTimer=false local shouldUpdateFormspec=false if config.activeOnTimer then shouldRerunTimer,shouldUpdateFormspec=config.activeOnTimer(pos,elapsed,meta,inv) end local def=minetest.registered_nodes[minetest.get_node(pos).name] if def.groups and def.groups._industrialtest_hasPowerInput and not industrialtest.api.isFullyCharged(meta) then local networks=industrialtest.api.isAttachedToNetwork(meta) if networks then for _,network in ipairs(networks) do minetest.get_node_timer(network):start(industrialtest.updateDelay) end end end if shouldUpdateFormspec then machine.updateFormspec(pos,config) end return shouldRerunTimer end if not definition.drop then definition.drop="industrialtest:"..config.name end if config.activeCustomKeys then for key,value in pairs(config.activeCustomKeys) do definition[key]=value end end if industrialtest.mclAvailable then definition.groups.not_in_creative_inventory=1 definition._doc_items_create_entry=false end minetest.register_node("industrialtest:"..config.name.."_active",definition) end industrialtest.api.addTag("industrialtest:"..config.name,"usesTimer") end local function craftResultProxy(method,item) if method=="cooking" then local output,after=minetest.get_craft_result({ method=method, width=1, items={item} }) return { item=output.item, time=output.time, src=after.items[1] } elseif method=="industrialtest.macerating" then local output=industrialtest.api.getMaceratorRecipeResult(item:get_name()) if not output then return { item=ItemStack(), time=0, src=item } end local srcAfter=ItemStack(item:get_name()) srcAfter:set_count(item:get_count()-1) return { item=ItemStack(output.output), time=output.time, src=srcAfter } elseif method=="industrialtest.compressing" then local output=industrialtest.api.getCompressorRecipeResult(item:get_name()) if not output or item:get_count()0 and "image[3.4,2.8;1,1;industrialtest_gui_electricity_bg.png^[lowpart:"..powerPercent..":industrialtest_gui_electricity_fg.png]" or "image[3.4,2.8;1,1;industrialtest_gui_electricity_bg.png]"), "list[context;powerStorage;3.4,3.9;1,1]", industrialtest.internal.getItemSlotBg(3.4,3.9,1,1), (srcPercent>0 and "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[lowpart:"..srcPercent..":gui_furnace_arrow_fg.png^[transformR270]" or "image[4.9,2.8;1,1;gui_furnace_arrow_bg.png^[transformR270]"), "list[context;dst;6.4,2.8;1,1]", industrialtest.internal.getItemSlotBg(6.4,2.8,1,1), "list[context;upgrades;9,0.9;1,4]", industrialtest.internal.getItemSlotBg(9,0.9,1,4), "listring[context;src]", "listring[context;dst]" } return table.concat(formspec,"") end simpleElectricItemProcessor.onPowerFlow=function(pos) -- FIXME: this probably will require refactor so node timer won't be started -- just to test if machine can process item minetest.get_node_timer(pos):start(industrialtest.updateDelay) end simpleElectricItemProcessor.onConstruct=function(pos,meta,inv) inv:set_size("src",1) inv:set_size("dst",1) inv:set_size("powerStorage",1) inv:set_size("upgrades",4) meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) end simpleElectricItemProcessor.onTimer=function(pos,elapsed,meta,inv,config) local srcSlot=inv:get_stack("src",1) local powerStorageSlot=inv:get_stack("powerStorage",1) local shouldUpdateFormspec=false local shouldRerunTimer=false local requiredPower=elapsed*config.opPower*industrialtest.api.getMachineSpeed(meta) shouldRerunTimer,shouldUpdateFormspec=industrialtest.internal.chargeFromPowerStorageItem(meta,inv) if srcSlot:get_count()>0 and meta:get_int("industrialtest.powerAmount")>=requiredPower then local output=craftResultProxy(config.method,srcSlot) if output.time>0 and inv:room_for_item("dst",output.item) then if meta:get_float("maxSrcTime")<=0 then meta:set_float("srcTime",0) meta:set_float("maxSrcTime",output.time*config.efficiency) end minetest.swap_node(pos,{ name="industrialtest:"..config.name.."_active", param2=minetest.get_node(pos).param2 }) minetest.get_node_timer(pos):start(industrialtest.updateDelay) end end return shouldRerunTimer,shouldUpdateFormspec end simpleElectricItemProcessor.allowMetadataInventoryMove=function(pos,fromList,fromIndex,toList,count) if toList=="dst" then return 0 elseif toList=="upgrades" then -- TODO: Add support for upgrades when they will be added return 0 end return count end simpleElectricItemProcessor.allowMetadataInventoryPut=function(pos,listname,index,stack) if listname=="dst" then return 0 elseif listname=="src" then local meta=minetest.get_meta(pos) local inv=meta:get_inventory() local srcSlot=inv:get_stack("src",1) if srcSlot:get_name()~=stack:get_name() then meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) end elseif listname=="upgrades" then --TODO: See allow_metadata_inventory_move return 0 end return stack:get_count() end simpleElectricItemProcessor.onMetadataInventoryPut=function(pos) minetest.get_node_timer(pos):start(industrialtest.updateDelay) end simpleElectricItemProcessor.onMetadataInventoryMove=function(pos,fromList,fromIndex,toList,toIndex,count) local meta=minetest.get_meta(pos) local inv=meta:get_inventory() local srcSlot=inv:get_stack("src",1) local dstSlot=inv:get_stack("dst",1) if fromList=="src" and count==srcSlot:get_count() then meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) if meta:get_int("industrialtest.powerAmount")>0 then meta:set_string("formspec",simpleElectricItemProcessor.getFormspec(pos)) end elseif fromList=="dst" and dstSlot:get_free_space()>0 then minetest.get_node_timer(pos):start(industrialtest.updateDelay) end end simpleElectricItemProcessor.onMetadataInventoryTake=function(pos,listname,index,stack) local meta=minetest.get_meta(pos) local inv=meta:get_inventory() local srcSlot=inv:get_stack("src",1) local dstSlot=inv:get_stack("dst",1) if listname=="src" and stack:get_count()==srcSlot:get_count() then meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) if meta:get_int("industrialtest.powerAmount")>0 then meta:set_string("formspec",simpleElectricItemProcessor.getFormspec(pos)) end elseif listname=="dst" and dstSlot:get_free_space()>0 then minetest.get_node_timer(pos):start(industrialtest.updateDelay) end end simpleElectricItemProcessor.activeOnTimer=function(pos,elapsed,meta,inv,config) local srcSlot=inv:get_stack("src",1) local powerStorageSlot=inv:get_stack("powerStorage",1) local shouldUpdateFormspec=false local shouldRerunTimer=false local requiredPower=elapsed*config.opPower*industrialtest.api.getMachineSpeed(meta) shouldRerunTimer,shouldUpdateFormspec=industrialtest.internal.chargeFromPowerStorageItem(meta,inv) if srcSlot:get_count()>0 and meta:get_float("maxSrcTime")<=0 and meta:get_int("industrialtest.powerAmount")>=requiredPower then local output=craftResultProxy(config.method,srcSlot) if output.time>0 and inv:room_for_item("dst",output.item) then meta:set_float("srcTime",0) meta:set_float("maxSrcTime",output.time*config.efficiency) end end if srcSlot:get_count()==0 and meta:get_float("maxSrcTime")>0 then meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) shouldUpdateFormspec=true end if meta:get_float("maxSrcTime")>0 then if meta:get_int("industrialtest.powerAmount")>=requiredPower then meta:set_int("industrialtest.powerAmount",meta:get_int("industrialtest.powerAmount")-requiredPower) meta:set_float("srcTime",meta:get_float("srcTime")+elapsed) shouldRerunTimer=true end shouldUpdateFormspec=true end if meta:get_float("maxSrcTime")<=0 or meta:get_int("industrialtest.powerAmount")=meta:get_float("maxSrcTime") then local output=craftResultProxy(config.method,srcSlot) local speed=industrialtest.api.getMachineSpeed(meta) local usedItems=srcSlot:get_count()-output.src:get_count() local multiplier=1 if srcSlot:get_count()>=speed*usedItems then multiplier=speed end if output.item:get_count()>0 then output.item:set_count(output.item:get_count()*multiplier) inv:add_item("dst",output.item) meta:set_float("srcTime",-1) meta:set_float("maxSrcTime",0) end srcSlot:set_count(srcSlot:get_count()-multiplier*usedItems) inv:set_stack("src",1,srcSlot) end return shouldRerunTimer,shouldUpdateFormspec end function industrialtest.internal.registerSimpleElectricItemProcessor(config) local machineBlockTexture=config.machineBlockTexture or "industrialtest_machine_block.png" industrialtest.internal.registerMachine({ name=config.name, displayName=config.displayName, capacity=config.capacity, getFormspec=simpleElectricItemProcessor.getFormspec, flow=config.flow, ioConfig="iiiiii", requiresWrench=config.requiresWrench, registerActiveVariant=true, sounds="metal", powerSlots={"powerStorage"}, storageSlots={"src","dst","powerStorage","upgrades"}, groups={ _industrialtest_hasPowerInput=1 }, customKeys={ tiles={ machineBlockTexture..(config.customTopTexture and "^industrialtest_"..config.name.."_top.png" or ""), machineBlockTexture..(config.customBottomTexture and "^industrialtest_"..config.name.."_bottom.png" or ""), machineBlockTexture..(config.customRightTexture and "^industrialtest_"..config.name.."_right.png" or ""), machineBlockTexture..(config.customLeftTexture and "^industrialtest_"..config.name.."_left.png" or ""), machineBlockTexture..(config.customBackTexture and "^industrialtest_"..config.name.."_back.png" or ""), machineBlockTexture..(config.customFrontTexture and "^industrialtest_"..config.name.."_front.png" or "") }, paramtype2="facedir", legacy_facedir_simple=true, _industrialtest_onPowerFlow=simpleElectricItemProcessor.onPowerFlow }, activeCustomKeys={ tiles={ machineBlockTexture..(config.customTopTexture and "^industrialtest_"..config.name.."_top_active.png" or ""), machineBlockTexture..(config.customBottomTexture and "^industrialtest_"..config.name.."_bottom_active.png" or ""), machineBlockTexture..(config.customRightTexture and "^industrialtest_"..config.name.."_right_active.png" or ""), machineBlockTexture..(config.customLeftTexture and "^industrialtest_"..config.name.."_left_active.png" or ""), machineBlockTexture..(config.customBackTexture and "^industrialtest_"..config.name.."_back_active.png" or ""), machineBlockTexture..(config.customFrontTexture and "^industrialtest_"..config.name.."_front_active.png" or "") } }, onConstruct=simpleElectricItemProcessor.onConstruct, onTimer=function(pos,elapsed,meta,inv) return simpleElectricItemProcessor.onTimer(pos,elapsed,meta,inv,config) end, allowMetadataInventoryMove=simpleElectricItemProcessor.allowMetadataInventoryMove, allowMetadataInventoryPut=simpleElectricItemProcessor.allowMetadataInventoryPut, onMetadataInventoryPut=simpleElectricItemProcessor.onMetadataInventoryPut, onMetadataInventoryMove=simpleElectricItemProcessor.onMetadataInventoryMove, onMetadataInventoryTake=simpleElectricItemProcessor.onMetadataInventoryTake, activeOnTimer=function(pos,elapsed,meta,inv) return simpleElectricItemProcessor.activeOnTimer(pos,elapsed,meta,inv,config) end }) industrialtest.api.addTag("industrialtest:"..config.name,"simpleElectricItemProcessor") end