Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- AE2 Stockpile Manager for CC: Tweaked
- -- Manages automatic crafting requests to maintain item quantities
- -- Compatible with CC: Tweaked and modern AE2 versions
- -- Configuration
- local CONFIG_FILE = "ae2_stockpile.txt"
- local TEST_MODE = false -- Set to true for emulator testing
- local INTERFACE_SIDE = "back"
- local INTERFACE_TYPE = "meBridge" -- Advanced Peripherals ME Bridge
- local CHECK_INTERVAL = 30 -- seconds between checks
- -- Global variables
- local ae2Interface = nil
- local monitor = nil
- local settings = {}
- local running = false
- local currentCraftingJobs = {}
- local lastUpdate = 0
- -- Helper function for formatted printing
- local function printf(format, ...)
- print(string.format(format, ...))
- end
- -- Test mode simulation data
- local testItems = {
- ["minecraft:iron_ingot"] = 450,
- ["minecraft:gold_ingot"] = 200,
- ["minecraft:diamond"] = 50,
- ["minecraft:redstone"] = 1000,
- ["minecraft:coal"] = 800,
- ["minecraft:stick"] = 300
- }
- local testCraftableItems = {
- "minecraft:iron_ingot",
- "minecraft:gold_ingot",
- "minecraft:diamond_sword",
- "minecraft:stick",
- "minecraft:crafting_table"
- }
- local testCraftingQueue = {}
- -- Fake AE2 interface for testing
- local function createFakeInterface()
- return {
- getAvailableItems = function()
- local items = {}
- for name, count in pairs(testItems) do
- table.insert(items, {
- type = "item",
- id = name,
- displayName = name:gsub("minecraft:", ""):gsub("_", " "),
- amount = count
- })
- end
- return items
- end,
- getCraftableItems = function()
- local items = {}
- for _, name in pairs(testCraftableItems) do
- table.insert(items, {
- type = "item",
- id = name,
- displayName = name:gsub("minecraft:", ""):gsub("_", " ")
- })
- end
- return items
- end,
- getCraftingJob = function(item, amount)
- print("FAKE: Requesting craft of " .. amount .. "x " .. item.id)
- table.insert(testCraftingQueue, {item = item.id, amount = amount, time = os.clock()})
- return {id = "fake_job_" .. os.clock()}
- end,
- getCraftingJobs = function()
- return testCraftingQueue
- end
- }
- end
- -- Initialize AE2 connection
- local function initAE2()
- if TEST_MODE then
- print("Starting in TEST MODE")
- ae2Interface = createFakeInterface()
- return true
- else
- -- Try to find Advanced Peripherals ME Bridge
- local bridge = peripheral.find(INTERFACE_TYPE)
- if bridge then
- print("Found Advanced Peripherals ME Bridge")
- ae2Interface = bridge
- -- Test the connection
- local success, items = pcall(function() return ae2Interface.listItems() end)
- if success then
- print("✓ ME Bridge connected successfully - found " .. #items .. " items")
- return true
- else
- print("✗ ME Bridge connection failed: " .. tostring(items))
- return false
- end
- else
- -- Fallback: try to find on specific side
- local interface = peripheral.wrap(INTERFACE_SIDE)
- if interface then
- local ptype = peripheral.getType(INTERFACE_SIDE)
- print("Found peripheral: " .. ptype .. " on " .. INTERFACE_SIDE)
- if ptype == INTERFACE_TYPE then
- ae2Interface = interface
- print("✓ ME Bridge found on " .. INTERFACE_SIDE)
- return true
- else
- print("✗ Wrong peripheral type. Expected '" .. INTERFACE_TYPE .. "', got '" .. ptype .. "'")
- end
- else
- print("✗ No peripheral found")
- end
- -- Show available peripherals for debugging
- local peripherals = peripheral.getNames()
- if #peripherals > 0 then
- print("Available peripherals:")
- for _, name in pairs(peripherals) do
- local ptype = peripheral.getType(name)
- print(" " .. name .. " (" .. ptype .. ")")
- end
- print()
- print("Make sure you have:")
- print("1. Advanced Peripherals mod installed")
- print("2. ME Bridge block placed and connected to your ME system")
- print("3. ME Bridge connected to computer or on the peripheral network")
- end
- return false
- end
- end
- end
- -- Initialize monitor/display
- local function initMonitor()
- local foundMonitor = peripheral.find("monitor")
- if foundMonitor then
- monitor = foundMonitor
- monitor.clear()
- monitor.setTextScale(0.5)
- print("✓ Monitor connected")
- return true
- else
- print("No monitor found (optional)")
- return false
- end
- end
- -- Load settings from file
- local function loadSettings()
- if fs.exists(CONFIG_FILE) then
- local file = fs.open(CONFIG_FILE, "r")
- if file then
- local data = file.readAll()
- file.close()
- settings = textutils.unserialize(data) or {}
- print("Loaded " .. #settings .. " configured items")
- end
- else
- settings = {}
- print("No existing configuration found")
- end
- end
- -- Save settings to file
- local function saveSettings()
- local file = fs.open(CONFIG_FILE, "w")
- if file then
- file.write(textutils.serialize(settings))
- file.close()
- print("Settings saved")
- else
- print("ERROR: Could not save settings")
- end
- end
- -- Clear screen and show header
- local function showHeader()
- term.clear()
- term.setCursorPos(1, 1)
- print("=== AE2 Stockpile Manager ===")
- if TEST_MODE then
- print("*** RUNNING IN TEST MODE ***")
- end
- if monitor then
- print("Monitor: Connected")
- end
- print()
- end
- -- Update monitor display
- local function updateMonitor()
- if not monitor then return end
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.setBackgroundColor(colors.black)
- monitor.setTextColor(colors.white)
- -- Header
- monitor.setTextColor(colors.yellow)
- monitor.write("=== AE2 Stockpile Manager ===")
- monitor.setCursorPos(1, 2)
- monitor.setTextColor(colors.gray)
- monitor.write("Last Update: " .. os.date("%H:%M:%S"))
- local line = 4
- -- System Status
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.lightBlue)
- monitor.write("System Status:")
- line = line + 1
- monitor.setCursorPos(1, line)
- if ae2Interface and not ae2Interface._isBasicInventory then
- monitor.setTextColor(colors.lime)
- monitor.write("Connected - ME Bridge Active")
- elseif TEST_MODE then
- monitor.setTextColor(colors.orange)
- monitor.write("Test Mode Active")
- else
- monitor.setTextColor(colors.red)
- monitor.write("Disconnected")
- end
- line = line + 2
- -- Current Crafting Jobs
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.lightBlue)
- monitor.write("Current Crafting:")
- line = line + 1
- if #currentCraftingJobs > 0 then
- for i, job in ipairs(currentCraftingJobs) do
- if line <= 15 then -- Don't overflow monitor
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.yellow)
- local itemName = job.item:gsub("minecraft:", ""):gsub("_", " ")
- monitor.write("• " .. job.amount .. "x " .. itemName)
- line = line + 1
- end
- end
- else
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.gray)
- monitor.write("No active crafting jobs")
- line = line + 1
- end
- line = line + 1
- -- Monitored Items Status
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.lightBlue)
- monitor.write("Monitored Items:")
- line = line + 1
- if #settings > 0 then
- local quantities = getCurrentQuantities()
- for i, config in ipairs(settings) do
- if line <= 19 then -- Leave room at bottom
- local currentAmount = quantities[config.item] or 0
- local itemName = config.item:gsub("minecraft:", ""):gsub("_", " ")
- monitor.setCursorPos(1, line)
- -- Color code based on stock level
- if currentAmount >= config.target then
- monitor.setTextColor(colors.lime)
- monitor.write("✓ ")
- elseif currentAmount >= config.threshold then
- monitor.setTextColor(colors.yellow)
- monitor.write("○ ")
- else
- monitor.setTextColor(colors.red)
- monitor.write("! ")
- end
- monitor.setTextColor(colors.white)
- monitor.write(string.format("%-12s %d/%d",
- itemName:sub(1, 12), currentAmount, config.target))
- line = line + 1
- end
- end
- else
- monitor.setCursorPos(1, line)
- monitor.setTextColor(colors.gray)
- monitor.write("No items configured")
- end
- -- Footer
- local maxY = select(2, monitor.getSize())
- monitor.setCursorPos(1, maxY)
- monitor.setTextColor(colors.gray)
- monitor.write("Status: " .. (running and "MONITORING" or "IDLE"))
- end
- -- Get current item quantities from AE2
- local function getCurrentQuantities()
- if not ae2Interface then return {} end
- if ae2Interface._isBasicInventory then
- -- Handle basic inventory interface (fallback)
- local success, items = pcall(function()
- return ae2Interface.list()
- end)
- if not success then
- print("ERROR: Failed to get items from inventory: " .. tostring(items))
- return {}
- end
- local quantities = {}
- items = items or {}
- for slot, item in pairs(items) do
- if item and item.name then
- quantities[item.name] = (quantities[item.name] or 0) + item.count
- end
- end
- return quantities
- else
- -- Handle Advanced Peripherals ME Bridge
- local success, items = pcall(function()
- return ae2Interface.listItems()
- end)
- if not success then
- print("ERROR: Failed to get items from ME Bridge: " .. tostring(items))
- return {}
- end
- items = items or {}
- local quantities = {}
- for _, item in pairs(items) do
- local name = item.name or item.id
- local count = item.amount or item.count or 0
- if name then
- quantities[name] = count
- end
- end
- return quantities
- end
- end
- -- Get craftable items from AE2
- local function getCraftableItems()
- if not ae2Interface then return {} end
- if ae2Interface._isBasicInventory then
- print("Craftable items not available in basic inventory mode")
- return {}
- end
- local success, items = pcall(function()
- return ae2Interface.listCraftableItems()
- end)
- if not success then
- print("ERROR: Failed to get craftable items: " .. tostring(items))
- return {}
- end
- local craftable = {}
- items = items or {}
- for _, item in pairs(items) do
- local name = item.name or item.id
- if name then
- craftable[name] = item
- end
- end
- return craftable
- end
- -- Find item by name in AE2 system
- local function findItem(itemName, inCraftable)
- if not ae2Interface then return nil end
- local items = {}
- if inCraftable then
- local craftableItems = getCraftableItems()
- for name, item in pairs(craftableItems) do
- table.insert(items, item)
- end
- else
- local success, availableItems = pcall(function()
- if ae2Interface._isBasicInventory then
- return ae2Interface.list()
- else
- return ae2Interface.listItems()
- end
- end)
- if success and availableItems then
- items = availableItems
- end
- end
- for _, item in pairs(items) do
- local name = item.name or item.id
- local displayName = item.displayName or item.label or name
- if name == itemName or (displayName and displayName:lower():find(itemName:lower())) then
- return item
- end
- end
- return nil
- end
- -- Request crafting for an item
- local function requestCrafting(itemName, amount)
- if not ae2Interface then
- print("ERROR: No AE2 interface connected")
- return false
- end
- if ae2Interface._isBasicInventory then
- print("ERROR: Cannot request crafting - basic inventory mode")
- print("You need Advanced Peripherals ME Bridge for auto-crafting")
- return false
- end
- -- For Advanced Peripherals ME Bridge, we can craft directly by item name
- local success, result = pcall(function()
- return ae2Interface.craftItem({name = itemName, count = amount})
- end)
- if success and result then
- print("Crafting requested: " .. amount .. "x " .. itemName)
- -- Add to current crafting jobs for display
- table.insert(currentCraftingJobs, {
- item = itemName,
- amount = amount,
- time = os.clock()
- })
- updateMonitor()
- return true
- else
- print("ERROR: Failed to request crafting for " .. itemName)
- if not success then
- print("Error details: " .. tostring(result))
- end
- -- Check if item is craftable
- local craftableItem = findItem(itemName, true)
- if not craftableItem then
- print("Item '" .. itemName .. "' is not craftable")
- end
- return false
- end
- end
- -- Monitor items and request crafting as needed
- local function monitorAndCraft()
- local quantities = getCurrentQuantities()
- -- Clean up old crafting jobs (remove jobs older than 5 minutes)
- for i = #currentCraftingJobs, 1, -1 do
- local job = currentCraftingJobs[i]
- if os.clock() - job.time > 300 then -- 5 minutes
- table.remove(currentCraftingJobs, i)
- end
- end
- for _, config in pairs(settings) do
- local currentAmount = quantities[config.item] or 0
- if currentAmount < config.threshold then
- local craftAmount = config.target - currentAmount
- print("LOW STOCK: " .. config.item .. " (" .. currentAmount .. "/" .. config.threshold .. ")")
- print("Requesting craft of " .. craftAmount .. " items...")
- if requestCrafting(config.item, craftAmount) then
- -- Add delay to prevent spam requests
- os.sleep(2)
- end
- end
- end
- updateMonitor()
- end
- -- Show main menu
- local function showMainMenu()
- showHeader()
- print("1. View Current Settings")
- print("2. Add/Edit Item Configuration")
- print("3. Remove Item Configuration")
- print("4. Start Monitoring")
- print("5. Test Crafting Request")
- print("6. View AE2 System Status")
- print("7. Toggle Test Mode (" .. (TEST_MODE and "ON" or "OFF") .. ")")
- print("8. Exit")
- print()
- write("Select option: ")
- end
- -- Show current settings
- local function viewSettings()
- showHeader()
- print("Current Item Configurations:")
- print()
- if #settings == 0 then
- print("No items configured")
- else
- print("Item Name Target Threshold")
- print("----------------------------------------")
- for i, config in pairs(settings) do
- local name = config.item:gsub("minecraft:", "")
- printf("%-28s %-9d %d", name, config.target, config.threshold)
- end
- end
- print()
- print("Press any key to continue...")
- os.pullEvent("key")
- end
- -- Show AE2 system status
- local function viewSystemStatus()
- showHeader()
- print("AE2 System Status:")
- print()
- if not ae2Interface then
- print("Not connected to any interface")
- print("Enable test mode or install Advanced Peripherals")
- print()
- print("Press any key to continue...")
- os.pullEvent("key")
- return
- end
- if ae2Interface._isBasicInventory then
- print("Connection Type: Basic Inventory (Limited)")
- print("⚠ No auto-crafting support available")
- print()
- print("To get full AE2 integration:")
- print("1. Install Advanced Peripherals mod")
- print("2. Craft and place an ME Bridge")
- print("3. Connect ME Bridge to your ME system")
- print()
- else
- print("Connection Type: Advanced Peripherals ME Bridge")
- print("✓ Full AE2 integration with auto-crafting")
- print()
- end
- -- Show available items
- local quantities = getCurrentQuantities()
- local itemCount = 0
- for _ in pairs(quantities) do itemCount = itemCount + 1 end
- print("Available Items: " .. itemCount)
- if itemCount > 0 then
- print("Sample items:")
- local count = 0
- for name, amount in pairs(quantities) do
- if count < 5 then
- local displayName = name:gsub("minecraft:", "")
- printf(" %-20s: %d", displayName, amount)
- count = count + 1
- end
- end
- if itemCount > 5 then
- print(" ... and " .. (itemCount - 5) .. " more items")
- end
- end
- print()
- -- Show craftable items only if we have proper AE2 integration
- if not ae2Interface._isBasicInventory then
- local craftable = getCraftableItems()
- local craftableCount = 0
- for _ in pairs(craftable) do craftableCount = craftableCount + 1 end
- print("Craftable Items: " .. craftableCount)
- if craftableCount > 0 then
- print("Sample craftable items:")
- local count = 0
- for name, item in pairs(craftable) do
- if count < 3 then
- local displayName = name:gsub("minecraft:", "")
- print(" " .. displayName)
- count = count + 1
- end
- end
- if craftableCount > 3 then
- print(" ... and " .. (craftableCount - 3) .. " more")
- end
- end
- else
- print("Craftable Items: Not available (basic inventory mode)")
- end
- print()
- print("Press any key to continue...")
- os.pullEvent("key")
- end
- -- Add or edit item configuration
- local function addEditItem()
- showHeader()
- print("Add/Edit Item Configuration")
- print()
- print("Examples: iron_ingot, gold_ingot, diamond, redstone")
- print("Tip: You can omit 'minecraft:' prefix")
- print()
- write("Item name: ")
- local itemName = read()
- if itemName == "" then
- print("Invalid item name")
- os.sleep(2)
- return
- end
- -- Auto-add minecraft: prefix if not present
- if not itemName:find(":") then
- itemName = "minecraft:" .. itemName
- end
- -- Check if item exists in AE2 system
- local item = findItem(itemName, false)
- if not item and not TEST_MODE then
- print("WARNING: Item not found in AE2 system")
- write("Continue anyway? (y/n): ")
- local confirm = read()
- if confirm:lower() ~= "y" then
- return
- end
- end
- -- Check if item is craftable
- local craftableItem = findItem(itemName, true)
- if not craftableItem and not TEST_MODE then
- print("WARNING: Item is not craftable in AE2 system")
- write("Continue anyway? (y/n): ")
- local confirm = read()
- if confirm:lower() ~= "y" then
- return
- end
- end
- write("Target quantity: ")
- local target = tonumber(read())
- if not target or target <= 0 then
- print("Invalid target quantity")
- os.sleep(2)
- return
- end
- write("Threshold (craft when below): ")
- local threshold = tonumber(read())
- if not threshold or threshold <= 0 or threshold >= target then
- print("Invalid threshold (must be positive and less than target)")
- os.sleep(2)
- return
- end
- -- Find existing config or create new one
- local found = false
- for i, config in pairs(settings) do
- if config.item == itemName then
- config.target = target
- config.threshold = threshold
- found = true
- break
- end
- end
- if not found then
- table.insert(settings, {
- item = itemName,
- target = target,
- threshold = threshold
- })
- end
- saveSettings()
- print("Configuration saved!")
- updateMonitor()
- os.sleep(2)
- end
- -- Remove item configuration
- local function removeItem()
- showHeader()
- print("Remove Item Configuration")
- print()
- if #settings == 0 then
- print("No items configured")
- os.sleep(2)
- return
- end
- print("Configured Items:")
- for i, config in pairs(settings) do
- print(i .. ". " .. config.item)
- end
- print()
- write("Enter number to remove (0 to cancel): ")
- local choice = tonumber(read())
- if choice and choice > 0 and choice <= #settings then
- local removed = table.remove(settings, choice)
- print("Removed: " .. removed.item)
- saveSettings()
- os.sleep(2)
- end
- end
- -- Test crafting request
- local function testCrafting()
- showHeader()
- print("Test Crafting Request")
- print()
- write("Enter item name to test: ")
- local itemName = read()
- write("Enter quantity: ")
- local amount = tonumber(read())
- if itemName ~= "" and amount and amount > 0 then
- print("Testing crafting request...")
- requestCrafting(itemName, amount)
- else
- print("Invalid input")
- end
- print("Press any key to continue...")
- os.pullEvent("key")
- end
- -- Monitoring loop
- local function startMonitoring()
- showHeader()
- print("Starting monitoring loop...")
- print("Press 'q' to stop monitoring")
- if monitor then
- print("Status will be shown on connected monitor")
- end
- print()
- running = true
- updateMonitor()
- -- Start monitoring in parallel
- parallel.waitForAny(
- function()
- while running do
- print("Checking item levels... (" .. os.date() .. ")")
- monitorAndCraft()
- -- Simulate test mode crafting completion
- if TEST_MODE then
- for i = #testCraftingQueue, 1, -1 do
- local craft = testCraftingQueue[i]
- if os.clock() - craft.time > 10 then -- Simulate 10 second crafting
- testItems[craft.item] = (testItems[craft.item] or 0) + craft.amount
- print("FAKE: Completed crafting " .. craft.amount .. "x " .. craft.item)
- table.remove(testCraftingQueue, i)
- -- Remove from currentCraftingJobs when completed
- for j = #currentCraftingJobs, 1, -1 do
- local job = currentCraftingJobs[j]
- if job.item == craft.item and job.amount == craft.amount then
- table.remove(currentCraftingJobs, j)
- break
- end
- end
- updateMonitor()
- end
- end
- end
- for i = 1, CHECK_INTERVAL do
- os.sleep(1)
- if not running then break end
- -- Update monitor every 10 seconds
- if i % 10 == 0 then
- updateMonitor()
- end
- end
- end
- end,
- function()
- while running do
- local event, key = os.pullEvent("key")
- if key == keys.q then
- running = false
- end
- end
- end
- )
- print()
- print("Monitoring stopped")
- updateMonitor()
- os.sleep(2)
- end
- -- Main program loop
- local function main()
- -- Initialize
- loadSettings()
- print("Attempting to connect to AE2...")
- local ae2Connected = initAE2()
- print("Looking for monitor...")
- initMonitor()
- if not ae2Connected then
- print()
- print("No proper AE2 connection found.")
- print("You can still use the program in TEST MODE.")
- print()
- print("Press any key to continue...")
- os.pullEvent("key")
- end
- -- Initial monitor update
- updateMonitor()
- -- Main menu loop
- while true do
- showMainMenu()
- local choice = read()
- if choice == "1" then
- viewSettings()
- elseif choice == "2" then
- addEditItem()
- elseif choice == "3" then
- removeItem()
- elseif choice == "4" then
- startMonitoring()
- elseif choice == "5" then
- testCrafting()
- elseif choice == "6" then
- viewSystemStatus()
- elseif choice == "7" then
- TEST_MODE = not TEST_MODE
- print("Test mode " .. (TEST_MODE and "enabled" or "disabled"))
- initAE2() -- Reinitialize with new mode
- updateMonitor()
- os.sleep(1)
- elseif choice == "8" then
- break
- end
- end
- showHeader()
- print("Thank you for using AE2 Stockpile Manager!")
- if monitor then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.setTextColor(colors.white)
- monitor.write("AE2 Stockpile Manager")
- monitor.setCursorPos(1, 2)
- monitor.write("Program Stopped")
- end
- end()
- elseif choice == "7" then
- TEST_MODE = not TEST_MODE
- print("Test mode " .. (TEST_MODE and "enabled" or "disabled"))
- initAE2() -- Reinitialize with new mode
- updateMonitor()
- os.sleep(1)
- elseif choice == "8" then
- break
- end
- end
- showHeader()
- print("Thank you for using AE2 Stockpile Manager!")
- if monitor then
- monitor.clear()
- monitor.setCursorPos(1, 1)
- monitor.setTextColor(colors.white)
- monitor.write("AE2 Stockpile Manager")
- monitor.setCursorPos(1, 2)
- monitor.write("Program Stopped")
- end
- end()
- elseif choice == "7" then
- TEST_MODE = not TEST_MODE
- print("Test mode " .. (TEST_MODE and "enabled" or "disabled"))
- initAE2() -- Reinitialize with new mode
- os.sleep(1)
- elseif choice == "8" then
- break
- end
- end
- showHeader()
- print("Thank you for using AE2 Stockpile Manager!")
- end
- -- Start the program
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement