CCCPaste

djwkjdjwjdjsjsnen


-- nanomachine_client.lua
local component = require("component")
local event = require("event")
local term = require("term")
local gpu = component.gpu
local keyboard = require("keyboard")

-- Config
local SERVER_ADDR = nil
local PORT = 2000
local modem = component.modem

-- UI State
local currentScreen = "main"
local selectedProfile = nil
local scrollOffset = 0
local statusData = nil
local profiles = {}
local manualInputs = {}

-- Colors
local COLOR_BG = 0x000000
local COLOR_FG = 0xFFFFFF
local COLOR_HEADER = 0x00FFFF
local COLOR_SUCCESS = 0x00FF00
local COLOR_WARNING = 0xFFFF00
local COLOR_ERROR = 0xFF0000
local COLOR_ACTIVE = 0x00FF00
local COLOR_INACTIVE = 0x888888
local COLOR_BUTTON = 0x0066CC
local COLOR_SELECTED = 0xFF6600

-- Setup
modem.open(PORT)
gpu.setResolution(80, 25)

-- Server Setup
local function setupServer()
  term.clear()
  gpu.setForeground(COLOR_HEADER)
  print("═══ NANOMACHINE CLIENT SETUP ═══")
  print("")
  gpu.setForeground(COLOR_FG)
  print("Enter Server Address:")
  print("(or 'broadcast' for auto-discovery)")
  print("")
  SERVER_ADDR = io.read()
  
  if SERVER_ADDR == "broadcast" then
    SERVER_ADDR = nil
    print("")
    gpu.setForeground(COLOR_SUCCESS)
    print("✓ Using broadcast mode")
  else
    print("")
    gpu.setForeground(COLOR_SUCCESS)
    print("✓ Server set to: " .. SERVER_ADDR:sub(1, 8) .. "...")
  end
  
  gpu.setForeground(COLOR_FG)
  print("")
  print("Press any key to continue...")
  event.pull("key_down")
end

-- Communication
local function sendCommand(command, ...)
  if SERVER_ADDR then
    modem.send(SERVER_ADDR, PORT, command, ...)
  else
    modem.broadcast(PORT, command, ...)
  end
end

local function requestData(command)
  sendCommand(command)
  local timeout = os.time() + 2
  
  while os.time() < timeout do
    local _, _, sender, _, _, cmd, data = event.pull(0.1, "modem_message")
    if cmd and cmd == command .. "_RESPONSE" then
      if not SERVER_ADDR then
        SERVER_ADDR = sender
      end
      return data
    end
  end
  
  return nil
end

