User:Lum Pfohl/LSL Goodies/HI-WA Occupancy Counter System/Relay Server Master 1.5

From Second Life Wiki
Jump to navigation Jump to search

<lsl>

//  _                      ______  __      _     _
// | |                     | ___ \/ _|    | |   | |
// | |    _   _ _ __ ___   | |_/ / |_ ___ | |__ | |
// | |   | | | | '_ ` _ \  |  __/|  _/ _ \| '_ \| |
// | |___| |_| | | | | | | | |   | || (_) | | | | |
// \_____/\__,_|_| |_| |_| \_|   |_| \___/|_| |_|_|


//
// Lum's Relay Server - Master
//
// Written by Lum Pfohl July 01, 2008
//
//

integer __debug = FALSE;
string __version = "1.5";

// string to send to tally server - notification of population
string method = "QUERY ALL EXT";      

float shortScanInterval = 0.5;      // 0.5 seconds
float longScanInterval  = 5.0;      // 5.0 seconds
integer scanningShort = FALSE;

integer serverResponded = FALSE;

string serverKey = "e323f55a-7fa7-8660-5a0d-bc9c38c679e7";

// We keep track of how many email slaves here, and which one we're going
// to use next
integer numEmailScripts = 16;
integer curEmailScript = 0;

string regionname = "";

integer nobodyCount = 0;
integer maxCount = 3;

integer countToReset = 0;
integer countToLongScan = 0;
float queryRetries = 0.0;

integer channel = 321123;

string oiPopulation = "";
string hiPopulation = "";
string waPopulation = "";

// update object to send if a client is using an older version
string invName = "HI/WA HUD 1.05";
string invVersion = "HUD01.05";

// local midnight expressed in number of seconds since SL-time (USA Pacific Time) midnight.
// Example:
//    USA Eastern Time (ET)  : (21:00 PT = 00:00 ET) 21 * 3600 = 75600
//    USA Central Time (CT)  : (22:00 PT = 00:00 CT) 22 * 3600 = 79200
//    USA Mountain Time (MT) : (23:00 PT = 00:00 MT) 23 * 3600 = 82800
//
// DST Note: SL-time follows local Pacific Time and is subject to Daylight Savings Times
// Most US regions also follow DST rules and thus the localMidnight values can be static
// However, locales such as Indiana, Hawaii, Guam follow "Standard Times" and thus the
// time difference between SL time varies with the time of year.  Adjust your local
// midnight accordingly if you do not live in the DST regions.  This also affects
// non-USA locations as well, who do not follow the DST protocol.
//
float localMidnight = 75600.0;

// replacement routine for llEmail(), designed to intercept
// the email request and dispatch it to one of several slave email scripts
sendMessage(string toAddress, string subject, string messageBody) {

  // marshall the email parameters to pass to the slave email scripts
  string messageToSend = toAddress + "|" + subject + "|" + messageBody;

  if (__debug) {
    llOwnerSay("linking: " + (string)curEmailScript + messageToSend);
  }

  // contact the slave script (by number - curEmailScript) and pass the marshalled message
  llMessageLinked(LINK_THIS, curEmailScript, messageToSend, NULL_KEY);

  // increment currentEmail script pointer, resetting to zero as needed
  curEmailScript = (curEmailScript + 1) % numEmailScripts;

}


// Method for requesting a query from the tally server.
queryServer() {

  // Send a query message.  Pass the HUD's key as a return address.
  sendMessage(serverKey + "@lsl.secondlife.com", "OI Ctr", method + "~" + (string)llGetKey());
  serverResponded = FALSE;

}


default {

  state_entry() {

    llOwnerSay("Started");
    llOwnerSay("Server Key is " + (string)llGetKey());

    // Notify the slave relays to reset too
    llSay(channel, "RESET");

    state active;

  }


  on_rez(integer num) {

    llResetScript();
  }
}


