diff --git a/farms/spawner.lua b/farms/spawner.lua new file mode 100644 index 0000000..82a3306 --- /dev/null +++ b/farms/spawner.lua @@ -0,0 +1,155 @@ +local Peripheral = require('peripheral') +local Point = require('point') +local Util = require('util') + +local device = _G.device +local os = _G.os +local turtle = _G.turtle + +local mobTypes = Util.transpose({ ... }) + +local function equip(side, item, rawName) + local equipped = Peripheral.lookup('side/' .. side) + + if equipped and equipped.type == item then + return true + end + + if not turtle.equip(side, rawName or item) then + if not turtle.selectSlotWithQuantity(0) then + error('No slots available') + end + turtle.equip(side) + if not turtle.equip(side, item) then + error('Unable to equip ' .. item) + end + end + + turtle.select(1) +end + +equip('left', 'minecraft:diamond_sword') + +equip('right', 'plethora:scanner', 'plethora:module:2') +local scanner = device['plethora:scanner'] + +turtle.reset() +local facing = scanner.getBlockMeta(0, 0, 0).state.facing +turtle.point.heading = Point.facings[facing].heading + +local data = scanner.scan() +local spawners = Util.findAll(data, 'name', 'minecraft:mob_spawner') +local spawner = Point.closest(turtle.point, spawners) or error('spawner not in range') + +turtle._goto(Point.below(spawner)) + +Util.filterInplace(data, function(b) + return b.name == 'minecraft:chest' or + b.name == 'minecraft:dispenser' or + b.name == 'minecraft:hopper' +end) +local chest = Point.closest(spawner, data) or error('missing drop off chest') +turtle._goto(Point.above(chest)) + +equip('right', 'plethora:sensor', 'plethora:module:3') +local sensor = device['plethora:sensor'] + +turtle.setMovementStrategy('goto') +turtle.setPolicy(turtle.policies.attack) + +local function dropOff() + local inv = turtle.getSummedInventory() + for _, slot in pairs(inv) do + if slot.count >= 16 then + if turtle.getFuelLevel() < 5000 then + turtle.refuel(slot.name, 16) + end + end + end + + inv = turtle.getSummedInventory() + for _, slot in pairs(inv) do + if slot.count >= 16 or turtle.getSlot(8).count > 0 then + turtle.eachFilledSlot(function(s) + if s.name ~= 'plethora:module' then + turtle.dropDownAt(chest, s.name, s.count) + end + end) + break + end + end + turtle.select(1) +end + +local function normalize(b) + b.x = Util.round(b.x) + turtle.point.x + b.y = Util.round(b.y) + turtle.point.y + b.z = Util.round(b.z) + turtle.point.z + + return b.x >= spawner.x - 4 and b.x <= spawner.x + 4 and + b.y >= spawner.y - 4 and b.y <= spawner.y + 4 and + b.z >= spawner.z - 4 and b.z <= spawner.z + 4 +end + +local function aboveAttack(b) + if turtle.attackDownAt(b) then + repeat until not turtle.attackDown() + end +end + +local function moveAgainst(b) + if turtle.faceAgainst(b) then + return turtle.attack() + end +end + +local function getAttackStrategy(name) + local Strategies = { + Pig = { + attack = aboveAttack, + }, + Default = { + attack = moveAgainst, + } + } + + return Strategies[name] or Strategies.Default +end + +while true do + local blocks = sensor.sense() + local mobs = Util.filterInplace(blocks, function(b) + if mobTypes[b.name] then + return normalize(b) + end + end) + + if turtle.getFuelLevel() == 0 then + error('Out of fuel') + end + +print(#mobs) + if #mobs == 0 then +print('sleeping') + os.sleep(3) + else + Point.eachClosest(turtle.point, mobs, function(b) +print('attack: ' .. b.id) + local strategy = getAttackStrategy(b.name) + if strategy.attack(b) then + while true do + local mob = sensor.getMetaByID(b.id) + if not mob or Util.empty(mob) then + break + end + normalize(mob) + if not strategy.attack(mob) then + break + end + end + end + end) + end + + dropOff() +end