// Startup&ShutdownHandler // Responsible for executing commands that perform startup initilization, respond to fatal // error conditions, and shutdown the terminal when requested to do so. // Copyright (C) 2005-2006 Francisco V. Saldana // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // Francisco V. Saldana can be contacted using his email account // username: dressedinblue, at domain: gmail.com // and in Second Life by IMming Christopher Omega // Responsible for executing high-level commands // to initilize the terminal, for notifying other // components of a user change, and for shutting down // the terminal when the user logs off. // This script also monitors a button named IO_BUTTON // that will turn the terminal on. integer MAIN_MENU_CATEGORY_ID = 0; float POLL_START_TIMEOUT = 0;//30.0; // Meters user is allowed to move before auto logout. float USER_MOVE_RANGE = 4.0; // Current user's key, NULL_KEY if no one is using terminal. key curUser = NULL_KEY; // ========== For method invocation ========== string randomSeperator(integer len) { integer firstChar = (integer)llFrand(60) + 20; // Range of printable chars = 0x20 to 0x7E if (len <= 1) return llUnescapeURL("%"+(string)firstChar); integer lastChar; do { // Last char must not equal first char. lastChar = (integer)llFrand(60) + 20; } while (lastChar == firstChar); string ret = llUnescapeURL("%"+(string)firstChar); for (len -= 2; len > 0; --len) ret += llUnescapeURL("%" + (string)((integer)llFrand(60) + 20)); return ret + llUnescapeURL("%"+(string)lastChar); } string listToString(list src) { string chars = (string) src; // Squashes all elements together. string seperator; do { // Find a seperator that's not in the list's string form seperator = randomSeperator(3); // so we dont kill data. } while (llSubStringIndex(chars, seperator) != -1); return seperator + llDumpList2String(src, seperator); } list stringToList(string src) { // First 3 chars is seperator. return llParseStringKeepNulls(llDeleteSubString(src, 0, 2), [llGetSubString(src, 0, 2)], []); } callMethod(integer identifyer, string methodName, list parameters) { llMessageLinked(LINK_THIS, identifyer, // ID only necessary for return value. listToString(parameters), methodName); } returnValue(integer identifyer, string methodName, list value) { callMethod(identifyer, methodName + "_ret", value); } // ============================================= trigger_displayStatusMessage(string message) { callMethod(0, "displayStatusMessage", [message]); } trigger_setUser(key newUser) { callMethod(0, "setUser", [newUser]); } trigger_trackAgent(key agentKey, float movementRange) { callMethod(0, "trackAgent", [agentKey, movementRange]); } trigger_stopTrackAgent(key agentKey) { callMethod(0, "stopTrackAgent", [agentKey]); } trigger_disableMenuLineButton(string moduleName, integer buttonNumber) { callMethod(0, "disableMenuLineButton", [moduleName, buttonNumber]); } trigger_setButtonWriter(string moduleName) { callMethod(0, "setButtonWriter", [moduleName]); } trigger_touchFilter(list rules) { callMethod(0, "touchFilter", [listToString(rules)]); } trigger_displayNotecard(string noteName) { callMethod(0, "displayNotecard", [noteName]); } trigger_pong(string moduleName) { callMethod(0, "pong", [moduleName]); } trigger_requestMenuCategory(integer id) { callMethod(0, "requestMenuCategory", [id]); } integer connectionStartupReturnVal; trigger_connectionStartup() { connectionStartupReturnVal = (integer) llFrand(182842); callMethod(connectionStartupReturnVal, "connectionStartup", []); } trigger_connectionShutdown() { callMethod(0, "connectionShutdown", []); } m_moduleReset(string moduleName) { callMethod(0, "moduleReset", [moduleName]); } //======================== integer DETECTED_GROUP = 1001; integer DETECTED_KEY = 1002; integer DETECTED_NAME = 1004; integer DETECTED_POS = 1006; integer DETECTED_ROT = 1007; list getDetectedValue(list detectedData, integer detectedConstant) { integer index = llListFindList(detectedData, [(string) detectedConstant]); if (index != -1) { return llList2List(detectedData, index + 1, index + 1); } return []; } // Performed when user logs on. setUser(key user) { if (user == NULL_KEY) { trigger_touchFilter([]); trigger_setUser(NULL_KEY); trigger_stopTrackAgent(NULL_KEY); } else { trigger_setUser(user); trigger_touchFilter([DETECTED_KEY, user]); trigger_trackAgent(user, USER_MOVE_RANGE); } } // Performed when user logs off. shutdown() { trigger_displayStatusMessage("Shutting down..."); setUser(NULL_KEY); trigger_connectionShutdown(); } string this; default { state_entry() { this = llGetScriptName(); m_moduleReset(this); setUser(NULL_KEY); trigger_displayNotecard(llGetInventoryName(INVENTORY_NOTECARD, 0)); } link_message(integer sender, integer num, string parameters, key methodName) { if (methodName == "menuLineButtonPressed") { list paramList = stringToList(parameters); // Method signature: // lineButtonPressed(integer lineNumber, list detectedData) integer lineNumber = (integer) llList2String(paramList, 0); list detectedData = stringToList(llList2String(paramList, 1)); trigger_setButtonWriter(this); trigger_disableMenuLineButton(this, lineNumber); key toucherKey = llList2String(getDetectedValue(detectedData, DETECTED_KEY), 0); trigger_displayStatusMessage("Set user to " + (string) toucherKey); curUser = toucherKey; trigger_displayStatusMessage("Connecting to server..."); trigger_connectionStartup(); } else if (methodName == "connectionStartup_ret" && num == connectionStartupReturnVal) { list paramList = stringToList(parameters); // Method signature: // connectionStartup_ret(integer successful) integer successful = (integer) llList2String(paramList, 0); if (successful) { trigger_displayStatusMessage("Connected to server. Requesting main menu..."); setUser(curUser); trigger_requestMenuCategory(MAIN_MENU_CATEGORY_ID); state started; } else { trigger_displayStatusMessage("Unable to connect to server, please try again later."); } } else if (methodName == "moduleReady") { list paramList = stringToList(parameters); string module = llList2String(paramList, 0); if (module == this) returnValue(num, methodName, [TRUE]); } } } state started { link_message(integer sender, integer num, string parameters, key methodName) { if (methodName == "agentOutOfRange") { list paramList = stringToList(parameters); // Method signature: // agentOutOfRange(key agent) key agent = (key) llList2String(paramList, 0); if (agent == curUser) { trigger_displayStatusMessage("User out of range, terminal resetting..."); state default; } } else if (methodName == "receivedTerminalReset") { // Method signature: // receivedTerminalReset() trigger_displayStatusMessage("Server error, terminal resetting..."); state default; } else if (methodName == "receivedServerError") { // Method signature: // receivedServerError(string details) trigger_displayStatusMessage("Server error, terminal resetting..."); state default; } else if (methodName == "logoutButtonPressed") { // Method signature: // logoutButtonPressed() trigger_displayStatusMessage("Logging off..."); state default; } else if (methodName == "moduleReady") { list paramList = stringToList(parameters); string module = llList2String(paramList, 0); if (module == this) returnValue(num, methodName, [TRUE]); } } state_exit() { shutdown(); } }