Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- nanomachine_server.lua
- local component = require("component")
- local event = require("event")
- local serialization = require("serialization")
- local filesystem = require("filesystem")
- -- Config
- local PORT = 2000
- local UPDATE_INTERVAL = 1
- local SAVE_FILE = "/home/nanomachine_data.cfg"
- -- Components
- local modem = component.modem
- local nano = component.nanomachines
- -- State Management
- local state = {
- power = 0,
- maxPower = 0,
- health = 0,
- maxHealth = 20,
- hunger = 0,
- activeInputs = 0,
- totalInputs = 0,
- activeEffects = 0,
- currentProfile = nil,
- autoProtect = false,
- healthThreshold = 10,
- hungerThreshold = 6,
- discoveryActive = false,
- discoveryProgress = 0,
- discoveryTested = 0,
- discoveryFound = 0,
- lastUpdate = 0
- }
- -- Data Storage
- local profiles = {}
- local inputStates = {}
- local discoveredEffects = {}
- local discoveryQueue = {}
- local discoveryIndex = 1
- -- Initialize
- local function initialize()
- print("=== NANOMACHINE SERVER INITIALIZING ===")
- print("")
- modem.open(PORT)
- print("✓ Modem listening on port " .. PORT)
- print("✓ Server Address: " .. modem.address)
- print("")
- -- Check for nanomachines
- if not nano then
- print("⚠ WARNING: No nanomachines component found!")
- print("Make sure nanomachines are installed and connected.")
- return false
- end
- print("✓ Nanomachines detected")
- -- Get total inputs
- state.totalInputs = nano.getInputCount()
- print("✓ Total inputs: " .. state.totalInputs)
- -- Initialize input states
- for i = 1, state.totalInputs do
- inputStates[i] = {
- id = i,
- active = false,
- lastToggled = 0
- }
- end
- -- Load saved data
- loadData()
- print("")
- print("=== SERVER READY ===")
- print("")
- return true
- end
- -- Save/Load Functions
- local function saveData()
- local data = {
- profiles = profiles,
- discoveredEffects = discoveredEffects,
- autoProtect = state.autoProtect,
- healthThreshold = state.healthThreshold,
- hungerThreshold = state.hungerThreshold
- }
- local file = io.open(SAVE_FILE, "w")
- if file then
- file:write(serialization.serialize(data))
- file:close()
- print("[SAVE] Data saved successfully")
- return true
- else
- print("[ERROR] Failed to save data")
- return false
- end
- end
- local function loadData()
- if not filesystem.exists(SAVE_FILE) then
- print("[LOAD] No saved data found, starting fresh")
- -- Create default profiles
- profiles = {
- {
- name = "Combat",
- description = "Speed + Strength + Resistance",
- inputs = {}
- },
- {
- name = "Mining",
- description = "Haste + Night Vision",
- inputs = {}
- },
- {
- name = "Safe",
- description = "Regeneration only",
- inputs = {}
- }
- }
- return
- end
- local file = io.open(SAVE_FILE, "r")
- if file then
- local content = file:read("*a")
- file:close()
- local success, data = pcall(serialization.unserialize, content)
- if success and data then
- profiles = data.profiles or {}
- discoveredEffects = data.discoveredEffects or {}
- state.autoProtect = data.autoProtect or false
- state.healthThreshold = data.healthThreshold or 10
- state.hungerThreshold = data.hungerThreshold or 6
- print("[LOAD] Data loaded successfully")
- print(" Profiles: " .. #profiles)
- print(" Discovered Effects: " .. #discoveredEffects)
- else
- print("[ERROR] Failed to parse saved data")
- end
- end
- end
- -- Nanomachine Control Functions
- local function updateNanoStatus()
- if not nano then return end
- -- Get power
- state.power = nano.getPowerState()
- state.maxPower = nano.getMaxPower()
- -- Count active inputs
- state.activeInputs = 0
- for i = 1, state.totalInputs do
- if nano.getInput(i) then
- inputStates[i].active = true
- state.activeInputs = state.activeInputs + 1
- else
- inputStates[i].active = false
- end
- end
- -- Get active effects
- local effects = nano.getActiveEffects()
- state.activeEffects = effects and #effects or 0
- state.lastUpdate = os.time()
- end
- local function setInput(inputId, active)
- if not nano or inputId < 1 or inputId > state.totalInputs then
- return false
- end
- nano.setInput(inputId, active)
- inputStates[inputId].active = active
- inputStates[inputId].lastToggled = os.time()
- print("[INPUT] Input " .. inputId .. " set to " .. (active and "ON" or "OFF"))
- return true
- end
- local function toggleInput(inputId)
- if not nano or inputId < 1 or inputId > state.totalInputs then
- return false
- end
- local currentState = nano.getInput(inputId)
- return setInput(inputId, not currentState)
- end
- local function disableAllInputs()
- print("[ACTION] Disabling all inputs...")
- for i = 1, state.totalInputs do
- setInput(i, false)
- end
- state.currentProfile = nil
- print("[ACTION] All inputs disabled")
- end
- -- Profile Management
- local function activateProfile(profileName)
- print("[PROFILE] Activating profile: " .. profileName)
- -- Find profile
- local profile = nil
- for _, p in ipairs(profiles) do
- if p.name == profileName then
- profile = p
- break
- end
- end
- if not profile then
- print("[ERROR] Profile not found: " .. profileName)
- return false
- end
- -- Disable all first
- disableAllInputs()
- -- Activate profile inputs
- if profile.inputs and #profile.inputs > 0 then
- for _, inputId in ipairs(profile.inputs) do
- setInput(inputId, true)
- end
- end
- state.currentProfile = profileName
- print("[PROFILE] Profile activated: " .. profileName)
- return true
- end
- local function createProfile(profileName)
- print("[PROFILE] Creating profile: " .. profileName)
- -- Get current active inputs
- local activeInputs = {}
- for i = 1, state.totalInputs do
- if inputStates[i].active then
- table.insert(activeInputs, i)
- end
- end
- -- Create profile
- local profile = {
- name = profileName,
- description = "Custom profile",
- inputs = activeInputs,
- created = os.time()
- }
- table.insert(profiles, profile)
- saveData()
- print("[PROFILE] Profile created with " .. #activeInputs .. " inputs")
- return true
- end
- local function deleteProfile(profileName)
- for i, profile in ipairs(profiles) do
- if profile.name == profileName then
- table.remove(profiles, i)
- saveData()
- print("[PROFILE] Deleted profile: " .. profileName)
- return true
- end
- end
- print("[ERROR] Profile not found: " .. profileName)
- return false
- end
- -- Auto-Protection System
- local function checkAutoProtection()
- if not state.autoProtect or not nano then
- return
- end
- -- Check health (would need player component or other method to get real health)
- -- This is a placeholder - you'd need to implement actual health checking
- -- For now, we'll use a simple low power protection
- if state.power < (state.maxPower * 0.2) then
- print("[AUTO-PROTECT] Low power detected, activating emergency profile")
- -- Could activate a specific safe profile here
- end
- end
- -- Discovery System
- local function initializeDiscovery()
- print("[DISCOVERY] Initializing discovery system...")
- discoveryQueue = {}
- -- Generate all possible single input combinations
- for i = 1, state.totalInputs do
- table.insert(discoveryQueue, {i})
- end
- -- Generate all possible double input combinations
- for i = 1, state.totalInputs do
- for j = i + 1, state.totalInputs do
- table.insert(discoveryQueue, {i, j})
- end
- end
- -- Could add triple combinations but that's a lot
- -- For 32 inputs: 32 + 496 + 4960 = 5488 combinations
- print("[DISCOVERY] Queue size: " .. #discoveryQueue .. " combinations")
- discoveryIndex = 1
- state.discoveryTested = 0
- state.discoveryFound = 0
- end
- local function runDiscoveryStep()
- if not state.discoveryActive or discoveryIndex > #discoveryQueue then
- state.discoveryActive = false
- print("[DISCOVERY] Discovery complete!")
- saveData()
- return
- end
- local combination = discoveryQueue[discoveryIndex]
- -- Disable all inputs
- for i = 1, state.totalInputs do
- setInput(i, false)
- end
- -- Wait a bit for effects to clear
- os.sleep(0.5)
- -- Enable combination
- for _, inputId in ipairs(combination) do
- setInput(inputId, true)
- end
- -- Wait for effects to activate
- os.sleep(1)
- -- Check for effects
- local effects = nano.getActiveEffects()
- if effects and #effects > 0 then
- local effectData = {
- combination = combination,
- effects = effects,
- discovered = os.time()
- }
- table.insert(discoveredEffects, effectData)
- state.discoveryFound = state.discoveryFound + 1
- print("[DISCOVERY] Found effects: " .. table.concat(effects, ", "))
- print(" Inputs: " .. table.concat(combination, ", "))
- end
- state.discoveryTested = state.discoveryTested + 1
- state.discoveryProgress = math.floor((discoveryIndex / #discoveryQueue) * 100)
- discoveryIndex = discoveryIndex + 1
- end
- -- Message Handler
- local function handleMessage(sender, port, distance, command, data)
- print("[REQUEST] " .. command .. " from " .. sender:sub(1, 8))
- if command == "GET_STATUS" then
- local serialized = serialization.serialize(state)
- modem.send(sender, PORT, "GET_STATUS_RESPONSE", serialized)
- elseif command == "GET_PROFILES" then
- local serialized = serialization.serialize(profiles)
- modem.send(sender, PORT, "GET_PROFILES_RESPONSE", serialized)
- elseif command == "GET_INPUTS" then
- local serialized = serialization.serialize(inputStates)
- modem.send(sender, PORT, "GET_INPUTS_RESPONSE", serialized)
- elseif command == "ACTIVATE_PROFILE" then
- activateProfile(data)
- modem.send(sender, PORT, "ACK")
- elseif command == "CREATE_PROFILE" then
- createProfile(data)
- modem.send(sender, PORT, "ACK")
- elseif command == "DELETE_PROFILE" then
- deleteProfile(data)
- modem.send(sender, PORT, "ACK")
- elseif command == "TOGGLE_INPUT" then
- toggleInput(data)
- modem.send(sender, PORT, "ACK")
- elseif command == "DISABLE_ALL" then
- disableAllInputs()
- modem.send(sender, PORT, "ACK")
- elseif command == "EMERGENCY_STOP" then
- disableAllInputs()
- state.autoProtect = false
- state.discoveryActive = false
- print("[EMERGENCY] Emergency stop activated!")
- modem.send(sender, PORT, "ACK")
- elseif command == "TOGGLE_AUTO" then
- state.autoProtect = not state.autoProtect
- saveData()
- print("[AUTO-PROTECT] " .. (state.autoProtect and "ENABLED" or "DISABLED"))
- modem.send(sender, PORT, "ACK")
- elseif command == "SET_HEALTH_THRESHOLD" then
- state.healthThreshold = data
- saveData()
- print("[SETTING] Health threshold set to " .. data)
- modem.send(sender, PORT, "ACK")
- elseif command == "SET_HUNGER_THRESHOLD" then
- state.hungerThreshold = data
- saveData()
- print("[SETTING] Hunger threshold set to " .. data)
- modem.send(sender, PORT, "ACK")
- elseif command == "START_DISCOVERY" then
- initializeDiscovery()
- state.discoveryActive = true
- print("[DISCOVERY] Discovery started")
- modem.send(sender, PORT, "ACK")
- elseif command == "PAUSE_DISCOVERY" then
- state.discoveryActive = false
- print("[DISCOVERY] Discovery paused")
- modem.send(sender, PORT, "ACK")
- elseif command == "RESET_DISCOVERY" then
- initializeDiscovery()
- state.discoveryActive = true
- print("[DISCOVERY] Discovery reset and restarted")
- modem.send(sender, PORT, "ACK")
- elseif command == "PING" then
- modem.send(sender, PORT, "PONG")
- else
- modem.send(sender, PORT, "ERROR")
- end
- end
- -- Status Display
- local function displayStatus()
- print("╔═══════════════════════════════════════════════╗")
- print("║ NANOMACHINE SERVER STATUS ║")
- print("╚═══════════════════════════════════════════════╝")
- print("")
- print("Server: " .. modem.address:sub(1, 8) .. "...")
- print("Port: " .. PORT)
- print("")
- print("Power: " .. state.power .. "/" .. state.maxPower)
- print("Active Inputs: " .. state.activeInputs .. "/" .. state.totalInputs)
- print("Active Effects: " .. state.activeEffects)
- print("")
- print("Current Profile: " .. (state.currentProfile or "None"))
- print("Auto-Protect: " .. (state.autoProtect and "ENABLED" or "DISABLED"))
- print("")
- if state.discoveryActive then
- print("Discovery: ACTIVE")
- print(" Progress: " .. state.discoveryProgress .. "%")
- print(" Tested: " .. state.discoveryTested)
- print(" Found: " .. state.discoveryFound .. " effects")
- else
- print("Discovery: IDLE")
- print(" Total Discovered: " .. #discoveredEffects .. " effects")
- end
- print("")
- print("Profiles: " .. #profiles)
- print("")
- print("Press Ctrl+C to stop server")
- print("───────────────────────────────────────────────")
- end
- -- Main Loop
- local function main()
- if not initialize() then
- print("Failed to initialize server")
- return
- end
- local lastStatusDisplay = 0
- local lastDataUpdate = 0
- local lastAutoCheck = 0
- local lastDiscoveryStep = 0
- while true do
- local currentTime = os.time()
- -- Update nanomachine status
- if currentTime - lastDataUpdate >= UPDATE_INTERVAL then
- updateNanoStatus()
- lastDataUpdate = currentTime
- end
- -- Check auto-protection
- if currentTime - lastAutoCheck >= 2 then
- checkAutoProtection()
- lastAutoCheck = currentTime
- end
- -- Run discovery step
- if state.discoveryActive and currentTime - lastDiscoveryStep >= 2 then
- runDiscoveryStep()
- lastDiscoveryStep = currentTime
- end
- -- Display status
- if currentTime - lastStatusDisplay >= 5 then
- displayStatus()
- lastStatusDisplay = currentTime
- end
- -- Handle messages
- local _, _, sender, port, distance, command, data = event.pull(0.1, "modem_message")
- if command then
- handleMessage(sender, port, distance, command, data)
- end
- end
- end
- -- Cleanup
- local function cleanup()
- print("")
- print("=== SERVER SHUTTING DOWN ===")
- -- Save data
- saveData()
- -- Close modem
- modem.close(PORT)
- print("✓ Server stopped")
- end
- -- Error handling
- local success, err = xpcall(main, debug.traceback)
- if not success then
- print("")
- print("ERROR: " .. tostring(err))
- end
- cleanup()
Advertisement
Add Comment
Please, Sign In to add comment