diff --git a/craftitems.lua b/craftitems.lua index f8be6ef..aff793b 100644 --- a/craftitems.lua +++ b/craftitems.lua @@ -381,6 +381,12 @@ industrialtest.api.registerPlate("bronze","Bronze",{ count=1 } },"#e48e88ff",true) +industrialtest.api.registerPlate("copper","Copper",{ + { + resource=industrialtest.elementKeys.copperIngot, + count=1 + } +},"#f48e44ff",true) -- Cells minetest.register_craftitem("industrialtest:empty_cell",{ @@ -429,6 +435,7 @@ industrialtest.api.registerStorageCell("lava","Lava",industrialtest.elementKeys. minetest.register_tool("industrialtest:uranium_cell",{ description=S("Uranium Cell"), groups={ + _industrialtest_placedInNuclearReactor=1, _industrialtest_nuclearReactorFuel=1 }, inventory_image="industrialtest_uranium_cell.png", @@ -445,7 +452,8 @@ minetest.register_craft({ minetest.register_tool("industrialtest:coolant_cell",{ description=S("Coolant Cell"), groups={ - _industrialtest_nuclearReactorFuel=1 + _industrialtest_placedInNuclearReactor=1, + _industrialtest_nuclearReactorCoolant=1 }, inventory_image="industrialtest_coolant_cell.png", }) diff --git a/init.lua b/init.lua index 2eb6ed8..909c644 100644 --- a/init.lua +++ b/init.lua @@ -40,6 +40,7 @@ dofile(modpath.."/machines/fluid_generator.lua") dofile(modpath.."/machines/generator.lua") dofile(modpath.."/machines/iron_furnace.lua") dofile(modpath.."/machines/macerator.lua") +dofile(modpath.."/machines/nuclear_reactor.lua") dofile(modpath.."/machines/power_storage.lua") dofile(modpath.."/machines/recycler.lua") dofile(modpath.."/machines/transformer.lua") diff --git a/machines/nuclear_reactor.lua b/machines/nuclear_reactor.lua new file mode 100644 index 0000000..69b156c --- /dev/null +++ b/machines/nuclear_reactor.lua @@ -0,0 +1,381 @@ +-- 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 S=minetest.get_translator("industrialtest") +local reactor={} + +reactor.getFormspec=function(pos) + local meta=minetest.get_meta(pos) + local charged=meta:get_int("industrialtest.powerAmount")/meta:get_int("industrialtest.powerCapacity") + local switchText=(meta:get_int("enabled")==0 and S("Start") or S("Stop")) + local formspec + if industrialtest.mtgAvailable then + formspec={ + "list[context;fuel;1,1;5,4]", + "listring[context;fuel]", + "list[context;charged;7.7,2.8;1,1]", + "listring[context;charged]", + "button[7.7,1;1,0.8;toggle;"..minetest.formspec_escape(switchText).."]", + "box[9,1;0.3,4.8;#202020]", + (charged>0 and "box[9,"..(1+4.8-(charged*4.8))..";0.3,"..(charged*4.8)..";#FF1010]" or ""), + } + elseif industrialtest.mclAvailable then + formspec={ + "list[context;fuel;1,1;5,4]", + mcl_formspec.get_itemslot_bg(1,1,5,4), + "listring[context;fuel]", + "list[context;charged;7,2.8;1,1]", + mcl_formspec.get_itemslot_bg(7.7,2.8,1,1), + "listring[context;charged]", + "button[7.7,1;1,0.8;toggle;"..minetest.formspec_escape(switchText).."]", + "box[9,1;0.3,4.8;#202020]", + (charged>0 and "box[9,"..(1+4.8-(charged*4.8))..";0.3,"..(charged*4.8)..";#FF1010]" or "") + } + end + return table.concat(formspec,"") +end + +reactor.onConstruct=function(pos,meta,inv) + inv:set_size("fuel",20) + inv:set_size("charged",1) + meta:set_int("heat",0) + meta:set_int("enabled",0) + meta:set_int("stateChanged",0) +end + +local function hasFuel(fuelList) + for _,stack in ipairs(fuelList) do + if stack:get_name()=="industrialtest:uranium_cell" then + return true + end + end + return false +end + +local function findMaxFuelCluster(fuelList) + local maxCluster={} + for y=1,4 do + for x=1,5 do + local iy=y-1 + local stack=fuelList[iy*4+x] + local def=minetest.registered_tools[stack:get_name()] + if def and def.groups._industrialtest_nuclearReactorFuel then + local cluster={ + [1]={ + x=x, + y=iy + } + } + if x>1 and fuelList[iy*4+x-1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x-1, + y=iy + }) + end + if x<5 and fuelList[iy*4+x+1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x+1, + y=iy + }) + end + if y>1 and fuelList[(iy-1)*4+x]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x, + i=iy-1 + }) + end + if y<4 and fuelList[(iy+1)*4+x]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x, + y=iy+1 + }) + end + if x>1 and y>1 and fuelList[(iy-1)*4+x-1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x-1, + y=iy-1 + }) + end + if x<5 and y>1 and fuelList[(iy-1)*4+x+1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x+1, + y=iy-1 + }) + end + if x>1 and y<4 and fuelList[(iy+1)*4+x-1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x-1, + y=iy+1 + }) + end + if x<5 and y<4 and fuelList[(iy+1)*4+x+1]:get_name()==stack:get_name() then + table.insert(cluster,{ + x=x+1, + y=iy+1 + }) + end + if #cluster>#maxCluster then + maxCluster=cluster + end + if #cluster==4 then + return maxCluster + end + end + end + end + return maxCluster +end + +local function findCoolant(fuelList) + for i=1,20 do + local stack=fuelList[i] + local def=minetest.registered_tools[stack:get_name()] + if def and def.groups._industrialtest_nuclearReactorCoolant then + return i + end + end + return 0 +end + +local function useFuel(stack,use) + local used=math.min(65535-stack:get_wear(),use) + if used0 + local shouldUpdateFormspec=false + + if chargedSlot:get_count()>0 and not industrialtest.api.isFullyCharged(chargedSlot:get_meta()) and meta:get_int("industrialtest.powerAmount")>0 then + industrialtest.api.transferPowerToItem(meta,chargedSlot,powerFlow) + inv:set_stack("charged",1,chargedSlot) + shouldUpdateFormspec=true + shouldRerunTimer=true + end + + if meta:get_int("stateChanged")>0 then + shouldUpdateFormspec=true + meta:set_int("stateChanged",0) + end + + if meta:get_int("enabled")>0 and hasFuel(fuelList) then + minetest.swap_node(pos,{ + name="industrialtest:nuclear_reactor_active", + param2=minetest.get_node(pos).param2 + }) + minetest.get_node_timer(pos):start(industrialtest.updateDelay) + shouldRerunTimer=false + end + + return shouldRerunTimer,shouldUpdateFormspec +end + +reactor.activeOnTimer=function(pos,elapsed,meta,inv) + local powerFlow=meta:get_int("industrialtest.powerFlow") + local chargedSlot=inv:get_stack("charged",1) + local fuelList=inv:get_list("fuel") + local afterFlow,flowTransferred=industrialtest.api.powerFlow(pos) + local shouldRerunTimer=meta:get_int("enabled")>0 + local shouldUpdateFormspec=false + + if chargedSlot:get_count()>0 and not industrialtest.api.isFullyCharged(chargedSlot:get_meta()) and meta:get_int("industrialtest.powerAmount")>0 then + industrialtest.api.transferPowerToItem(meta,chargedSlot,powerFlow) + inv:set_stack("charged",1,chargedSlot) + shouldUpdateFormspec=true + shouldRerunTimer=true + end + + if meta:get_int("stateChanged")>0 then + shouldUpdateFormspec=true + meta:set_int("stateChanged",0) + end + + if meta:get_int("enabled")==0 or not hasFuel(fuelList) then + minetest.swap_node(pos,{ + name="industrialtest:nuclear_reactor", + param2=minetest.get_node(pos).param2 + }) + meta:set_int("enabled",0) + minetest.get_node_timer(pos):start(industrialtest.updateDelay) + return false,shouldUpdateFormspec + end + + local maxCluster=findMaxFuelCluster(fuelList) + for _,stack in ipairs(maxCluster) do + local index=stack.y*4+stack.x + local usedStack,_=useFuel(fuelList[index],5) + inv:set_stack("fuel",index,usedStack) + end + local generatedPowerAmount=math.pow(20,#maxCluster) + if industrialtest.api.addPower(meta,generatedPowerAmount)>0 then + shouldUpdateFormspec=true + end + + local heat=meta:get_int("heat")+#maxCluster + local coolant=findCoolant(fuelList) + if coolant>0 then + local coolantStack,used=useFuel(fuelList[coolant],#maxCluster*50) + heat=heat-used + inv:set_stack("fuel",coolant,coolantStack) + end + if heat>200 then + -- TODO: Explode + minetest.remove_node(pos) + return false,false + end + meta:set_int("heat",heat) + + return shouldRerunTimer,shouldUpdateFormspec +end + +reactor.allowMetadataInventoryMove=function(pos,fromList,fromIndex,toList,toIndex,count) + local meta=minetest.get_meta(pos) + local inv=meta:get_inventory() + local movedItemStack=inv:get_stack(fromList,fromIndex) + local def=minetest.registered_tools[movedItemStack:get_name()] + if toList=="fuel" and (not def or not def.groups._industrialtest_placedInNuclearReactor) then + return 0 + end + return count +end + +reactor.allowMetadataInventoryPut=function(pos,listname,index,stack) + local def=minetest.registered_tools[stack:get_name()] + if listname=="fuel" and (not def or not def.groups._industrialtest_placedInNuclearReactor) then + return 0 + end + return stack:get_count() +end + +reactor.metadataChange=function(pos) + minetest.get_node_timer(pos):start(industrialtest.updateDelay) +end + +reactor.handleFormspecFields=function(pos,formname,fields) + if not fields.toggle then + return + end + local meta=minetest.get_meta(pos) + local inv=meta:get_inventory() + local fuelList=inv:get_list("fuel") + if not hasFuel(fuelList) and meta:get_int("enabled")==0 then + return + end + if meta:get_int("enabled")==0 then + meta:set_int("enabled",1) + else + meta:set_int("enabled",0) + end + meta:set_int("stateChanged",1) + reactor.metadataChange(pos) +end + +local definition={ + description=S("Nuclear Reactor Chamber"), + tiles={"industrialtest_machine_block.png^industrialtest_nuclear_reactor_top.png"}, + drop="industrialtest:machine_block", + groups={ + _industrialtest_wrenchUnmountable=1 + } +} +if industrialtest.mtgAvailable then + definition.sounds=default.node_sound_metal_defaults() + definition.groups.cracky=1 + definition.groups.level=2 +elseif industrialtest.mclAvailable then + definition.sounds=mcl_sounds.node_sound_metal_defaults() + definition._mcl_blast_resistance=6 + definition._mcl_hardness=5 +end +minetest.register_node("industrialtest:nuclear_reactor_chamber",definition) +minetest.register_craft({ + type="shaped", + output="industrialtest:nuclear_reactor_chamber", + recipe={ + {"","industrialtest:copper_plate",""}, + {"industrialtest:copper_plate","industrialtest:machine_block","industrialtest:copper_plate"}, + {"","industrialtest:copper_plate",""} + } +}) + +industrialtest.internal.registerMachine({ + name="nuclear_reactor", + displayName=S("Nuclear Reactor"), + getFormspec=reactor.getFormspec, + capacity=industrialtest.api.ivPowerFlow*2, + flow=industrialtest.api.ivPowerFlow, + ioConfig="oooooo", + requiresWrench=true, + registerActiveVariant=true, + powerSlots={"charged"}, + storageSlots={"charged","fuel"}, + sounds="metal", + groups={ + _industrialtest_hasPowerOutput=1 + }, + customKeys={ + tiles={ + "industrialtest_machine_block.png^industrialtest_nuclear_reactor_top.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png^industrialtest_nuclear_reactor_front.png", + "industrialtest_machine_block.png" + }, + paramtype2="facedir", + legacy_facedir_simple=true, + on_receive_fields=reactor.handleFormspecFields + }, + activeCustomKeys={ + tiles={ + "industrialtest_machine_block.png^industrialtest_nuclear_reactor_top.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png", + "industrialtest_machine_block.png^industrialtest_nuclear_reactor_front_active.png", + "industrialtest_machine_block.png" + }, + light_source=2, + on_receive_fields=reactor.handleFormspecFields + }, + onConstruct=reactor.onConstruct, + onTimer=reactor.onTimer, + activeOnTimer=reactor.activeOnTimer, + allowMetadataInventoryMove=reactor.allowMetadataInventoryMove, + allowMetadataInventoryPut=reactor.allowMetadataInventoryPut, + onMetadataInventoryMove=reactor.metadataChange, + onMetadataInventoryPut=reactor.metadataChange +}) +minetest.register_craft({ + type="shaped", + output="industrialtest:nuclear_reactor", + recipe={ + {"","industrialtest:advanced_electronic_circuit",""}, + {"industrialtest:nuclear_reactor_chamber","industrialtest:nuclear_reactor_chamber","industrialtest:nuclear_reactor_chamber"}, + {"","industrialtest:generator",""} + } +})