// === Controller Memory Monitor === // Handles memory monitoring and reporting for the Main Controller // Communicates with other scripts via link messages // Verbose logging control integer VERBOSE_LOGGING = TRUE; // Global flag for verbose debug logs #define MSG_TOGGLE_VERBOSE_LOGS 9998 // Message to toggle verbose logging // Memory monitoring system #define MEMORY_WARNING_THRESHOLD 0.8 // Warn at 80% usage #define MEMORY_CRITICAL_THRESHOLD 0.9 // Critical at 90% usage integer lastMemoryCheck = 0; // Track last memory check time #define MEMORY_CHECK_INTERVAL 60 // Check every 60 seconds // Message constants for inter-script communication #define MSG_MEMORY_CHECK 6001 #define MSG_MEMORY_STATS 6002 #define MSG_MEMORY_CLEANUP 6003 #define MSG_MEMORY_REPORT 6004 #define MSG_EMERGENCY_CLEANUP 6005 #define MSG_MEMORY_STATS_REQUEST 6006 // Track main controller stats for comprehensive reporting list mainControllerStats = []; checkMemoryUsage(string context) { integer currentTime = llGetUnixTime(); integer usedMemory = llGetUsedMemory(); float memoryPercentage = (float)usedMemory / 65536.0; // 64KB = 65536 bytes if (memoryPercentage > MEMORY_CRITICAL_THRESHOLD) { llOwnerSay("🎆 [Memory Monitor] CRITICAL MEMORY: " + context + " - " + (string)usedMemory + " bytes (" + (string)llRound(memoryPercentage * 100.0) + "% of 64KB limit)"); // Trigger emergency cleanup in main controller llMessageLinked(LINK_SET, MSG_EMERGENCY_CLEANUP, context, NULL_KEY); } else if (memoryPercentage > MEMORY_WARNING_THRESHOLD) { // Only warn once per interval to avoid spam if ((currentTime - lastMemoryCheck) >= MEMORY_CHECK_INTERVAL) { if (VERBOSE_LOGGING) { llOwnerSay("⚠️ [Memory Monitor] High memory in " + context + ": " + (string)usedMemory + " bytes (" + (string)llRound(memoryPercentage * 100.0) + "% of 64KB limit)"); } lastMemoryCheck = currentTime; } } // Send status to main controller string status = context + "|" + (string)usedMemory + "|" + (string)llRound(memoryPercentage * 100.0); llMessageLinked(LINK_SET, MSG_MEMORY_REPORT, status, NULL_KEY); } // Emergency memory cleanup function emergencyMemoryCleanup() { llOwnerSay("🎆 [Memory Monitor] Emergency memory cleanup initiated!"); // Clean up temporary variables and optimize lists mainControllerStats = []; // Force garbage collection by clearing and rebuilding critical lists list tempStats = mainControllerStats; mainControllerStats = []; mainControllerStats = tempStats; llOwnerSay("🎆 [Memory Monitor] Emergency cleanup complete - memory: " + (string)llGetUsedMemory() + " bytes"); } reportMemoryStats() { integer statsUsedMemory = llGetUsedMemory(); float statsMemoryPercentage = (float)statsUsedMemory / 65536.0; llOwnerSay("📊 [Memory Monitor] Memory Monitor Stats:"); llOwnerSay(" Helper Memory Used: " + (string)statsUsedMemory + " bytes (" + (string)llRound(statsMemoryPercentage * 100.0) + "% of 64KB)"); string memoryStatus; if (statsMemoryPercentage > MEMORY_CRITICAL_THRESHOLD) { memoryStatus = "CRITICAL"; } else if (statsMemoryPercentage > MEMORY_WARNING_THRESHOLD) { memoryStatus = "WARNING"; } else { memoryStatus = "NORMAL"; } llOwnerSay(" Memory Status: " + memoryStatus); // Request main controller stats llMessageLinked(LINK_SET, MSG_MEMORY_STATS_REQUEST, "REQUEST_MAIN_STATS", NULL_KEY); } // Process main controller stats response processMainControllerStats(string statsData) { list parts = llParseString2List(statsData, ["|"], []); if (llGetListLength(parts) >= 8) { integer mainMemory = (integer)llList2String(parts, 0); integer players = (integer)llList2String(parts, 1); integer names = (integer)llList2String(parts, 2); integer lives = (integer)llList2String(parts, 3); integer picksData = (integer)llList2String(parts, 4); integer readyPlayers = (integer)llList2String(parts, 5); integer pickQueue = (integer)llList2String(parts, 6); integer globalPicked = (integer)llList2String(parts, 7); integer floaterChannels = 0; if (llGetListLength(parts) >= 9) { floaterChannels = (integer)llList2String(parts, 8); } float mainMemoryPercentage = (float)mainMemory / 65536.0; llOwnerSay("📊 [Memory Monitor] Main Controller Stats:"); llOwnerSay(" Main Memory Used: " + (string)mainMemory + " bytes (" + (string)llRound(mainMemoryPercentage * 100.0) + "% of 64KB)"); llOwnerSay(" Players: " + (string)players); llOwnerSay(" Names: " + (string)names); llOwnerSay(" Lives: " + (string)lives); llOwnerSay(" Picks Data: " + (string)picksData); llOwnerSay(" Ready Players: " + (string)readyPlayers); llOwnerSay(" Pick Queue: " + (string)pickQueue); llOwnerSay(" Global Picked: " + (string)globalPicked); if (floaterChannels > 0) { llOwnerSay(" Floater Channels: " + (string)floaterChannels); } } } default { state_entry() { llOwnerSay("📊 [Memory] Memory Monitor ready!"); // Start periodic memory monitoring llSetTimerEvent(MEMORY_CHECK_INTERVAL); } timer() { // Periodic memory check checkMemoryUsage("periodic_check"); } link_message(integer sender, integer num, string str, key id) { // Handle verbose logging toggle if (num == MSG_TOGGLE_VERBOSE_LOGS) { VERBOSE_LOGGING = !VERBOSE_LOGGING; if (VERBOSE_LOGGING) { llOwnerSay("🔊 [Memory Monitor] Verbose logging ENABLED"); } else { llOwnerSay("🔊 [Memory Monitor] Verbose logging DISABLED"); } return; } if (num == MSG_MEMORY_CHECK) { // Manual memory check request checkMemoryUsage(str); } else if (num == MSG_MEMORY_STATS) { if (str == "REQUEST_MAIN_STATS") { // This is a response with main controller stats processMainControllerStats(str); } else { // Report memory statistics reportMemoryStats(); } } else if (num == MSG_MEMORY_STATS_REQUEST) { // Main controller is providing stats data processMainControllerStats(str); } else if (num == MSG_EMERGENCY_CLEANUP) { // Perform emergency cleanup on this helper script emergencyMemoryCleanup(); } else if (num == -99999 && str == "FULL_RESET") { // Handle full game reset lastMemoryCheck = 0; mainControllerStats = []; llOwnerSay("🔄 [Memory Monitor] Reset complete"); } } }