-- Draw Functions
local function drawHeader(title)
  gpu.setBackground(COLOR_BG)
  gpu.setForeground(COLOR_HEADER)
  gpu.fill(1, 1, 80, 3, " ")
  
  local titleText = "╔═══ " .. title .. " ═══╗"
  gpu.set(math.floor((80 - #titleText) / 2), 2, titleText)
end

local function drawButton(x, y, text, width, active)
  local bg = active and COLOR_SELECTED or COLOR_BUTTON
  gpu.setBackground(bg)
  gpu.setForeground(COLOR_FG)
  
  local padding = math.floor((width - #text) / 2)
  local buttonText = string.rep(" ", padding) .. text .. string.rep(" ", width - padding - #text)
  
  gpu.set(x, y, buttonText)
  gpu.setBackground(COLOR_BG)
end

local function drawStatusBar(y, label, value, maxValue, color)
  gpu.setForeground(COLOR_FG)
  gpu.set(2, y, label .. ":")
  
  local barWidth = 50
  local barX = 20
  local percentage = maxValue > 0 and (value / maxValue) or 0
  local filled = math.floor(barWidth * percentage)
  
  gpu.setForeground(color)
  gpu.set(barX, y, "[" .. string.rep("█", filled) .. string.rep("░", barWidth - filled) .. "]")
  
  gpu.setForeground(COLOR_FG)
  gpu.set(barX + barWidth + 3, y, string.format("%d/%d (%.1f%%)", value, maxValue, percentage * 100))
end

-- Main Dashboard Screen
local function drawMainScreen()
  term.clear()
  drawHeader("NANOMACHINE CONTROL CENTER")
  
  gpu.setForeground(COLOR_FG)
  
  if not statusData then
    gpu.setForeground(COLOR_ERROR)
    gpu.set(2, 5, "⚠ No connection to server")
    gpu.setForeground(COLOR_WARNING)
    gpu.set(2, 7, "Attempting to reconnect...")
  else
    -- Status Section
    gpu.setForeground(COLOR_HEADER)
    gpu.set(2, 5, "═══ SYSTEM STATUS ═══")
    gpu.setForeground(COLOR_FG)
    
    drawStatusBar(7, "Power", statusData.power or 0, statusData.maxPower or 100, COLOR_SUCCESS)
    drawStatusBar(8, "Health", statusData.health or 0, statusData.maxHealth or 20, COLOR_ERROR)
    drawStatusBar(9, "Hunger", statusData.hunger or 0, 20, COLOR_WARNING)
    
    gpu.set(2, 11, "Active Inputs: " .. (statusData.activeInputs or 0) .. "/" .. (statusData.totalInputs or 0))
    gpu.set(2, 12, "Active Effects: " .. (statusData.activeEffects or 0))
    
    -- Current Profile
    gpu.setForeground(COLOR_HEADER)
    gpu.set(2, 14, "═══ CURRENT PROFILE ═══")
    gpu.setForeground(COLOR_FG)
    
    if statusData.currentProfile then
      gpu.setForeground(COLOR_SUCCESS)
      gpu.set(2, 15, "● " .. statusData.currentProfile)
    else
      gpu.setForeground(COLOR_INACTIVE)
      gpu.set(2, 15, "○ No profile active")
    end
    
    -- Auto-Protection Status
    gpu.setForeground(COLOR_HEADER)
    gpu.set(45, 14, "═══ AUTO-PROTECT ═══")
    gpu.setForeground(COLOR_FG)
    
    local autoProtect = statusData.autoProtect or false
    if autoProtect then
      gpu.setForeground(COLOR_SUCCESS)
      gpu.set(45, 15, "● ENABLED")
    else
      gpu.setForeground(COLOR_INACTIVE)
      gpu.set(45, 15, "○ DISABLED")
    end
  end
  
  -- Navigation Buttons
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 18, "═══ QUICK ACTIONS ═══")
  
  drawButton(2, 20, "1: Profiles", 15, false)
  drawButton(19, 20, "2: Manual", 15, false)
  drawButton(36, 20, "3: Discovery", 15, false)
  drawButton(53, 20, "4: Settings", 15, false)
  
  drawButton(2, 22, "E: Emergency Stop", 20, false)
  drawButton(24, 22, "A: Toggle Auto", 20, false)
  drawButton(46, 22, "R: Refresh", 20, false)
  
  -- Footer
  gpu.setForeground(COLOR_INACTIVE)
  gpu.set(2, 24, "Q: Quit")
  gpu.set(70, 24, "v1.0")
end

-- Profile Selection Screen
local function drawProfileScreen()
  term.clear()
  drawHeader("PROFILE MANAGER")
  
  gpu.setForeground(COLOR_FG)
  
  if not profiles or #profiles == 0 then
    gpu.setForeground(COLOR_WARNING)
    gpu.set(2, 5, "No profiles available")
    gpu.setForeground(COLOR_FG)
    gpu.set(2, 7, "Press B to go back")
    return
  end
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 5, "═══ AVAILABLE PROFILES ═══")
  gpu.setForeground(COLOR_FG)
  
  for i, profile in ipairs(profiles) do
    if i > scrollOffset and i <= scrollOffset + 10 then
      local y = 7 + (i - scrollOffset - 1)
      local isActive = statusData and statusData.currentProfile == profile.name
      
      if isActive then
        gpu.setForeground(COLOR_SUCCESS)
        gpu.set(2, y, "▶ ")
      else
        gpu.setForeground(COLOR_INACTIVE)
        gpu.set(2, y, "  ")
      end
      
      gpu.setForeground(COLOR_FG)
      gpu.set(5, y, string.format("[%d] %s", i, profile.name))
      
      if profile.description then
        gpu.setForeground(COLOR_INACTIVE)
        gpu.set(30, y, "- " .. profile.description)
      end
    end
  end
  
  -- Instructions
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 20, "═══ CONTROLS ═══")
  gpu.setForeground(COLOR_FG)
  gpu.set(2, 21, "Number: Activate profile")
  gpu.set(2, 22, "C: Create new profile")
  gpu.set(2, 23, "B: Back to main menu")
end

-- Manual Control Screen
local function drawManualScreen()
  term.clear()
  drawHeader("MANUAL INPUT CONTROL")
  
  gpu.setForeground(COLOR_FG)
  
  if not manualInputs or #manualInputs == 0 then
    gpu.setForeground(COLOR_WARNING)
    gpu.set(2, 5, "No input data available")
    gpu.setForeground(COLOR_FG)
    gpu.set(2, 7, "Press B to go back")
    return
  end
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 5, "═══ INPUT CHANNELS ═══")
  gpu.setForeground(COLOR_FG)
  
  local cols = 4
  local row = 0
  
  for i = 1, math.min(#manualInputs, 32) do
    local input = manualInputs[i]
    local col = (i - 1) % cols
    local x = 2 + (col * 19)
    local y = 7 + row
    
    if col == 0 and i > 1 then
      row = row + 1
    end
    
    local status = input.active and "ON " or "OFF"
    local color = input.active and COLOR_SUCCESS or COLOR_INACTIVE
    
    gpu.setForeground(color)
    gpu.set(x, y, string.format("[%2d] %s", i, status))
  end
  
  -- Instructions
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 20, "═══ CONTROLS ═══")
  gpu.setForeground(COLOR_FG)
  gpu.set(2, 21, "Number: Toggle input")
  gpu.set(2, 22, "X: Disable all")
  gpu.set(2, 23, "B: Back to main menu")
end

-- Discovery Screen
local function drawDiscoveryScreen()
  term.clear()
  drawHeader("EFFECT DISCOVERY")
  
  gpu.setForeground(COLOR_FG)
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 5, "═══ DISCOVERY MODE ═══")
  gpu.setForeground(COLOR_FG)
  
  if statusData and statusData.discoveryActive then
    gpu.setForeground(COLOR_SUCCESS)
    gpu.set(2, 7, "● Discovery in progress...")
    gpu.setForeground(COLOR_FG)
    gpu.set(2, 9, "Progress: " .. (statusData.discoveryProgress or 0) .. "%")
    gpu.set(2, 10, "Tested: " .. (statusData.discoveryTested or 0) .. " combinations")
    gpu.set(2, 11, "Found: " .. (statusData.discoveryFound or 0) .. " effects")
  else
    gpu.setForeground(COLOR_INACTIVE)
    gpu.set(2, 7, "○ Discovery not running")
  end
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 14, "═══ CONTROLS ═══")
  gpu.setForeground(COLOR_FG)
  gpu.set(2, 15, "S: Start discovery")
  gpu.set(2, 16, "P: Pause discovery")
  gpu.set(2, 17, "R: Reset and restart")
  gpu.set(2, 18, "B: Back to main menu")
  
  gpu.setForeground(COLOR_WARNING)
  gpu.set(2, 20, "⚠ Warning: Discovery will systematically test all")
  gpu.set(2, 21, "  input combinations. This may take several minutes.")
