mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 19:19:21 +01:00
414 lines
13 KiB
Lua
414 lines
13 KiB
Lua
|
||
local computer = require("computer")
|
||
local component = require("component")
|
||
local robot = require("robot")
|
||
local event = require("event")
|
||
local sides = require("sides")
|
||
local geo = component.geolyzer
|
||
local inventoryController = component.inventory_controller
|
||
|
||
-------------------------------------------------------------------------------------------------------------------
|
||
|
||
local fuels = {
|
||
"minecraft:coal",
|
||
"minecraft:lava_bucket",
|
||
"minecraft:coal_block",
|
||
}
|
||
|
||
local shittyResources = {
|
||
"minecraft:cobblestone",
|
||
"minecraft:grass",
|
||
"minecraft:dirt",
|
||
"minecraft:gravel",
|
||
"minecraft:sand",
|
||
"minecraft:sandstone",
|
||
"minecraft:torch",
|
||
"minecraft:planks",
|
||
"minecraft:fence",
|
||
"minecraft:chest",
|
||
"minecraft:monster_egg",
|
||
"minecraft:stonebrick",
|
||
}
|
||
|
||
local oreSearchRadius = 24
|
||
local searchPassesCount = 5
|
||
local minimumOreHardness = 2.5
|
||
local maximumOreHardness = 9
|
||
local replaceToolDurabilityTrigger = 0.05
|
||
local replaceToolRegex = "(minecraft:).+(_pickaxe)"
|
||
local rechargeTrigger = 0.1
|
||
local dropShittyResourcesOnEmptySlots = 5
|
||
|
||
-------------------------------------------------------------------------------------------------------------------
|
||
|
||
local program = {}
|
||
local robotPosition = {x = 0, y = 0, z = 0, rotation = 0}
|
||
local energyStatusCheckEnabled = true
|
||
local toolStatusCheckEnabled = true
|
||
local generatorIsAvailable = component.isAvailable("generator")
|
||
|
||
function program.scan(radius, passes, minHardness, maxHardness)
|
||
local ores = {}
|
||
|
||
-- Заносим все руды в массивыч руд
|
||
for pass = 1, passes do
|
||
print("Scan pass " .. pass .. " started...")
|
||
for x = -radius, radius do
|
||
for z = -radius, radius do
|
||
local stack = geo.scan(x, z, true)
|
||
for y = 1, #stack do
|
||
if stack[y] >= minHardness and stack[y] <= maxHardness then
|
||
-- Заполняем координатную сетку, если массивов еще не существует
|
||
ores[x] = ores[x] or {}
|
||
ores[x][y] = ores[x][y] or {}
|
||
|
||
-- Если мы уже сканировали этот блок, то получаем среднюю плотность из двух значений
|
||
-- Если нет, то банально ставим полученное значение
|
||
if ores[x][y][z] then
|
||
ores[x][y][z] = (ores[x][y][z] + stack[y]) / 2
|
||
else
|
||
ores[x][y][z] = stack[y]
|
||
end
|
||
|
||
-- print("x=" .. x .. ", y=" .. y .. ", z=" .. z .. ", hardness=" .. stack[y])
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Проверяем энергосостояние, а то уже один раз вылетело с ошибкой нот еаугх ЕНЕРГИ, БЛЯДЬ!!11
|
||
program.checkEnergyStatus()
|
||
end
|
||
end
|
||
|
||
-- Переебошиваем массив руд для более удобной работы с ним в линейном формате
|
||
-- Не забываем подчищать говнище за собой, а то роботы не резиновые
|
||
local newOres = {}
|
||
for x in pairs(ores) do
|
||
for y in pairs(ores[x]) do
|
||
for z in pairs(ores[x][y]) do
|
||
table.insert(newOres, {x = robotPosition.x + x, y = robotPosition.y + y - 33, z = robotPosition.z + z})
|
||
ores[x][y][z] = nil
|
||
end
|
||
ores[x][y] = nil
|
||
end
|
||
ores[x]= nil
|
||
end
|
||
|
||
return newOres
|
||
end
|
||
|
||
local function getHardness(x, z)
|
||
local stack = geo.scan(x, z)
|
||
for i = 1, #stack do
|
||
print("i=" .. i .. ", val=" .. stack[i])
|
||
event.pull("key_down")
|
||
end
|
||
end
|
||
|
||
function program.move(direction)
|
||
while true do
|
||
local swingSuccess, swingReason = component.robot.swing(direction)
|
||
if swingSuccess or swingReason == "air" then
|
||
local moveSuccess, moveReason = component.robot.move(direction)
|
||
if moveSuccess then
|
||
break
|
||
end
|
||
else
|
||
if swingReason == "block" then
|
||
print("Unbreakable block detected, going to base")
|
||
program.returnToBase()
|
||
os.exit()
|
||
end
|
||
end
|
||
end
|
||
|
||
if direction == sides.front or direction == sides.back then
|
||
local directionOffset = direction == sides.front and 1 or -1
|
||
|
||
if robotPosition.rotation == 0 then
|
||
robotPosition.x = robotPosition.x + directionOffset
|
||
elseif robotPosition.rotation == 1 then
|
||
robotPosition.z = robotPosition.z + directionOffset
|
||
elseif robotPosition.rotation == 2 then
|
||
robotPosition.x = robotPosition.x - directionOffset
|
||
elseif robotPosition.rotation == 3 then
|
||
robotPosition.z = robotPosition.z - directionOffset
|
||
end
|
||
elseif direction == sides.up or direction == sides.down then
|
||
local directionOffset = direction == sides.up and 1 or -1
|
||
robotPosition.y = robotPosition.y + directionOffset
|
||
end
|
||
end
|
||
|
||
|
||
function program.returnToBase()
|
||
program.gotoPoint(0, robotPosition.y, 0)
|
||
program.turnToRequiredRotation(0)
|
||
program.gotoPoint(0, -2, 0)
|
||
program.tryToDropShittyResources()
|
||
program.gotoPoint(0, 0, 0)
|
||
program.dropAllResoucesIntoBaseChest()
|
||
end
|
||
|
||
function program.getSlotWithFuel()
|
||
for slot = 1, component.robot.inventorySize() do
|
||
local stack = inventoryController.getStackInInternalSlot(slot)
|
||
if stack then
|
||
for fuel = 1, #fuels do
|
||
if stack.name == fuels[fuel] then
|
||
return slot
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function program.tryToRechargeByGenerator()
|
||
if generatorIsAvailable then
|
||
if component.generator.count() == 0 then
|
||
print("Generator is empty, trying to find some fuel in inventory")
|
||
local slot = program.getSlotWithFuel()
|
||
if slot then
|
||
print("Found slot with fuel: " .. slot)
|
||
local oldSlot = robot.select(slot)
|
||
component.generator.insert()
|
||
robot.select(oldSlot)
|
||
return
|
||
else
|
||
print("Slot with fuel not found")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function program.checkEnergyStatus()
|
||
if computer.energy() / computer.maxEnergy() < rechargeTrigger then
|
||
print("Low energy level detected")
|
||
energyStatusCheckEnabled = false
|
||
-- Запоминаем старую позицию, шобы суда вернуться
|
||
local oldPosition = {x = robotPosition.x, y = robotPosition.y, z = robotPosition.z, rotation = robotPosition.rotation}
|
||
-- Пиздуем на базу за зарядкой
|
||
program.returnToBase()
|
||
-- Заряжаемся, пока энергия не достигнет более-менее максимума
|
||
while computer.energy() / computer.maxEnergy() < 0.99 do
|
||
print("Charging up: " .. math.floor(computer.energy() / computer.maxEnergy() * 100) .. "%")
|
||
os.sleep(1)
|
||
end
|
||
-- Пиздуем обратно
|
||
program.gotoPoint(oldPosition.x, oldPosition.y, oldPosition.z)
|
||
program.turnToRequiredRotation(oldPosition.rotation)
|
||
energyStatusCheckEnabled = true
|
||
end
|
||
end
|
||
|
||
function program.turn(clockwise)
|
||
component.robot.turn(clockwise)
|
||
robotPosition.rotation = robotPosition.rotation + (clockwise and 1 or -1)
|
||
if robotPosition.rotation > 3 then
|
||
robotPosition.rotation = 0
|
||
elseif robotPosition.rotation < 0 then
|
||
robotPosition.rotation = 3
|
||
end
|
||
end
|
||
|
||
function program.turnToRequiredRotation(requiredRotation)
|
||
local difference = robotPosition.rotation - requiredRotation
|
||
|
||
if difference ~= 0 then
|
||
local fastestWay
|
||
if difference > 0 then
|
||
if difference > 2 then fastestWay = true else fastestWay = false end
|
||
else
|
||
if -difference > 2 then fastestWay = false else fastestWay = true end
|
||
end
|
||
|
||
while robotPosition.rotation ~= requiredRotation do
|
||
program.turn(fastestWay)
|
||
end
|
||
end
|
||
end
|
||
|
||
function program.gotoPoint(xTarget, yTarget, zTarget)
|
||
local xDistance = xTarget - robotPosition.x
|
||
local yDistance = yTarget - robotPosition.y
|
||
local zDistance = zTarget - robotPosition.z
|
||
|
||
if yDistance ~= 0 then
|
||
local direction = yDistance > 0 and sides.up or sides.down
|
||
for i = 1, math.abs(yDistance) do program.move(direction) end
|
||
end
|
||
|
||
if xDistance ~= 0 then
|
||
program.turnToRequiredRotation(xDistance > 0 and 0 or 2)
|
||
for i = 1, math.abs(xDistance) do program.move(sides.front) end
|
||
end
|
||
|
||
if zDistance ~= 0 then
|
||
program.turnToRequiredRotation(zDistance > 0 and 1 or 3)
|
||
for i = 1, math.abs(zDistance) do program.move(sides.front) end
|
||
end
|
||
|
||
-- Если количество пустых слотов меньше, чем лимит пустых слотов,
|
||
-- то выбрасываем весь дерьмовый шмот, указанный в массиве дерьмового шмота
|
||
program.tryToDropShittyResources()
|
||
|
||
-- Если включена проверка энергосостояния, то делаем ее и возвращаемся на базу
|
||
-- для подзарядки, если требуется
|
||
if energyStatusCheckEnabled then program.checkEnergyStatus() end
|
||
|
||
-- Проверяем также состояние инструментов
|
||
if toolStatusCheckEnabled then program.checkToolStatus() end
|
||
|
||
-- А еще заправляем генератор
|
||
program.tryToRechargeByGenerator()
|
||
end
|
||
|
||
function program.findNearestOre(ores)
|
||
local nearest
|
||
for i = 1, #ores do
|
||
local distance = math.sqrt((ores[i].x - robotPosition.x) ^ 2 + (ores[i].y - robotPosition.y) ^ 2 + (ores[i].z - robotPosition.z) ^ 2)
|
||
if not nearest or distance < nearest.distance then
|
||
nearest = {x = ores[i].x, y = ores[i].y, z = ores[i].z, distance = distance, oreIndex = i}
|
||
end
|
||
end
|
||
return nearest
|
||
end
|
||
|
||
function program.scanAndDig(radius, passes, minHardness, maxHardness, bedrockLocation)
|
||
local ores = program.scan(radius, passes, minHardness, maxHardness)
|
||
print("Scanning finished, count of resources to mine: " .. #ores)
|
||
while #ores > 0 do
|
||
local nearest = program.findNearestOre(ores)
|
||
if nearest.y >= bedrockLocation and nearest.y < 0 then
|
||
-- print("Found next nearest ore: (" .. nearest.x .. "; " .. nearest.y .. "; " .. nearest.z .. ")")
|
||
program.gotoPoint(nearest.x, nearest.y, nearest.z)
|
||
end
|
||
table.remove(ores, nearest.oreIndex)
|
||
end
|
||
end
|
||
|
||
function program.getBedrockLocation()
|
||
while true do
|
||
local success, reason = component.robot.swing(sides.down)
|
||
if success or reason == "air" then
|
||
program.move(sides.down)
|
||
else
|
||
if reason == "block" then
|
||
print("Bedrock location is: " .. robotPosition.y)
|
||
return robotPosition.y
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function program.getEmptySlotsCount()
|
||
local count = 0
|
||
for slot = 1, robot.inventorySize() do
|
||
count = count + (robot.count(slot) == 0 and 1 or 0)
|
||
end
|
||
return count
|
||
end
|
||
|
||
function program.tryToDropShittyResources()
|
||
if program.getEmptySlotsCount() < dropShittyResourcesOnEmptySlots then
|
||
print("Trying to drop all shitty resources to free some slots for mining")
|
||
for slot = 1, robot.inventorySize() do
|
||
local stack = inventoryController.getStackInInternalSlot(slot)
|
||
if stack then
|
||
for i = 1, #shittyResources do
|
||
if stack.name == shittyResources[i] then
|
||
robot.select(slot)
|
||
robot.drop()
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if program.getEmptySlotsCount() < dropShittyResourcesOnEmptySlots - 2 then
|
||
local oldPosition = {x = robotPosition.x, y = robotPosition.y, z = robotPosition.z, rotation = robotPosition.rotation}
|
||
program.returnToBase()
|
||
program.gotoPoint(oldPosition.x, oldPosition.y, oldPosition.z)
|
||
program.turnToRequiredRotation(oldPosition.rotation)
|
||
end
|
||
|
||
robot.select(1)
|
||
end
|
||
end
|
||
|
||
function program.dropAllResoucesIntoBaseChest()
|
||
print("Dropping all mined resources to chest on base")
|
||
for slot = 1, robot.inventorySize() do
|
||
local stack = inventoryController.getStackInInternalSlot(slot)
|
||
if stack then
|
||
if not string.match(stack.name, replaceToolRegex) then
|
||
robot.select(slot)
|
||
robot.drop()
|
||
end
|
||
end
|
||
end
|
||
robot.select(1)
|
||
end
|
||
|
||
function program.checkToolStatus()
|
||
if robot.durability() < replaceToolDurabilityTrigger then
|
||
print("Equipped tool durability lesser then " .. replaceToolDurabilityTrigger)
|
||
local success = false
|
||
|
||
for slot = 1, robot.inventorySize() do
|
||
local stack = inventoryController.getStackInInternalSlot(slot)
|
||
if stack then
|
||
if string.match(stack.name, replaceToolRegex) and stack.damage / stack.maxDamage < replaceToolDurabilityTrigger then
|
||
local oldSlot = robot.select(slot)
|
||
inventoryController.equip()
|
||
robot.select(oldSlot)
|
||
success = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
if not success and toolStatusCheckEnabled then
|
||
toolStatusCheckEnabled = false
|
||
returnToBase()
|
||
print("No one useable tool are found in inventory, going back to base")
|
||
os.exit()
|
||
else
|
||
print("Successfullty switched tool to another from inventory")
|
||
end
|
||
end
|
||
end
|
||
|
||
-------------------------------------------------------------------------------------------------------------------
|
||
|
||
-- getHardness(1, 0)
|
||
-- program.checkToolStatus()
|
||
-- program.move(sides.front)
|
||
|
||
-- Выбираем сразу первый слотик по умолчанию
|
||
robot.select(1)
|
||
-- Определяем позицию говна
|
||
print("Going deeper to determine bedrock location...")
|
||
local bedrockLocation = program.getBedrockLocation() + 4
|
||
-- Ебошим стартовую точку после определения позиции говна, и если она слишком высоко, то робот начнет как раз от нее же
|
||
local startPoint = bedrockLocation + 32
|
||
if startPoint > 0 then startPoint = 0 end
|
||
|
||
-- Пиздуем на старт и вкалываем до посинения
|
||
program.gotoPoint(0, startPoint, 0)
|
||
program.scanAndDig(oreSearchRadius, searchPassesCount, minimumOreHardness, maximumOreHardness, bedrockLocation)
|
||
|
||
-- В конце возвращаемся на начало и ожидаем, че уж там
|
||
program.returnToBase()
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|