User:Void Singer/Region Stats

From Second Life Wiki
Jump to navigation Jump to search

Region Stats

What is it?


Regions Stats is an open source extension for Teacup designed as a demo of pulling live data from within SL into an html page. It additionally demonstrates the use of inline scripting for .tsp files, as well a method by which live data pages can overcome the internal browsers caching of duplicate page requests therein.

Code

Region Stats


  • Save in a MONO script named "Region Stats"
/*( Region Stats )*/

string  gStrNom = "Region Stats.tsp"; //-- file name that we serve data to
//-- we insert the page name & request key later for the refresh to override same page cahing in the internal browser
string  gStrPg0 = "v0='<script>RS=setTimeout(\"u1(\\'";
string  gStrPg1 = "\\')\", 60000 );</script>\\n<p><a href=\"index.tsp\" onClick=\"clearTimeout(RS);\">Return to index</a>?</p>\\n<table>\\n";
string  gStrPg2 = "</table>';"; //-- page footer

string  gStrNfo; //-- stores static Region information
integer gIntFlg; //-- the current region flags
string  gStrFlg; //-- stores Region flags (updated as needed only)
string  gStrTod; //-- Stores Region Time of Day (updates live if Fixed Sun == false)

key     gKeyQry; //-- Dataserver Query key
integer gBooRdy; //-- Controls availability advertisement

uGetTod( vector vPosSun ){ //-- grabs Region apparent Time of Day (slightly inaccurate)
	vPosSun = llVecNorm( <vPosSun.x, 0.0, vPosSun.z> );
	integer vIntTod = (integer)(86400.0 - (llAtan2( vPosSun.x, vPosSun.z ) * RAD_TO_DEG + 180) * 240.0);
	gStrTod = (string)(vIntTod / 3600) + ":" + llGetSubString( "0" + (string)(vIntTod % 3600 / 60), -2, -1 ) +
		":" + llGetSubString( "0" + (string)(vIntTod % 60), -2, -1 ) + "";
}