end

-- Settings Screen
local function drawSettingsScreen()
  term.clear()
  drawHeader("SETTINGS")
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 5, "═══ AUTO-PROTECTION ═══")
  gpu.setForeground(COLOR_FG)
  
  local autoProtect = statusData and statusData.autoProtect or false
  gpu.set(2, 7, "Status: " .. (autoProtect and "ENABLED" or "DISABLED"))
  gpu.set(2, 8, "Health Threshold: " .. (statusData and statusData.healthThreshold or 10))
  gpu.set(2, 9, "Hunger Threshold: " .. (statusData and statusData.hungerThreshold or 6))
  
  gpu.setForeground(COLOR_HEADER)
  gpu.set(2, 12, "═══ CONTROLS ═══")
  gpu.setForeground(COLOR_FG)
  gpu.set(2, 13, "A: Toggle auto-protection")
  gpu.set(2, 14, "H: Set health threshold")
  gpu.set(2, 15, "F: Set hunger threshold")
  gpu.set(2, 16, "B: Back to main menu")
end

-- Input Handling
local function handleMainInput(char)
  if char == string.byte("1") then
    currentScreen = "profiles"
    profiles = requestData("GET_PROFILES") or {}
  elseif char == string.byte("2") then
    currentScreen = "manual"
    manualInputs = requestData("GET_INPUTS") or {}
  elseif char == string.byte("3") then
    currentScreen = "discovery"
  elseif char == string.byte("4") then
    currentScreen = "settings"
  elseif char == string.byte("e") or char == string.byte("E") then
    sendCommand("EMERGENCY_STOP")
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("a") or char == string.byte("A") then
    sendCommand("TOGGLE_AUTO")
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("r") or char == string.byte("R") then
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("q") or char == string.byte("Q") then
    return false
  end
  return true
