Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- pastebin get wngsBEP2 StorageManager
- -- === CONFIG ===
- local DISK_NAMES = {
- incoming = "Incoming Task",
- user = "User Task",
- outgoing = "Outgoing Task",
- finished = "Finished Task",
- settings = "Settings",
- storage = "Data Storage",
- init = "Turtle Initializing"
- }
- local TASK_DATA = {
- currentTasks = {},
- emptyChests = {},
- storedItems = {},
- completedTasks = {},
- totalChestCount = 0,
- outgoingTask = nil
- }
- local SYSTEM_STATE = {
- chestInitialized = false,
- waitingForChestPlacement = false,
- orientation = nil,
- orientationDirection = 1,
- startCoords = nil,
- endCoords = nil,
- finishBlockCoords = nil,
- outputChestCoords = nil,
- refuelChestCoords = nil,
- modulo = nil,
- yModulo = nil,
- maxEntriesPerDiskFile = 100
- }
- local TASK_TYPES = {
- createChests = "create_chests",
- storeItems = "store_items",
- getItems = "get_items",
- checkInventory = "check_inventory",
- initializeChests = "initialize_chests"
- }
- local MULTI_DISK_FILES = {
- currentTasks = true,
- emptyChests = true,
- storedItems = true,
- completedTasks = true
- }
- local taskIdCounter = 1
- local currentTaskSourceIndex = 1
- local TASK_SOURCES = {"incoming", "user", "settings"} -- disk name keys
- local DEFAULT_MAX_ENTRIES_PER_FILE = 100
- local DEFAULT_COMPLETED_TASKS_LIMIT = 50
- SYSTEM_STATE = SYSTEM_STATE or {}
- SYSTEM_STATE.maxEntriesPerDiskFile = SYSTEM_STATE.maxEntriesPerDiskFile or DEFAULT_MAX_ENTRIES_PER_FILE
- local STORAGE_LABEL_BASE = DISK_NAMES.storage
- -- === UTILITIES ===
- -- compare two coords
- local function equalCoords(coord1, coord2)
- return coord1.x == coord2.x and coord1.y == coord2.y and coord1.z == coord2.z
- end
- -- copy a table
- function deepCopy(orig)
- local copy
- if type(orig) == 'table' then
- copy = {}
- for k, v in pairs(orig) do
- copy[k] = deepCopy(v)
- end
- else
- copy = orig
- end
- return copy
- end
- local function coordToString(coord)
- return "(" .. tostring(coord.x) .. ", " .. tostring(coord.y) .. ", " .. tostring(coord.z) .. ")"
- end
- -- === DISK MANAGEMENT ===
- local function getDiskByLabel(label)
- for _, side in ipairs(peripheral.getNames()) do
- if peripheral.getType(side) == "drive" then
- local disk = peripheral.wrap(side)
- if disk.getDiskLabel() == label then
- return disk, disk.getMountPath()
- end
- end
- end
- return nil, nil
- end
- local function getStorageDisks()
- local disks = {}
- local index = 1
- while true do
- local label = STORAGE_LABEL_BASE .. (index > 1 and (" " .. tostring(index)) or "")
- local _, path = getDiskByLabel(label)
- if not path then break end
- table.insert(disks, {label = label, path = path})
- index = index + 1
- end
- return disks
- end
- local function splitTable(tbl, chunkSize)
- local chunks = {}
- for i = 1, #tbl, chunkSize do
- table.insert(chunks, {unpack(tbl, i, math.min(i + chunkSize - 1, #tbl))})
- end
- return chunks
- end
- local function saveTableToDisk(tableData, baseFilename)
- local maxEntries = SYSTEM_STATE.maxEntriesPerDiskFile or DEFAULT_MAX_ENTRIES_PER_FILE
- local parts = splitTable(tableData, maxEntries)
- local disks = getStorageDisks()
- if #parts > #disks then
- print("[WARN] Speichergrenze erreicht: Füge eine weitere Data Storage Disk hinzu.")
- repeat
- sleep(1)
- disks = getStorageDisks()
- until #disks >= #parts
- end
- for i, part in ipairs(parts) do
- local fullPath = fs.combine(disks[i].path, baseFilename .. "_" .. tostring(i))
- local file = fs.open(fullPath, "w")
- file.write(textutils.serialize(part))
- file.close()
- end
- for i = #parts + 1, #disks do
- local path = fs.combine(disks[i].path, baseFilename .. "_" .. tostring(i))
- if fs.exists(path) then fs.delete(path) end
- end
- end
- local function loadTableFromDisk(baseFilename)
- local result = {}
- local index = 1
- while true do
- local label = STORAGE_LABEL_BASE .. (index > 1 and (" " .. tostring(index)) or "")
- local _, path = getDiskByLabel(label)
- if not path then break end
- local filePath = fs.combine(path, baseFilename .. "_" .. tostring(index))
- if not fs.exists(filePath) then break end
- local file = fs.open(filePath, "r")
- local chunk = textutils.unserialize(file.readAll())
- file.close()
- if type(chunk) == "table" then
- for _, entry in ipairs(chunk) do
- table.insert(result, entry)
- end
- end
- index = index + 1
- end
- return result
- end
- -- == Individual Save and Loading ==
- local function saveTotalChestCount(count)
- local disk, path = getDiskByLabel("Data Storage")
- if not path then error("Data Storage disk not found") end
- local fullPath = fs.combine(path, "totalChestCount.txt")
- local file = fs.open(fullPath, "w")
- file.write(textutils.serialize({ count = count }))
- file.close()
- end
- local function loadTotalChestCount()
- local disk, path = getDiskByLabel("Data Storage")
- local fullPath = fs.combine(path, "totalChestCount.txt")
- if not path or not fs.exists(fullPath) then return nil end
- local file = fs.open(fullPath, "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- return data
- end
- local function saveSystemState()
- for _, field in ipairs({"orientation", "startCoords", "endCoords", "finishBlockCoords", "outputChestCoords", "modulo", "yModulo"}) do
- if SYSTEM_STATE[field] == nil then
- print("[WARNUNG] SYSTEM_STATE-Feld fehlt: " .. field)
- end
- end
- local disk, path = getDiskByLabel("Data Storage")
- if not path then error("Data Storage disk not found") end
- local fullPath = fs.combine(path, "systemState.txt")
- local file = fs.open(fullPath, "w")
- file.write(textutils.serialize(SYSTEM_STATE))
- file.close()
- end
- local function loadSystemState()
- local disk, path = getDiskByLabel("Data Storage")
- if not path then return {} end
- local fullPath = fs.combine(path, "systemState.txt")
- if not fs.exists(fullPath) then return {} end
- local file = fs.open(fullPath, "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- return data or {}
- end
- -- == save general IdCounter on storage ==
- local function loadTaskIdCounter()
- local disk, path = getDiskByLabel(DISK_NAMES.storage)
- if not path then return 1 end
- local fullPath = fs.combine(path, "taskIdCounter")
- if fs.exists(fullPath) then
- local file = fs.open(fullPath, "r")
- local id = tonumber(file.readLine())
- file.close()
- return id or 1
- end
- return 1
- end
- local function saveTaskIdCounter()
- local disk, path = getDiskByLabel(DISK_NAMES.storage)
- if not path then error("Data Storage disk not found for saving taskIdCounter") end
- local fullPath = fs.combine(path, "taskIdCounter")
- local file = fs.open(fullPath, "w")
- file.writeLine(tostring(taskIdCounter))
- file.close()
- end
- -- == save general coords ==
- local function getCoordsList(path)
- if not fs.exists(path) then return {} end
- local file = fs.open(path, "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- return data or {}
- end
- local function saveCoordList(path, coordList)
- local file = fs.open(path, "w")
- file.write(textutils.serialize(coordList))
- file.close()
- end
- local function addCoordToList(path, coord)
- local coords = getCoordsList(path)
- table.insert(coords, coord)
- saveCoordList(path, coords)
- end
- -- == save general tasks ==
- function getTaskList(path)
- local filename = path:match(".-([^/]+)$")
- local baseName = filename:gsub("%.txt", "")
- if MULTI_DISK_FILES[baseName] then
- return loadTableFromDisk(baseName)
- end
- if not fs.exists(path) then return {} end
- local file = fs.open(path, "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- return data or {}
- end
- function saveTaskList(path, taskList)
- local filename = path:match(".-([^/]+)$")
- local baseName = filename:gsub("%.txt", "")
- if MULTI_DISK_FILES[baseName] then
- return saveTableToDisk(taskList, baseName)
- end
- local file = fs.open(path, "w")
- file.write(textutils.serialize(taskList))
- file.close()
- end
- local function addTaskToList(path, task)
- local tasks = getTaskList(path)
- table.insert(tasks, task)
- saveTaskList(path, tasks)
- end
- -- save task on outgoing
- local function saveTaskToDisk(contentTable)
- local taskCopy = deepCopy(contentTable) -- wichtig: Kopie erstellen
- taskCopy.taskId = taskIdCounter
- taskIdCounter = taskIdCounter + 1
- saveTaskIdCounter()
- local outgoingDisk, outgoingPath = getDiskByLabel(DISK_NAMES.outgoing)
- if not outgoingPath then error("Outgoing Task disk not found") end
- local fullOutgoingPath = fs.combine(outgoingPath, "task_list.txt")
- addTaskToList(fullOutgoingPath, taskCopy)
- local storageDisk, storagePath = getDiskByLabel(DISK_NAMES.storage)
- if not storagePath then error("Data Storage disk not found") end
- local fullStoragePath = fs.combine(storagePath, "currentTasks")
- addTaskToList(fullStoragePath, taskCopy)
- table.insert(TASK_DATA.currentTasks, taskCopy)
- end
- local function trimCompletedTasks()
- if TASK_DATA and TASK_DATA.completedTasks and #TASK_DATA.completedTasks > DEFAULT_COMPLETED_TASKS_LIMIT then
- while #TASK_DATA.completedTasks > DEFAULT_COMPLETED_TASKS_LIMIT do
- table.remove(TASK_DATA.completedTasks, 1)
- end
- saveTableToDisk(TASK_DATA.completedTasks, "completedTasks")
- end
- end
- local function checkStorageOverflow()
- local tablesToCheck = {
- currentTasks = TASK_DATA.currentTasks,
- emptyChests = TASK_DATA.emptyChests,
- storedItems = TASK_DATA.storedItems,
- completedTasks = TASK_DATA.completedTasks
- }
- local disks = getStorageDisks()
- local maxEntries = SYSTEM_STATE.maxEntriesPerDiskFile or DEFAULT_MAX_ENTRIES_PER_FILE
- local availableChunks = #disks
- for name, list in pairs(tablesToCheck) do
- if math.ceil((#list + 5) / maxEntries) > availableChunks then
- print("[INFO] Bitte weitere Data Storage Disk anschließen für " .. name)
- repeat
- sleep(1)
- disks = getStorageDisks()
- availableChunks = #disks
- until math.ceil((#list + 5) / maxEntries) <= availableChunks
- end
- end
- end
- -- === MONITOR STORAGE SPACE ===
- function monitorStorageSpace()
- local MIN_FREE_BYTES = 20000 -- Warnschwelle
- local REDUCE_PERCENTAGE = 0.05
- local disks = getStorageDisks()
- local lowSpaceDetected = false
- for _, disk in ipairs(disks) do
- local free = fs.getFreeSpace(disk.path)
- if free < MIN_FREE_BYTES then
- print("[WARNUNG] Speicherplatz auf " .. disk.label .. " ist gering: " .. tostring(free) .. " Bytes frei.")
- lowSpaceDetected = true
- end
- end
- if lowSpaceDetected then
- print("[INFO] Speicherplatz wird knapp. Werte werden neu gespeichert und Chunkgröße ggf. angepasst.")
- print("Bitte neue Disk bereithalten, falls nötig.")
- print("Drücke Enter zum Fortfahren.")
- io.read()
- local oldMax = SYSTEM_STATE.maxEntriesPerDiskFile or DEFAULT_MAX_ENTRIES_PER_FILE
- local reduceBy = math.max(1, math.floor(oldMax * REDUCE_PERCENTAGE))
- local newMax = oldMax - reduceBy
- SYSTEM_STATE.maxEntriesPerDiskFile = newMax
- saveSystemState()
- -- Speicherbare Tabellen erneut sichern
- saveTableToDisk(TASK_DATA.currentTasks, "currentTasks")
- saveTableToDisk(TASK_DATA.emptyChests, "emptyChests")
- saveTableToDisk(TASK_DATA.storedItems, "storedItems")
- saveTableToDisk(TASK_DATA.completedTasks, "completedTasks")
- print("[INFO] Neue Chunkgröße gesetzt: " .. tostring(newMax) .. " Einträge pro Datei.")
- end
- end
- local function hasOutgoingTasks()
- local _, path = getDiskByLabel(DISK_NAMES.outgoing)
- if not path then return false end
- local tasks = getTaskList(fs.combine(path, "task_list.txt"))
- return #tasks > 0
- end
- local function registerNewChestCoord(newCoord)
- local storageDisk, storagePath = getDiskByLabel(DISK_NAMES.storage)
- local fullPath = fs.combine(storagePath, "usedCoords.txt")
- local chestCoords = getCoordsList(fullPath)
- local bNewCoord = true
- for index, coord in ipairs(chestCoords) do
- if equalCoords(coord, newCoord) then
- bNewCoord = false
- print("Coords " .. coordToString(newCoord) .. " already registered.\n")
- end
- end
- if bNewCoord then
- addCoordToList(fullPath, newCoord)
- end
- return bNewCoord
- end
- -- === INITIALIZATION ===
- local function determineOrientation(startPos, endPos)
- local finishPos = SYSTEM_STATE.finishBlockCoords
- local outputPos = SYSTEM_STATE.outputChestCoords
- local refuelPos = SYSTEM_STATE.refuelChestCoords
- if startPos.x ~= endPos.x then
- SYSTEM_STATE.orientation = "x"
- SYSTEM_STATE.orientationDirection = (endPos.x - startPos.x > 0) and 1 or -1
- SYSTEM_STATE.modulo = (startPos.z - 2 * SYSTEM_STATE.orientationDirection) % 8
- elseif startPos.z ~= endPos.z then
- SYSTEM_STATE.orientation = "z"
- SYSTEM_STATE.orientationDirection = (endPos.z - startPos.z > 0) and 1 or -1
- SYSTEM_STATE.modulo = (startPos.x + 2 * SYSTEM_STATE.orientationDirection) % 8
- else
- SYSTEM_STATE.orientation = "unknown"
- SYSTEM_STATE.orientationDirection = 1
- SYSTEM_STATE.modulo = 0
- end
- SYSTEM_STATE.yModulo = (startPos.y - 1) % 7
- local disk, path = getDiskByLabel(DISK_NAMES.init)
- if path then
- local file = fs.open(fs.combine(path, "init.txt"), "w")
- file.writeLine("orientation=" .. SYSTEM_STATE.orientation)
- file.writeLine("direction=" .. tostring(SYSTEM_STATE.orientationDirection))
- file.writeLine("modulo=" .. tostring(SYSTEM_STATE.modulo))
- file.writeLine("yModulo=" .. tostring(SYSTEM_STATE.yModulo))
- file.writeLine("finish_x=" .. tostring(finishPos.x))
- file.writeLine("finish_y=" .. tostring(finishPos.y))
- file.writeLine("finish_z=" .. tostring(finishPos.z))
- file.writeLine("output_x=" .. tostring(outputPos.x))
- file.writeLine("output_y=" .. tostring(outputPos.y))
- file.writeLine("output_z=" .. tostring(outputPos.z))
- file.writeLine("refuel_x=" .. tostring(refuelPos.x))
- file.writeLine("refuel_y=" .. tostring(refuelPos.y))
- file.writeLine("refuel_z=" .. tostring(refuelPos.z))
- file.close()
- end
- end
- local function waitForInitialSettings()
- print("Waiting for settings...")
- local _, path = getDiskByLabel(DISK_NAMES.settings)
- while not path do sleep(1) path = select(2, getDiskByLabel(DISK_NAMES.settings)) end
- local settingsPath = fs.combine(path, "initial_coords.txt")
- while not fs.exists(settingsPath) do sleep(1) end
- sleep(1)
- local file = fs.open(settingsPath, "r")
- local x1, y1, z1 = file.readLine():match("(-?%d+),(-?%d+),(-?%d+)")
- local x2, y2, z2 = file.readLine():match("(-?%d+),(-?%d+),(-?%d+)")
- local x3, y3, z3 = file.readLine():match("(-?%d+),(-?%d+),(-?%d+)")
- local x4, y4, z4 = file.readLine():match("(-?%d+),(-?%d+),(-?%d+)")
- local x5, y5, z5 = file.readLine():match("(-?%d+),(-?%d+),(-?%d+)")
- file.close()
- SYSTEM_STATE.startCoords = {x=tonumber(x1), y=tonumber(y1), z=tonumber(z1)}
- SYSTEM_STATE.endCoords = {x=tonumber(x2), y=tonumber(y2), z=tonumber(z2)}
- SYSTEM_STATE.finishBlockCoords = {x=tonumber(x3), y=tonumber(y3), z=tonumber(z3)}
- SYSTEM_STATE.outputChestCoords = {x=tonumber(x4), y=tonumber(y4), z=tonumber(z4)}
- SYSTEM_STATE.refuelChestCoords = {x=tonumber(x5), y=tonumber(y5), z=tonumber(z5)}
- determineOrientation(SYSTEM_STATE.startCoords, SYSTEM_STATE.endCoords)
- end
- local function initializeTotalChestCount()
- -- Versuche, die Datei zu laden
- local chestCountData = loadTotalChestCount()
- -- Prüfe, ob ein gültiger Wert vorhanden ist
- if chestCountData and type(chestCountData.count) == "number" then
- TASK_DATA.totalChestCount = chestCountData.count
- return
- end
- -- Wenn keine Datei vorhanden ist, aber relevante Daten existieren
- local hasStoredItems = TASK_DATA.storedItems and #TASK_DATA.storedItems > 0
- local hasEmptyChests = TASK_DATA.emptyChests and #TASK_DATA.emptyChests > 0
- if hasStoredItems or hasEmptyChests then
- print("[WARNUNG] Kein gespeicherter Kistenzähler (totalChestCount) gefunden.")
- print("Es wurden jedoch gespeicherte Kisteninformationen entdeckt.")
- print("Bitte gib die gesamte Anzahl aller Kisten im System ein:")
- while true do
- io.write("Kistenzahl: ")
- local input = io.read()
- local num = tonumber(input)
- if num and num > 0 then
- TASK_DATA.totalChestCount = num
- saveTotalChestCount(num)
- print("[INFO] Gesamtanzahl an Kisten auf " .. num .. " gesetzt und gespeichert.")
- break
- else
- print("Ungültige Eingabe. Bitte eine positive Zahl eingeben.")
- end
- end
- end
- end
- local function isSystemStateComplete()
- for _, field in ipairs({
- "orientation", "startCoords", "endCoords",
- "finishBlockCoords", "outputChestCoords", "modulo", "yModulo"
- }) do
- if SYSTEM_STATE[field] == nil then
- print("[WARNUNG] SYSTEM_STATE-Feld fehlt: " .. field)
- return false
- end
- end
- return true
- end
- -- == chest inventory ==
- local function getChestFromEmptyForItem(item)
- if #TASK_DATA.emptyChests == 0 then
- error("Keine leeren Kisten mehr verfügbar!")
- end
- local newChest = table.remove(TASK_DATA.emptyChests, 1)
- saveTableToDisk(TASK_DATA.emptyChests, "emptyChests")
- newChest.amount = 0
- newChest.incomingAmount = 0
- newChest.outgoingAmount = 0
- newChest.stackSize = item.stackSize
- newChest.maxAmount = item.stackSize * 54
- return newChest
- end
- local function addChestToEmpty(chestToAdd)
- local chest = {id = chestToAdd.id, pos = chestToAdd.pos}
- local insertPos = nil
- for i, emptyChest in ipairs(TASK_DATA.emptyChests) do
- if emptyChest.id > chest.id then
- insertPos = i
- break
- end
- end
- if insertPos then
- print("insert at " .. tostring(insertPos))
- table.insert(TASK_DATA.emptyChests, insertPos, chest)
- else
- print("insert at end")
- table.insert(TASK_DATA.emptyChests, chest)
- end
- saveTableToDisk(TASK_DATA.emptyChests, "emptyChests")
- end
- local function getOpenAmount(chest)
- local maxAmount = chest.maxAmount
- local incomingAmount = chest.incomingAmount
- local currentAmount = chest.amount
- return maxAmount - incomingAmount - currentAmount
- end
- local function getOrderableAmount(chest)
- local currentAmount = chest.amount
- local outgoingAmount = chest.outgoingAmount
- return currentAmount - outgoingAmount
- end
- -- == last task steps ==
- local function initializeChestList(coords)
- print("Initializing chest list...")
- for row = 0, 4 do
- for col = 0, 9 do
- local offsetX = SYSTEM_STATE.orientation == "x" and col * SYSTEM_STATE.orientationDirection or 0
- local offsetZ = SYSTEM_STATE.orientation == "z" and col * SYSTEM_STATE.orientationDirection or 0
- local chestPos = {
- x = coords.x + offsetX,
- y = coords.y + row,
- z = coords.z + offsetZ
- }
- TASK_DATA.totalChestCount = TASK_DATA.totalChestCount + 1
- table.insert(TASK_DATA.emptyChests, {id = TASK_DATA.totalChestCount, pos = chestPos})
- end
- end
- SYSTEM_STATE.chestInitialized = true
- SYSTEM_STATE.waitingForChestPlacement = false
- saveTableToDisk(TASK_DATA.emptyChests, "emptyChests")
- saveTotalChestCount(TASK_DATA.totalChestCount)
- saveSystemState()
- end
- local function storageManagerTick()
- checkStorageOverflow()
- trimCompletedTasks()
- monitorStorageSpace()
- end
- -- adds (+ or -) amount to chest and item. If Al amounts (including transits) are zero removes
- -- chest from item and if item amount is zero
- local function updateStoredItem(itemDisplayName, amount, chestId)
- local itemIndex
- for index, item in ipairs(TASK_DATA.storedItems) do
- if item.itemDisplayName == itemDisplayName then
- local actualChest
- local chestIndex
- for i, chest in ipairs(item.storedChestsList) do
- print("chest.id = " .. tostring(chest.id))
- print("chestId = " .. tostring(chestId))
- if chest.id == chestId then
- print("Refresh Chest amount")
- -- Aktualisiere gelagerten Amount
- chest.amount = chest.amount + amount
- if amount > 0 then
- -- Items wurden geliefert
- chest.incomingAmount = chest.incomingAmount - amount
- item.itemIncomingAmount = item.itemIncomingAmount - amount
- elseif amount < 0 then
- -- Items wurden entnommen
- local delta = math.abs(amount)
- chest.outgoingAmount = chest.outgoingAmount - delta
- item.itemOutgoingAmount = item.itemOutgoingAmount - delta
- end
- -- Item Count anpassen
- print("Refresh Item Count")
- item.itemCount = item.itemCount + amount
- -- Leere Kiste wieder zurück in die leeren Kisten verschieben
- if chest.amount == 0 and chest.incomingAmount == 0 and chest.outgoingAmount == 0 then
- actualChest = chest
- chestIndex = i
- end
- end
- end
- -- Kiste entfernen
- if chestIndex then
- print("Add chest " .. tostring(actualChest.id) .. " to empty.")
- table.remove(item.storedChestsList, chestIndex)
- addChestToEmpty(actualChest)
- -- Item komplett löschen, wenn leer
- if item.itemCount == 0 and item.itemIncomingAmount == 0 and item.itemOutgoingAmount == 0 then
- itemIndex = index
- end
- end
- end
- end
- -- Item aus Liste löschen
- if itemIndex then
- table.remove(TASK_DATA.storedItems, itemIndex)
- end
- saveTableToDisk(TASK_DATA.storedItems, "storedItems")
- end
- local function checkForCompletedTasks()
- local _, finishedPath = getDiskByLabel(DISK_NAMES.finished)
- if not finishedPath then error("Finished disk not found") end
- local finishedTasks = getTaskList(fs.combine(finishedPath, "task_list.txt"))
- for _, task in ipairs(finishedTasks) do
- if task.taskId then
- local handled = false
- if task.taskType == TASK_TYPES.createChests then
- print("Abgeschlossener Task: " .. tostring(task.taskType) .." --- Initialisiere Kistenliste")
- initializeChestList({x = task.x, y = task.y, z = task.z})
- handled = true
- elseif task.taskType == TASK_TYPES.storeItems then
- print("Abgeschlossener Task: " .. tostring(task.taskType) .. " --- Update stored Items")
- updateStoredItem(task.itemDisplayName, task.itemCount, task.chestId)
- handled = true
- elseif task.taskType == TASK_TYPES.getItems then
- print("Abgeschlossener Task: " .. tostring(task.taskType) .. " --- Update stored Items")
- updateStoredItem(task.itemDisplayName, -task.itemCount, task.chestId)
- handled = true
- elseif task.taskType == TASK_TYPES.checkInventory then
- print("Abgeschlossener Task: " .. tostring(task.taskType))
- handled = true
- elseif task.taskType == TASK_TYPES.initializeChests then
- print("Abgeschlossener Task: " .. tostring(task.taskType) .." --- Initialisiere Kistenliste")
- initializeChestList({x = task.x, y = task.y, z = task.z})
- handled = true
- else
- print("Unbekannter Task-Typ: " .. tostring(task.taskType))
- end
- if handled then
- -- Suche Task in den aktuellen Tasks
- local matchedIndex = nil
- for index, current in ipairs(TASK_DATA.currentTasks) do
- if current.taskId == task.taskId then
- matchedIndex = index
- break
- end
- end
- if matchedIndex then
- local matchedTask = TASK_DATA.currentTasks[matchedIndex]
- table.insert(TASK_DATA.completedTasks, matchedTask)
- table.remove(TASK_DATA.currentTasks, matchedIndex)
- local disk, storagePath = getDiskByLabel(DISK_NAMES.storage)
- if not storagePath then error("Data Storage disk not found") end
- -- Aktuelle Tasks speichern
- local currentPath = fs.combine(storagePath, "currentTasks")
- saveTaskList(currentPath, TASK_DATA.currentTasks)
- -- Abgeschlossene Tasks speichern
- local completedPath = fs.combine(storagePath, "completedTasks")
- addTaskToList(completedPath, matchedTask)
- else
- print("Warnung: Task nicht in den aktuellen Tasks gefunden: " .. tostring(task.id))
- end
- end
- else
- print("Warnung: Task ohne ID gefunden, wird übersprungen")
- print(task.taskType)
- end
- end
- saveTaskList(fs.combine(finishedPath, "task_list.txt"), {})
- end
- local function processNextTaskFromDisk(diskLabelKey)
- local disk, path = getDiskByLabel(DISK_NAMES[diskLabelKey])
- if not path then return end
- local tasks = getTaskList(fs.combine(path, "task_list.txt"))
- if #tasks == 0 then return end
- local task = table.remove(tasks, 1)
- -- Save remaining tasks back
- local fullPath = fs.combine(path, "task_list.txt")
- local file = fs.open(fullPath, "w")
- print("process Next task from " .. diskLabelKey)
- file.write(textutils.serialize(tasks))
- file.close()
- print("processed task from " .. diskLabelKey)
- return task
- end
- local function handleIncomingTask()
- local task = processNextTaskFromDisk("incoming")
- if not task then return end
- if task.taskType == TASK_TYPES.storeItems then
- local displayName = task.itemDisplayName
- local bNewItem = true
- local taskItem = nil
- local taskIndex = nil
- -- lookup item
- for index, item in ipairs(TASK_DATA.storedItems) do
- if displayName == item.itemDisplayName then
- bNewItem = false
- taskItem = item
- taskIndex = index
- end
- end
- -- create new item
- if bNewItem then
- taskItem = {
- itemName = task.itemName,
- itemDisplayName = displayName,
- stackSize = task.itemStackSize,
- itemCount = 0,
- itemIncomingAmount = 0,
- itemOutgoingAmount = 0,
- storedChestsList = {}
- }
- end
- local itemAmount = task.itemCount
- for i, chest in ipairs(taskItem.storedChestsList) do
- local openAmount = getOpenAmount(chest)
- if openAmount >= task.itemCount then
- chest.incomingAmount = chest.incomingAmount + task.itemCount
- taskItem.itemIncomingAmount = taskItem.itemIncomingAmount + task.itemCount
- task.chestCoord = chest.pos
- task.chestId = chest.id
- saveTaskToDisk(task)
- itemAmount = itemAmount - task.itemCount
- break
- elseif openAmount < task.itemCount and openAmount > 0 then
- local task1 = deepCopy(task)
- chest.incomingAmount = chest.incomingAmount + openAmount
- taskItem.itemIncomingAmount = taskItem.itemIncomingAmount + openAmount
- task1.itemCount = openAmount
- task.itemCount = task.itemCount - openAmount
- task1.chestCoord = chest.pos
- task1.chestId = chest.id
- saveTaskToDisk(task1)
- itemAmount = itemAmount - task1.itemCount
- end
- end
- if itemAmount > 0 then
- local chest = getChestFromEmptyForItem(taskItem)
- table.insert(taskItem.storedChestsList, chest)
- chest.incomingAmount = chest.incomingAmount + task.itemCount
- taskItem.itemIncomingAmount = taskItem.itemIncomingAmount + task.itemCount
- task.chestCoord = chest.pos
- task.chestId = chest.id
- saveTaskToDisk(task)
- end
- if taskIndex then
- TASK_DATA.storedItems[taskIndex] = taskItem
- else
- table.insert(TASK_DATA.storedItems, taskItem)
- end
- saveTableToDisk(TASK_DATA.storedItems, "storedItems")
- end
- print("Processed incoming task ID: " .. tostring(taskIdCounter - 1))
- end
- local function handleUserTask()
- local task = processNextTaskFromDisk("user")
- if not task then return end
- if task.taskType == TASK_TYPES.getItems then
- local displayName = task.itemDisplayName
- local taskItem = nil
- local taskIndex = nil
- -- lookup item
- for index, item in ipairs(TASK_DATA.storedItems) do
- if displayName == item.itemDisplayName then
- taskItem = item
- taskIndex = index
- end
- end
- if not taskIndex then return end
- local itemAmount = task.itemCount
- for i, chest in ipairs(taskItem.storedChestsList) do
- local orderableAmount = getOrderableAmount(chest)
- if orderableAmount >= task.itemCount then
- chest.outgoingAmount = chest.outgoingAmount + task.itemCount
- taskItem.itemOutgoingAmount = taskItem.itemOutgoingAmount + task.itemCount
- while itemAmount > 0 do
- local taskAmount = math.min(taskItem.stackSize * 16, task.itemCount)
- if taskAmount >= task.itemCount then
- task.chestCoord = chest.pos
- task.chestId = chest.id
- saveTaskToDisk(task)
- itemAmount = itemAmount - task.itemCount
- elseif taskAmount < task.itemCount then
- local task1 = deepCopy(task)
- task1.chestCoord = chest.pos
- task1.chestId = chest.id
- task1.itemCount = taskAmount
- task.itemCount = task.itemCount - taskAmount
- saveTaskToDisk(task1)
- itemAmount = itemAmount - task1.itemCount
- end
- end
- break
- elseif orderableAmount < task.itemCount and orderableAmount > 0 then
- chest.outgoingAmount = chest.outgoingAmount + orderableAmount
- taskItem.itemOutgoingAmount = taskItem.itemOutgoingAmount + orderableAmount
- local amountToOrder = orderableAmount
- while amountToOrder > 0 do
- local taskAmount = math.min(taskItem.stackSize * 16, amountToOrder)
- local task1 = deepCopy(task)
- task1.itemCount = taskAmount
- task.itemCount = task.itemCount - taskAmount
- amountToOrder = amountToOrder - taskAmount
- task1.chestCoord = chest.pos
- task1.chestId = chest.id
- saveTaskToDisk(task1)
- itemAmount = itemAmount - task1.itemCount
- end
- end
- end
- if itemAmount > 0 then
- print("Error more items requested then available.")
- end
- if taskIndex then
- TASK_DATA.storedItems[taskIndex] = taskItem
- end
- saveTableToDisk(TASK_DATA.storedItems, "storedItems")
- end
- print("Processed user task ID: " .. tostring(taskIdCounter - 1))
- end
- local function handleSettingsTask()
- local task = processNextTaskFromDisk("settings")
- if not task then return end
- if task.taskType == TASK_TYPES.initializeChests then
- local firstChestCoord = {x = task.x, y = task.y, z = task.z}
- local bNewCoord = registerNewChestCoord(firstChestCoord)
- if bNewCoord then
- task.taskId = taskIdCounter
- taskIdCounter = taskIdCounter + 1
- saveTaskIdCounter()
- local finishedDisk, finishedPath = getDiskByLabel(DISK_NAMES.finished)
- if not finishedPath then error("Finished disk not found") end
- local fullFinishedPath = fs.combine(finishedPath, "task_list.txt")
- addTaskToList(fullFinishedPath, task)
- local storageDisk, storagePath = getDiskByLabel(DISK_NAMES.storage)
- if not storagePath then error("Data Storage disk not found") end
- local fullStoragePath = fs.combine(storagePath, "currentTasks")
- addTaskToList(fullStoragePath, task)
- table.insert(TASK_DATA.currentTasks, task)
- end
- elseif task.taskType == TASK_TYPES.createChests then
- local firstChestCoord = {x = task.x, y = task.y, z = task.z}
- local bNewCoord = registerNewChestCoord(firstChestCoord)
- if bNewCoord then
- -- Save to outgoing
- saveTaskToDisk(task)
- end
- elseif task.taskType == TASK_TYPES.checkInventory then
- print("Checking Inventory")
- end
- print("Processed settings task ID: " .. tostring(taskIdCounter - 1))
- end
- local handlerMap = {
- incoming = handleIncomingTask,
- user = handleUserTask,
- settings = handleSettingsTask
- }
- -- === START ===
- local loadedSystemState = loadSystemState()
- for k, v in pairs(loadedSystemState) do
- SYSTEM_STATE[k] = v
- end
- if not isSystemStateComplete() then
- print("[INFO] SYSTEM_STATE unvollständig. Initiale Einstellungen werden geladen...")
- waitForInitialSettings()
- end
- saveSystemState()
- TASK_DATA.currentTasks = loadTableFromDisk("currentTasks")
- TASK_DATA.emptyChests = loadTableFromDisk("emptyChests")
- TASK_DATA.storedItems = loadTableFromDisk("storedItems")
- TASK_DATA.completedTasks = loadTableFromDisk("completedTasks")
- initializeTotalChestCount()
- taskIdCounter = loadTaskIdCounter()
- if #TASK_DATA.emptyChests == 0 and not SYSTEM_STATE.chestInitialized then
- waitForInitialSettings()
- local _, settingsPath = getDiskByLabel(DISK_NAMES.settings)
- if not settingsPath then error("Settings disk not found") end
- local taskList = getTaskList(fs.combine(settingsPath, "task_list.txt"))
- local hasCreateTask = false
- local createTaskIndex = nil
- local createTask = nil
- for index, task in ipairs(taskList) do
- if task.taskType == TASK_TYPES.createChests then
- local firstChestCoord = {x = task.x, y = task.y, z = task.z}
- local bNewCoord = registerNewChestCoord(firstChestCoord)
- if bNewCoord then
- hasCreateTask = true
- createTaskIndex = index
- createTask = task
- end
- break
- end
- end
- if hasCreateTask then
- -- Task abspeichern auf Daten-Disk (als wäre er gerade ausgeführt worden)
- local disk, path = getDiskByLabel(DISK_NAMES.storage)
- if not path then error("Data Storage disk not found") end
- local currentPath = fs.combine(path, "currentTasks")
- addTaskToList(currentPath, createTask)
- saveTaskToDisk(createTask)
- -- Task aus taskList entfernen und aktualisieren
- table.remove(taskList, createTaskIndex)
- saveTaskList(fs.combine(settingsPath, "task_list.txt"), taskList)
- else
- local bNewCoord = registerNewChestCoord(SYSTEM_STATE.startCoords)
- if bNewCoord then
- initializeChestList(SYSTEM_STATE.startCoords)
- else
- print("Warning: System trying to initialize but Coords are already present")
- end
- end
- end
- -- === MAIN LOOP ===
- while true do
- storageManagerTick()
- checkForCompletedTasks()
- if not hasOutgoingTasks() then
- if SYSTEM_STATE.waitingForChestPlacement then
- handlerMap.settings()
- elseif #TASK_DATA.emptyChests == 0 then
- SYSTEM_STATE.waitingForChestPlacement = true
- saveSystemState()
- else
- local sourceKey = TASK_SOURCES[currentTaskSourceIndex]
- handlerMap[sourceKey]()
- currentTaskSourceIndex = currentTaskSourceIndex + 1
- if currentTaskSourceIndex > #TASK_SOURCES then
- currentTaskSourceIndex = 1
- end
- end
- end
- sleep(1)
- end
Advertisement
Add Comment
Please, Sign In to add comment