-- 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()