end

local function handleProfileInput(char)
  if char == string.byte("b") or char == string.byte("B") then
    currentScreen = "main"
  elseif char >= string.byte("0") and char <= string.byte("9") then
    local num = char - string.byte("0")
    if profiles[num] then
      sendCommand("ACTIVATE_PROFILE", profiles[num].name)
      statusData = requestData("GET_STATUS")
    end
  elseif char == string.byte("c") or char == string.byte("C") then
    term.clear()
    print("Enter profile name:")
    local name = io.read()
    if name and name ~= "" then
      sendCommand("CREATE_PROFILE", name)
      profiles = requestData("GET_PROFILES") or {}
    end
  end
end

local function handleManualInput(char)
  if char == string.byte("b") or char == string.byte("B") then
    currentScreen = "main"
  elseif char == string.byte("x") or char == string.byte("X") then
    sendCommand("DISABLE_ALL")
    manualInputs = requestData("GET_INPUTS") or {}
  elseif char >= string.byte("0") and char <= string.byte("9") then
    local num = char - string.byte("0")
    sendCommand("TOGGLE_INPUT", num)
    manualInputs = requestData("GET_INPUTS") or {}
  end
end

local function handleDiscoveryInput(char)
  if char == string.byte("b") or char == string.byte("B") then
    currentScreen = "main"
  elseif char == string.byte("s") or char == string.byte("S") then
    sendCommand("START_DISCOVERY")
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("p") or char == string.byte("P") then
    sendCommand("PAUSE_DISCOVERY")
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("r") or char == string.byte("R") then
    sendCommand("RESET_DISCOVERY")
    statusData = requestData("GET_STATUS")
  end
end

local function handleSettingsInput(char)
  if char == string.byte("b") or char == string.byte("B") then
    currentScreen = "main"
  elseif char == string.byte("a") or char == string.byte("A") then
    sendCommand("TOGGLE_AUTO")
    statusData = requestData("GET_STATUS")
  elseif char == string.byte("h") or char == string.byte("H") then
    term.clear()
    print("Enter health threshold (1-20):")
    local threshold = tonumber(io.read())
    if threshold then
      sendCommand("SET_HEALTH_THRESHOLD", threshold)
      statusData = requestData("GET_STATUS")
    end
  elseif char == string.byte("f") or char == string.byte("F") then
    term.clear()
    print("Enter hunger threshold (1-20):")
    local threshold = tonumber(io.read())
    if threshold then
      sendCommand("SET_HUNGER_THRESHOLD", threshold)
      statusData = requestData("GET_STATUS")
    end
  end
end

-- Main Loop
local function main()
  setupServer()
  
  local running = true
  local lastUpdate = 0
  
  while running do
    local currentTime = os.time()
    
    -- Auto-refresh every 2 seconds
    if currentTime - lastUpdate >= 2 then
      statusData = requestData("GET_STATUS")
      lastUpdate = currentTime
    end
    
    -- Draw current screen
    if currentScreen == "main" then
      drawMainScreen()
    elseif currentScreen == "profiles" then
      drawProfileScreen()
    elseif currentScreen == "manual" then
      drawManualScreen()
    elseif currentScreen == "discovery" then
      drawDiscoveryScreen()
    elseif currentScreen == "settings" then
      drawSettingsScreen()
    end
    
    -- Handle input
    local _, _, char, code = event.pull(0.5, "key_down")
    
    if char then
      if currentScreen == "main" then
        running = handleMainInput(char)
      elseif currentScreen == "profiles" then
        handleProfileInput(char)
      elseif currentScreen == "manual" then
        handleManualInput(char)
      elseif currentScreen == "discovery" then
        handleDiscoveryInput(char)
      elseif currentScreen == "settings" then
        handleSettingsInput(char)
      end
    end
  end
  
  term.clear()
  print("Nanomachine Client terminated.")
end

-- Error handling
local success, err = xpcall(main, debug.traceback)

if not success then
  term.clear()
  gpu.setForeground(COLOR_ERROR)
  print("ERROR: " .. tostring(err))
  gpu.setForeground(COLOR_FG)
end