state active {

  state_entry() {

    countToReset = (countToReset + 1) % 12;
    if (countToReset == 0) {

      llResetScript();
    }

    // llOwnerSay("Querying server.  This may take a few moments.");
    queryServer();


    llSetTimerEvent(longScanInterval);
  }

  touch_start(integer num_detected) {

    llWhisper(0, "Server Key is " + (string)llGetKey());
    llWhisper(0, "Current OI = " + oiPopulation);
    llWhisper(0, "Current HI = " + hiPopulation);
    llWhisper(0, "Current WA = " + waPopulation);

    if (llGetOwner() == llDetectedKey(0)) {
      if (__debug == FALSE) {
        __debug = TRUE;
        llOwnerSay("Debug is on.");
      } else {
        __debug = FALSE;
        llOwnerSay("Debug is off.");
      }
    }
  }



  //------------------------------------------------------------------------------------
  // Every time the timer expires, check for emails
  //------------------------------------------------------------------------------------
  timer() {
    llGetNextEmail("", ""); // Check for email with any sender address and subject.
    if (__debug) {
      // llOwnerSay("Timer Set");
    }

    if (scanningShort == TRUE) {
      queryRetries += shortScanInterval;
    } else {
      queryRetries += longScanInterval;
    }



    if (serverResponded == TRUE && queryRetries > 120.0) {
      queryServer();
    }

    if (scanningShort == TRUE && countToLongScan++ == 10) {
      llSetTimerEvent(longScanInterval);
      scanningShort = FALSE;
      countToLongScan = 0;
    }

    float currentSLTime = llGetWallclock();

    if (__debug) {
      llSay(0,(string)llGetWallclock() + "  " + (string)(llGetWallclock() - localMidnight));
    }

    // Reset the server at midnight Easter Time every night
    if ((currentSLTime - localMidnight >= 0) && ((currentSLTime - localMidnight) < 6)  ) {

      if (__debug) {
        llSay(0, "I detected midnight had occurred. Emailing list.");
      }
      llResetScript();
    }

  }



  //------------------------------------------------------------------------------------
  // If we get an email, check for replies, and display to the client
  //------------------------------------------------------------------------------------
  email(string time, string address, string subj, string message, integer num_left) {

    llSetTimerEvent(0.0);
    countToLongScan = 0;
    // llOwnerSay("Message " + message);

    if (subj == "Query Response") {
      queryRetries = 0;

      if (__debug) {
        llOwnerSay("Message Received");
      }

      // Remove the header
      message = llDeleteSubString(message, 0, llSubStringIndex(message, "\n\n") + 1);

      if (__debug) {
        llOwnerSay(message);
      }

      // The message that is received from the tally server is in a CSV format.  Convert
      // this to a list so that we can iterate the elements

      list tempList = llParseString2List(message,["!"],[]);
      oiPopulation = llList2String(tempList, 0);
      hiPopulation = llList2String(tempList, 1);
      waPopulation = llList2String(tempList, 2);

      // llOwnerSay("OI: " + oiPopulation);
      // llOwnerSay("HI: " + hiPopulation);
      // llOwnerSay("WA: " + waPopulation);

      integer numElements = llGetListLength(llCSV2List(oiPopulation)) + llGetListLength(llCSV2List(hiPopulation)) + llGetListLength(llCSV2List(waPopulation));

      // Once in a while, we receive an incomplete list, presumably while results are being
      // collated on the server.  If this is the case, re-query the server
      if (numElements != 210) {

        if (__debug) {
          llOwnerSay("Requerying the server... (" +(string)llGetListLength(tempList) + ")");
        }
        //queryServer();

        llSetTimerEvent(2.5);
        return;
      }

      // Notify the slave(s) of an incoming message
      llSay(channel, message);
      serverResponded = TRUE;

    } else if (subj == "OI Ctr") {
      // Remove the header
      message = llDeleteSubString(message, 0, llSubStringIndex(message, "\n\n") + 1);

      // Break of the message
      if (__debug) {
          llOwnerSay(message);
      }
      
      list notificationMessage = llParseString2List(message,["~",","],[]);
      string method = llList2String(notificationMessage, 0);

      string hudVersion = "";
      string avatarName = "";
      string avatarKey = "";

      if (llGetListLength(notificationMessage) > 2) {
        hudVersion = llToUpper(llList2String(notificationMessage, 2));
        if (llGetListLength(notificationMessage) > 3) {
          avatarName = llList2String(notificationMessage, 3);
          if (llGetListLength(notificationMessage) > 4) {
            avatarKey = llList2String(notificationMessage, 4);
          }
        }
      }
      if (__debug) {
        llOwnerSay("Hud Version = " + hudVersion);
        llOwnerSay("Avatar Name = " + avatarName);
        llOwnerSay("Avatar Key  = " + avatarKey);
      }

      if (method == "QUERY ALL") {

        // Decompose the return address (HUD UUID) from the message
        string returnAddress = llList2String(notificationMessage, 1);

        if (__debug) {
          llOwnerSay("QUERY (ALL) returnAddress = " + returnAddress);
        }
        // Send that object, the current OI + HI (HI1 - 210) population
        sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", "Update");
        // sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", oiPopulation + "," + llList2CSV(llDeleteSubList(llCSV2List(hiPopulation), 30, 79)));
        returnAddress = "";

      } else if (method == "QUERY ALL EXT") {

        // Decompose the return address (HUD UUID) from the message
        string returnAddress = llList2String(notificationMessage, 1);

        if (__debug) {
          llOwnerSay("QUERY (ALL EXT) returnAddress = " + returnAddress);
        }

        // Send that object, the current OI + HI + WA population in a !-separated format
        // If we need to send an updated HUD and an avatar key is available,
        // do so!
        if (hudVersion != "" && avatarKey != "") {
          if (llSubStringIndex(hudVersion, "HUD") != -1 && hudVersion != invVersion) {
            sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", "Update");
            llGiveInventory(avatarKey, invName);
          } else {
            sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", oiPopulation + "!" + hiPopulation + "!" + waPopulation);
          }
        } else {
          sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", oiPopulation + "!" + hiPopulation + "!" + waPopulation);
        }
        returnAddress = "";

      } else if (method == "QUERY") {

        // Decompose the return address (HUD UUID) from the message
        string returnAddress = llList2String(notificationMessage, 1);

        if (__debug) {
          llOwnerSay("QUERY (OI) returnAddress = " + returnAddress);
        }

        // Send that object, the current OI population only
        sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", "Update");
        //sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", oiPopulation);
        returnAddress = "";


      } else if (method == "QUERY HI") {

        // Decompose the return address (HUD UUID) from the message
        string returnAddress = llList2String(notificationMessage, 1);

        if (__debug) {
          llOwnerSay("QUERY (HI) returnAddress = " + returnAddress);
        }

        // Send that object, the current HI (HI1 - HI210) population
        sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", llList2CSV(llDeleteSubList(llCSV2List(hiPopulation), 30, 79)));
        returnAddress = "";

      } else if (method == "QUERY HI EXT") {

        // Decompose the return address (HUD UUID) from the message
        string returnAddress = llList2String(notificationMessage, 1);

        if (__debug) {
          llOwnerSay("QUERY (HI) returnAddress = " + returnAddress);
        }

        // Send that object, the current HI population

        sendMessage(returnAddress + "@lsl.secondlife.com", "Query Response", hiPopulation);
        returnAddress = "";

      }

    }

    llSetTimerEvent(shortScanInterval);
    scanningShort = TRUE;
  }

  on_rez(integer num) {

    llResetScript();
  }

}

</lsl>