From ccf472585ac6be1d920fae0c19184fce5eeb150b Mon Sep 17 00:00:00 2001 From: RebeccaNod1 Date: Thu, 9 Apr 2026 01:43:28 -0600 Subject: [PATCH] feat: add Enhanced Link Scanner and Experience Admin HUD tools, remove memory report template --- MEMORY_REPORT_TEMPLATE.lsl | 31 ------- tools/Enhanced_LinkScanner.lsl | 149 +++++++++++++++++++++++++++++++++ tools/Experience_Admin_HUD.lsl | 138 ++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 31 deletions(-) delete mode 100644 MEMORY_REPORT_TEMPLATE.lsl create mode 100644 tools/Enhanced_LinkScanner.lsl create mode 100644 tools/Experience_Admin_HUD.lsl diff --git a/MEMORY_REPORT_TEMPLATE.lsl b/MEMORY_REPORT_TEMPLATE.lsl deleted file mode 100644 index b17c38b..0000000 --- a/MEMORY_REPORT_TEMPLATE.lsl +++ /dev/null @@ -1,31 +0,0 @@ -// === MEMORY REPORTING TEMPLATE === -// Add this to the state_entry() of every script to track memory usage - -// Add this function to every script: -reportMemoryUsage(string scriptName) { - integer used = llGetUsedMemory(); - integer free = llGetFreeMemory(); - integer total = used + free; - float percentUsed = ((float)used / (float)total) * 100.0; - - llOwnerSay("🧠 [" + scriptName + "] Memory: " + - (string)used + " used, " + - (string)free + " free (" + - llGetSubString((string)percentUsed, 0, 4) + "% used)"); -} - -// Add this to state_entry() in every script: -state_entry() { - // Replace "SCRIPT_NAME" with the actual script name - reportMemoryUsage("SCRIPT_NAME"); - - // ... rest of existing state_entry() code ... -} - -// Add this to on_rez() in every script: -on_rez(integer start_param) { - // Replace "SCRIPT_NAME" with the actual script name - reportMemoryUsage("SCRIPT_NAME"); - - // ... rest of existing on_rez() code ... -} \ No newline at end of file diff --git a/tools/Enhanced_LinkScanner.lsl b/tools/Enhanced_LinkScanner.lsl new file mode 100644 index 0000000..2b5a2fb --- /dev/null +++ b/tools/Enhanced_LinkScanner.lsl @@ -0,0 +1,149 @@ +#include "peril/Peril_Constants.lsl" + +// ==================================================================== +// Enhanced Link Scanner for Peril Dice Linkset +// ==================================================================== +// Extended version of Temp_LinkScanner.lsl that identifies: +// 1. Current linkset structure +// 2. Which scripts belong on which links +// 3. Missing scripts or misplaced scripts +// +// USAGE: Place this script on any prim in the linkset, touch to scan +// ==================================================================== + +// Expected script locations based on WARP.md architecture +list LINK1_SCRIPTS = [ + "Main_Controller_Linkset.lsl", + "Game_Manager.lsl", + "Controller_Memory.lsl", + "Controller_MessageHandler.lsl", + "Player_RegistrationManager.lsl", + "Player_DialogHandler.lsl", + "NumberPicker_DialogHandler.lsl", + "Floater_Manager.lsl", + "Roll_ConfettiModule.lsl", + "Bot_Manager.lsl", + "Game_Calculator.lsl", + "Verbose_Logger.lsl", + "System_Debugger.lsl" +]; + +// Link-specific scripts (based on architecture documentation) +list LINKSET_SPECIFIC_SCRIPTS = [ + "Game_Scoreboard_Manager_Linkset.lsl", // Link 12 + "Leaderboard_Communication_Linkset.lsl", // Link 35 + "XyzzyText_Dice_Bridge_Linkset.lsl" // Link 83 +]; + +#define XYZZY_SCRIPT "xyzzy_Master_script.lsl" // Links 35-82 (48 prims) + +// Scan results +integer totalPrims = 0; +list linkNames = []; +list linkPositions = []; + +// Function to perform the full linkset scan +performFullScan() { + totalPrims = llGetNumberOfPrims(); + linkNames = []; + linkPositions = []; + + llOwnerSay("=== 🔍 PERIL DICE LINKSET ANALYSIS ==="); + llOwnerSay("📊 Total Prims: " + (string)totalPrims); + llOwnerSay("🎯 Expected Architecture: 84-prim single linkset"); + llOwnerSay(""); + + // Scan all links + integer i; + for (i = 1; i <= totalPrims; i++) { + string primName = llGetLinkName(i); + vector pos = llList2Vector(llGetLinkPrimitiveParams(i, [PRIM_POSITION]), 0); + + linkNames += [primName]; + linkPositions += [pos]; + + // Basic link info + llOwnerSay("Link " + (string)i + ": " + primName); + + // Add delays to prevent spam + if (i % 15 == 0) { + llSleep(DELAY_SCAN_LINKSET); + } + } + + llOwnerSay(""); + llOwnerSay("=== 📋 SCRIPT PLACEMENT ANALYSIS ==="); + + // Analyze Link 1 (Root Prim) + llOwnerSay("🔧 LINK 1 (ROOT PRIM) ANALYSIS:"); + llOwnerSay(" Name: " + llList2String(linkNames, 0)); + llOwnerSay(" Expected Scripts: " + (string)llGetListLength(LINK1_SCRIPTS) + " scripts"); + + integer j; + for (j = 0; j < llGetListLength(LINK1_SCRIPTS); j++) { + string scriptName = llList2String(LINK1_SCRIPTS, j); + llOwnerSay(" • " + scriptName); + } + llOwnerSay(""); + + // Analyze scoreboard + llOwnerSay("📊 SCOREBOARD SECTION (Links 2-24):"); + if (totalPrims >= 12) { + llOwnerSay(" Link 12: " + llList2String(linkNames, 11) + " (Scoreboard Manager)"); + llOwnerSay(" Expected Script: Game_Scoreboard_Manager_Linkset.lsl"); + } + llOwnerSay(" Links 2-11: Overlay prims (elimination markers)"); + llOwnerSay(" Links 13-24: Player display prims (profiles & hearts)"); + llOwnerSay(""); + + // Analyze leaderboard + llOwnerSay("🏆 LEADERBOARD SECTION (Links 35-82):"); + if (totalPrims >= 35) { + llOwnerSay(" Link 35: " + llList2String(linkNames, 34) + " (Leaderboard Bridge)"); + llOwnerSay(" Expected Script: Leaderboard_Communication_Linkset.lsl"); + } + llOwnerSay(" Links 35-82: XyzzyText display prims (48 total)"); + llOwnerSay(" Each prim needs: xyzzy_Master_script.lsl"); + llOwnerSay(" Organization: 4 banks × 12 prims each"); + llOwnerSay(""); + + // Analyze dice display + llOwnerSay("🎲 DICE DISPLAY SECTION (Links 83-84):"); + if (totalPrims >= 83) { + llOwnerSay(" Link 83: " + llList2String(linkNames, 82) + " (Dice Bridge)"); + llOwnerSay(" Expected Script: XyzzyText_Dice_Bridge_Linkset.lsl"); + } + if (totalPrims >= 84) { + llOwnerSay(" Link 84: " + llList2String(linkNames, 83) + " (Dice Display)"); + llOwnerSay(" No script needed"); + } + llOwnerSay(""); + + llOwnerSay("🔄 ESSENTIAL FILES FOR GAMEPLAY:"); + llOwnerSay(" 📂 Link 1 Scripts (" + (string)llGetListLength(LINK1_SCRIPTS) + " files)"); + llOwnerSay(" 📂 Link-Specific Scripts (3 files)"); + llOwnerSay(" 📂 XyzzyText Script (1 file × 48 prims)"); + llOwnerSay(" 📂 Documentation (4 files)"); + llOwnerSay(""); + + llOwnerSay("⚠️ EXCLUDED FROM UPDATES:"); + llOwnerSay(" 🚫 Development files: lsl_validator.py, debug_mcp.py"); + llOwnerSay(" 🚫 Test files: test_*.py, MCP_README.md"); + llOwnerSay(" 🚫 Templates: MEMORY_REPORT_TEMPLATE.lsl"); + llOwnerSay(" 🚫 Utilities: Temp_LinkScanner.lsl, Enhanced_LinkScanner.lsl"); + + llOwnerSay(""); + llOwnerSay("✅ Linkset analysis complete!"); +} + +default { + state_entry() { + llOwnerSay("🔍 Enhanced Link Scanner ready for Peril Dice linkset"); + llOwnerSay("👆 Touch to perform full linkset analysis"); + } + + touch_start(integer total_number) { + if (llDetectedKey(0) != llGetOwner()) return; + performFullScan(); + } +} diff --git a/tools/Experience_Admin_HUD.lsl b/tools/Experience_Admin_HUD.lsl new file mode 100644 index 0000000..1ff3980 --- /dev/null +++ b/tools/Experience_Admin_HUD.lsl @@ -0,0 +1,138 @@ +// ============================================================================ +// Experience Admin HUD +// ============================================================================ +// Instructions: +// 1. Create a new box, put this script inside. +// 2. DO NOT FORGET to check "Use Experience" and select Final Girlz I.N.C! +// 3. Attach it to your HUD or click it if it's rezzed. +// +// Commands (type in local chat): +// /99 keys - Lists all keys currently in the entire database +// /99 get [Key] - Reads and displays the data inside a specific key +// /99 del [Key] - Deletes a specific key from the database +// ============================================================================ + +key requestKeys; +key requestRead; +key requestDelete; +key requestWrite; +key lastUser; +string pendingSetKey; +string pendingSetValue; + +default { + state_entry() { + lastUser = llGetOwner(); + llRegionSayTo(lastUser, 0, "🔧 Experience Admin Terminal Ready."); + llRegionSayTo(lastUser, 0, "💬 Type commands in local chat:"); + llRegionSayTo(lastUser, 0, " /99 keys"); + llRegionSayTo(lastUser, 0, " /99 get key_name"); + llRegionSayTo(lastUser, 0, " /99 set key_name=Hello World"); + llRegionSayTo(lastUser, 0, " /99 del key_name"); + llListen(99, "", NULL_KEY, ""); + } + + listen(integer channel, string name, key id, string msg) { + // SECURITY CHECK: Strictly whitelist authorized Admin usernames! + string uname = llStringTrim(llToLower(llGetUsername(id)), STRING_TRIM); + if (id != llGetOwner() && uname != "djmusica28" && uname != "finalgirlzbot") { + llRegionSayTo(id, 0, "❌ Access Denied: You are not on the authorized Administrator whitelist for this database."); + return; + } + lastUser = id; + msg = llStringTrim(msg, STRING_TRIM); + + if (msg == "keys") { + llRegionSayTo(lastUser, 0, "🔍 Requesting list of database keys (up to 100)..."); + requestKeys = llKeysKeyValue(0, 100); + } + else if (llGetSubString(msg, 0, 3) == "get ") { + string targetKey = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM); + llRegionSayTo(lastUser, 0, "🔍 Reading key: " + targetKey + "..."); + requestRead = llReadKeyValue(targetKey); + } + else if (llGetSubString(msg, 0, 3) == "set ") { + string payload = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM); + integer equalSign = llSubStringIndex(payload, "="); + if (equalSign != -1) { + pendingSetKey = llStringTrim(llGetSubString(payload, 0, equalSign - 1), STRING_TRIM); + pendingSetValue = llStringTrim(llGetSubString(payload, equalSign + 1, -1), STRING_TRIM); + llRegionSayTo(lastUser, 0, "💾 Writing key: " + pendingSetKey + "..."); + requestWrite = llUpdateKeyValue(pendingSetKey, pendingSetValue, FALSE, ""); + } else { + llRegionSayTo(lastUser, 0, "❌ Format: /99 set key=value"); + } + } + else if (llGetSubString(msg, 0, 3) == "del ") { + string targetKey = llStringTrim(llGetSubString(msg, 4, -1), STRING_TRIM); + llRegionSayTo(lastUser, 0, "🗑️ Deleting key: " + targetKey + "..."); + requestDelete = llDeleteKeyValue(targetKey); + } + } + + dataserver(key queryid, string data) { + // llKeysKeyValue returns data as CSV: + // Success: 1,keyname1,keyname2... + // Failure: 0,error_code + if (queryid == requestKeys) { + list result = llCSV2List(data); + if (llList2Integer(result, 0) == 1) { + // Success + integer numKeys = llGetListLength(result) - 1; + llRegionSayTo(lastUser, 0, "✅ Found " + (string)numKeys + " keys in database:"); + + integer i; + for(i = 1; i < llGetListLength(result); i++) { + llRegionSayTo(lastUser, 0, " 🔑 " + llList2String(result, i)); + } + } else if (llList2Integer(result, 1) == 3) { + llRegionSayTo(lastUser, 0, "📭 The database is completely empty! No keys exist."); + } else { + llRegionSayTo(lastUser, 0, "❌ Failed to read keys (Error " + llList2String(result, 1) + ")"); + } + } + + // llReadKeyValue returns data as: status,value + else if (queryid == requestRead) { + integer comma = llSubStringIndex(data, ","); + string status = llGetSubString(data, 0, comma - 1); + string val = llGetSubString(data, comma + 1, -1); + + if (status == "1") { + llRegionSayTo(lastUser, 0, "📄 Content:\n" + val); + } else if (status == "3") { + llRegionSayTo(lastUser, 0, "❌ That key doesn't exist!"); + } else { + llRegionSayTo(lastUser, 0, "❌ Read failed (Status: " + status + ")"); + } + } + + // llDeleteKeyValue dataserver logic + else if (queryid == requestDelete) { + integer comma = llSubStringIndex(data, ","); + string status = llGetSubString(data, 0, comma - 1); + + if (status == "1") { + llRegionSayTo(lastUser, 0, "✅ Key successfully deleted!"); + } else if (status == "3") { + llRegionSayTo(lastUser, 0, "❌ Key didn't exist to delete."); + } else { + llRegionSayTo(lastUser, 0, "❌ Delete failed (Status: " + status + ")"); + } + } + + // Write logic + else if (queryid == requestWrite) { + integer comma = llSubStringIndex(data, ","); + string status = llGetSubString(data, 0, comma - 1); + if (status == "1") { + llRegionSayTo(lastUser, 0, "✅ Key saved successfully!"); + } else if (status == "3") { + // Key didn't exist to update, manually create it! + requestWrite = llCreateKeyValue(pendingSetKey, pendingSetValue); + } else { + llRegionSayTo(lastUser, 0, "❌ Write failed (Status: " + status + ")"); + } + } + } +}