Implement Pump
This commit is contained in:
1
init.lua
1
init.lua
@@ -60,6 +60,7 @@ dofile(modpath.."/machines/mass_fabricator.lua")
|
|||||||
dofile(modpath.."/machines/miner.lua")
|
dofile(modpath.."/machines/miner.lua")
|
||||||
dofile(modpath.."/machines/nuclear_reactor.lua")
|
dofile(modpath.."/machines/nuclear_reactor.lua")
|
||||||
dofile(modpath.."/machines/power_storage.lua")
|
dofile(modpath.."/machines/power_storage.lua")
|
||||||
|
dofile(modpath.."/machines/pump.lua")
|
||||||
dofile(modpath.."/machines/recycler.lua")
|
dofile(modpath.."/machines/recycler.lua")
|
||||||
dofile(modpath.."/machines/rotary_macerator.lua")
|
dofile(modpath.."/machines/rotary_macerator.lua")
|
||||||
dofile(modpath.."/machines/tool_workshop.lua")
|
dofile(modpath.."/machines/tool_workshop.lua")
|
||||||
|
|||||||
407
machines/pump.lua
Normal file
407
machines/pump.lua
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
-- IndustrialTest
|
||||||
|
-- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local S=minetest.get_translator("industrialtest")
|
||||||
|
industrialtest.Pump=table.copy(industrialtest.ActivatedElectricMachine)
|
||||||
|
industrialtest.internal.unpackTableInto(industrialtest.Pump,{
|
||||||
|
name="industrialtest:pump",
|
||||||
|
description=S("Pump"),
|
||||||
|
tiles={
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png^industrialtest_pump_front.png"
|
||||||
|
},
|
||||||
|
sounds="metal",
|
||||||
|
facedir=true,
|
||||||
|
storageLists={
|
||||||
|
"src",
|
||||||
|
"dst",
|
||||||
|
"powerStorage"
|
||||||
|
},
|
||||||
|
powerLists={
|
||||||
|
{
|
||||||
|
list="powerStorage",
|
||||||
|
direction="i"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
active={
|
||||||
|
tiles={
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png",
|
||||||
|
"industrialtest_machine_block.png^industrialtest_pump_front_active.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
capacity=industrialtest.api.lvPowerFlow*2,
|
||||||
|
flow=industrialtest.api.lvPowerFlow,
|
||||||
|
ioConfig="iiiiii",
|
||||||
|
requiresWrench=true,
|
||||||
|
hasPowerInput=true,
|
||||||
|
_fluidCapacity=5000,
|
||||||
|
_opPower=300,
|
||||||
|
_pumpTime=10
|
||||||
|
})
|
||||||
|
|
||||||
|
function industrialtest.Pump.onConstruct(self,pos)
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
local inv=meta:get_inventory()
|
||||||
|
inv:set_size("src",1)
|
||||||
|
inv:set_size("dst",1)
|
||||||
|
inv:set_size("powerStorage",1)
|
||||||
|
meta:set_float("srcTime",0)
|
||||||
|
industrialtest.api.addFluidStorage(meta,self._fluidCapacity)
|
||||||
|
self.determinePumpTargets(pos)
|
||||||
|
industrialtest.ActivatedElectricMachine.onConstruct(self,pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.getFormspec(self,pos)
|
||||||
|
local parentFormspec=industrialtest.ActivatedElectricMachine.getFormspec(self,pos)
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
local powerPercent=meta:get_int("industrialtest.powerAmount")/meta:get_int("industrialtest.powerCapacity")*100
|
||||||
|
local srcPercent=meta:get_float("srcTime")/self._pumpTime*100
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
local fluidPercent=0
|
||||||
|
if meta:contains("industrialtest.fluidAmount") and meta:contains("industrialtest.fluidCapacity") then
|
||||||
|
fluidPercent=meta:get_int("industrialtest.fluidAmount")/meta:get_int("industrialtest.fluidCapacity")*100
|
||||||
|
end
|
||||||
|
local pumpFluid=industrialtest.api.getPumpFluid(fluidType)
|
||||||
|
local tile=(pumpFluid and pumpFluid.texture or "industrialtest_gui_fluid_bg.png")
|
||||||
|
local formspec={
|
||||||
|
"list[context;src;3.2,1.7;1,1]",
|
||||||
|
industrialtest.internal.getItemSlotBg(3.2,1.7,1,1),
|
||||||
|
"list[context;dst;4.6,1.7;1,1]",
|
||||||
|
industrialtest.internal.getItemSlotBg(4.6,1.7,1,1),
|
||||||
|
"list[context;powerStorage;3.9,3.7;1,1]",
|
||||||
|
industrialtest.internal.getItemSlotBg(3.9,3.7,1,1),
|
||||||
|
(powerPercent>0 and "image[3.9,2.7;1,1;industrialtest_gui_electricity_bg.png^[lowpart:"..powerPercent..":industrialtest_gui_electricity_fg.png]"
|
||||||
|
or "image[3.9,2.7;1,1;industrialtest_gui_electricity_bg.png]"),
|
||||||
|
(srcPercent>0 and "image[6.7,2.7;1,1;gui_furnace_arrow_bg.png^[lowpart:"..srcPercent..":gui_furnace_arrow_fg.png]"
|
||||||
|
or "image[6.7,2.7;1,1;gui_furnace_arrow_bg.png]"),
|
||||||
|
(fluidPercent>0 and "image[7.7,2.7;1,1;industrialtest_gui_fluid_bg.png^[lowpart:"..fluidPercent..":"..tile.."]" or "image[7.7,2.7;1,1;industrialtest_gui_fluid_bg.png]"),
|
||||||
|
"label[3.2,1.5;"..S("Input").."]",
|
||||||
|
"label[4.6,1.5;"..S("Output").."]",
|
||||||
|
"listring[context;src]",
|
||||||
|
"listring[context;dst]"
|
||||||
|
}
|
||||||
|
return parentFormspec..table.concat(formspec,"")
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.allowMetadataInventoryMove(self,pos,fromList,fromIndex,toList,count)
|
||||||
|
if toList=="dst" then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return industrialtest.ActivatedElectricMachine.allowMetadataInventoryMove(self,pos,fromList,fromIndex,toList,count)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.allowMetadataInventoryPut(self,pos,listname,index,stack,player)
|
||||||
|
if listname=="dst" then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
return industrialtest.ActivatedElectricMachine.allowMetadataInventoryPut(self,pos,listname,index,stack,player)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.allowMetadataInventoryTake(self,pos,listname,index,stack,player)
|
||||||
|
if listname=="src" then
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
local inv=meta:get_inventory()
|
||||||
|
local srcSlot=inv:get_stack("src",1)
|
||||||
|
if stack:get_count()==srcSlot:get_count() and not meta:get_int("hasOutputTarget") then
|
||||||
|
meta:set_float("srcTime",0)
|
||||||
|
self:updateFormspec(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return industrialtest.ActivatedElectricMachine.allowMetadataInventoryTake(self,pos,listname,index,stack,player)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.onMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
|
||||||
|
if fromList=="src" then
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
local inv=meta:get_inventory()
|
||||||
|
local srcSlot=inv:get_stack("src",1)
|
||||||
|
if count==srcSlot:get_count() and not meta:get_int("hasOutputTarget") then
|
||||||
|
meta:set_float("srcTime",0)
|
||||||
|
self:updateFormspec(pos)
|
||||||
|
end
|
||||||
|
elseif toList=="src" then
|
||||||
|
self:triggerIfNeeded(pos)
|
||||||
|
end
|
||||||
|
industrialtest.ActivatedElectricMachine.onMetadataInventoryMove(self,pos,fromList,fromIndex,toList,toIndex,count)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.onMetadataInventoryPut(self,pos,listname,index,stack)
|
||||||
|
if listname=="src" then
|
||||||
|
self:triggerIfNeeded(pos)
|
||||||
|
end
|
||||||
|
industrialtest.ActivatedElectricMachine.onMetadataInventoryPut(self,pos,listname,index,stack)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Miner.onMetadataInventoryTake(self,pos,listname,index,stack)
|
||||||
|
if listname=="dst" then
|
||||||
|
self:triggerIfNeeded(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.shouldActivate(self,pos)
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
if meta:get_int("industrialtest.powerAmount")<self._opPower then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local hasInput=false
|
||||||
|
local nodeUnder=minetest.get_node(vector.offset(pos,0,-1,0))
|
||||||
|
local fluidAmount=meta:get_int("industrialtest.fluidAmount")
|
||||||
|
if fluidAmount>0 then
|
||||||
|
hasInput=true
|
||||||
|
else
|
||||||
|
-- Check if there is node that can be pumped under pump
|
||||||
|
if industrialtest.api.getPumpFluid(nodeUnder.name) then
|
||||||
|
hasInput=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if any input target can provide with fluid
|
||||||
|
if not hasInput and meta:get_int("hasInputTarget")>0 then
|
||||||
|
local polledTargets=self.pollInputTargets(pos)
|
||||||
|
hasInput=#polledTargets>0
|
||||||
|
end
|
||||||
|
|
||||||
|
if not hasInput then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local hasOutput=false
|
||||||
|
-- First check if pump can push into any neighour node
|
||||||
|
if meta:get_int("hasOutputTarget") then
|
||||||
|
local outputTargets=minetest.deserialize(meta:get_string("outputTargets"))
|
||||||
|
for _,target in ipairs(outputTargets) do
|
||||||
|
local node=minetest.get_node(target)
|
||||||
|
local def=minetest.registered_nodes[node.name]
|
||||||
|
hasOutput=(def and def._industrialtest_self and def._industrialtest_self:canPushFluid(target,nodeUnder.name,fluidAmount))
|
||||||
|
if hasOutput then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if it's possible to pump fluid into item
|
||||||
|
if not hasOutput then
|
||||||
|
local inv=meta:get_inventory()
|
||||||
|
local srcSlot=inv:get_stack("src",1)
|
||||||
|
if not srcSlot:is_empty() then
|
||||||
|
local def=srcSlot:get_definition()
|
||||||
|
if def.groups._industrialtest_simpleFluidStorage and def._industrialtest_simpleFluidStorageCapacity and fluidAmount>=def._industrialtest_simpleFluidStorageCapacity and
|
||||||
|
def._industrialtest_getResultingFluidStorageItemByNode then
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
local resulting=def._industrialtest_getResultingFluidStorageItemByNode(fluidType)
|
||||||
|
if resulting then
|
||||||
|
local dstSlot=inv:get_stack("dst",1)
|
||||||
|
hasOutput=dstSlot:item_fits(ItemStack(resulting.name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if pump storage is not full
|
||||||
|
if not hasOutput then
|
||||||
|
local fluidCapacity=meta:get_int("industrialtest.fluidCapacity")
|
||||||
|
hasOutput=fluidCapacity-fluidAmount>=industrialtest.api.nodeFluidCapacity
|
||||||
|
end
|
||||||
|
|
||||||
|
return hasOutput
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.shouldDeactivate(self,pos)
|
||||||
|
return not self:shouldActivate(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.afterDeactivation(self,pos)
|
||||||
|
-- If machine was deactivated then make sure to update formspec
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
meta:set_float("srcTime",0)
|
||||||
|
self:updateFormspec(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.activeUpdate(self,pos,elapsed,meta,inv)
|
||||||
|
local nodeUnderPos=vector.offset(pos,0,-1,0)
|
||||||
|
local nodeUnder=minetest.get_node(nodeUnderPos)
|
||||||
|
local fluidAmount=meta:get_int("industrialtest.fluidAmount")
|
||||||
|
local fluidCapacity=meta:get_int("industrialtest.fluidCapacity")
|
||||||
|
local shouldUpdateFormspec=false
|
||||||
|
|
||||||
|
-- First try to pump fluid under
|
||||||
|
-- Check if there is node that can be pumped under pump
|
||||||
|
if fluidCapacity-fluidAmount>=industrialtest.api.nodeFluidCapacity and industrialtest.api.getPumpFluid(nodeUnder.name) then
|
||||||
|
local srcTime=meta:get_float("srcTime")+elapsed*industrialtest.api.getMachineSpeed(meta)
|
||||||
|
if srcTime>=self._pumpTime then
|
||||||
|
fluidAmount=fluidAmount+industrialtest.api.nodeFluidCapacity
|
||||||
|
meta:set_string("industrialtest.fluidType",nodeUnder.name)
|
||||||
|
meta:set_int("industrialtest.fluidAmount",fluidAmount)
|
||||||
|
minetest.remove_node(nodeUnderPos)
|
||||||
|
srcTime=0
|
||||||
|
end
|
||||||
|
industrialtest.api.addPower(meta,-self._opPower)
|
||||||
|
meta:set_float("srcTime",srcTime)
|
||||||
|
shouldUpdateFormspec=true
|
||||||
|
end
|
||||||
|
|
||||||
|
if meta:get_int("hasInputTarget")>0 then
|
||||||
|
local polledTargets=self.pollInputTargets(pos)
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
for _,target in ipairs(polledTargets) do
|
||||||
|
local moved=math.min(fluidCapacity-fluidAmount,target.fluidInfo.remaining)
|
||||||
|
fluidAmount=fluidAmount+moved
|
||||||
|
target.pullFluid(moved)
|
||||||
|
meta:set_string("industrialtest.fluidType",target.fluidInfo.fluidType)
|
||||||
|
shouldUpdateFormspec=true
|
||||||
|
if fluidCapacity-fluidAmount<=0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
meta:set_int("industrialtest.fluidAmount",fluidAmount)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to push fluid into item if available
|
||||||
|
local inv=meta:get_inventory()
|
||||||
|
local srcSlot=inv:get_stack("src",1)
|
||||||
|
if not srcSlot:is_empty() then
|
||||||
|
local def=srcSlot:get_definition()
|
||||||
|
if def.groups._industrialtest_simpleFluidStorage and def._industrialtest_simpleFluidStorageCapacity and fluidAmount>=def._industrialtest_simpleFluidStorageCapacity and
|
||||||
|
def._industrialtest_getResultingFluidStorageItemByNode then
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
local resulting=def._industrialtest_getResultingFluidStorageItemByNode(fluidType)
|
||||||
|
if resulting then
|
||||||
|
local dstSlot=inv:get_stack("dst",1)
|
||||||
|
local resultingStack=ItemStack(resulting.name)
|
||||||
|
if dstSlot:item_fits(resultingStack) then
|
||||||
|
dstSlot:add_item(resultingStack)
|
||||||
|
inv:set_stack("dst",1,dstSlot)
|
||||||
|
srcSlot:take_item()
|
||||||
|
inv:set_stack("src",1,srcSlot)
|
||||||
|
fluidAmount=fluidAmount-def._industrialtest_simpleFluidStorageCapacity
|
||||||
|
meta:set_int("industrialtest.fluidAmount",fluidAmount)
|
||||||
|
shouldUpdateFormspec=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to push fluid into neighbour target
|
||||||
|
if meta:get_int("hasOutputTarget")>0 then
|
||||||
|
local outputTargets=minetest.deserialize(meta:get_string("outputTargets"))
|
||||||
|
for _,targetPos in ipairs(outputTargets) do
|
||||||
|
local targetNode=minetest.get_node(targetPos)
|
||||||
|
local targetDef=minetest.registered_nodes[targetNode.name]
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
if targetDef and targetDef._industrialtest_self and targetDef._industrialtest_self.canPushFluid and
|
||||||
|
targetDef._industrialtest_self.onPumpFluidPush and targetDef._industrialtest_self:canPushFluid(targetPos,fluidType,fluidAmount) then
|
||||||
|
fluidAmount=targetDef._industrialtest_self:onPumpFluidPush(targetPos,pos,fluidType,fluidAmount)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
meta:set_int("industrialtest.fluidAmount",fluidAmount)
|
||||||
|
end
|
||||||
|
|
||||||
|
return shouldUpdateFormspec
|
||||||
|
end
|
||||||
|
|
||||||
|
function industrialtest.Pump.action(self,pos)
|
||||||
|
self.determinePumpTargets(pos)
|
||||||
|
self:triggerIfNeeded(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Scans neighbour positions for pump targets
|
||||||
|
function industrialtest.Pump.determinePumpTargets(pos)
|
||||||
|
local neighbourPositions={
|
||||||
|
vector.offset(pos,-1,0,0),
|
||||||
|
vector.offset(pos,1,0,0),
|
||||||
|
vector.offset(pos,0,-1,0),
|
||||||
|
vector.offset(pos,0,1,0),
|
||||||
|
vector.offset(pos,0,0,-1),
|
||||||
|
vector.offset(pos,0,0,1)
|
||||||
|
}
|
||||||
|
local inputTargets={}
|
||||||
|
local outputTargets={}
|
||||||
|
for _,neighbour in ipairs(neighbourPositions) do
|
||||||
|
local node=minetest.get_node(neighbour)
|
||||||
|
local targetDef=industrialtest.api.getPumpTarget(node.name)
|
||||||
|
if targetDef then
|
||||||
|
if targetDef.direction=="i" then
|
||||||
|
table.insert(inputTargets,neighbour)
|
||||||
|
elseif targetDef.direction=="o" then
|
||||||
|
table.insert(outputTargets,neighbour)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
meta:set_string("inputTargets",minetest.serialize(inputTargets))
|
||||||
|
meta:set_int("hasInputTarget",#inputTargets>0 and 1 or 0)
|
||||||
|
meta:set_string("outputTargets",minetest.serialize(outputTargets))
|
||||||
|
meta:set_int("hasOutputTarget",#outputTargets>0 and 1 or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- \brief Checks all input targets if they have any fluid incoming
|
||||||
|
-- \param pos vector
|
||||||
|
-- \returns table
|
||||||
|
function industrialtest.Pump.pollInputTargets(pos)
|
||||||
|
local meta=minetest.get_meta(pos)
|
||||||
|
local inputTargets=minetest.deserialize(meta:get_string("inputTargets"))
|
||||||
|
local fluidType=meta:get_string("industrialtest.fluidType")
|
||||||
|
local result={}
|
||||||
|
for _,targetPos in ipairs(inputTargets) do
|
||||||
|
local targetNode=minetest.get_node(targetPos)
|
||||||
|
local targetDef=minetest.registered_nodes[targetNode.name]
|
||||||
|
if targetDef and targetDef._industrialtest_self and targetDef._industrialtest_self.pullFluid then
|
||||||
|
local fluidInfo=targetDef._industrialtest_self:pullFluid(targetPos,0)
|
||||||
|
if fluidInfo and (fluidInfo.fluidType==fluidType or fluidType=="ignore") then
|
||||||
|
table.insert(result,{
|
||||||
|
pos=targetPos,
|
||||||
|
fluidInfo=fluidInfo,
|
||||||
|
pullFluid=function(amount)
|
||||||
|
return targetDef._industrialtest_self:pullFluid(targetPos,amount)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
fluidType=fluidInfo.fluidType
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
industrialtest.Pump:register()
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
label="Pump pumping",
|
||||||
|
nodenames={"industrialtest:pump"},
|
||||||
|
interval=industrialtest.config.updateDelay,
|
||||||
|
chance=1,
|
||||||
|
action=function(pos)
|
||||||
|
industrialtest.Pump:action(pos)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type="shaped",
|
||||||
|
output="industrialtest:pump",
|
||||||
|
recipe={
|
||||||
|
{"industrialtest:empty_cell","industrialtest:electronic_circuit","industrialtest:empty_cell"},
|
||||||
|
{"industrialtest:empty_cell","industrialtest:machine_block","industrialtest:empty_cell"},
|
||||||
|
{"industrialtest:mining_pipe",industrialtest.elementKeys.treetap,"industrialtest:mining_pipe"}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user