default{
	state_entry(){ //-- make the page seem unavailable while we refresh our static data
		llMessageLinked( LINK_SET, 600, gStrNom, NULL_KEY );
		gStrNfo = //-- Start building static info
		  "<tr><td><span style=\"font-weight: bold;\">Pre-calculated Data</span></td></tr>\\n<tr><td>Region Name:</td><td>" +
		  llGetRegionName() + "</td></tr>\\n";
		uGetTod( llGetSunDirection() ); //-- set once to make logic faster later
		gKeyQry = llRequestSimulatorData( llGetRegionName(), DATA_SIM_RATING );
	}
	
	dataserver( key vKeyQID, string vStrDta ){
		if (gKeyQry == vKeyQID){ //-- continue building static info
			gStrNfo += "<tr><td>Region Rating:</td><td>" + //-- this is one way to get unknown ratings noticed =X
			  llList2String( ["General", "Moderate", "Adult", "XXX Pr0nland"],
			                 llListFindList( ["PG", "MATURE", "ADULT", "UNKNOWN"], [vStrDta] ) ) +
			  "</td></tr>\\n<tr><td>Region Location:</td><td>(";
			vector vPosTmp = llGetRegionCorner();
			gStrNfo += (string)((integer)vPosTmp.x) + ", " +
			  (string)((integer)vPosTmp.y) + ")</td></tr>\\n<tr><td>Server Name:</td><td>" +
			  llGetSimulatorHostname() + "</td></tr>\\n<tr><td>Server Channel:</td><td>" +
			  llGetEnv( "sim_channel" ) + "</td></tr>\\n<tr><td>Server Version:</td><td>";
			list vLstTmp = llParseString2List( llGetEnv( "sim_version" ), ["."], [] );
			gStrNfo += //-- version number contains build date, sneaky huh?
			  llDumpList2String( vLstTmp, "." ) + "</td></tr>\\n<tr><td>Server Build Date:</td><td>" +
			  llList2String( ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
			                 ~-llList2Integer( vLstTmp, 1 ) ) +
			  " " + llList2String( vLstTmp, 2 ) + ", 20" + llList2String( vLstTmp, 0 ) + "</td></tr>\\n";
			gBooRdy = TRUE; //-- this variable is only used to readvertise to Saucer when it starts
			llMessageLinked( LINK_SET, 601, gStrNom, NULL_KEY );
		}
	}
	
	link_message( integer vIntSrc, integer vIntDta, string vStrDta, key vKeyDta ){
		if (418 == vIntDta){
			if (vKeyDta){
				if (gStrNom == llList2String( llParseStringKeepNulls( vStrDta, ["?"], [] ), 0 )){
					if (gIntFlg != vIntDta = llGetRegionFlags()){
						gIntFlg = vIntDta; //-- only (re)built if flags change or at first request
						list vLstFlg = ["Y", "N"]; //-- need to check this is better for mono lists than inline
						gStrFlg = "<tr><td><span style=\"font-weight:bold;\">Region Flags</span></td></tr>\\n<tr><td>Damage Enabled?</td><td>" +
						llList2String( vLstFlg, !(0x00000001 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Allow Landmark?</td><td>" +
						llList2String( vLstFlg, !(0x00000002 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Allow Set Home?</td><td>" +
						llList2String( vLstFlg, !(0x00000004 & gIntFlg) ) +
						/*//-- I don't think this is used
						"</td></tr>\\n<tr><td>†Reset Home On Teleport?</td><td>" +
						llList2String( vLstFlg, !(0x00000008 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>Fixed Sun?</td><td>" +
						llList2String( vLstFlg, !(0x00000010 & gIntFlg) ) +
						/*//-- Unused, taxes were abolished for SL ages ago
						"</td></tr>\\n<tr><td>†Tax Free?</td><td>" +
						llList2String( vLstFlg, !(0x00000020 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>Block Terraform?</td><td>" +
						llList2String( vLstFlg, !(0x00000040 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Block Land Resell?</td><td>" +
						llList2String( vLstFlg, !(0x00000080 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>Is Sandbox?</td><td>" +
						llList2String( vLstFlg, !(0x00000100 & gIntFlg) ) +
						/*//-- I don't think any of these are used
						"</td></tr>\\n<tr><td>‡Null Layer?</td><td>" +
						llList2String( vLstFlg, !(0x00000200 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>‡Allow Land Xfer?</td><td>" +
						llList2String( vLstFlg, !(0x00000400 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>‡Skip Update Interest List?</td><td>" +
						llList2String( vLstFlg, !(0x00000800 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>Disable Collisions?</td><td>" +
						llList2String( vLstFlg, !(0x00001000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Skip Scripts?</td><td>" +
						llList2String( vLstFlg, !(0x00002000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>Disable Physics?</td><td>" +
						llList2String( vLstFlg, !(0x00004000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Externally Visible?</td><td>" +
						llList2String( vLstFlg, !(0x00008000 & gIntFlg) ) +
						/*//-- Encroachment code isn't used(yet), Dwell was removed ages ago
						"</td></tr>\\n<tr><td>†Allow Return Encroaching<td>?</td><td>" +
						llList2String( vLstFlg, !(0x00010000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Allow Return Enchroching(Estate)?</td><td>" +
						llList2String( vLstFlg, !(0x00020000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Block Dwell?</td><td>" +
						llList2String( vLstFlg, !(0x00040000 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>Block Fly?</td><td>" +
						llList2String( vLstFlg, !(0x00080000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>Allow Direct TP?</td><td>" +
						llList2String( vLstFlg, !(0x00100000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Skip Scripts(Estate)?</td><td>" +
						llList2String( vLstFlg, !(0x00200000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>Restrict Push?</td><td>" +
						llList2String( vLstFlg, !(0x00400000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Deny Anonymous?</td><td>" +
						llList2String( vLstFlg, !(0x00800000 & gIntFlg) ) +
						/*//-- I don't think these are used anymore, used to be for OI?
						"</td></tr>\\n<tr><td>‡Deny Identified?</td><td>" +
						llList2String( vLstFlg, !(0x01000000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>‡Deny Transacted?</td><td>" +
						llList2String( vLstFlg, !(0x02000000 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>†Allow Parcel Changes?</td><td>" +
						llList2String( vLstFlg, !(0x04000000 & gIntFlg) ) +
						/*//-- Prtty sure this is disabled
						"</td></tr>\\n<tr><td>‡Abuse Email 2 Estate Owner?</td><td>" +
						llList2String( vLstFlg, !(0x08000000 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td>†Allow Voice?</td><td>" +
						llList2String( vLstFlg, !(0x10000000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Block Parcel Search?</td><td>" +
						llList2String( vLstFlg, !(0x20000000 & gIntFlg) ) +
						"</td></tr>\\n<tr><td>†Deny Age unVerified?</td><td>" +
						llList2String( vLstFlg, !(0x40000000 & gIntFlg) ) +
						/*//-- Pretty sure this is disabled as well since MONO went mainstream.
						"</td></tr>\\n<tr><td>‡Skip Scripts(MONO)?</td><td>" +
						llList2String( vLstFlg, !(0x80000000 & gIntFlg) ) +
						*/
						"</td></tr>\\n<tr><td><br>†=Does not have an LSL constant<br>‡=No longer exists in source code</td></tr>\\n";
					}
					if (~gIntFlg & 0x00000010){ //-- don't update for fixed sun
						uGetTod( llGetSunDirection() );
					}
					llMessageLinked( vIntSrc,
					                 201, //-- Next Line: key insertion lets us override internal browser page caching for live refresh
					                 gStrPg0 + gStrNom + "?" + (string)vKeyDta + gStrPg1 + gStrNfo + 
					                 "<tr><td><span style=\"font-weight: bold;\">Live Data</span></td></tr>\\n<tr><td>Region Tod:</td><td>" +
					                 gStrTod + " rST (24hr)</td></tr>\\n<tr><td>Region FPS:</td><td>" +
					                 (string)llGetRegionFPS() + "</td></tr>\\n<tr><td>Time Dilation:</td><td>" +
					                 (string)llGetRegionTimeDilation() + "</td></tr>\\n<tr><td>Agent Count:</td><td>" +
					                 (string)llGetRegionAgentCount() + "</td></tr>\\n<tr><td>Shared Borders:</td><td>" +
					                 (string)(!llEdgeOfWorld( <128.0, 128.0, 128.0>, < 0.0,  1.0, 0.0> ) + 
					                 !llEdgeOfWorld( <128.0, 128.0, 128.0>, < 1.0,  0.0, 0.0> ) +
					                 !llEdgeOfWorld( <128.0, 128.0, 128.0>, < 0.0, -1.0, 0.0> ) + 
					                 !llEdgeOfWorld( <128.0, 128.0, 128.0>, <-1.0,  0.0, 0.0> )) +
					                 "</td></tr>\\n" + gStrFlg + gStrPg2,
					                 vKeyDta );
				}
			}else if (NULL_KEY == vKeyDta && "" == vStrDta && gBooRdy){
				//-- Saucer stared, let tell it we have a page. Realistically unneccessary
				llMessageLinked( vIntSrc, 601, gStrNom, NULL_KEY );
			}//-- out page actualy serves in under a sec even on first request, but I wanted to demo the logic
		}
	}
	
	changed( integer vBitChg ){
		if ((CHANGED_REGION | CHANGED_REGION_START) & vBitChg){
			llResetScript(); //-- Regions changes or Restarts may have new static info
		}
	}
	
	on_rez( integer vIntBgn ){
		llResetScript(); //-- Make sure static info is releveant to current region
	}
}
/*//--                           License Text                           --//*/
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//    (C)2011 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/
Return to top

Notes

Compatible Servers, File Systems, and Extensions


  • Teacup - SIP front end
  • Saucer - Optional Fast 404 Extension for preventing long timeouts for missing/bad pages
  • Tea Strainer - Optional Troubleshooting Monitor for checking messages being sent and received.

Known Bugs


  • There is a vague posibility that an initial request could come in during the state_entry, before the dataserver fires. if this happens, the first display will not include some static data, subsequent auto-refreshes will eventually update this (usually on the next refresh)
Return to top

Questions or Comments?

Feel free to leave me a note on the discussion page.