添加货运程序
This commit is contained in:
400
Logistics/startup.lua
Normal file
400
Logistics/startup.lua
Normal file
@@ -0,0 +1,400 @@
|
||||
-- Turtle Logistics System v4.1 (Optimized)
|
||||
-- Supports direct container-to-container transfers
|
||||
-- Config saved in config.cfg
|
||||
|
||||
local configFile = "config.cfg"
|
||||
local tasks = {}
|
||||
local turtleName = "turtle_" .. os.getComputerID() -- Default name
|
||||
local directions = {
|
||||
up = "up", down = "down", forward = "forward"
|
||||
}
|
||||
|
||||
-- Load configuration
|
||||
local function loadConfig()
|
||||
if fs.exists(configFile) then
|
||||
local file = fs.open(configFile, "r")
|
||||
local data = file.readAll()
|
||||
file.close()
|
||||
tasks = textutils.unserialize(data) or {}
|
||||
end
|
||||
|
||||
-- Load turtle name if set
|
||||
if fs.exists("turtle_name.cfg") then
|
||||
local nameFile = fs.open("turtle_name.cfg", "r")
|
||||
turtleName = nameFile.readAll()
|
||||
nameFile.close()
|
||||
end
|
||||
end
|
||||
|
||||
-- Save configuration
|
||||
local function saveConfig()
|
||||
local file = fs.open(configFile, "w")
|
||||
file.write(textutils.serialize(tasks))
|
||||
file.close()
|
||||
end
|
||||
|
||||
-- Save turtle name
|
||||
local function saveTurtleName()
|
||||
local nameFile = fs.open("turtle_name.cfg", "w")
|
||||
nameFile.write(turtleName)
|
||||
nameFile.close()
|
||||
end
|
||||
|
||||
-- Check if value is a direction
|
||||
local function isDirection(value)
|
||||
return directions[value] ~= nil
|
||||
end
|
||||
|
||||
-- Parse item requirements from string
|
||||
local function parseItemRequirements(input)
|
||||
local requirements = {}
|
||||
|
||||
-- Check if input is a JSON-like table
|
||||
if input:sub(1,1) == "{" and input:sub(-1) == "}" then
|
||||
-- Remove curly braces
|
||||
local content = input:sub(2, -2)
|
||||
|
||||
-- Split key-value pairs
|
||||
for pair in content:gmatch("[^,]+") do
|
||||
local key, value = pair:match("[\"']?(.-)[\"']?%s*:%s*(%d+)")
|
||||
if key and value then
|
||||
requirements[key] = tonumber(value)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Simple format: item:minCount
|
||||
for item in input:gmatch("%S+") do
|
||||
local name, minCount = item:match("([^:]+):(%d+)")
|
||||
if name and minCount then
|
||||
requirements[name] = tonumber(minCount)
|
||||
else
|
||||
requirements[item] = 0 -- No minimum requirement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return requirements
|
||||
end
|
||||
|
||||
-- Get container item list using container.list()
|
||||
local function getContainerItems(containerName)
|
||||
local container = peripheral.wrap(containerName)
|
||||
if not container then return nil end
|
||||
|
||||
local items = {}
|
||||
local containerList = container.list()
|
||||
|
||||
for slot, item in pairs(containerList) do
|
||||
items[slot] = {
|
||||
count = item.count,
|
||||
name = item.name
|
||||
}
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
-- Execute item transfer with min count requirements (Optimized)
|
||||
local function executeTransfer(task)
|
||||
-- Case 1: Both source and destination are containers
|
||||
if not isDirection(task.source) and not isDirection(task.destination) then
|
||||
local source = peripheral.wrap(task.source)
|
||||
local destination = peripheral.wrap(task.destination)
|
||||
|
||||
if not source or not destination then
|
||||
if not source then print("Error: Source container not found: "..task.source) end
|
||||
if not destination then print("Error: Destination container not found: "..task.destination) end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get destination name for pushItems
|
||||
local destName = peripheral.getName(destination)
|
||||
|
||||
-- Check min count requirements
|
||||
if task.items then
|
||||
local sourceItems = getContainerItems(task.source)
|
||||
local itemCounts = {}
|
||||
|
||||
for slot, item in pairs(sourceItems) do
|
||||
if task.items[item.name] then
|
||||
itemCounts[item.name] = (itemCounts[item.name] or 0) + item.count
|
||||
end
|
||||
end
|
||||
|
||||
for itemName, minCount in pairs(task.items) do
|
||||
if minCount > 0 and (itemCounts[itemName] or 0) < minCount then
|
||||
print("Not enough "..itemName.." ("..(itemCounts[itemName] or 0).." < "..minCount..")")
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Transfer items directly
|
||||
local sourceItems = getContainerItems(task.source)
|
||||
local totalTransferred = 0
|
||||
|
||||
for slot, item in pairs(sourceItems) do
|
||||
local shouldTransfer = not task.items or (task.items[item.name] ~= nil)
|
||||
|
||||
if shouldTransfer then
|
||||
local count = item.count
|
||||
if task.items and task.items[item.name] then
|
||||
count = math.min(count, task.items[item.name])
|
||||
end
|
||||
|
||||
local transferred = source.pushItems(destName, slot, count)
|
||||
totalTransferred = totalTransferred + transferred
|
||||
end
|
||||
end
|
||||
|
||||
return totalTransferred > 0
|
||||
|
||||
-- Case 2: Source is direction, destination is container
|
||||
elseif isDirection(task.source) and not isDirection(task.destination) then
|
||||
local destination = peripheral.wrap(task.destination)
|
||||
if not destination then
|
||||
print("Error: Destination container not found: "..task.destination)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Suck items from direction (limited to 16 slots)
|
||||
local sucked = false
|
||||
local suckFunc = turtle.suck
|
||||
if task.source == "up" then suckFunc = turtle.suckUp
|
||||
elseif task.source == "down" then suckFunc = turtle.suckDown end
|
||||
|
||||
for i = 1, 16 do
|
||||
if suckFunc() then
|
||||
sucked = true
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not sucked then return false end
|
||||
|
||||
-- Push items to destination container
|
||||
local pushed = false
|
||||
for slot = 1, 16 do
|
||||
if turtle.getItemCount(slot) > 0 then
|
||||
if destination.pullItems(turtleName, slot) > 0 then
|
||||
pushed = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return pushed
|
||||
|
||||
-- Case 3: Source is container, destination is direction
|
||||
elseif not isDirection(task.source) and isDirection(task.destination) then
|
||||
local source = peripheral.wrap(task.source)
|
||||
if not source then
|
||||
print("Error: Source container not found: "..task.source)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check min count requirements
|
||||
if task.items then
|
||||
local sourceItems = getContainerItems(task.source)
|
||||
local itemCounts = {}
|
||||
|
||||
for slot, item in pairs(sourceItems) do
|
||||
if task.items[item.name] then
|
||||
itemCounts[item.name] = (itemCounts[item.name] or 0) + item.count
|
||||
end
|
||||
end
|
||||
|
||||
for itemName, minCount in pairs(task.items) do
|
||||
if minCount > 0 and (itemCounts[itemName] or 0) < minCount then
|
||||
print("Not enough "..itemName.." ("..(itemCounts[itemName] or 0).." < "..minCount..")")
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Pull items to turtle
|
||||
local sourceItems = getContainerItems(task.source)
|
||||
local pulled = false
|
||||
|
||||
for slot, item in pairs(sourceItems) do
|
||||
local shouldTransfer = not task.items or (task.items[item.name] ~= nil)
|
||||
|
||||
if shouldTransfer then
|
||||
local count = item.count
|
||||
if task.items and task.items[item.name] then
|
||||
count = math.min(count, task.items[item.name])
|
||||
end
|
||||
|
||||
if source.pushItems(turtleName, slot, count) > 0 then
|
||||
pulled = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not pulled then return false end
|
||||
|
||||
-- Drop items to direction
|
||||
local dropFunc = turtle.drop
|
||||
if task.destination == "up" then dropFunc = turtle.dropUp
|
||||
elseif task.destination == "down" then dropFunc = turtle.dropDown end
|
||||
|
||||
local dropped = false
|
||||
for slot = 1, 16 do
|
||||
if turtle.getItemCount(slot) > 0 then
|
||||
turtle.select(slot)
|
||||
if dropFunc() then
|
||||
dropped = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return dropped
|
||||
|
||||
-- Case 4: Both source and destination are directions
|
||||
else
|
||||
-- Suck items from source direction (limited to 16 slots)
|
||||
local suckFunc = turtle.suck
|
||||
if task.source == "up" then suckFunc = turtle.suckUp
|
||||
elseif task.source == "down" then suckFunc = turtle.suckDown end
|
||||
|
||||
local sucked = false
|
||||
for i = 1, 16 do
|
||||
if suckFunc() then
|
||||
sucked = true
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not sucked then return false end
|
||||
|
||||
-- Drop items to destination direction
|
||||
local dropFunc = turtle.drop
|
||||
if task.destination == "up" then dropFunc = turtle.dropUp
|
||||
elseif task.destination == "down" then dropFunc = turtle.dropDown end
|
||||
|
||||
local dropped = false
|
||||
for slot = 1, 16 do
|
||||
if turtle.getItemCount(slot) > 0 then
|
||||
turtle.select(slot)
|
||||
if dropFunc() then
|
||||
dropped = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return dropped
|
||||
end
|
||||
end
|
||||
|
||||
-- Main task loop (optimized)
|
||||
local function taskLoop()
|
||||
while true do
|
||||
for i, task in ipairs(tasks) do
|
||||
local success, err = pcall(executeTransfer, task)
|
||||
if not success then
|
||||
print("Task "..i.." error: "..err)
|
||||
end
|
||||
end
|
||||
os.sleep(0.5) -- Slightly longer sleep to reduce CPU usage
|
||||
end
|
||||
end
|
||||
|
||||
-- Command processing
|
||||
local function processCommand(cmd)
|
||||
local args = {}
|
||||
for word in cmd:gmatch("%S+") do
|
||||
table.insert(args, word)
|
||||
end
|
||||
|
||||
if #args == 0 then return end
|
||||
|
||||
local command = args[1]:lower()
|
||||
|
||||
if command == "add" and #args >= 3 then
|
||||
local newTask = {
|
||||
source = args[2],
|
||||
destination = args[3],
|
||||
items = nil
|
||||
}
|
||||
|
||||
-- Parse item requirements
|
||||
if #args > 3 then
|
||||
local itemsInput = table.concat(args, " ", 4)
|
||||
newTask.items = parseItemRequirements(itemsInput)
|
||||
end
|
||||
|
||||
table.insert(tasks, newTask)
|
||||
saveConfig()
|
||||
print("Task added: "..newTask.source.." -> "..newTask.destination)
|
||||
|
||||
elseif command == "list" then
|
||||
if #tasks == 0 then
|
||||
print("No tasks configured")
|
||||
else
|
||||
for i, task in ipairs(tasks) do
|
||||
local itemInfo = ""
|
||||
if task.items then
|
||||
local itemsList = {}
|
||||
for name, minCount in pairs(task.items) do
|
||||
if minCount > 0 then
|
||||
table.insert(itemsList, name..":"..minCount)
|
||||
else
|
||||
table.insert(itemsList, name)
|
||||
end
|
||||
end
|
||||
itemInfo = " ("..table.concat(itemsList, ", ")..")"
|
||||
end
|
||||
print("["..i.."] "..task.source.." -> "..task.destination..itemInfo)
|
||||
end
|
||||
end
|
||||
|
||||
elseif command == "remove" and #args >= 2 then
|
||||
local index = tonumber(args[2])
|
||||
if index and tasks[index] then
|
||||
table.remove(tasks, index)
|
||||
saveConfig()
|
||||
print("Task "..index.." removed")
|
||||
else
|
||||
print("Invalid task index")
|
||||
end
|
||||
|
||||
elseif command == "setname" and #args >= 2 then
|
||||
turtleName = args[2]
|
||||
saveTurtleName()
|
||||
print("Turtle name set to: "..turtleName)
|
||||
|
||||
elseif command == "help" then
|
||||
print("Available commands:")
|
||||
print("add <source> <destination> [items] - Add transfer task")
|
||||
print(" Items format:")
|
||||
print(" Simple: item1[:minCount] item2[:minCount] ...")
|
||||
print(" JSON-like: {\"item1\":minCount, \"item2\":minCount}")
|
||||
print("list - List all tasks")
|
||||
print("remove <index> - Remove task")
|
||||
print("setname <name> - Set turtle peripheral name")
|
||||
print("exit - Exit program")
|
||||
|
||||
elseif command == "exit" then
|
||||
print("Exiting program")
|
||||
os.sleep(0.5)
|
||||
error("Program terminated", 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialize
|
||||
loadConfig()
|
||||
print("Turtle Logistics System started. Type 'help' for commands.")
|
||||
print("Current turtle name: "..turtleName)
|
||||
|
||||
-- Main loop
|
||||
parallel.waitForAll(
|
||||
function()
|
||||
while true do
|
||||
write("> ")
|
||||
local command = read()
|
||||
processCommand(command)
|
||||
end
|
||||
end,
|
||||
taskLoop
|
||||
)
|
||||
Reference in New Issue
Block a user