-- nanomachine_server.lua -- Designed by fxllenfx for fx-Studios -- Nanomachine Profile Management Server v2.0 local component = require("component") local event = require("event") local serialization = require("serialization") local filesystem = require("filesystem") -- Config local PORT = 2000 local SAVE_FILE = "/home/nanomachine_profiles.cfg" -- Components local modem = component.modem -- Data Storage local profiles = {} local discoveredEffects = {} local clientStats = {} -- Initialize local function initialize() print("╔═══════════════════════════════════════════════╗") print("║ fx-Studios NANOMACHINE SERVER v2.0 ║") print("║ Designed by fxllenfx ║") print("╚═══════════════════════════════════════════════╝") print("") modem.open(PORT) print("✓ Modem listening on port " .. PORT) print("✓ Server Address: " .. modem.address) print("") -- Load saved data loadData() print("✓ Server bereit") print("") return true end -- Save/Load Functions local function saveData() local data = { profiles = profiles, discoveredEffects = discoveredEffects, version = "2.0", lastSaved = os.time() } local file = io.open(SAVE_FILE, "w") if file then file:write(serialization.serialize(data)) file:close() print("[SAVE] Daten erfolgreich gespeichert") return true else print("[ERROR] Fehler beim Speichern") return false end end local function loadData() if not filesystem.exists(SAVE_FILE) then print("[LOAD] Keine gespeicherten Daten gefunden") -- Create default profiles profiles = { { name = "Safe", description = "Nur Regeneration", inputs = {}, created = os.time(), creator = "system" }, { name = "Combat", description = "Kampf-Modus mit Staerke und Geschwindigkeit", inputs = {}, created = os.time(), creator = "system" }, { name = "Mining", description = "Bergbau mit Haste und Nachtsicht", inputs = {}, created = os.time(), creator = "system" } } saveData() 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 {} print("[LOAD] Daten geladen") print(" Profile: " .. #profiles) print(" Entdeckte Effekte: " .. #discoveredEffects) else print("[ERROR] Fehler beim Parsen der Daten") end end end -- Profile Management local function addProfile(profile) -- Check if profile name already exists for i, p in ipairs(profiles) do if p.name == profile.name then -- Update existing profile profiles[i] = profile print("[PROFILE] Profil aktualisiert: " .. profile.name) saveData() return true end end -- Add new profile table.insert(profiles, profile) print("[PROFILE] Neues Profil gespeichert: " .. profile.name) saveData() return true end local function deleteProfile(profileName) for i, profile in ipairs(profiles) do if profile.name == profileName then table.remove(profiles, i) print("[PROFILE] Profil geloescht: " .. profileName) saveData() return true end end print("[ERROR] Profil nicht gefunden: " .. profileName) return false end local function getProfile(profileName) for _, profile in ipairs(profiles) do if profile.name == profileName then return profile end end return nil end -- Discovery Management local function addDiscoveredEffect(effectData) -- Check if combination already exists local comboStr = table.concat(effectData.combination, ",") for _, existing in ipairs(discoveredEffects) do local existingStr = table.concat(existing.combination, ",") if existingStr == comboStr then -- Update existing existing.effects = effectData.effects existing.lastSeen = os.time() return true end end -- Add new discovery table.insert(discoveredEffects, effectData) print("[DISCOVERY] Neuer Effekt entdeckt: " .. table.concat(effectData.effects, ", ")) saveData() return true end -- Client Statistics local function updateClientStats(clientAddr, action) if not clientStats[clientAddr] then clientStats[clientAddr] = { address = clientAddr, firstSeen = os.time(), lastSeen = os.time(), requests = 0 } end clientStats[clientAddr].lastSeen = os.time() clientStats[clientAddr].requests = clientStats[clientAddr].requests + 1 clientStats[clientAddr].lastAction = action end -- Message Handler local function handleMessage(sender, port, distance, command, serializedData) updateClientStats(sender, command) print("[REQUEST] " .. command .. " von " .. sender:sub(1, 8) .. "...") if command == "GET_PROFILES" then local serialized = serialization.serialize(profiles) modem.send(sender, PORT, "GET_PROFILES_RESPONSE", serialized) elseif command == "SAVE_PROFILE" then if serializedData then local success, profile = pcall(serialization.unserialize, serializedData) if success and profile then profile.lastModified = os.time() profile.modifiedBy = sender:sub(1, 8) addProfile(profile) modem.send(sender, PORT, "ACK") else modem.send(sender, PORT, "ERROR") end end elseif command == "DELETE_PROFILE" then if serializedData then local success, profileName = pcall(serialization.unserialize, serializedData) if success and profileName then deleteProfile(profileName) modem.send(sender, PORT, "ACK") else modem.send(sender, PORT, "ERROR") end end elseif command == "GET_PROFILE" then if serializedData then local success, profileName = pcall(serialization.unserialize, serializedData) if success and profileName then local profile = getProfile(profileName) if profile then local serialized = serialization.serialize(profile) modem.send(sender, PORT, "GET_PROFILE_RESPONSE", serialized) else modem.send(sender, PORT, "ERROR") end end end elseif command == "SAVE_DISCOVERY" then if serializedData then local success, effectData = pcall(serialization.unserialize, serializedData) if success and effectData then addDiscoveredEffect(effectData) modem.send(sender, PORT, "ACK") else modem.send(sender, PORT, "ERROR") end end elseif command == "GET_DISCOVERIES" then local serialized = serialization.serialize(discoveredEffects) modem.send(sender, PORT, "GET_DISCOVERIES_RESPONSE", serialized) elseif command == "PING" then modem.send(sender, PORT, "PONG") elseif command == "GET_STATS" then local serialized = serialization.serialize(clientStats) modem.send(sender, PORT, "GET_STATS_RESPONSE", serialized) else print("[WARNING] Unbekannter Command: " .. command) modem.send(sender, PORT, "ERROR") end end -- Status Display local function displayStatus() print("╔═══════════════════════════════════════════════╗") print("║ fx-Studios NANOMACHINE SERVER STATUS ║") print("╚═══════════════════════════════════════════════╝") print("") print("Server: " .. modem.address:sub(1, 8) .. "...") print("Port: " .. PORT) print("") print("Gespeicherte Profile: " .. #profiles) print("Entdeckte Effekte: " .. #discoveredEffects) print("Verbundene Clients: " .. (function() local count = 0 for _ in pairs(clientStats) do count = count + 1 end return count end)()) print("") -- Show recent profiles if #profiles > 0 then print("═══ LETZTE PROFILE ═══") for i = math.max(1, #profiles - 4), #profiles do local p = profiles[i] print(string.format(" [%d] %s (%d inputs)", i, p.name, #p.inputs)) end print("") end -- Show active clients local activeClients = 0 local cutoff = os.time() - 60 -- Active in last 60 seconds for addr, stats in pairs(clientStats) do if stats.lastSeen > cutoff then activeClients = activeClients + 1 end end if activeClients > 0 then print("Aktive Clients (letzte 60s): " .. activeClients) print("") end print("Druecke Ctrl+C zum Beenden") print("───────────────────────────────────────────────") end -- Cleanup old client stats local function cleanupClientStats() local cutoff = os.time() - 3600 -- Remove clients inactive for 1 hour local removed = 0 for addr, stats in pairs(clientStats) do if stats.lastSeen < cutoff then clientStats[addr] = nil removed = removed + 1 end end if removed > 0 then print("[CLEANUP] " .. removed .. " inaktive Clients entfernt") end end -- Main Loop local function main() if not initialize() then print("Server-Initialisierung fehlgeschlagen") return end local lastStatusDisplay = 0 local lastCleanup = 0 while true do local currentTime = os.time() -- Display status every 30 seconds if currentTime - lastStatusDisplay >= 30 then displayStatus() lastStatusDisplay = currentTime end -- Cleanup every 10 minutes if currentTime - lastCleanup >= 600 then cleanupClientStats() lastCleanup = currentTime end -- Handle messages local _, _, sender, port, distance, command, data = event.pull(0.5, "modem_message") if command then handleMessage(sender, port, distance, command, data) end end end -- Cleanup local function cleanup() print("") print("╔═══════════════════════════════════════════════╗") print("║ SERVER HERUNTERFAHREN ║") print("╚═══════════════════════════════════════════════╝") print("") -- Save data one last time saveData() -- Close modem modem.close(PORT) print("✓ Server gestoppt") print("") print("fx-Studios - Designed by fxllenfx") end -- Error handling local success, err = xpcall(main, debug.traceback) if not success then print("") print("╔═══════════════════════════════════════════════╗") print("║ FATAL ERROR ║") print("╚═══════════════════════════════════════════════╝") print("") print(tostring(err)) print("") end cleanup()