-- 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 . local S=minetest.get_translator("industrialtest") local function findFenceRailEnd(initialPosition,direction) local y=initialPosition.y local railNode=minetest.get_node(vector.new(initialPosition.x,y,initialPosition.z)) while minetest.get_item_group(railNode.name,"_industrialtest_metalFence")>0 and math.abs(initialPosition.y-y)<=19 do y=y+direction railNode=minetest.get_node(vector.new(initialPosition.x,y,initialPosition.z)) end return y-direction end local function hasMetalBoots(player) local inv if industrialtest.mtgAvailable then _,inv=armor:get_valid_player(player,"") elseif industrialtest.mclAvailable then inv=player:get_inventory() end if inv then local armorList=inv:get_list("armor") assert(armorList) local requiredGroups={ "armor_iron", "armor_gold", "armor_bronze", "_industrialtest_electricArmor" } -- 3D armor boots have to be hardcoded here because they don't provide any group depending on material local requiredNames={ "3d_armor:boots_steel", "3d_armor:boots_gold", "3d_armor:boots_bronze" } for _,itemstack in ipairs(armorList) do local def=itemstack:get_definition() if def and def.groups and def.groups.armor_feet then for _,group in ipairs(requiredGroups) do if def.groups[group] then -- Matching group succeeded return true end end end for _,itemname in ipairs(requiredNames) do if itemname==itemstack:get_name() then -- Matching itemname succeeded return true end end end end return false end industrialtest.Magnetizer=table.copy(industrialtest.ElectricMachine) industrialtest.internal.unpackTableInto(industrialtest.Magnetizer,{ name="industrialtest:magnetizer", description=S("Magnetizer"), 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_magnetizer_front.png" }, sounds="metal", facedir=true, storageLists={ "powerStorage" }, powerLists={ { list="powerStorage", direction="i" } }, capacity=industrialtest.api.lvPowerFlow*2, flow=industrialtest.api.lvPowerFlow, ioConfig="iiiiii", requiresWrench=true, hasPowerInput=true, _capacityPerFence=15, _opPower=4 }) function industrialtest.Magnetizer.onConstruct(self,pos) local meta=minetest.get_meta(pos) local inv=meta:get_inventory() inv:set_size("powerStorage",1) self:determineFenceRail(pos) self:determinePowerCapacity(pos) industrialtest.ElectricMachine.onConstruct(self,pos) end function industrialtest.Magnetizer.onDestruct(self,pos) self.detachFenceRail(pos) industrialtest.ElectricMachine.onDestruct(self,pos) end function industrialtest.Magnetizer.onDig(self,pos,node,digger) self.detachFenceRail(pos) return industrialtest.ElectricMachine.onDig(self,pos,node,digger) end function industrialtest.Magnetizer.getFormspec(self,pos) local parentFormspec=industrialtest.ElectricMachine.getFormspec(self,pos) local meta=minetest.get_meta(pos) local powerPercent=meta:get_int("industrialtest.powerAmount")/meta:get_int("industrialtest.powerCapacity")*100 local formspec={ (powerPercent>0 and "image[4.7,2.7;1,1;industrialtest_gui_electricity_bg.png^[lowpart:"..powerPercent..":industrialtest_gui_electricity_fg.png]" or "image[4.7,2.7;1,1;industrialtest_gui_electricity_bg.png]"), "list[context;powerStorage;4.7,3.7;1,1]", "listring[context;powerStorage]" } return parentFormspec..table.concat(formspec,"") end function industrialtest.Magnetizer.determinePowerCapacity(self,pos) local meta=minetest.get_meta(pos) if meta:contains("lowY") and meta:contains("highY") then local lowY=meta:get_int("lowY") local highY=meta:get_int("highY") local capacity=self.capacity+(highY-lowY)*self._capacityPerFence meta:set_int("industrialtest.powerCapacity",capacity) end end -- Checks all sides on the same Y level if there is rail made from metal fences attached function industrialtest.Magnetizer.determineFenceRail(self,pos) local neighbourPositions={ vector.offset(pos,-1,0,0), vector.offset(pos,1,0,0), vector.offset(pos,0,0,-1), vector.offset(pos,0,0,1) } local railPosition for _,neighbourPosition in ipairs(neighbourPositions) do local neighbourNode=minetest.get_node(neighbourPosition) if minetest.get_item_group(neighbourNode.name,"_industrialtest_metalFence")>0 then railPosition=neighbourPosition break end end if not railPosition then return end local direction=vector.subtract(railPosition,pos) minetest.swap_node(pos,{ name=self.name, -- Some cryptic code that converts direction vector to param2 param2=direction.z+1*math.abs(direction.z)+direction.x+2*math.abs(direction.x) }) -- Find low and high points of fence rail local lowY=findFenceRailEnd(railPosition,-1) local highY=findFenceRailEnd(railPosition,1) -- Keep magnetizer position in fence metadata so new fences can be attached easily for y=lowY,highY,1 do local meta=minetest.get_meta(vector.new(railPosition.x,y,railPosition.z)) meta:set_string("magnetizerPosition",minetest.serialize(pos)) end local meta=minetest.get_meta(pos) meta:set_string("railPosition",minetest.serialize(railPosition)) meta:set_int("lowY",lowY) meta:set_int("highY",highY) end function industrialtest.Magnetizer.detachFenceRail(pos) local meta=minetest.get_meta(pos) if not meta:contains("railPosition") or not meta:contains("lowY") or not meta:contains("highY") then return end local railPosition=minetest.deserialize(meta:get_string("railPosition")) local lowY=meta:get_int("lowY") local highY=meta:get_int("highY") for y=lowY,highY,1 do local fenceMeta=minetest.get_meta(vector.new(railPosition.x,y,railPosition.z)) fenceMeta:set_string("magnetizerPosition","") end meta:set_string("railPosition","") end industrialtest.Magnetizer:register() minetest.register_craft({ type="shaped", output="industrialtest:magnetizer", recipe={ {industrialtest.elementKeys.powerCarrier,"industrialtest:iron_fence",industrialtest.elementKeys.powerCarrier}, {industrialtest.elementKeys.powerCarrier,"industrialtest:machine_block",industrialtest.elementKeys.powerCarrier}, {industrialtest.elementKeys.powerCarrier,"industrialtest:iron_fence",industrialtest.elementKeys.powerCarrier} } }) -- Players to which Y velocity should be added local validatedPlayers={} -- Time since last check to which players the effect should be applied local validationDelta=0.2 minetest.register_globalstep(function(dtime) validationDelta=validationDelta+dtime if validationDelta>=0.2 then validatedPlayers={} local players=minetest.get_connected_players() for _,player in ipairs(players) do local control=player:get_player_control() if (control.jump or control.sneak) and hasMetalBoots(player) then local props=player:get_properties() local pos=player:get_pos() local offsets={ vector.new(props.collisionbox[1],0,0), vector.new(props.collisionbox[4],0,0), vector.new(0,0,props.collisionbox[3]), vector.new(0,0,props.collisionbox[6]) } for _,offset in ipairs(offsets) do local targetPos=vector.add(pos,offset) local targetNode=minetest.get_node(targetPos) if minetest.get_item_group(targetNode.name,"_industrialtest_metalFence")>0 then local fenceMeta=minetest.get_meta(targetPos) if fenceMeta:contains("magnetizerPosition") then table.insert(validatedPlayers,{ playerName=player:get_player_name(), magnetizerPosition=minetest.deserialize(fenceMeta:get_string("magnetizerPosition")), multiplier=(control.sneak and 0.55 or 1) }) break end end end end end end for _,validatedPlayer in ipairs(validatedPlayers) do local player=minetest.get_player_by_name(validatedPlayer.playerName) if player then local magnetizerMeta=minetest.get_meta(validatedPlayer.magnetizerPosition) local physicsOverride=player:get_physics_override() local requiredPower=industrialtest.Magnetizer._opPower*physicsOverride.gravity if magnetizerMeta:get_int("industrialtest.powerAmount")>=requiredPower then industrialtest.api.addPower(magnetizerMeta,-requiredPower) industrialtest.Magnetizer:requestPower(validatedPlayer.magnetizerPosition) industrialtest.Magnetizer:updateFormspec(validatedPlayer.magnetizerPosition) industrialtest.internal.addYVelocityClamped(player,30*dtime*physicsOverride.gravity*validatedPlayer.multiplier,5*physicsOverride.gravity) end end end end)